Example #1
0
        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);
                }
            }
        }
Example #2
0
        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);
                }
            }
        }
Example #3
0
        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);
        }
Example #4
0
 /// <summary>
 /// Creates and adds a new single <see cref="Option"/> contract to the algorithm
 /// </summary>
 /// <param name="symbol">The option 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="Option"/> security</returns>
 public Option AddOptionContract(Symbol symbol, Resolution resolution = Resolution.Minute, bool fillDataForward = true, decimal leverage = 0m)
 => _baseAlgorithm.AddOptionContract(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);
        }