private void AddUnrequestedSecurity(IAlgorithm algorithm, Symbol symbol) { if (!algorithm.Portfolio.ContainsKey(symbol)) { var resolution = algorithm.UniverseSettings.Resolution; if (!_notifiedDefaultResolutionUsed) { // let's just send the message once _notifiedDefaultResolutionUsed = true; algorithm.Debug($"Will use UniverseSettings.Resolution value '{resolution}' for automatically added securities for open orders and holdings."); } Log.Trace("BrokerageSetupHandler.Setup(): Adding unrequested security: " + symbol.Value); if (symbol.SecurityType == SecurityType.Option || symbol.SecurityType == SecurityType.FutureOption) { // add current option contract to the system algorithm.AddOptionContract(symbol, resolution, true, 1.0m); } else if (symbol.SecurityType == SecurityType.Future) { // add current future contract to the system algorithm.AddFutureContract(symbol, resolution, true, 1.0m); } else { // for items not directly requested set leverage to 1 and at the min resolution algorithm.AddSecurity(symbol.SecurityType, symbol.Value, resolution, symbol.ID.Market, true, 1.0m, false); } } }
/// <summary> /// Wrapper for <see cref = "IAlgorithm.AddSecurity" /> in Python /// </summary> /// <param name="securityType"></param> /// <param name="symbol"></param> /// <param name="resolution"></param> /// <param name="market"></param> /// <param name="fillDataForward"></param> /// <param name="leverage"></param> /// <param name="extendedMarketHours"></param> /// <returns></returns> public Security AddSecurity(SecurityType securityType, string symbol, Resolution resolution, string market, bool fillDataForward, decimal leverage, bool extendedMarketHours) { using (Py.GIL()) { return(_algorithm.AddSecurity(securityType, symbol, resolution, market, fillDataForward, leverage, extendedMarketHours)); } }
/// <summary> /// Runs this command against the specified algorithm instance /// </summary> /// <param name="algorithm">The algorithm to run this command against</param> public CommandResultPacket Run(IAlgorithm algorithm) { try { var security = algorithm.AddSecurity(SecurityType, Symbol, Resolution, Market, FillDataForward, Leverage, ExtendedMarketHours); return new Result(this, true, security.Symbol); } catch (Exception err) { Log.Error(err); algorithm.Error("AddSecuityCommand Error: " + err.Message); return new Result(this, false, QuantConnect.Symbol.Empty); } }
private static void AddUnrequestedSecurity(IAlgorithm algorithm, Symbol symbol, Resolution minResolution) { if (!algorithm.Portfolio.ContainsKey(symbol)) { Log.Trace("BrokerageSetupHandler.Setup(): Adding unrequested security: " + symbol.Value); if (symbol.SecurityType == SecurityType.Option) { // add current option contract to the system algorithm.AddOptionContract(symbol, minResolution, true, 1.0m); } else if (symbol.SecurityType == SecurityType.Future) { // add current future contract to the system algorithm.AddFutureContract(symbol, minResolution, true, 1.0m); } else { // for items not directly requested set leverage to 1 and at the min resolution algorithm.AddSecurity(symbol.SecurityType, symbol.Value, minResolution, symbol.ID.Market, true, 1.0m, false); } } }
private Security AddUnrequestedSecurity(IAlgorithm algorithm, Symbol symbol) { if (!algorithm.Securities.TryGetValue(symbol, out Security security)) { var resolution = algorithm.UniverseSettings.Resolution; var fillForward = algorithm.UniverseSettings.FillForward; var leverage = algorithm.UniverseSettings.Leverage; var extendedHours = algorithm.UniverseSettings.ExtendedMarketHours; if (!_notifiedUniverseSettingsUsed) { // let's just send the message once _notifiedUniverseSettingsUsed = true; algorithm.Debug($"Will use UniverseSettings for automatically added securities for open orders and holdings. UniverseSettings:" + $" Resolution = {resolution}; Leverage = {leverage}; FillForward = {fillForward}; ExtendedHours = {extendedHours}"); } Log.Trace("BrokerageSetupHandler.Setup(): Adding unrequested security: " + symbol.Value); if (symbol.SecurityType.IsOption()) { // add current option contract to the system security = algorithm.AddOptionContract(symbol, resolution, fillForward, leverage); } else if (symbol.SecurityType == SecurityType.Future) { // add current future contract to the system security = algorithm.AddFutureContract(symbol, resolution, fillForward, leverage); } else { // for items not directly requested set leverage to 1 and at the min resolution security = algorithm.AddSecurity(symbol.SecurityType, symbol.Value, resolution, symbol.ID.Market, fillForward, leverage, extendedHours); } } return(security); }
/// <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..."); resultHandler.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Initializing, "Initializing algorithm..."); //Execute the initialize code: var isolator = new Isolator(); var initializeComplete = isolator.ExecuteWithTimeLimit(TimeSpan.FromSeconds(300), () => { 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 and settlement models based on the brokerage properties SetupHandler.UpdateModels(algorithm, algorithm.BrokerageModel); algorithm.Transactions.SetOrderProcessor(transactionHandler); algorithm.PostInitialize(); 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.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); } 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 + " - " + 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 }; var minResolution = new Lazy <Resolution>(() => algorithm.Securities.Min(x => x.Value.Resolution)); foreach (var holding in holdings) { var symbol = new Symbol(holding.Symbol); 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.ToUpper()); 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(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, symbol, minResolution.Value, null, true, 1.0m, false); } algorithm.Portfolio[symbol].SetHoldings(holding.AveragePrice, (int)holding.Quantity); algorithm.Securities[symbol].SetMarketPrice(new TradeBar { Time = DateTime.Now, Open = holding.MarketPrice, High = holding.MarketPrice, Low = holding.MarketPrice, Close = holding.MarketPrice, Volume = 0, Symbol = symbol, DataType = MarketDataType.TradeBar }); } } catch (Exception err) { Log.Error(err); AddInitializationError("Error getting account holdings from brokerage: " + err.Message); return(false); } Log.Trace("BrokerageSetupHandler.Setup(): Ensuring currency data feeds present..."); // 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> /// Set a required SecurityType-symbol and resolution for algorithm /// </summary> /// <param name="securityType">SecurityType Enum: Equity, Commodity, FOREX or Future</param> /// <param name="symbol">Symbol Representation of the MarketType, e.g. AAPL</param> /// <param name="resolution">Resolution of the MarketType required: MarketData, Second or Minute</param> /// <param name="market">The market the requested security belongs to, such as 'usa' or 'fxcm'</param> /// <param name="fillDataForward">If true, returns the last available data even if none in that timeslice.</param> /// <param name="leverage">leverage for this security</param> /// <param name="extendedMarketHours">ExtendedMarketHours send in data from 4am - 8pm, not used for FOREX</param> public Security AddSecurity(SecurityType securityType, string symbol, Resolution resolution, string market, bool fillDataForward, decimal leverage, bool extendedMarketHours) => _baseAlgorithm.AddSecurity(securityType, symbol, resolution, market, fillDataForward, leverage, extendedMarketHours);
/// <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 default markets algorithm.SetDefaultMarkets(_factory.DefaultMarkets.ToDictionary()); //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); algorithm.PostInitialize(); 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 }; 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); } //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> /// 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; }
public CommandResultPacket Run(IAlgorithm algorithm) { var security = algorithm.AddSecurity(SecurityType, Symbol, Resolution, Market, FillDataForward, Leverage, ExtendedMarketHours); return(new Result(this, true, security.Symbol)); }
/// <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> /// 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> /// <returns>True on successfully setting up the algorithm state, or false on error.</returns> public bool Setup(IAlgorithm algorithm, out IBrokerage brokerage, AlgorithmNodePacket job) { _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); } try { Log.Trace("BrokerageSetupHandler.Setup(): Initializing algorithm..."); //Execute the initialize code: 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); //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 Engine.ResultHandler.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.LoggingIn, "Logging into brokerage..."); // initialize the correct brokerage using the resolved factory brokerage = _factory.CreateBrokerage(liveJob, algorithm); // set the transaction models base on the brokerage properties SetupHandler.UpdateTransactionModels(algorithm, algorithm.BrokerageModel); 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."); 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."); 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(); algorithm.Orders.AddOrUpdate(order.Id, order, (i, o) => order); } } catch (Exception err) { Log.Error(err); AddInitializationError("Error getting open orders from brokerage."); 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, true, 1.0m, false); } algorithm.Portfolio[holding.Symbol].SetHoldings(holding.AveragePrice, (int)holding.Quantity); algorithm.Securities[holding.Symbol].SetMarketPrice(DateTime.Now, 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."); 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); //Set the starting portfolio value for the strategy to calculate performance: StartingPortfolioValue = algorithm.Portfolio.TotalPortfolioValue; StartingDate = DateTime.Now; } catch (Exception err) { AddInitializationError(err.Message); } return(Errors.Count == 0); }
/// <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> /// <returns>True on successfully setting up the algorithm state, or false on error.</returns> public bool Setup(IAlgorithm algorithm, out IBrokerage brokerage, AlgorithmNodePacket job) { _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); } try { //Execute the initialize code: 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, 10, 5); break; } //Algorithm is live, not backtesting: algorithm.SetLiveMode(true); //Initialise the algorithm, get the required data: algorithm.Initialize(); } catch (Exception err) { AddInitializationError(err.Message); } }); if (!initializeComplete) { AddInitializationError("Failed to initialize algorithm."); return(false); } // find the correct brokerage factory based on the specified brokerage in the live job packet var brokerageFactory = Composer.Instance.Single <IBrokerageFactory>(factory => factory.BrokerageType.MatchesTypeName(liveJob.Brokerage)); // initialize the correct brokerage using the resolved factory brokerage = brokerageFactory.CreateBrokerage(liveJob, algorithm); brokerage.Connect(); // set the algorithm's cash balance for each currency var cashBalance = brokerage.GetCashBalance(); foreach (var item in cashBalance) { algorithm.SetCash(item.Key, item.Value, 0); } // 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 order.Id = algorithm.Transactions.GetIncrementOrderId(); algorithm.Orders.AddOrUpdate(order.Id, order, (i, o) => order); } // 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) { if (!algorithm.Portfolio.ContainsKey(holding.Symbol)) { // for items not directly requested set leverage to 1 and at the min resolution algorithm.AddSecurity(holding.Type, holding.Symbol, minResolution.Value, true, 1.0m, false); } algorithm.Portfolio[holding.Symbol].SetHoldings(holding.AveragePrice, (int)holding.Quantity); algorithm.Securities[holding.Symbol].Update(DateTime.Now, new TradeBar { Time = DateTime.Now, Open = holding.AveragePrice, High = holding.AveragePrice, Low = holding.AveragePrice, Close = holding.AveragePrice, Volume = 0, Symbol = holding.Symbol, DataType = MarketDataType.TradeBar }); } // 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); //Set the starting capital for the strategy to calculate performance: StartingCapital = algorithm.Portfolio.Cash; StartingDate = DateTime.Now; } catch (Exception err) { AddInitializationError(err.Message); } return(Errors.Count == 0); }
/// <summary> /// Set a required SecurityType-symbol and resolution for algorithm /// </summary> /// <param name="securityType">SecurityType Enum: Equity, Commodity, FOREX or Future</param> /// <param name="symbol">Symbol Representation of the MarketType, e.g. AAPL</param> /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily.</param> /// <param name="market">The market the requested security belongs to, such as 'usa' or 'fxcm'</param> /// <param name="fillDataForward">If true, returns the last available data even if none in that timeslice.</param> /// <param name="leverage">leverage for this security</param> /// <param name="extendedMarketHours">ExtendedMarketHours send in data from 4am - 8pm, not used for FOREX</param> /// <param name="dataMappingMode">The contract mapping mode to use for the security</param> /// <param name="dataNormalizationMode">The price scaling mode to use for the security</param> public Security AddSecurity(SecurityType securityType, string symbol, Resolution?resolution, string market, bool fillDataForward, decimal leverage, bool extendedMarketHours, DataMappingMode?dataMappingMode = null, DataNormalizationMode?dataNormalizationMode = null) => _baseAlgorithm.AddSecurity(securityType, symbol, resolution, market, fillDataForward, leverage, extendedMarketHours, dataMappingMode, dataNormalizationMode);
/// <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="baseJob">Algorithm job task</param> /// <returns>True on successfully setting up the algorithm state, or false on error.</returns> public bool Setup(IAlgorithm algorithm, out IBrokerage brokerage, AlgorithmNodePacket baseJob) { //-> Initialize: var initializeComplete = false; var job = baseJob as LiveNodePacket; var portfolioResolution = PortfolioResolution(algorithm.Securities); //-> Connect to Tradier: _tradier = new TradierBrokerage(); //_tradier = (Tradier)brokerage; _tradier.SetTokens(job.UserId, job.AccessToken, job.RefreshToken, job.IssuedAt, job.LifeTime); brokerage = _tradier; // -> Refresh the session immediately, buy us 24 hours: if (!_tradier.RefreshSession()) { Errors.Add("Failed to refresh access token. Please login again."); return(false); } //-> Setup any user specific code: try { algorithm.Initialize(); } catch (Exception err) { Errors.Add("Failed to initialize user algorithm, Initialize() returned error - " + err.Message); return(false); } Log.Trace("TradierSetupHandler.Setup(): Algorithm initialized"); //-> Strip any FOREX Symbols: var symbols = algorithm.Securities.Keys.ToList(); foreach (var symbol in symbols) { if (algorithm.Securities[symbol].Type == SecurityType.Forex) { algorithm.Securities.Remove(symbol); } } //-> Fetch the orders on the account: var orders = _tradier.FetchOrders(job.AccountId); foreach (var order in orders) { //Ignore option orders for now. if (order.Class != TradierOrderClass.Equity) { continue; } var qcPrice = order.Price; var qcQuantity = order.Quantity; var qcType = OrderType.Limit; var qcStatus = OrderStatus.None; // Get the order type: switch (order.Type) { case TradierOrderType.Market: qcType = OrderType.Market; break; case TradierOrderType.Limit: qcType = OrderType.Limit; break; case TradierOrderType.StopMarket: qcType = OrderType.StopMarket; break; } // Convert order direction to a quantity switch (order.Direction) { case TradierOrderDirection.Buy: case TradierOrderDirection.BuyToCover: break; case TradierOrderDirection.Sell: case TradierOrderDirection.SellShort: qcQuantity *= -1; //Invert quantity. break; } //Set the QC Order Status Flag: switch (order.Status) { case TradierOrderStatus.Canceled: qcStatus = OrderStatus.Canceled; break; case TradierOrderStatus.Filled: qcStatus = OrderStatus.Filled; break; case TradierOrderStatus.Open: case TradierOrderStatus.Submitted: case TradierOrderStatus.Pending: qcStatus = OrderStatus.Submitted; break; case TradierOrderStatus.PartiallyFilled: qcStatus = OrderStatus.PartiallyFilled; break; case TradierOrderStatus.Rejected: qcStatus = OrderStatus.Invalid; break; } //Create the new qcOrder var qcOrder = new Order(order.Symbol, Convert.ToInt32((decimal)qcQuantity), qcType, order.CreatedDate, qcPrice); //Set Status for Order: qcOrder.Status = qcStatus; //Create any fill information: var fill = new OrderEvent(qcOrder, "Pre-existing Tradier Order"); fill.FillPrice = order.AverageFillPrice; fill.FillQuantity = Convert.ToInt32((decimal)order.QuantityExecuted); var fillList = new List <OrderEvent>() { fill }; //Get a unique qc-id: set to fill var qcid = algorithm.Transactions.GetIncrementOrderId(); order.Id = qcid; fill.OrderId = qcid; qcOrder.Id = qcid; //Add the order to our internal records: algorithm.Transactions.Orders.AddOrUpdate <int, Order>(Convert.ToInt32((long)order.Id), qcOrder); //Add the fill quantity to the list: algorithm.Transactions.OrderEvents.AddOrUpdate <int, List <OrderEvent> >(Convert.ToInt32((long)order.Id), fillList); //If we don't have this symbol, add it manually: if (!algorithm.Portfolio.ContainsKey(order.Symbol)) { algorithm.AddSecurity(SecurityType.Equity, order.Symbol, portfolioResolution, true, 1, false); } } //-> Retrieve/Set Tradier Portfolio Positions: var positions = _tradier.Positions(job.AccountId); foreach (var position in positions) { //We can't support options. if (position.Symbol.Length >= 10) { continue; } //If we don't have this symbol, add it manually: if (!algorithm.Portfolio.ContainsKey(position.Symbol)) { algorithm.AddSecurity(SecurityType.Equity, position.Symbol, portfolioResolution, true, 1, false); } //Once we have the symbol, set the holdings: var avgPrice = Math.Round(position.CostBasis / Convert.ToDecimal((long)position.Quantity), 4); algorithm.Portfolio[position.Symbol].SetHoldings(avgPrice, (int)position.Quantity); Log.Trace("TradierSetupHandler.Setup(): Portfolio security added to algorithm: " + position.Symbol + " with " + position.Quantity + " shares at " + avgPrice.ToString("C")); } //-> Retrieve/Set Tradier Cash Positions: var balanceFound = false; //HACK: //balanceFound = true; //algorithm.Portfolio.SetCash(100000); //_startingCapital = 100000; var balance = _tradier.Balance(job.AccountId); if (balance != null) { if (balance.AccountNumber == job.AccountId) { //Set the cash in this account: var cash = balance.TotalCash - balance.OptionRequirement; algorithm.Portfolio.SetCash(cash); StartingCapital = cash; balanceFound = true; Log.Trace("TradierSetupHandler.Setup(): Free Cash: " + cash.ToString("C")); Log.Trace("TradierSetupHandler.Setup(): Total Cash: " + balance.TotalCash.ToString("C")); } //Set the leverage on all the securities: switch (balance.Type) { //Maximum 1x Leverage case TradierAccountType.Cash: foreach (var security in algorithm.Securities.Values) { if (security.Type == SecurityType.Equity) { security.SetLeverage(1m); } } break; //Maximum 2x Leverage case TradierAccountType.Margin: foreach (var security in algorithm.Securities.Values) { if (security.Type == SecurityType.Equity && security.Leverage > 2) { security.SetLeverage(2m); } } break; case TradierAccountType.DayTrader: //Do nothing, let the user set their own leverage: foreach (var security in algorithm.Securities.Values) { if (security.Type == SecurityType.Equity && security.Leverage > 4) { security.SetLeverage(4m); } } break; } } // Maximum number of orders or the algorithm MaxOrders = int.MaxValue; if (!balanceFound) { Errors.Add("Could not get the account cash balance"); } if (Errors.Count == 0) { initializeComplete = true; } return(initializeComplete); }
/// <summary> /// Runs this command against the specified algorithm instance /// </summary> /// <param name="algorithm">The algorithm to run this command against</param> public CommandResultPacket Run(IAlgorithm algorithm) { var security = algorithm.AddSecurity(SecurityType, Symbol, Resolution, Market, FillDataForward, Leverage, ExtendedMarketHours); return new Result(this, true, security.Symbol); }