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); } } }
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> /// Creates and adds a new single <see cref="Future"/> contract to the algorithm /// </summary> /// <param name="symbol">The futures contract symbol</param> /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param> /// <param name="fillDataForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param> /// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param> /// <returns>The new <see cref="Future"/> security</returns> public Future AddFutureContract(Symbol symbol, Resolution resolution = Resolution.Minute, bool fillDataForward = true, decimal leverage = 0m) => _baseAlgorithm.AddFutureContract(symbol, resolution, fillDataForward, leverage);
/// <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) { // verify we were given the correct job packet type var liveJob = job as LiveNodePacket; if (liveJob == null) { AddInitializationError("BrokerageSetupHandler requires a LiveNodePacket"); return(false); } algorithm.Name = liveJob.GetAlgorithmName(); // 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); //Margin calls are disabled by default in live mode algorithm.Portfolio.MarginCallModel = MarginCallModel.Null; //Set our parameters algorithm.SetParameters(job.Parameters); algorithm.SetAvailableDataTypes(GetConfiguredDataFeeds()); //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); // set the option chain provider algorithm.SetOptionChainProvider(new CachingOptionChainProvider(new LiveOptionChainProvider())); // If we're going to receive market data from IB, // set the default subscription limit to 100, // algorithms can override this setting in the Initialize method if (brokerage is InteractiveBrokersBrokerage && liveJob.DataQueueHandler.EndsWith("InteractiveBrokersBrokerage")) { algorithm.Settings.DataSubscriptionLimit = 100; } //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.ToString()); } }, controls.RamAllocation); 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; 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 { GetOpenOrders(algorithm, resultHandler, transactionHandler, brokerage); } 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, SecurityType.Option, SecurityType.Future, SecurityType.Crypto }; 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.Value); if (holding.Type == SecurityType.Option) { // add current option contract to the system algorithm.AddOptionContract(holding.Symbol, minResolution.Value, true, 1.0m); } else if (holding.Type == SecurityType.Future) { // add current future contract to the system algorithm.AddFutureContract(holding.Symbol, minResolution.Value, true, 1.0m); } else { // 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, 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.ToString()); } finally { if (brokerage != null) { brokerage.Message -= brokerageOnMessage; } } return(Errors.Count == 0); }