Exemplo n.º 1
0
        public OhlcBacktesterTests()
        {
            _robotParametersMock = new Mock <IRobotParameters>();

            var symbols = new List <ISymbol>
            {
                new OhlcSymbol(new Mock <IBars>().Object)
                {
                    Name = "Main"
                },
                new OhlcSymbol(new Mock <IBars>().Object)
                {
                    Name = "First"
                },
                new OhlcSymbol(new Mock <IBars>().Object)
                {
                    Name = "Second"
                },
                new OhlcSymbol(new Mock <IBars>().Object)
                {
                    Name = "Third"
                },
            };

            var startTime = DateTimeOffset.Now.AddDays(-30);
            var endTime   = DateTimeOffset.Now;

            var symbolsData = new List <ISymbolBacktestData>();

            var random = new Random(0);

            symbols.ForEach(iSymbol =>
            {
                var symbolData = new SymbolBacktestData(iSymbol, GetData(100 * random.Next(1, 5), startTime, endTime));

                symbolsData.Add(symbolData);
            });

            _backtestSettings = new BacktestSettings(startTime, endTime);

            _backtester = new OhlcBacktester {
                Interval = TimeSpan.FromHours(1)
            };

            _robotParametersMock.SetupProperty(robotParameters => robotParameters.Symbols, symbols);
            _robotParametersMock.SetupProperty(robotParameters => robotParameters.SymbolsBacktestData, symbolsData);
            _robotParametersMock.SetupProperty(robotParameters => robotParameters.Backtester, _backtester);
            _robotParametersMock.SetupProperty(robotParameters => robotParameters.BacktestSettings, _backtestSettings);
            _robotParametersMock.SetupProperty(robotParameters => robotParameters.Server, new Server());
            _robotParametersMock.SetupProperty(robotParameters => robotParameters.Account, new Mock <IAccount>().Object);
            _robotParametersMock.SetupProperty(robotParameters => robotParameters.Mode, Mode.Backtest);

            var tradeEngine = new BacktestTradeEngine(_robotParametersMock.Object.Server, _robotParametersMock.Object.Account);

            _robotParametersMock.SetupProperty(settings => settings.TradeEngine, tradeEngine);

            _robotMock = new Mock <Robot>();
        }
Exemplo n.º 2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="BacktestTimerProvider"/> class.
        /// </summary>
        /// <param name="loggerFactory">Used to create output.</param>
        /// <param name="settings">Provides startDate, endDate and outputFolder.</param>
        public BacktestTimerProvider(ILoggerFactory loggerFactory, BacktestSettings settings)
            : base(loggerFactory)
        {
            _logger            = loggerFactory.CreateLogger(GetType());
            _backtestOrders    = new List <OrderUpdate>();
            _stateSwitchEvents = new List <StateSwitchEvent>();

            BeginTime = DateTimeOffset.FromUnixTimeMilliseconds(
                BacktestDaemonService.Instance.State.BeginTimeStamp);
            _currentTime    = BeginTime;
            _lastCandleOpen = _currentTime;

            EndTime = DateTimeOffset.FromUnixTimeMilliseconds(
                BacktestDaemonService.Instance.State.EndTimeStamp);
            _outputFolder = settings.OutputFolder;
        }
Exemplo n.º 3
0
 /// <summary>
 /// Runs backtest (in separate thread) for all Selections and numeric Parameters
 /// </summary>
 /// <param name="settings">Settings to use for backtest</param>
 public void StartBacktest(BacktestSettings settings)
 {
     if (!_isBusy && State == SignalState.Backtesting)
     {
         BacktestSettings = settings ?? new BacktestSettings();
         var thread = new System.Threading.Thread(() => Backtest())
         {
             Name         = "Signal Backtest",
             IsBackground = true
         };
         thread.Start();
     }
     else
     {
         if (State != SignalState.Backtesting)
         {
             Alert("Can't start backtest: signal is not in a backtest mode");
         }
         else if (_isBusy)
         {
             Alert("Can't start backtest: signal is busy");
         }
     }
 }
Exemplo n.º 4
0
        /// <summary>
        /// Runs backtest for single instrument and a set of parameter values
        /// </summary>
        /// <param name="instruments">Instruments to be backtested</param>
        /// <param name="parameters">Set of parameter values to use for backtest</param>
        /// <returns>List of generated trades</returns>
        protected override List <TradeSignal> BacktestSlotItem(IEnumerable <Selection> instruments,
                                                               IEnumerable <object> parameters)
        {
            // Get data for all provided instruments
            var data = new Dictionary <Selection, List <Bar> >(instruments.Count());

            if (BacktestSettings == null)
            {
                BacktestSettings = new BacktestSettings();
            }

            if (BacktestSettings?.BarData != null && BacktestSettings.BarData.Any()) //provided with backtest settings
            {
                foreach (var item in instruments)
                {
                    var bars = BacktestSettings.BarData
                               .FirstOrDefault(b => b.Key.Symbol == item.Symbol &&
                                               b.Key.TimeFactor == item.TimeFactor &&
                                               b.Key.Timeframe == item.Timeframe).Value;
                    if (bars != null && bars.Count > 0)
                    {
                        data.Add(item, bars);
                    }
                }
            }
            else //need to request from data provider
            {
                foreach (var item in instruments)
                {
                    var btInstrument = (Selection)item.Clone();
                    if (BacktestSettings.BarsBack > 0)
                    {
                        btInstrument.BarCount = BacktestSettings.BarsBack;
                    }
                    if (BacktestSettings.StartDate.Year > 2000)
                    {
                        btInstrument.From = BacktestSettings.StartDate;
                    }
                    if (BacktestSettings.EndDate > BacktestSettings.StartDate)
                    {
                        btInstrument.To = BacktestSettings.EndDate;
                    }
                    var bars = DataProvider.GetBars(btInstrument);
                    if (bars != null && bars.Count > 0)
                    {
                        data.Add(btInstrument, bars);
                    }
                }
            }

            int batchSize = GetBacktestBatchSize(parameters);

            if (data.Count == 0 || batchSize < 1)
            {
                return(new List <TradeSignal>(0));
            }

            // Scan all data collections
            var result  = new List <TradeSignal>();
            var indices = data.ToDictionary(k => k.Key, v => 0);

            while (true)
            {
                // Get instrument with oldest/earliest data
                var time = DateTime.MaxValue;
                foreach (var item in data)
                {
                    var idx = indices[item.Key];
                    if (idx >= 0 && idx < item.Value.Count && item.Value[idx].Date < time)
                    {
                        time = item.Value[idx].Date;
                    }
                }

                if (time == DateTime.MaxValue)
                {
                    break;
                }

                var selectionsToUse = new List <Selection>();
                foreach (var item in data)
                {
                    var idx = indices[item.Key];
                    if (idx >= 0 && idx < item.Value.Count && item.Value[idx].Date == time)
                    {
                        selectionsToUse.Add(item.Key);
                    }
                }

                // Get necessary data frame to scan
                var dataFrames = new Dictionary <Selection, IEnumerable <Bar> >(selectionsToUse.Count);
                foreach (var item in data)
                {
                    if (selectionsToUse.Contains(item.Key))
                    {
                        dataFrames.Add(item.Key, item.Value.GetRange(indices[item.Key], batchSize));
                        indices[item.Key]++;
                    }
                }

                // Evaluate current batch
                if (dataFrames.Count > 0)
                {
                    var trades = Evaluate(dataFrames, parameters);

                    var barData       = dataFrames.Keys.FirstOrDefault();
                    var barToProccess = dataFrames.Values.FirstOrDefault()?.FirstOrDefault();
                    SimulationBroker.ProcessBar(barData?.Symbol, barToProccess);

                    foreach (var account in BrokerAccounts)
                    {
                        foreach (var orderInfo in GenerateOrderParams(trades))
                        {
                            PlaceOrder(orderInfo, account);
                        }
                    }

                    if (trades != null && trades.Count > 0)
                    {
                        result.AddRange(trades);
                    }
                }

                // Break if backtest has been aborted
                if (State != SignalState.Backtesting && State != SignalState.BacktestingPaused)
                {
                    break;
                }
            }

            return(result);
        }
Exemplo n.º 5
0
        private List <TradeSignal> Evaluate(Dictionary <Selection, IEnumerable <Bar> > marketData,
                                            IEnumerable <object> parameterItem,
                                            Selection triggerInstrument = null,
                                            IEnumerable <Tick> ticks    = null)
        {
            /* Evaluate supplied data bars using provided parameters
             * and return a collection of trades on successful evaluation
             * Hint: you can pass these bars to your IndicatorBase instance in its Calculate() method
             * and you can use current parameter values as that IndicatorBase parameters */

            var dataTickframes = marketData.Keys.Where(p => p.Timeframe == Timeframe.Tick);
            Dictionary <Selection, IEnumerable <Bar> > trigInstrData = new Dictionary <Selection, IEnumerable <Bar> >();

            #region Internal Backtest

            if (_execTradesParam.EvalCount % 10 == 0 && _internalBacktest == true)
            {
                _internalBacktest = false;

                var backtestSet = new BacktestSettings
                {
                    InitialBalance   = 10000,
                    TransactionCosts = 0,
                    Risk             = 0,
                    BarsBack         = 5,
                };

                Alert("----------------------------------");
                Alert("START Internal Backtest");
                Alert("----------------------------------");

                var res        = Backtest(false);
                var tradeCount = res?[0].Summaries?.Select(i => i.NumberOfTradeSignals).DefaultIfEmpty(0)?.Sum() ?? 0;
                _internalBacktest = true;

                Alert("Evaluate(): Internal Backtest Trades: " + tradeCount);
                Alert("----------------------------------");
                Alert("STOP Internal Backtest");
                Alert("----------------------------------");
            }

            #endregion

            #region Prepare marketdata and pass it to trading logic for processing

            if (StartMethod == StartMethod.NewBar && triggerInstrument != null)
            {
                trigInstrData.Clear();
                trigInstrData.Add(triggerInstrument, DataProvider.GetBars(triggerInstrument));
            }

            if (State == SignalState.Backtesting) // && dataTickframes.Count() > 0)
            {
                var timer = new MicroStopwatch();
                timer.Start();

                var trades = new List <TradeSignal>();
                trades = BacktestPriceSegmentation.BacktestPriceSegmentProcessor(this, marketData, _execTradesParam,
                                                                                 backtestPriceConst, Calculate, trigInstrData, ticks);

                timer.Stop();
                Alert($"Init instrumentData: ExecutionTime = {timer.ElapsedMicroseconds:#,0} µs");

                return(trades);
            }

            try
            {
                return(Calculate(marketData));
            }

            catch (Exception e)
            {
                Alert($"Evaluate(): Failed to Run on Usercode: {e.Message}");
                return(new List <TradeSignal>());
            }

            #endregion
        }