Example #1
0
        private Security GetSecurity(AlorTable table, object[] values, AlorColumn codeColumn, AlorColumn boardColumn)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }

            if (values == null)
            {
                throw new ArgumentNullException(nameof(values));
            }

            if (codeColumn == null)
            {
                throw new ArgumentNullException(nameof(codeColumn));
            }

            if (boardColumn == null)
            {
                throw new ArgumentNullException(nameof(boardColumn));
            }

            var secCode  = table.GetValue <string>(values, codeColumn);
            var secBoard = ExchangeBoard.GetBoard(table.GetValue <string>(values, boardColumn));

            var id = SecurityIdGenerator.GenerateId(secCode, secBoard);

            return(GetSecurity(id, name =>
            {
                var security = EntityFactory.CreateSecurity(name);
                security.Board = secBoard;
                security.Code = secCode;
                return security;
            }, security => false));
        }
        public AllSecurityMarketDataStorage(Security security, object arg, Func <T, DateTimeOffset> getTime, Func <T, Security> getSecurity, Func <Security, IMarketDataDrive, IMarketDataStorage <T> > getStorage, IMarketDataStorageDrive drive)
        {
            if (security == null)
            {
                throw new ArgumentNullException("security");
            }

            if (getTime == null)
            {
                throw new ArgumentNullException("getTime");
            }

            if (getSecurity == null)
            {
                throw new ArgumentNullException("getSecurity");
            }

            if (getStorage == null)
            {
                throw new ArgumentNullException("getStorage");
            }

            if (drive == null)
            {
                throw new ArgumentNullException("drive");
            }

            _security = security;
            _getTime  = getTime;

            _arg  = arg;
            Drive = drive;

            _basket = new BasketMarketDataStorage <T>();

            var idGenerator = new SecurityIdGenerator();

            var parts = idGenerator.Split(security.Id);
            var code  = parts.Item1;

            var securities = InteropHelper
                             .GetDirectories(Path.Combine(Drive.Drive.Path, code.Substring(0, 1)), code + "*")
                             .Select(p => Path.GetFileName(p).FolderNameToSecurityId())
                             .Select(s =>
            {
                var id = idGenerator.Split(s);

                var clone   = security.Clone();
                clone.Id    = s;
                clone.Board = ExchangeBoard.GetOrCreateBoard(id.Item2);
                return(clone);
            });

            foreach (var sec in securities)
            {
                _basket.InnerStorages.Add(getStorage(sec, Drive.Drive));
            }
        }
Example #3
0
            public void Init()
            {
                if (!File.Exists(_fileName))
                {
                    return;
                }

                CultureInfo.InvariantCulture.DoInCulture(() =>
                {
                    using (var stream = new FileStream(_fileName, FileMode.Open, FileAccess.Read))
                    {
                        var reader = new FastCsvReader(stream, Encoding.UTF8);

                        reader.NextLine();
                        reader.Skip();

                        var fields = new string[reader.ColumnCount - 1];

                        for (var i = 0; i < reader.ColumnCount - 1; i++)
                        {
                            fields[i] = reader.ReadString();
                        }

                        reader.NextLine();
                        reader.Skip();

                        var types = new Type[reader.ColumnCount - 1];

                        for (var i = 0; i < reader.ColumnCount - 1; i++)
                        {
                            types[i] = reader.ReadString().To <Type>();
                            _fieldTypes.Add(fields[i], types[i]);
                        }

                        var idGenerator = new SecurityIdGenerator();

                        while (reader.NextLine())
                        {
                            var secId = idGenerator.Split(reader.ReadString());

                            var values = new Dictionary <object, object>();

                            for (var i = 0; i < fields.Length; i++)
                            {
                                values[fields[i]] = reader.ReadString().To(types[i]);
                            }

                            _cache.Add(secId, values);
                        }
                    }
                });
            }
Example #4
0
        private void ExecutedSaveSecurityCommand(object sender, ExecutedRoutedEventArgs e)
        {
            var entityRegistry = ConfigManager.GetService <IStudioEntityRegistry>();
            var security       = (Security)PropertyGrid.SelectedObject;

            if (_isNew)
            {
                var mbBuilder = new MessageBoxBuilder()
                                .Owner(this)
                                .Error();

                if (security.Code.IsEmpty())
                {
                    mbBuilder.Text(LocalizedStrings.Str1551).Show();
                    return;
                }

                if (security.Board == null)
                {
                    mbBuilder.Text(LocalizedStrings.Str1547).Show();
                    return;
                }

                if (security.PriceStep == null)
                {
                    mbBuilder.Text(LocalizedStrings.Str1546).Show();
                    return;
                }

                var id = new SecurityIdGenerator().GenerateId(security.Code, security.Board);

                if (entityRegistry.Securities.ReadById(id) != null)
                {
                    mbBuilder.Text(LocalizedStrings.Str3275Params.Put(id)).Show();
                    return;
                }

                security.Id = id;
            }
            else
            {
                security.CopyTo(SecurityPicker.SelectedSecurity);
                security = SecurityPicker.SelectedSecurity;
            }

            entityRegistry.Securities.Save(security);

            _isNew   = false;
            _changed = false;
        }
Example #5
0
        private Security GetSecurityBySecCode(string secCode)
        {
            var sfxSecurity = new SfxSecurity
            {
                SlotID  = _slot.ID,
                SecCode = secCode
            };

            sfxSecurity.Load().ThrowIfNeed(LocalizedStrings.Str3704);
            secCode = sfxSecurity.SecCode;

            var secBoard = ExchangeBoard.GetBoard(sfxSecurity.SecBoard);
            var id       = SecurityIdGenerator.GenerateId(secCode, secBoard);

            return(GetSecurity(id, name =>
            {
                var security = EntityFactory.CreateSecurity(name);

                security.Board = secBoard;
                security.Code = secCode;

                return security;
            }, security => false));
        }
Example #6
0
        private void StartBtnClick(object sender, RoutedEventArgs e)
        {
            InitChart();

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

            if (_connectors.Any(t => t.State != EmulationStates.Stopped))
            {
                MessageBox.Show(this, LocalizedStrings.Str3015);
                return;
            }

            var secGen = new SecurityIdGenerator();
            var id     = secGen.Split(SecId.Text);

            //if (secIdParts.Length != 2)
            //{
            //	MessageBox.Show(this, LocalizedStrings.Str3016);
            //	return;
            //}

            var timeFrame = TimeSpan.FromMinutes(TimeFrame.SelectedIndex == 0 ? 1 : 5);

            var secCode = id.SecurityCode;
            var board   = ExchangeBoard.GetOrCreateBoard(id.BoardCode);

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

            if (FinamCandlesCheckBox.IsChecked == true)
            {
                _finamHistorySource.Refresh(new FinamSecurityStorage(security), security, s => {}, () => false);
            }

            // create backtesting modes
            var settings = new[]
            {
                Tuple.Create(
                    TicksCheckBox,
                    TicksProgress,
                    TicksParameterGrid,
                    // ticks
                    new EmulationInfo {
                    UseTicks = true, CurveColor = Colors.DarkGreen, StrategyName = LocalizedStrings.Ticks
                }),

                Tuple.Create(
                    TicksAndDepthsCheckBox,
                    TicksAndDepthsProgress,
                    TicksAndDepthsParameterGrid,
                    // ticks + order book
                    new EmulationInfo {
                    UseTicks = true, UseMarketDepth = true, CurveColor = Colors.Red, StrategyName = LocalizedStrings.XamlStr757
                }),

                Tuple.Create(
                    DepthsCheckBox,
                    DepthsProgress,
                    DepthsParameterGrid,
                    // order book
                    new EmulationInfo {
                    UseMarketDepth = true, CurveColor = Colors.OrangeRed, StrategyName = LocalizedStrings.MarketDepths
                }),

                Tuple.Create(
                    CandlesCheckBox,
                    CandlesProgress,
                    CandlesParameterGrid,
                    // candles
                    new EmulationInfo {
                    UseCandleTimeFrame = timeFrame, CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.Candles
                }),

                Tuple.Create(
                    CandlesAndDepthsCheckBox,
                    CandlesAndDepthsProgress,
                    CandlesAndDepthsParameterGrid,
                    // candles + orderbook
                    new EmulationInfo {
                    UseMarketDepth = true, UseCandleTimeFrame = timeFrame, CurveColor = Colors.Cyan, StrategyName = LocalizedStrings.XamlStr635
                }),

                Tuple.Create(
                    OrderLogCheckBox,
                    OrderLogProgress,
                    OrderLogParameterGrid,
                    // order log
                    new EmulationInfo {
                    UseOrderLog = true, CurveColor = Colors.CornflowerBlue, StrategyName = LocalizedStrings.OrderLog
                }),

                Tuple.Create(
                    Level1CheckBox,
                    Level1Progress,
                    Level1ParameterGrid,
                    // order log
                    new EmulationInfo {
                    UseLevel1 = true, CurveColor = Colors.Aquamarine, StrategyName = LocalizedStrings.Level1
                }),

                Tuple.Create(
                    FinamCandlesCheckBox,
                    FinamCandlesProgress,
                    FinamCandlesParameterGrid,
                    // candles
                    new EmulationInfo {
                    UseCandleTimeFrame = timeFrame, HistorySource = d => _finamHistorySource.GetCandles(security, timeFrame, d.Date, d.Date), CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.FinamCandles
                }),

                Tuple.Create(
                    YahooCandlesCheckBox,
                    YahooCandlesProgress,
                    YahooCandlesParameterGrid,
                    // candles
                    new EmulationInfo {
                    UseCandleTimeFrame = timeFrame, HistorySource = d => new YahooHistorySource().GetCandles(security, timeFrame, d.Date, d.Date), CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.YahooCandles
                }),
            };

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

            var startTime = ((DateTime)From.Value).ChangeKind(DateTimeKind.Utc);
            var stopTime  = ((DateTime)To.Value).ChangeKind(DateTimeKind.Utc);

            // (ru only) ОЛ необходимо загружать с 18.45 пред дня, чтобы стаканы строились правильно
            if (OrderLogCheckBox.IsChecked == true)
            {
                startTime = startTime.Subtract(TimeSpan.FromDays(1)).AddHours(18).AddMinutes(45).AddTicks(1).ApplyTimeZone(TimeHelper.Moscow).UtcDateTime;
            }

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

            // set ProgressBar bounds
            _progressBars.ForEach(p =>
            {
                p.Value   = 0;
                p.Maximum = 100;
            });

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

            logManager.Listeners.Add(fileLogListener);
            //logManager.Listeners.Add(new DebugLogListener());	// for track logs in output window in Vusial Studio (poor performance).

            var generateDepths = GenDepthsCheckBox.IsChecked == true;
            var maxDepth       = MaxDepth.Text.To <int>();
            var maxVolume      = MaxVolume.Text.To <int>();
            var secId          = security.ToSecurityId();

            foreach (var set in settings)
            {
                if (set.Item1.IsChecked == false)
                {
                    continue;
                }

                var progressBar   = set.Item2;
                var statistic     = set.Item3;
                var emulationInfo = set.Item4;

                var level1Info = new Level1ChangeMessage
                {
                    SecurityId = secId,
                    ServerTime = startTime,
                }
                .TryAdd(Level1Fields.PriceStep, secCode == "RIZ2" ? 10m : 1)
                .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 connector = new HistoryEmulationConnector(
                    new[] { security },
                    new[] { portfolio })
                {
                    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 = false,
                            }
                        }
                    },

                    UseExternalCandleSource = emulationInfo.UseCandleTimeFrame != null,

                    CreateDepthFromOrdersLog  = emulationInfo.UseOrderLog,
                    CreateTradesFromOrdersLog = emulationInfo.UseOrderLog,

                    HistoryMessageAdapter =
                    {
                        StorageRegistry             = storageRegistry,

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

                        OrderLogMarketDepthBuilders =
                        {
                            {
                                secId,
                                LocalizedStrings.ActiveLanguage == Languages.Russian
                                                                        ? (IOrderLogMarketDepthBuilder) new PlazaOrderLogMarketDepthBuilder(secId)
                                                                        : new ItchOrderLogMarketDepthBuilder(secId)
                            }
                        }
                    },

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

                ((ILogSource)connector).LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info;

                logManager.Sources.Add(connector);

                var candleManager = emulationInfo.UseCandleTimeFrame == null
                                        ? new CandleManager(new TradeCandleBuilderSourceEx(connector))
                                        : new CandleManager(connector);

                var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame);

                _shortMa = new SimpleMovingAverage {
                    Length = 10
                };
                _shortElem = new ChartIndicatorElement
                {
                    Color          = Colors.Coral,
                    ShowAxisMarker = false,
                    FullTitle      = _shortMa.ToString()
                };
                _bufferedChart.AddElement(_area, _shortElem);

                _longMa = new SimpleMovingAverage {
                    Length = 80
                };
                _longElem = new ChartIndicatorElement
                {
                    ShowAxisMarker = false,
                    FullTitle      = _longMa.ToString()
                };
                _bufferedChart.AddElement(_area, _longElem);

                // create strategy based on 80 5-min и 10 5-min
                var strategy = new SmaStrategy(_bufferedChart, _candlesElem, _tradesElem, _shortMa, _shortElem, _longMa, _longElem, candleManager, series)
                {
                    Volume    = 1,
                    Portfolio = portfolio,
                    Security  = security,
                    Connector = connector,
                    LogLevel  = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info,

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

                logManager.Sources.Add(strategy);

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

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

                    if (emulationInfo.HistorySource != null)
                    {
                        if (emulationInfo.UseCandleTimeFrame != null)
                        {
                            connector.RegisterHistorySource(security, MarketDataTypes.CandleTimeFrame, emulationInfo.UseCandleTimeFrame.Value, emulationInfo.HistorySource);
                        }

                        if (emulationInfo.UseTicks)
                        {
                            connector.RegisterHistorySource(security, MarketDataTypes.Trades, null, emulationInfo.HistorySource);
                        }

                        if (emulationInfo.UseLevel1)
                        {
                            connector.RegisterHistorySource(security, MarketDataTypes.Level1, null, emulationInfo.HistorySource);
                        }

                        if (emulationInfo.UseMarketDepth)
                        {
                            connector.RegisterHistorySource(security, MarketDataTypes.MarketDepth, null, emulationInfo.HistorySource);
                        }
                    }
                    else
                    {
                        if (emulationInfo.UseMarketDepth)
                        {
                            connector.RegisterMarketDepth(security);

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

                        if (emulationInfo.UseOrderLog)
                        {
                            connector.RegisterOrderLog(security);
                        }

                        if (emulationInfo.UseTicks)
                        {
                            connector.RegisterTrades(security);
                        }

                        if (emulationInfo.UseLevel1)
                        {
                            connector.RegisterSecurity(security);
                        }
                    }

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

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

                // fill parameters panel
                statistic.Parameters.Clear();
                statistic.Parameters.AddRange(strategy.StatisticManager.Parameters);

                var pnlCurve           = Curve.CreateCurve(LocalizedStrings.PnL + " " + emulationInfo.StrategyName, emulationInfo.CurveColor, EquityCurveChartStyles.Area);
                var unrealizedPnLCurve = Curve.CreateCurve(LocalizedStrings.PnLUnreal + emulationInfo.StrategyName, Colors.Black);
                var commissionCurve    = Curve.CreateCurve(LocalizedStrings.Str159 + " " + emulationInfo.StrategyName, Colors.Red, EquityCurveChartStyles.DashedLine);
                var posItems           = PositionCurve.CreateCurve(emulationInfo.StrategyName, emulationInfo.CurveColor);
                strategy.PnLChanged += () =>
                {
                    var pnl = new EquityData
                    {
                        Time  = strategy.CurrentTime,
                        Value = strategy.PnL - strategy.Commission ?? 0
                    };

                    var unrealizedPnL = new EquityData
                    {
                        Time  = strategy.CurrentTime,
                        Value = strategy.PnLManager.UnrealizedPnL
                    };

                    var commission = new EquityData
                    {
                        Time  = strategy.CurrentTime,
                        Value = strategy.Commission ?? 0
                    };

                    pnlCurve.Add(pnl);
                    unrealizedPnLCurve.Add(unrealizedPnL);
                    commissionCurve.Add(commission);
                };

                strategy.PositionChanged += () => posItems.Add(new EquityData {
                    Time = strategy.CurrentTime, Value = strategy.Position
                });

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

                connector.StateChanged += () =>
                {
                    if (connector.State == EmulationStates.Stopped)
                    {
                        candleManager.Stop(series);
                        strategy.Stop();

                        logManager.Dispose();
                        _connectors.Clear();

                        SetIsEnabled(false);

                        this.GuiAsync(() =>
                        {
                            if (connector.IsFinished)
                            {
                                progressBar.Value = progressBar.Maximum;
                                MessageBox.Show(this, LocalizedStrings.Str3024.Put(DateTime.Now - _startEmulationTime));
                            }
                            else
                            {
                                MessageBox.Show(this, LocalizedStrings.cancelled);
                            }
                        });
                    }
                    else if (connector.State == EmulationStates.Started)
                    {
                        SetIsEnabled(true);
                    }
                };

                if (ShowDepth.IsChecked == true)
                {
                    MarketDepth.UpdateFormat(security);

                    connector.NewMessage += message =>
                    {
                        var quoteMsg = message as QuoteChangeMessage;

                        if (quoteMsg != null)
                        {
                            MarketDepth.UpdateDepth(quoteMsg);
                        }
                    };
                }

                _connectors.Add(connector);

                progressBar.Value = 0;
            }

            _startEmulationTime = DateTime.Now;

            // start emulation
            foreach (var connector in _connectors)
            {
                // 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
                    }
                });
            }

            TabControl.Items.Cast <TabItem>().First(i => i.Visibility == Visibility.Visible).IsSelected = true;
        }
Example #7
0
        private void LoadData()
        {
            _candle    = null;
            _lastPrice = 0m;
            _allCandles.Clear();

            var id = new SecurityIdGenerator().Split(SecurityId.Text);

            _security = new Security
            {
                Id        = SecurityId.Text,
                PriceStep = _priceStep,
                Board     = _exchangeInfoProvider.GetExchangeBoard(id.BoardCode)
            };

            Chart.Reset(new IChartElement[] { _candleElement1 });

            var storage = new StorageRegistry();

            var maxDays = 2;

            BusyIndicator.IsBusy = true;

            var path = HistoryPath.Folder;

            Task.Factory.StartNew(() =>
            {
                var date = DateTime.MinValue;

                foreach (var tick in storage.GetTickMessageStorage(_security, new LocalMarketDataDrive(path)).Load())
                {
                    AppendTick(_security, tick);

                    _lastTime = tick.ServerTime;

                    if (date != tick.ServerTime.Date)
                    {
                        date = tick.ServerTime.Date;

                        var str = date.To <string>();
                        this.GuiAsync(() => BusyIndicator.BusyContent = str);

                        maxDays--;

                        if (maxDays == 0)
                        {
                            break;
                        }
                    }
                }
            })
            .ContinueWith(t =>
            {
                if (t.Exception != null)
                {
                    Error(t.Exception.Message);
                }

                this.GuiAsync(() =>
                {
                    BusyIndicator.IsBusy = false;
                    Chart.IsAutoRange    = false;
                    _areaComb.YAxises.First().AutoRange = false;
                });
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }
Example #8
0
        /// <summary>
        /// Synchronize securities with storage.
        /// </summary>
        /// <param name="drives">Storage drives.</param>
        /// <param name="entityRegistry">The storage of trade objects.</param>
        /// <param name="newSecurity">The handler through which a new instrument will be passed.</param>
        /// <param name="updateProgress">The handler through which a progress change will be passed.</param>
        /// <param name="addLog">The handler through which a new log message be passed.</param>
        /// <param name="isCancelled">The handler which returns an attribute of search cancel.</param>
        public static void SynchronizeSecurities(this IEnumerable <IMarketDataDrive> drives, IEntityRegistry entityRegistry, Action <Security> newSecurity,
                                                 Action <int, int> updateProgress, Action <LogMessage> addLog, Func <bool> isCancelled)
        {
            if (drives == null)
            {
                throw new ArgumentNullException(nameof(drives));
            }

            if (entityRegistry == null)
            {
                throw new ArgumentNullException(nameof(entityRegistry));
            }

            if (newSecurity == null)
            {
                throw new ArgumentNullException(nameof(newSecurity));
            }

            if (updateProgress == null)
            {
                throw new ArgumentNullException(nameof(updateProgress));
            }

            if (addLog == null)
            {
                throw new ArgumentNullException(nameof(addLog));
            }

            if (isCancelled == null)
            {
                throw new ArgumentNullException(nameof(isCancelled));
            }

            var securityPaths = new List <string>();
            var progress      = 0;

            foreach (var dir in drives.Select(drive => drive.Path).Distinct())
            {
                foreach (var letterDir in InteropHelper.GetDirectories(dir))
                {
                    if (isCancelled())
                    {
                        break;
                    }

                    var name = Path.GetFileName(letterDir);

                    if (name == null || name.Length != 1)
                    {
                        continue;
                    }

                    securityPaths.AddRange(InteropHelper.GetDirectories(letterDir));
                }

                if (isCancelled())
                {
                    break;
                }
            }

            if (isCancelled())
            {
                return;
            }

            // кол-во проходов по директории для создания инструмента
            var iterCount = securityPaths.Count;

            updateProgress(0, iterCount);

            var logSource = ConfigManager.GetService <LogManager>().Application;

            var securityIdGenerator = new SecurityIdGenerator();

            var securities = entityRegistry.Securities.ToDictionary(s => s.Id, s => s, StringComparer.InvariantCultureIgnoreCase);

            foreach (var securityPath in securityPaths)
            {
                if (isCancelled())
                {
                    break;
                }

                var securityId = Path.GetFileName(securityPath).FolderNameToSecurityId();

                var isNew = false;

                var security = securities.TryGetValue(securityId);

                if (security == null)
                {
                    var firstDataFile =
                        Directory.EnumerateDirectories(securityPath)
                        .SelectMany(d => Directory.EnumerateFiles(d, "*.bin")
                                    .Concat(Directory.EnumerateFiles(d, "*.csv"))
                                    .OrderBy(f => Path.GetExtension(f).CompareIgnoreCase(".bin") ? 0 : 1))
                        .FirstOrDefault();

                    if (firstDataFile != null)
                    {
                        var id = securityIdGenerator.Split(securityId);

                        decimal priceStep;

                        if (Path.GetExtension(firstDataFile).CompareIgnoreCase(".bin"))
                        {
                            try
                            {
                                priceStep = File.ReadAllBytes(firstDataFile).Range(6, 16).To <decimal>();
                            }
                            catch (Exception ex)
                            {
                                throw new InvalidOperationException(LocalizedStrings.Str2929Params.Put(firstDataFile), ex);
                            }
                        }
                        else
                        {
                            priceStep = 0.01m;
                        }

                        security = new Security
                        {
                            Id        = securityId,
                            PriceStep = priceStep,
                            Name      = id.SecurityCode,
                            Code      = id.SecurityCode,
                            Board     = ExchangeBoard.GetOrCreateBoard(id.BoardCode),
                        };

                        securities.Add(securityId, security);

                        entityRegistry.Securities.Save(security);
                        newSecurity(security);

                        isNew = true;
                    }
                }

                updateProgress(progress++, iterCount);

                if (isNew)
                {
                    addLog(new LogMessage(logSource, TimeHelper.NowWithOffset, LogLevels.Info, LocalizedStrings.Str2930Params.Put(security)));
                }
            }
        }
        private void StartBtnClick(object sender, RoutedEventArgs e)
        {
            InitChart();

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

            var secGen     = new SecurityIdGenerator();
            var secIdParts = secGen.Split(SecId.Text);

            var storageRegistry = new StorageRegistry()
            {
                DefaultDrive = new LocalMarketDataDrive(HistoryPath.Text)
            };

            var startTime = ((DateTime)From.Value).ChangeKind(DateTimeKind.Utc);
            var stopTime  = ((DateTime)To.Value).ChangeKind(DateTimeKind.Utc);

            //var logManager = new LogManager();
            //var fileLogListener = new FileLogListener("sample.log");
            //logManager.Listeners.Add(fileLogListener);
            //logManager.Listeners.Add(new DebugLogListener());	// for track logs in output window in Vusial Studio (poor performance).

            var maxDepth  = 5;
            var maxVolume = 5;

            var secCode = secIdParts.Item1;
            var board   = ExchangeBoard.GetOrCreateBoard(secIdParts.Item2);

            var progressBar  = TicksTestingProcess;
            var progressStep = ((stopTime - startTime).Ticks / 100).To <TimeSpan>();

            progressBar.Value   = 0;
            progressBar.Maximum = 100;

            var statistic = TicksParameterGrid;
            var security  = new Security()
            {
                Id    = SecId.Text,
                Code  = secCode,
                Board = board,
            };

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

            var connector = new HistoryEmulationConnector(new[] { security }, new[] { portfolio })
            {
                EmulationAdapter =
                {
                    Emulator     =
                    {
                        Settings = { MatchOnTouch = true, PortfolioRecalcInterval = TimeSpan.FromMilliseconds(100), SpreadSize = 1, },
                        LogLevel = LogLevels.Debug,
                    },
                    LogLevel     = LogLevels.Debug,
                },
                HistoryMessageAdapter = { StorageRegistry = storageRegistry, StartDate = startTime, StopDate = stopTime, MarketTimeChangedInterval = TimeSpan.FromMilliseconds(50), },
            };

            //logManager.Sources.Add(connector);

            var candleManager = new CandleManager(connector);
            var series        = new CandleSeries(typeof(RangeCandle), security, new Unit(100));

            shortMa = new SimpleMovingAverage {
                Length = 10
            };
            shortElem = new ChartIndicatorElement
            {
                Color          = Colors.Coral,
                ShowAxisMarker = false,
                FullTitle      = shortMa.ToString()
            };
            bufferedChart.AddElement(area, shortElem);

            longMa = new SimpleMovingAverage {
                Length = 30
            };
            longElem = new ChartIndicatorElement
            {
                ShowAxisMarker = false,
                FullTitle      = longMa.ToString()
            };

            bufferedChart.AddElement(area, longElem);

            var strategy = new SmaStrategy(bufferedChart, candlesElem, tradesElem, shortMa, shortElem, longMa, longElem, series)
            {
                Volume                = 1,
                Portfolio             = portfolio,
                Security              = security,
                Connector             = connector,
                LogLevel              = LogLevels.Debug,
                UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To <TimeSpan>()
            };

            //logManager.Sources.Add(strategy);

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

                connector.RegisterMarketDepth(security);
                connector.RegisterMarketDepth(new TrendMarketDepthGenerator(connector.GetSecurityId(security))
                {
                    Interval           = TimeSpan.FromMilliseconds(100),       // order book freq refresh is 1 sec
                    MaxAsksDepth       = maxDepth,
                    MaxBidsDepth       = maxDepth,
                    UseTradeVolume     = true,
                    MaxVolume          = maxVolume,
                    MinSpreadStepCount = 1,     // min spread generation is 2 pips
                    MaxSpreadStepCount = 1,     // max spread generation size (prevent extremely size)
                    MaxPriceStepCount  = 3      // pips size,
                });

                connector.RegisterTrades(security);
                connector.RegisterSecurity(security);

                strategy.Start();
                candleManager.Start(series);

                connector.Start();
            };

            statistic.Parameters.Clear();
            statistic.Parameters.AddRange(strategy.StatisticManager.Parameters);

            var pnlCurve           = Curve.CreateCurve(LocalizedStrings.PnL + " " + StrategyName, Colors.Cyan, EquityCurveChartStyles.Area);
            var unrealizedPnLCurve = Curve.CreateCurve(LocalizedStrings.PnLUnreal + StrategyName, Colors.Black);
            var commissionCurve    = Curve.CreateCurve(LocalizedStrings.Str159 + " " + StrategyName, Colors.Red, EquityCurveChartStyles.DashedLine);
            var posItems           = PositionCurve.CreateCurve(StrategyName, Colors.Crimson);

            strategy.PnLChanged += () =>
            {
                var pnl = new EquityData()
                {
                    Time = strategy.CurrentTime, Value = strategy.PnL - strategy.Commission ?? 0
                };
                var unrealizedPnL = new EquityData()
                {
                    Time = strategy.CurrentTime, Value = strategy.PnLManager.UnrealizedPnL
                };
                var commission = new EquityData()
                {
                    Time = strategy.CurrentTime, Value = strategy.Commission ?? 0
                };

                pnlCurve.Add(pnl);
                unrealizedPnLCurve.Add(unrealizedPnL);
                commissionCurve.Add(commission);
            };

            strategy.PositionChanged += () => posItems.Add(new EquityData {
                Time = strategy.CurrentTime, Value = strategy.Position
            });

            var nextTime = startTime + progressStep;

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

            connector.StateChanged += () =>
            {
                if (connector.State == EmulationStates.Stopped)
                {
                    candleManager.Stop(series);
                    strategy.Stop();

                    //logManager.Dispose();

                    SetIsEnabled(false);

                    this.GuiAsync(() =>
                    {
                        if (connector.IsFinished)
                        {
                            progressBar.Value = progressBar.Maximum;
                            MessageBox.Show(this, LocalizedStrings.Str3024.Put(DateTime.Now - startEmulationTime));
                        }
                        else
                        {
                            MessageBox.Show(this, LocalizedStrings.cancelled);
                        }
                    });
                }
                else if (connector.State == EmulationStates.Started)
                {
                    SetIsEnabled(true);
                }
            };

            progressBar.Value  = 0;
            startEmulationTime = DateTime.Now;

            connector.Connect();
            connector.SendInMessage(new CommissionRuleMessage()
            {
                Rule = new CommissionPerTradeRule {
                    Value = 0.01m
                }
            });
        }
Example #10
0
        //private void InitOrderLogBuilders(DateTime loadDate)
        //{
        //	if (StorageRegistry == null || !MarketEmulator.Settings.UseMarketDepth)
        //		return;

        //	foreach (var security in RegisteredMarketDepths)
        //	{
        //		var builder = _orderLogBuilders.TryGetValue(security);

        //		if (builder == null)
        //			continue;

        //		// стакан из ОЛ строиться начиная с 18.45 предыдущей торговой сессии
        //		var olDate = loadDate.Date;

        //		do
        //		{
        //			olDate -= TimeSpan.FromDays(1);
        //		}
        //		while (!ExchangeBoard.Forts.WorkingTime.IsTradeDate(olDate));

        //		olDate += new TimeSpan(18, 45, 0);

        //		foreach (var item in StorageRegistry.GetOrderLogStorage(security, Drive).Load(olDate, loadDate - TimeSpan.FromTicks(1)))
        //		{
        //			builder.Update(item);
        //		}
        //	}
        //}

        private Security FindSecurity(SecurityId secId)
        {
            return(this.LookupById(SecurityIdGenerator.GenerateId(secId.SecurityCode, secId.BoardCode)));
        }
Example #11
0
        private void OnSecurity(int tableId, object[] values)
        {
            var table = SecuritiesTable;

            var secCode  = table.GetValue <string>(values, AlorSecurityColumns.Code);
            var secBoard = ExchangeBoard.GetBoard(table.GetValue <string>(values, AlorSecurityColumns.Board));

            var id = SecurityIdGenerator.GenerateId(secCode, secBoard);

            GetSecurity(id, name =>
            {
                var security = EntityFactory.CreateSecurity(name);

                security.Code       = table.GetValue <string>(values, AlorSecurityColumns.Code);
                security.Name       = table.GetValue <string>(values, AlorSecurityColumns.Name);
                security.ShortName  = table.GetValue <string>(values, AlorSecurityColumns.ShortName);
                security.Board      = secBoard;
                security.ExpiryDate = table.GetValue <DateTime>(values, AlorSecurityColumns.ExecutionDate);

                security.Decimals     = table.GetValue <int>(values, AlorSecurityColumns.Decimals);
                security.Multiplier   = table.GetValue <int>(values, AlorSecurityColumns.MinLotSize);
                security.MinStepPrice = table.GetValue <decimal>(values, AlorSecurityColumns.MinStepPrice);
                security.PriceStep    = table.GetValue <decimal>(values, AlorSecurityColumns.MinStep);

                return(security);
            }, security =>
            {
                using (security.BeginUpdate())
                {
                    security.BestBid = new Quote
                    {
                        OrderDirection = OrderDirections.Buy,
                        Price          = table.GetValue <decimal>(values, AlorSecurityColumns.BestBidPrice),
                        Volume         = table.GetValue <int>(values, AlorSecurityColumns.BestBidVolume),
                        Security       = security,
                    };

                    security.BestAsk = new Quote
                    {
                        OrderDirection = OrderDirections.Sell,
                        Price          = table.GetValue <decimal>(values, AlorSecurityColumns.BestAskPrice),
                        Volume         = table.GetValue <int>(values, AlorSecurityColumns.BestBidVolume),
                        Security       = security,
                    };

                    security.OpenPrice = table.GetValue <decimal>(values, AlorSecurityColumns.OpenPrice);
                    security.HighPrice = table.GetValue <decimal>(values, AlorSecurityColumns.HighPrice);
                    security.LowPrice  = table.GetValue <decimal>(values, AlorSecurityColumns.LowPrice);
                    // NOTE:

                    security.SettlementDate = table.GetValue <DateTime>(values, AlorSecurityColumns.CancellationDate);

                    if (table.GetValue <string>(values, AlorSecurityColumns.OptionType).Trim().IsEmpty() ||
                        table.GetValue <string>(values, AlorSecurityColumns.OptionType) == "F")
                    {
                        if (table.GetValue <string>(values, AlorSecurityColumns.FutureCode).Trim().IsEmpty())
                        {
                            security.Type = SecurityTypes.Stock;
                        }
                        else
                        {
                            security.Type = SecurityTypes.Future;
                            security.ExtensionInfo[AlorSecurityColumns.FutureCode] = table.GetValue <string>(values, AlorSecurityColumns.FutureCode);
                        }
                    }
                    else
                    {
                        security.Type = SecurityTypes.Option;
                        security.ExtensionInfo[AlorSecurityColumns.OptionType] = table.GetValue <string>(values, AlorSecurityColumns.OptionType);
                    }

                    security.LastTrade = new Trade
                    {
                        Security = security,
                        Time     = table.GetValue <DateTime>(values, AlorSecurityColumns.LastTradeTime),
                        Price    = table.GetValue <decimal>(values, AlorSecurityColumns.LastTradePrice),
                        Volume   = table.GetValue <int>(values, AlorSecurityColumns.LastTradeVolume),
                    };

                    security.MinPrice = table.GetValue <decimal>(values, AlorSecurityColumns.LowPriceLimit);
                    security.MaxPrice = table.GetValue <decimal>(values, AlorSecurityColumns.HighPriceLimit);

                    security.MarginBuy  = table.GetValue <decimal>(values, AlorSecurityColumns.BuyDeposit);
                    security.MarginSell = table.GetValue <decimal>(values, AlorSecurityColumns.SellDeposit);

                    security.State = table.GetValue <string>(values, AlorSecurityColumns.TradingStatus) == "O" ? SecurityStates.Trading : SecurityStates.Stoped;

                    table.FillNonMandatoryInfo(security, values);
                }
                return(true);
            });
        }
Example #12
0
        private void LoadData()
        {
            _lastPrice = 0m;

            _candles.Clear();
            var id = new SecurityIdGenerator().Split(SecurityId);

            _security = new Security
            {
                Id        = SecurityId,
                PriceStep = PriceStep,
                Board     = ExchangeBoard.GetBoard(id.BoardCode)
            };

            Chart.Reset(new IChartElement[] { _candleElement });

            var storage = new StorageRegistry();

            var maxDays = 50;

            BusyIndicator.IsBusy = true;

            var path = HistoryPath;

            _curCandleNum = 0;

            Task.Factory.StartNew(() =>
            {
                var date = DateTime.MinValue;

                foreach (var tick in storage.GetTickMessageStorage(_security, new LocalMarketDataDrive(path)).Load())
                {
                    if (date != tick.ServerTime.Date)
                    {
                        date = tick.ServerTime.Date;

                        this.GuiAsync(() => BusyIndicator.BusyContent = $"Loading ticks for {date:dd MMM yyyy}...");

                        if (--maxDays == 0)
                        {
                            break;
                        }
                    }

                    AppendTick(tick);
                }
            })
            .ContinueWith(t =>
            {
                this.GuiAsync(() => BusyIndicator.IsBusy = false);

                for (var i = 0; i < _candles.Count; i += CandlesPacketSize)
                {
                    var data = new ChartDrawData();

                    var candles = _candles.GetRange(i, Math.Min(CandlesPacketSize, _candles.Count - i)).Select(c => c.ToCandle(TFSpan));

                    foreach (var candle in candles)
                    {
                        candle.State = CandleStates.Finished;

                        var group = data.Group(candle.OpenTime);

                        group.Add(_candleElement, candle);

                        if (_indicatorElement != null)
                        {
                            group.Add(_indicatorElement, _indicator.Process((double)candle.ClosePrice));
                        }
                    }

                    Chart.Draw(data);
                }
            })
            .ContinueWith(t =>
            {
                if (t.Exception != null)
                {
                    Error(t.Exception.Message);
                }

                _dataIsLoaded = true;

                this.GuiAsync(() => BusyIndicator.IsBusy = false);

                Chart.IsAutoRange = false;
                //_area.YAxises.FirstOrDefault().Do(a => a.AutoRange = false);
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }
Example #13
0
        private void StartButtonOnClick(object sender, RoutedEventArgs e)
        {
            _logManager.Sources.Clear();
            _bufferedChart.ClearAreas();

            Curve.Clear();
            PositionCurve.Clear();

            if (HistoryPathTextBox.Text.IsEmpty() || !Directory.Exists(HistoryPathTextBox.Text))
            {
                MessageBox.Show("Wrong path.");
                return;
            }

            if (_connector != null && _connector.State != EmulationStates.Stopped)
            {
                MessageBox.Show("Already launched.");
                return;
            }

            if (Composition == null)
            {
                MessageBox.Show("No strategy selected.");
                return;
            }

            var secGen     = new SecurityIdGenerator();
            var secIdParts = secGen.Split(SecusityTextBox.Text);
            var secCode    = secIdParts.SecurityCode;
            var board      = ExchangeBoard.GetOrCreateBoard(secIdParts.BoardCode);
            var timeFrame  = (TimeSpan)TimeFrameComboBox.SelectedItem;
            var useCandles = (string)MarketDataTypeComboBox.SelectedItem != "Ticks";

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

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

            var startTime = ((DateTime)FromDatePicker.Value).ChangeKind(DateTimeKind.Utc);
            var stopTime  = ((DateTime)ToDatePicke.Value).ChangeKind(DateTimeKind.Utc);

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

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

            var level1Info = new Level1ChangeMessage
            {
                SecurityId = security.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);

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

            // create backtesting connector
            _connector = new HistoryEmulationConnector(
                new[] { security },
                new[] { portfolio })
            {
                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 = false,
                        }
                    }
                },

                UseExternalCandleSource = useCandles,

                HistoryMessageAdapter =
                {
                    StorageRegistry = storageRegistry,

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

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

            //((ILogSource)_connector).LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info;

            _logManager.Sources.Add(_connector);

            var candleManager = !useCandles
                                        ? new CandleManager(new TradeCandleBuilderSourceEx(_connector))
                                        : new CandleManager(_connector);

            // create strategy based on 80 5-min и 10 5-min
            var strategy = new DiagramStrategy
            {
                Volume    = 1,
                Portfolio = portfolio,
                Security  = security,
                Connector = _connector,
                //LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info,

                Composition = Composition,

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

            strategy.SetChart(_bufferedChart);
            strategy.SetCandleManager(candleManager);

            _logManager.Sources.Add(strategy);

            strategy.OrderRegistering    += OnStrategyOrderRegistering;
            strategy.OrderReRegistering  += OnStrategyOrderReRegistering;
            strategy.OrderRegisterFailed += OnStrategyOrderRegisterFailed;

            strategy.StopOrderRegistering    += OnStrategyOrderRegistering;
            strategy.StopOrderReRegistering  += OnStrategyOrderReRegistering;
            strategy.StopOrderRegisterFailed += OnStrategyOrderRegisterFailed;

            strategy.NewMyTrades += OnStrategyNewMyTrade;

            var pnlCurve           = Curve.CreateCurve(LocalizedStrings.PnL + " " + strategy.Name, Colors.DarkGreen, EquityCurveChartStyles.Area);
            var unrealizedPnLCurve = Curve.CreateCurve(LocalizedStrings.PnLUnreal + strategy.Name, Colors.Black);
            var commissionCurve    = Curve.CreateCurve(LocalizedStrings.Str159 + " " + strategy.Name, Colors.Red, EquityCurveChartStyles.DashedLine);

            strategy.PnLChanged += () =>
            {
                var pnl = new EquityData
                {
                    Time  = strategy.CurrentTime,
                    Value = strategy.PnL - strategy.Commission ?? 0
                };

                var unrealizedPnL = new EquityData
                {
                    Time  = strategy.CurrentTime,
                    Value = strategy.PnLManager.UnrealizedPnL
                };

                var commission = new EquityData
                {
                    Time  = strategy.CurrentTime,
                    Value = strategy.Commission ?? 0
                };

                pnlCurve.Add(pnl);
                unrealizedPnLCurve.Add(unrealizedPnL);
                commissionCurve.Add(commission);
            };

            var posItems = PositionCurve.CreateCurve(strategy.Name, Colors.DarkGreen);

            strategy.PositionChanged += () => posItems.Add(new EquityData {
                Time = strategy.CurrentTime, Value = strategy.Position
            });

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

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

                //_connector.RegisterMarketDepth(security);
                if (!useCandles)
                {
                    _connector.RegisterTrades(security);
                }

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

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

            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.StateChanged += () =>
            {
                switch (_connector.State)
                {
                case EmulationStates.Stopped:
                    strategy.Stop();
                    SetIsEnabled(false);

                    this.GuiAsync(() =>
                    {
                        if (_connector.IsFinished)
                        {
                            TicksAndDepthsProgress.Value = TicksAndDepthsProgress.Maximum;
                            MessageBox.Show("Done.");
                        }
                        else
                        {
                            MessageBox.Show("Cancelled.");
                        }
                    });
                    break;

                case EmulationStates.Started:
                    SetIsEnabled(true);
                    break;
                }
            };

            TicksAndDepthsProgress.Value = 0;

            // 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
                }
            });
        }
Example #14
0
        private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
        {
            Year.ItemsSource  = Competition.AllYears;
            Year.SelectedItem = Competition.AllYears.Last();

            Directory.CreateDirectory(_settingsDir);

            var ns = typeof(IIndicator).Namespace;

            var rendererTypes = typeof(Chart).Assembly
                                .GetTypes()
                                .Where(t => !t.IsAbstract && typeof(BaseChartIndicatorPainter).IsAssignableFrom(t))
                                .ToDictionary(t => t.Name);

            var indicators = typeof(IIndicator).Assembly
                             .GetTypes()
                             .Where(t => t.Namespace == ns && !t.IsAbstract && typeof(IIndicator).IsAssignableFrom(t))
                             .Select(t => new IndicatorType(t, rendererTypes.TryGetValue(t.Name + "Painter")));

            Chart.IndicatorTypes.AddRange(indicators);

            var finamSecurities = Path.Combine(_settingsDir, "finam2.csv");

            BusyIndicator.BusyContent = "Обновление инструментов...";
            BusyIndicator.IsBusy      = true;

            Task.Factory.StartNew(() =>
            {
                File.Delete("finam.csv");

                if (File.Exists(finamSecurities))
                {
                    CultureInfo.InvariantCulture.DoInCulture(() =>
                    {
                        var idGen = new SecurityIdGenerator();

                        var securities = File.ReadAllLines(finamSecurities).Select(line =>
                        {
                            var cells   = line.SplitByComma();
                            var idParts = idGen.Split(cells[0]);

                            return(new Security
                            {
                                Id = cells[0],
                                Code = idParts.Item1,
                                Board = ExchangeBoard.GetOrCreateBoard(idParts.Item2),
                                ExtensionInfo = new Dictionary <object, object>
                                {
                                    { FinamHistorySource.MarketIdField, cells[1].To <long>() },
                                    { FinamHistorySource.SecurityIdField, cells[2].To <long>() },
                                },
                                PriceStep = cells[3].To <decimal?>(),
                                Decimals = cells[4].To <int?>(),
                                Currency = cells[5].To <CurrencyTypes?>(),
                            });
                        });

                        foreach (var security in securities)
                        {
                            _securityProvider.Securities.Add(security);
                            _securityStorage.Save(security);
                        }
                    });
                }
                else
                {
                    _finamHistorySource.Refresh(_securityStorage, new Security(), s => { }, () => false);

                    var securities = _securityStorage.LookupAll().ToArray();

                    foreach (var security in securities)
                    {
                        _securityProvider.Securities.Add(security);
                    }

                    File.WriteAllLines(finamSecurities, securities.Where(s => !s.Id.Contains(',')).Select(s => "{0},{1},{2},{3},{4},{5}"
                                                                                                          .Put(s.Id, s.ExtensionInfo[FinamHistorySource.MarketIdField], s.ExtensionInfo[FinamHistorySource.SecurityIdField], s.PriceStep, s.Decimals, s.Currency)));
                }
            })
            .ContinueWith(res =>
            {
                BusyIndicator.IsBusy = false;

                if (res.Exception != null)
                {
                    new MessageBoxBuilder()
                    .Error()
                    .Owner(this)
                    .Text(res.Exception.ToString())
                    .Show();
                }

                if (File.Exists(_settingsFile))
                {
                    var settings = CultureInfo.InvariantCulture.DoInCulture(() => new XmlSerializer <SettingsStorage>().Deserialize(_settingsFile).Load <Settings>());

                    Year.SelectedItem      = settings.Year;
                    Trader.Text            = settings.Trader;
                    From.Value             = settings.From;
                    To.Value               = settings.To;
                    Security1.Text         = settings.Security1;
                    Security2.Text         = settings.Security2;
                    Security3.Text         = settings.Security3;
                    Security4.Text         = settings.Security4;
                    TimeFrame.SelectedItem = settings.TimeFrame;
                    Apart.IsChecked        = settings.Apart;
                }
                else
                {
                    Trader.Text    = "Vasya";
                    Security1.Text = "RIZ5@FORTS";
                    //Trader.Text = "iZotov";
                    //Security1.Text = "SPZ5@FORTS";
                    //Security2.Text = "SIZ5@FORTS";
                    //From.Value = new DateTime(2014, 09, 16);
                    Apart.IsChecked = true;
                }
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }
        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
                }
            });
        }
Example #16
0
        private void LoadData()
        {
            _lastPrice = 0m;

            _candles.Clear();
            var id = new SecurityIdGenerator().Split(SecurityId);

            _security = new Security
            {
                Id        = SecurityId,
                PriceStep = PriceStep,
                Board     = ExchangeBoard.GetBoard(id.BoardCode)
            };

            Chart.Reset(new IChartElement[] { _candleElement });

            var storage = new StorageRegistry();

            var maxDays = 1;

            BusyIndicator.IsBusy = true;

            var path = HistoryPath;

            _curCandleNum = 0;

            Task.Factory.StartNew(() =>
            {
                var date = DateTime.MinValue;

                foreach (var tick in storage.GetTickMessageStorage(_security, new LocalMarketDataDrive(path)).Load())
                {
                    if (date != tick.ServerTime.Date)
                    {
                        date = tick.ServerTime.Date;

                        this.GuiAsync(() => BusyIndicator.BusyContent = $"Loading ticks for {date:dd MMM yyyy}...");

                        if (maxDays-- == 0)
                        {
                            break;
                        }
                    }

                    AppendTick(tick);
                }
            })
            .ContinueWith(t =>
            {
                this.GuiAsync(() => BusyIndicator.IsBusy = false);

                for (var i = 0; i < _candles.Count; i += CandlesPacketSize)
                {
                    var candles = _candles.GetRange(i, Math.Min(CandlesPacketSize, _candles.Count - i)).Select(c => c.ToCandle(TFSpan));

                    Chart.Draw(candles.Select(c =>
                    {
                        c.State = CandleStates.Finished;

                        var dict = (IDictionary <IChartElement, object>) new Dictionary <IChartElement, object>
                        {
                            { _candleElement, c }
                        };

                        if (_indicatorElement != null)
                        {
                            dict.Add(_indicatorElement, _indicator.Process((double)c.ClosePrice));
                        }

                        if (_tradeElement != null && _curCandleNum++ % TradeEveryNCandles == 0)
                        {
                            dict.Add(_tradeElement, new MyTrade
                            {
                                Trade = new Trade
                                {
                                    Security       = _security,
                                    Volume         = 1,
                                    Price          = c.LowPrice,
                                    OrderDirection = Sides.Buy,
                                    Time           = c.OpenTime
                                },
                                Order = new Order {
                                    Security = _security, Direction = Sides.Buy
                                }
                            });
                        }

                        return(RefTuple.Create(c.OpenTime, dict));
                    }).ToArray());
                }
            })
            .ContinueWith(t =>
            {
                if (t.Exception != null)
                {
                    Error(t.Exception.Message);
                }

                _dataIsLoaded = true;

                this.GuiAsync(() => BusyIndicator.IsBusy = false);

                Chart.IsAutoRange = false;
                //_area.YAxises.FirstOrDefault().Do(a => a.AutoRange = false);
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }
Example #17
0
        private void OkClick(object sender, RoutedEventArgs e)
        {
            var volumeStep = VolumeStep.Text.To <decimal?>();
            var priceStep  = PriceStep.Text.To <decimal?>();
            var type       = TypeCtrl.SelectedType;

            if (Securities == null)
            {
                if (Code.Text.IsEmpty())
                {
                    ShowError(LocalizedStrings.Str2923);
                    return;
                }

                //if (SecName.Text.IsEmpty())
                //{
                //	ShowError("Не заполнено название инструмента.");
                //	return;
                //}

                if (volumeStep == null)
                {
                    ShowError(LocalizedStrings.Str2924);
                    return;
                }

                if (priceStep == null)
                {
                    ShowError(LocalizedStrings.Str2925);
                    return;
                }

                if (ExchangeCtrl.SelectedBoard == null)
                {
                    ShowError(LocalizedStrings.Str2926);
                    return;
                }

                var security = Security;

                security.Code = Code.Text;

                if (!SecName.Text.IsEmpty())
                {
                    security.Name = SecName.Text;
                }

                security.VolumeStep = volumeStep.Value;
                security.PriceStep  = priceStep.Value;
                security.Board      = ExchangeCtrl.SelectedBoard;
                security.Type       = TypeCtrl.SelectedType;

                if (security.Id.IsEmpty())
                {
                    var id = new SecurityIdGenerator().GenerateId(security.Code, security.Board);

                    var isExist = _entityRegistry.Securities.ReadById(id) != null;

                    if (isExist)
                    {
                        new MessageBoxBuilder()
                        .Text(LocalizedStrings.Str2927Params.Put(id))
                        .Owner(this)
                        .Warning()
                        .Show();

                        return;
                    }

                    security.Id            = id;
                    security.ExtensionInfo = new Dictionary <object, object>();
                }

                _entityRegistry.Securities.Save(security);
            }
            else
            {
                foreach (var security in Securities)
                {
                    if (volumeStep != null)
                    {
                        security.VolumeStep = volumeStep.Value;
                    }

                    if (priceStep != null)
                    {
                        security.PriceStep = priceStep.Value;
                    }

                    if (type != null)
                    {
                        security.Type = type.Value;
                    }

                    _entityRegistry.Securities.Save(security);
                }
            }

            DialogResult = true;
        }
Example #18
0
        private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
        {
            Year.ItemsSource  = Competition.AllYears;
            Year.SelectedItem = Competition.AllYears.Last();

            var ns = typeof(IIndicator).Namespace;

            var rendererTypes = typeof(Chart).Assembly
                                .GetTypes()
                                .Where(t => !t.IsAbstract && typeof(BaseChartIndicatorPainter).IsAssignableFrom(t))
                                .ToDictionary(t => t.Name);

            var indicators = typeof(IIndicator).Assembly
                             .GetTypes()
                             .Where(t => t.Namespace == ns && !t.IsAbstract && typeof(IIndicator).IsAssignableFrom(t))
                             .Select(t => new IndicatorType(t, rendererTypes.TryGetValue(t.Name + "Painter")));

            Chart.IndicatorTypes.AddRange(indicators);

            const string finamSecurities = "finam.csv";

            if (File.Exists(finamSecurities))
            {
                var idGen = new SecurityIdGenerator();

                var securities = File.ReadAllLines(finamSecurities).Select(line =>
                {
                    var cells   = line.SplitByComma();
                    var idParts = idGen.Split(cells[0]);

                    return(new Security
                    {
                        Id = cells[0],
                        Code = idParts.Item1,
                        Board = ExchangeBoard.GetOrCreateBoard(idParts.Item2),
                        ExtensionInfo = new Dictionary <object, object>
                        {
                            { FinamHistorySource.MarketIdField, cells[1].To <long>() },
                            { FinamHistorySource.SecurityIdField, cells[2].To <long>() },
                        }
                    });
                });

                foreach (var security in securities)
                {
                    _securities.Add(security);
                    _securityStorage.Save(security);
                }
            }
            else
            {
                _finamHistorySource.Refresh(_securityStorage, new Security(), s => { }, () => false);

                var securities = _securityStorage.LookupAll().ToArray();

                foreach (var security in securities)
                {
                    _securities.Add(security);
                }

                File.WriteAllLines(finamSecurities, securities.Where(s => !s.Id.Contains(',')).Select(s => "{0},{1},{2}"
                                                                                                      .Put(s.Id, s.ExtensionInfo[FinamHistorySource.MarketIdField], s.ExtensionInfo[FinamHistorySource.SecurityIdField])));
            }

            Trader.Text   = "Bull";
            Security.Text = "SIZ4@FORTS";
            From.Value    = new DateTime(2014, 09, 16);
        }
Example #19
0
        private void Sync_Click(object sender, RoutedEventArgs e)
        {
            if (_token != null)
            {
                StopSync();
                return;
            }

            Sync.Content = LocalizedStrings.Str2890;

            _token = new CancellationTokenSource();

            Task.Factory.StartNew(() =>
            {
                var securityPaths = new List <string>();

                foreach (var dir in DriveCache.Instance.AllDrives
                         .OfType <LocalMarketDataDrive>()
                         .Select(drive => drive.Path)
                         .Distinct())
                {
                    foreach (var letterDir in InteropHelper.GetDirectories(dir))
                    {
                        if (_token.IsCancellationRequested)
                        {
                            break;
                        }

                        var name = Path.GetFileName(letterDir);

                        if (name == null || name.Length != 1)
                        {
                            continue;
                        }

                        securityPaths.AddRange(InteropHelper.GetDirectories(letterDir));
                    }

                    if (_token.IsCancellationRequested)
                    {
                        break;
                    }
                }

                if (_token.IsCancellationRequested)
                {
                    return;
                }

                var iterCount =
                    securityPaths.Count +                                                                            // кол-во проходов по директории для создания инструмента
                    DriveCache.Instance.AllDrives.Count() * (EntityRegistry.Securities.Count + securityPaths.Count); // кол-во сбросов кэша дат

                this.GuiSync(() => Progress.Maximum = iterCount);

                var logSource = ConfigManager.GetService <LogManager>().Application;

                var securityIdGenerator = new SecurityIdGenerator();

                var securities = EntityRegistry.Securities.ToDictionary(s => s.Id, s => new KeyValuePair <Security, bool>(s, true), StringComparer.InvariantCultureIgnoreCase);

                foreach (var securityPath in securityPaths)
                {
                    if (_token.IsCancellationRequested)
                    {
                        break;
                    }

                    var securityId = Path.GetFileName(securityPath).FolderNameToSecurityId();

                    var isNew = false;

                    var security = securities.TryGetValue(securityId).Key;
                    if (security == null)
                    {
                        var firstDataFile =
                            Directory.EnumerateDirectories(securityPath)
                            .SelectMany(d => Directory.EnumerateFiles(d, "*.bin")
                                        .Concat(Directory.EnumerateFiles(d, "*.csv"))
                                        .OrderBy(f => Path.GetExtension(f).CompareIgnoreCase(".bin") ? 0 : 1))
                            .FirstOrDefault();

                        if (firstDataFile != null)
                        {
                            var info = securityIdGenerator.Split(securityId);

                            decimal priceStep;

                            if (Path.GetExtension(firstDataFile).CompareIgnoreCase(".bin"))
                            {
                                try
                                {
                                    priceStep = File.ReadAllBytes(firstDataFile).Range(6, 16).To <decimal>();
                                }
                                catch (Exception ex)
                                {
                                    throw new InvalidOperationException(LocalizedStrings.Str2929Params.Put(firstDataFile), ex);
                                }
                            }
                            else
                            {
                                priceStep = 0.01m;
                            }

                            security = new Security
                            {
                                Id            = securityId,
                                PriceStep     = priceStep,
                                Name          = info.Item1,
                                Code          = info.Item1,
                                Board         = ExchangeBoard.GetOrCreateBoard(info.Item2),
                                ExtensionInfo = new Dictionary <object, object>()
                            };

                            securities.Add(securityId, new KeyValuePair <Security, bool>(security, false));

                            isNew = true;
                        }
                    }

                    this.GuiSync(() =>
                    {
                        Progress.Value++;

                        if (isNew)
                        {
                            Logs.Messages.Add(new LogMessage(logSource, TimeHelper.Now, LogLevels.Info, LocalizedStrings.Str2930Params.Put(security)));
                        }
                    });
                }

                EntityRegistry.Securities.AddRange(securities.Values.Where(p => !p.Value).Select(p => p.Key));

                if (_token.IsCancellationRequested)
                {
                    return;
                }

                var dataTypes = new Dictionary <Type, object>
                {
                    { typeof(ExecutionMessage), ExecutionTypes.Tick },
                    { typeof(ExecutionMessage), ExecutionTypes.OrderLog },
                    { typeof(ExecutionMessage), ExecutionTypes.Order },
                    { typeof(ExecutionMessage), ExecutionTypes.Trade },
                    { typeof(QuoteChangeMessage), null },
                    { typeof(Level1ChangeMessage), null },
                    { typeof(NewsMessage), null }
                };

                var formats = Enumerator.GetValues <StorageFormats>();

                foreach (var drive in DriveCache.Instance.AllDrives)
                {
                    foreach (var security in EntityRegistry.Securities)
                    {
                        foreach (var dataType in dataTypes)
                        {
                            foreach (var format in formats)
                            {
                                if (_token.IsCancellationRequested)
                                {
                                    break;
                                }

                                drive.GetStorageDrive(security.ToSecurityId(), dataType.Key, dataType.Value, format).ClearDatesCache();
                            }
                        }

                        if (_token.IsCancellationRequested)
                        {
                            break;
                        }

                        this.GuiSync(() =>
                        {
                            Progress.Value++;
                            Logs.Messages.Add(new LogMessage(logSource, TimeHelper.Now, LogLevels.Info,
                                                             LocalizedStrings.Str2931Params.Put(security, drive.Path)));
                        });
                    }

                    if (_token.IsCancellationRequested)
                    {
                        break;
                    }
                }
            }, _token.Token)
            .ContinueWithExceptionHandling(this, res =>
            {
                Sync.Content   = LocalizedStrings.Str2932;
                Sync.IsEnabled = true;

                Progress.Value = 0;

                _token = null;
            });
        }
Example #20
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 = Strategy;

            if (strategy.DataPath.IsEmpty() || !Directory.Exists(strategy.DataPath))
            {
                throw new InvalidOperationException(LocalizedStrings.Str3014);
            }

            strategy.Reset();

            OrderGrid.Orders.Clear();
            MyTradeGrid.Trades.Clear();

            _pnlCurve.Clear();
            _unrealizedPnLCurve.Clear();
            _commissionCurve.Clear();
            _posItems.Clear();

            var secGen     = new SecurityIdGenerator();
            var secIdParts = secGen.Split(strategy.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    = strategy.SecurityId,              // sec id has the same name as folder with historical data
                Code  = secCode,
                Board = board,
            };

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

            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;

            var level1Info = new Level1ChangeMessage
            {
                SecurityId = security.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);

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

            // create backtesting connector
            _connector = new HistoryEmulationConnector(
                new[] { security },
                new[] { portfolio })
            {
                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 = false,
                        }
                    }
                },

                UseExternalCandleSource = useCandles,

                HistoryMessageAdapter =
                {
                    StorageRegistry = storageRegistry,

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

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

            //((ILogSource)_connector).LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info;

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

            var candleManager = !useCandles
                                                    ? new CandleManager(new TradeCandleBuilderSourceEx(_connector))
                                                    : new CandleManager(_connector);

            strategy.Volume    = 1;
            strategy.Portfolio = portfolio;
            strategy.Security  = security;
            strategy.Connector = _connector;
            //LogLevel = DebugLogCheckBox.IsChecked == true ? 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.SetChart(_bufferedChart);
            strategy.SetCandleManager(candleManager);

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

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

                //_connector.RegisterMarketDepth(security);
                if (!useCandles)
                {
                    _connector.RegisterTrades(security);
                }

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

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

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

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