/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using QuantConnect.Brokerages.Backtesting; using QuantConnect.Data.Market; using QuantConnect.Interfaces; using QuantConnect.Lean.Engine.Results; using QuantConnect.Logging; using QuantConnect.Orders; using QuantConnect.Util; namespace QuantConnect.Lean.Engine.TransactionHandlers { /// /// This transaction handler is used for processing transactions during backtests /// public class BacktestingTransactionHandler : BrokerageTransactionHandler { // save off a strongly typed version of the brokerage private BacktestingBrokerage _brokerage; private IAlgorithm _algorithm; private Delistings _lastestDelistings; /// /// Gets current time UTC. This is here to facilitate testing /// protected override DateTime CurrentTimeUtc => _algorithm.UtcTime; /// /// Creates a new BacktestingTransactionHandler using the BacktestingBrokerage /// /// The algorithm instance /// The BacktestingBrokerage /// public override void Initialize(IAlgorithm algorithm, IBrokerage brokerage, IResultHandler resultHandler) { if (!(brokerage is BacktestingBrokerage)) { throw new ArgumentException("Brokerage must be of type BacktestingBrokerage for use wth the BacktestingTransactionHandler"); } _brokerage = (BacktestingBrokerage) brokerage; _algorithm = algorithm; base.Initialize(algorithm, brokerage, resultHandler); // non blocking implementation _orderRequestQueue = new BusyCollection(); } /// /// Processes all synchronous events that must take place before the next time loop for the algorithm /// public override void ProcessSynchronousEvents() { // we process pending order requests our selves Run(); base.ProcessSynchronousEvents(); _brokerage.Scan(); // Run our delistings processing, only do this once a slice if (_algorithm.CurrentSlice != null && _algorithm.CurrentSlice.Delistings != _lastestDelistings) { _lastestDelistings = _algorithm.CurrentSlice.Delistings; _brokerage.ProcessDelistings(_algorithm.CurrentSlice.Delistings); } } /// /// Processes asynchronous events on the transaction handler's thread /// public override void ProcessAsynchronousEvents() { base.ProcessAsynchronousEvents(); _brokerage.Scan(); } /// /// For backtesting we will submit the order ourselves /// /// The expecting to be submitted protected override void WaitForOrderSubmission(OrderTicket ticket) { // we submit the order request our selves Run(); if (!ticket.OrderSet.WaitOne(0)) { // this could happen if there was some error handling the order // and it was not set Log.Error("BacktestingTransactionHandler.WaitForOrderSubmission(): " + $"The order request (Id={ticket.OrderId}) was not submitted. " + "See the OrderRequest.Response for more information"); } } /// /// For backtesting order requests will be processed by the algorithm thread /// sequentially at and /// protected override void InitializeTransactionThread() { // nop } } }