Example #1
0
        private void CreateSourceElements(IndexSecurity security)
        {
            var area = _mainArea;

            var axisId = 1;

            foreach (var innerSecurity in security.InnerSecurities)
            {
                var axisName = "SA_" + axisId++;

                var series           = new CandleSeries(typeof(TimeFrameCandle), innerSecurity, TimeSpan.FromMinutes(5));
                var indicatorElement = new ChartIndicatorElement
                {
                    Title           = innerSecurity.Id,
                    Color           = _colors[axisId],
                    YAxisId         = axisName,
                    StrokeThickness = 1
                };

                area.YAxises.Add(new ChartAxis
                {
                    Id            = axisName,
                    AutoRange     = true,
                    AxisType      = ChartAxisType.Numeric,
                    AxisAlignment = ChartAxisAlignment.Right
                });

                var indicator = new CandlePartIndicator();

                //_indicators.Add(indicatorElement, indicator);
                _sourceElements.Add(innerSecurity, indicatorElement);
                _bufferedChart.AddElement(area, indicatorElement, series, indicator);
            }
        }
Example #2
0
        private void AddIndicator(ChartIndicatorElement element)
        {
            var series = (CandleSeries)_bufferedChart.GetSource(element);

            if (series == null)
            {
                return;
            }

            if (_sourceElements.ContainsKey(series.Security))
            {
                return;
            }

            List <RefPair <DateTimeOffset, IDictionary <IChartElement, object> > > allValues;

            lock (_syncRoot)
            {
                allValues = series
                            .GetCandles <TimeFrameCandle>()
                            .Take(_candlesCount)
                            .Select(candle => new RefPair <DateTimeOffset, IDictionary <IChartElement, object> >(candle.OpenTime, new Dictionary <IChartElement, object>
                {
                    { element, CreateIndicatorValue(element, candle) }
                }))
                            .ToList();

                _skipElements.Remove(element);
            }

            _bufferedChart.Reset(new[] { element });
            _bufferedChart.Draw(allValues);
        }
Example #3
0
        private void OnChartPanelSubscribeIndicatorElement(ChartIndicatorElement element, CandleSeries candleSeries, IIndicator indicator)
        {
            _bufferedChart.SetSource(element, candleSeries);
            _indicators.Add(element, indicator);

            AddElement(element, candleSeries);
        }
Example #4
0
        private void Chart_SubscribeIndicatorElement(ChartIndicatorElement element, CandleSeries series, IIndicator indicator)
        {
            var candles = _candles.TryGetValue(series.Security);

            if (candles == null)
            {
                throw new InvalidOperationException("_candles == null");
            }

            var values = candles
                         .Select(candle =>
            {
                if (candle.State != CandleStates.Finished)
                {
                    candle.State = CandleStates.Finished;
                }

                return(new RefPair <DateTimeOffset, IDictionary <IChartElement, object> >(candle.OpenTime, new Dictionary <IChartElement, object>
                {
                    { element, indicator.Process(candle) }
                }));
            })
                         .ToArray();

            Chart.Draw(values);
        }
Example #5
0
        private void Chart_OnSubscribeIndicatorElement(ChartIndicatorElement element, CandleSeries series, IIndicator indicator)
        {
            _dataThreadActions.Add(() =>
            {
                var oldReset = Chart.DisableIndicatorReset;
                try
                {
                    Chart.DisableIndicatorReset = true;
                    indicator.Reset();
                }
                finally
                {
                    Chart.DisableIndicatorReset = oldReset;
                }

                var chartData = new ChartDrawData();

                foreach (var candle in _allCandles.CachedValues)
                {
                    chartData.Group(candle.OpenTime).Add(element, indicator.Process(candle));
                }

                Chart.Reset(new[] { element });
                Chart.Draw(chartData);

                _indicators[element] = indicator;
            });
        }
        private void InitChart(CandleSeries series)
        {
            Chart.ClearAreas();
            _area = new ChartArea();
            var yAxis = _area.YAxises.First();
            var xAxis = _area.XAxises.First();

            yAxis.AutoRange    = true;
            Chart.IsAutoRange  = true;
            Chart.IsAutoScroll = true;
            Chart.ShowOverview = true;

            _sma = new SimpleMovingAverage()
            {
                Length = (int)IntegerUpDown.Value
            };

            _candleElement = new ChartCandleElement()
            {
                FullTitle = "Candles"
            };
            _indicatorElement = new ChartIndicatorElement()
            {
                FullTitle = "SMA"
            };

            Chart.AddArea(_area);
            Chart.AddElement(_area, _candleElement, series);
            Chart.AddElement(_area, _indicatorElement);
        }
        private void SetSource(ChartIndicatorElement element, CandleSeries candleSeries, IIndicator indicator)
        {
            RefPair <DateTimeOffset, IDictionary <IChartElement, object> >[] values = null;

            lock (_syncRoot)
            {
                _indicators[element] = indicator;

                var isNew = !_elementsBySeries.ContainsKey(candleSeries);

                if (!isNew && CanProcess)
                {
                    values = ProcessHistoryCandles(element, candleSeries);
                }
                else if (isNew)
                {
                    SubscribeSeries(candleSeries);
                }

                var lastDate = values == null || values.IsEmpty() ? DateTimeOffset.MinValue : values.Last().First;

                _elementsInfo.SafeAdd(element, e => RefTuple.Create(lastDate, candleSeries));
                _elementsBySeries.SafeAdd(candleSeries).Add(element);
            }

            if (values != null && values.Length > 0)
            {
                new ChartDrawCommand(values).Process(this);
            }
        }
Example #8
0
		private void OnChartPanelSubscribeIndicatorElement(ChartIndicatorElement element, CandleSeries candleSeries, IIndicator indicator)
		{
			_drawTimer.Cancel();

			_elements.Add(new RefPair<IChartElement, int>(element, 0));
			_indicators.Add(element, indicator);
			_drawTimer.Activate();
		}
Example #9
0
        private void OnChartPanelSubscribeIndicatorElement(ChartIndicatorElement element, CandleSeries candleSeries, IIndicator indicator)
        {
            _drawTimer.Cancel();

            _elements.Add(new RefPair <IChartElement, int>(element, 0));
            _indicators.Add(element, indicator);
            _drawTimer.Activate();
        }
Example #10
0
        public UnSubscribeIndicatorElementCommand(ChartIndicatorElement element)
        {
            if (element == null)
            {
                throw new ArgumentNullException(nameof(element));
            }

            Element = element;
        }
Example #11
0
        private IIndicatorValue CreateIndicatorValue(ChartIndicatorElement element, Candle candle)
        {
            var indicator = _indicators.TryGetValue(element);

            if (indicator == null)
            {
                throw new InvalidOperationException(LocalizedStrings.IndicatorNotFound.Put(element));
            }

            return(indicator.Process(candle));
        }
		public SubscribeIndicatorElementCommand(ChartIndicatorElement element, CandleSeries candleSeries, IIndicator indicator)
		{
			if (element == null)
				throw new ArgumentNullException(nameof(element));

			if (candleSeries == null)
				throw new ArgumentNullException(nameof(candleSeries));

			if (indicator == null)
				throw new ArgumentNullException(nameof(indicator));

			Element = element;
			CandleSeries = candleSeries;
			Indicator = indicator;
		}
Example #13
0
        private void Chart_OnSubscribeIndicatorElement(ChartIndicatorElement element, CandleSeries series, IIndicator indicator)
        {
            var chartData = new ChartDrawData();

            foreach (var candle in _allCandles.Cache)
            {
                //if (candle.State != CandleStates.Finished)
                //	candle.State = CandleStates.Finished;

                chartData.Group(candle.OpenTime).Add(element, indicator.Process(candle));
            }

            Chart.Draw(chartData);

            _indicators.Add(element, indicator);
        }
Example #14
0
        public SmaStrategy(CandleSeries series,
                           SimpleMovingAverage longSma, SimpleMovingAverage shortSma,
                           IChart chart, ChartCandleElement candlesElem, ChartTradeElement tradesElem,
                           ChartIndicatorElement longElem, ChartIndicatorElement shortElem)
        {
            _series = new Subscription(series);

            ShortSma = shortSma;
            LongSma  = longSma;

            _chart       = chart;
            _candlesElem = candlesElem;
            _tradesElem  = tradesElem;
            _shortElem   = shortElem;
            _longElem    = longElem;
        }
Example #15
0
        public RiskStrategy(IChart chart, ChartCandleElement candlesElem,
                            ChartTradeElement tradesElem, ChartIndicatorElement shortElem, ChartIndicatorElement longElem,
                            CandleSeries series)
        {
            _chart       = chart;
            _candlesElem = candlesElem;
            _tradesElem  = tradesElem;
            _shortElem   = shortElem;
            _longElem    = longElem;

            _series = series;

            LongATR  = (AverageTrueRange)longElem.Indicator;
            ShortATR = (AverageTrueRange)shortElem.Indicator;
            // PLB = new ParabolicSar();
        }
Example #16
0
        private void ProcessIndicator(ChartIndicatorElement element, IEnumerable <Candle> candles)
        {
            var allValues = candles
                            .Take(_candlesCount)
                            .Select(candle => new RefPair <DateTimeOffset, IDictionary <IChartElement, object> >(candle.OpenTime, new Dictionary <IChartElement, object>
            {
                { element, CreateIndicatorValue(element, candle) }
            }))
                            .ToList();

            GuiDispatcher.GlobalDispatcher.AddAction(() =>
            {
                ChartPanel.Reset(new[] { element });
                ChartPanel.Draw(allValues);
            });
        }
Example #17
0
		public SmaStrategy(IChart chart, ChartCandleElement candlesElem, ChartTradeElement tradesElem, 
			SimpleMovingAverage shortMa, ChartIndicatorElement shortElem,
			SimpleMovingAverage longMa, ChartIndicatorElement longElem,
			CandleSeries series)
		{
			_chart = chart;
			_candlesElem = candlesElem;
			_tradesElem = tradesElem;
			_shortElem = shortElem;
			_longElem = longElem;
			
			_series = series;

			ShortSma = shortMa;
			LongSma = longMa;
		}
Example #18
0
            /// <summary>
            /// Инициализировать рендерер.
            /// </summary>
            /// <returns>Графические данные.</returns>
            public override IEnumerable <ChartIndicatorElement> Init()
            {
                InnerElements.Clear();

                InnerElements.Add(_pnl = new ChartIndicatorElement
                {
                    YAxisId         = BaseElement.YAxisId,
                    DrawStyle       = ChartIndicatorDrawStyles.BandOneValue,
                    Color           = Colors.Green,
                    AdditionalColor = Colors.Red,
                    StrokeThickness = BaseElement.StrokeThickness,
                    Title           = "PnL"
                });

                return(InnerElements);
            }
Example #19
0
        public SmaStrategy(IChart chart, ChartCandleElement candlesElem, ChartTradeElement tradesElem,
                           SimpleMovingAverage shortMa, ChartIndicatorElement shortElem,
                           SimpleMovingAverage longMa, ChartIndicatorElement longElem,
                           CandleSeries series)
        {
            _chart       = chart;
            _candlesElem = candlesElem;
            _tradesElem  = tradesElem;
            _shortElem   = shortElem;
            _longElem    = longElem;

            _series = series;

            ShortSma = shortMa;
            LongSma  = longMa;
        }
Example #20
0
        private void InitCharts()
        {
            Chart.ClearAreas();

            _area = new ChartArea();

            var yAxis = _area.YAxises.First();

            yAxis.AutoRange    = true;
            Chart.IsAutoRange  = true;
            Chart.IsAutoScroll = true;

            Chart.AddArea(_area);

            var series = new CandleSeries(
                typeof(TimeFrameCandle),
                _security,
                TimeSpan.FromMinutes(_timeframe));

            _indicatorElement = null;

            _candleElement = new ChartCandleElement
            {
                FullTitle = "Candles",
                YAxisId   = yAxis.Id
            };
            Chart.AddElement(_area, _candleElement, series);

            if (_addIndicator)
            {
                _indicator = new MyMovingAverage(200)
                {
                    Name = "MyMA"
                };

                _indicatorElement = new ChartIndicatorElement
                {
                    DrawStyle       = ChartIndicatorDrawStyles.Line,
                    AntiAliasing    = true,
                    StrokeThickness = 1,
                    Color           = Colors.Blue,
                    YAxisId         = yAxis.Id,
                };

                Chart.AddElement(_area, _indicatorElement, series, _indicator);
            }
        }
Example #21
0
		private void Chart_OnSubscribeIndicatorElement(ChartIndicatorElement element, CandleSeries series, IIndicator indicator, ChartPanel chart)
		{
			var values = _allCandles
				.Select(candle =>
				{
					if (candle.State != CandleStates.Finished)
						candle.State = CandleStates.Finished;

					return new RefPair<DateTimeOffset, IDictionary<IChartElement, object>>(candle.OpenTime, new Dictionary<IChartElement, object>
					{
						{ element, indicator.Process(candle) }
					});
				})
				.ToArray();

			chart.Draw(values);
		}
Example #22
0
        public void Draw(CandleSeries series, IEnumerable <Candle> candles)
        {
            if (series == null)
            {
                throw new ArgumentNullException("series");
            }

            if (candles == null)
            {
                throw new ArgumentNullException("candles");
            }

            Series   = series;
            _candles = candles;

            _candlesCount = 0;

            var ohlcArea = new ChartArea {
                Height = 210
            };

            ChartPanel.AddArea(ohlcArea);

            _candlesElem = new ChartCandleElement();
            ChartPanel.AddElement(ohlcArea, _candlesElem, series);

            var volumeArea = new ChartArea {
                Height = 130
            };

            ChartPanel.AddArea(volumeArea);

            _volumeElem = new ChartIndicatorElement
            {
                IndicatorPainter = new VolumePainter(),
            };
            var indicator = new VolumeIndicator();

            _indicators.Add(_volumeElem, indicator);
            ChartPanel.AddElement(volumeArea, _volumeElem, series, indicator);

            CancelButton.Visibility = Visibility.Visible;

            _drawTimer.Flush();
        }
Example #23
0
        private void Chart_OnSubscribeIndicatorElement(ChartIndicatorElement element, CandleSeries series, IIndicator indicator)
        {
            var values = _allCandles.Cache
                         .Select(candle =>
            {
                if (candle.State != CandleStates.Finished)
                {
                    candle.State = CandleStates.Finished;
                }

                return(new RefPair <DateTimeOffset, IDictionary <IChartElement, object> >(candle.OpenTime, new Dictionary <IChartElement, object>
                {
                    { element, indicator.Process(candle) }
                }));
            });

            Chart.Draw(values);
        }
Example #24
0
        private void Chart_OnSubscribeIndicatorElement(ChartIndicatorElement element, CandleSeries series, IIndicator indicator)
        {
            _dataThreadActions.Add(() =>
            {
                var chartData = new ChartDrawData();

                foreach (var candle in _allCandles.CachedValues)
                {
                    chartData.Group(candle.OpenTime).Add(element, indicator.Process(candle));
                }

                Chart.Reset(new[] { element });
                Chart.Draw(chartData);

                _indicators[element] = indicator;

                this.GuiAsync(() => CustomColors_Changed(null, null));
            });
        }
Example #25
0
        public SubscribeIndicatorElementCommand(ChartIndicatorElement element, CandleSeries candleSeries, IIndicator indicator)
        {
            if (element == null)
            {
                throw new ArgumentNullException(nameof(element));
            }

            if (candleSeries == null)
            {
                throw new ArgumentNullException(nameof(candleSeries));
            }

            if (indicator == null)
            {
                throw new ArgumentNullException(nameof(indicator));
            }

            Element      = element;
            CandleSeries = candleSeries;
            Indicator    = indicator;
        }
Example #26
0
        private void CreateSourceElements(ContinuousSecurity security)
        {
            var area = _mainArea;
            var id   = 1;

            foreach (var innerSecurity in security.InnerSecurities)
            {
                var series           = new CandleSeries(typeof(TimeFrameCandle), innerSecurity, TimeSpan.FromMinutes(5));
                var indicatorElement = new ChartIndicatorElement
                {
                    Title           = innerSecurity.Id,
                    Color           = _colors[id++],
                    StrokeThickness = 1
                };

                var indicator = new CandlePartIndicator();

                //_indicators.Add(indicatorElement, indicator);
                _sourceElements.Add(innerSecurity, indicatorElement);
                _bufferedChart.AddElement(area, indicatorElement, series, indicator);
            }
        }
Example #27
0
		private IIndicatorValue CreateIndicatorValue(ChartIndicatorElement element, Candle candle)
		{
			var indicator = _indicators.TryGetValue(element);

			if (indicator == null)
				throw new InvalidOperationException(LocalizedStrings.IndicatorNotFound.Put(element));

			return indicator.Process(candle);
		}
Example #28
0
        private void StartClick(object sender, RoutedEventArgs e)
        {
            // если были получены и инструмент, и портфель
            if (_strategy == null)
            {
                if (Portfolios.SelectedPortfolio == null)
                {
                    MessageBox.Show(this, LocalizedStrings.Str3009);
                    return;
                }

                // создаем скользящие средние, на 80 5-минуток и 10 5-минуток
                var longSma = new SimpleMovingAverage {
                    Length = 80
                };
                var shortSma = new SimpleMovingAverage {
                    Length = 10
                };

                // регистрируем наш тайм-фрейм
                var series = new CandleSeries(typeof(TimeFrameCandle), _lkoh, _timeFrame);

                // создаем торговую стратегию
                _strategy = new SmaStrategy(_candleManager, series, longSma, shortSma)
                {
                    Volume    = 1,
                    Security  = _lkoh,
                    Portfolio = Portfolios.SelectedPortfolio,
                    Connector = _trader,
                };
                _logManager.Sources.Add(_strategy);
                //_strategy.Log += OnLog;
                _strategy.PropertyChanged += OnStrategyPropertyChanged;

                _candlesElem = new ChartCandleElement();
                _area.Elements.Add(_candlesElem);

                _longMaElem = new ChartIndicatorElement
                {
                    Title = LocalizedStrings.Long,
                    Color = Colors.OrangeRed
                };
                _area.Elements.Add(_longMaElem);

                _shortMaElem = new ChartIndicatorElement
                {
                    Title = LocalizedStrings.Short,
                    Color = Colors.RoyalBlue
                };
                _area.Elements.Add(_shortMaElem);

                var marketTime = _trader.CurrentTime;

                // начинаем получать свечи за период в 5 дней
                _candleManager.Start(series, DateTime.Today - TimeSpan.FromDays(5), marketTime);

                _lastHistoryCandle = _timeFrame.GetCandleBounds(marketTime).Min;

                Report.IsEnabled = true;
            }

            if (_strategy.ProcessState == ProcessStates.Stopped)
            {
                // запускаем процесс получения стакана, необходимый для работы алгоритма котирования
                _trader.RegisterMarketDepth(_strategy.Security);
                _strategy.Start();
                Start.Content = LocalizedStrings.Str242;
            }
            else
            {
                _trader.UnRegisterMarketDepth(_strategy.Security);
                _strategy.Stop();
                Start.Content = LocalizedStrings.Str2421;
            }
        }
Example #29
0
        private RefPair <DateTimeOffset, IDictionary <IChartElement, object> >[] ProcessHistoryCandles(ChartIndicatorElement element, CandleSeries series)
        {
            var candles = series.GetCandles <Candle>().Where(c => c.State == CandleStates.Finished).ToArray();

            return(candles
                   .Select(candle => new RefPair <DateTimeOffset, IDictionary <IChartElement, object> >(candle.OpenTime, new Dictionary <IChartElement, object>
            {
                { element, CreateIndicatorValue(element, candle) }
            }))
                   .ToArray());
        }
Example #30
0
		private List<RefPair<DateTimeOffset, IDictionary<IChartElement, object>>> ProcessHistoryCandles(ChartIndicatorElement element, CandleSeries series)
		{
			var candles = series.GetCandles<Candle>().Where(c => c.State == CandleStates.Finished).ToArray();

			return candles
				.Select(candle => new RefPair<DateTimeOffset, IDictionary<IChartElement, object>>(candle.OpenTime, new Dictionary<IChartElement, object>
				{
					{ element, CreateIndicatorValue(element, candle) }
				}))
				.ToList();
		}
Example #31
0
		public void Draw(CandleSeries series, IEnumerable<Candle> candles)
		{
			if (series == null)
				throw new ArgumentNullException("series");

			if (candles == null)
				throw new ArgumentNullException("candles");

			Series = series;
			_candles = candles;

			//_candlesCount = 0;

			var ohlcArea = new ChartArea { Height = 210 };
			ChartPanel.AddArea(ohlcArea);

			_candlesElem = new ChartCandleElement();
			ChartPanel.AddElement(ohlcArea, _candlesElem, series);

			var volumeArea = new ChartArea { Height = 130 };
			ChartPanel.AddArea(volumeArea);

			_volumeElem = new ChartIndicatorElement
			{
				IndicatorPainter = new VolumePainter(),
			};
			var indicator = new VolumeIndicator();
			ChartPanel.AddElement(volumeArea, _volumeElem, series, indicator);

			CancelButton.Visibility = Visibility.Visible;

			_drawTimer.Activate();
		}
		public UnSubscribeIndicatorElementCommand(ChartIndicatorElement element)
		{
			if (element == null)
				throw new ArgumentNullException(nameof(element));

			Element = element;
		}
		private void OnChartPanelSubscribeIndicatorElement(ChartIndicatorElement element, CandleSeries candleSeries, IIndicator indicator)
		{
			_bufferedChart.SetSource(element, candleSeries);
			_indicators.Add(element, indicator);

			AddElement(element, candleSeries);
		}
Example #34
0
            public override IEnumerable<ChartIndicatorElement> Init()
            {
                InnerElements.Clear();

                InnerElements.Add(_pnl = new ChartIndicatorElement
                {
                    YAxisId = BaseElement.YAxisId,
                    DrawStyle = ChartIndicatorDrawStyles.BandOneValue,
                    Color = Colors.Green,
                    AdditionalColor = Colors.Red,
                    StrokeThickness = BaseElement.StrokeThickness,
                    Title = LocalizedStrings.PnL
                });

                return InnerElements;
            }
Example #35
0
        private void StartClick(object sender, RoutedEventArgs e)
        {
            if (_strategy == null)
            {
                if (Portfolios.SelectedPortfolio == null)
                {
                    MessageBox.Show(this, LocalizedStrings.Str3009);
                    return;
                }

                // регистрируем наш тайм-фрейм
                var series = new CandleSeries(typeof(TimeFrameCandle), _lkoh, _timeFrame);

                // создаем торговую стратегию, скользящие средние на 80 5-минуток и 10 5-минуток
                _strategy = new SmaStrategy(_candleManager, series, new SimpleMovingAverage {
                    Length = 80
                }, new SimpleMovingAverage {
                    Length = 10
                })
                {
                    Volume    = 1,
                    Security  = _lkoh,
                    Portfolio = Portfolios.SelectedPortfolio,
                    Connector = _trader,
                };
                _strategy.Log             += OnLog;
                _strategy.PropertyChanged += OnStrategyPropertyChanged;

                _candlesElem = new ChartCandleElement();
                _area.Elements.Add(_candlesElem);

                _longMaElem = new ChartIndicatorElement
                {
                    Title = LocalizedStrings.Long,
                    Color = Colors.OrangeRed
                };
                _area.Elements.Add(_longMaElem);

                _shortMaElem = new ChartIndicatorElement
                {
                    Title = LocalizedStrings.Short,
                    Color = Colors.RoyalBlue
                };
                _area.Elements.Add(_shortMaElem);

                IEnumerable <Candle> candles = CultureInfo.InvariantCulture.DoInCulture(() => File.ReadAllLines("LKOH_history.txt").Select(line =>
                {
                    var parts = line.Split(',');
                    var time  = (parts[0] + parts[1]).ToDateTime("yyyyMMddHHmmss").ApplyTimeZone(TimeHelper.Moscow);
                    return((Candle) new TimeFrameCandle
                    {
                        OpenPrice = parts[2].To <decimal>(),
                        HighPrice = parts[3].To <decimal>(),
                        LowPrice = parts[4].To <decimal>(),
                        ClosePrice = parts[5].To <decimal>(),
                        TimeFrame = _timeFrame,
                        OpenTime = time,
                        CloseTime = time + _timeFrame,
                        TotalVolume = parts[6].To <decimal>(),
                        Security = _lkoh,
                        State = CandleStates.Finished,
                    });
                }).ToArray());

                var lastCandleTime = default(DateTimeOffset);

                // начинаем вычислять скользящие средние
                foreach (var candle in candles)
                {
                    ProcessCandle(candle);
                    lastCandleTime = candle.OpenTime;
                }

                _candleManager.Start(series);

                // вычисляем временные отрезки текущей свечи
                var bounds = _timeFrame.GetCandleBounds(_trader.CurrentTime);

                candles = _candleManager.Container.GetCandles(series, new Range <DateTimeOffset>(lastCandleTime + _timeFrame, bounds.Min));

                foreach (var candle in candles)
                {
                    ProcessCandle(candle);
                }

                _isTodaySmaDrawn = true;

                Report.IsEnabled = true;
            }

            if (_strategy.ProcessState == ProcessStates.Stopped)
            {
                // запускаем процесс получения стакана, необходимый для работы алгоритма котирования
                _trader.RegisterMarketDepth(_strategy.Security);
                _strategy.Start();
                Start.Content = LocalizedStrings.Str242;
            }
            else
            {
                _trader.UnRegisterMarketDepth(_strategy.Security);
                _strategy.Stop();
                Start.Content = LocalizedStrings.Str2421;
            }
        }
Example #36
0
		private void StartClick(object sender, RoutedEventArgs e)
		{
			// если были получены и инструмент, и портфель
			if (_strategy == null)
			{
				if (Portfolios.SelectedPortfolio == null)
				{
					MessageBox.Show(this, LocalizedStrings.Str3009);
					return;
				}

				// создаем скользящие средние, на 80 5-минуток и 10 5-минуток
				var longSma = new SimpleMovingAverage { Length = 80 };
				var shortSma = new SimpleMovingAverage { Length = 10 };

				// регистрируем наш тайм-фрейм
				var series = new CandleSeries(typeof(TimeFrameCandle), _lkoh, _timeFrame);

				// создаем торговую стратегию
				_strategy = new SmaStrategy(_candleManager, series, longSma, shortSma)
				{
					Volume = 1,
					Security = _lkoh,
					Portfolio = Portfolios.SelectedPortfolio,
					Connector = _trader,
				};
				_logManager.Sources.Add(_strategy);
				//_strategy.Log += OnLog;
				_strategy.PropertyChanged += OnStrategyPropertyChanged;

				_candlesElem = new ChartCandleElement();
				_area.Elements.Add(_candlesElem);

				_longMaElem = new ChartIndicatorElement
				{
					Title = LocalizedStrings.Long,
					Color = Colors.OrangeRed
				};
				_area.Elements.Add(_longMaElem);

				_shortMaElem = new ChartIndicatorElement
				{
					Title = LocalizedStrings.Short,
					Color = Colors.RoyalBlue
				};
				_area.Elements.Add(_shortMaElem);

				var marketTime = _trader.CurrentTime;

				// начинаем получать свечи за период в 5 дней
				_candleManager.Start(series, DateTime.Today - TimeSpan.FromDays(5), marketTime);

				_lastHistoryCandle = _timeFrame.GetCandleBounds(marketTime).Min;

				Report.IsEnabled = true;
			}

			if (_strategy.ProcessState == ProcessStates.Stopped)
			{
				// запускаем процесс получения стакана, необходимый для работы алгоритма котирования
				_trader.RegisterMarketDepth(_strategy.Security);
				_strategy.Start();
				Start.Content = LocalizedStrings.Str242;
			}
			else
			{
				_trader.UnRegisterMarketDepth(_strategy.Security);
				_strategy.Stop();
				Start.Content = LocalizedStrings.Str2421;
			}
		}
		private void OnChartPanelSubscribeIndicatorElement(ChartIndicatorElement element, CandleSeries candleSeries, IIndicator indicator)
		{
			new SubscribeIndicatorElementCommand(element, candleSeries, indicator).Process(this);
		}
Example #38
0
 private void OnChartPanelSubscribeIndicatorElement(ChartIndicatorElement element, CandleSeries candleSeries, IIndicator indicator)
 {
     _elements.Add(element);
     _indicators.Add(element, indicator);
     _drawTimer.Reset();
 }
Example #39
0
        private void InitCharts()
        {
            Chart.ClearAreas();

            _area = new ChartArea {
                ShowPerfStats = true
            };

            var yAxis = _area.YAxises.First();

            yAxis.AutoRange    = true;
            Chart.IsAutoRange  = true;
            Chart.IsAutoScroll = true;

            Chart.AddArea(_area);

            var series = new CandleSeries(
                typeof(TimeFrameCandle),
                _security,
                TimeSpan.FromMinutes(Timeframe));

            _indicatorElement = null;
            _tradeElement     = null;

            _candleElement = new ChartCandleElement(Timeframe, PriceStep)
            {
                FullTitle = "Candles", YAxisId = yAxis.Id
            };
            Chart.AddElement(_area, _candleElement, series);

            if (AddIndicator)
            {
                _indicator = new MyMovingAverage(200)
                {
                    Name = "MyMA"
                };

                _indicatorElement = new ChartIndicatorElement
                {
                    DrawStyle       = ChartIndicatorDrawStyles.Line,
                    Antialiasing    = true,
                    StrokeThickness = 1,
                    Color           = Colors.Blue,
                    YAxisId         = yAxis.Id,
                };

                Chart.AddElement(_area, _indicatorElement, series, _indicator);
            }

            if (AddTrades)
            {
                _tradeElement = new ChartTradeElement {
                    FullTitle = "Trades"
                };
                Chart.AddElement(_area, _tradeElement, _security);
            }

            var ns = typeof(IIndicator).Namespace;

            var rendererTypes = typeof(Chart).Assembly
                                .GetTypes()
                                .Where(t => !t.IsAbstract && typeof(BaseChartIndicatorPainter).IsAssignableFrom(t))
                                .ToDictionary(t => t.Name);

            var indicators = typeof(IIndicator).Assembly
                             .GetTypes()
                             .Where(t => t.Namespace == ns && !t.IsAbstract && typeof(IIndicator).IsAssignableFrom(t))
                             .Select(t =>
            {
                var name = t.Name;
                var p    = rendererTypes.TryGetValue(name + "Painter");
                if (p == null)
                {
                    if (t.Name.EndsWith("Indicator"))
                    {
                        name = name.Substring(0, name.Length - "Indicator".Length);
                    }

                    p = rendererTypes.TryGetValue(name + "Painter");
                }

                return(new IndicatorType(t, p));
            })
                             .ToArray();

            Chart.IndicatorTypes.AddRange(indicators);
        }
Example #40
0
        private void Chart_SubscribeIndicatorElement(ChartIndicatorElement element, CandleSeries series, IIndicator indicator)
        {
            var candles = _candles.TryGetValue(series.Security);

            if (candles == null)
                throw new InvalidOperationException("_candles == null");

            var values = candles
                .Select(candle =>
                {
                    if (candle.State != CandleStates.Finished)
                        candle.State = CandleStates.Finished;

                    return new RefPair<DateTimeOffset, IDictionary<IChartElement, object>>(candle.OpenTime, new Dictionary<IChartElement, object>
                    {
                        { element, indicator.Process(candle) }
                    });
                })
                .ToArray();

            Chart.Draw(values);
        }
		private void AddIndicator(ChartIndicatorElement element)
		{
			var series = (CandleSeries)_bufferedChart.GetSource(element);

			if (series == null)
				return;

			if (_sourceElements.ContainsKey(series.Security))
				return;

			IEnumerable<RefPair<DateTimeOffset, IDictionary<IChartElement, object>>> allValues;

			lock (_syncRoot)
			{
				allValues = series
					.GetCandles<TimeFrameCandle>()
					.Take(_candlesCount)
					.Select(candle => new RefPair<DateTimeOffset, IDictionary<IChartElement, object>>(candle.OpenTime, new Dictionary<IChartElement, object>
					{
						{ element, CreateIndicatorValue(element, candle) }
					}))
					.ToArray();

				_skipElements.Remove(element);
			}

			_bufferedChart.Reset(new[] { element });
			_bufferedChart.Draw(allValues);
		}
Example #42
0
        private void Download_OnClick(object sender, RoutedEventArgs e)
        {
            var year = SelectedYear;
            var from = From.Value ?? year.Days.First();
            var to = (To.Value ?? year.Days.Last()).EndOfDay();
            var trader = SelectedTrader;
            var tf = SelectedTimeFrame;

            var seriesSet = _securityCtrls
                .Where(pair => pair.Key.SelectedSecurity != null)
                .Select(pair => Tuple.Create(new CandleSeries(typeof(TimeFrameCandle), pair.Key.SelectedSecurity, tf), pair.Value))
                .ToArray();

            BusyIndicator.BusyContent = "Подготовка данных...";
            BusyIndicator.IsBusy = true;

            _candles.Clear();

            var trades = new Dictionary<Security, Dictionary<DateTimeOffset, Tuple<MyTrade[], MyTrade>>>();

            var worker = new BackgroundWorker { WorkerReportsProgress = true };

            worker.DoWork += (o, ea) =>
            {
                foreach (var series in seriesSet)
                {
                    var security = series.Item1.Security;
                    var candleStorage = _dataRegistry.GetCandleStorage(series.Item1, format: StorageFormats.Csv);
                    var secCandles = _candles.SafeAdd(security);

                    secCandles.Clear();
                    secCandles.AddRange(candleStorage.Load(from, to));

                    var candlesDatesCache = _candlesDates.SafeAdd(Tuple.Create(security, tf), k => new DatesCache(Path.Combine(((LocalMarketDataDrive)candleStorage.Drive.Drive).GetSecurityPath(security.ToSecurityId()), "{0}min_date.bin".Put((int)tf.TotalMinutes))));

                    var minCandleDate = candlesDatesCache.MinValue;
                    var maxCandleDate = candlesDatesCache.MaxValue;

                    if (from >= minCandleDate && to <= maxCandleDate)
                        continue;

                    var finamFrom = from;
                    var finamTo = to;

                    if (maxCandleDate != null && finamFrom >= minCandleDate && finamFrom <= maxCandleDate)
                        finamFrom = maxCandleDate.Value + TimeSpan.FromDays(1);

                    if (minCandleDate != null && finamTo >= minCandleDate && finamTo <= maxCandleDate)
                        finamTo = minCandleDate.Value - TimeSpan.FromDays(1);

                    if (finamTo <= finamFrom)
                        continue;

                    worker.ReportProgress(1, Tuple.Create(security, finamFrom, finamTo));

                    var newCandles = (tf.Ticks == 1
                        ? finamFrom.Range(finamTo, TimeSpan.FromDays(1)).SelectMany(day => _finamHistorySource.GetTrades(security, day, day)).ToEx().ToCandles<TimeFrameCandle>(tf)
                        : _finamHistorySource.GetCandles(security, tf, finamFrom, finamTo)
                        ).ToArray();

                    candleStorage.Save(newCandles);

                    foreach (var date in newCandles.Select(c => c.OpenTime.Date).Distinct())
                        candlesDatesCache.Add(date);

                    candlesDatesCache.Save();

                    // TODO
                    secCandles.AddRange(newCandles);
                }

                var traderDrive = new LocalMarketDataDrive(trader);
                var traderStorage = _traderStorages.SafeAdd(trader, key => new StorageRegistry { DefaultDrive = traderDrive });

                foreach (var series in seriesSet)
                {
                    var security = series.Item1.Security;

                    var olStorage = traderStorage.GetOrderLogStorage(security, format: StorageFormats.Csv);
                    var tradeDatesCache = _tradesDates.SafeAdd(trader, k => new DatesCache(Path.Combine(traderDrive.Path, "dates.bin")));

                    var secTrades = from
                        .Range(to, TimeSpan.FromDays(1))
                        .Intersect(year.Days)
                        .SelectMany(date =>
                        {
                            if (olStorage.Dates.Contains(date))
                                return olStorage.Load(date);

                            if (tradeDatesCache.Contains(date))
                                return Enumerable.Empty<OrderLogItem>();

                            worker.ReportProgress(2, date);

                            var loadedTrades = year.GetTrades(_securityStorage, trader, date);

                            var dateTrades = Enumerable.Empty<OrderLogItem>();

                            foreach (var group in loadedTrades.GroupBy(t => t.Order.Security))
                            {
                                var sec = group.Key;

                                traderStorage
                                    .GetOrderLogStorage(sec, format: StorageFormats.Csv)
                                    .Save(group.OrderBy(i => i.Order.Time));

                                if (group.Key == security)
                                    dateTrades = group;
                            }

                            tradeDatesCache.Add(date);
                            tradeDatesCache.Save();

                            return dateTrades;
                        })
                        .GroupBy(ol =>
                        {
                            var time = ol.Order.Time;

                            var period = security.Board.WorkingTime.GetPeriod(time.ToLocalTime(security.Board.Exchange.TimeZoneInfo));
                            if (period != null && period.Times.Length > 0)
                            {
                                var last = period.Times.Last().Max;

                                if (time.TimeOfDay >= last)
                                    time = time.AddTicks(-1);
                            }

                            return time.Truncate(tf);
                        })
                        .ToDictionary(g => g.Key, g =>
                        {
                            var candleTrades = g.Select(ol => new MyTrade
                            {
                                Order = ol.Order,
                                Trade = ol.Trade
                            })
                            .ToArray();

                            if (candleTrades.Length == 0)
                                return null;

                            var order = candleTrades[0].Order;
                            var volume = candleTrades.Sum(t1 => t1.Trade.Volume * (t1.Order.Direction == Sides.Buy ? 1 : -1));

                            if (volume == 0)
                                return Tuple.Create(candleTrades, (MyTrade)null);

                            var side = volume > 0 ? Sides.Buy : Sides.Sell;

                            volume = volume.Abs();

                            var availableVolume = volume;
                            var avgPrice = 0m;

                            foreach (var trade in candleTrades.Where(t1 => t1.Order.Direction == side))
                            {
                                var tradeVol = trade.Trade.Volume.Min(availableVolume);
                                avgPrice += trade.Trade.Price * tradeVol;

                                availableVolume -= tradeVol;

                                if (availableVolume <= 0)
                                    break;
                            }

                            avgPrice = avgPrice / volume;

                            return Tuple.Create(candleTrades, new MyTrade
                            {
                                Order = new Order
                                {
                                    Security = order.Security,
                                    Direction = side,
                                    Time = g.Key,
                                    Portfolio = order.Portfolio,
                                    Price = avgPrice,
                                    Volume = volume,
                                },
                                Trade = new Trade
                                {
                                    Security = order.Security,
                                    Time = g.Key,
                                    Volume = volume,
                                    Price = avgPrice
                                }
                            });
                        });

                    trades.Add(security, secTrades);
                }
            };

            worker.ProgressChanged += (o, ea) =>
            {
                switch (ea.ProgressPercentage)
                {
                    case 1:
                        BusyIndicator.BusyContent = "Скачивание {Item1.Id} свечей с {Item2:yyyy-MM-dd} по {Item3:yyyy-MM-dd}...".PutEx(ea.UserState);
                        break;

                    default:
                        BusyIndicator.BusyContent = "Скачивание сделок за {0:yyyy-MM-dd}...".Put(ea.UserState);
                        break;
                }
            };

            worker.RunWorkerCompleted += (o, ea) =>
            {
                BusyIndicator.IsBusy = false;

                if (ea.Error == null)
                {
                    Chart.ClearAreas();

                    _statisticManager.Reset();

                    var candlesArea = new ChartArea();
                    Chart.AddArea(candlesArea);

                    var positionArea = new ChartArea { Height = 200 };
                    Chart.AddArea(positionArea);
                    positionArea.YAxises.Clear();

                    const string equityYAxis = "Equity";

                    candlesArea.YAxises.Clear();
                    candlesArea.YAxises.Add(new ChartAxis
                    {
                        Id = equityYAxis,
                        AutoRange = true,
                        AxisType = ChartAxisType.Numeric,
                        AxisAlignment = ChartAxisAlignment.Left,
                    });
                    var equityElem = new ChartIndicatorElement
                    {
                        YAxisId = equityYAxis,
                        FullTitle = LocalizedStrings.PnL,
                        IndicatorPainter = new PnlPainter()
                    };
                    var equityInd = new SimpleMovingAverage { Length = 1 };
                    Chart.AddElement(candlesArea, equityElem);

                    var chartValues = new SortedDictionary<DateTimeOffset, IDictionary<IChartElement, object>>();
                    var pnlValues = new Dictionary<DateTimeOffset, decimal>();

                    foreach (var series in seriesSet)
                    {
                        var security = series.Item1.Security;

                        var candleYAxis = "Candles_Y_" + security.Id;

                        candlesArea.YAxises.Add(new ChartAxis
                        {
                            Id = candleYAxis,
                            AutoRange = true,
                            AxisType = ChartAxisType.Numeric,
                            AxisAlignment = ChartAxisAlignment.Right,
                        });

                        var candlesElem = new ChartCandleElement
                        {
                            ShowAxisMarker = false,
                            YAxisId = candleYAxis,
                        };
                        Chart.AddElement(candlesArea, candlesElem, series.Item1);

                        var tradesElem = new ChartTradeElement
                        {
                            BuyStrokeColor = Colors.Black,
                            SellStrokeColor = Colors.Black,
                            BuyColor = series.Item2.Buy,
                            SellColor = series.Item2.Sell,
                            FullTitle = LocalizedStrings.Str985 + " " + security.Id,
                            YAxisId = candleYAxis,
                        };
                        Chart.AddElement(candlesArea, tradesElem);

                        var posYAxis = "Pos_Y_" + security.Id;
                        positionArea.YAxises.Add(new ChartAxis
                        {
                            Id = posYAxis,
                            AutoRange = true,
                            AxisType = ChartAxisType.Numeric,
                            AxisAlignment = ChartAxisAlignment.Right,
                        });
                        var positionElem = new ChartIndicatorElement
                        {
                            FullTitle = LocalizedStrings.Str862 + " " + security.Id,
                            YAxisId = posYAxis,
                            Color = series.Item2.Position
                        };
                        var positionInd = new SimpleMovingAverage { Length = 1 };
                        Chart.AddElement(positionArea, positionElem);

                        var pnlQueue = new PnLQueue(security.ToSecurityId());
                        //var level1Info = new Level1ChangeMessage
                        //{
                        //	SecurityId = pnlQueue.SecurityId,
                        //}
                        //.TryAdd(Level1Fields.PriceStep, security.PriceStep)
                        //.TryAdd(Level1Fields.StepPrice, security.StepPrice);

                        //pnlQueue.ProcessLevel1(level1Info);

                        var pos = 0m;

                        var secTrades = trades[security];

                        var secValues = _candles[security]
                            .Select(c =>
                            {
                                if (c.State != CandleStates.Finished)
                                    c.State = CandleStates.Finished;

                                pnlQueue.ProcessLevel1(new Level1ChangeMessage
                                {
                                    SecurityId = security.ToSecurityId(),
                                }.TryAdd(Level1Fields.LastTradePrice, c.ClosePrice));

                                var values = new Dictionary<IChartElement, object>
                                {
                                    { candlesElem, c },
                                };

                                var candleTrade = secTrades.TryGetValue(c.OpenTime);

                                if (candleTrade != null)
                                {
                                    if (candleTrade.Item2 != null)
                                        values.Add(tradesElem, candleTrade.Item2);

                                    foreach (var myTrade in candleTrade.Item1)
                                    {
                                        pos += myTrade.Order.Direction == Sides.Buy ? myTrade.Trade.Volume : -myTrade.Trade.Volume;
                                        var pnl = pnlQueue.Process(myTrade.ToMessage());

                                        _statisticManager.AddMyTrade(pnl);
                                    }

                                    _statisticManager.AddPosition(c.OpenTime, pos);
                                    _statisticManager.AddPnL(c.OpenTime, pnlQueue.RealizedPnL + pnlQueue.UnrealizedPnL);
                                }

                                pnlValues[c.OpenTime] = pnlValues.TryGetValue(c.OpenTime) + (pnlQueue.RealizedPnL + pnlQueue.UnrealizedPnL);
                                values.Add(positionElem, positionInd.Process(pos));

                                return new RefPair<DateTimeOffset, IDictionary<IChartElement, object>>
                                {
                                    First = c.OpenTime,
                                    Second = values
                                };
                            })
                            .ToArray();

                        foreach (var pair in secValues)
                        {
                            var dict = chartValues.SafeAdd(pair.First, key => new Dictionary<IChartElement, object>());

                            foreach (var pair2 in pair.Second)
                            {
                                dict[pair2.Key] = pair2.Value;
                            }
                        }
                    }

                    foreach (var pair in pnlValues)
                    {
                        chartValues[pair.Key].Add(equityElem, equityInd.Process(pair.Value));
                    }

                    Chart.IsAutoRange = true;

                    try
                    {
                        Chart.Draw(chartValues.Select(p => RefTuple.Create(p.Key, p.Value)));
                    }
                    finally
                    {
                        Chart.IsAutoRange = false;
                    }
                }
                else
                {
                    new MessageBoxBuilder()
                        .Error()
                        .Owner(this)
                        .Text(ea.Error.ToString())
                        .Show();
                }
            };

            worker.RunWorkerAsync();
        }
		private void CreateSourceElements(IndexSecurity security)
		{
			var area = _mainArea;

			var axisId = 1;

			foreach (var innerSecurity in security.InnerSecurities)
			{
				var axisName = "SA_" + axisId++;

				var series = new CandleSeries(typeof(TimeFrameCandle), innerSecurity, TimeSpan.FromMinutes(5));
				var indicatorElement = new ChartIndicatorElement
				{
					Title = innerSecurity.Id,
					Color = _colors[axisId],
					YAxisId = axisName,
					StrokeThickness = 1
				};

				area.YAxises.Add(new ChartAxis
				{
					Id = axisName,
					AutoRange = true,
					AxisType = ChartAxisType.Numeric,
					AxisAlignment = ChartAxisAlignment.Right
				});

				var indicator = new CandlePartIndicator();

				//_indicators.Add(indicatorElement, indicator);
				_sourceElements.Add(innerSecurity, indicatorElement);
				_bufferedChart.AddElement(area, indicatorElement, series, indicator);
			}
		}
Example #44
0
		private void StartBtnClick(object sender, RoutedEventArgs e)
		{
			InitChart();

			if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text))
			{
				MessageBox.Show(this, LocalizedStrings.Str3014);
				return;
			}

			if (_connectors.Any(t => t.State != EmulationStates.Stopped))
			{
				MessageBox.Show(this, LocalizedStrings.Str3015);
				return;
			}

			var secIdParts = SecId.Text.Split('@');

			if (secIdParts.Length != 2)
			{
				MessageBox.Show(this, LocalizedStrings.Str3016);
				return;
			}

			var timeFrame = TimeSpan.FromMinutes(5);

			// create backtesting modes
			var settings = new[]
			{
				Tuple.Create(
					TicksCheckBox,
					TicksTestingProcess,
					TicksParameterGrid,
					// ticks
					new EmulationInfo {UseTicks = true, CurveColor = Colors.DarkGreen, StrategyName = LocalizedStrings.Ticks}),

				Tuple.Create(
					TicksAndDepthsCheckBox,
					TicksAndDepthsTestingProcess,
					TicksAndDepthsParameterGrid,
					// ticks + order book
					new EmulationInfo {UseTicks = true, UseMarketDepth = true, CurveColor = Colors.Red, StrategyName = LocalizedStrings.XamlStr757}),

				Tuple.Create(
					DepthsCheckBox,
					DepthsTestingProcess,
					DepthsParameterGrid,
					// order book
					new EmulationInfo {UseMarketDepth = true, CurveColor = Colors.OrangeRed, StrategyName = LocalizedStrings.MarketDepths}),


				Tuple.Create(
					CandlesCheckBox,
					CandlesTestingProcess,
					CandlesParameterGrid,
					// candles
					new EmulationInfo {UseCandleTimeFrame = timeFrame, CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.Candles}),
				
				Tuple.Create(
					CandlesAndDepthsCheckBox,
					CandlesAndDepthsTestingProcess,
					CandlesAndDepthsParameterGrid,
					// candles + orderbook
					new EmulationInfo {UseMarketDepth = true, UseCandleTimeFrame = timeFrame, CurveColor = Colors.Cyan, StrategyName = LocalizedStrings.XamlStr635}),
			
				Tuple.Create(
					OrderLogCheckBox,
					OrderLogTestingProcess,
					OrderLogParameterGrid,
					// order log
					new EmulationInfo {UseOrderLog = true, CurveColor = Colors.CornflowerBlue, StrategyName = LocalizedStrings.OrderLog})
			};

			// storage to historical data
			var storageRegistry = new StorageRegistry
			{
				// set historical path
				DefaultDrive = new LocalMarketDataDrive(HistoryPath.Text)
			};

			var startTime = ((DateTime)From.Value).ChangeKind(DateTimeKind.Utc);
			var stopTime = ((DateTime)To.Value).ChangeKind(DateTimeKind.Utc);

			// ОЛ необходимо загружать с 18.45 пред дня, чтобы стаканы строились правильно
			if (OrderLogCheckBox.IsChecked == true)
				startTime = startTime.Subtract(TimeSpan.FromDays(1)).AddHours(18).AddMinutes(45).AddTicks(1);

			// ProgressBar refresh step
			var progressStep = ((stopTime - startTime).Ticks / 100).To<TimeSpan>();

			// set ProgressBar bounds
			_progressBars.ForEach(p =>
			{
				p.Value = 0;
				p.Maximum = 100;
			});
			
			var logManager = new LogManager();
			var fileLogListener = new FileLogListener("sample.log");
			logManager.Listeners.Add(fileLogListener);
			//logManager.Listeners.Add(new DebugLogListener());	// for track logs in output window in Vusial Studio (poor performance).

			var generateDepths = GenDepthsCheckBox.IsChecked == true;
			var maxDepth = MaxDepth.Text.To<int>();
			var maxVolume = MaxVolume.Text.To<int>();

			var secCode = secIdParts[0];
			var board = ExchangeBoard.GetOrCreateBoard(secIdParts[1]);

			foreach (var set in settings)
			{
				if (set.Item1.IsChecked == false)
					continue;

				var progressBar = set.Item2;
				var statistic = set.Item3;
				var emulationInfo = set.Item4;

				// create test security
				var security = new Security
				{
					Id = SecId.Text, // sec id has the same name as folder with historical data
					Code = secCode,
					Board = board,
				};

				var level1Info = new Level1ChangeMessage
				{
					SecurityId = security.ToSecurityId(),
					ServerTime = startTime,
				}
				.TryAdd(Level1Fields.PriceStep, 10m)
				.TryAdd(Level1Fields.StepPrice, 6m)
				.TryAdd(Level1Fields.MinPrice, 10m)
				.TryAdd(Level1Fields.MaxPrice, 1000000m)
				.TryAdd(Level1Fields.MarginBuy, 10000m)
				.TryAdd(Level1Fields.MarginSell, 10000m);

				// test portfolio
				var portfolio = new Portfolio
				{
					Name = "test account",
					BeginValue = 1000000,
				};

				// create backtesting connector
				var connector = new HistoryEmulationConnector(
					new[] { security },
					new[] { portfolio })
				{
					MarketEmulator =
					{
						Settings =
						{
							// match order if historical price touched our limit order price. 
							// It is terned off, and price should go through limit order price level
							// (more "severe" test mode)
							MatchOnTouch = false,
						}
					},

					UseExternalCandleSource = emulationInfo.UseCandleTimeFrame != null,

					CreateDepthFromOrdersLog = emulationInfo.UseOrderLog,
					CreateTradesFromOrdersLog = emulationInfo.UseOrderLog,

					HistoryMessageAdapter =
					{
						StorageRegistry = storageRegistry,

						// set history range
						StartDate = startTime,
						StopDate = stopTime,
					},

					// set market time freq as time frame
					MarketTimeChangedInterval = timeFrame,
				};

				((ILogSource)connector).LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info;

				logManager.Sources.Add(connector);

				var candleManager = emulationInfo.UseCandleTimeFrame == null
					? new CandleManager(new TradeCandleBuilderSourceEx(connector))
					: new CandleManager(connector);

				var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame);

				_shortMa = new SimpleMovingAverage { Length = 10 };
				_shortElem = new ChartIndicatorElement
				{
					Color = Colors.Coral,
					ShowAxisMarker = false,
					FullTitle = _shortMa.ToString()
				};
				_bufferedChart.AddElement(_area, _shortElem);

				_longMa = new SimpleMovingAverage { Length = 80 };
				_longElem = new ChartIndicatorElement
				{
					ShowAxisMarker = false,
					FullTitle = _longMa.ToString()
				};
				_bufferedChart.AddElement(_area, _longElem);

				// create strategy based on 80 5-min и 10 5-min
				var strategy = new SmaStrategy(_bufferedChart, _candlesElem, _tradesElem, _shortMa, _shortElem, _longMa, _longElem, series)
				{
					Volume = 1,
					Portfolio = portfolio,
					Security = security,
					Connector = connector,
					LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info,

					// by default interval is 1 min,
					// it is excessively for time range with several months
					UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To<TimeSpan>()
				};

				logManager.Sources.Add(strategy);

				connector.NewSecurities += securities =>
				{
					if (securities.All(s => s != security))
						return;

					// fill level1 values
					connector.SendInMessage(level1Info);

					if (emulationInfo.UseMarketDepth)
					{
						connector.RegisterMarketDepth(security);

						if (
								// if order book will be generated
								generateDepths ||
								// of backtesting will be on candles
								emulationInfo.UseCandleTimeFrame != TimeSpan.Zero
							)
						{
							// if no have order book historical data, but strategy is required,
							// use generator based on last prices
							connector.RegisterMarketDepth(new TrendMarketDepthGenerator(connector.GetSecurityId(security))
							{
								Interval = TimeSpan.FromSeconds(1), // order book freq refresh is 1 sec
								MaxAsksDepth = maxDepth,
								MaxBidsDepth = maxDepth,
								UseTradeVolume = true,
								MaxVolume = maxVolume,
								MinSpreadStepCount = 2,	// min spread generation is 2 pips
								MaxSpreadStepCount = 5,	// max spread generation size (prevent extremely size)
								MaxPriceStepCount = 3	// pips size,
							});
						}
					}

					if (emulationInfo.UseOrderLog)
					{
						connector.RegisterOrderLog(security);
					}

					if (emulationInfo.UseTicks)
					{
						connector.RegisterTrades(security);
					}

					// start strategy before emulation started
					strategy.Start();
					candleManager.Start(series);

					// start historical data loading when connection established successfully and all data subscribed
					connector.Start();
				};

				// fill parameters panel
				statistic.Parameters.Clear();
				statistic.Parameters.AddRange(strategy.StatisticManager.Parameters);

				var pnlCurve = Curve.CreateCurve("P&L " + emulationInfo.StrategyName, emulationInfo.CurveColor, EquityCurveChartStyles.Area);
				var unrealizedPnLCurve = Curve.CreateCurve(LocalizedStrings.PnLUnreal + emulationInfo.StrategyName, Colors.Black);
				var commissionCurve = Curve.CreateCurve(LocalizedStrings.Str159 + " " + emulationInfo.StrategyName, Colors.Red, EquityCurveChartStyles.DashedLine);
				var posItems = PositionCurve.CreateCurve(emulationInfo.StrategyName, emulationInfo.CurveColor);
				strategy.PnLChanged += () =>
				{
					var pnl = new EquityData
					{
						Time = strategy.CurrentTime,
						Value = strategy.PnL - strategy.Commission ?? 0
					};

					var unrealizedPnL = new EquityData
					{
						Time = strategy.CurrentTime,
						Value = strategy.PnLManager.UnrealizedPnL
					};

					var commission = new EquityData
					{
						Time = strategy.CurrentTime,
						Value = strategy.Commission ?? 0
					};

					pnlCurve.Add(pnl);
					unrealizedPnLCurve.Add(unrealizedPnL);
					commissionCurve.Add(commission);
				};

				strategy.PositionChanged += () => posItems.Add(new EquityData { Time = strategy.CurrentTime, Value = strategy.Position });

				var nextTime = startTime + progressStep;

				// handle historical time for update ProgressBar
				connector.MarketTimeChanged += d =>
				{
					if (connector.CurrentTime < nextTime && connector.CurrentTime < stopTime)
						return;

					var steps = (connector.CurrentTime - startTime).Ticks / progressStep.Ticks + 1;
					nextTime = startTime + (steps * progressStep.Ticks).To<TimeSpan>();
					this.GuiAsync(() => progressBar.Value = steps);
				};

				connector.StateChanged += () =>
				{
					if (connector.State == EmulationStates.Stopped)
					{
						candleManager.Stop(series);
						strategy.Stop();

						logManager.Dispose();
						_connectors.Clear();

						SetIsEnabled(false);

						this.GuiAsync(() =>
						{
							if (connector.IsFinished)
							{
								progressBar.Value = progressBar.Maximum;
								MessageBox.Show(this, LocalizedStrings.Str3024.Put(DateTime.Now - _startEmulationTime));
							}
							else
								MessageBox.Show(this, LocalizedStrings.cancelled);
						});
					}
					else if (connector.State == EmulationStates.Started)
					{
						SetIsEnabled(true);
					}
				};

				if (ShowDepth.IsChecked == true)
				{
					MarketDepth.UpdateFormat(security);

					connector.NewMessage += message =>
					{
						var quoteMsg = message as QuoteChangeMessage;

						if (quoteMsg != null)
							MarketDepth.UpdateDepth(quoteMsg);
					};
				}

				_connectors.Add(connector);

				progressBar.Value = 0;
			}

			_startEmulationTime = DateTime.Now;

			// start emulation
			foreach (var connector in _connectors)
			{
				// raise NewSecurities and NewPortfolio for full fill strategy properties
				connector.Connect();

				// 1 cent commission for trade
				connector.SendInMessage(new CommissionRuleMessage
				{
					Rule = new CommissionPerTradeRule { Value = 0.01m }
				});
			}

			TabControl.Items.Cast<TabItem>().First(i => i.Visibility == Visibility.Visible).IsSelected = true;
		}
		private void CreateSourceElements(ContinuousSecurity security)
		{
			var area = _mainArea;
			var id = 1;

			foreach (var innerSecurity in security.InnerSecurities)
			{
				var series = new CandleSeries(typeof(TimeFrameCandle), innerSecurity, TimeSpan.FromMinutes(5));
				var indicatorElement = new ChartIndicatorElement
				{
					Title = innerSecurity.Id,
					Color = _colors[id++],
					StrokeThickness = 1
				};

				var indicator = new CandlePartIndicator();

				//_indicators.Add(indicatorElement, indicator);
				_sourceElements.Add(innerSecurity, indicatorElement);
				_bufferedChart.AddElement(area, indicatorElement, series, indicator);
			}
		}
Example #46
0
		private void StartClick(object sender, RoutedEventArgs e)
		{
			if (_strategy == null)
			{
				if (Portfolios.SelectedPortfolio == null)
				{
					MessageBox.Show(this, LocalizedStrings.Str3009);
					return;
				}

				// регистрируем наш тайм-фрейм
				var series = new CandleSeries(typeof(TimeFrameCandle), _lkoh, _timeFrame);

				// создаем торговую стратегию, скользящие средние на 80 5-минуток и 10 5-минуток
				_strategy = new SmaStrategy(series, new SimpleMovingAverage { Length = 80 }, new SimpleMovingAverage { Length = 10 })
				{
					Volume = 1,
					Security = _lkoh,
					Portfolio = Portfolios.SelectedPortfolio,
					Connector = _trader,
				};
				_strategy.Log += OnLog;
				_strategy.PropertyChanged += OnStrategyPropertyChanged;

				_candlesElem = new ChartCandleElement();
				_area.Elements.Add(_candlesElem);

				_longMaElem = new ChartIndicatorElement
				{
					Title = LocalizedStrings.Long,
					Color = Colors.OrangeRed
				};
				_area.Elements.Add(_longMaElem);

				_shortMaElem = new ChartIndicatorElement
				{
					Title = LocalizedStrings.Short,
					Color = Colors.RoyalBlue
				};
				_area.Elements.Add(_shortMaElem);

				IEnumerable<Candle> candles = CultureInfo.InvariantCulture.DoInCulture(() => File.ReadAllLines("LKOH_history.txt").Select(line =>
				{
					var parts = line.Split(',');
					var time = (parts[0] + parts[1]).ToDateTime("yyyyMMddHHmmss").ApplyTimeZone(TimeHelper.Moscow);
					return (Candle)new TimeFrameCandle
					{
						OpenPrice = parts[2].To<decimal>(),
						HighPrice = parts[3].To<decimal>(),
						LowPrice = parts[4].To<decimal>(),
						ClosePrice = parts[5].To<decimal>(),
						TimeFrame = _timeFrame,
						OpenTime = time,
						CloseTime = time + _timeFrame,
						TotalVolume = parts[6].To<decimal>(),
						Security = _lkoh,
						State = CandleStates.Finished,
					};
				}).ToArray());

				var lastCandleTime = default(DateTimeOffset);

				// начинаем вычислять скользящие средние
				foreach (var candle in candles)
				{
					ProcessCandle(candle);
					lastCandleTime = candle.OpenTime;
				}

				_candleManager.Start(series);

				// вычисляем временные отрезки текущей свечи
				var bounds = _timeFrame.GetCandleBounds(series.Security.ToExchangeTime(_trader.CurrentTime));

				candles = _candleManager.Container.GetCandles(series, new Range<DateTimeOffset>(lastCandleTime + _timeFrame, bounds.Min));

				foreach (var candle in candles)
				{
					ProcessCandle(candle);
				}

				_isTodaySmaDrawn = true;

				Report.IsEnabled = true;
			}

			if (_strategy.ProcessState == ProcessStates.Stopped)
			{
				// запускаем процесс получения стакана, необходимый для работы алгоритма котирования
				_trader.RegisterMarketDepth(_strategy.Security);
				_strategy.Start();
				Start.Content = LocalizedStrings.Str242;
			}
			else
			{
				_trader.UnRegisterMarketDepth(_strategy.Security);
				_strategy.Stop();
				Start.Content = LocalizedStrings.Str2421;
			}
		}
Example #47
0
		private void SetSource(ChartIndicatorElement element, CandleSeries candleSeries, IIndicator indicator)
		{
			List<RefPair<DateTimeOffset, IDictionary<IChartElement, object>>> values = null;

			lock (_syncRoot)
			{
				_indicators[element] = indicator;

				var isNew = !_elementsBySeries.ContainsKey(candleSeries);

				if (!isNew && CanProcess)
				{
					values = ProcessHistoryCandles(element, candleSeries);
				}
				else if (isNew)
					SubscribeSeries(candleSeries);

				var lastDate = values == null || values.IsEmpty() ? DateTimeOffset.MinValue : values.Last().First;

				_elementsInfo.SafeAdd(element, e => RefTuple.Create(lastDate, candleSeries));
				_elementsBySeries.SafeAdd(candleSeries).Add(element);
			}

			if (values != null && values.Count > 0)
				new ChartDrawCommand(values).Process(this);
		}
Example #48
0
        private void Download_OnClick(object sender, RoutedEventArgs e)
        {
            var year     = SelectedYear;
            var from     = From.Value ?? year.Days.First();
            var to       = (To.Value ?? year.Days.Last()).EndOfDay();
            var trader   = SelectedTrader;
            var security = SelectedSecurity;
            var tf       = SelectedTimeFrame;
            var series   = new CandleSeries(typeof(TimeFrameCandle), security, tf);

            BusyIndicator.BusyContent = "Подготовка данных...";
            BusyIndicator.IsBusy      = true;

            Dictionary <DateTimeOffset, Tuple <MyTrade[], MyTrade> > trades = null;

            var worker = new BackgroundWorker {
                WorkerReportsProgress = true
            };

            worker.DoWork += (o, ea) =>
            {
                var candleStorage = _dataRegistry.GetCandleStorage(series, format: StorageFormats.Csv);

                _candles = candleStorage.Load(from, to);

                var candlesDatesCache = _candlesDates.SafeAdd(Tuple.Create(security, tf), k => new DatesCache(Path.Combine(((LocalMarketDataDrive)candleStorage.Drive.Drive).GetSecurityPath(security.ToSecurityId()), "{0}min_date.bin".Put((int)tf.TotalMinutes))));

                var minCandleDate = candlesDatesCache.MinValue;
                var maxCandleDate = candlesDatesCache.MaxValue;

                if (from < minCandleDate || to > maxCandleDate)
                {
                    var finamFrom = from;
                    var finamTo   = to;

                    if (maxCandleDate != default(DateTime) && finamFrom >= minCandleDate && finamFrom <= maxCandleDate)
                    {
                        finamFrom = maxCandleDate + TimeSpan.FromDays(1);
                    }

                    if (minCandleDate != default(DateTime) && finamTo >= minCandleDate && finamTo <= maxCandleDate)
                    {
                        finamTo = minCandleDate - TimeSpan.FromDays(1);
                    }

                    if (finamTo > finamFrom)
                    {
                        worker.ReportProgress(1);

                        var newCandles = (tf.Ticks == 1
                                                        ? finamFrom.Range(finamTo, TimeSpan.FromDays(1)).SelectMany(day => _finamHistorySource.GetTrades(security, day, day)).ToEx().ToCandles <TimeFrameCandle>(tf)
                                                        : _finamHistorySource.GetCandles(security, tf, finamFrom, finamTo)
                                          ).ToArray();

                        candleStorage.Save(newCandles);

                        foreach (var date in newCandles.Select(c => c.OpenTime.Date).Distinct())
                        {
                            candlesDatesCache.Add(date);
                        }

                        candlesDatesCache.Save();

                        _candles = _candles.Concat(newCandles);
                    }
                }

                var traderDrive   = new LocalMarketDataDrive(trader);
                var traderStorage = _traderStorages.SafeAdd(trader, key => new StorageRegistry {
                    DefaultDrive = traderDrive
                });

                var olStorage       = traderStorage.GetOrderLogStorage(security, format: StorageFormats.Csv);
                var tradeDatesCache = _tradesDates.SafeAdd(trader, k => new DatesCache(Path.Combine(traderDrive.Path, "dates.bin")));

                trades = from
                         .Range(to, TimeSpan.FromDays(1))
                         .Intersect(year.Days)
                         .SelectMany(date =>
                {
                    if (olStorage.Dates.Contains(date))
                    {
                        return(olStorage.Load(date));
                    }

                    if (tradeDatesCache.Contains(date))
                    {
                        return(Enumerable.Empty <OrderLogItem>());
                    }

                    worker.ReportProgress(2, date);

                    var loadedTrades = year.GetTrades(_securityStorage, trader, date);

                    var secTrades = Enumerable.Empty <OrderLogItem>();

                    foreach (var group in loadedTrades.GroupBy(t => t.Order.Security))
                    {
                        var sec = group.Key;

                        traderStorage
                        .GetOrderLogStorage(sec, format: StorageFormats.Csv)
                        .Save(group.OrderBy(i => i.Order.Time));

                        if (group.Key == security)
                        {
                            secTrades = group;
                        }
                    }

                    tradeDatesCache.Add(date);
                    tradeDatesCache.Save();

                    return(secTrades);
                })
                         .GroupBy(ol =>
                {
                    var time = ol.Order.Time;

                    var period = security.Board.WorkingTime.GetPeriod(time.DateTime);
                    if (period != null && period.Times.Length > 0)
                    {
                        var last = period.Times.Last().Max;

                        if (time.TimeOfDay >= last)
                        {
                            time = time.AddTicks(-1);
                        }
                    }

                    return(time.Truncate(tf));
                })
                         .ToDictionary(g => g.Key, g =>
                {
                    var candleTrades = g
                                       .Select(order => new MyTrade
                    {
                        Order = order.Order,
                        Trade = order.Trade
                    })
                                       .ToArray();

                    if (candleTrades.Length > 0)
                    {
                        var order  = candleTrades[0].Order;
                        var volume = candleTrades.Sum(t1 => t1.Trade.Volume * (t1.Order.Direction == Sides.Buy ? 1 : -1));

                        if (volume == 0)
                        {
                            return(Tuple.Create(candleTrades, (MyTrade)null));
                        }

                        var side = volume > 0 ? Sides.Buy : Sides.Sell;

                        volume = volume.Abs();

                        var availableVolume = volume;
                        var avgPrice        = 0m;

                        foreach (var trade in candleTrades.Where(t1 => t1.Order.Direction == side))
                        {
                            var tradeVol = trade.Trade.Volume.Min(availableVolume);
                            avgPrice    += trade.Trade.Price * tradeVol;

                            availableVolume -= tradeVol;

                            if (availableVolume <= 0)
                            {
                                break;
                            }
                        }

                        avgPrice = avgPrice / volume;

                        return(Tuple.Create(candleTrades, new MyTrade
                        {
                            Order = new Order
                            {
                                Security = order.Security,
                                Direction = side,
                                Time = g.Key,
                                Portfolio = order.Portfolio,
                                Price = avgPrice,
                                Volume = volume,
                            },
                            Trade = new Trade
                            {
                                Security = order.Security,
                                Time = g.Key,
                                Volume = volume,
                                Price = avgPrice
                            }
                        }));
                    }

                    return(null);
                });
            };

            worker.ProgressChanged += (o, ea) =>
            {
                switch (ea.ProgressPercentage)
                {
                case 1:
                    BusyIndicator.BusyContent = "Скачивание свечей...";
                    break;

                default:
                    BusyIndicator.BusyContent = "Скачивание сделок за {0:yyyy-MM-dd}...".Put(ea.UserState);
                    break;
                }
            };

            worker.RunWorkerCompleted += (o, ea) =>
            {
                BusyIndicator.IsBusy = false;

                if (ea.Error == null)
                {
                    Chart.ClearAreas();
                    _statisticManager.Reset();

                    var area = new ChartArea();
                    area.YAxises.Add(new ChartAxis
                    {
                        Id            = "equity",
                        AutoRange     = true,
                        AxisType      = ChartAxisType.Numeric,
                        AxisAlignment = ChartAxisAlignment.Left,
                    });
                    Chart.AddArea(area);

                    var candlesElem = new ChartCandleElement {
                        ShowAxisMarker = false
                    };
                    Chart.AddElement(area, candlesElem, series);

                    var tradesElem = new ChartTradeElement
                    {
                        BuyStrokeColor  = Colors.Black,
                        SellStrokeColor = Colors.Black,
                        FullTitle       = "trades",
                    };
                    Chart.AddElement(area, tradesElem);

                    var equityElem = new ChartIndicatorElement {
                        YAxisId = "equity", FullTitle = "equity", IndicatorPainter = new PnlPainter()
                    };
                    var equityInd = new SimpleMovingAverage {
                        Length = 1
                    };
                    Chart.AddElement(area, equityElem);

                    var positionArea = new ChartArea {
                        Height = 200
                    };
                    Chart.AddArea(positionArea);

                    var positionElem = new ChartIndicatorElement {
                        FullTitle = "position"
                    };
                    var positionInd = new SimpleMovingAverage {
                        Length = 1
                    };
                    Chart.AddElement(positionArea, positionElem);

                    Chart.IsAutoRange = true;

                    var pnlQueue = new PnLQueue(security.ToSecurityId());
                    //var level1Info = new Level1ChangeMessage
                    //{
                    //	SecurityId = pnlQueue.SecurityId,
                    //}
                    //.TryAdd(Level1Fields.PriceStep, security.PriceStep)
                    //.TryAdd(Level1Fields.StepPrice, security.StepPrice);

                    //pnlQueue.ProcessLevel1(level1Info);

                    var pos = 0m;

                    var chartValues = _candles
                                      .Select(c =>
                    {
                        c.State = CandleStates.Finished;

                        pnlQueue.ProcessLevel1(new Level1ChangeMessage
                        {
                            SecurityId = security.ToSecurityId(),
                        }.TryAdd(Level1Fields.LastTradePrice, c.ClosePrice));

                        var values = new Dictionary <IChartElement, object>
                        {
                            { candlesElem, c },
                        };

                        var candleTrade = trades.TryGetValue(c.OpenTime);

                        if (candleTrade != null)
                        {
                            if (candleTrade.Item2 != null)
                            {
                                values.Add(tradesElem, candleTrade.Item2);
                            }

                            foreach (var myTrade in candleTrade.Item1)
                            {
                                pos    += myTrade.Order.Direction == Sides.Buy ? myTrade.Trade.Volume : -myTrade.Trade.Volume;
                                var pnl = pnlQueue.Process(myTrade.ToMessage());

                                _statisticManager.AddMyTrade(pnl);
                            }

                            _statisticManager.AddPosition(c.OpenTime, pos);
                            _statisticManager.AddPnL(c.OpenTime, pnlQueue.RealizedPnL + pnlQueue.UnrealizedPnL);
                        }

                        values.Add(equityElem, equityInd.Process(pnlQueue.RealizedPnL + pnlQueue.UnrealizedPnL));
                        values.Add(positionElem, positionInd.Process(pos));

                        return(new RefPair <DateTimeOffset, IDictionary <IChartElement, object> >
                        {
                            First = c.OpenTime,
                            Second = values
                        });
                    })
                                      .ToArray();

                    Chart.Draw(chartValues);

                    Chart.IsAutoRange = false;
                }
                else
                {
                    new MessageBoxBuilder()
                    .Error()
                    .Owner(this)
                    .Text(ea.Error.ToString())
                    .Show();
                }
            };

            worker.RunWorkerAsync();
        }
Example #49
0
        private void StartBtnClick(object sender, RoutedEventArgs e)
        {
            if (_connectors.Count > 0)
            {
                foreach (var connector in _connectors)
                {
                    connector.Start();
                }

                return;
            }

            if (HistoryPath.Folder.IsEmpty() || !Directory.Exists(HistoryPath.Folder))
            {
                MessageBox.Show(this, LocalizedStrings.Str3014);
                return;
            }

            if (_connectors.Any(t => t.State != EmulationStates.Stopped))
            {
                MessageBox.Show(this, LocalizedStrings.Str3015);
                return;
            }

            var id = SecId.Text.ToSecurityId();

            //if (secIdParts.Length != 2)
            //{
            //	MessageBox.Show(this, LocalizedStrings.Str3016);
            //	return;
            //}

            var timeFrame = TimeSpan.FromMinutes(TimeFrame.SelectedIndex == 0 ? 1 : 5);

            var secCode = id.SecurityCode;
            var board   = _exchangeInfoProvider.GetOrCreateBoard(id.BoardCode);

            // create test security
            var security = new Security
            {
                Id    = SecId.Text,              // sec id has the same name as folder with historical data
                Code  = secCode,
                Board = board,
            };

            if (FinamCandlesCheckBox.IsChecked == true)
            {
                _finamHistorySource.Refresh(new FinamSecurityStorage(security), security, s => {}, () => false);
            }

            // create backtesting modes
            var settings = new[]
            {
                Tuple.Create(
                    TicksCheckBox,
                    TicksProgress,
                    TicksParameterGrid,
                    // ticks
                    new EmulationInfo {
                    UseTicks = true, CurveColor = Colors.DarkGreen, StrategyName = LocalizedStrings.Ticks
                },
                    TicksChart,
                    TicksEquity,
                    TicksPosition),

                Tuple.Create(
                    TicksAndDepthsCheckBox,
                    TicksAndDepthsProgress,
                    TicksAndDepthsParameterGrid,
                    // ticks + order book
                    new EmulationInfo {
                    UseTicks = true, UseMarketDepth = true, CurveColor = Colors.Red, StrategyName = LocalizedStrings.XamlStr757
                },
                    TicksAndDepthsChart,
                    TicksAndDepthsEquity,
                    TicksAndDepthsPosition),

                Tuple.Create(
                    DepthsCheckBox,
                    DepthsProgress,
                    DepthsParameterGrid,
                    // order book
                    new EmulationInfo {
                    UseMarketDepth = true, CurveColor = Colors.OrangeRed, StrategyName = LocalizedStrings.MarketDepths
                },
                    DepthsChart,
                    DepthsEquity,
                    DepthsPosition),

                Tuple.Create(
                    CandlesCheckBox,
                    CandlesProgress,
                    CandlesParameterGrid,
                    // candles
                    new EmulationInfo {
                    UseCandleTimeFrame = timeFrame, CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.Candles
                },
                    CandlesChart,
                    CandlesEquity,
                    CandlesPosition),

                Tuple.Create(
                    CandlesAndDepthsCheckBox,
                    CandlesAndDepthsProgress,
                    CandlesAndDepthsParameterGrid,
                    // candles + orderbook
                    new EmulationInfo {
                    UseMarketDepth = true, UseCandleTimeFrame = timeFrame, CurveColor = Colors.Cyan, StrategyName = LocalizedStrings.XamlStr635
                },
                    CandlesAndDepthsChart,
                    CandlesAndDepthsEquity,
                    CandlesAndDepthsPosition),

                Tuple.Create(
                    OrderLogCheckBox,
                    OrderLogProgress,
                    OrderLogParameterGrid,
                    // order log
                    new EmulationInfo {
                    UseOrderLog = true, CurveColor = Colors.CornflowerBlue, StrategyName = LocalizedStrings.OrderLog
                },
                    OrderLogChart,
                    OrderLogEquity,
                    OrderLogPosition),

                Tuple.Create(
                    Level1CheckBox,
                    Level1Progress,
                    Level1ParameterGrid,
                    // order log
                    new EmulationInfo {
                    UseLevel1 = true, CurveColor = Colors.Aquamarine, StrategyName = LocalizedStrings.Level1
                },
                    Level1Chart,
                    Level1Equity,
                    Level1Position),

                Tuple.Create(
                    FinamCandlesCheckBox,
                    FinamCandlesProgress,
                    FinamCandlesParameterGrid,
                    // candles
                    new EmulationInfo {
                    UseCandleTimeFrame = timeFrame, HistorySource = d => _finamHistorySource.GetCandles(security, timeFrame, d.Date, d.Date), CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.FinamCandles
                },
                    FinamCandlesChart,
                    FinamCandlesEquity,
                    FinamCandlesPosition),

                Tuple.Create(
                    YahooCandlesCheckBox,
                    YahooCandlesProgress,
                    YahooCandlesParameterGrid,
                    // candles
                    new EmulationInfo {
                    UseCandleTimeFrame = timeFrame, HistorySource = d => new YahooHistorySource(_exchangeInfoProvider).GetCandles(security, timeFrame, d.Date, d.Date), CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.YahooCandles
                },
                    YahooCandlesChart,
                    YahooCandlesEquity,
                    YahooCandlesPosition),
            };

            // storage to historical data
            var storageRegistry = new StorageRegistry
            {
                // set historical path
                DefaultDrive = new LocalMarketDataDrive(HistoryPath.Folder)
            };

            var startTime = ((DateTime)From.Value).ChangeKind(DateTimeKind.Utc);
            var stopTime  = ((DateTime)To.Value).ChangeKind(DateTimeKind.Utc);

            // (ru only) ОЛ необходимо загружать с 18.45 пред дня, чтобы стаканы строились правильно
            if (OrderLogCheckBox.IsChecked == true)
            {
                startTime = startTime.Subtract(TimeSpan.FromDays(1)).AddHours(18).AddMinutes(45).AddTicks(1).ApplyTimeZone(TimeHelper.Moscow).UtcDateTime;
            }

            // ProgressBar refresh step
            var progressStep = ((stopTime - startTime).Ticks / 100).To <TimeSpan>();

            // set ProgressBar bounds
            _progressBars.ForEach(p =>
            {
                p.Value   = 0;
                p.Maximum = 100;
            });

            var logManager      = new LogManager();
            var fileLogListener = new FileLogListener("sample.log");

            logManager.Listeners.Add(fileLogListener);
            //logManager.Listeners.Add(new DebugLogListener());	// for track logs in output window in Vusial Studio (poor performance).

            var generateDepths = GenDepthsCheckBox.IsChecked == true;
            var maxDepth       = MaxDepth.Text.To <int>();
            var maxVolume      = MaxVolume.Text.To <int>();
            var secId          = security.ToSecurityId();

            SetIsEnabled(false, false, false);

            foreach (var set in settings)
            {
                if (set.Item1.IsChecked == false)
                {
                    continue;
                }

                var title = (string)set.Item1.Content;

                InitChart(set.Item5, set.Item6, set.Item7);

                var progressBar   = set.Item2;
                var statistic     = set.Item3;
                var emulationInfo = set.Item4;

                var level1Info = new Level1ChangeMessage
                {
                    SecurityId = secId,
                    ServerTime = startTime,
                }
                .TryAdd(Level1Fields.PriceStep, secCode == "RIZ2" ? 10m : 1)
                .TryAdd(Level1Fields.StepPrice, 6m)
                .TryAdd(Level1Fields.MinPrice, 10m)
                .TryAdd(Level1Fields.MaxPrice, 1000000m)
                .TryAdd(Level1Fields.MarginBuy, 10000m)
                .TryAdd(Level1Fields.MarginSell, 10000m);

                // test portfolio
                var portfolio = new Portfolio
                {
                    Name       = "test account",
                    BeginValue = 1000000,
                };

                // create backtesting connector
                var connector = new HistoryEmulationConnector(
                    new[] { security },
                    new[] { portfolio })
                {
                    EmulationAdapter =
                    {
                        Emulator             =
                        {
                            Settings         =
                            {
                                // match order if historical price touched our limit order price.
                                // It is terned off, and price should go through limit order price level
                                // (more "severe" test mode)
                                MatchOnTouch = false,
                            }
                        }
                    },

                    //UseExternalCandleSource = emulationInfo.UseCandleTimeFrame != null,

                    CreateDepthFromOrdersLog  = emulationInfo.UseOrderLog,
                    CreateTradesFromOrdersLog = emulationInfo.UseOrderLog,

                    HistoryMessageAdapter =
                    {
                        StorageRegistry             = storageRegistry,

                        // set history range
                        StartDate = startTime,
                        StopDate  = stopTime,

                        OrderLogMarketDepthBuilders =
                        {
                            {
                                secId,
                                LocalizedStrings.ActiveLanguage == Languages.Russian
                                                                        ? (IOrderLogMarketDepthBuilder) new PlazaOrderLogMarketDepthBuilder(secId)
                                                                        : new ItchOrderLogMarketDepthBuilder(secId)
                            }
                        }
                    },

                    // set market time freq as time frame
                    MarketTimeChangedInterval = timeFrame,
                };

                ((ILogSource)connector).LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info;

                logManager.Sources.Add(connector);

                var candleManager = new CandleManager(connector);

                var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame)
                {
                    BuildCandlesMode = emulationInfo.UseCandleTimeFrame == null ? BuildCandlesModes.Build : BuildCandlesModes.Load
                };

                _shortMa = new SimpleMovingAverage {
                    Length = 10
                };
                _shortElem = new ChartIndicatorElement
                {
                    Color          = Colors.Coral,
                    ShowAxisMarker = false,
                    FullTitle      = _shortMa.ToString()
                };

                var chart = set.Item5;

                chart.AddElement(_area, _shortElem);

                _longMa = new SimpleMovingAverage {
                    Length = 80
                };
                _longElem = new ChartIndicatorElement
                {
                    ShowAxisMarker = false,
                    FullTitle      = _longMa.ToString()
                };
                chart.AddElement(_area, _longElem);

                // create strategy based on 80 5-min и 10 5-min
                var strategy = new SmaStrategy(chart, _candlesElem, _tradesElem, _shortMa, _shortElem, _longMa, _longElem, candleManager, series)
                {
                    Volume    = 1,
                    Portfolio = portfolio,
                    Security  = security,
                    Connector = connector,
                    LogLevel  = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info,

                    // by default interval is 1 min,
                    // it is excessively for time range with several months
                    UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To <TimeSpan>()
                };

                logManager.Sources.Add(strategy);

                connector.NewSecurity += s =>
                {
                    if (s != security)
                    {
                        return;
                    }

                    // fill level1 values
                    connector.HistoryMessageAdapter.SendOutMessage(level1Info);

                    if (emulationInfo.HistorySource != null)
                    {
                        if (emulationInfo.UseCandleTimeFrame != null)
                        {
                            connector.RegisterHistorySource(security, MarketDataTypes.CandleTimeFrame, emulationInfo.UseCandleTimeFrame.Value, emulationInfo.HistorySource);
                        }

                        if (emulationInfo.UseTicks)
                        {
                            connector.RegisterHistorySource(security, MarketDataTypes.Trades, null, emulationInfo.HistorySource);
                        }

                        if (emulationInfo.UseLevel1)
                        {
                            connector.RegisterHistorySource(security, MarketDataTypes.Level1, null, emulationInfo.HistorySource);
                        }

                        if (emulationInfo.UseMarketDepth)
                        {
                            connector.RegisterHistorySource(security, MarketDataTypes.MarketDepth, null, emulationInfo.HistorySource);
                        }
                    }
                    else
                    {
                        if (emulationInfo.UseMarketDepth)
                        {
                            connector.RegisterMarketDepth(security);

                            if (
                                // if order book will be generated
                                generateDepths ||
                                // of backtesting will be on candles
                                emulationInfo.UseCandleTimeFrame != TimeSpan.Zero
                                )
                            {
                                // if no have order book historical data, but strategy is required,
                                // use generator based on last prices
                                connector.RegisterMarketDepth(new TrendMarketDepthGenerator(connector.GetSecurityId(security))
                                {
                                    Interval           = TimeSpan.FromSeconds(1),                           // order book freq refresh is 1 sec
                                    MaxAsksDepth       = maxDepth,
                                    MaxBidsDepth       = maxDepth,
                                    UseTradeVolume     = true,
                                    MaxVolume          = maxVolume,
                                    MinSpreadStepCount = 2,                                     // min spread generation is 2 pips
                                    MaxSpreadStepCount = 5,                                     // max spread generation size (prevent extremely size)
                                    MaxPriceStepCount  = 3                                      // pips size,
                                });
                            }
                        }

                        if (emulationInfo.UseOrderLog)
                        {
                            connector.RegisterOrderLog(security);
                        }

                        if (emulationInfo.UseTicks)
                        {
                            connector.RegisterTrades(security);
                        }

                        if (emulationInfo.UseLevel1)
                        {
                            connector.RegisterSecurity(security);
                        }
                    }

                    // start strategy before emulation started
                    strategy.Start();
                    candleManager.Start(series);

                    // start historical data loading when connection established successfully and all data subscribed
                    connector.Start();
                };

                // fill parameters panel
                statistic.Parameters.Clear();
                statistic.Parameters.AddRange(strategy.StatisticManager.Parameters);

                var equity = set.Item6;

                var pnlCurve           = equity.CreateCurve(LocalizedStrings.PnL + " " + emulationInfo.StrategyName, emulationInfo.CurveColor, LineChartStyles.Area);
                var unrealizedPnLCurve = equity.CreateCurve(LocalizedStrings.PnLUnreal + " " + emulationInfo.StrategyName, Colors.Black);
                var commissionCurve    = equity.CreateCurve(LocalizedStrings.Str159 + " " + emulationInfo.StrategyName, Colors.Red, LineChartStyles.DashedLine);
                var posItems           = set.Item7.CreateCurve(emulationInfo.StrategyName, emulationInfo.CurveColor);
                strategy.PnLChanged += () =>
                {
                    var pnl = new EquityData
                    {
                        Time  = strategy.CurrentTime,
                        Value = strategy.PnL - strategy.Commission ?? 0
                    };

                    var unrealizedPnL = new EquityData
                    {
                        Time  = strategy.CurrentTime,
                        Value = strategy.PnLManager.UnrealizedPnL ?? 0
                    };

                    var commission = new EquityData
                    {
                        Time  = strategy.CurrentTime,
                        Value = strategy.Commission ?? 0
                    };

                    pnlCurve.Add(pnl);
                    unrealizedPnLCurve.Add(unrealizedPnL);
                    commissionCurve.Add(commission);
                };

                strategy.PositionChanged += () => posItems.Add(new EquityData {
                    Time = strategy.CurrentTime, Value = strategy.Position
                });

                var nextTime = startTime + progressStep;

                // handle historical time for update ProgressBar
                connector.MarketTimeChanged += d =>
                {
                    if (connector.CurrentTime < nextTime && connector.CurrentTime < stopTime)
                    {
                        return;
                    }

                    var steps = (connector.CurrentTime - startTime).Ticks / progressStep.Ticks + 1;
                    nextTime = startTime + (steps * progressStep.Ticks).To <TimeSpan>();
                    this.GuiAsync(() => progressBar.Value = steps);
                };

                connector.StateChanged += () =>
                {
                    if (connector.State == EmulationStates.Stopped)
                    {
                        candleManager.Stop(series);
                        strategy.Stop();

                        SetIsChartEnabled(chart, false);

                        if (_connectors.All(c => c.State == EmulationStates.Stopped))
                        {
                            logManager.Dispose();
                            _connectors.Clear();

                            SetIsEnabled(true, false, false);
                        }

                        this.GuiAsync(() =>
                        {
                            if (connector.IsFinished)
                            {
                                progressBar.Value = progressBar.Maximum;
                                MessageBox.Show(this, LocalizedStrings.Str3024.Put(DateTime.Now - _startEmulationTime), title);
                            }
                            else
                            {
                                MessageBox.Show(this, LocalizedStrings.cancelled, title);
                            }
                        });
                    }
                    else if (connector.State == EmulationStates.Started)
                    {
                        if (_connectors.All(c => c.State == EmulationStates.Started))
                        {
                            SetIsEnabled(false, true, true);
                        }

                        SetIsChartEnabled(chart, true);
                    }
                    else if (connector.State == EmulationStates.Suspended)
                    {
                        if (_connectors.All(c => c.State == EmulationStates.Suspended))
                        {
                            SetIsEnabled(true, false, true);
                        }
                    }
                };

                if (ShowDepth.IsChecked == true)
                {
                    MarketDepth.UpdateFormat(security);

                    connector.NewMessage += message =>
                    {
                        var quoteMsg = message as QuoteChangeMessage;

                        if (quoteMsg != null)
                        {
                            MarketDepth.UpdateDepth(quoteMsg);
                        }
                    };
                }

                _connectors.Add(connector);

                progressBar.Value = 0;
            }

            _startEmulationTime = DateTime.Now;

            // start emulation
            foreach (var connector in _connectors)
            {
                // raise NewSecurities and NewPortfolio for full fill strategy properties
                connector.Connect();

                // 1 cent commission for trade
                connector.SendInMessage(new CommissionRuleMessage
                {
                    Rule = new CommissionPerTradeRule {
                        Value = 0.01m
                    }
                });
            }

            TabControl.Items.Cast <TabItem>().First(i => i.Visibility == Visibility.Visible).IsSelected = true;
        }
        private void StartBtnClick(object sender, RoutedEventArgs e)
        {
            InitChart();

            if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text))
            {
                MessageBox.Show(this, LocalizedStrings.Str3014);
                return;
            }

            var secGen     = new SecurityIdGenerator();
            var secIdParts = secGen.Split(SecId.Text);

            var storageRegistry = new StorageRegistry()
            {
                DefaultDrive = new LocalMarketDataDrive(HistoryPath.Text)
            };

            var startTime = ((DateTime)From.Value).ChangeKind(DateTimeKind.Utc);
            var stopTime  = ((DateTime)To.Value).ChangeKind(DateTimeKind.Utc);

            //var logManager = new LogManager();
            //var fileLogListener = new FileLogListener("sample.log");
            //logManager.Listeners.Add(fileLogListener);
            //logManager.Listeners.Add(new DebugLogListener());	// for track logs in output window in Vusial Studio (poor performance).

            var maxDepth  = 5;
            var maxVolume = 5;

            var secCode = secIdParts.Item1;
            var board   = ExchangeBoard.GetOrCreateBoard(secIdParts.Item2);

            var progressBar  = TicksTestingProcess;
            var progressStep = ((stopTime - startTime).Ticks / 100).To <TimeSpan>();

            progressBar.Value   = 0;
            progressBar.Maximum = 100;

            var statistic = TicksParameterGrid;
            var security  = new Security()
            {
                Id    = SecId.Text,
                Code  = secCode,
                Board = board,
            };

            var portfolio = new Portfolio()
            {
                Name       = "test account",
                BeginValue = 1000000,
            };

            var connector = new HistoryEmulationConnector(new[] { security }, new[] { portfolio })
            {
                EmulationAdapter =
                {
                    Emulator     =
                    {
                        Settings = { MatchOnTouch = true, PortfolioRecalcInterval = TimeSpan.FromMilliseconds(100), SpreadSize = 1, },
                        LogLevel = LogLevels.Debug,
                    },
                    LogLevel     = LogLevels.Debug,
                },
                HistoryMessageAdapter = { StorageRegistry = storageRegistry, StartDate = startTime, StopDate = stopTime, MarketTimeChangedInterval = TimeSpan.FromMilliseconds(50), },
            };

            //logManager.Sources.Add(connector);

            var candleManager = new CandleManager(connector);
            var series        = new CandleSeries(typeof(RangeCandle), security, new Unit(100));

            shortMa = new SimpleMovingAverage {
                Length = 10
            };
            shortElem = new ChartIndicatorElement
            {
                Color          = Colors.Coral,
                ShowAxisMarker = false,
                FullTitle      = shortMa.ToString()
            };
            bufferedChart.AddElement(area, shortElem);

            longMa = new SimpleMovingAverage {
                Length = 30
            };
            longElem = new ChartIndicatorElement
            {
                ShowAxisMarker = false,
                FullTitle      = longMa.ToString()
            };

            bufferedChart.AddElement(area, longElem);

            var strategy = new SmaStrategy(bufferedChart, candlesElem, tradesElem, shortMa, shortElem, longMa, longElem, series)
            {
                Volume                = 1,
                Portfolio             = portfolio,
                Security              = security,
                Connector             = connector,
                LogLevel              = LogLevels.Debug,
                UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To <TimeSpan>()
            };

            //logManager.Sources.Add(strategy);

            connector.NewSecurities += securities =>
            {
                if (securities.All(s => s != security))
                {
                    return;
                }

                connector.RegisterMarketDepth(security);
                connector.RegisterMarketDepth(new TrendMarketDepthGenerator(connector.GetSecurityId(security))
                {
                    Interval           = TimeSpan.FromMilliseconds(100),       // order book freq refresh is 1 sec
                    MaxAsksDepth       = maxDepth,
                    MaxBidsDepth       = maxDepth,
                    UseTradeVolume     = true,
                    MaxVolume          = maxVolume,
                    MinSpreadStepCount = 1,     // min spread generation is 2 pips
                    MaxSpreadStepCount = 1,     // max spread generation size (prevent extremely size)
                    MaxPriceStepCount  = 3      // pips size,
                });

                connector.RegisterTrades(security);
                connector.RegisterSecurity(security);

                strategy.Start();
                candleManager.Start(series);

                connector.Start();
            };

            statistic.Parameters.Clear();
            statistic.Parameters.AddRange(strategy.StatisticManager.Parameters);

            var pnlCurve           = Curve.CreateCurve(LocalizedStrings.PnL + " " + StrategyName, Colors.Cyan, EquityCurveChartStyles.Area);
            var unrealizedPnLCurve = Curve.CreateCurve(LocalizedStrings.PnLUnreal + StrategyName, Colors.Black);
            var commissionCurve    = Curve.CreateCurve(LocalizedStrings.Str159 + " " + StrategyName, Colors.Red, EquityCurveChartStyles.DashedLine);
            var posItems           = PositionCurve.CreateCurve(StrategyName, Colors.Crimson);

            strategy.PnLChanged += () =>
            {
                var pnl = new EquityData()
                {
                    Time = strategy.CurrentTime, Value = strategy.PnL - strategy.Commission ?? 0
                };
                var unrealizedPnL = new EquityData()
                {
                    Time = strategy.CurrentTime, Value = strategy.PnLManager.UnrealizedPnL
                };
                var commission = new EquityData()
                {
                    Time = strategy.CurrentTime, Value = strategy.Commission ?? 0
                };

                pnlCurve.Add(pnl);
                unrealizedPnLCurve.Add(unrealizedPnL);
                commissionCurve.Add(commission);
            };

            strategy.PositionChanged += () => posItems.Add(new EquityData {
                Time = strategy.CurrentTime, Value = strategy.Position
            });

            var nextTime = startTime + progressStep;

            connector.MarketTimeChanged += d =>
            {
                if (connector.CurrentTime < nextTime && connector.CurrentTime < stopTime)
                {
                    return;
                }

                var steps = (connector.CurrentTime - startTime).Ticks / progressStep.Ticks + 1;
                nextTime = startTime + (steps * progressStep.Ticks).To <TimeSpan>();
                this.GuiAsync(() => progressBar.Value = steps);
            };

            connector.StateChanged += () =>
            {
                if (connector.State == EmulationStates.Stopped)
                {
                    candleManager.Stop(series);
                    strategy.Stop();

                    //logManager.Dispose();

                    SetIsEnabled(false);

                    this.GuiAsync(() =>
                    {
                        if (connector.IsFinished)
                        {
                            progressBar.Value = progressBar.Maximum;
                            MessageBox.Show(this, LocalizedStrings.Str3024.Put(DateTime.Now - startEmulationTime));
                        }
                        else
                        {
                            MessageBox.Show(this, LocalizedStrings.cancelled);
                        }
                    });
                }
                else if (connector.State == EmulationStates.Started)
                {
                    SetIsEnabled(true);
                }
            };

            progressBar.Value  = 0;
            startEmulationTime = DateTime.Now;

            connector.Connect();
            connector.SendInMessage(new CommissionRuleMessage()
            {
                Rule = new CommissionPerTradeRule {
                    Value = 0.01m
                }
            });
        }
Example #51
0
        private void InitChart(EMAEventModelStrategy strategy)
        {
            _longMA = new ExponentialMovingAverage { Length = strategy.LongMA.Length};
            _shortMA = new ExponentialMovingAverage { Length = strategy.ShortMA.Length };
            _filterMA = new ExponentialMovingAverage { Length = strategy.FilterMA.Length };

            _area.Elements.Clear();

            _candlesElem = new ChartCandleElement()
            {
                DownBodyColor = Color.FromRgb(133, 133, 133),
                UpBodyColor = Color.FromRgb(255, 255, 255)
            };
            _area.Elements.Add(_candlesElem);

            _longMaElem = new ChartIndicatorElement
            {
                Title = "LongMA",
                Indicator = _longMA,
                Color = Color.FromRgb(120, 199, 130)
            };
            _area.Elements.Add(_longMaElem);

            _shortMaElem = new ChartIndicatorElement
            {
                Title = "ShortMA",
                Indicator = _shortMA,
                Color = Color.FromRgb(193, 53, 45)
            };
            _area.Elements.Add(_shortMaElem);

            _filterMaElem = new ChartIndicatorElement
            {
                Title = "FilterMA",
                Indicator = _filterMA,
                Color = Color.FromRgb(0, 124, 207)
            };
            _area.Elements.Add(_filterMaElem);

            _tradeElem = new ChartTradeElement()
            {
                BuyColor = Color.FromRgb(255, 0, 0),
                SellColor = Color.FromRgb(0, 0, 255),
                IsLegend = true
            };
            _area.Elements.Add(_tradeElem);
        }