/// <summary> /// Creates a new BrokerageTransactionHandler to process orders using the specified brokerage implementation /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="brokerage">The brokerage implementation to process orders and fire fill events</param> /// <param name="resultHandler"></param> public virtual void Initialize(IAlgorithm algorithm, IBrokerage brokerage, IResultHandler resultHandler) { if (brokerage == null) { throw new ArgumentNullException("brokerage"); } // we don't need to do this today because we just initialized/synced _resultHandler = resultHandler; _syncedLiveBrokerageCashToday = true; _lastSyncTimeTicks = DateTime.Now.Ticks; _brokerage = brokerage; _brokerage.OrderStatusChanged += (sender, fill) => { HandleOrderEvent(fill); }; _brokerage.SecurityHoldingUpdated += (sender, holding) => { HandleSecurityHoldingUpdated(holding); }; _brokerage.AccountChanged += (sender, account) => { HandleAccountChanged(account); }; IsActive = true; _algorithm = algorithm; }
protected override void DisposeBrokerage(IBrokerage brokerage) { if (!_manualGatewayControl && brokerage != null) { brokerage.Disconnect(); } }
public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice) { // FXCM Buy Limit orders will be rejected if the limit price is above the market price // FXCM Sell Limit orders will be rejected if the limit price is below the market price var limit = (LimitOrder)order; var previousLimit = limit.LimitPrice; var fxcmBrokerage = (FxcmBrokerage)brokerage; var quotes = fxcmBrokerage.GetBidAndAsk(new List <string> { fxcmBrokerage.ConvertSymbolToFxcmSymbol(order.Symbol) }); if (order.Quantity > 0) { // for limit buys we need to increase the limit price // buy limit price must be at bid price or below var bidPrice = Convert.ToDecimal(quotes.Single().BidPrice); Log.Trace("FxcmLimitOrderTestParameters.ModifyOrderToFill(): Bid: " + bidPrice); limit.LimitPrice = Math.Max(previousLimit, Math.Min(bidPrice, limit.LimitPrice * 2)); } else { // for limit sells we need to decrease the limit price // sell limit price must be at ask price or above var askPrice = Convert.ToDecimal(quotes.Single().AskPrice); Log.Trace("FxcmLimitOrderTestParameters.ModifyOrderToFill(): Ask: " + askPrice); limit.LimitPrice = Math.Min(previousLimit, Math.Max(askPrice, limit.LimitPrice / 2)); } return(limit.LimitPrice != previousLimit); }
/// <summary> /// We simulate activity of market makers on expiration. Trying to get profit close to expiration dates in deep ITM positions. /// This version of the simulator exercises short positions in full. /// </summary> public void SimulateMarketConditions(IBrokerage brokerage, IAlgorithm algorithm) { if (!IsReadyToSimulate(algorithm)) { return; } var backtestingBrokerage = (BacktestingBrokerage)brokerage; Func <Symbol, bool> deepITM = symbol => { var undelyingPrice = algorithm.Securities[symbol.Underlying].Close; var result = symbol.ID.OptionRight == OptionRight.Call ? (undelyingPrice - symbol.ID.StrikePrice) / undelyingPrice > _deepITM : (symbol.ID.StrikePrice - undelyingPrice) / undelyingPrice > _deepITM; return(result); }; algorithm.Securities // we take only options that expire soon .Where(x => x.Key.ID.SecurityType == SecurityType.Option && x.Key.ID.Date - algorithm.UtcTime <= _priorExpiration) // we look into short positions only (short for user means long for us) .Where(x => x.Value.Holdings.IsShort) // we take only deep ITM strikes .Where(x => deepITM(x.Key)) // we estimate P/L .Where(x => EstimateArbitragePnL((Option)x.Value, (OptionHolding)x.Value.Holdings, algorithm.Securities[x.Value.Symbol.Underlying]) > 0.0m) .ToList() // we exercise options with positive expected P/L (over basic sale of option) .ForEach(x => backtestingBrokerage.ActivateOptionAssignment((Option)x.Value, (int)((OptionHolding)x.Value.Holdings).AbsoluteQuantity)); }
protected override void DisposeBrokerage(IBrokerage brokerage) { if (brokerage != null) { brokerage.Disconnect(); } }
public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice) { // FXCM Buy StopMarket orders will be rejected if the stop price is below the market price // FXCM Sell StopMarket orders will be rejected if the stop price is above the market price var stop = (StopMarketOrder)order; var previousStop = stop.StopPrice; var fxcmBrokerage = (FxcmBrokerage)brokerage; var quotes = fxcmBrokerage.GetBidAndAsk(new List <string> { fxcmBrokerage.ConvertSymbolToFxcmSymbol(order.Symbol) }); if (order.Quantity > 0) { // for stop buys we need to decrease the stop price // buy stop price must be strictly above ask price var askPrice = Convert.ToDecimal(quotes.Single().AskPrice); Log.Trace("FxcmStopMarketOrderTestParameters.ModifyOrderToFill(): Ask: " + askPrice); stop.StopPrice = Math.Min(previousStop, Math.Max(askPrice, stop.StopPrice / 2) + 0.00001m); } else { // for stop sells we need to increase the stop price // sell stop price must be strictly below bid price var bidPrice = Convert.ToDecimal(quotes.Single().BidPrice); Log.Trace("FxcmStopMarketOrderTestParameters.ModifyOrderToFill(): Bid: " + bidPrice); stop.StopPrice = Math.Max(previousStop, Math.Min(bidPrice, stop.StopPrice * 2) - 0.00001m); } return(stop.StopPrice != previousStop); }
/// <summary> /// Get an instance of the data feed handler we're requesting for this work. /// </summary> /// <param name="algorithm">User algorithm to scan for securities</param> /// <param name="job">Algorithm Node Packet</param> /// <param name="brokerage">Brokerage instance to avoid access token duplication</param> /// <returns>Class matching IDataFeed Interface</returns> private static IDataFeed GetDataFeedHandler(IAlgorithm algorithm, IBrokerage brokerage, AlgorithmNodePacket job) { var df = default(IDataFeed); switch (job.DataEndpoint) { //default: ////Backtesting: case DataFeedEndpoint.Backtesting: df = new BacktestingDataFeed(algorithm, (BacktestNodePacket)job); Log.Trace("Engine.GetDataFeedHandler(): Selected Backtesting Datafeed"); break; //Operation from local files: case DataFeedEndpoint.FileSystem: df = new FileSystemDataFeed(algorithm, (BacktestNodePacket)job); Log.Trace("Engine.GetDataFeedHandler(): Selected FileSystem Datafeed"); break; //Tradier Data Source: case DataFeedEndpoint.Tradier: df = new TradierDataFeed(algorithm, brokerage, (LiveNodePacket)job); Log.Trace("Engine.GetDataFeedHandler(): Selected Tradier Datafeed"); break; } return(df); }
public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice) { // FXCM Buy Limit orders will be rejected if the limit price is above the market price // FXCM Sell Limit orders will be rejected if the limit price is below the market price var limit = (LimitOrder)order; var previousLimit = limit.LimitPrice; var fxcmBrokerage = (FxcmBrokerage)brokerage; var quotes = fxcmBrokerage.GetBidAndAsk(new List<string> { new FxcmSymbolMapper().GetBrokerageSymbol(order.Symbol) }); if (order.Quantity > 0) { // for limit buys we need to increase the limit price // buy limit price must be at bid price or below var bidPrice = Convert.ToDecimal(quotes.Single().BidPrice); Log.Trace("FxcmLimitOrderTestParameters.ModifyOrderToFill(): Bid: " + bidPrice); limit.LimitPrice = Math.Max(previousLimit, Math.Min(bidPrice, limit.LimitPrice * 2)); } else { // for limit sells we need to decrease the limit price // sell limit price must be at ask price or above var askPrice = Convert.ToDecimal(quotes.Single().AskPrice); Log.Trace("FxcmLimitOrderTestParameters.ModifyOrderToFill(): Ask: " + askPrice); limit.LimitPrice = Math.Min(previousLimit, Math.Max(askPrice, limit.LimitPrice / 2)); } return limit.LimitPrice != previousLimit; }
public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice) { var stop = (StopLimitOrder) order; var previousStop = stop.StopPrice; if (order.Quantity > 0) { // for stop buys we need to decrease the stop price stop.StopPrice = Math.Min(stop.StopPrice, Math.Max(stop.StopPrice/2, Math.Round(lastMarketPrice, 2, MidpointRounding.AwayFromZero))); //change behaviour for forex type unit tests if(order.SecurityType == SecurityType.Forex) { stop.StopPrice = Math.Min(stop.StopPrice, Math.Max(stop.StopPrice / 2, Math.Round(lastMarketPrice, 4, MidpointRounding.AwayFromZero))); } } else { // for stop sells we need to increase the stop price stop.StopPrice = Math.Max(stop.StopPrice, Math.Min(stop.StopPrice * 2, Math.Round(lastMarketPrice, 2, MidpointRounding.AwayFromZero))); //change behaviour for forex type unit tests if (order.SecurityType == SecurityType.Forex) { stop.StopPrice = Math.Max(stop.StopPrice, Math.Min(stop.StopPrice * 2, Math.Round(lastMarketPrice, 4, MidpointRounding.AwayFromZero))); } } stop.LimitPrice = stop.StopPrice; return stop.StopPrice != previousStop; }
public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice) { var stop = (StopLimitOrder)order; var previousStop = stop.StopPrice; if (order.Quantity > 0) { // for stop buys we need to decrease the stop price stop.StopPrice = Math.Min(stop.StopPrice, Math.Max(stop.StopPrice / 2, Math.Round(lastMarketPrice, 2, MidpointRounding.AwayFromZero))); //change behaviour for forex type unit tests if (order.SecurityType == SecurityType.Forex || order.SecurityType == SecurityType.Crypto) { stop.StopPrice = Math.Min(stop.StopPrice, Math.Max(stop.StopPrice / 2, Math.Round(lastMarketPrice, 4, MidpointRounding.AwayFromZero))); } } else { // for stop sells we need to increase the stop price stop.StopPrice = Math.Max(stop.StopPrice, Math.Min(stop.StopPrice * 2, Math.Round(lastMarketPrice, 2, MidpointRounding.AwayFromZero))); //change behaviour for forex type unit tests if (order.SecurityType == SecurityType.Forex || order.SecurityType == SecurityType.Crypto) { stop.StopPrice = Math.Max(stop.StopPrice, Math.Min(stop.StopPrice * 2, Math.Round(lastMarketPrice, 4, MidpointRounding.AwayFromZero))); } } stop.LimitPrice = stop.StopPrice; return(stop.StopPrice != previousStop); }
/// <summary> /// Creates a new BrokerageTransactionHandler to process orders using the specified brokerage implementation /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="brokerage">The brokerage implementation to process orders and fire fill events</param> public BrokerageTransactionHandler(IAlgorithm algorithm, IBrokerage brokerage) { if (brokerage == null) { throw new ArgumentNullException("brokerage"); } _brokerage = brokerage; _brokerage.OrderStatusChanged += (sender, fill) => { HandleOrderEvent(fill); }; _brokerage.SecurityHoldingUpdated += (sender, holding) => { HandleSecurityHoldingUpdated(holding); }; // maintain proper portfolio cash balance _brokerage.AccountChanged += (sender, account) => { HandleAccountChanged(account); }; IsActive = true; _algorithm = algorithm; // also save off the various order data structures locally _orders = algorithm.Transactions.Orders; _orderEvents = algorithm.Transactions.OrderEvents; _orderQueue = algorithm.Transactions.OrderQueue; }
public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice) { // FXCM Buy StopMarket orders will be rejected if the stop price is below the market price // FXCM Sell StopMarket orders will be rejected if the stop price is above the market price var stop = (StopMarketOrder)order; var previousStop = stop.StopPrice; var fxcmBrokerage = (FxcmBrokerage)brokerage; var quotes = fxcmBrokerage.GetBidAndAsk(new List<string> { new FxcmSymbolMapper().GetBrokerageSymbol(order.Symbol) }); if (order.Quantity > 0) { // for stop buys we need to decrease the stop price // buy stop price must be strictly above ask price var askPrice = Convert.ToDecimal(quotes.Single().AskPrice); Log.Trace("FxcmStopMarketOrderTestParameters.ModifyOrderToFill(): Ask: " + askPrice); stop.StopPrice = Math.Min(previousStop, Math.Max(askPrice, stop.StopPrice / 2) + 0.00001m); } else { // for stop sells we need to increase the stop price // sell stop price must be strictly below bid price var bidPrice = Convert.ToDecimal(quotes.Single().BidPrice); Log.Trace("FxcmStopMarketOrderTestParameters.ModifyOrderToFill(): Bid: " + bidPrice); stop.StopPrice = Math.Max(previousStop, Math.Min(bidPrice, stop.StopPrice * 2) - 0.00001m); } return stop.StopPrice != previousStop; }
/// <summary> /// Creates a new BrokerageTransactionHandler to process orders using the specified brokerage implementation /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="brokerage">The brokerage implementation to process orders and fire fill events</param> public BrokerageTransactionHandler(IAlgorithm algorithm, IBrokerage brokerage) { if (brokerage == null) { throw new ArgumentNullException("brokerage"); } _brokerage = brokerage; _brokerage.OrderStatusChanged += (sender, fill) => { HandleOrderEvent(fill); }; // maintain proper portfolio cash balance _brokerage.AccountChanged += (sender, account) => { //_algorithm.Portfolio.SetCash(account.CashBalance); // how close are we? decimal delta = _algorithm.Portfolio.Cash - account.CashBalance; Log.Trace(string.Format("BrokerageTransactionHandler.AccountChanged(): Algo Cash: {0} Brokerage Cash: {1} Delta: {2}", algorithm.Portfolio.Cash, account.CashBalance, delta)); }; IsActive = true; _algorithm = algorithm; // also save off the various order data structures locally _orders = algorithm.Transactions.Orders; _orderEvents = algorithm.Transactions.OrderEvents; _orderQueue = algorithm.Transactions.OrderQueue; }
/// <summary> /// Setup the algorithm cash, dates and portfolio as desired. /// </summary> /// <param name="algorithm">Algorithm instance</param> /// <param name="brokerage">Output new instance of the brokerage</param> /// <param name="job">Algorithm job/task we're running</param> /// <returns>Bool setup success</returns> public bool Setup(IAlgorithm algorithm, out IBrokerage brokerage, AlgorithmNodePacket job) { var initializeComplete = false; brokerage = new PaperBrokerage(algorithm); //For the console, let it set itself up primarily: try { algorithm.Initialize(); } catch (Exception err) { Log.Error("PaperTradingSetupHandler.Setup(): " + err.Message); Errors.Add("Error setting up the paper trading algorithm; " + err.Message); } // Starting capital is portfolio cash: StartingCapital = algorithm.Portfolio.Cash; if (Errors.Count == 0) { initializeComplete = true; } return(initializeComplete); }
/// <summary> /// Setup the algorithm cash, dates and portfolio as desired. /// </summary> /// <param name="algorithm">Existing algorithm instance</param> /// <param name="brokerage">New brokerage instance</param> /// <param name="baseJob">Backtesting job</param> /// <param name="resultHandler">The configured result handler</param> /// <param name="transactionHandler">The configuration transaction handler</param> /// <param name="realTimeHandler">The configured real time handler</param> /// <returns>Boolean true on successfully setting up the console.</returns> public bool Setup(IAlgorithm algorithm, IBrokerage brokerage, AlgorithmNodePacket baseJob, IResultHandler resultHandler, ITransactionHandler transactionHandler, IRealTimeHandler realTimeHandler) { var initializeComplete = false; try { //Set common variables for console programs: if (baseJob.Type == PacketType.BacktestNode) { var backtestJob = baseJob as BacktestNodePacket; //Set our default markets algorithm.SetDefaultMarkets(BacktestingBrokerageFactory.DefaultMarketMap.ToDictionary()); algorithm.SetMaximumOrders(int.MaxValue); // set our parameters algorithm.SetParameters(baseJob.Parameters); algorithm.SetLiveMode(false); //Set the source impl for the event scheduling algorithm.Schedule.SetEventSchedule(realTimeHandler); //Setup Base Algorithm: algorithm.Initialize(); //Set the time frontier of the algorithm algorithm.SetDateTime(algorithm.StartDate.ConvertToUtc(algorithm.TimeZone)); //Construct the backtest job packet: backtestJob.PeriodStart = algorithm.StartDate; backtestJob.PeriodFinish = algorithm.EndDate; backtestJob.BacktestId = "LOCALHOST"; backtestJob.UserId = 1001; backtestJob.Type = PacketType.BacktestNode; //Backtest Specific Parameters: StartingDate = backtestJob.PeriodStart; StartingPortfolioValue = algorithm.Portfolio.Cash; } else { throw new Exception("The ConsoleSetupHandler is for backtests only. Use the BrokerageSetupHandler."); } } catch (Exception err) { Log.Error(err); Errors.Add("Failed to initialize algorithm: Initialize(): " + err.Message); } if (Errors.Count == 0) { initializeComplete = true; } // set the transaction and settlement models based on the brokerage properties algorithm.UpdateModels(algorithm.BrokerageModel); algorithm.Transactions.SetOrderProcessor(transactionHandler); algorithm.PostInitialize(); return(initializeComplete); }
/******************************************************** * PUBLIC CONSTRUCTOR *********************************************************/ /// <summary> /// Initialize the realtime event handler with all information required for triggering daily events. /// </summary> public LiveTradingRealTimeHandler(IAlgorithm algorithm, IDataFeed feed, IResultHandler results, IBrokerage brokerage, AlgorithmNodePacket job) { //Initialize: _algorithm = algorithm; _events = new List<RealTimeEvent>(); _today = new Dictionary<SecurityType, MarketToday>(); _feed = feed; _results = results; }
/// <summary> /// Setup the algorithm cash, dates and portfolio as desired. /// </summary> /// <param name="algorithm">Existing algorithm instance</param> /// <param name="brokerage">New brokerage instance</param> /// <param name="baseJob">Backtesting job</param> /// <param name="resultHandler">The configured result handler</param> /// <param name="transactionHandler">The configuration transaction handler</param> /// <returns>Boolean true on successfully setting up the console.</returns> public bool Setup(IAlgorithm algorithm, out IBrokerage brokerage, AlgorithmNodePacket baseJob, IResultHandler resultHandler, ITransactionHandler transactionHandler) { var initializeComplete = false; try { //Set common variables for console programs: if (baseJob.Type == PacketType.BacktestNode) { var backtestJob = baseJob as BacktestNodePacket; //Set the limits on the algorithm assets (for local no limits) algorithm.SetAssetLimits(999, 999, 999); algorithm.SetMaximumOrders(int.MaxValue); //Setup Base Algorithm: algorithm.Initialize(); //Add currency data feeds that weren't explicity added in Initialize algorithm.Portfolio.CashBook.EnsureCurrencyDataFeeds(algorithm.Securities, algorithm.SubscriptionManager, SecurityExchangeHoursProvider.FromDataFolder()); //Construct the backtest job packet: backtestJob.PeriodStart = algorithm.StartDate; backtestJob.PeriodFinish = algorithm.EndDate; backtestJob.BacktestId = "LOCALHOST"; backtestJob.UserId = 1001; backtestJob.Type = PacketType.BacktestNode; //Backtest Specific Parameters: StartingDate = backtestJob.PeriodStart; StartingPortfolioValue = algorithm.Portfolio.Cash; } else { throw new Exception("The ConsoleSetupHandler is for backtests only. Use the BrokerageSetupHandler."); } } catch (Exception err) { Log.Error("ConsoleSetupHandler().Setup(): " + err.Message); Errors.Add("Failed to initialize algorithm: Initialize(): " + err.Message); } if (Errors.Count == 0) { initializeComplete = true; } // we need to do this after algorithm initialization brokerage = new BacktestingBrokerage(algorithm); // set the transaction models base on the requested brokerage properties SetupHandler.UpdateTransactionModels(algorithm, algorithm.BrokerageModel); algorithm.Transactions.SetOrderProcessor(transactionHandler); return(initializeComplete); }
public void Setup() { _algorithm = new QCAlgorithm(); _transactionHandler = new BrokerageTransactionHandler(); _resultHandler = new NonDequeingTestResultsHandler(); _brokerage = new TestBrokerage(); _brokerageSetupHandler = new TestableBrokerageSetupHandler(); }
/// <summary> /// Setup the algorithm cash, dates and portfolio as desired. /// </summary> /// <param name="algorithm">Existing algorithm instance</param> /// <param name="brokerage">New brokerage instance</param> /// <param name="baseJob">Backtesting job</param> /// <param name="resultHandler">The configured result handler</param> /// <param name="transactionHandler">The configuration transaction handler</param> /// <param name="realTimeHandler">The configured real time handler</param> /// <returns>Boolean true on successfully setting up the console.</returns> public bool Setup(IAlgorithm algorithm, IBrokerage brokerage, AlgorithmNodePacket baseJob, IResultHandler resultHandler, ITransactionHandler transactionHandler, IRealTimeHandler realTimeHandler) { var initializeComplete = false; try { //Set common variables for console programs: if (baseJob.Type == PacketType.BacktestNode) { var backtestJob = baseJob as BacktestNodePacket; algorithm.SetMaximumOrders(int.MaxValue); // set our parameters algorithm.SetParameters(baseJob.Parameters); algorithm.SetLiveMode(false); algorithm.SetAvailableDataTypes(GetConfiguredDataFeeds()); //Set the source impl for the event scheduling algorithm.Schedule.SetEventSchedule(realTimeHandler); //Setup Base Algorithm: algorithm.Initialize(); //Set the time frontier of the algorithm algorithm.SetDateTime(algorithm.StartDate.ConvertToUtc(algorithm.TimeZone)); //Construct the backtest job packet: backtestJob.PeriodStart = algorithm.StartDate; backtestJob.PeriodFinish = algorithm.EndDate; backtestJob.BacktestId = algorithm.GetType().Name; backtestJob.Type = PacketType.BacktestNode; backtestJob.UserId = baseJob.UserId; backtestJob.Channel = baseJob.Channel; //Backtest Specific Parameters: StartingDate = backtestJob.PeriodStart; StartingPortfolioValue = algorithm.Portfolio.Cash; } else { throw new Exception("The ConsoleSetupHandler is for backtests only. Use the BrokerageSetupHandler."); } } catch (Exception err) { Log.Error(err); Errors.Add("Failed to initialize algorithm: Initialize(): " + err); } if (Errors.Count == 0) { initializeComplete = true; } algorithm.Transactions.SetOrderProcessor(transactionHandler); algorithm.PostInitialize(); return(initializeComplete); }
/// <summary> /// Setup the algorithm cash, dates and portfolio as desired. /// </summary> /// <param name="algorithm">Algorithm instance</param> /// <param name="brokerage">Output new instance of the brokerage</param> /// <param name="job">Algorithm job/task we're running</param> /// <returns>Bool setup success</returns> public bool Setup(IAlgorithm algorithm, out IBrokerage brokerage, AlgorithmNodePacket job) { var initializeComplete = false; var liveJob = job as LiveNodePacket; brokerage = new PaperBrokerage(algorithm); try { //Algorithm is live, not backtesting: algorithm.SetLiveMode(true); //Set the live trading level asset/ram allocation limits. //Protects algorithm from linux killing the job by excess memory: switch (job.ServerType) { case ServerType.Server1024: algorithm.SetAssetLimits(100, 20, 10); break; case ServerType.Server2048: algorithm.SetAssetLimits(400, 50, 30); break; default: //512 algorithm.SetAssetLimits(50, 10, 5); break; } //Initialize the algorithm algorithm.Initialize(); //Add currency data feeds that weren't explicity added in Initialize algorithm.Portfolio.CashBook.EnsureCurrencyDataFeeds(algorithm.SubscriptionManager, algorithm.Securities); //Try and use the live job packet cash if exists, otherwise resort to the user algo cash: if (liveJob != null && liveJob.BrokerageData.ContainsKey("project-paper-equity")) { var consistentCash = Convert.ToDecimal(liveJob.BrokerageData["project-paper-equity"]); algorithm.SetCash(consistentCash); } } catch (Exception err) { Log.Error("PaperTradingSetupHandler.Setup(): " + err.Message); Errors.Add("Error setting up the paper trading algorithm; " + err.Message); } // Starting capital is portfolio cash: StartingCapital = algorithm.Portfolio.Cash; if (Errors.Count == 0) { initializeComplete = true; } return(initializeComplete); }
public void Setup() { _algorithm = new QCAlgorithm(); _algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(_algorithm)); _transactionHandler = new BrokerageTransactionHandler(); _resultHandler = new NonDequeingTestResultsHandler(); _brokerage = new TestBrokerage(); _brokerageSetupHandler = new TestableBrokerageSetupHandler(); }
/// <summary> /// Creates a new BacktestingTransactionHandler using the BacktestingBrokerage /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="brokerage">The BacktestingBrokerage</param> /// <param name="resultHandler"></param> 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; base.Initialize(algorithm, brokerage, resultHandler); }
/// <summary> /// Creates a new BacktestingTransactionHandler using the BacktestingBrokerage /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="brokerage">The BacktestingBrokerage</param> /// <param name="resultHandler"></param> 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; base.Initialize(algorithm, brokerage, resultHandler); }
private bool LoadCashBalance(LiveNodePacket liveJob, IBrokerage brokerage, IAlgorithm algorithm) { Log.Trace("BrokerageSetupHandler.Setup(): Fetching cash balance from brokerage..."); try { // set the algorithm's cash balance for each currency var cashBalance = brokerage.GetCashBalance(); string maxCashLimitStr; if (liveJob.BrokerageData.TryGetValue("max-cash-limit", out maxCashLimitStr)) { var maxCashLimit = JsonConvert.DeserializeObject <HashSet <CashAmount> >(maxCashLimitStr); brokerage.DisableCashSync(); Log.Trace("BrokerageSetupHandler.Setup(): will use job packet max cash limit. Disabled cash sync."); foreach (var cash in maxCashLimit) { var brokerageCash = cashBalance.FirstOrDefault( brokerageCashAmount => string.Equals(brokerageCashAmount.Currency, cash.Currency, StringComparison.InvariantCultureIgnoreCase)); // we use the min amount between the brokerage and the job packet, if any if (brokerageCash != default(CashAmount)) { Log.Trace($"BrokerageSetupHandler.Setup(): Job packet amount {cash.Currency} {cash.Amount}. Brokerage amount {brokerageCash.Amount}."); var cashToUse = new CashAmount(Math.Min(cash.Amount, brokerageCash.Amount), cash.Currency); algorithm.Debug($"Live deployment has been allocation limited to {cashToUse.Amount:C} {cashToUse.Currency}"); algorithm.Portfolio.SetCash(cashToUse.Currency, cashToUse.Amount, 0); } else { Log.Trace($"BrokerageSetupHandler.Setup(): Skip setting {cash.Currency} brokerage does not have it."); } } } else { foreach (var cash in cashBalance) { Log.Trace($"BrokerageSetupHandler.Setup(): Setting {cash.Currency} cash to {cash.Amount}"); algorithm.Portfolio.SetCash(cash.Currency, cash.Amount, 0); } } } catch (Exception err) { Log.Error(err); AddInitializationError("Error getting cash balance from brokerage: " + err.Message, err); return(false); } return(true); }
/******************************************************** * CONSTRUCTOR *********************************************************/ /// <summary> /// Constructor for the tradier transaction handler /// </summary> /// <param name="algorithm">Algorithm instance</param> /// <param name="brokerage">Brokerage instance</param> /// <param name="results">Result handler </param> /// <param name="accountId">Tradier account id</param> public TradierTransactionHandler(IAlgorithm algorithm, IBrokerage brokerage, IResultHandler results, int accountId) { _algorithm = algorithm; _isActive = true; _ready = false; _accountId = accountId; //Connect with Tradier: _tradier = (TradierBrokerage)brokerage; _results = results; }
/// <summary> /// Error handlers in event of a brokerage error. /// </summary> /// <param name="results">Result handler for sending results on error.</param> /// <param name="brokerage">Brokerage instance firing the errors</param> /// <returns>Boolean true on successfully setting up local algorithm</returns> public bool SetupErrorHandler(IResultHandler results, IBrokerage brokerage) { //Setup handler for access token error. brokerage.AddErrorHander("Access Token expired", () => { results.RuntimeError("Brokerage access token has expired. In general this should not happen, please contact [email protected]"); }); brokerage.AddErrorHander("Invalid Access Token", () => { results.RuntimeError("Access token is invalid. In general this should not happen, please contact [email protected]"); }); return(true); }
/// <summary> /// Creates a new BacktestingTransactionHandler using the BacktestingBrokerage /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="brokerage">The BacktestingBrokerage</param> /// <param name="resultHandler"></param> 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; base.Initialize(algorithm, brokerage, resultHandler); // non blocking implementation _orderRequestQueue = new BusyCollection <OrderRequest>(); }
/// <summary> /// Creates a new BrokerageTransactionHandler to process orders using the specified brokerage implementation /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="brokerage">The brokerage implementation to process orders and fire fill events</param> public BrokerageTransactionHandler(IAlgorithm algorithm, IBrokerage brokerage) { if (brokerage == null) { throw new ArgumentNullException("brokerage"); } _brokerage = brokerage; _brokerage.OrderEvent += (sender, fill) => { // save that the order event took place, we're initializing the list with a capacity of 2 to reduce number of mallocs //these hog memory //List<OrderEvent> orderEvents = _orderEvents.GetOrAdd(orderEvent.OrderId, i => new List<OrderEvent>(2)); //orderEvents.Add(orderEvent); //Apply the filled order to our portfolio: if (fill.Status == OrderStatus.Filled || fill.Status == OrderStatus.PartiallyFilled) { _algorithm.Portfolio.ProcessFill(fill); } //We have an event! :) Order filled, send it in to be handled by algorithm portfolio. if (fill.Status != OrderStatus.None) //order.Status != OrderStatus.Submitted { //Create new order event: Engine.ResultHandler.OrderEvent(fill); try { //Trigger our order event handler _algorithm.OnOrderEvent(fill); } catch (Exception err) { _algorithm.Error("Order Event Handler Error: " + err.Message); } } }; //_brokerage.AccountChanged += //_brokerage.PortfolioChanged += IsActive = true; _algorithm = algorithm; // also save off the various order data structures locally _orders = algorithm.Transactions.Orders; _orderEvents = algorithm.Transactions.OrderEvents; _orderQueue = algorithm.Transactions.OrderQueue; }
public void Setup() { Log.Trace(""); Log.Trace(""); Log.Trace("--- SETUP ---"); Log.Trace(""); Log.Trace(""); // we want to regenerate these for each test _brokerage = null; _orderProvider = null; _holdingsProvider = null; Thread.Sleep(1000); CancelOpenOrders(); LiquidateHoldings(); Thread.Sleep(1000); }
public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice) { var stop = (StopMarketOrder)order; var previousStop = stop.StopPrice; if (order.Quantity > 0) { // for stop buys we need to decrease the stop price stop.StopPrice = Math.Min(stop.StopPrice, Math.Max(stop.StopPrice / 2, lastMarketPrice)); } else { // for stop sells we need to increase the stop price stop.StopPrice = Math.Max(stop.StopPrice, Math.Min(stop.StopPrice * 2, lastMarketPrice)); } return stop.StopPrice != previousStop; }
/// <summary> /// Setup the algorithm cash, dates and portfolio as desired. /// </summary> /// <param name="algorithm">Algorithm instance</param> /// <param name="brokerage">Output new instance of the brokerage</param> /// <param name="job">Algorithm job/task we're running</param> /// <returns>Bool setup success</returns> public bool Setup(IAlgorithm algorithm, out IBrokerage brokerage, AlgorithmNodePacket job) { var initializeComplete = false; brokerage = new PaperBrokerage(algorithm); //For the console, let it set itself up primarily: try { //Algorithm is backtesting, not live: algorithm.SetLiveMode(true); //Set the live trading level asset/ram allocation limits. //Protects algorithm from linux killing the job by excess memory: switch (job.ServerType) { case ServerType.Server1024: algorithm.SetAssetLimits(100, 20, 10); break; case ServerType.Server2048: algorithm.SetAssetLimits(400, 50, 30); break; default: //512 algorithm.SetAssetLimits(50, 10, 5); break; } //Initialize the algorithm algorithm.Initialize(); } catch (Exception err) { Log.Error("PaperTradingSetupHandler.Setup(): " + err.Message); Errors.Add("Error setting up the paper trading algorithm; " + err.Message); } // Starting capital is portfolio cash: StartingCapital = algorithm.Portfolio.Cash; if (Errors.Count == 0) { initializeComplete = true; } return(initializeComplete); }
public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice) { var stop = (StopMarketOrder)order; var previousStop = stop.StopPrice; if (order.Quantity > 0) { // for stop buys we need to decrease the stop price stop.StopPrice = Math.Min(stop.StopPrice, Math.Max(stop.StopPrice / 2, lastMarketPrice)); } else { // for stop sells we need to increase the stop price stop.StopPrice = Math.Max(stop.StopPrice, Math.Min(stop.StopPrice * 2, lastMarketPrice)); } return(stop.StopPrice != previousStop); }
/// <summary> /// Creates a new instance /// </summary> /// <param name="universeSelection">The universe selection instance</param> /// <param name="algorithm">Algorithm instance</param> /// <param name="brokerage">New brokerage output instance</param> /// <param name="algorithmNodePacket">Algorithm job task</param> /// <param name="resultHandler">The configured result handler</param> /// <param name="transactionHandler">The configured transaction handler</param> /// <param name="realTimeHandler">The configured real time handler</param> public SetupHandlerParameters(UniverseSelection universeSelection, IAlgorithm algorithm, IBrokerage brokerage, AlgorithmNodePacket algorithmNodePacket, IResultHandler resultHandler, ITransactionHandler transactionHandler, IRealTimeHandler realTimeHandler ) { UniverseSelection = universeSelection; Algorithm = algorithm; Brokerage = brokerage; AlgorithmNodePacket = algorithmNodePacket; ResultHandler = resultHandler; TransactionHandler = transactionHandler; RealTimeHandler = realTimeHandler; }
public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice) { // limit orders will process even if they go beyond the market price var limit = (LimitOrder) order; if (order.Quantity > 0) { // for limit buys we need to increase the limit price limit.LimitPrice *= 2; } else { // for limit sells we need to decrease the limit price limit.LimitPrice /= 2; } return true; }
/// <summary> /// Setup the algorithm cash, dates and portfolio as desired. /// </summary> /// <param name="algorithm">Algorithm instance</param> /// <param name="brokerage">Output new instance of the brokerage</param> /// <param name="job">Algorithm job/task we're running</param> /// <returns>Bool setup success</returns> public bool Setup(IAlgorithm algorithm, out IBrokerage brokerage, AlgorithmNodePacket job) { var initializeComplete = false; brokerage = new Brokerage(); //Not used. //For the console, let it set itself up primarily: algorithm.Initialize(); // Starting capital is portfolio cash: StartingCapital = algorithm.Portfolio.Cash; if (Errors.Count == 0) { initializeComplete = true; } return(initializeComplete); }
public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice) { // limit orders will process even if they go beyond the market price var limit = (LimitOrder)order; if (order.Quantity > 0) { // for limit buys we need to increase the limit price limit.LimitPrice = lastMarketPrice * 1.05m; } else { // for limit sells we need to decrease the limit price limit.LimitPrice = lastMarketPrice / 1.05m; } return(true); }
/// <summary> /// Creates a new BrokerageTransactionHandler to process orders using the specified brokerage implementation /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="brokerage">The brokerage implementation to process orders and fire fill events</param> /// <param name="resultHandler"></param> public virtual void Initialize(IAlgorithm algorithm, IBrokerage brokerage, IResultHandler resultHandler) { if (brokerage == null) { throw new ArgumentNullException("brokerage"); } // we don't need to do this today because we just initialized/synced _resultHandler = resultHandler; _syncedLiveBrokerageCashToday = true; _lastSyncTimeTicks = DateTime.UtcNow.Ticks; _brokerage = brokerage; _brokerage.OrderStatusChanged += (sender, fill) => { // log every fill in live mode if (algorithm.LiveMode) { var brokerIds = string.Empty; var order = GetOrderById(fill.OrderId); if (order != null && order.BrokerId.Count > 0) { brokerIds = string.Join(", ", order.BrokerId); } Log.Trace("BrokerageTransactionHandler.OrderStatusChanged(): " + fill + " BrokerId: " + brokerIds); } HandleOrderEvent(fill); }; _brokerage.AccountChanged += (sender, account) => { HandleAccountChanged(account); }; _brokerage.OptionPositionAssigned += (sender, fill) => { HandlePositionAssigned(fill); }; IsActive = true; _algorithm = algorithm; }
/// <summary> /// Creates a new BrokerageTransactionHandler to process orders using the specified brokerage implementation /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="brokerage">The brokerage implementation to process orders and fire fill events</param> public BrokerageTransactionHandler(IAlgorithm algorithm, IBrokerage brokerage) { if (brokerage == null) { throw new ArgumentNullException("brokerage"); } // we don't need to do this today because we just initialized/synced _syncedLiveBrokerageCashToday = true; _lastSyncTimeTicks = DateTime.Now.Ticks; _brokerage = brokerage; _brokerage.OrderStatusChanged += (sender, fill) => { HandleOrderEvent(fill); }; _brokerage.SecurityHoldingUpdated += (sender, holding) => { HandleSecurityHoldingUpdated(holding); }; _brokerage.AccountChanged += (sender, account) => { HandleAccountChanged(account); }; IsActive = true; _algorithm = algorithm; // also save off the various order data structures locally _orders = algorithm.Transactions.Orders; _orderEvents = algorithm.Transactions.OrderEvents; _orderQueue = algorithm.Transactions.OrderQueue; }
/// <summary> /// Setup the algorithm cash, dates and data subscriptions as desired. /// </summary> /// <param name="algorithm">Algorithm instance</param> /// <param name="brokerage">Brokerage instance</param> /// <param name="baseJob">Algorithm job</param> /// <param name="resultHandler">The configured result handler</param> /// <param name="transactionHandler">The configurated transaction handler</param> /// <param name="realTimeHandler">The configured real time handler</param> /// <returns>Boolean true on successfully initializing the algorithm</returns> public bool Setup(IAlgorithm algorithm, IBrokerage brokerage, AlgorithmNodePacket baseJob, IResultHandler resultHandler, ITransactionHandler transactionHandler, IRealTimeHandler realTimeHandler) { var job = baseJob as BacktestNodePacket; if (job == null) { throw new ArgumentException("Expected BacktestNodePacket but received " + baseJob.GetType().Name); } Log.Trace(string.Format("BacktestingSetupHandler.Setup(): Setting up job: Plan: {0}, UID: {1}, PID: {2}, Version: {3}, Source: {4}", job.UserPlan, job.UserId, job.ProjectId, job.Version, job.RequestSource)); if (algorithm == null) { Errors.Add("Could not create instance of algorithm"); return false; } //Make sure the algorithm start date ok. if (job.PeriodStart == default(DateTime)) { Errors.Add("Algorithm start date was never set"); return false; } var controls = job.Controls; var isolator = new Isolator(); var initializeComplete = isolator.ExecuteWithTimeLimit(TimeSpan.FromMinutes(5), () => { try { //Set our parameters algorithm.SetParameters(job.Parameters); //Algorithm is backtesting, not live: algorithm.SetLiveMode(false); //Set the algorithm time before we even initialize: algorithm.SetDateTime(job.PeriodStart.ConvertToUtc(algorithm.TimeZone)); //Set the source impl for the event scheduling algorithm.Schedule.SetEventSchedule(realTimeHandler); //Initialise the algorithm, get the required data: algorithm.Initialize(); } catch (Exception err) { Errors.Add("Failed to initialize algorithm: Initialize(): " + err.Message); } }); //Before continuing, detect if this is ready: if (!initializeComplete) return false; algorithm.Transactions.SetOrderProcessor(transactionHandler); algorithm.PostInitialize(); //Calculate the max runtime for the strategy _maxRuntime = GetMaximumRuntime(job.PeriodStart, job.PeriodFinish, algorithm.SubscriptionManager.Count); //Get starting capital: _startingCaptial = algorithm.Portfolio.Cash; //Max Orders: 10k per backtest: if (job.UserPlan == UserPlan.Free) { _maxOrders = 10000; } else { _maxOrders = int.MaxValue; _maxRuntime += _maxRuntime; } //Set back to the algorithm, algorithm.SetMaximumOrders(_maxOrders); //Starting date of the algorithm: _startingDate = job.PeriodStart; //Put into log for debugging: Log.Trace("SetUp Backtesting: User: "******" ProjectId: " + job.ProjectId + " AlgoId: " + job.AlgorithmId); Log.Trace("Dates: Start: " + job.PeriodStart.ToShortDateString() + " End: " + job.PeriodFinish.ToShortDateString() + " Cash: " + _startingCaptial.ToString("C")); if (Errors.Count > 0) { initializeComplete = false; } return initializeComplete; }
/// <summary> /// Setup the algorithm cash, dates and portfolio as desired. /// </summary> /// <param name="algorithm">Existing algorithm instance</param> /// <param name="brokerage">New brokerage instance</param> /// <param name="baseJob">Backtesting job</param> /// <param name="resultHandler"></param> /// <returns>Boolean true on successfully setting up the console.</returns> public bool Setup(IAlgorithm algorithm, out IBrokerage brokerage, AlgorithmNodePacket baseJob, IResultHandler resultHandler) { var initializeComplete = false; try { //Set common variables for console programs: if (baseJob.Type == PacketType.BacktestNode) { var backtestJob = baseJob as BacktestNodePacket; //Set the limits on the algorithm assets (for local no limits) algorithm.SetAssetLimits(999, 999, 999); algorithm.SetMaximumOrders(int.MaxValue); //Setup Base Algorithm: algorithm.Initialize(); //Add currency data feeds that weren't explicity added in Initialize algorithm.Portfolio.CashBook.EnsureCurrencyDataFeeds(algorithm.Securities, algorithm.SubscriptionManager); //Construct the backtest job packet: backtestJob.PeriodStart = algorithm.StartDate; backtestJob.PeriodFinish = algorithm.EndDate; backtestJob.BacktestId = "LOCALHOST"; backtestJob.UserId = 1001; backtestJob.Type = PacketType.BacktestNode; //Backtest Specific Parameters: StartingDate = backtestJob.PeriodStart; StartingPortfolioValue = algorithm.Portfolio.Cash; } else { throw new Exception("The ConsoleSetupHandler is for backtests only. Use the BrokerageSetupHandler."); } } catch (Exception err) { Log.Error("ConsoleSetupHandler().Setup(): " + err.Message); Errors.Add("Failed to initialize algorithm: Initialize(): " + err.Message); } if (Errors.Count == 0) { initializeComplete = true; } // we need to do this after algorithm initialization brokerage = new BacktestingBrokerage(algorithm); // set the transaction models base on the requested brokerage properties SetupHandler.UpdateTransactionModels(algorithm, algorithm.BrokerageModel); return initializeComplete; }
/// <summary> /// Creates a new BrokerageTransactionHandler to process orders using the specified brokerage implementation /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="brokerage">The brokerage implementation to process orders and fire fill events</param> /// <param name="resultHandler"></param> public virtual void Initialize(IAlgorithm algorithm, IBrokerage brokerage, IResultHandler resultHandler) { if (brokerage == null) { throw new ArgumentNullException("brokerage"); } // we don't need to do this today because we just initialized/synced _resultHandler = resultHandler; _syncedLiveBrokerageCashToday = true; _lastSyncTimeTicks = DateTime.Now.Ticks; _brokerage = brokerage; _brokerage.OrderStatusChanged += (sender, fill) => { // log every fill in live mode if (algorithm.LiveMode) { var brokerIds = string.Empty; var order = GetOrderById(fill.OrderId); if (order != null && order.BrokerId.Count > 0) brokerIds = string.Join(", ", order.BrokerId); Log.Trace("BrokerageTransactionHandler.OrderStatusChanged(): " + fill + " BrokerId: " + brokerIds); } HandleOrderEvent(fill); }; _brokerage.AccountChanged += (sender, account) => { HandleAccountChanged(account); }; IsActive = true; _algorithm = algorithm; }
/// <summary> /// Creates a new BrokerageTransactionHandler to process orders using the specified brokerage implementation /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="brokerage">The brokerage implementation to process orders and fire fill events</param> /// <param name="resultHandler"></param> public virtual void Initialize(IAlgorithm algorithm, IBrokerage brokerage, IResultHandler resultHandler) { if (brokerage == null) { throw new ArgumentNullException("brokerage"); } // we don't need to do this today because we just initialized/synced _resultHandler = resultHandler; _syncedLiveBrokerageCashToday = true; _lastSyncTimeTicks = DateTime.Now.Ticks; _brokerage = brokerage; _brokerage.OrderStatusChanged += (sender, fill) => { HandleOrderEvent(fill); }; _brokerage.SecurityHoldingUpdated += (sender, holding) => { HandleSecurityHoldingUpdated(holding); }; _brokerage.AccountChanged += (sender, account) => { HandleAccountChanged(account); }; IsActive = true; _algorithm = algorithm; // also save off the various order data structures locally _orders = new ConcurrentDictionary<int, Order>(); _orderRequestQueue = new ConcurrentQueue<OrderRequest>(); _orderTickets = new ConcurrentDictionary<int, OrderTicket>(); _processingCompletedEvent = new ManualResetEventSlim(true); }
public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice) { // NOP // market orders should fill without modification return false; }
/// <summary> /// Disposes of the brokerage and any external resources started in order to create it /// </summary> /// <param name="brokerage">The brokerage instance to be disposed of</param> protected virtual void DisposeBrokerage(IBrokerage brokerage) { }
/// <summary> /// Setup error handlers for the backtest. /// </summary> /// <param name="results">Result handler</param> /// <param name="brokerage">Brokerage interface</param> /// <returns>Boolean true on successful setup</returns> /// <remarks>Not used in a backtesting setup handler. This is primarily for setting up brokerage error handler functions</remarks> public bool SetupErrorHandler(IResultHandler results, IBrokerage brokerage) { return true; }
/// <summary> /// Creates a new BrokerageTransactionHandler to process orders using the specified brokerage implementation /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="brokerage">The brokerage implementation to process orders and fire fill events</param> /// <param name="resultHandler"></param> public virtual void Initialize(IAlgorithm algorithm, IBrokerage brokerage, IResultHandler resultHandler) { if (brokerage == null) { throw new ArgumentNullException("brokerage"); } // we don't need to do this today because we just initialized/synced _resultHandler = resultHandler; _syncedLiveBrokerageCashToday = true; _lastSyncTimeTicks = DateTime.Now.Ticks; _brokerage = brokerage; _brokerage.OrderStatusChanged += (sender, fill) => { HandleOrderEvent(fill); }; _brokerage.AccountChanged += (sender, account) => { HandleAccountChanged(account); }; IsActive = true; _algorithm = algorithm; }
/// <summary> /// Get an instance of the transaction handler set by the task. /// </summary> /// <param name="algorithm">Algorithm instance</param> /// <param name="job">Algorithm job packet</param> /// <param name="brokerage">Brokerage instance to avoid access token duplication</param> /// <param name="results">Results array for sending order events.</param> /// <returns>Class matching ITransactionHandler interface</returns> private static ITransactionHandler GetTransactionHandler(IAlgorithm algorithm, IBrokerage brokerage, IResultHandler results, AlgorithmNodePacket job) { ITransactionHandler th; switch (job.TransactionEndpoint) { case TransactionHandlerEndpoint.Brokerage: th = new BrokerageTransactionHandler(algorithm, brokerage); Log.Trace("Engine.GetTransactionHandler(): Selected Brokerage Transaction Models."); break; //Operation from local files: default: th = new BacktestingTransactionHandler(algorithm, brokerage as BacktestingBrokerage); Log.Trace("Engine.GetTransactionHandler(): Selected Backtesting Transaction Models."); break; } return th; }
/// <summary> /// Select the realtime event handler set in the job. /// </summary> private static IRealTimeHandler GetRealTimeHandler(IAlgorithm algorithm, IBrokerage brokerage, IDataFeed feed, IResultHandler results, AlgorithmNodePacket job) { var rth = default(IRealTimeHandler); switch (job.RealTimeEndpoint) { //Don't fire based on system time but virtualized backtesting time. case RealTimeEndpoint.Backtesting: Log.Trace("Engine.GetRealTimeHandler(): Selected Backtesting RealTimeEvent Handler"); rth = new BacktestingRealTimeHandler(algorithm, job); break; // Fire events based on real system clock time. case RealTimeEndpoint.LiveTrading: Log.Trace("Engine.GetRealTimeHandler(): Selected LiveTrading RealTimeEvent Handler"); rth = new LiveTradingRealTimeHandler(algorithm, feed, results); break; } return rth; }
/// <summary> /// Setup the algorithm cash, dates and data subscriptions as desired. /// </summary> /// <param name="algorithm">Algorithm instance</param> /// <param name="brokerage">Brokerage instance</param> /// <param name="baseJob">Algorithm job</param> /// <param name="resultHandler">The configured result handler</param> /// <param name="transactionHandler">The configurated transaction handler</param> /// <returns>Boolean true on successfully initializing the algorithm</returns> public bool Setup(IAlgorithm algorithm, out IBrokerage brokerage, AlgorithmNodePacket baseJob, IResultHandler resultHandler, ITransactionHandler transactionHandler) { var job = baseJob as BacktestNodePacket; if (job == null) { throw new ArgumentException("Expected BacktestNodePacket but received " + baseJob.GetType().Name); } Log.Trace(string.Format("BacktestingSetupHandler.Setup(): Setting up job: Plan: {0}, UID: {1}, PID: {2}, Version: {3}, Source: {4}", job.UserPlan, job.UserId, job.ProjectId, job.Version, job.RequestSource)); brokerage = null; if (algorithm == null) { Errors.Add("Could not create instance of algorithm"); return false; } //Make sure the algorithm start date ok. if (job.PeriodStart == default(DateTime)) { Errors.Add("Algorithm start date was never set"); return false; } //Execute the initialize code: var isolator = new Isolator(); var initializeComplete = isolator.ExecuteWithTimeLimit(TimeSpan.FromSeconds(10), () => { try { //Algorithm is backtesting, not live: algorithm.SetLiveMode(false); //Set the backtest level asset ram allocation limits algorithm.SetAssetLimits(500, 100, 30); //Set the algorithm time before we even initialize: algorithm.SetDateTime(job.PeriodStart); //Initialise the algorithm, get the required data: algorithm.Initialize(); //Add currency data feeds that weren't explicity added in Initialize algorithm.Portfolio.CashBook.EnsureCurrencyDataFeeds(algorithm.Securities, algorithm.SubscriptionManager); } catch (Exception err) { Errors.Add("Failed to initialize algorithm: Initialize(): " + err.Message); } }); //Before continuing, detect if this is ready: if (!initializeComplete) return false; // this needs to be done after algorithm initialization brokerage = new BacktestingBrokerage(algorithm); SetupHandler.UpdateTransactionModels(algorithm, algorithm.BrokerageModel); algorithm.Transactions.SetOrderProcessor(transactionHandler); //Calculate the max runtime for the strategy _maxRuntime = GetMaximumRuntime(job.PeriodStart, job.PeriodFinish, algorithm.SubscriptionManager.Count); //Get starting capital: _startingCaptial = algorithm.Portfolio.Cash; //Max Orders: 10k per backtest: if (job.UserPlan == UserPlan.Free) { _maxOrders = 10000; } else { _maxOrders = int.MaxValue; _maxRuntime += _maxRuntime; } //Set back to the algorithm, algorithm.SetMaximumOrders(_maxOrders); //Starting date of the algorithm: _startingDate = job.PeriodStart; //Put into log for debugging: Log.Trace("SetUp Backtesting: User: "******" ProjectId: " + job.ProjectId + " AlgoId: " + job.AlgorithmId); Log.Trace("Dates: Start: " + job.PeriodStart.ToShortDateString() + " End: " + job.PeriodFinish.ToShortDateString() + " Cash: " + _startingCaptial.ToString("C")); if (Errors.Count > 0) { initializeComplete = false; } return initializeComplete; }
/// <summary> /// Primary entry point to setup a new algorithm /// </summary> /// <param name="algorithm">Algorithm instance</param> /// <param name="brokerage">New brokerage output instance</param> /// <param name="job">Algorithm job task</param> /// <param name="resultHandler">The configured result handler</param> /// <param name="transactionHandler">The configurated transaction handler</param> /// <param name="realTimeHandler">The configured real time handler</param> /// <returns>True on successfully setting up the algorithm state, or false on error.</returns> public bool Setup(IAlgorithm algorithm, IBrokerage brokerage, AlgorithmNodePacket job, IResultHandler resultHandler, ITransactionHandler transactionHandler, IRealTimeHandler realTimeHandler) { _algorithm = algorithm; // verify we were given the correct job packet type var liveJob = job as LiveNodePacket; if (liveJob == null) { AddInitializationError("BrokerageSetupHandler requires a LiveNodePacket"); return false; } // verify the brokerage was specified if (string.IsNullOrWhiteSpace(liveJob.Brokerage)) { AddInitializationError("A brokerage must be specified"); return false; } // attach to the message event to relay brokerage specific initialization messages EventHandler<BrokerageMessageEvent> brokerageOnMessage = (sender, args) => { if (args.Type == BrokerageMessageType.Error) { AddInitializationError(string.Format("Brokerage Error Code: {0} - {1}", args.Code, args.Message)); } }; try { Log.Trace("BrokerageSetupHandler.Setup(): Initializing algorithm..."); resultHandler.SendStatusUpdate(AlgorithmStatus.Initializing, "Initializing algorithm..."); //Execute the initialize code: var controls = job.Controls; var isolator = new Isolator(); var initializeComplete = isolator.ExecuteWithTimeLimit(TimeSpan.FromSeconds(300), () => { try { //Set the default brokerage model before initialize algorithm.SetBrokerageModel(_factory.BrokerageModel); //Set our parameters algorithm.SetParameters(job.Parameters); //Algorithm is live, not backtesting: algorithm.SetLiveMode(true); //Initialize the algorithm's starting date algorithm.SetDateTime(DateTime.UtcNow); //Set the source impl for the event scheduling algorithm.Schedule.SetEventSchedule(realTimeHandler); //Initialise the algorithm, get the required data: algorithm.Initialize(); if (liveJob.Brokerage != "PaperBrokerage") { //Zero the CashBook - we'll populate directly from brokerage foreach (var kvp in algorithm.Portfolio.CashBook) { kvp.Value.SetAmount(0); } } } catch (Exception err) { AddInitializationError(err.Message); } }); if (!initializeComplete) { AddInitializationError("Initialization timed out."); return false; } // let the world know what we're doing since logging in can take a minute resultHandler.SendStatusUpdate(AlgorithmStatus.LoggingIn, "Logging into brokerage..."); brokerage.Message += brokerageOnMessage; algorithm.Transactions.SetOrderProcessor(transactionHandler); Log.Trace("BrokerageSetupHandler.Setup(): Connecting to brokerage..."); try { // this can fail for various reasons, such as already being logged in somewhere else brokerage.Connect(); } catch (Exception err) { Log.Error(err); AddInitializationError(string.Format("Error connecting to brokerage: {0}. " + "This may be caused by incorrect login credentials or an unsupported account type.", err.Message)); return false; } if (!brokerage.IsConnected) { // if we're reporting that we're not connected, bail AddInitializationError("Unable to connect to brokerage."); return false; } Log.Trace("BrokerageSetupHandler.Setup(): Fetching cash balance from brokerage..."); try { // set the algorithm's cash balance for each currency var cashBalance = brokerage.GetCashBalance(); foreach (var cash in cashBalance) { Log.Trace("BrokerageSetupHandler.Setup(): Setting " + cash.Symbol + " cash to " + cash.Amount); algorithm.Portfolio.SetCash(cash.Symbol, cash.Amount, cash.ConversionRate); } } catch (Exception err) { Log.Error(err); AddInitializationError("Error getting cash balance from brokerage: " + err.Message); return false; } Log.Trace("BrokerageSetupHandler.Setup(): Fetching open orders from brokerage..."); try { // populate the algorithm with the account's outstanding orders var openOrders = brokerage.GetOpenOrders(); foreach (var order in openOrders) { // be sure to assign order IDs such that we increment from the SecurityTransactionManager to avoid ID collisions Log.Trace("BrokerageSetupHandler.Setup(): Has open order: " + order.Symbol.ToString() + " - " + order.Quantity); order.Id = algorithm.Transactions.GetIncrementOrderId(); transactionHandler.Orders.AddOrUpdate(order.Id, order, (i, o) => order); } } catch (Exception err) { Log.Error(err); AddInitializationError("Error getting open orders from brokerage: " + err.Message); return false; } Log.Trace("BrokerageSetupHandler.Setup(): Fetching holdings from brokerage..."); try { // populate the algorithm with the account's current holdings var holdings = brokerage.GetAccountHoldings(); var supportedSecurityTypes = new HashSet<SecurityType> { SecurityType.Equity, SecurityType.Forex, SecurityType.Cfd }; var minResolution = new Lazy<Resolution>(() => algorithm.Securities.Select(x => x.Value.Resolution).DefaultIfEmpty(Resolution.Second).Min()); foreach (var holding in holdings) { Log.Trace("BrokerageSetupHandler.Setup(): Has existing holding: " + holding); // verify existing holding security type if (!supportedSecurityTypes.Contains(holding.Type)) { Log.Error("BrokerageSetupHandler.Setup(): Unsupported security type: " + holding.Type + "-" + holding.Symbol.Value); AddInitializationError("Found unsupported security type in existing brokerage holdings: " + holding.Type + ". " + "QuantConnect currently supports the following security types: " + string.Join(",", supportedSecurityTypes)); // keep aggregating these errors continue; } if (!algorithm.Portfolio.ContainsKey(holding.Symbol)) { Log.Trace("BrokerageSetupHandler.Setup(): Adding unrequested security: " + holding.Symbol.ToString()); // for items not directly requested set leverage to 1 and at the min resolution algorithm.AddSecurity(holding.Type, holding.Symbol.Value, minResolution.Value, null, true, 1.0m, false); } algorithm.Portfolio[holding.Symbol].SetHoldings(holding.AveragePrice, (int) holding.Quantity); algorithm.Securities[holding.Symbol].SetMarketPrice(new TradeBar { Time = DateTime.Now, Open = holding.MarketPrice, High = holding.MarketPrice, Low = holding.MarketPrice, Close = holding.MarketPrice, Volume = 0, Symbol = holding.Symbol, DataType = MarketDataType.TradeBar }); } } catch (Exception err) { Log.Error(err); AddInitializationError("Error getting account holdings from brokerage: " + err.Message); return false; } algorithm.PostInitialize(); //Set the starting portfolio value for the strategy to calculate performance: StartingPortfolioValue = algorithm.Portfolio.TotalPortfolioValue; StartingDate = DateTime.Now; } catch (Exception err) { AddInitializationError(err.Message); } finally { if (brokerage != null) { brokerage.Message -= brokerageOnMessage; } } return Errors.Count == 0; }
/// <summary> /// Setup the algorithm cash, dates and portfolio as desired. /// </summary> /// <param name="algorithm">Existing algorithm instance</param> /// <param name="brokerage">New brokerage instance</param> /// <param name="baseJob">Backtesting job</param> /// <param name="resultHandler">The configured result handler</param> /// <param name="transactionHandler">The configuration transaction handler</param> /// <param name="realTimeHandler">The configured real time handler</param> /// <returns>Boolean true on successfully setting up the console.</returns> public bool Setup(IAlgorithm algorithm, IBrokerage brokerage, AlgorithmNodePacket baseJob, IResultHandler resultHandler, ITransactionHandler transactionHandler, IRealTimeHandler realTimeHandler) { var initializeComplete = false; try { //Set common variables for console programs: if (baseJob.Type == PacketType.BacktestNode) { var backtestJob = baseJob as BacktestNodePacket; //Set our default markets algorithm.SetDefaultMarkets(BacktestingBrokerageFactory.DefaultMarketMap.ToDictionary()); algorithm.SetMaximumOrders(int.MaxValue); // set our parameters algorithm.SetParameters(baseJob.Parameters); algorithm.SetLiveMode(false); //Set the source impl for the event scheduling algorithm.Schedule.SetEventSchedule(realTimeHandler); //Setup Base Algorithm: algorithm.Initialize(); //Set the time frontier of the algorithm algorithm.SetDateTime(algorithm.StartDate.ConvertToUtc(algorithm.TimeZone)); //Construct the backtest job packet: backtestJob.PeriodStart = algorithm.StartDate; backtestJob.PeriodFinish = algorithm.EndDate; backtestJob.BacktestId = "LOCALHOST"; backtestJob.UserId = 1001; backtestJob.Type = PacketType.BacktestNode; //Backtest Specific Parameters: StartingDate = backtestJob.PeriodStart; StartingPortfolioValue = algorithm.Portfolio.Cash; } else { throw new Exception("The ConsoleSetupHandler is for backtests only. Use the BrokerageSetupHandler."); } } catch (Exception err) { Log.Error(err); Errors.Add("Failed to initialize algorithm: Initialize(): " + err.Message); } if (Errors.Count == 0) { initializeComplete = true; } // set the transaction and settlement models based on the brokerage properties algorithm.UpdateModels(algorithm.BrokerageModel); algorithm.Transactions.SetOrderProcessor(transactionHandler); algorithm.PostInitialize(); return initializeComplete; }
/// <summary> /// Setup the algorithm cash, dates and portfolio as desired. /// </summary> /// <param name="algorithm">Algorithm instance</param> /// <param name="brokerage">Output new instance of the brokerage</param> /// <param name="job">Algorithm job/task we're running</param> /// <returns>Bool setup success</returns> public bool Setup(IAlgorithm algorithm, out IBrokerage brokerage, AlgorithmNodePacket job) { var initializeComplete = false; brokerage = new PaperBrokerage(algorithm); //For the console, let it set itself up primarily: try { //Algorithm is backtesting, not live: algorithm.SetLiveMode(true); //Set the live trading level asset/ram allocation limits. //Protects algorithm from linux killing the job by excess memory: switch (job.ServerType) { case ServerType.Server1024: algorithm.SetAssetLimits(100, 20, 10); break; case ServerType.Server2048: algorithm.SetAssetLimits(400, 50, 30); break; default: //512 algorithm.SetAssetLimits(50, 10, 5); break; } //Initialize the algorithm algorithm.Initialize(); } catch (Exception err) { Log.Error("PaperTradingSetupHandler.Setup(): " + err.Message); Errors.Add("Error setting up the paper trading algorithm; " + err.Message); } // Starting capital is portfolio cash: StartingCapital = algorithm.Portfolio.Cash; if (Errors.Count == 0) { initializeComplete = true; } return initializeComplete; }
/// <summary> /// Setup the algorithm cash, dates and data subscriptions as desired. /// </summary> /// <param name="algorithm">Algorithm instance</param> /// <param name="brokerage">Brokerage instance</param> /// <param name="baseJob">Algorithm job</param> /// <returns>Boolean true on successfully initializing the algorithm</returns> public bool Setup(IAlgorithm algorithm, out IBrokerage brokerage, AlgorithmNodePacket baseJob) { var job = baseJob as BacktestNodePacket; if (job == null) { throw new ArgumentException("Expected BacktestNodePacket but received " + baseJob.GetType().Name); } // Must be set since its defined as an out parameters brokerage = new BacktestingBrokerage(algorithm); if (algorithm == null) { Errors.Add("Could not create instance of algorithm"); return false; } //Make sure the algorithm start date ok. if (job.PeriodStart == default(DateTime)) { Errors.Add("Algorithm start date was never set"); return false; } //Execute the initialize code: var initializeComplete = Isolator.ExecuteWithTimeLimit(TimeSpan.FromSeconds(10), () => { try { //Algorithm is backtesting, not live: algorithm.SetLiveMode(false); //Set the backtest level asset ram allocation limits algorithm.SetAssetLimits(500, 100, 30); //Set the algorithm time before we even initialize: algorithm.SetDateTime(job.PeriodStart); //Initialise the algorithm, get the required data: algorithm.Initialize(); } catch (Exception err) { Errors.Add("Failed to initialize algorithm: Initialize(): " + err.Message); } }); //Before continuing, detect if this is ready: if (!initializeComplete) return false; //Calculate the max runtime for the strategy _maxRuntime = GetMaximumRuntime(job.PeriodStart, job.PeriodFinish, algorithm.SubscriptionManager.Count); //Get starting capital: _startingCaptial = algorithm.Portfolio.Cash; //Max Orders: 100 per day: _maxOrders = (int)(job.PeriodFinish - job.PeriodStart).TotalDays * 100; //Starting date of the algorithm: _startingDate = job.PeriodStart; //Put into log for debugging: Log.Trace("SetUp Backtesting: User: "******" ProjectId: " + job.ProjectId + " AlgoId: " + job.AlgorithmId); Log.Trace("Dates: Start: " + job.PeriodStart.ToShortDateString() + " End: " + job.PeriodFinish.ToShortDateString() + " Cash: " + _startingCaptial.ToString("C")); if (Errors.Count > 0) { initializeComplete = false; } return initializeComplete; }
/// <summary> /// Primary entry point to setup a new algorithm /// </summary> /// <param name="algorithm">Algorithm instance</param> /// <param name="brokerage">New brokerage output instance</param> /// <param name="job">Algorithm job task</param> /// <param name="resultHandler">The configured result handler</param> /// <param name="transactionHandler">The configurated transaction handler</param> /// <param name="realTimeHandler">The configured real time handler</param> /// <returns>True on successfully setting up the algorithm state, or false on error.</returns> public bool Setup(IAlgorithm algorithm, out IBrokerage brokerage, AlgorithmNodePacket job, IResultHandler resultHandler, ITransactionHandler transactionHandler, IRealTimeHandler realTimeHandler) { _algorithm = algorithm; brokerage = default(IBrokerage); // verify we were given the correct job packet type var liveJob = job as LiveNodePacket; if (liveJob == null) { AddInitializationError("BrokerageSetupHandler requires a LiveNodePacket"); return false; } // verify the brokerage was specified if (string.IsNullOrWhiteSpace(liveJob.Brokerage)) { AddInitializationError("A brokerage must be specified"); return false; } // attach to the message event to relay brokerage specific initialization messages EventHandler<BrokerageMessageEvent> brokerageOnMessage = (sender, args) => { if (args.Type == BrokerageMessageType.Error) { AddInitializationError(string.Format("Brokerage Error Code: {0} - {1}", args.Code, args.Message)); } }; try { Log.Trace("BrokerageSetupHandler.Setup(): Initializing algorithm..."); //Execute the initialize code: var isolator = new Isolator(); var initializeComplete = isolator.ExecuteWithTimeLimit(TimeSpan.FromSeconds(10), () => { try { //Set the live trading level asset/ram allocation limits. //Protects algorithm from linux killing the job by excess memory: switch (job.ServerType) { case ServerType.Server1024: algorithm.SetAssetLimits(100, 20, 10); break; case ServerType.Server2048: algorithm.SetAssetLimits(400, 50, 30); break; default: //512 algorithm.SetAssetLimits(50, 25, 15); break; } //Algorithm is live, not backtesting: algorithm.SetLiveMode(true); //Initialize the algorithm's starting date algorithm.SetDateTime(DateTime.UtcNow); //Set the source impl for the event scheduling algorithm.Schedule.SetEventSchedule(realTimeHandler); //Initialise the algorithm, get the required data: algorithm.Initialize(); } catch (Exception err) { AddInitializationError(err.Message); } }); if (!initializeComplete) { AddInitializationError("Initialization timed out."); return false; } try { // find the correct brokerage factory based on the specified brokerage in the live job packet _factory = Composer.Instance.Single<IBrokerageFactory>(factory => factory.BrokerageType.MatchesTypeName(liveJob.Brokerage)); } catch (Exception err) { Log.Error("BrokerageSetupHandler.Setup(): Error resolving brokerage factory for " + liveJob.Brokerage + ". " + err.Message); AddInitializationError("Unable to locate factory for brokerage: " + liveJob.Brokerage); } // let the world know what we're doing since logging in can take a minute resultHandler.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.LoggingIn, "Logging into brokerage..."); // initialize the correct brokerage using the resolved factory brokerage = _factory.CreateBrokerage(liveJob, algorithm); if (brokerage == null) { AddInitializationError("Failed to create instance of brokerage: " + liveJob.Brokerage); return false; } brokerage.Message += brokerageOnMessage; // set the transaction models base on the brokerage properties SetupHandler.UpdateTransactionModels(algorithm, algorithm.BrokerageModel); algorithm.Transactions.SetOrderProcessor(transactionHandler); algorithm.PostInitialize(); try { // this can fail for various reasons, such as already being logged in somewhere else brokerage.Connect(); } catch (Exception err) { Log.Error(err); AddInitializationError("Error connecting to brokerage: " + err.Message); return false; } if (!brokerage.IsConnected) { // if we're reporting that we're not connected, bail AddInitializationError("Unable to connect to brokerage."); return false; } try { // set the algorithm's cash balance for each currency var cashBalance = brokerage.GetCashBalance(); foreach (var cash in cashBalance) { Log.Trace("BrokerageSetupHandler.Setup(): Setting " + cash.Symbol + " cash to " + cash.Quantity); algorithm.SetCash(cash.Symbol, cash.Quantity, cash.ConversionRate); } } catch (Exception err) { Log.Error(err); AddInitializationError("Error getting cash balance from brokerage: " + err.Message); return false; } try { // populate the algorithm with the account's outstanding orders var openOrders = brokerage.GetOpenOrders(); foreach (var order in openOrders) { // be sure to assign order IDs such that we increment from the SecurityTransactionManager to avoid ID collisions Log.Trace("BrokerageSetupHandler.Setup(): Has open order: " + order.Symbol + " - " + order.Quantity); order.Id = algorithm.Transactions.GetIncrementOrderId(); transactionHandler.Orders.AddOrUpdate(order.Id, order, (i, o) => order); } } catch (Exception err) { Log.Error(err); AddInitializationError("Error getting open orders from brokerage: " + err.Message); return false; } try { // populate the algorithm with the account's current holdings var holdings = brokerage.GetAccountHoldings(); var minResolution = new Lazy<Resolution>(() => algorithm.Securities.Min(x => x.Value.Resolution)); foreach (var holding in holdings) { Log.Trace("BrokerageSetupHandler.Setup(): Has existing holding: " + holding); if (!algorithm.Portfolio.ContainsKey(holding.Symbol)) { Log.Trace("BrokerageSetupHandler.Setup(): Adding unrequested security: " + holding.Symbol); // for items not directly requested set leverage to 1 and at the min resolution algorithm.AddSecurity(holding.Type, holding.Symbol, minResolution.Value, null, true, 1.0m, false); } algorithm.Portfolio[holding.Symbol].SetHoldings(holding.AveragePrice, (int) holding.Quantity); algorithm.Securities[holding.Symbol].SetMarketPrice(new TradeBar { Time = DateTime.Now, Open = holding.MarketPrice, High = holding.MarketPrice, Low = holding.MarketPrice, Close = holding.MarketPrice, Volume = 0, Symbol = holding.Symbol, DataType = MarketDataType.TradeBar }); } } catch (Exception err) { Log.Error(err); AddInitializationError("Error getting account holdings from brokerage: " + err.Message); return false; } // call this after we've initialized everything from the brokerage since we may have added some holdings/currencies algorithm.Portfolio.CashBook.EnsureCurrencyDataFeeds(algorithm.Securities, algorithm.SubscriptionManager, SecurityExchangeHoursProvider.FromDataFolder()); //Set the starting portfolio value for the strategy to calculate performance: StartingPortfolioValue = algorithm.Portfolio.TotalPortfolioValue; StartingDate = DateTime.Now; } catch (Exception err) { AddInitializationError(err.Message); } finally { if (brokerage != null) { brokerage.Message -= brokerageOnMessage; } } return Errors.Count == 0; }
/// <summary> /// Setup the error handler for the brokerage errors. /// </summary> /// <param name="results">Result handler.</param> /// <param name="brokerage">Brokerage endpoint.</param> /// <returns>True on successfully setting up the error handlers.</returns> public bool SetupErrorHandler(IResultHandler results, IBrokerage brokerage) { brokerage.Message += (sender, message) => { // based on message type dispatch to result handler switch (message.Type) { case BrokerageMessageType.Information: results.DebugMessage("Brokerage Info: " + message.Message); break; case BrokerageMessageType.Warning: results.ErrorMessage("Brokerage Warning: " + message.Message); break; case BrokerageMessageType.Error: results.ErrorMessage("Brokerage Error: " + message.Message); _algorithm.RunTimeError = new Exception(message.Message); break; } }; return true; }
/// <summary> /// Modifies the order so it is more likely to fill /// </summary> public abstract bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice);