namespace SampleHistoryTestingParallel { using System; using System.IO; using System.Linq; using System.Windows; using System.Windows.Forms; using System.Windows.Media; using MessageBox = System.Windows.MessageBox; using Ecng.Xaml; using Ecng.Common; using StockSharp.Algo; using StockSharp.Algo.Candles; using StockSharp.Algo.Storages; using StockSharp.Algo.Testing; using StockSharp.Algo.Strategies; using StockSharp.Algo.Indicators.Trend; using StockSharp.BusinessEntities; using StockSharp.Xaml.Charting; using Wintellect.PowerCollections; public partial class MainWindow { private DateTime _nextTime; private DateTime _startEmulationTime; public MainWindow() { InitializeComponent(); } private void FindPathClick(object sender, RoutedEventArgs e) { var dlg = new FolderBrowserDialog(); if (!HistoryPath.Text.IsEmpty()) dlg.SelectedPath = HistoryPath.Text; if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { HistoryPath.Text = dlg.SelectedPath; } } private void StartBtnClick(object sender, RoutedEventArgs e) { if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text)) { MessageBox.Show(this, "Неправильный путь."); return; } if (Math.Abs(TestingProcess.Value - 0) > double.Epsilon) { MessageBox.Show(this, "Уже запущен."); return; } // создаем длины скользящих средник var periods = new[] { new Triple(80, 10, Colors.DarkGreen), new Triple(70, 8, Colors.Red), new Triple(60, 6, Colors.DarkBlue) }; // хранилище, через которое будет производиться доступ к тиковой и котировочной базе var storageRegistry = new StorageRegistry(); // изменяем путь, используемый по умолчанию storageRegistry.DefaultDrive = new LocalMarketDataDrive(HistoryPath.Text); TimeSpan timeFrame = TimeSpan.FromSeconds(1); int tickFrame = 100; decimal volumeFrame = 100; var basketTrader = new BasketConnector { // не поддерживать контроль уникальности сделок // (уменьшает потребление памяти) SupportTradesUnique = false, }; var startTime = new DateTime(2012, 10, 1); var stopTime = new DateTime(2012, 10, 1); // задаем шаг ProgressBar var progressStep = ((stopTime - startTime).Ticks / 100).To(); _nextTime = startTime + progressStep; TestingProcess.Maximum = 100; TestingProcess.Value = 0; foreach (var period in periods) { // создаем тестовый инструмент, на котором будет производится тестирование var security = new Security { Id = "RIZ2@FORTS", // по идентификатору инструмента будет искаться папка с историческими маркет данными Code = "RIZ2", Name = "RTS-12.12", MinStepSize = 10, MinStepPrice = 2, ExchangeBoard = ExchangeBoard.Forts, }; // тестовый портфель var portfolio = new Portfolio { Name = "test account", BeginValue = 1000000, }; // создаем подключение для эмуляции // инициализируем настройки (инструмент в истории обновляется раз в секунду) var trader = new HistoryEmulationConnector( new[] { security }, new[] { portfolio }, storageRegistry) { StorageRegistry = storageRegistry, }; ((MessageAdapter)trader.MarketDataAdapter).MarketTimeChangedInterval = TimeSpan.FromMilliseconds(10); trader.NewSecurities += securities => { //подписываемся на получение данных после получения инструмента if (securities.All(s => s != security)) return; trader.RegisterMarketDepth(new TrendMarketDepthGenerator(trader.GetSecurityId(security)) { // стакан для инструмента в истории обновляется раз в секунду Interval = TimeSpan.FromSeconds(1), }); }; // соединяемся с трейдером и запускаем экспорт, // чтобы инициализировать переданными инструментами и портфелями необходимые свойства EmulationTrader trader.Connect(); trader.StartExport(); var candleManager = new CandleManager(trader); var series1 = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame); var series2 = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame); var series3 = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame); var series4 = new CandleSeries(typeof(TickCandle), security, tickFrame); var series5 = new CandleSeries(typeof(TickCandle), security, tickFrame); var series6 = new CandleSeries(typeof(TickCandle), security, tickFrame); var series7 = new CandleSeries(typeof(VolumeCandle), security, volumeFrame); var series8 = new CandleSeries(typeof(VolumeCandle), security, volumeFrame); var series9 = new CandleSeries(typeof(VolumeCandle), security, volumeFrame); // создаем торговую стратегию var strategy = new BasketStrategy(BasketStrategyFinishModes.All) { Volume = 1, Security = security, Portfolio = portfolio, Connector = trader, }; var strategy1 = new SmaStrategy(series1, new SimpleMovingAverage { Length = period.First }, new SimpleMovingAverage { Length = period.Second }); var strategy2 = new SmaStrategy(series2, new SimpleMovingAverage { Length = period.First }, new SimpleMovingAverage { Length = period.Second }); var strategy3 = new SmaStrategy(series3, new SimpleMovingAverage { Length = period.First }, new SimpleMovingAverage { Length = period.Second }); var strategy4 = new SmaStrategy(series4, new SimpleMovingAverage { Length = period.First }, new SimpleMovingAverage { Length = period.Second }); var strategy5 = new SmaStrategy(series5, new SimpleMovingAverage { Length = period.First }, new SimpleMovingAverage { Length = period.Second }); var strategy6 = new SmaStrategy(series6, new SimpleMovingAverage { Length = period.First }, new SimpleMovingAverage { Length = period.Second }); var strategy7 = new SmaStrategy(series7, new SimpleMovingAverage { Length = period.First }, new SimpleMovingAverage { Length = period.Second }); var strategy8 = new SmaStrategy(series8, new SimpleMovingAverage { Length = period.First }, new SimpleMovingAverage { Length = period.Second }); var strategy9 = new SmaStrategy(series9, new SimpleMovingAverage { Length = period.First }, new SimpleMovingAverage { Length = period.Second }); strategy.ChildStrategies.Add(strategy1); strategy.ChildStrategies.Add(strategy2); strategy.ChildStrategies.Add(strategy3); strategy.ChildStrategies.Add(strategy4); strategy.ChildStrategies.Add(strategy5); strategy.ChildStrategies.Add(strategy6); strategy.ChildStrategies.Add(strategy7); strategy.ChildStrategies.Add(strategy8); strategy.ChildStrategies.Add(strategy9); var curveItems = Curve.CreateCurve("Длинная {0} Короткая {1}".Put(period.First, period.Second), period.Third); strategy.PnLChanged += () => { var data = new EquityData { Time = strategy.GetMarketTime(), Value = strategy.PnL, }; this.GuiAsync(() => curveItems.Add(data)); }; // полосу прогресса будет обновлять только первый период if (periods.IndexOf(period) == 0) { // и подписываемся на событие изменения времени, чтобы обновить ProgressBar trader.MarketTimeChanged += d => { if (trader.CurrentTime >= _nextTime || trader.CurrentTime >= stopTime) { _nextTime += progressStep; this.GuiAsync(() => TestingProcess.Value++); } }; } trader.StateChanged += (oldState, newState) => { if (trader.State == EmulationStates.Stopped) { this.GuiAsync(() => { if (trader.IsFinished) { TestingProcess.Value = TestingProcess.Maximum; //MessageBox.Show("Закончено за " + (DateTime.Now - _startEmulationTime)); candleManager.Stop(series1); candleManager.Stop(series2); candleManager.Stop(series3); candleManager.Stop(series4); candleManager.Stop(series5); candleManager.Stop(series6); candleManager.Stop(series7); candleManager.Stop(series8); candleManager.Stop(series9); series1.Dispose(); series2.Dispose(); series3.Dispose(); series4.Dispose(); series5.Dispose(); series6.Dispose(); series7.Dispose(); series8.Dispose(); series9.Dispose(); candleManager.Dispose(); trader.Dispose(); } else MessageBox.Show("Отменено"); }); } else if (trader.State == EmulationStates.Started) { // запускаем стратегию когда эмулятор запустился strategy.Start(); candleManager.Start(series1); candleManager.Start(series2); candleManager.Start(series3); candleManager.Start(series4); candleManager.Start(series5); candleManager.Start(series6); candleManager.Start(series7); candleManager.Start(series8); candleManager.Start(series9); } }; basketTrader.InnerConnectors.Add(trader); } _startEmulationTime = DateTime.Now; // запускаем эмуляцию foreach (var trader in basketTrader.InnerConnectors.OfType()) { // указываем даты начала и конца тестирования trader.Start(startTime, stopTime); } } } }