Ejemplo n.º 1
0
        private void StartEmulation()
        {
            if (_connector != null && _connector.State != EmulationStates.Stopped)
            {
                throw new InvalidOperationException(LocalizedStrings.Str3015);
            }

            if (Strategy == null)
            {
                throw new InvalidOperationException("Strategy not selected.");
            }

            var strategy = (EmulationDiagramStrategy)Strategy;
            var settings = strategy.EmulationSettings;

            if (settings.MarketDataSettings == null)
            {
                throw new InvalidOperationException(LocalizedStrings.Str3014);
            }

            new SetDefaultEmulationSettingsCommand(settings).Process(this);

            strategy
            .Composition
            .Parameters
            .ForEach(p =>
            {
                if (p.Type == typeof(Security) && p.Value == null)
                {
                    throw new InvalidOperationException(LocalizedStrings.Str1380);
                }
            });

            strategy.Reset();
            Reset();

            var securityId = "empty@empty";
            var secGen     = new SecurityIdGenerator();
            var secIdParts = secGen.Split(securityId);
            var secCode    = secIdParts.SecurityCode;
            var board      = ExchangeBoard.GetOrCreateBoard(secIdParts.BoardCode);
            var timeFrame  = settings.CandlesTimeFrame;
            var useCandles = settings.MarketDataSource == MarketDataSource.Candles;

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

            // storage to historical data
            var storageRegistry = new StudioStorageRegistry
            {
                MarketDataSettings = settings.MarketDataSettings
            };

            var startTime = settings.StartDate.ChangeKind(DateTimeKind.Utc);
            var stopTime  = settings.StopDate.ChangeKind(DateTimeKind.Utc);

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

            // set ProgressBar bounds
            TicksAndDepthsProgress.Value   = 0;
            TicksAndDepthsProgress.Maximum = 100;

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

            var securityProvider = ConfigManager.GetService <ISecurityProvider>();

            // create backtesting connector
            _connector = new HistoryEmulationConnector(securityProvider, new[] { portfolio }, new StorageRegistry())
            {
                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              = settings.MatchOnTouch,
                            IsSupportAtomicReRegister = settings.IsSupportAtomicReRegister,
                            Latency                   = settings.EmulatoinLatency,
                        }
                    }
                },

                UseExternalCandleSource = useCandles,

                HistoryMessageAdapter =
                {
                    StorageRegistry = storageRegistry,
                    StorageFormat   = settings.StorageFormat,

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

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

            ((ILogSource)_connector).LogLevel = settings.DebugLog ? LogLevels.Debug : LogLevels.Info;

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

            strategy.Volume    = 1;
            strategy.Portfolio = portfolio;
            strategy.Security  = security;
            strategy.Connector = _connector;
            strategy.LogLevel  = settings.DebugLog ? LogLevels.Debug : LogLevels.Info;

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

            strategy.SetCandleManager(new CandleManager(_connector));

            _connector.NewSecurity += s =>
            {
                //TODO send real level1 message
                var level1Info = new Level1ChangeMessage
                {
                    SecurityId = s.ToSecurityId(),
                    ServerTime = startTime,
                }
                .TryAdd(Level1Fields.PriceStep, secIdParts.SecurityCode == "RIZ2" ? 10m : 1)
                .TryAdd(Level1Fields.StepPrice, 6m)
                .TryAdd(Level1Fields.MinPrice, 10m)
                .TryAdd(Level1Fields.MaxPrice, 1000000m)
                .TryAdd(Level1Fields.MarginBuy, 10000m)
                .TryAdd(Level1Fields.MarginSell, 10000m);

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

                if (settings.UseMarketDepths)
                {
                    _connector.RegisterMarketDepth(security);

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

            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(() => TicksAndDepthsProgress.Value = steps);
            };

            _connector.LookupSecuritiesResult += (ss) =>
            {
                if (strategy.ProcessState != ProcessStates.Stopped)
                {
                    return;
                }

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

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

            _connector.StateChanged += () =>
            {
                switch (_connector.State)
                {
                case EmulationStates.Stopped:
                    strategy.Stop();

                    this.GuiAsync(() =>
                    {
                        if (_connector.IsFinished)
                        {
                            TicksAndDepthsProgress.Value = TicksAndDepthsProgress.Maximum;
                        }
                    });
                    break;

                case EmulationStates.Started:
                    break;
                }
            };

            _connector.Disconnected += () =>
            {
                this.GuiAsync(() => _connector.Dispose());
            };

            TicksAndDepthsProgress.Value = 0;

            DiagramDebuggerControl.Debugger.IsEnabled = true;

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