/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using NodaTime; using NodaTime.TimeZones; using QuantConnect.Benchmarks; using QuantConnect.Brokerages; using QuantConnect.Data; using QuantConnect.Data.Auxiliary; using QuantConnect.Data.UniverseSelection; using QuantConnect.Interfaces; using QuantConnect.Notifications; using QuantConnect.Orders; using QuantConnect.Parameters; using QuantConnect.Scheduling; using QuantConnect.Securities; using QuantConnect.Securities.Cfd; using QuantConnect.Securities.Equity; using QuantConnect.Securities.Forex; using QuantConnect.Securities.Option; using QuantConnect.Statistics; using QuantConnect.Util; using System.Collections.Concurrent; using QuantConnect.Securities.Future; using QuantConnect.Securities.Crypto; using System.Net; using QuantConnect.Algorithm.Framework.Alphas; using QuantConnect.Algorithm.Framework.Alphas.Analysis.Providers; using QuantConnect.Algorithm.Framework.Execution; using QuantConnect.Algorithm.Framework.Portfolio; using QuantConnect.Algorithm.Framework.Risk; using QuantConnect.Algorithm.Framework.Selection; namespace QuantConnect.Algorithm { /// /// QC Algorithm Base Class - Handle the basic requirements of a trading algorithm, /// allowing user to focus on event methods. The QCAlgorithm class implements Portfolio, /// Securities, Transactions and Data Subscription Management. /// public partial class QCAlgorithm : MarshalByRefObject, IAlgorithm { private readonly TimeKeeper _timeKeeper; private LocalTimeKeeper _localTimeKeeper; private DateTime _startDate; //Default start and end dates. private DateTime _endDate; //Default end to yesterday private RunMode _runMode = RunMode.Series; private bool _locked; private bool _liveMode; private string _algorithmId = ""; private ConcurrentQueue _debugMessages = new ConcurrentQueue(); private ConcurrentQueue _logMessages = new ConcurrentQueue(); private ConcurrentQueue _errorMessages = new ConcurrentQueue(); //Error tracking to avoid message flooding: private string _previousDebugMessage = ""; private string _previousErrorMessage = ""; /// /// Gets the market hours database in use by this algorithm /// protected MarketHoursDatabase MarketHoursDatabase { get; } // used for calling through to void OnData(Slice) if no override specified private bool _checkedForOnDataSlice; private Action _onDataSlice; // set by SetBenchmark helper API functions private Symbol _benchmarkSymbol = QuantConnect.Symbol.Empty; // flips to true when the user private bool _userSetSecurityInitializer = false; // warmup resolution variables private TimeSpan? _warmupTimeSpan; private int? _warmupBarCount; private Resolution? _warmupResolution; private Dictionary _parameters = new Dictionary(); private readonly HistoryRequestFactory _historyRequestFactory; private readonly OrderBasedInsightGenerator _orderBasedInsightGenerator; private bool _emitAutogeneratedOrderBasedInsight; private bool _autogeneratedOrderBasedInsightWasCalled; private bool _emitInsightWasCalled; private IApi _api; /// /// QCAlgorithm Base Class Constructor - Initialize the underlying QCAlgorithm components. /// QCAlgorithm manages the transactions, portfolio, charting and security subscriptions for the users algorithms. /// public QCAlgorithm() { Name = GetType().Name; Status = AlgorithmStatus.Running; // AlgorithmManager will flip this when we're caught up with realtime IsWarmingUp = true; //Initialise the Algorithm Helper Classes: //- Note - ideally these wouldn't be here, but because of the DLL we need to make the classes shared across // the Worker & Algorithm, limiting ability to do anything else. //Initialise Start and End Dates: _startDate = new DateTime(1998, 01, 01); _endDate = DateTime.Now.AddDays(-1); // intialize our time keeper with only new york _timeKeeper = new TimeKeeper(_startDate, new[] { TimeZones.NewYork }); // set our local time zone _localTimeKeeper = _timeKeeper.GetLocalTimeKeeper(TimeZones.NewYork); Settings = new AlgorithmSettings(); DefaultOrderProperties = new OrderProperties(); //Initialise Data Manager SubscriptionManager = new SubscriptionManager(); Securities = new SecurityManager(_timeKeeper); Transactions = new SecurityTransactionManager(this, Securities); Portfolio = new SecurityPortfolioManager(Securities, Transactions, DefaultOrderProperties); BrokerageModel = new DefaultBrokerageModel(); Notify = new NotificationManager(false); // Notification manager defaults to disabled. //Initialise Algorithm RunMode to Series - Parallel Mode deprecated: _runMode = RunMode.Series; //Initialise to unlocked: _locked = false; // get exchange hours loaded from the market-hours-database.csv in /Data/market-hours MarketHoursDatabase = MarketHoursDatabase.FromDataFolder(); // universe selection UniverseManager = new UniverseManager(); Universe = new UniverseDefinitions(this); UniverseSettings = new UniverseSettings(Resolution.Minute, 2m, true, false, TimeSpan.FromDays(1)); // initialize our scheduler, this acts as a liason to the real time handler Schedule = new ScheduleManager(Securities, TimeZone); // initialize the trade builder TradeBuilder = new TradeBuilder(FillGroupingMethod.FillToFill, FillMatchingMethod.FIFO); SecurityInitializer = new BrokerageModelSecurityInitializer(new DefaultBrokerageModel(AccountType.Margin), SecuritySeeder.Null); CandlestickPatterns = new CandlestickPatterns(this); // initialize trading calendar TradingCalendar = new TradingCalendar(Securities, MarketHoursDatabase); OptionChainProvider = new EmptyOptionChainProvider(); FutureChainProvider = new EmptyFutureChainProvider(); _historyRequestFactory = new HistoryRequestFactory(this); _orderBasedInsightGenerator = new OrderBasedInsightGenerator(); // Framework _securityValuesProvider = new AlgorithmSecurityValuesProvider(this); // set model defaults, universe selection set via PostInitialize SetAlpha(new NullAlphaModel()); SetPortfolioConstruction(new NullPortfolioConstructionModel()); SetExecution(new ImmediateExecutionModel()); SetRiskManagement(new NullRiskManagementModel()); SetUniverseSelection(new NullUniverseSelectionModel()); } /// /// Event fired when the algorithm generates insights /// public event AlgorithmEvent InsightsGenerated; /// /// Security collection is an array of the security objects such as Equities and FOREX. Securities data /// manages the properties of tradeable assets such as price, open and close time and holdings information. /// public SecurityManager Securities { get; set; } /// /// Read-only dictionary containing all active securities. An active security is /// a security that is currently selected by the universe or has holdings or open orders. /// public IReadOnlyDictionary ActiveSecurities => UniverseManager.ActiveSecurities; /// /// Portfolio object provieds easy access to the underlying security-holding properties; summed together in a way to make them useful. /// This saves the user time by providing common portfolio requests in a single /// public SecurityPortfolioManager Portfolio { get; set; } /// /// Gets the account currency /// public string AccountCurrency => Portfolio.CashBook.AccountCurrency; /// /// Gets the time keeper instance /// public ITimeKeeper TimeKeeper => _timeKeeper; /// /// Generic Data Manager - Required for compiling all data feeds in order, and passing them into algorithm event methods. /// The subscription manager contains a list of the data feed's we're subscribed to and properties of each data feed. /// public SubscriptionManager SubscriptionManager { get; set; } /// /// Gets the brokerage model - used to model interactions with specific brokerages. /// public IBrokerageModel BrokerageModel { get; private set; } /// /// Gets the brokerage message handler used to decide what to do /// with each message sent from the brokerage /// public IBrokerageMessageHandler BrokerageMessageHandler { get; set; } /// /// Notification Manager for Sending Live Runtime Notifications to users about important events. /// public NotificationManager Notify { get; set; } /// /// Gets schedule manager for adding/removing scheduled events /// public ScheduleManager Schedule { get; private set; } /// /// Gets or sets the current status of the algorithm /// public AlgorithmStatus Status { get; set; } /// /// Gets an instance that is to be used to initialize newly created securities. /// public ISecurityInitializer SecurityInitializer { get; private set; } /// /// Gets the Trade Builder to generate trades from executions /// public ITradeBuilder TradeBuilder { get; private set; } /// /// Gets an instance to access the candlestick pattern helper methods /// public CandlestickPatterns CandlestickPatterns { get; private set; } /// /// Gets the date rules helper object to make specifying dates for events easier /// public DateRules DateRules { get { return Schedule.DateRules; } } /// /// Gets the time rules helper object to make specifying times for events easier /// public TimeRules TimeRules { get { return Schedule.TimeRules; } } /// /// Gets trading calendar populated with trading events /// public TradingCalendar TradingCalendar { get; private set; } /// /// Gets the user settings for the algorithm /// public IAlgorithmSettings Settings { get; private set; } /// /// Gets the option chain provider, used to get the list of option contracts for an underlying symbol /// public IOptionChainProvider OptionChainProvider { get; private set; } /// /// Gets the future chain provider, used to get the list of future contracts for an underlying symbol /// public IFutureChainProvider FutureChainProvider { get; private set; } /// /// Gets the default order properties /// public IOrderProperties DefaultOrderProperties { get; set; } /// /// Public name for the algorithm as automatically generated by the IDE. Intended for helping distinguish logs by noting /// the algorithm-id. /// /// public string Name { get; set; } /// /// Read-only value for current time frontier of the algorithm in terms of the /// /// During backtesting this is primarily sourced from the data feed. During live trading the time is updated from the system clock. public DateTime Time { get { return _localTimeKeeper.LocalTime; } } /// /// Current date/time in UTC. /// public DateTime UtcTime { get { return _timeKeeper.UtcTime; } } /// /// Gets the time zone used for the property. The default value /// is /// public DateTimeZone TimeZone { get { return _localTimeKeeper.TimeZone; } } /// /// Value of the user set start-date from the backtest. /// /// This property is set with SetStartDate() and defaults to the earliest QuantConnect data available - Jan 1st 1998. It is ignored during live trading /// public DateTime StartDate { get { return _startDate; } } /// /// Value of the user set start-date from the backtest. Controls the period of the backtest. /// /// This property is set with SetEndDate() and defaults to today. It is ignored during live trading. /// public DateTime EndDate { get { return _endDate; } } /// /// Algorithm Id for this backtest or live algorithm. /// /// A unique identifier for public string AlgorithmId { get { return _algorithmId; } } /// /// Control the server setup run style for the backtest: Automatic, Parallel or Series. /// /// /// Series mode runs all days through one computer, allowing memory of the previous days. /// Parallel mode runs all days separately which maximises speed but gives no memory of a previous day trading. /// /// The RunMode enum propert is now obsolete. All algorithms will default to RunMode.Series for series backtests. [Obsolete("The RunMode enum propert is now obsolete. All algorithms will default to RunMode.Series for series backtests.")] public RunMode RunMode { get { return _runMode; } } /// /// Boolean property indicating the algorithm is currently running in live mode. /// /// Intended for use where certain behaviors will be enabled while the algorithm is trading live: such as notification emails, or displaying runtime statistics. public bool LiveMode { get { return _liveMode; } } /// /// Storage for debugging messages before the event handler has passed control back to the Lean Engine. /// /// public ConcurrentQueue DebugMessages { get { return _debugMessages; } set { _debugMessages = value; } } /// /// Storage for log messages before the event handlers have passed control back to the Lean Engine. /// /// public ConcurrentQueue LogMessages { get { return _logMessages; } set { _logMessages = value; } } /// /// Gets the run time error from the algorithm, or null if none was encountered. /// public Exception RunTimeError { get; set; } /// /// List of error messages generated by the user's code calling the "Error" function. /// /// This method is best used within a try-catch bracket to handle any runtime errors from a user algorithm. /// public ConcurrentQueue ErrorMessages { get { return _errorMessages; } set { _errorMessages = value; } } /// /// Returns the current Slice object /// public Slice CurrentSlice { get; private set; } /// /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized. /// /// /// /// public virtual void Initialize() { //Setup Required Data throw new NotImplementedException("Please override the Initialize() method"); } /// /// Called by setup handlers after Initialize and allows the algorithm a chance to organize /// the data gather in the Initialize method /// public virtual void PostInitialize() { FrameworkPostInitialize(); // if the benchmark hasn't been set yet, set it if (Benchmark == null) { if (_benchmarkSymbol != null) { // if the requested benchmark symbol wasn't already added, then add it now // we do a simple compare here for simplicity, also it avoids confusion over // the desired market. Security security; if (!Securities.TryGetValue(_benchmarkSymbol, out security)) { // add the security as an internal feed so the algorithm doesn't receive the data security = CreateBenchmarkSecurity(); } // just return the current price Benchmark = new SecurityBenchmark(security); } else { var start = StartDate; var startingCapital = Portfolio.TotalPortfolioValue; Benchmark = new FuncBenchmark(dt => { var years = (dt - start).TotalDays / 365.25; return startingCapital * (decimal) Math.Exp(0.02 * years); }); } } // perform end of time step checks, such as enforcing underlying securities are in raw data mode OnEndOfTimeStep(); } /// /// Called when the algorithm has completed initialization and warm up. /// public virtual void OnWarmupFinished() { } /// /// Gets the parameter with the specified name. If a parameter /// with the specified name does not exist, null is returned /// /// The name of the parameter to get /// The value of the specified parameter, or null if not found public string GetParameter(string name) { string value; return _parameters.TryGetValue(name, out value) ? value : null; } /// /// Gets a read-only dictionary with all current parameters /// public IReadOnlyDictionary GetParameters() { return _parameters.ToReadOnlyDictionary(); } /// /// Sets the parameters from the dictionary /// /// Dictionary containing the parameter names to values public void SetParameters(Dictionary parameters) { // save off a copy and try to apply the parameters _parameters = parameters.ToDictionary(); try { ParameterAttribute.ApplyAttributes(parameters, this); } catch (Exception err) { Error("Error applying parameter values: " + err.Message); } } /// /// Set the available data feeds in the /// /// The different each supports public void SetAvailableDataTypes(Dictionary> availableDataTypes) { foreach (var dataFeed in availableDataTypes) { SubscriptionManager.AvailableDataTypes[dataFeed.Key] = dataFeed.Value; } } /// /// Sets the security initializer, used to initialize/configure securities after creation. /// The initializer will be applied to all universes and manually added securities. /// /// The security initializer public void SetSecurityInitializer(ISecurityInitializer securityInitializer) { if (_locked) { throw new Exception("SetSecurityInitializer() cannot be called after algorithm initialization. " + "When you use the SetSecurityInitializer() method it will apply to all universes and manually added securities."); } if (_userSetSecurityInitializer) { Debug("Warning: SetSecurityInitializer() has already been called, existing security initializers in all universes will be overwritten."); } // this flag will prevent calls to SetBrokerageModel from overwriting this initializer _userSetSecurityInitializer = true; SecurityInitializer = securityInitializer; } /// /// Sets the security initializer function, used to initialize/configure securities after creation. /// The initializer will be applied to all universes and manually added securities. /// /// The security initializer function [Obsolete("This method is deprecated. Please use this overload: SetSecurityInitializer(Action securityInitializer)")] public void SetSecurityInitializer(Action securityInitializer) { SetSecurityInitializer(new FuncSecurityInitializer(security => securityInitializer(security, false))); } /// /// Sets the security initializer function, used to initialize/configure securities after creation. /// The initializer will be applied to all universes and manually added securities. /// /// The security initializer function public void SetSecurityInitializer(Action securityInitializer) { SetSecurityInitializer(new FuncSecurityInitializer(securityInitializer)); } /// /// Sets the option chain provider, used to get the list of option contracts for an underlying symbol /// /// The option chain provider public void SetOptionChainProvider(IOptionChainProvider optionChainProvider) { OptionChainProvider = optionChainProvider; } /// /// Sets the future chain provider, used to get the list of future contracts for an underlying symbol /// /// The future chain provider public void SetFutureChainProvider(IFutureChainProvider futureChainProvider) { FutureChainProvider = futureChainProvider; } /// /// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event /// /// /// TradeBars bars = slice.Bars; /// Ticks ticks = slice.Ticks; /// TradeBar spy = slice["SPY"]; /// List{Tick} aaplTicks = slice["AAPL"] /// Quandl oil = slice["OIL"] /// dynamic anySymbol = slice[symbol]; /// DataDictionary{Quandl} allQuandlData = slice.Get{Quand} /// Quandl oil = slice.Get{Quandl}("OIL") /// /// The current slice of data keyed by symbol string public virtual void OnData(Slice slice) { // as a default implementation, let's look for and call OnData(Slice) just in case a user forgot to use the override keyword if (!_checkedForOnDataSlice) { _checkedForOnDataSlice = true; var method = GetType().GetMethods() .Where(x => x.Name == "OnData") .Where(x => x.DeclaringType != typeof(QCAlgorithm)) .Where(x => x.GetParameters().Length == 1) .FirstOrDefault(x => x.GetParameters()[0].ParameterType == typeof (Slice)); if (method == null) { return; } var self = Expression.Constant(this); var parameter = Expression.Parameter(typeof (Slice), "data"); var call = Expression.Call(self, method, parameter); var lambda = Expression.Lambda>(call, parameter); _onDataSlice = lambda.Compile(); } // if we have it, then invoke it if (_onDataSlice != null) { _onDataSlice(slice); } } /// /// Event fired each time the we add/remove securities from the data feed /// /// Security additions/removals for this time step public virtual void OnSecuritiesChanged(SecurityChanges changes) { } // // Event - v2.0 TRADEBAR EVENT HANDLER: (Pattern) Basic template for user to override when requesting tradebar data. // // //public void OnData(TradeBars data) //{ // //} // // Event - v2.0 QUOTEBAR EVENT HANDLER: (Pattern) Basic template for user to override when requesting quotebar data. // // //public void OnData(QuoteBars data) //{ // //} // // Event - v2.0 TICK EVENT HANDLER: (Pattern) Basic template for user to override when requesting tick data. // // List of Tick Data //public void OnData(Ticks data) //{ // //} // // Event - v2.0 OPTIONCHAIN EVENT HANDLER: (Pattern) Basic template for user to override when requesting option data. // // List of Tick Data //public void OnData(OptionChains data) //{ // //} // // Event - v2.0 SPLIT EVENT HANDLER: (Pattern) Basic template for user to override when inspecting split data. // // IDictionary of Split Data Keyed by Symbol String //public void OnData(Splits data) //{ // //} // // Event - v2.0 DIVIDEND EVENT HANDLER: (Pattern) Basic template for user to override when inspecting dividend data // // IDictionary of Dividend Data Keyed by Symbol String //public void OnData(Dividends data) //{ // //} // // Event - v2.0 DELISTING EVENT HANDLER: (Pattern) Basic template for user to override when inspecting delisting data // // IDictionary of Delisting Data Keyed by Symbol String //public void OnData(Delistings data) // // Event - v2.0 SYMBOL CHANGED EVENT HANDLER: (Pattern) Basic template for user to override when inspecting symbol changed data // // IDictionary of SymbolChangedEvent Data Keyed by Symbol String //public void OnData(SymbolChangedEvents data) /// /// Margin call event handler. This method is called right before the margin call orders are placed in the market. /// /// The orders to be executed to bring this algorithm within margin limits public virtual void OnMarginCall(List requests) { } /// /// Margin call warning event handler. This method is called when Portfolio.MarginRemaining is under 5% of your Portfolio.TotalPortfolioValue /// public virtual void OnMarginCallWarning() { } /// /// End of a trading day event handler. This method is called at the end of the algorithm day (or multiple times if trading multiple assets). /// /// Method is called 10 minutes before closing to allow user to close out position. /// Deprecated because different assets have different market close times, /// and because Python does not support two methods with the same name [Obsolete("This method is deprecated. Please use this overload: OnEndOfDay(Symbol symbol)")] public virtual void OnEndOfDay() { } /// /// End of a trading day event handler. This method is called at the end of the algorithm day (or multiple times if trading multiple assets). /// /// /// This method is left for backwards compatibility and is invoked via , if that method is /// override then this method will not be called without a called to base.OnEndOfDay(string) /// /// Asset symbol for this end of day event. Forex and equities have different closing hours. public virtual void OnEndOfDay(string symbol) { } /// /// End of a trading day event handler. This method is called at the end of the algorithm day (or multiple times if trading multiple assets). /// /// Asset symbol for this end of day event. Forex and equities have different closing hours. public virtual void OnEndOfDay(Symbol symbol) { OnEndOfDay(symbol.ToString()); } /// /// End of algorithm run event handler. This method is called at the end of a backtest or live trading operation. Intended for closing out logs. /// public virtual void OnEndOfAlgorithm() { } /// /// Order fill event handler. On an order fill update the resulting information is passed to this method. /// /// Order event details containing details of the evemts /// This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects public virtual void OnOrderEvent(OrderEvent orderEvent) { } /// /// Option assignment event handler. On an option assignment event for short legs the resulting information is passed to this method. /// /// Option exercise event details containing details of the assignment /// This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects public virtual void OnAssignmentOrderEvent(OrderEvent assignmentEvent) { } /// /// Brokerage message event handler. This method is called for all types of brokerage messages. /// public virtual void OnBrokerageMessage(BrokerageMessageEvent messageEvent) { } /// /// Brokerage disconnected event handler. This method is called when the brokerage connection is lost. /// public virtual void OnBrokerageDisconnect() { } /// /// Brokerage reconnected event handler. This method is called when the brokerage connection is restored after a disconnection. /// public virtual void OnBrokerageReconnect() { } /// /// Update the internal algorithm time frontier. /// /// For internal use only to advance time. /// Current datetime. public void SetDateTime(DateTime frontier) { _timeKeeper.SetUtcDateTime(frontier); } /// /// Sets the time zone of the property in the algorithm /// /// The desired time zone public void SetTimeZone(string timeZone) { DateTimeZone tz; try { tz = DateTimeZoneProviders.Tzdb[timeZone]; } catch (DateTimeZoneNotFoundException) { throw new ArgumentException(string.Format("TimeZone with id '{0}' was not found. For a complete list of time zones please visit: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones", timeZone)); } SetTimeZone(tz); } /// /// Sets the time zone of the property in the algorithm /// /// The desired time zone public void SetTimeZone(DateTimeZone timeZone) { if (_locked) { throw new Exception("Algorithm.SetTimeZone(): Cannot change time zone after algorithm running."); } if (timeZone == null) throw new ArgumentNullException("timeZone"); _timeKeeper.AddTimeZone(timeZone); _localTimeKeeper = _timeKeeper.GetLocalTimeKeeper(timeZone); // the time rules need to know the default time zone as well TimeRules.SetDefaultTimeZone(timeZone); // reset the current time according to the time zone SetDateTime(_startDate.ConvertToUtc(TimeZone)); } /// /// Set the RunMode for the Servers. If you are running an overnight algorithm, you must select series. /// Automatic will analyse the selected data, and if you selected only minute data we'll select series for you. /// /// This method is now obsolete and has no replacement. All algorithms now run in Series mode. /// Enum RunMode with options Series, Parallel or Automatic. Automatic scans your requested symbols and resolutions and makes a decision on the fastest analysis [Obsolete("This method is now obsolete and has no replacement. All algorithms now run in Series mode.")] public void SetRunMode(RunMode mode) { if (mode != RunMode.Parallel) return; Debug("Algorithm.SetRunMode(): RunMode-Parallel Type has been deprecated. Series analysis selected instead"); } /// /// Sets the brokerage to emulate in backtesting or paper trading. /// This can be used for brokerages that have been implemented in LEAN /// /// The brokerage to emulate /// The account type (Cash or Margin) public void SetBrokerageModel(BrokerageName brokerage, AccountType accountType = AccountType.Margin) { SetBrokerageModel(Brokerages.BrokerageModel.Create(brokerage, accountType)); } /// /// Sets the brokerage to emulate in backtesting or paper trading. /// This can be used to set a custom brokerage model. /// /// The brokerage model to use public void SetBrokerageModel(IBrokerageModel model) { BrokerageModel = model; if (!_userSetSecurityInitializer) { // purposefully use the direct setter vs Set method so we don't flip the switch :/ SecurityInitializer = new BrokerageModelSecurityInitializer(model, SecuritySeeder.Null); // update models on securities added earlier (before SetBrokerageModel is called) foreach (var kvp in Securities) { var security = kvp.Value; // save the existing leverage specified in AddSecurity, // if Leverage needs to be set in a SecurityInitializer, // SetSecurityInitializer must be called before SetBrokerageModel var leverage = security.Leverage; SecurityInitializer.Initialize(security); // restore the saved leverage security.SetLeverage(leverage); } } } /// /// Sets the implementation used to handle messages from the brokerage. /// The default implementation will forward messages to debug or error /// and when a occurs, the algorithm /// is stopped. /// /// The message handler to use public void SetBrokerageMessageHandler(IBrokerageMessageHandler handler) { if (handler == null) { throw new ArgumentNullException("handler"); } BrokerageMessageHandler = handler; } /// /// Sets the benchmark used for computing statistics of the algorithm to the specified symbol /// /// symbol to use as the benchmark /// Is the symbol an equity, forex, base, etc. Default SecurityType.Equity /// /// Must use symbol that is available to the trade engine in your data store(not strictly enforced) /// [Obsolete("Symbol implicit operator to string is provided for algorithm use only.")] public void SetBenchmark(SecurityType securityType, string symbol) { string market = Market.USA; this.BrokerageModel.DefaultMarkets.TryGetValue(securityType, out market); _benchmarkSymbol = QuantConnect.Symbol.Create(symbol, securityType, market); } /// /// Sets the benchmark used for computing statistics of the algorithm to the specified symbol, defaulting to SecurityType.Equity /// if the symbol doesn't exist in the algorithm /// /// symbol to use as the benchmark /// /// Overload to accept symbol without passing SecurityType. If symbol is in portfolio it will use that SecurityType, otherwise will default to SecurityType.Equity /// public void SetBenchmark(string symbol) { // check existence symbol = symbol.LazyToUpper(); var security = Securities.FirstOrDefault(x => x.Key.Value == symbol).Value; if (security == null) { Debug($"Warning: SetBenchmark({symbol}): no existing security found, benchmark security will be added with {SecurityType.Equity} type."); _benchmarkSymbol = QuantConnect.Symbol.Create(symbol, SecurityType.Equity, Market.USA); } else { _benchmarkSymbol = security.Symbol; } } /// /// Sets the benchmark used for computing statistics of the algorithm to the specified symbol /// /// symbol to use as the benchmark public void SetBenchmark(Symbol symbol) { _benchmarkSymbol = symbol; } /// /// Sets the specified function as the benchmark, this function provides the value of /// the benchmark at each date/time requested /// /// The benchmark producing function public void SetBenchmark(Func benchmark) { Benchmark = new FuncBenchmark(benchmark); } /// /// Benchmark /// /// Use Benchmark to override default symbol based benchmark, and create your own benchmark. For example a custom moving average benchmark /// public IBenchmark Benchmark { get; private set; } /// /// Sets the account currency cash symbol this algorithm is to manage. /// /// Has to be called during before /// calling or adding any /// The account currency cash symbol to set public void SetAccountCurrency(string accountCurrency) { if (_locked) { throw new InvalidOperationException("Algorithm.SetAccountCurrency(): " + "Cannot change AccountCurrency after algorithm initialized."); } Portfolio.SetAccountCurrency(accountCurrency); } /// /// Set initial cash for the strategy while backtesting. During live mode this value is ignored /// and replaced with the actual cash of your brokerage account. /// /// Starting cash for the strategy backtest /// Alias of SetCash(decimal) public void SetCash(double startingCash) { SetCash((decimal)startingCash); } /// /// Set initial cash for the strategy while backtesting. During live mode this value is ignored /// and replaced with the actual cash of your brokerage account. /// /// Starting cash for the strategy backtest /// Alias of SetCash(decimal) public void SetCash(int startingCash) { SetCash((decimal)startingCash); } /// /// Set initial cash for the strategy while backtesting. During live mode this value is ignored /// and replaced with the actual cash of your brokerage account. /// /// Starting cash for the strategy backtest public void SetCash(decimal startingCash) { if (!_locked) { Portfolio.SetCash(startingCash); } else { throw new Exception("Algorithm.SetCash(): Cannot change cash available after algorithm initialized."); } } /// /// Set the cash for the specified symbol /// /// The cash symbol to set /// Decimal cash value of portfolio /// The current conversion rate for the public void SetCash(string symbol, decimal startingCash, decimal conversionRate = 0) { if (!_locked) { Portfolio.SetCash(symbol, startingCash, conversionRate); } else { throw new Exception("Algorithm.SetCash(): Cannot change cash available after algorithm initialized."); } } /// /// Set the start date for backtest. /// /// Int starting date 1-30 /// Int month starting date /// Int year starting date /// /// Wrapper for SetStartDate(DateTime). /// Must be less than end date. /// Ignored in live trading mode. /// public void SetStartDate(int year, int month, int day) { try { var start = new DateTime(year, month, day); // We really just want the date of the start, so it's 12am of the requested day (first moment of the day) start = start.Date; SetStartDate(start); } catch (Exception err) { throw new Exception("Date Invalid: " + err.Message); } } /// /// Set the end date for a backtest run /// /// Int end date 1-30 /// Int month end date /// Int year end date /// Wrapper for SetEndDate(datetime). /// public void SetEndDate(int year, int month, int day) { try { var end = new DateTime(year, month, day); // we want the end date to be just before the next day (last moment of the day) end = end.Date.AddDays(1).Subtract(TimeSpan.FromTicks(1)); SetEndDate(end); } catch (Exception err) { throw new Exception("Date Invalid: " + err.Message); } } /// /// Set the algorithm id (backtestId or live deployId for the algorithmm). /// /// String Algorithm Id /// Intended for internal QC Lean Engine use only as a setter for AlgorihthmId public void SetAlgorithmId(string algorithmId) { _algorithmId = algorithmId; } /// /// Set the start date for the backtest /// /// Datetime Start date for backtest /// Must be less than end date and within data available /// public void SetStartDate(DateTime start) { // no need to set this value in live mode, will be set using the current time. if (_liveMode) return; //Round down start = start.RoundDown(TimeSpan.FromDays(1)); //Validate the start date: //1. Check range; if (start < (new DateTime(1900, 01, 01))) { throw new Exception("Please select a start date after January 1st, 1900."); } //2. Check future date var todayInAlgorithmTimeZone = DateTime.UtcNow.ConvertFromUtc(TimeZone).Date; if (start > todayInAlgorithmTimeZone) { throw new Exception("Please select start date less than today"); } //3. Check end date greater: if (_endDate != new DateTime()) { if (start > _endDate) { throw new Exception("Please select start date less than end date."); } } //4. Check not locked already: if (!_locked) { // this is only or backtesting if (!LiveMode) { _startDate = start; SetDateTime(_startDate.ConvertToUtc(TimeZone)); } } else { throw new Exception("Algorithm.SetStartDate(): Cannot change start date after algorithm initialized."); } } /// /// Set the end date for a backtest. /// /// Datetime value for end date /// Must be greater than the start date /// public void SetEndDate(DateTime end) { // no need to set this value in live mode, will be set using the current time. if (_liveMode) return; //Validate: //1. Check Range: if (end > DateTime.Now.Date.AddDays(-1)) { end = DateTime.Now.Date.AddDays(-1); } //2. Check start date less: if (_startDate != new DateTime()) { if (end < _startDate) { throw new Exception("Please select end date greater than start date."); } } //3. Make this at the very end of the requested date end = end.RoundDown(TimeSpan.FromDays(1)).AddDays(1).AddTicks(-1); //4. Check not locked already: if (!_locked) { _endDate = end; } else { throw new Exception("Algorithm.SetEndDate(): Cannot change end date after algorithm initialized."); } } /// /// Lock the algorithm initialization to avoid user modifiying cash and data stream subscriptions /// /// Intended for Internal QC Lean Engine use only to prevent accidental manipulation of important properties public void SetLocked() { _locked = true; } /// /// Gets whether or not this algorithm has been locked and fully initialized /// public bool GetLocked() { return _locked; } /// /// Set live mode state of the algorithm run: Public setter for the algorithm property LiveMode. /// public void SetLiveMode(bool live) { if (!_locked) { _liveMode = live; Notify = new NotificationManager(live); TradeBuilder.SetLiveMode(live); Securities.SetLiveMode(live); if (live) { _startDate = DateTime.Today; _endDate = QuantConnect.Time.EndOfTime; } } } /// /// Set the implementation to generate trades from executions and market price updates /// public void SetTradeBuilder(ITradeBuilder tradeBuilder) { TradeBuilder = tradeBuilder; TradeBuilder.SetLiveMode(LiveMode); } /// /// Add specified data to our data subscriptions. QuantConnect will funnel this data to the handle data routine. /// /// MarketType Type: Equity, Commodity, Future, FOREX or Crypto /// The security ticker /// Resolution of the Data Required /// When no data available on a tradebar, return the last data that was generated /// Show the after market data as well public Security AddSecurity(SecurityType securityType, string ticker, Resolution resolution = Resolution.Minute, bool fillDataForward = true, bool extendedMarketHours = false) { return AddSecurity(securityType, ticker, resolution, fillDataForward, 0, extendedMarketHours); } /// /// Add specified data to required list. QC will funnel this data to the handle data routine. /// /// MarketType Type: Equity, Commodity, Future, FOREX or Crypto /// The security ticker /// Resolution of the Data Required /// When no data available on a tradebar, return the last data that was generated /// Custom leverage per security /// Extended market hours /// AddSecurity(SecurityType securityType, Symbol symbol, Resolution resolution, bool fillDataForward, decimal leverage, bool extendedMarketHours) public Security AddSecurity(SecurityType securityType, string ticker, Resolution resolution, bool fillDataForward, decimal leverage, bool extendedMarketHours) { return AddSecurity(securityType, ticker, resolution, null, fillDataForward, leverage, extendedMarketHours); } /// /// Set a required SecurityType-symbol and resolution for algorithm /// /// MarketType Type: Equity, Commodity, Future, FOREX or Crypto /// The security ticker, e.g. AAPL /// Resolution of the MarketType required: MarketData, Second or Minute /// The market the requested security belongs to, such as 'usa' or 'fxcm' /// If true, returns the last available data even if none in that timeslice. /// leverage for this security /// ExtendedMarketHours send in data from 4am - 8pm, not used for FOREX public Security AddSecurity(SecurityType securityType, string ticker, Resolution resolution, string market, bool fillDataForward, decimal leverage, bool extendedMarketHours) { // if AddSecurity method is called to add an option or a future, we delegate a call to respective methods if (securityType == SecurityType.Option) { return AddOption(ticker, resolution, market, fillDataForward, leverage); } if (securityType == SecurityType.Future) { return AddFuture(ticker, resolution, market, fillDataForward, leverage); } try { if (market == null) { if (!BrokerageModel.DefaultMarkets.TryGetValue(securityType, out market)) { throw new Exception("No default market set for security type: " + securityType); } } Symbol symbol; if (!SymbolCache.TryGetSymbol(ticker, out symbol) || symbol.ID.Market != market || symbol.SecurityType != securityType) { symbol = QuantConnect.Symbol.Create(ticker, securityType, market); } var configs = SubscriptionManager.SubscriptionDataConfigService.Add(symbol, resolution, fillDataForward, extendedMarketHours); var security = Securities.CreateSecurity(symbol, configs, leverage); AddToUserDefinedUniverse(security, configs); return security; } catch (Exception err) { Error("Algorithm.AddSecurity(): " + err); return null; } } /// /// Creates and adds a new security to the algorithm /// /// The equity ticker symbol /// The of market data, Tick, Second, Minute, Hour, or Daily. Default is /// The equity's market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in /// If true, returns the last available data even if none in that timeslice. Default is true /// The requested leverage for this equity. Default is set by /// True to send data during pre and post market sessions. Default is false /// The new security public Equity AddEquity(string ticker, Resolution resolution = Resolution.Minute, string market = null, bool fillDataForward = true, decimal leverage = 0m, bool extendedMarketHours = false) { return AddSecurity(SecurityType.Equity, ticker, resolution, market, fillDataForward, leverage, extendedMarketHours); } /// /// Creates and adds a new equity security to the algorithm /// /// The underlying equity ticker /// The of market data, Tick, Second, Minute, Hour, or Daily. Default is /// The equity's market, . Default is value null and looked up using BrokerageModel.DefaultMarkets in /// If true, returns the last available data even if none in that timeslice. Default is true /// The requested leverage for this equity. Default is set by /// The new security public Option AddOption(string underlying, Resolution resolution = Resolution.Minute, string market = null, bool fillDataForward = true, decimal leverage = 0m) { if (market == null) { if (!BrokerageModel.DefaultMarkets.TryGetValue(SecurityType.Option, out market)) { throw new Exception("No default market set for security type: " + SecurityType.Option); } } Symbol canonicalSymbol; var alias = "?" + underlying; if (!SymbolCache.TryGetSymbol(alias, out canonicalSymbol) || canonicalSymbol.ID.Market != market || canonicalSymbol.SecurityType != SecurityType.Option) { canonicalSymbol = QuantConnect.Symbol.Create(underlying, SecurityType.Option, market, alias); } var configs = SubscriptionManager.SubscriptionDataConfigService.Add(typeof(ZipEntryName), canonicalSymbol, resolution, fillDataForward, isFilteredSubscription: false); var canonicalSecurity = (Option)Securities.CreateSecurity(canonicalSymbol, configs, leverage); canonicalSecurity.IsTradable = false; Securities.Add(canonicalSecurity); // add this security to the user defined universe Universe universe; if (!UniverseManager.TryGetValue(canonicalSymbol, out universe) && _pendingUniverseAdditions.All(u => u.Configuration.Symbol != canonicalSymbol)) { var settings = new UniverseSettings(resolution, leverage, true, false, TimeSpan.Zero); universe = new OptionChainUniverse(canonicalSecurity, settings, LiveMode); _pendingUniverseAdditions.Add(universe); } return canonicalSecurity; } /// /// Creates and adds a new security to the algorithm /// /// The future ticker /// The of market data, Tick, Second, Minute, Hour, or Daily. Default is /// The futures market, . Default is value null and looked up using BrokerageModel.DefaultMarkets in /// If true, returns the last available data even if none in that timeslice. Default is true /// The requested leverage for this equity. Default is set by /// The new security public Future AddFuture(string ticker, Resolution resolution = Resolution.Minute, string market = null, bool fillDataForward = true, decimal leverage = 0m) { if (market == null) { if (!BrokerageModel.DefaultMarkets.TryGetValue(SecurityType.Future, out market)) { throw new Exception("No default market set for security type: " + SecurityType.Future); } } Symbol canonicalSymbol; var alias = "/" + ticker; if (!SymbolCache.TryGetSymbol(alias, out canonicalSymbol) || canonicalSymbol.ID.Market != market || canonicalSymbol.SecurityType != SecurityType.Future) { canonicalSymbol = QuantConnect.Symbol.Create(ticker, SecurityType.Future, market, alias); } var configs = SubscriptionManager.SubscriptionDataConfigService.Add(canonicalSymbol, resolution, fillDataForward, isFilteredSubscription: false); var canonicalSecurity = (Future)Securities.CreateSecurity(canonicalSymbol, configs, leverage); canonicalSecurity.IsTradable = false; Securities.Add(canonicalSecurity); // add this security to the user defined universe Universe universe; if (!UniverseManager.TryGetValue(canonicalSymbol, out universe) && _pendingUniverseAdditions.All(u => u.Configuration.Symbol != canonicalSymbol)) { var settings = new UniverseSettings(resolution, leverage, true, false, TimeSpan.Zero); universe = new FuturesChainUniverse(canonicalSecurity, settings); _pendingUniverseAdditions.Add(universe); } return canonicalSecurity; } /// /// Creates and adds a new single contract to the algorithm /// /// The futures contract symbol /// The of market data, Tick, Second, Minute, Hour, or Daily. Default is /// If true, returns the last available data even if none in that timeslice. Default is true /// The requested leverage for this equity. Default is set by /// The new security public Future AddFutureContract(Symbol symbol, Resolution resolution = Resolution.Minute, bool fillDataForward = true, decimal leverage = 0m) { var configs = SubscriptionManager.SubscriptionDataConfigService.Add(symbol, resolution, fillDataForward); var future = (Future)Securities.CreateSecurity(symbol, configs, leverage); AddToUserDefinedUniverse(future, configs); return future; } /// /// Creates and adds a new single contract to the algorithm /// /// The option contract symbol /// The of market data, Tick, Second, Minute, Hour, or Daily. Default is /// If true, returns the last available data even if none in that timeslice. Default is true /// The requested leverage for this equity. Default is set by /// The new security public Option AddOptionContract(Symbol symbol, Resolution resolution = Resolution.Minute, bool fillDataForward = true, decimal leverage = 0m) { var configs = SubscriptionManager.SubscriptionDataConfigService.Add(symbol, resolution, fillDataForward); var option = (Option)Securities.CreateSecurity(symbol, configs, leverage); // add underlying if not present var underlying = option.Symbol.Underlying; Security equity; List underlyingConfigs; if (!Securities.TryGetValue(underlying, out equity)) { equity = AddEquity(underlying.Value, resolution, underlying.ID.Market, false); underlyingConfigs = SubscriptionManager.SubscriptionDataConfigService .GetSubscriptionDataConfigs(underlying); } else { underlyingConfigs = SubscriptionManager.SubscriptionDataConfigService .GetSubscriptionDataConfigs(underlying); var dataNormalizationMode = underlyingConfigs.DataNormalizationMode(); if (dataNormalizationMode != DataNormalizationMode.Raw && _locked) { // We check the "locked" flag here because during initialization we need to load existing open orders and holdings from brokerages. // There is no data streaming yet, so it is safe to change the data normalization mode to Raw. throw new ArgumentException($"The underlying equity asset ({underlying.Value}) is set to {dataNormalizationMode}, " + "please change this to DataNormalizationMode.Raw with the SetDataNormalization() method"); } } underlyingConfigs.SetDataNormalizationMode(DataNormalizationMode.Raw); // For backward compatibility we need to refresh the security DataNormalizationMode Property equity.RefreshDataNormalizationModeProperty(); option.Underlying = equity; AddToUserDefinedUniverse(option, configs); return option; } /// /// Creates and adds a new security to the algorithm /// /// The currency pair /// The of market data, Tick, Second, Minute, Hour, or Daily. Default is /// The foreign exchange trading market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in /// If true, returns the last available data even if none in that timeslice. Default is true /// The requested leverage for this equity. Default is set by /// The new security public Forex AddForex(string ticker, Resolution resolution = Resolution.Minute, string market = null, bool fillDataForward = true, decimal leverage = 0m) { return AddSecurity(SecurityType.Forex, ticker, resolution, market, fillDataForward, leverage, false); } /// /// Creates and adds a new security to the algorithm /// /// The currency pair /// The of market data, Tick, Second, Minute, Hour, or Daily. Default is /// The cfd trading market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in /// If true, returns the last available data even if none in that timeslice. Default is true /// The requested leverage for this equity. Default is set by /// The new security public Cfd AddCfd(string ticker, Resolution resolution = Resolution.Minute, string market = null, bool fillDataForward = true, decimal leverage = 0m) { return AddSecurity(SecurityType.Cfd, ticker, resolution, market, fillDataForward, leverage, false); } /// /// Creates and adds a new security to the algorithm /// /// The currency pair /// The of market data, Tick, Second, Minute, Hour, or Daily. Default is /// The cfd trading market, . Default value is null and looked up using BrokerageModel.DefaultMarkets in /// If true, returns the last available data even if none in that timeslice. Default is true /// The requested leverage for this equity. Default is set by /// The new security public Crypto AddCrypto(string ticker, Resolution resolution = Resolution.Minute, string market = null, bool fillDataForward = true, decimal leverage = 0m) { return AddSecurity(SecurityType.Crypto, ticker, resolution, market, fillDataForward, leverage, false); } /// /// Removes the security with the specified symbol. This will cancel all /// open orders and then liquidate any existing holdings /// /// The symbol of the security to be removed public bool RemoveSecurity(Symbol symbol) { Security security; if (!Securities.TryGetValue(symbol, out security)) { return false; } // cancel open orders Transactions.CancelOpenOrders(security.Symbol); // liquidate if invested if (security.Invested) { Liquidate(security.Symbol); } // Clear cache security.Cache.Reset(); // Mark security as not tradable security.IsTradable = false; if (symbol.IsCanonical()) { // remove underlying equity data if it's marked as internal var universe = UniverseManager.Select(x => x.Value).FirstOrDefault(x => x.Configuration.Symbol == symbol); if (universe != null) { // remove underlying if not used by other universes var otherUniverses = UniverseManager.Select(ukvp => ukvp.Value).Where(u => !ReferenceEquals(u, universe)).ToList(); if (symbol.HasUnderlying) { var underlying = Securities[symbol.Underlying]; if (!otherUniverses.Any(u => u.Members.ContainsKey(underlying.Symbol))) { RemoveSecurity(underlying.Symbol); } } // remove child securities (option contracts for option chain universes) if not used in other universes foreach (var child in universe.Members.Values) { if (!otherUniverses.Any(u => u.Members.ContainsKey(child.Symbol))) { RemoveSecurity(child.Symbol); } } // finally, dispose and remove the canonical security from the universe manager UniverseManager.Remove(symbol); } } else { var universe = UniverseManager.Select(x => x.Value).OfType().FirstOrDefault(x => x.Members.ContainsKey(symbol)); if (universe != null) { universe.Remove(symbol); // if we are removing the symbol which is also the benchmark, add it back as internal feed if (symbol == _benchmarkSymbol) { Securities.Remove(symbol); security = CreateBenchmarkSecurity(); } } } return true; } /// /// AddData a new user defined data source, requiring only the minimum config options. /// The data is added with a default time zone of NewYork (Eastern Daylight Savings Time) /// /// Key/Ticker for data /// Resolution of the data /// The new /// Generic type T must implement base data public Security AddData(string ticker, Resolution resolution = Resolution.Minute) where T : IBaseData, new() { //Add this new generic data as a tradeable security: // Defaults:extended market hours" = true because we want events 24 hours, // fillforward = false because only want to trigger when there's new custom data. // leverage = 1 because no leverage on nonmarket data? return AddData(ticker, resolution, fillDataForward: false, leverage: 1m); } /// /// AddData a new user defined data source, requiring only the minimum config options. /// The data is added with a default time zone of NewYork (Eastern Daylight Savings Time) /// /// Key/Ticker for data /// Resolution of the Data Required /// When no data available on a tradebar, return the last data that was generated /// Custom leverage per security /// The new /// Generic type T must implement base data public Security AddData(string ticker, Resolution resolution, bool fillDataForward, decimal leverage = 1.0m) where T : IBaseData, new() { return AddData(ticker, resolution, TimeZones.NewYork, fillDataForward, leverage); } /// /// AddData a new user defined data source, requiring only the minimum config options. /// /// Key/Ticker for data /// Resolution of the Data Required /// Specifies the time zone of the raw data /// When no data available on a tradebar, return the last data that was generated /// Custom leverage per security /// The new /// Generic type T must implement base data public Security AddData(string ticker, Resolution resolution, DateTimeZone timeZone, bool fillDataForward = false, decimal leverage = 1.0m) where T : IBaseData, new() { //Add this custom symbol to our market hours database MarketHoursDatabase.SetEntryAlwaysOpen(Market.USA, ticker, SecurityType.Base, timeZone); //Add this to the data-feed subscriptions var symbol = new Symbol(SecurityIdentifier.GenerateBase(ticker, Market.USA), ticker); //Add this new generic data as a tradeable security: var config = SubscriptionManager.SubscriptionDataConfigService.Add(typeof(T), symbol, resolution, fillDataForward, extendedMarketHours: true, isCustomData: true); var security = Securities.CreateSecurity(symbol, config, leverage); AddToUserDefinedUniverse(security, new List{ config }); return security; } /// /// Send a debug message to the web console: /// /// Message to send to debug console /// /// public void Debug(string message) { if (!_liveMode && (message == "" || _previousDebugMessage == message)) return; _debugMessages.Enqueue(message); _previousDebugMessage = message; } /// /// Send a debug message to the web console: /// /// Message to send to debug console /// /// public void Debug(int message) { Debug(message.ToString()); } /// /// Send a debug message to the web console: /// /// Message to send to debug console /// /// public void Debug(double message) { Debug(message.ToString()); } /// /// Send a debug message to the web console: /// /// Message to send to debug console /// /// public void Debug(decimal message) { Debug(message.ToString()); } /// /// Added another method for logging if user guessed. /// /// String message to log. /// /// public void Log(string message) { if (!_liveMode && message == "") return; _logMessages.Enqueue(message); } /// /// Added another method for logging if user guessed. /// /// Int message to log. /// /// public void Log(int message) { Log(message.ToString()); } /// /// Added another method for logging if user guessed. /// /// Double message to log. /// /// public void Log(double message) { Log(message.ToString()); } /// /// Added another method for logging if user guessed. /// /// Decimal message to log. /// /// public void Log(decimal message) { Log(message.ToString()); } /// /// Send a string error message to the Console. /// /// Message to display in errors grid /// /// public void Error(string message) { if (!_liveMode && (message == "" || _previousErrorMessage == message)) return; _errorMessages.Enqueue(message); _previousErrorMessage = message; } /// /// Send a int error message to the Console. /// /// Message to display in errors grid /// /// public void Error(int message) { Error(message.ToString()); } /// /// Send a double error message to the Console. /// /// Message to display in errors grid /// /// public void Error(double message) { Error(message.ToString()); } /// /// Send a decimal error message to the Console. /// /// Message to display in errors grid /// /// public void Error(decimal message) { Error(message.ToString()); } /// /// Send a string error message to the Console. /// /// Exception object captured from a try catch loop /// /// public void Error(Exception error) { var message = error.Message; if (!_liveMode && (message == "" || _previousErrorMessage == message)) return; _errorMessages.Enqueue(message); _previousErrorMessage = message; } /// /// Terminate the algorithm after processing the current event handler. /// /// Exit message to display on quitting public void Quit(string message = "") { Debug("Quit(): " + message); Status = AlgorithmStatus.Stopped; } /// /// Set the Quit flag property of the algorithm. /// /// Intended for internal use by the QuantConnect Lean Engine only. /// Boolean quit state /// public void SetQuit(bool quit) { if (quit) { Status = AlgorithmStatus.Stopped; } } /// /// Converts the string 'ticker' symbol into a full object /// This requires that the string 'ticker' has been added to the algorithm /// /// The ticker symbol. This should be the ticker symbol /// as it was added to the algorithm /// The symbol object mapped to the specified ticker public Symbol Symbol(string ticker) { return SymbolCache.GetSymbol(ticker); } /// /// Creates and adds a new to the algorithm /// private T AddSecurity(SecurityType securityType, string ticker, Resolution resolution, string market, bool fillDataForward, decimal leverage, bool extendedMarketHours) where T : Security { if (market == null) { if (!BrokerageModel.DefaultMarkets.TryGetValue(securityType, out market)) { throw new Exception("No default market set for security type: " + securityType); } } Symbol symbol; if (!SymbolCache.TryGetSymbol(ticker, out symbol) || symbol.ID.Market != market || symbol.SecurityType != securityType) { symbol = QuantConnect.Symbol.Create(ticker, securityType, market); } var configs = SubscriptionManager.SubscriptionDataConfigService.Add(symbol, resolution, fillDataForward, extendedMarketHours); var security = Securities.CreateSecurity(symbol, configs, leverage); AddToUserDefinedUniverse(security, configs); return (T)security; } /// /// Creates and returns a object to be used as the benchmark /// private Security CreateBenchmarkSecurity() { // add the security as an internal feed so the algorithm doesn't receive the data Resolution resolution; if (_liveMode) { resolution = Resolution.Second; } else { // check to see if any universes arn't the ones added via AddSecurity var hasNonAddSecurityUniverses = ( from universe in UniverseManager.Select(kvp => kvp.Value).Union(_pendingUniverseAdditions) let config = universe.Configuration let symbol = UserDefinedUniverse.CreateSymbol(config.SecurityType, config.Market) where config.Symbol != symbol select universe).Any(); resolution = hasNonAddSecurityUniverses ? UniverseSettings.Resolution : Resolution.Daily; } var configs = SubscriptionManager.SubscriptionDataConfigService.Add(_benchmarkSymbol, resolution, isInternalFeed:true); var security = Securities.CreateSecurity(_benchmarkSymbol, configs, 1m); AddToUserDefinedUniverse(security, configs); return security; } /// /// Set the historical data provider /// /// Historical data provider public void SetHistoryProvider(IHistoryProvider historyProvider) { if (historyProvider == null) { throw new ArgumentNullException("Algorithm.SetHistoryProvider(): Historical data provider cannot be null."); } HistoryProvider = historyProvider; } /// /// Set the runtime error /// /// Represents error that occur during execution public void SetRunTimeError(Exception exception) { if (exception == null) { throw new ArgumentNullException("Algorithm.SetRunTimeError(): Algorithm.RunTimeError cannot be set to null."); } RunTimeError = exception; } /// /// Set the state of a live deployment /// /// Live deployment status public void SetStatus(AlgorithmStatus status) { Status = status; } /// /// Downloads the requested resource as a . /// The resource to download is specified as a containing the URI. /// /// A string containing the URI to download /// The requested resource as a public string Download(string address) => Download(address, Enumerable.Empty>()); /// /// Downloads the requested resource as a . /// The resource to download is specified as a containing the URI. /// /// A string containing the URI to download /// Defines header values to add to the request /// The requested resource as a public string Download(string address, IEnumerable> headers) => Download(address, headers, null, null); /// /// Downloads the requested resource as a . /// The resource to download is specified as a containing the URI. /// /// A string containing the URI to download /// Defines header values to add to the request /// The user name associated with the credentials /// The password for the user name associated with the credentials /// The requested resource as a public string Download(string address, IEnumerable> headers, string userName, string password) { return _api.Download(address, headers, userName, password); } /// /// Event invocator for the event /// /// The collection of insights generaed at the current time step /// Will emit a clone of the generated insights private void OnInsightsGenerated(IEnumerable insights, bool clone = true) { var insightCollection = insights.ToArray(); // debug printing of generated insights if (DebugMode) { Log($"{Time}: ALPHA: {string.Join(" | ", insightCollection.Select(i => i.ToString()).OrderBy(i => i))}"); } InsightsGenerated?.Invoke(this, new GeneratedInsightsCollection(UtcTime, insightCollection, clone: clone)); } /// /// Sets the current slice /// /// The Slice object public void SetCurrentSlice(Slice slice) { CurrentSlice = slice; } /// /// Provide the API for the algorithm. /// /// Initiated API public void SetApi(IApi api) { _api = api; } /// /// Sets the order event provider /// /// The order event provider public void SetOrderEventProvider(IOrderEventProvider newOrderEvent) { newOrderEvent.NewOrderEvent += (sender, orderEvent) => { EmitInsightBasedOnFill(orderEvent); }; } /// /// Will emit a new based on the given /// /// /// To be called before updating the /// The from which /// the new will be created private void EmitInsightBasedOnFill(OrderEvent orderEvent) { if (_emitAutogeneratedOrderBasedInsight && !_emitInsightWasCalled && (orderEvent.Status == OrderStatus.Filled || orderEvent.Status == OrderStatus.PartiallyFilled)) { _autogeneratedOrderBasedInsightWasCalled = true; var security = Securities[orderEvent.Symbol]; var insight = _orderBasedInsightGenerator.GenerateInsightFromFill( orderEvent, security.Holdings); OnInsightsGenerated(new[] { insight }, clone: false); } } } }