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; }
private void SettingsChanged(MarketDataSettings settings) { if (settings == null) { SettingsPanel.IsEnabled = false; Grid.IsEnabled = false; return; } SettingsPanel.IsEnabled = true; Grid.IsEnabled = true; SettingsPanel.IsLocal = settings.UseLocal; //SettingsPanel.IsAlphabetic = settings.IsAlphabetic; if (settings.UseLocal) { SettingsPanel.Path = settings.Path; } else { SettingsPanel.Address = settings.Path; } SetCredentials(settings.IsStockSharpStorage, settings.Credentials); _storageRegistry = new StudioStorageRegistry { MarketDataSettings = settings }; RefreshGrid(); }
public StrategyConnector(StrategyContainer strategy, DateTimeOffset startDate, DateTimeOffset stopDate, TimeSpan useCandlesTimeFrame, bool onlyInitialize) { if (strategy == null) { throw new ArgumentNullException("strategy"); } UpdateSecurityLastQuotes = false; UpdateSecurityByLevel1 = false; var entityRegistry = ConfigManager.GetService <IStudioEntityRegistry>(); _strategy = strategy; _useCandlesTimeFrame = useCandlesTimeFrame; _onlyInitialize = onlyInitialize; _sessionStrategy = entityRegistry.ReadSessionStrategyById(strategy.Strategy.Id); if (_sessionStrategy == null) { throw new InvalidOperationException("sessionStrategy = null"); } Id = strategy.Id; Name = strategy.Name + " Connector"; _realConnector = (StudioConnector)ConfigManager.GetService <IStudioConnector>(); _realConnector.NewMessage += RealConnectorNewMessage; EntityFactory = new StudioConnectorEntityFactory(); _securityProvider = new StudioSecurityProvider(); var storageRegistry = new StudioStorageRegistry { MarketDataSettings = strategy.MarketDataSettings }; Adapter.InnerAdapters.Add(_historyMessageAdapter = new HistoryMessageAdapter(TransactionIdGenerator, _securityProvider) { StartDate = startDate, StopDate = stopDate, StorageRegistry = storageRegistry }); //_historyMessageAdapter.UpdateCurrentTime(startDate); var transactionAdapter = new PassThroughMessageAdapter(TransactionIdGenerator); transactionAdapter.AddTransactionalSupport(); Adapter.InnerAdapters.Add(transactionAdapter); _historyMessageAdapter.MarketTimeChangedInterval = useCandlesTimeFrame; // при инициализации по свечкам, время меняется быстрее и таймаут должен быть больше 30с. ReConnectionSettings.TimeOutInterval = TimeSpan.MaxValue; _historyMessageAdapter.BasketStorage.InnerStorages.AddRange(GetExecutionStorages()); this.LookupById(strategy.Security.Id); new ChartAutoRangeCommand(true).Process(_strategy); }
private void SettingsChanged(MarketDataSettings settings) { if (settings != null) { MarketDataGrid.IsEnabled = true; SecurityPicker.SelectedSecurity = null; _storageRegistry = new StudioStorageRegistry { MarketDataSettings = settings }; RefreshGrid(); } else { MarketDataGrid.IsEnabled = false; } }
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; if (strategy.MarketDataSettings == null) { throw new InvalidOperationException(LocalizedStrings.Str3014); } 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 = strategy.CandlesTimeFrame; var useCandles = strategy.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 = strategy.MarketDataSettings }; var startTime = strategy.StartDate.ChangeKind(DateTimeKind.Utc); var stopTime = strategy.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 = strategy.MatchOnTouch, IsSupportAtomicReRegister = strategy.IsSupportAtomicReRegister, Latency = strategy.EmulatoinLatency, } } }, UseExternalCandleSource = useCandles, HistoryMessageAdapter = { StorageRegistry = storageRegistry, StorageFormat = strategy.StorageFormat, // set history range StartDate = startTime, StopDate = stopTime, }, // set market time freq as time frame MarketTimeChangedInterval = timeFrame, }; ((ILogSource)_connector).LogLevel = strategy.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 = strategy.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 (strategy.UseMarketDepths) { _connector.RegisterMarketDepth(security); if ( // if order book will be generated strategy.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 = strategy.MaxDepths, MaxBidsDepth = strategy.MaxDepths, UseTradeVolume = true, MaxVolume = strategy.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; } }; 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 } }); }