public KeyValuePair<OptVarItem, EMAEventModelStrategy> GetOptContext(OptVarItem optVarItem) { // clone doesn't work for some reason var security = new Security { Id = _security.Id, Code = _security.Code, Name = _security.Name, MinStepSize = _security.MinStepSize, MinStepPrice = _security.MinStepPrice, ExchangeBoard = _security.ExchangeBoard, MaxPrice = 99999, MinPrice = 1 }; // Create local Storage to make it disposable after optimization var storage = new StorageRegistry(); ((LocalMarketDataDrive) storage.DefaultDrive).Path = ((LocalMarketDataDrive) _storage.DefaultDrive).Path; ((LocalMarketDataDrive) storage.DefaultDrive).UseAlphabeticPath = true; var portfolio = new Portfolio { BeginValue = _portfolio.BeginValue }; EmulationTrader trader = new EmulationTrader( new[] { security }, new[] { portfolio }) { MarketTimeChangedInterval = optVarItem.TimeFrame, StorageRegistry = storage, UseMarketDepth = true, //UseCandlesTimeFrame = optVarItem.TimeFrame }; if (trader.UseMarketDepth) { trader.MarketEmulator.Settings.DepthExpirationTime = TimeSpan.FromMinutes(5); // Default: TimeSpan.FromDays(1); var marketDepthGenerator = new TrendMarketDepthGenerator(security) { // стакан для инструмента в истории обновляется раз в 10 секунд Interval = TimeSpan.FromSeconds(10), //MaxAsksDepth = 5, //MaxBidsDepth = 5 }; trader.RegisterMarketDepth(marketDepthGenerator); trader.StateChanged += (oldState, newState) => { if (trader.State == EmulationStates.Stopped) { trader.UnRegisterMarketDepth(marketDepthGenerator); marketDepthGenerator = null; } }; } // соединяемся с трейдером и запускаем экспорт, // чтобы инициализировать переданными инструментами и портфелями необходимые свойства EmulationTrader trader.Connect(); trader.StartExport(); var series = new CandleSeries(typeof(TimeFrameCandle), trader.Securities.First(), optVarItem.TimeFrame); var candleManager = new CandleManager(trader); candleManager.Start(series); var strategy = new EMAEventModelStrategy(series, new ExponentialMovingAverage { Length = optVarItem.FilterOptPeriod }, new ExponentialMovingAverage { Length = optVarItem.LongOptPeriods }, new ExponentialMovingAverage { Length = optVarItem.ShortOptPeriods }, optVarItem.TakeProfitUnit, optVarItem.StopLossUnit) { Volume = this.Volume, Portfolio = portfolio, Security = security, Trader = trader, UseQuoting = this.UseQuoting }; trader.StateChanged += (oldState, newState) => { if (trader.State == EmulationStates.Started) { strategy.Start(); } else if (trader.State == EmulationStates.Stopped) { strategy.Stop(); candleManager = null; storage = null; } }; var result = new KeyValuePair<OptVarItem, EMAEventModelStrategy>(optVarItem, strategy); return result; }
private void UpdateStrategyStat(EMAEventModelStrategy strategy) { this.Status.Content = strategy.ProcessState; this.TradesNumber.Content = strategy.Trader.MyTrades.Count(); this.PnL.Content = strategy.PnLManager.PnL; this.Slippage.Content = strategy.SlippageManager.Slippage; this.Position.Content = strategy.PositionManager.Position; this.Latency.Content = strategy.LatencyManager.LatencyRegistration; this._log.AddLog( new LogMessage(this._log, DateTime.Now, LogLevels.Info, "Stat Changed. State: {0}, PnL: {1} {2}, Slippage: {3}, Position: {4}, LatencyRegistration: {5}, LatencyCancellation: {6}", strategy.ProcessState, strategy.PnLManager.PnL, (strategy.PnLManager.PnL < 0) ? ":(" : ":)", strategy.SlippageManager.Slippage, strategy.PositionManager.Position, strategy.LatencyManager.LatencyRegistration, strategy.LatencyManager.LatencyCancellation)); }
private void OnHistoryStartClick(object sender, RoutedEventArgs e) { btnHistoryStart.IsEnabled = false; this.InitGrids(); // создаем тестовый инструмент, на котором будет производится тестирование var security = new Security { Id = this.txtSecurityId.Text, // по идентификатору инструмента будет искаться папка с историческими маркет данными Code = this.txtSecurityCode.Text, Name = this.txtSecurityCode.Text, MinPrice = 1, MaxPrice = 99999, MinStepSize = 1, MinStepPrice = 1, ExchangeBoard = ExchangeBoard.Forts, }; security.ExchangeBoard.IsSupportAtomicReRegister = false; // fixed quoting reregister error var storageRegistry = new StorageRegistry(); ((LocalMarketDataDrive) storageRegistry.DefaultDrive).Path = this.txtHistoryPath.Text; ((LocalMarketDataDrive) storageRegistry.DefaultDrive).UseAlphabeticPath = true; var portfolio = new Portfolio { Name = "test account", BeginValue = 30000m }; DateTime startTime; DateTime stopTime; if (!DateTime.TryParse(txtHistoryRangeEnd.Text, out stopTime)) { stopTime = DateTime.Now; txtHistoryRangeEnd.Text = stopTime.ToString(); } if (!DateTime.TryParse(txtHistoryRangeBegin.Text, out startTime)) { startTime = stopTime.AddDays(-3); txtHistoryRangeBegin.Text = startTime.ToString(); } EMAStrategyOptimizer optimizer = new EMAStrategyOptimizer(security, storageRegistry, portfolio, startTime, stopTime) { Volume = this.Volume, Log = _log }; var context = optimizer.GetOptContext(this.MainOptVarItem); _trader = context.Value.Trader; _strategy = context.Value; this.InitChart(_strategy); _strategy.Trader.NewOrders += orders => orders.ForEach(OnOrderRegistered); _strategy.Trader.NewMyTrades += OnNewTrades; _logManager.Sources.Add(_strategy); // устанавливаем в визуальный элемент ProgressBar максимальное количество итераций) this.pbHistoryTestProgress.Maximum = 10; this.pbHistoryTestProgress.Value = 0; var totalMinutes = (stopTime - startTime).TotalMinutes; var segment = Math.Floor(totalMinutes / 10); var nSegment = 1; var sSegment = segment; _trader.MarketTimeChanged += span => { var currentMinute = (_trader.CurrentTime - startTime).TotalMinutes; if (currentMinute >= sSegment || _trader.CurrentTime >= stopTime) { nSegment += 1; sSegment = segment * nSegment; this.GuiAsync(() => { this.pbHistoryTestProgress.Value = nSegment; this.UpdateStrategyStat(_strategy); }); } }; Stopwatch sw = new Stopwatch(); ((EmulationTrader)_trader).StateChanged += (states, emulationStates) => { if (((EmulationTrader)_trader).State == EmulationStates.Stopped) { sw.Stop(); this.GuiAsync(() => { this.UpdateStrategyStat(_strategy); _strategy.CandleSeries.GetCandles<TimeFrameCandle>().ForEach(DrawCandleAndEma); _strategy.Trader.MyTrades.ForEach(DrawTrade); this.pbHistoryTestProgress.Value = 0; btnHistoryStart.IsEnabled = true; }); // clean stupid dictionary //var value = _trader.GetType().GetField("#=qUTBJ0c9uFmGWYx4a3_oZjOoV9pJDtArCh9oL5k$U8DQ=", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(_trader); //value.GetType().GetMethod("Clear").Invoke(value, null); _log.AddLog(new LogMessage(_log, DateTime.Now, LogLevels.Info, String.Format("History testing done ({0}). Result: PnL: {1}, {2}", sw.Elapsed, _strategy.PnLManager.PnL, this.MainOptVarItem ))); } else if (((EmulationTrader)_trader).State == EmulationStates.Started) { sw.Start(); } }; // соединяемся с трейдером и запускаем экспорт, // чтобы инициализировать переданными инструментами и портфелями необходимые свойства EmulationTrader _trader.Connect(); _trader.StartExport(); // запускаем эмуляцию, задавая период тестирования (startTime, stopTime). ((EmulationTrader)_trader).Start(startTime, stopTime); }
private void OnStartClick(object sender, RoutedEventArgs e) { if (_strategy != null && _strategy.ProcessState != ProcessStates.Stopped) { _strategy.Stop(); return; } if (this.Portfolios.SelectedPortfolio == null) { this.Portfolios.SelectedIndex = this.Portfolios.Items.Count - 1; } this.InitGrids(); _candleManager = new CandleManager(_trader); // Добавление в источник свечек TimeFrameCandleBuilder источник данных в виде файлов гидры var storageRegistry = new StorageRegistry(); ((LocalMarketDataDrive) storageRegistry.DefaultDrive).Path = this.txtHistoryPath.Text; ((LocalMarketDataDrive) storageRegistry.DefaultDrive).UseAlphabeticPath = true; var cbs = new TradeStorageCandleBuilderSource { StorageRegistry = storageRegistry }; _candleManager.Sources.OfType<TimeFrameCandleBuilder>().Single().Sources.Add(cbs); // регистрируем наш тайм-фрейм var series = new CandleSeries(typeof(TimeFrameCandle), _security, this.MainOptVarItem.TimeFrame); _strategy = new EMAEventModelStrategy(series, new ExponentialMovingAverage { Length = this.MainOptVarItem.FilterOptPeriod}, new ExponentialMovingAverage { Length = this.MainOptVarItem.LongOptPeriods }, new ExponentialMovingAverage { Length = this.MainOptVarItem.ShortOptPeriods }, this.MainOptVarItem.TakeProfitUnit, this.MainOptVarItem.StopLossUnit) { Volume = this.Volume, Security = _security, Portfolio = this.Portfolios.SelectedPortfolio, Trader = _trader, UseQuoting = true //_trader is QuikTrader // hack to turn quoting off for RealTimeEmulationTrader }; DateTime startTime; if (!DateTime.TryParse(txtHistoryRangeBegin.Text, out startTime)) { startTime = DateTime.Now.AddDays(-3); txtHistoryRangeBegin.Text = startTime.ToString(); } this.InitChart(_strategy); _candleManager.Processing += (candleSeries, candle) => { if (candle.State == CandleStates.Finished) { this.GuiAsync(() => DrawCandleAndEma(candle)); } }; _candleManager.Start(series, startTime, DateTime.MaxValue); // Subscribe UI to all strategy actions _strategy.Trader.NewOrders += orders => orders.ForEach(OnOrderRegistered); _strategy.Trader.NewMyTrades += OnNewTrades; _strategy.Trader.NewMyTrades += trades => this.GuiAsync(() => trades.ForEach(DrawTrade)); _strategy.PropertyChanged += (o, args) => this.GuiAsync(() => OnStrategyPropertyChanged(o, args)); _strategy.ProcessStateChanged += strategy => { if (strategy.ProcessState == ProcessStates.Started) { this.Start.Content = "Stop"; } else if (strategy.ProcessState == ProcessStates.Stopped) { this.Start.Content = "Start"; } }; _logManager.Sources.Add(_strategy); // запускаем процесс получения стакана, необходимый для работы алгоритма котирования _strategy.Start(); this.Start.Content = "Stop"; }
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); }