Esempio n. 1
0
        public EmulationService(StrategyContainer strategy)
        {
            if (strategy == null)
            {
                throw new ArgumentNullException(nameof(strategy));
            }

            Strategy   = strategy;
            Strategies = new[] { strategy }.ToEx(1);

            var storageRegistry = new StudioStorageRegistry {
                MarketDataSettings = Strategy.MarketDataSettings
            };

            _basketEmulation = new BatchEmulation(new StudioSecurityProvider(), new Portfolio[0], storageRegistry);

            _basketEmulation.StateChanged    += BasketEmulationOnStateChanged;
            _basketEmulation.ProgressChanged += (curr, total) =>
            {
                Progress = total;

                _basketEmulation
                .BatchStrategies
                .OfType <StrategyContainer>()
                .ForEach(s => ProgressChanged.SafeInvoke((StrategyContainer)s.Strategy, curr));
            };

            ConfigManager.GetService <LogManager>().Sources.Add(EmulationConnector);

            EmulationConnector.HistoryMessageAdapter.StorageRegistry = storageRegistry;

            CanStart = true;
        }
Esempio n. 2
0
        private void StartBtnClick(object sender, RoutedEventArgs e)
        {
            if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text))
            {
                MessageBox.Show(this, LocalizedStrings.Str3014);
                return;
            }

            if (Math.Abs(TestingProcess.Value - 0) > double.Epsilon)
            {
                MessageBox.Show(this, LocalizedStrings.Str3015);
                return;
            }

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

            logManager.Listeners.Add(fileLogListener);

            // SMA periods
            var periods = new[]
            {
                new Tuple <int, int, Color>(80, 10, Colors.DarkGreen),
                new Tuple <int, int, Color>(70, 8, Colors.Red),
                new Tuple <int, int, Color>(60, 6, Colors.DarkBlue)
            };

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

            var timeFrame = TimeSpan.FromMinutes(5);

            // create test security
            var security = new Security
            {
                Id    = "RIZ2@FORTS",              // sec id has the same name as folder with historical data
                Code  = "RIZ2",
                Name  = "RTS-12.12",
                Board = ExchangeBoard.Forts,
            };

            var startTime = new DateTime(2012, 10, 1);
            var stopTime  = new DateTime(2012, 10, 31);

            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 batchEmulation = new BatchEmulation(new[] { security }, new[] { portfolio }, storageRegistry)
            {
                EmulationSettings =
                {
                    MarketTimeChangedInterval = timeFrame,
                    StartTime = startTime,
                    StopTime  = stopTime,

                    // count of parallel testing strategies
                    BatchSize                 = periods.Length,
                }
            };

            // handle historical time for update ProgressBar
            batchEmulation.ProgressChanged += (curr, total) => this.GuiAsync(() => TestingProcess.Value = total);

            batchEmulation.StateChanged += (oldState, newState) =>
            {
                if (batchEmulation.State != EmulationStates.Stopped)
                {
                    return;
                }

                this.GuiAsync(() =>
                {
                    if (batchEmulation.IsFinished)
                    {
                        TestingProcess.Value = TestingProcess.Maximum;
                        MessageBox.Show(this, LocalizedStrings.Str3024.Put(DateTime.Now - _startEmulationTime));
                    }
                    else
                    {
                        MessageBox.Show(this, LocalizedStrings.cancelled);
                    }
                });
            };

            // get emulation connector
            var connector = batchEmulation.EmulationConnector;

            logManager.Sources.Add(connector);

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

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

                connector.RegisterMarketDepth(new TrendMarketDepthGenerator(connector.GetSecurityId(security))
                {
                    // order book freq refresh is 1 sec
                    Interval = TimeSpan.FromSeconds(1),
                });
            };

            TestingProcess.Maximum = 100;
            TestingProcess.Value   = 0;

            _startEmulationTime = DateTime.Now;

            var strategies = periods
                             .Select(period =>
            {
                var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame);

                // create strategy based SMA
                var strategy = new SmaStrategy(series, new SimpleMovingAverage {
                    Length = period.Item1
                }, new SimpleMovingAverage {
                    Length = period.Item2
                })
                {
                    Volume    = 1,
                    Security  = security,
                    Portfolio = portfolio,
                    Connector = connector,

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

                strategy.SetCandleManager(new CandleManager(connector));

                var curveItems       = Curve.CreateCurve(LocalizedStrings.Str3026Params.Put(period.Item1, period.Item2), period.Item3);
                strategy.PnLChanged += () =>
                {
                    var data = new EquityData
                    {
                        Time  = strategy.CurrentTime,
                        Value = strategy.PnL,
                    };

                    this.GuiAsync(() => curveItems.Add(data));
                };

                Stat.AddStrategies(new[] { strategy });

                return(strategy);
            })
                             .ToEx(periods.Length);

            // start emulation
            batchEmulation.Start(strategies);
        }
        private void StartBtnClick(object sender, RoutedEventArgs e)
        {
            if (_batchEmulation != null)
            {
                _batchEmulation.Resume();
                return;
            }

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

            TestingProcess.Value = 0;
            Curve.Clear();
            Stat.Clear();

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

            logManager.Listeners.Add(fileLogListener);

            // SMA periods
            var periods = new List <(int longMa, int shortMa, Color color)>();

            for (var l = 100; l >= 50; l -= 10)
            {
                for (var s = 10; s >= 5; s -= 1)
                {
                    periods.Add((l, s, Color.FromRgb((byte)RandomGen.GetInt(255), (byte)RandomGen.GetInt(255), (byte)RandomGen.GetInt(255))));
                }
            }

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

            var timeFrame = TimeSpan.FromMinutes(1);

            // create test security
            var security = new Security
            {
                Id    = "SBER@TQBR",              // sec id has the same name as folder with historical data
                Code  = "SBER",
                Name  = "SBER",
                Board = ExchangeBoard.Micex,
            };

            var startTime = new DateTime(2020, 4, 1);
            var stopTime  = new DateTime(2020, 4, 20);

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

            // test portfolio
            var portfolio = Portfolio.CreateSimulator();

            // create backtesting connector
            _batchEmulation = new BatchEmulation(new[] { security }, new[] { portfolio }, storageRegistry)
            {
                EmulationSettings =
                {
                    MarketTimeChangedInterval = timeFrame,
                    StartTime = startTime,
                    StopTime  = stopTime,

                    // count of parallel testing strategies
                    // if not set, then CPU count * 2
                    //BatchSize = 3,
                }
            };

            // handle historical time for update ProgressBar
            _batchEmulation.TotalProgressChanged += (currBatch, total) => this.GuiAsync(() => TestingProcess.Value = total);

            _batchEmulation.StateChanged += (oldState, newState) =>
            {
                var isFinished = _batchEmulation.IsFinished;

                if (_batchEmulation.State == ChannelStates.Stopped)
                {
                    _batchEmulation = null;
                }

                this.GuiAsync(() =>
                {
                    switch (newState)
                    {
                    case ChannelStates.Stopping:
                    case ChannelStates.Starting:
                    case ChannelStates.Suspending:
                        SetIsEnabled(false, false, false);
                        break;

                    case ChannelStates.Stopped:
                        SetIsEnabled(true, false, false);

                        if (isFinished)
                        {
                            TestingProcess.Value = TestingProcess.Maximum;
                            MessageBox.Show(this, LocalizedStrings.Str3024.Put(DateTime.Now - _startEmulationTime));
                        }
                        else
                        {
                            MessageBox.Show(this, LocalizedStrings.cancelled);
                        }

                        break;

                    case ChannelStates.Started:
                        SetIsEnabled(false, true, true);
                        break;

                    case ChannelStates.Suspended:
                        SetIsEnabled(true, false, true);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(newState.ToString());
                    }
                });
            };

            _startEmulationTime = DateTime.Now;

            var strategies = periods
                             .Select(period =>
            {
                var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame);

                // create strategy based SMA
                var strategy = new SampleHistoryTesting.SmaStrategy(series)
                {
                    ShortSma = { Length = period.shortMa },
                    LongSma  = { Length = period.longMa },

                    Volume    = 1,
                    Security  = security,
                    Portfolio = portfolio,
                    //Connector = connector,

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

                this.GuiSync(() =>
                {
                    var curveElem = Curve.CreateCurve(LocalizedStrings.Str3026Params.Put(period.Item1, period.Item2), period.Item3, ChartIndicatorDrawStyles.Line);

                    strategy.PnLChanged += () =>
                    {
                        var data = new ChartDrawData();

                        data
                        .Group(strategy.CurrentTime)
                        .Add(curveElem, strategy.PnL);

                        Curve.Draw(data);
                    };

                    Stat.AddStrategies(new[] { strategy });
                });

                return(strategy);
            });

            // start emulation
            _batchEmulation.Start(strategies, periods.Count);
        }
Esempio n. 4
0
        private void StartBtnClick(object sender, RoutedEventArgs e)
        {
            if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text))
            {
                MessageBox.Show(this, LocalizedStrings.Str3014);
                return;
            }

            if (Math.Abs(TestingProcess.Value - 0) > double.Epsilon)
            {
                MessageBox.Show(this, LocalizedStrings.Str3015);
                return;
            }

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

            logManager.Listeners.Add(fileLogListener);

            // создаем длины скользящих средник
            var periods = new[]
            {
                new Tuple <int, int, Color>(80, 10, Colors.DarkGreen),
                new Tuple <int, int, Color>(70, 8, Colors.Red),
                new Tuple <int, int, Color>(60, 6, Colors.DarkBlue)
            };

            // хранилище, через которое будет производиться доступ к тиковой и котировочной базе
            var storageRegistry = new StorageRegistry
            {
                // изменяем путь, используемый по умолчанию
                DefaultDrive = new LocalMarketDataDrive(HistoryPath.Text)
            };

            var timeFrame = TimeSpan.FromMinutes(5);

            // создаем тестовый инструмент, на котором будет производится тестирование
            var security = new Security
            {
                Id    = "RIZ2@FORTS",              // по идентификатору инструмента будет искаться папка с историческими маркет данными
                Code  = "RIZ2",
                Name  = "RTS-12.12",
                Board = ExchangeBoard.Forts,
            };

            var startTime = new DateTime(2012, 10, 1);
            var stopTime  = new DateTime(2012, 10, 31);

            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);

            // тестовый портфель
            var portfolio = new Portfolio
            {
                Name       = "test account",
                BeginValue = 1000000,
            };

            // создаем подключение для эмуляции
            var batchEmulation = new BatchEmulation(new[] { security }, new[] { portfolio }, storageRegistry)
            {
                // инициализируем настройки (инструмент в истории обновляется раз в секунду)
                EmulationSettings =
                {
                    MarketTimeChangedInterval = timeFrame,
                    StartTime = startTime,
                    StopTime  = stopTime,

                    // кол-во одновременно тестируемых стратегий
                    BatchSize                 = periods.Length,
                }
            };

            // и подписываемся на событие изменения прогресса тестирования, чтобы обновить ProgressBar
            batchEmulation.ProgressChanged += (curr, total) => this.GuiAsync(() => TestingProcess.Value = total);

            batchEmulation.StateChanged += (oldState, newState) =>
            {
                if (batchEmulation.State != EmulationStates.Stopped)
                {
                    return;
                }

                this.GuiAsync(() =>
                {
                    if (batchEmulation.IsFinished)
                    {
                        TestingProcess.Value = TestingProcess.Maximum;
                        MessageBox.Show(LocalizedStrings.Str3024 + (DateTime.Now - _startEmulationTime));
                    }
                    else
                    {
                        MessageBox.Show(LocalizedStrings.cancelled);
                    }
                });
            };

            // получаем подключение для эмуляции
            var connector = batchEmulation.EmulationConnector;

            logManager.Sources.Add(connector);

            // подписываемся на получение данных после получения инструмента
            connector.NewSecurities += securities =>
            {
                if (securities.All(s => s != security))
                {
                    return;
                }

                // отправляем данные Level1 для инструмента
                connector.MarketDataAdapter.SendOutMessage(level1Info);

                connector.RegisterMarketDepth(new TrendMarketDepthGenerator(connector.GetSecurityId(security))
                {
                    // стакан для инструмента в истории обновляется раз в секунду
                    Interval = TimeSpan.FromSeconds(1),
                });
            };

            TestingProcess.Maximum = 100;
            TestingProcess.Value   = 0;

            _startEmulationTime = DateTime.Now;

            var strategies = periods
                             .Select(period =>
            {
                var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame);

                // создаем торговую стратегию
                var strategy = new SmaStrategy(series, new SimpleMovingAverage {
                    Length = period.Item1
                }, new SimpleMovingAverage {
                    Length = period.Item2
                })
                {
                    Volume    = 1,
                    Security  = security,
                    Portfolio = portfolio,
                    Connector = connector,

                    // по-умолчанию интервал равен 1 минут,
                    // что для истории в диапазон от нескольких месяцев излишне
                    UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To <TimeSpan>()
                };

                strategy.SetCandleManager(new CandleManager(connector));

                var curveItems       = Curve.CreateCurve(LocalizedStrings.Str3026Params.Put(period.Item1, period.Item2), period.Item3);
                strategy.PnLChanged += () =>
                {
                    var data = new EquityData
                    {
                        Time  = strategy.CurrentTime,
                        Value = strategy.PnL,
                    };

                    this.GuiAsync(() => curveItems.Add(data));
                };

                Stat.AddStrategies(new[] { strategy });

                return(strategy);
            })
                             .ToEx(periods.Length);

            // запускаем эмуляцию
            batchEmulation.Start(strategies);
        }