Lean  $LEAN_TAG$
QCAlgorithm.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
16 using System;
17 using System.Collections.Generic;
18 using System.Linq;
19 using System.Linq.Expressions;
20 using System.Globalization;
21 using NodaTime;
22 using NodaTime.TimeZones;
25 using QuantConnect.Data;
29 using QuantConnect.Orders;
38 using QuantConnect.Util;
39 using System.Collections.Concurrent;
48 using QuantConnect.Storage;
49 using Index = QuantConnect.Securities.Index.Index;
53 
54 namespace QuantConnect.Algorithm
55 {
56  /// <summary>
57  /// QC Algorithm Base Class - Handle the basic requirements of a trading algorithm,
58  /// allowing user to focus on event methods. The QCAlgorithm class implements Portfolio,
59  /// Securities, Transactions and Data Subscription Management.
60  /// </summary>
61  public partial class QCAlgorithm : MarshalByRefObject, IAlgorithm
62  {
63  #region Documentation Attribute Categories
64  const string AddingData = "Adding Data";
65  const string AlgorithmFramework = "Algorithm Framework";
66  const string Charting = "Charting";
67  const string ConsolidatingData = "Consolidating Data";
68  const string HandlingData = "Handling Data";
69  const string HistoricalData = "Historical Data";
70  const string Indicators = "Indicators";
71  const string LiveTrading = "Live Trading";
72  const string Logging = "Logging";
73  const string MachineLearning = "Machine Learning";
74  const string Modeling = "Modeling";
75  const string ParameterAndOptimization = "Parameter and Optimization";
76  const string ScheduledEvents = "Scheduled Events";
77  const string SecuritiesAndPortfolio = "Securities and Portfolio";
78  const string TradingAndOrders = "Trading and Orders";
79  const string Universes = "Universes";
80  #endregion
81 
82  private readonly TimeKeeper _timeKeeper;
83  private LocalTimeKeeper _localTimeKeeper;
84 
85  private DateTime _start;
86  private DateTime _startDate; //Default start and end dates.
87  private DateTime _endDate; //Default end to yesterday
88  private bool _locked;
89  private bool _liveMode;
90  private string _algorithmId = "";
91  private ConcurrentQueue<string> _debugMessages = new ConcurrentQueue<string>();
92  private ConcurrentQueue<string> _logMessages = new ConcurrentQueue<string>();
93  private ConcurrentQueue<string> _errorMessages = new ConcurrentQueue<string>();
94 
95  //Error tracking to avoid message flooding:
96  private string _previousDebugMessage = "";
97  private string _previousErrorMessage = "";
98 
99  /// <summary>
100  /// Gets the market hours database in use by this algorithm
101  /// </summary>
103 
104  /// <summary>
105  /// Gets the symbol properties database in use by this algorithm
106  /// </summary>
108 
109  // used for calling through to void OnData(Slice) if no override specified
110  private bool _checkedForOnDataSlice;
111  private Action<Slice> _onDataSlice;
112 
113  // flips to true when the user
114  private bool _userSetSecurityInitializer;
115 
116  // warmup resolution variables
117  private TimeSpan? _warmupTimeSpan;
118  private int? _warmupBarCount;
119  private Dictionary<string, string> _parameters = new Dictionary<string, string>();
120  private SecurityDefinitionSymbolResolver _securityDefinitionSymbolResolver;
121 
122  private readonly HistoryRequestFactory _historyRequestFactory;
123 
124  private IApi _api;
125 
126  /// <summary>
127  /// QCAlgorithm Base Class Constructor - Initialize the underlying QCAlgorithm components.
128  /// QCAlgorithm manages the transactions, portfolio, charting and security subscriptions for the users algorithms.
129  /// </summary>
130  public QCAlgorithm()
131  {
132  Name = GetType().Name;
133  Status = AlgorithmStatus.Running;
134 
135  // AlgorithmManager will flip this when we're caught up with realtime
136  IsWarmingUp = true;
137 
138  //Initialise the Algorithm Helper Classes:
139  //- Note - ideally these wouldn't be here, but because of the DLL we need to make the classes shared across
140  // the Worker & Algorithm, limiting ability to do anything else.
141 
142  //Initialise Start Date:
143  _startDate = new DateTime(1998, 01, 01);
144  // intialize our time keeper with only new york
145  _timeKeeper = new TimeKeeper(_startDate, new[] { TimeZones.NewYork });
146  // set our local time zone
147  _localTimeKeeper = _timeKeeper.GetLocalTimeKeeper(TimeZones.NewYork);
148  //Initialise End Date:
149  SetEndDate(DateTime.UtcNow.ConvertFromUtc(TimeZone));
150 
151  _securityDefinitionSymbolResolver = SecurityDefinitionSymbolResolver.GetInstance();
152 
153  Settings = new AlgorithmSettings();
155 
156  //Initialise Data Manager
158 
159  Securities = new SecurityManager(_timeKeeper);
162  SignalExport = new SignalExportManager(this);
163 
165  Notify = new NotificationManager(false); // Notification manager defaults to disabled.
166 
167  //Initialise to unlocked:
168  _locked = false;
169 
170  // get exchange hours loaded from the market-hours-database.csv in /Data/market-hours
173 
174  // universe selection
176  Universe = new UniverseDefinitions(this);
177  UniverseSettings = new UniverseSettings(Resolution.Minute, Security.NullLeverage, true, false, TimeSpan.FromDays(1));
178 
179  // initialize our scheduler, this acts as a liason to the real time handler
181 
182  // initialize the trade builder
184 
186 
188 
189  // initialize trading calendar
191 
194  _historyRequestFactory = new HistoryRequestFactory(this);
195 
196  // set model defaults, universe selection set via PostInitialize
197  SetAlpha(new NullAlphaModel());
202 
203  Insights = new InsightManager(this);
204  }
205 
206  /// <summary>
207  /// Event fired when the algorithm generates insights
208  /// </summary>
209  [DocumentationAttribute(AlgorithmFramework)]
210  public event AlgorithmEvent<GeneratedInsightsCollection> InsightsGenerated;
211 
212  /// <summary>
213  /// Security collection is an array of the security objects such as Equities and FOREX. Securities data
214  /// manages the properties of tradeable assets such as price, open and close time and holdings information.
215  /// </summary>
216  [DocumentationAttribute(SecuritiesAndPortfolio)]
218  {
219  get;
220  set;
221  }
222 
223  /// <summary>
224  /// Read-only dictionary containing all active securities. An active security is
225  /// a security that is currently selected by the universe or has holdings or open orders.
226  /// </summary>
227  [DocumentationAttribute(SecuritiesAndPortfolio)]
228  public IReadOnlyDictionary<Symbol, Security> ActiveSecurities => UniverseManager.ActiveSecurities;
229 
230  /// <summary>
231  /// Portfolio object provieds easy access to the underlying security-holding properties; summed together in a way to make them useful.
232  /// This saves the user time by providing common portfolio requests in a single
233  /// </summary>
234  [DocumentationAttribute(SecuritiesAndPortfolio)]
236  {
237  get;
238  set;
239  }
240 
241  /// <summary>
242  /// Gets the account currency
243  /// </summary>
244  [DocumentationAttribute(SecuritiesAndPortfolio)]
246 
247  /// <summary>
248  /// Gets the time keeper instance
249  /// </summary>
250  public ITimeKeeper TimeKeeper => _timeKeeper;
251 
252  /// <summary>
253  /// Generic Data Manager - Required for compiling all data feeds in order, and passing them into algorithm event methods.
254  /// The subscription manager contains a list of the data feed's we're subscribed to and properties of each data feed.
255  /// </summary>
256  [DocumentationAttribute(HandlingData)]
258  {
259  get;
260  set;
261  }
262 
263  /// <summary>
264  /// SignalExport - Allows sending export signals to different 3rd party API's. For example, it allows to send signals
265  /// to Collective2, CrunchDAO and Numerai API's
266  /// </summary>
267  [DocumentationAttribute(SecuritiesAndPortfolio)]
269  {
270  get;
271  }
272 
273  /// <summary>
274  /// The project id associated with this algorithm if any
275  /// </summary>
276  public int ProjectId
277  {
278  get;
279  set;
280  }
281 
282  /// <summary>
283  /// Gets the brokerage model - used to model interactions with specific brokerages.
284  /// </summary>
285  [DocumentationAttribute(Modeling)]
287  {
288  get;
289  private set;
290  }
291 
292  /// <summary>
293  /// Gets the brokerage message handler used to decide what to do
294  /// with each message sent from the brokerage
295  /// </summary>
296  [DocumentationAttribute(Modeling)]
298  {
299  get;
300  set;
301  }
302 
303  /// <summary>
304  /// Notification Manager for Sending Live Runtime Notifications to users about important events.
305  /// </summary>
306  [DocumentationAttribute(LiveTrading)]
308  {
309  get;
310  set;
311  }
312 
313  /// <summary>
314  /// Gets schedule manager for adding/removing scheduled events
315  /// </summary>
316  [DocumentationAttribute(ScheduledEvents)]
318  {
319  get;
320  private set;
321  }
322 
323  /// <summary>
324  /// Gets or sets the current status of the algorithm
325  /// </summary>
326  [DocumentationAttribute(HandlingData)]
327  public AlgorithmStatus Status
328  {
329  get;
330  set;
331  }
332 
333  /// <summary>
334  /// Gets an instance that is to be used to initialize newly created securities.
335  /// </summary>
336  [DocumentationAttribute(AddingData)]
338  {
339  get;
340  private set;
341  }
342 
343  /// <summary>
344  /// Gets the Trade Builder to generate trades from executions
345  /// </summary>
346  [DocumentationAttribute(TradingAndOrders)]
348  {
349  get;
350  private set;
351  }
352 
353  /// <summary>
354  /// Gets an instance to access the candlestick pattern helper methods
355  /// </summary>
356  [DocumentationAttribute(Indicators)]
358  {
359  get;
360  private set;
361  }
362 
363  /// <summary>
364  /// Gets the date rules helper object to make specifying dates for events easier
365  /// </summary>
366  [DocumentationAttribute(ScheduledEvents)]
367  public DateRules DateRules
368  {
369  get { return Schedule.DateRules; }
370  }
371 
372  /// <summary>
373  /// Gets the time rules helper object to make specifying times for events easier
374  /// </summary>
375  [DocumentationAttribute(ScheduledEvents)]
376  public TimeRules TimeRules
377  {
378  get { return Schedule.TimeRules; }
379  }
380 
381  /// <summary>
382  /// Gets trading calendar populated with trading events
383  /// </summary>
384  [DocumentationAttribute(ScheduledEvents)]
386  {
387  get;
388  private set;
389  }
390 
391  /// <summary>
392  /// Gets the user settings for the algorithm
393  /// </summary>
394  [DocumentationAttribute(HandlingData)]
396  {
397  get;
398  private set;
399  }
400 
401  /// <summary>
402  /// Gets the option chain provider, used to get the list of option contracts for an underlying symbol
403  /// </summary>
404  [DocumentationAttribute(AddingData)]
405  public IOptionChainProvider OptionChainProvider { get; private set; }
406 
407  /// <summary>
408  /// Gets the future chain provider, used to get the list of future contracts for an underlying symbol
409  /// </summary>
410  [DocumentationAttribute(AddingData)]
411  public IFutureChainProvider FutureChainProvider { get; private set; }
412 
413  /// <summary>
414  /// Gets the default order properties
415  /// </summary>
416  [DocumentationAttribute(TradingAndOrders)]
418 
419  /// <summary>
420  /// Public name for the algorithm as automatically generated by the IDE. Intended for helping distinguish logs by noting
421  /// the algorithm-id.
422  /// </summary>
423  /// <seealso cref="AlgorithmId"/>
424  [DocumentationAttribute(HandlingData)]
425  public string Name
426  {
427  get;
428  set;
429  }
430 
431  /// <summary>
432  /// Read-only value for current time frontier of the algorithm in terms of the <see cref="TimeZone"/>
433  /// </summary>
434  /// <remarks>During backtesting this is primarily sourced from the data feed. During live trading the time is updated from the system clock.</remarks>
435  [DocumentationAttribute(HandlingData)]
436  public DateTime Time
437  {
438  get { return _localTimeKeeper.LocalTime; }
439  }
440 
441  /// <summary>
442  /// Current date/time in UTC.
443  /// </summary>
444  [DocumentationAttribute(HandlingData)]
445  public DateTime UtcTime
446  {
447  get { return _timeKeeper.UtcTime; }
448  }
449 
450  /// <summary>
451  /// Gets the time zone used for the <see cref="Time"/> property. The default value
452  /// is <see cref="TimeZones.NewYork"/>
453  /// </summary>
454  [DocumentationAttribute(HandlingData)]
455  public DateTimeZone TimeZone
456  {
457  get { return _localTimeKeeper.TimeZone; }
458  }
459 
460  /// <summary>
461  /// Value of the user set start-date from the backtest.
462  /// </summary>
463  /// <remarks>This property is set with SetStartDate() and defaults to the earliest QuantConnect data available - Jan 1st 1998. It is ignored during live trading </remarks>
464  /// <seealso cref="SetStartDate(DateTime)"/>
465  [DocumentationAttribute(HandlingData)]
466  public DateTime StartDate => _startDate;
467 
468  /// <summary>
469  /// Value of the user set start-date from the backtest. Controls the period of the backtest.
470  /// </summary>
471  /// <remarks> This property is set with SetEndDate() and defaults to today. It is ignored during live trading.</remarks>
472  /// <seealso cref="SetEndDate(DateTime)"/>
473  [DocumentationAttribute(HandlingData)]
474  public DateTime EndDate
475  {
476  get
477  {
478  return _endDate;
479  }
480  }
481 
482  /// <summary>
483  /// Algorithm Id for this backtest or live algorithm.
484  /// </summary>
485  /// <remarks>A unique identifier for </remarks>
486  [DocumentationAttribute(HandlingData)]
487  public string AlgorithmId
488  {
489  get
490  {
491  return _algorithmId;
492  }
493  }
494 
495  /// <summary>
496  /// Boolean property indicating the algorithm is currently running in live mode.
497  /// </summary>
498  /// <remarks>Intended for use where certain behaviors will be enabled while the algorithm is trading live: such as notification emails, or displaying runtime statistics.</remarks>
499  [DocumentationAttribute(LiveTrading)]
500  public bool LiveMode
501  {
502  get
503  {
504  return _liveMode;
505  }
506  }
507 
508  /// <summary>
509  /// Storage for debugging messages before the event handler has passed control back to the Lean Engine.
510  /// </summary>
511  /// <seealso cref="Debug(string)"/>
512  [DocumentationAttribute(Logging)]
513  public ConcurrentQueue<string> DebugMessages
514  {
515  get
516  {
517  return _debugMessages;
518  }
519  set
520  {
521  _debugMessages = value;
522  }
523  }
524 
525  /// <summary>
526  /// Storage for log messages before the event handlers have passed control back to the Lean Engine.
527  /// </summary>
528  /// <seealso cref="Log(string)"/>
529  [DocumentationAttribute(Logging)]
530  public ConcurrentQueue<string> LogMessages
531  {
532  get
533  {
534  return _logMessages;
535  }
536  set
537  {
538  _logMessages = value;
539  }
540  }
541 
542  /// <summary>
543  /// Gets the run time error from the algorithm, or null if none was encountered.
544  /// </summary>
545  [DocumentationAttribute(Logging)]
546  public Exception RunTimeError { get; set; }
547 
548  /// <summary>
549  /// List of error messages generated by the user's code calling the "Error" function.
550  /// </summary>
551  /// <remarks>This method is best used within a try-catch bracket to handle any runtime errors from a user algorithm.</remarks>
552  /// <see cref="Error(string)"/>
553  [DocumentationAttribute(Logging)]
554  public ConcurrentQueue<string> ErrorMessages
555  {
556  get
557  {
558  return _errorMessages;
559  }
560  set
561  {
562  _errorMessages = value;
563  }
564  }
565 
566  /// <summary>
567  /// Returns the current Slice object
568  /// </summary>
569  [DocumentationAttribute(HandlingData)]
570  public Slice CurrentSlice { get; private set; }
571 
572  /// <summary>
573  /// Gets the object store, used for persistence
574  /// </summary>
575  [DocumentationAttribute(HandlingData)]
576  [DocumentationAttribute(MachineLearning)]
577  public ObjectStore ObjectStore { get; private set; }
578 
579  /// <summary>
580  /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
581  /// </summary>
582  /// <seealso cref="SetStartDate(DateTime)"/>
583  /// <seealso cref="SetEndDate(DateTime)"/>
584  /// <seealso cref="SetCash(decimal)"/>
585  [DocumentationAttribute(AlgorithmFramework)]
586  [DocumentationAttribute(HandlingData)]
587  public virtual void Initialize()
588  {
589  //Setup Required Data
590  throw new NotImplementedException("Please override the Initialize() method");
591  }
592 
593  /// <summary>
594  /// Called by setup handlers after Initialize and allows the algorithm a chance to organize
595  /// the data gather in the Initialize method
596  /// </summary>
597  [DocumentationAttribute(AlgorithmFramework)]
598  [DocumentationAttribute(HandlingData)]
599  public virtual void PostInitialize()
600  {
601  if (_endDate < _startDate)
602  {
603  throw new ArgumentException("Please select an algorithm end date greater than start date.");
604  }
605 
606  var portfolioConstructionModel = PortfolioConstruction as PortfolioConstructionModel;
607  if (portfolioConstructionModel != null)
608  {
609  // only override default values if user set the algorithm setting
611  {
612  portfolioConstructionModel.RebalanceOnSecurityChanges
614  }
616  {
617  portfolioConstructionModel.RebalanceOnInsightChanges
619  }
620  }
621  else
622  {
625  {
626  Debug("Warning: rebalance portfolio settings are set but not supported by the current IPortfolioConstructionModel type: " +
627  $"{PortfolioConstruction.GetType()}");
628  }
629  }
630 
632 
633  // if the benchmark hasn't been set yet, load in the default from the brokerage model
634  if (Benchmark == null)
635  {
636  Benchmark = BrokerageModel.GetBenchmark(Securities);
637  }
638 
639  // Check benchmark timezone against algorithm timezone to warn for misaligned statistics
640  if (Benchmark is SecurityBenchmark securityBenchmark)
641  {
642  // Only warn on algorithms subscribed to daily resolution as its statistics will suffer the most
643  var subscription = SubscriptionManager.Subscriptions.OrderByDescending(x => x.Resolution).FirstOrDefault();
644  var benchmarkTimeZone = MarketHoursDatabase.GetDataTimeZone(securityBenchmark.Security.Symbol.ID.Market,
645  securityBenchmark.Security.Symbol, securityBenchmark.Security.Type);
646  if ((subscription?.Resolution == Resolution.Daily || UniverseSettings.Resolution == Resolution.Daily) && benchmarkTimeZone != TimeZone)
647  {
648  Log($"QCAlgorithm.PostInitialize(): Warning: Using a security benchmark of a different timezone ({benchmarkTimeZone})" +
649  $" than the algorithm TimeZone ({TimeZone}) may lead to skewed and incorrect statistics. Use a higher resolution than daily to minimize.");
650  }
651  }
652 
653  if(TryGetWarmupHistoryStartTime(out var result))
654  {
655  SetDateTime(result.ConvertToUtc(TimeZone));
656  }
657  else
658  {
660  }
661 
662  // perform end of time step checks, such as enforcing underlying securities are in raw data mode
663  OnEndOfTimeStep();
664  }
665 
666  /// <summary>
667  /// Called when the algorithm has completed initialization and warm up.
668  /// </summary>
669  [DocumentationAttribute(HandlingData)]
670  public virtual void OnWarmupFinished()
671  {
672  }
673 
674  /// <summary>
675  /// Gets the parameter with the specified name. If a parameter with the specified name does not exist,
676  /// the given default value is returned if any, else null
677  /// </summary>
678  /// <param name="name">The name of the parameter to get</param>
679  /// <param name="defaultValue">The default value to return</param>
680  /// <returns>The value of the specified parameter, or defaultValue if not found or null if there's no default value</returns>
681  [DocumentationAttribute(ParameterAndOptimization)]
682  public string GetParameter(string name, string defaultValue = null)
683  {
684  return _parameters.TryGetValue(name, out var value) ? value : defaultValue;
685  }
686 
687  /// <summary>
688  /// Gets the parameter with the specified name parsed as an integer. If a parameter with the specified name does not exist,
689  /// or the conversion is not possible, the given default value is returned
690  /// </summary>
691  /// <param name="name">The name of the parameter to get</param>
692  /// <param name="defaultValue">The default value to return</param>
693  /// <returns>The value of the specified parameter, or defaultValue if not found or null if there's no default value</returns>
694  [DocumentationAttribute(ParameterAndOptimization)]
695  public int GetParameter(string name, int defaultValue)
696  {
697  return _parameters.TryGetValue(name, out var strValue) && int.TryParse(strValue, out var value) ? value : defaultValue;
698  }
699 
700  /// <summary>
701  /// Gets the parameter with the specified name parsed as a double. If a parameter with the specified name does not exist,
702  /// or the conversion is not possible, the given default value is returned
703  /// </summary>
704  /// <param name="name">The name of the parameter to get</param>
705  /// <param name="defaultValue">The default value to return</param>
706  /// <returns>The value of the specified parameter, or defaultValue if not found or null if there's no default value</returns>
707  [DocumentationAttribute(ParameterAndOptimization)]
708  public double GetParameter(string name, double defaultValue)
709  {
710  return _parameters.TryGetValue(name, out var strValue) &&
711  double.TryParse(strValue, NumberStyles.Any, CultureInfo.InvariantCulture, out var value) ? value : defaultValue;
712  }
713 
714  /// <summary>
715  /// Gets the parameter with the specified name parsed as a decimal. If a parameter with the specified name does not exist,
716  /// or the conversion is not possible, the given default value is returned
717  /// </summary>
718  /// <param name="name">The name of the parameter to get</param>
719  /// <param name="defaultValue">The default value to return</param>
720  /// <returns>The value of the specified parameter, or defaultValue if not found or null if there's no default value</returns>
721  [DocumentationAttribute(ParameterAndOptimization)]
722  public decimal GetParameter(string name, decimal defaultValue)
723  {
724  return _parameters.TryGetValue(name, out var strValue) &&
725  decimal.TryParse(strValue, NumberStyles.Any, CultureInfo.InvariantCulture, out var value) ? value : defaultValue;
726  }
727 
728  /// <summary>
729  /// Gets a read-only dictionary with all current parameters
730  /// </summary>
731  [DocumentationAttribute(ParameterAndOptimization)]
732  public IReadOnlyDictionary<string, string> GetParameters()
733  {
734  return _parameters.ToReadOnlyDictionary();
735  }
736 
737  /// <summary>
738  /// Sets the parameters from the dictionary
739  /// </summary>
740  /// <param name="parameters">Dictionary containing the parameter names to values</param>
741  [DocumentationAttribute(ParameterAndOptimization)]
742  public void SetParameters(Dictionary<string, string> parameters)
743  {
744  // save off a copy and try to apply the parameters
745  _parameters = parameters.ToDictionary();
746  try
747  {
748  ParameterAttribute.ApplyAttributes(parameters, this);
749  }
750  catch (Exception err)
751  {
752  Error("Error applying parameter values: " + err.Message);
753  }
754  }
755 
756  /// <summary>
757  /// Set the available data feeds in the <see cref="SecurityManager"/>
758  /// </summary>
759  /// <param name="availableDataTypes">The different <see cref="TickType"/> each <see cref="Security"/> supports</param>
760  [DocumentationAttribute(HandlingData)]
761  public void SetAvailableDataTypes(Dictionary<SecurityType, List<TickType>> availableDataTypes)
762  {
763  if (availableDataTypes == null)
764  {
765  return;
766  }
767 
768  foreach (var dataFeed in availableDataTypes)
769  {
770  SubscriptionManager.AvailableDataTypes[dataFeed.Key] = dataFeed.Value;
771  }
772  }
773 
774  /// <summary>
775  /// Sets the security initializer, used to initialize/configure securities after creation.
776  /// The initializer will be applied to all universes and manually added securities.
777  /// </summary>
778  /// <param name="securityInitializer">The security initializer</param>
779  [DocumentationAttribute(AddingData)]
780  [DocumentationAttribute(Modeling)]
781  public void SetSecurityInitializer(ISecurityInitializer securityInitializer)
782  {
783  if (_locked)
784  {
785  throw new Exception("SetSecurityInitializer() cannot be called after algorithm initialization. " +
786  "When you use the SetSecurityInitializer() method it will apply to all universes and manually added securities.");
787  }
788 
789  if (_userSetSecurityInitializer)
790  {
791  Debug("Warning: SetSecurityInitializer() has already been called, existing security initializers in all universes will be overwritten.");
792  }
793 
794  // this flag will prevent calls to SetBrokerageModel from overwriting this initializer
795  _userSetSecurityInitializer = true;
796  SecurityInitializer = securityInitializer;
797  }
798 
799  /// <summary>
800  /// Sets the security initializer function, used to initialize/configure securities after creation.
801  /// The initializer will be applied to all universes and manually added securities.
802  /// </summary>
803  /// <param name="securityInitializer">The security initializer function</param>
804  [Obsolete("This method is deprecated. Please use this overload: SetSecurityInitializer(Action<Security> securityInitializer)")]
805  [DocumentationAttribute(AddingData)]
806  [DocumentationAttribute(Modeling)]
807  public void SetSecurityInitializer(Action<Security, bool> securityInitializer)
808  {
809  SetSecurityInitializer(new FuncSecurityInitializer(security => securityInitializer(security, false)));
810  }
811 
812  /// <summary>
813  /// Sets the security initializer function, used to initialize/configure securities after creation.
814  /// The initializer will be applied to all universes and manually added securities.
815  /// </summary>
816  /// <param name="securityInitializer">The security initializer function</param>
817  [DocumentationAttribute(AddingData)]
818  [DocumentationAttribute(Modeling)]
819  public void SetSecurityInitializer(Action<Security> securityInitializer)
820  {
821  SetSecurityInitializer(new FuncSecurityInitializer(securityInitializer));
822  }
823 
824  /// <summary>
825  /// Sets the option chain provider, used to get the list of option contracts for an underlying symbol
826  /// </summary>
827  /// <param name="optionChainProvider">The option chain provider</param>
828  [DocumentationAttribute(AddingData)]
829  public void SetOptionChainProvider(IOptionChainProvider optionChainProvider)
830  {
831  OptionChainProvider = optionChainProvider;
832  }
833 
834  /// <summary>
835  /// Sets the future chain provider, used to get the list of future contracts for an underlying symbol
836  /// </summary>
837  /// <param name="futureChainProvider">The future chain provider</param>
838  [DocumentationAttribute(AddingData)]
839  public void SetFutureChainProvider(IFutureChainProvider futureChainProvider)
840  {
841  FutureChainProvider = futureChainProvider;
842  }
843 
844  /// <summary>
845  /// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
846  /// </summary>
847  /// <code>
848  /// TradeBars bars = slice.Bars;
849  /// Ticks ticks = slice.Ticks;
850  /// TradeBar spy = slice["SPY"];
851  /// List{Tick} aaplTicks = slice["AAPL"]
852  /// Quandl oil = slice["OIL"]
853  /// dynamic anySymbol = slice[symbol];
854  /// DataDictionary{Quandl} allQuandlData = slice.Get{Quand}
855  /// Quandl oil = slice.Get{Quandl}("OIL")
856  /// </code>
857  /// <param name="slice">The current slice of data keyed by symbol string</param>
858  [DocumentationAttribute(HandlingData)]
859  public virtual void OnData(Slice slice)
860  {
861  // as a default implementation, let's look for and call OnData(Slice) just in case a user forgot to use the override keyword
862  if (!_checkedForOnDataSlice)
863  {
864  _checkedForOnDataSlice = true;
865 
866  var method = GetType().GetMethods()
867  .Where(x => x.Name == "OnData")
868  .Where(x => x.DeclaringType != typeof(QCAlgorithm))
869  .Where(x => x.GetParameters().Length == 1)
870  .FirstOrDefault(x => x.GetParameters()[0].ParameterType == typeof (Slice));
871 
872  if (method == null)
873  {
874  return;
875  }
876 
877  var self = Expression.Constant(this);
878  var parameter = Expression.Parameter(typeof (Slice), "data");
879  var call = Expression.Call(self, method, parameter);
880  var lambda = Expression.Lambda<Action<Slice>>(call, parameter);
881  _onDataSlice = lambda.Compile();
882  }
883  // if we have it, then invoke it
884  if (_onDataSlice != null)
885  {
886  _onDataSlice(slice);
887  }
888  }
889 
890  /// <summary>
891  /// Event fired each time the we add/remove securities from the data feed
892  /// </summary>
893  /// <param name="changes">Security additions/removals for this time step</param>
894  [DocumentationAttribute(AddingData)]
895  [DocumentationAttribute(Universes)]
896  public virtual void OnSecuritiesChanged(SecurityChanges changes)
897  {
898  }
899 
900  // <summary>
901  // Event - v2.0 TRADEBAR EVENT HANDLER: (Pattern) Basic template for user to override when requesting tradebar data.
902  // </summary>
903  // <param name="data"></param>
904  //public void OnData(TradeBars data)
905  //{
906  //
907  //}
908 
909  // <summary>
910  // Event - v2.0 QUOTEBAR EVENT HANDLER: (Pattern) Basic template for user to override when requesting quotebar data.
911  // </summary>
912  // <param name="data"></param>
913  //public void OnData(QuoteBars data)
914  //{
915  //
916  //}
917 
918  // <summary>
919  // Event - v2.0 TICK EVENT HANDLER: (Pattern) Basic template for user to override when requesting tick data.
920  // </summary>
921  // <param name="data">List of Tick Data</param>
922  //public void OnData(Ticks data)
923  //{
924  //
925  //}
926 
927  // <summary>
928  // Event - v2.0 OPTIONCHAIN EVENT HANDLER: (Pattern) Basic template for user to override when requesting option data.
929  // </summary>
930  // <param name="data">List of Tick Data</param>
931  //public void OnData(OptionChains data)
932  //{
933  //
934  //}
935 
936  // <summary>
937  // Event - v2.0 SPLIT EVENT HANDLER: (Pattern) Basic template for user to override when inspecting split data.
938  // </summary>
939  // <param name="data">IDictionary of Split Data Keyed by Symbol String</param>
940  //public void OnData(Splits data)
941  //{
942  //
943  //}
944 
945  // <summary>
946  // Event - v2.0 DIVIDEND EVENT HANDLER: (Pattern) Basic template for user to override when inspecting dividend data
947  // </summary>
948  // <param name="data">IDictionary of Dividend Data Keyed by Symbol String</param>
949  //public void OnData(Dividends data)
950  //{
951  //
952  //}
953 
954  // <summary>
955  // Event - v2.0 DELISTING EVENT HANDLER: (Pattern) Basic template for user to override when inspecting delisting data
956  // </summary>
957  // <param name="data">IDictionary of Delisting Data Keyed by Symbol String</param>
958  //public void OnData(Delistings data)
959 
960  // <summary>
961  // Event - v2.0 SYMBOL CHANGED EVENT HANDLER: (Pattern) Basic template for user to override when inspecting symbol changed data
962  // </summary>
963  // <param name="data">IDictionary of SymbolChangedEvent Data Keyed by Symbol String</param>
964  //public void OnData(SymbolChangedEvents data)
965 
966  /// <summary>
967  /// Margin call event handler. This method is called right before the margin call orders are placed in the market.
968  /// </summary>
969  /// <param name="requests">The orders to be executed to bring this algorithm within margin limits</param>
970  [DocumentationAttribute(Modeling)]
971  [DocumentationAttribute(TradingAndOrders)]
972  public virtual void OnMarginCall(List<SubmitOrderRequest> requests)
973  {
974  }
975 
976  /// <summary>
977  /// Margin call warning event handler. This method is called when Portfolio.MarginRemaining is under 5% of your Portfolio.TotalPortfolioValue
978  /// </summary>
979  [DocumentationAttribute(Modeling)]
980  [DocumentationAttribute(TradingAndOrders)]
981  public virtual void OnMarginCallWarning()
982  {
983  }
984 
985  /// <summary>
986  /// 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).
987  /// </summary>
988  /// <remarks>Method is called 10 minutes before closing to allow user to close out position.</remarks>
989  /// <remarks>Deprecated because different assets have different market close times,
990  /// and because Python does not support two methods with the same name</remarks>
991  [Obsolete("This method is deprecated and will be removed after August 2021. Please use this overload: OnEndOfDay(Symbol symbol)")]
992  [DocumentationAttribute(HandlingData)]
993  public virtual void OnEndOfDay()
994  {
995 
996  }
997 
998  /// <summary>
999  /// 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).
1000  /// </summary>
1001  /// <remarks>
1002  /// This method is left for backwards compatibility and is invoked via <see cref="OnEndOfDay(Symbol)"/>, if that method is
1003  /// override then this method will not be called without a called to base.OnEndOfDay(string)
1004  /// </remarks>
1005  /// <param name="symbol">Asset symbol for this end of day event. Forex and equities have different closing hours.</param>
1006  [DocumentationAttribute(HandlingData)]
1007  public virtual void OnEndOfDay(string symbol)
1008  {
1009  }
1010 
1011  /// <summary>
1012  /// 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).
1013  /// </summary>
1014  /// <param name="symbol">Asset symbol for this end of day event. Forex and equities have different closing hours.</param>
1015  [DocumentationAttribute(HandlingData)]
1016  public virtual void OnEndOfDay(Symbol symbol)
1017  {
1018  OnEndOfDay(symbol.ToString());
1019  }
1020 
1021  /// <summary>
1022  /// 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.
1023  /// </summary>
1024  [DocumentationAttribute(HandlingData)]
1025  public virtual void OnEndOfAlgorithm()
1026  {
1027 
1028  }
1029 
1030  /// <summary>
1031  /// Order fill event handler. On an order fill update the resulting information is passed to this method.
1032  /// </summary>
1033  /// <param name="orderEvent">Order event details containing details of the events</param>
1034  /// <remarks>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</remarks>
1035  [DocumentationAttribute(TradingAndOrders)]
1036  public virtual void OnOrderEvent(OrderEvent orderEvent)
1037  {
1038 
1039  }
1040 
1041  /// <summary>
1042  /// Option assignment event handler. On an option assignment event for short legs the resulting information is passed to this method.
1043  /// </summary>
1044  /// <param name="assignmentEvent">Option exercise event details containing details of the assignment</param>
1045  /// <remarks>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</remarks>
1046  [DocumentationAttribute(TradingAndOrders)]
1047  public virtual void OnAssignmentOrderEvent(OrderEvent assignmentEvent)
1048  {
1049 
1050  }
1051 
1052  /// <summary>
1053  /// Brokerage message event handler. This method is called for all types of brokerage messages.
1054  /// </summary>
1055  [DocumentationAttribute(LiveTrading)]
1056  [DocumentationAttribute(Modeling)]
1057  [DocumentationAttribute(TradingAndOrders)]
1058  public virtual void OnBrokerageMessage(BrokerageMessageEvent messageEvent)
1059  {
1060 
1061  }
1062 
1063  /// <summary>
1064  /// Brokerage disconnected event handler. This method is called when the brokerage connection is lost.
1065  /// </summary>
1066  [DocumentationAttribute(LiveTrading)]
1067  public virtual void OnBrokerageDisconnect()
1068  {
1069 
1070  }
1071 
1072  /// <summary>
1073  /// Brokerage reconnected event handler. This method is called when the brokerage connection is restored after a disconnection.
1074  /// </summary>
1075  [DocumentationAttribute(LiveTrading)]
1076  public virtual void OnBrokerageReconnect()
1077  {
1078 
1079  }
1080 
1081  /// <summary>
1082  /// Update the internal algorithm time frontier.
1083  /// </summary>
1084  /// <remarks>For internal use only to advance time.</remarks>
1085  /// <param name="frontier">Current utc datetime.</param>
1086  [DocumentationAttribute(HandlingData)]
1087  public void SetDateTime(DateTime frontier)
1088  {
1089  _timeKeeper.SetUtcDateTime(frontier);
1090  if (_locked && IsWarmingUp && Time >= _start)
1091  {
1093  }
1094  }
1095 
1096  /// <summary>
1097  /// Sets the time zone of the <see cref="Time"/> property in the algorithm
1098  /// </summary>
1099  /// <param name="timeZone">The desired time zone</param>
1100  [DocumentationAttribute(HandlingData)]
1101  public void SetTimeZone(string timeZone)
1102  {
1103  DateTimeZone tz;
1104  try
1105  {
1106  tz = DateTimeZoneProviders.Tzdb[timeZone];
1107  }
1108  catch (DateTimeZoneNotFoundException)
1109  {
1110  throw new ArgumentException($"TimeZone with id '{timeZone}' was not found. For a complete list of time zones please visit: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones");
1111  }
1112 
1113  SetTimeZone(tz);
1114  }
1115 
1116  /// <summary>
1117  /// Sets the time zone of the <see cref="Time"/> property in the algorithm
1118  /// </summary>
1119  /// <param name="timeZone">The desired time zone</param>
1120  [DocumentationAttribute(HandlingData)]
1121  public void SetTimeZone(DateTimeZone timeZone)
1122  {
1123  if (_locked)
1124  {
1125  throw new InvalidOperationException("Algorithm.SetTimeZone(): Cannot change time zone after algorithm running.");
1126  }
1127 
1128  if (timeZone == null) throw new ArgumentNullException("timeZone");
1129  _timeKeeper.AddTimeZone(timeZone);
1130  _localTimeKeeper = _timeKeeper.GetLocalTimeKeeper(timeZone);
1131 
1132  // the time rules need to know the default time zone as well
1133  TimeRules.SetDefaultTimeZone(timeZone);
1134  DateRules.SetDefaultTimeZone(timeZone);
1135 
1136  // In BackTest mode we reset the Algorithm time to reflect the new timezone
1137  // startDate is set by the user so we expect it to be for their timezone already
1138  // so there is no need to update it.
1139  if (!LiveMode)
1140  {
1141  _start = _startDate;
1142  SetDateTime(_startDate.ConvertToUtc(TimeZone));
1143  }
1144  // In live mode we need to adjust startDate to reflect the new timezone
1145  // startDate is set by Lean to the default timezone (New York), so we must update it here
1146  else
1147  {
1148  SetLiveModeStartDate();
1149  }
1150  }
1151 
1152  /// <summary>
1153  /// Sets the brokerage to emulate in backtesting or paper trading.
1154  /// This can be used for brokerages that have been implemented in LEAN
1155  /// </summary>
1156  /// <param name="brokerage">The brokerage to emulate</param>
1157  /// <param name="accountType">The account type (Cash or Margin)</param>
1158  [DocumentationAttribute(Modeling)]
1159  public void SetBrokerageModel(BrokerageName brokerage, AccountType accountType = AccountType.Margin)
1160  {
1161  SetBrokerageModel(Brokerages.BrokerageModel.Create(Transactions, brokerage, accountType));
1162  }
1163 
1164  /// <summary>
1165  /// Sets the brokerage to emulate in backtesting or paper trading.
1166  /// This can be used to set a custom brokerage model.
1167  /// </summary>
1168  /// <param name="model">The brokerage model to use</param>
1169  [DocumentationAttribute(Modeling)]
1171  {
1172  BrokerageModel = model;
1173  if (!_userSetSecurityInitializer)
1174  {
1175  // purposefully use the direct setter vs Set method so we don't flip the switch :/
1177 
1178  // update models on securities added earlier (before SetBrokerageModel is called)
1179  foreach (var kvp in Securities)
1180  {
1181  var security = kvp.Value;
1182 
1183  // save the existing leverage specified in AddSecurity,
1184  // if Leverage needs to be set in a SecurityInitializer,
1185  // SetSecurityInitializer must be called before SetBrokerageModel
1186  var leverage = security.Leverage;
1187 
1188  SecurityInitializer.Initialize(security);
1189 
1190  // restore the saved leverage
1191  security.SetLeverage(leverage);
1192  }
1193  }
1194  }
1195 
1196  /// <summary>
1197  /// Sets the implementation used to handle messages from the brokerage.
1198  /// The default implementation will forward messages to debug or error
1199  /// and when a <see cref="BrokerageMessageType.Error"/> occurs, the algorithm
1200  /// is stopped.
1201  /// </summary>
1202  /// <param name="handler">The message handler to use</param>
1203  [DocumentationAttribute(Modeling)]
1204  [DocumentationAttribute(Logging)]
1206  {
1207  BrokerageMessageHandler = handler ?? throw new ArgumentNullException(nameof(handler));
1208  }
1209 
1210  /// <summary>
1211  /// Sets the benchmark used for computing statistics of the algorithm to the specified symbol
1212  /// </summary>
1213  /// <param name="symbol">symbol to use as the benchmark</param>
1214  /// <param name="securityType">Is the symbol an equity, forex, base, etc. Default SecurityType.Equity</param>
1215  /// <remarks>
1216  /// Must use symbol that is available to the trade engine in your data store(not strictly enforced)
1217  /// </remarks>
1218  [Obsolete("Symbol implicit operator to string is provided for algorithm use only.")]
1219  [DocumentationAttribute(TradingAndOrders)]
1220  [DocumentationAttribute(SecuritiesAndPortfolio)]
1221  [DocumentationAttribute(Indicators)]
1222  public void SetBenchmark(SecurityType securityType, string symbol)
1223  {
1224  if (_locked)
1225  {
1226  throw new InvalidOperationException("Algorithm.SetBenchmark(): Cannot change Benchmark after algorithm initialized.");
1227  }
1228 
1229  string market;
1230  if (!BrokerageModel.DefaultMarkets.TryGetValue(securityType, out market))
1231  {
1232  market = Market.USA;
1233  }
1234 
1235  var benchmarkSymbol = QuantConnect.Symbol.Create(symbol, securityType, market);
1236  SetBenchmark(benchmarkSymbol);
1237  }
1238 
1239  /// <summary>
1240  /// Sets the benchmark used for computing statistics of the algorithm to the specified ticker, defaulting to SecurityType.Equity
1241  /// if the ticker doesn't exist in the algorithm
1242  /// </summary>
1243  /// <param name="ticker">Ticker to use as the benchmark</param>
1244  /// <remarks>
1245  /// Overload to accept ticker without passing SecurityType. If ticker is in portfolio it will use that SecurityType, otherwise will default to SecurityType.Equity
1246  /// </remarks>
1247  [DocumentationAttribute(TradingAndOrders)]
1248  [DocumentationAttribute(SecuritiesAndPortfolio)]
1249  [DocumentationAttribute(Indicators)]
1250  public void SetBenchmark(string ticker)
1251  {
1252  Symbol symbol;
1253 
1254  // Check the cache for the symbol
1255  if (!SymbolCache.TryGetSymbol(ticker, out symbol))
1256  {
1257  // Check our securities for a symbol matched with this ticker
1258  symbol = Securities.FirstOrDefault(x => x.Key.Value == ticker).Key;
1259 
1260  // If we didn't find a symbol matching our ticker, create one.
1261  if (symbol == null)
1262  {
1263  Debug($"Warning: SetBenchmark({ticker}): no existing symbol found, benchmark security will be added with {SecurityType.Equity} type.");
1264  symbol = QuantConnect.Symbol.Create(ticker, SecurityType.Equity, Market.USA);
1265  }
1266  }
1267 
1268  // Send our symbol through
1269  SetBenchmark(symbol);
1270  }
1271 
1272  /// <summary>
1273  /// Sets the benchmark used for computing statistics of the algorithm to the specified symbol
1274  /// </summary>
1275  /// <param name="symbol">symbol to use as the benchmark</param>
1276  [DocumentationAttribute(TradingAndOrders)]
1277  [DocumentationAttribute(SecuritiesAndPortfolio)]
1278  [DocumentationAttribute(Indicators)]
1279  public void SetBenchmark(Symbol symbol)
1280  {
1281  if (_locked)
1282  {
1283  throw new InvalidOperationException("Algorithm.SetBenchmark(): Cannot change Benchmark after algorithm initialized.");
1284  }
1285 
1286  // Create our security benchmark
1288  }
1289 
1290  /// <summary>
1291  /// Sets the specified function as the benchmark, this function provides the value of
1292  /// the benchmark at each date/time requested
1293  /// </summary>
1294  /// <param name="benchmark">The benchmark producing function</param>
1295  [DocumentationAttribute(TradingAndOrders)]
1296  [DocumentationAttribute(SecuritiesAndPortfolio)]
1297  [DocumentationAttribute(Indicators)]
1298  public void SetBenchmark(Func<DateTime, decimal> benchmark)
1299  {
1300  if (_locked)
1301  {
1302  throw new InvalidOperationException("Algorithm.SetBenchmark(): Cannot change Benchmark after algorithm initialized.");
1303  }
1304 
1305  Benchmark = new FuncBenchmark(benchmark);
1306  }
1307 
1308  /// <summary>
1309  /// Benchmark
1310  /// </summary>
1311  /// <remarks>Use Benchmark to override default symbol based benchmark, and create your own benchmark. For example a custom moving average benchmark </remarks>
1312  ///
1313  [DocumentationAttribute(TradingAndOrders)]
1314  [DocumentationAttribute(SecuritiesAndPortfolio)]
1315  [DocumentationAttribute(Indicators)]
1316  public IBenchmark Benchmark
1317  {
1318  get;
1319  private set;
1320  }
1321 
1322  /// <summary>
1323  /// Sets the account currency cash symbol this algorithm is to manage, as well as
1324  /// the starting cash in this currency if given
1325  /// </summary>
1326  /// <remarks>Has to be called during <see cref="Initialize"/> before
1327  /// calling <see cref="SetCash(decimal)"/> or adding any <see cref="Security"/></remarks>
1328  /// <param name="accountCurrency">The account currency cash symbol to set</param>
1329  /// <param name="startingCash">The account currency starting cash to set</param>
1330  [DocumentationAttribute(SecuritiesAndPortfolio)]
1331  public void SetAccountCurrency(string accountCurrency, decimal? startingCash = null)
1332  {
1333  if (_locked)
1334  {
1335  throw new InvalidOperationException("Algorithm.SetAccountCurrency(): " +
1336  "Cannot change AccountCurrency after algorithm initialized.");
1337  }
1338 
1339  if (startingCash == null)
1340  {
1341  Debug($"Changing account currency from {AccountCurrency} to {accountCurrency}...");
1342  }
1343  else
1344  {
1345  Debug($"Changing account currency from {AccountCurrency} to {accountCurrency}, with a starting cash of {startingCash}...");
1346  }
1347 
1348  Portfolio.SetAccountCurrency(accountCurrency, startingCash);
1349  }
1350 
1351  /// <summary>
1352  /// Set initial cash for the strategy while backtesting. During live mode this value is ignored
1353  /// and replaced with the actual cash of your brokerage account.
1354  /// </summary>
1355  /// <param name="startingCash">Starting cash for the strategy backtest</param>
1356  /// <remarks>Alias of SetCash(decimal)</remarks>
1357  [DocumentationAttribute(SecuritiesAndPortfolio)]
1358  public void SetCash(double startingCash)
1359  {
1360  SetCash((decimal)startingCash);
1361  }
1362 
1363  /// <summary>
1364  /// Set initial cash for the strategy while backtesting. During live mode this value is ignored
1365  /// and replaced with the actual cash of your brokerage account.
1366  /// </summary>
1367  /// <param name="startingCash">Starting cash for the strategy backtest</param>
1368  /// <remarks>Alias of SetCash(decimal)</remarks>
1369  [DocumentationAttribute(SecuritiesAndPortfolio)]
1370  public void SetCash(int startingCash)
1371  {
1372  SetCash((decimal)startingCash);
1373  }
1374 
1375  /// <summary>
1376  /// Set initial cash for the strategy while backtesting. During live mode this value is ignored
1377  /// and replaced with the actual cash of your brokerage account.
1378  /// </summary>
1379  /// <param name="startingCash">Starting cash for the strategy backtest</param>
1380  [DocumentationAttribute(SecuritiesAndPortfolio)]
1381  public void SetCash(decimal startingCash)
1382  {
1383  if (!_locked)
1384  {
1385  Portfolio.SetCash(startingCash);
1386  }
1387  else
1388  {
1389  throw new InvalidOperationException("Algorithm.SetCash(): Cannot change cash available after algorithm initialized.");
1390  }
1391  }
1392 
1393  /// <summary>
1394  /// Set the cash for the specified symbol
1395  /// </summary>
1396  /// <param name="symbol">The cash symbol to set</param>
1397  /// <param name="startingCash">Decimal cash value of portfolio</param>
1398  /// <param name="conversionRate">The current conversion rate for the</param>
1399  [DocumentationAttribute(SecuritiesAndPortfolio)]
1400  public void SetCash(string symbol, decimal startingCash, decimal conversionRate = 0)
1401  {
1402  if (!_locked)
1403  {
1404  Portfolio.SetCash(symbol, startingCash, conversionRate);
1405  }
1406  else
1407  {
1408  throw new InvalidOperationException("Algorithm.SetCash(): Cannot change cash available after algorithm initialized.");
1409  }
1410  }
1411 
1412  /// <summary>
1413  /// Set the start date for backtest.
1414  /// </summary>
1415  /// <param name="day">Int starting date 1-30</param>
1416  /// <param name="month">Int month starting date</param>
1417  /// <param name="year">Int year starting date</param>
1418  /// <remarks>Wrapper for SetStartDate(DateTime).
1419  /// Must be less than end date.
1420  /// Ignored in live trading mode.</remarks>
1421  /// <seealso cref="SetStartDate(DateTime)"/>
1422  [DocumentationAttribute(HandlingData)]
1423  public void SetStartDate(int year, int month, int day)
1424  {
1425  try
1426  {
1427  var start = new DateTime(year, month, day);
1428 
1429  // We really just want the date of the start, so it's 12am of the requested day (first moment of the day)
1430  start = start.Date;
1431 
1432  SetStartDate(start);
1433  }
1434  catch (Exception err)
1435  {
1436  throw new ArgumentException($"Date Invalid: {err.Message}");
1437  }
1438  }
1439 
1440  /// <summary>
1441  /// Set the end date for a backtest run
1442  /// </summary>
1443  /// <param name="day">Int end date 1-30</param>
1444  /// <param name="month">Int month end date</param>
1445  /// <param name="year">Int year end date</param>
1446  /// <remarks>Wrapper for SetEndDate(datetime).</remarks>
1447  /// <seealso cref="SetEndDate(DateTime)"/>
1448  [DocumentationAttribute(HandlingData)]
1449  public void SetEndDate(int year, int month, int day)
1450  {
1451  try
1452  {
1453  var end = new DateTime(year, month, day);
1454 
1455  // we want the end date to be just before the next day (last moment of the day)
1456  end = end.Date.AddDays(1).Subtract(TimeSpan.FromTicks(1));
1457 
1458  SetEndDate(end);
1459  }
1460  catch (Exception err)
1461  {
1462  throw new ArgumentException($"Date Invalid: {err.Message}");
1463  }
1464  }
1465 
1466  /// <summary>
1467  /// Set the algorithm id (backtestId or live deployId for the algorithm).
1468  /// </summary>
1469  /// <param name="algorithmId">String Algorithm Id</param>
1470  /// <remarks>Intended for internal QC Lean Engine use only as a setter for AlgorithmId</remarks>
1471  [DocumentationAttribute(HandlingData)]
1472  public void SetAlgorithmId(string algorithmId)
1473  {
1474  _algorithmId = algorithmId;
1475  }
1476 
1477  /// <summary>
1478  /// Set the start date for the backtest
1479  /// </summary>
1480  /// <param name="start">Datetime Start date for backtest</param>
1481  /// <remarks>Must be less than end date and within data available</remarks>
1482  /// <seealso cref="SetStartDate(int, int, int)"/>
1483  [DocumentationAttribute(HandlingData)]
1484  public void SetStartDate(DateTime start)
1485  {
1486  // no need to set this value in live mode, will be set using the current time.
1487  if (_liveMode) return;
1488 
1489  //Round down
1490  start = start.RoundDown(TimeSpan.FromDays(1));
1491 
1492  //Validate the start date:
1493  //1. Check range;
1494  if (start < (new DateTime(1900, 01, 01)))
1495  {
1496  throw new ArgumentOutOfRangeException(nameof(start), "Please select a start date after January 1st, 1900.");
1497  }
1498 
1499  //2. Check future date
1500  var todayInAlgorithmTimeZone = DateTime.UtcNow.ConvertFromUtc(TimeZone).Date;
1501  if (start > todayInAlgorithmTimeZone)
1502  {
1503  throw new ArgumentOutOfRangeException(nameof(start), "Please select start date less than today");
1504  }
1505 
1506  //3. Check not locked already:
1507  if (!_locked)
1508  {
1509  _start = _startDate = start;
1510  SetDateTime(_startDate.ConvertToUtc(TimeZone));
1511  }
1512  else
1513  {
1514  throw new InvalidOperationException("Algorithm.SetStartDate(): Cannot change start date after algorithm initialized.");
1515  }
1516  }
1517 
1518  /// <summary>
1519  /// Set the end date for a backtest.
1520  /// </summary>
1521  /// <param name="end">Datetime value for end date</param>
1522  /// <remarks>Must be greater than the start date</remarks>
1523  /// <seealso cref="SetEndDate(int, int, int)"/>
1524  [DocumentationAttribute(HandlingData)]
1525  public void SetEndDate(DateTime end)
1526  {
1527  // no need to set this value in live mode, will be set using the current time.
1528  if (_liveMode) return;
1529 
1530  //1. Check not locked already:
1531  if (_locked)
1532  {
1533  throw new InvalidOperationException("Algorithm.SetEndDate(): Cannot change end date after algorithm initialized.");
1534  }
1535 
1536  //Validate:
1537  //2. Check Range:
1538  var yesterdayInAlgorithmTimeZone = DateTime.UtcNow.ConvertFromUtc(TimeZone).Date.AddDays(-1);
1539  if (end > yesterdayInAlgorithmTimeZone)
1540  {
1541  end = yesterdayInAlgorithmTimeZone;
1542  }
1543 
1544  //3. Make this at the very end of the requested date
1545  _endDate = end.RoundDown(TimeSpan.FromDays(1)).AddDays(1).AddTicks(-1);
1546  }
1547 
1548  /// <summary>
1549  /// Lock the algorithm initialization to avoid user modifiying cash and data stream subscriptions
1550  /// </summary>
1551  /// <remarks>Intended for Internal QC Lean Engine use only to prevent accidental manipulation of important properties</remarks>
1552  [DocumentationAttribute(AlgorithmFramework)]
1553  public void SetLocked()
1554  {
1555  _locked = true;
1556  }
1557 
1558  /// <summary>
1559  /// Gets whether or not this algorithm has been locked and fully initialized
1560  /// </summary>
1561  [DocumentationAttribute(AlgorithmFramework)]
1562  public bool GetLocked()
1563  {
1564  return _locked;
1565  }
1566 
1567  /// <summary>
1568  /// Set live mode state of the algorithm run: Public setter for the algorithm property LiveMode.
1569  /// </summary>
1570  [DocumentationAttribute(LiveTrading)]
1571  public void SetLiveMode(bool live)
1572  {
1573  if (!_locked)
1574  {
1575  _liveMode = live;
1576  Notify = new NotificationManager(live);
1577  TradeBuilder.SetLiveMode(live);
1578  Securities.SetLiveMode(live);
1579  Transactions.SetLiveMode(live);
1580  if (live)
1581  {
1582  SetLiveModeStartDate();
1583  }
1584  }
1585  }
1586 
1587  /// <summary>
1588  /// Set the <see cref="ITradeBuilder"/> implementation to generate trades from executions and market price updates
1589  /// </summary>
1590  [DocumentationAttribute(TradingAndOrders)]
1591  public void SetTradeBuilder(ITradeBuilder tradeBuilder)
1592  {
1593  TradeBuilder = tradeBuilder;
1595  }
1596 
1597  /// <summary>
1598  /// Add specified data to our data subscriptions. QuantConnect will funnel this data to the handle data routine.
1599  /// </summary>
1600  /// <param name="securityType">MarketType Type: Equity, Commodity, Future, FOREX or Crypto</param>
1601  /// <param name="ticker">The security ticker</param>
1602  /// <param name="resolution">Resolution of the Data Required</param>
1603  /// <param name="fillForward">When no data available on a tradebar, return the last data that was generated</param>
1604  /// <param name="extendedMarketHours">Use extended market hours data</param>
1605  /// <param name="dataMappingMode">The contract mapping mode to use for the security</param>
1606  /// <param name="dataNormalizationMode">The price scaling mode to use for the security</param>
1607  [DocumentationAttribute(AddingData)]
1608  public Security AddSecurity(SecurityType securityType, string ticker, Resolution? resolution = null, bool fillForward = true, bool extendedMarketHours = false,
1609  DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null)
1610  {
1611  return AddSecurity(securityType, ticker, resolution, fillForward, Security.NullLeverage, extendedMarketHours, dataMappingMode, dataNormalizationMode);
1612  }
1613 
1614  /// <summary>
1615  /// Add specified data to required list. QC will funnel this data to the handle data routine.
1616  /// </summary>
1617  /// <param name="securityType">MarketType Type: Equity, Commodity, Future, FOREX or Crypto</param>
1618  /// <param name="ticker">The security ticker</param>
1619  /// <param name="resolution">Resolution of the Data Required</param>
1620  /// <param name="fillForward">When no data available on a tradebar, return the last data that was generated</param>
1621  /// <param name="leverage">Custom leverage per security</param>
1622  /// <param name="extendedMarketHours">Use extended market hours data</param>
1623  /// <param name="dataMappingMode">The contract mapping mode to use for the security</param>
1624  /// <param name="dataNormalizationMode">The price scaling mode to use for the security</param>
1625  /// <remarks> AddSecurity(SecurityType securityType, Symbol symbol, Resolution resolution, bool fillForward, decimal leverage, bool extendedMarketHours)</remarks>
1626  [DocumentationAttribute(AddingData)]
1627  public Security AddSecurity(SecurityType securityType, string ticker, Resolution? resolution, bool fillForward, decimal leverage, bool extendedMarketHours,
1628  DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null)
1629  {
1630  return AddSecurity(securityType, ticker, resolution, null, fillForward, leverage, extendedMarketHours, dataMappingMode, dataNormalizationMode);
1631  }
1632 
1633  /// <summary>
1634  /// Set a required SecurityType-symbol and resolution for algorithm
1635  /// </summary>
1636  /// <param name="securityType">MarketType Type: Equity, Commodity, Future, FOREX or Crypto</param>
1637  /// <param name="ticker">The security ticker, e.g. AAPL</param>
1638  /// <param name="resolution">Resolution of the MarketType required: MarketData, Second or Minute</param>
1639  /// <param name="market">The market the requested security belongs to, such as 'usa' or 'fxcm'</param>
1640  /// <param name="fillForward">If true, returns the last available data even if none in that timeslice.</param>
1641  /// <param name="leverage">leverage for this security</param>
1642  /// <param name="extendedMarketHours">Use extended market hours data</param>
1643  /// <param name="dataMappingMode">The contract mapping mode to use for the security</param>
1644  /// <param name="dataNormalizationMode">The price scaling mode to use for the security</param>
1645  [DocumentationAttribute(AddingData)]
1646  public Security AddSecurity(SecurityType securityType, string ticker, Resolution? resolution, string market, bool fillForward, decimal leverage, bool extendedMarketHours,
1647  DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null)
1648  {
1649  // if AddSecurity method is called to add an option or a future, we delegate a call to respective methods
1650  if (securityType == SecurityType.Option)
1651  {
1652  return AddOption(ticker, resolution, market, fillForward, leverage);
1653  }
1654 
1655  if (securityType == SecurityType.Future)
1656  {
1657  return AddFuture(ticker, resolution, market, fillForward, leverage, extendedMarketHours, dataMappingMode, dataNormalizationMode);
1658  }
1659 
1660  try
1661  {
1662  if (market == null)
1663  {
1664  if (!BrokerageModel.DefaultMarkets.TryGetValue(securityType, out market))
1665  {
1666  throw new KeyNotFoundException($"No default market set for security type: {securityType}");
1667  }
1668  }
1669 
1670  Symbol symbol;
1671  if (!SymbolCache.TryGetSymbol(ticker, out symbol) ||
1672  symbol.ID.Market != market ||
1673  symbol.SecurityType != securityType)
1674  {
1675  symbol = QuantConnect.Symbol.Create(ticker, securityType, market);
1676  }
1677 
1678  return AddSecurity(symbol, resolution, fillForward, leverage, extendedMarketHours, dataMappingMode, dataNormalizationMode);
1679  }
1680  catch (Exception err)
1681  {
1682  Error("Algorithm.AddSecurity(): " + err);
1683  return null;
1684  }
1685  }
1686 
1687  /// <summary>
1688  /// Set a required SecurityType-symbol and resolution for algorithm
1689  /// </summary>
1690  /// <param name="symbol">The security Symbol</param>
1691  /// <param name="resolution">Resolution of the MarketType required: MarketData, Second or Minute</param>
1692  /// <param name="fillForward">If true, returns the last available data even if none in that timeslice.</param>
1693  /// <param name="leverage">leverage for this security</param>
1694  /// <param name="extendedMarketHours">Use extended market hours data</param>
1695  /// <param name="dataMappingMode">The contract mapping mode to use for the security</param>
1696  /// <param name="dataNormalizationMode">The price scaling mode to use for the security</param>
1697  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
1698  /// For example, 0 (default) will use the front month, 1 will use the back month contract</param>
1699  /// <returns>The new Security that was added to the algorithm</returns>
1700  [DocumentationAttribute(AddingData)]
1701  public Security AddSecurity(Symbol symbol, Resolution? resolution = null, bool fillForward = true, decimal leverage = Security.NullLeverage, bool extendedMarketHours = false,
1702  DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null, int contractDepthOffset = 0)
1703  {
1704  // allow users to specify negative numbers, we get the abs of it
1705  var contractOffset = (uint)Math.Abs(contractDepthOffset);
1706  if (contractOffset > Futures.MaximumContractDepthOffset)
1707  {
1708  throw new ArgumentOutOfRangeException(nameof(contractDepthOffset), $"'contractDepthOffset' current maximum value is {Futures.MaximumContractDepthOffset}." +
1709  $" Front month (0) and only {Futures.MaximumContractDepthOffset} back month contracts are currently supported.");
1710  }
1711 
1712  var isCanonical = symbol.IsCanonical();
1713 
1714  // Short-circuit to AddOptionContract because it will add the underlying if required
1715  if (!isCanonical && symbol.SecurityType.IsOption())
1716  {
1717  return AddOptionContract(symbol, resolution, fillForward, leverage, extendedMarketHours);
1718  }
1719 
1720  var isFilteredSubscription = !isCanonical;
1721  List<SubscriptionDataConfig> configs;
1722  // we pass dataNormalizationMode to SubscriptionManager.SubscriptionDataConfigService.Add conditionally,
1723  // so the default value for its argument is used when the it is null here.
1724  if (dataNormalizationMode.HasValue)
1725  {
1727  resolution,
1728  fillForward,
1729  extendedMarketHours,
1730  isFilteredSubscription,
1731  dataNormalizationMode: dataNormalizationMode.Value,
1732  contractDepthOffset: (uint)contractDepthOffset);
1733  }
1734  else
1735  {
1737  resolution,
1738  fillForward,
1739  extendedMarketHours,
1740  isFilteredSubscription,
1741  contractDepthOffset: (uint)contractDepthOffset);
1742  }
1743 
1744  var security = Securities.CreateSecurity(symbol, configs, leverage);
1745 
1746  if (isCanonical)
1747  {
1748  security.IsTradable = false;
1749  Securities.Add(security);
1750 
1751  // add this security to the user defined universe
1752  Universe universe;
1753  if (!UniverseManager.TryGetValue(symbol, out universe) && !IsAlreadyPending(symbol))
1754  {
1755  var canonicalConfig = configs.First();
1756  var settings = new UniverseSettings(canonicalConfig.Resolution, leverage, fillForward, extendedMarketHours, UniverseSettings.MinimumTimeInUniverse);
1757  if (symbol.SecurityType.IsOption())
1758  {
1759  universe = new OptionChainUniverse((Option)security, settings);
1760  }
1761  else
1762  {
1763  // add the expected configurations of the canonical symbol right away, will allow it to warmup and indicators register to them
1765  GetResolution(symbol, resolution), isCanonical: false);
1766  var continuousUniverseSettings = new UniverseSettings(settings)
1767  {
1768  ExtendedMarketHours = extendedMarketHours,
1769  DataMappingMode = dataMappingMode ?? UniverseSettings.DataMappingMode,
1770  DataNormalizationMode = dataNormalizationMode ?? UniverseSettings.GetUniverseNormalizationModeOrDefault(symbol.SecurityType),
1771  ContractDepthOffset = (int)contractOffset,
1772  SubscriptionDataTypes = dataTypes,
1773  };
1775 
1776  // let's add a MHDB entry for the continuous symbol using the associated security
1777  var continuousContractSymbol = ContinuousContractUniverse.CreateSymbol(security.Symbol);
1778  MarketHoursDatabase.SetEntry(continuousContractSymbol.ID.Market,
1779  continuousContractSymbol.ID.Symbol,
1780  continuousContractSymbol.ID.SecurityType,
1781  security.Exchange.Hours);
1782  AddUniverse(new ContinuousContractUniverse(security, continuousUniverseSettings, LiveMode, new SubscriptionDataConfig(canonicalConfig, symbol: continuousContractSymbol)));
1783 
1784  universe = new FuturesChainUniverse((Future)security, settings);
1785  }
1786 
1787  AddUniverse(universe);
1788  }
1789  return security;
1790  }
1791 
1792  return AddToUserDefinedUniverse(security, configs);
1793  }
1794 
1795  /// <summary>
1796  /// Creates and adds a new <see cref="Equity"/> security to the algorithm
1797  /// </summary>
1798  /// <param name="ticker">The equity ticker symbol</param>
1799  /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
1800  /// <param name="market">The equity's market, <seealso cref="Market"/>. Default value is null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
1801  /// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
1802  /// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
1803  /// <param name="extendedMarketHours">True to send data during pre and post market sessions. Default is <value>false</value></param>
1804  /// <param name="dataNormalizationMode">The price scaling mode to use for the equity</param>
1805  /// <returns>The new <see cref="Equity"/> security</returns>
1806  [DocumentationAttribute(AddingData)]
1807  public Equity AddEquity(string ticker, Resolution? resolution = null, string market = null, bool fillForward = true,
1808  decimal leverage = Security.NullLeverage, bool extendedMarketHours = false, DataNormalizationMode? dataNormalizationMode = null)
1809  {
1810  return AddSecurity<Equity>(SecurityType.Equity, ticker, resolution, market, fillForward, leverage, extendedMarketHours, normalizationMode: dataNormalizationMode);
1811  }
1812 
1813  /// <summary>
1814  /// Creates and adds a new equity <see cref="Option"/> security to the algorithm
1815  /// </summary>
1816  /// <param name="underlying">The underlying equity ticker</param>
1817  /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
1818  /// <param name="market">The equity's market, <seealso cref="Market"/>. Default is value null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
1819  /// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
1820  /// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
1821  /// <returns>The new <see cref="Option"/> security</returns>
1822  [DocumentationAttribute(AddingData)]
1823  public Option AddOption(string underlying, Resolution? resolution = null, string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
1824  {
1825  if (market == null)
1826  {
1827  if (!BrokerageModel.DefaultMarkets.TryGetValue(SecurityType.Option, out market))
1828  {
1829  throw new KeyNotFoundException($"No default market set for security type: {SecurityType.Option}");
1830  }
1831  }
1832 
1833  var underlyingSymbol = QuantConnect.Symbol.Create(underlying, SecurityType.Equity, market);
1834  return AddOption(underlyingSymbol, resolution, market, fillForward, leverage);
1835  }
1836 
1837  /// <summary>
1838  /// Creates and adds a new <see cref="Option"/> security to the algorithm.
1839  /// This method can be used to add options with non-equity asset classes
1840  /// to the algorithm (e.g. Future Options).
1841  /// </summary>
1842  /// <param name="underlying">Underlying asset Symbol to use as the option's underlying</param>
1843  /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
1844  /// <param name="market">The option's market, <seealso cref="Market"/>. Default value is null, but will be resolved using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
1845  /// <param name="fillForward">If true, data will be provided to the algorithm every Second, Minute, Hour, or Day, while the asset is open and depending on the Resolution this option was configured to use.</param>
1846  /// <param name="leverage">The requested leverage for the </param>
1847  /// <returns>The new option security instance</returns>
1848  /// <exception cref="KeyNotFoundException"></exception>
1849  [DocumentationAttribute(AddingData)]
1850  public Option AddOption(Symbol underlying, Resolution? resolution = null, string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
1851  {
1852  return AddOption(underlying, null, resolution, market, fillForward, leverage);
1853  }
1854 
1855  /// <summary>
1856  /// Creates and adds a new <see cref="Option"/> security to the algorithm.
1857  /// This method can be used to add options with non-equity asset classes
1858  /// to the algorithm (e.g. Future Options).
1859  /// </summary>
1860  /// <param name="underlying">Underlying asset Symbol to use as the option's underlying</param>
1861  /// <param name="targetOption">The target option ticker. This is useful when the option ticker does not match the underlying, e.g. SPX index and the SPXW weekly option. If null is provided will use underlying</param>
1862  /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
1863  /// <param name="market">The option's market, <seealso cref="Market"/>. Default value is null, but will be resolved using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
1864  /// <param name="fillForward">If true, data will be provided to the algorithm every Second, Minute, Hour, or Day, while the asset is open and depending on the Resolution this option was configured to use.</param>
1865  /// <param name="leverage">The requested leverage for the </param>
1866  /// <returns>The new option security instance</returns>
1867  /// <exception cref="KeyNotFoundException"></exception>
1868  public Option AddOption(Symbol underlying, string targetOption, Resolution? resolution = null,
1869  string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
1870  {
1871  var optionType = QuantConnect.Symbol.GetOptionTypeFromUnderlying(underlying);
1872 
1873  if (market == null)
1874  {
1875  if (!BrokerageModel.DefaultMarkets.TryGetValue(optionType, out market))
1876  {
1877  throw new KeyNotFoundException($"No default market set for security type: {optionType}");
1878  }
1879  }
1880 
1881  Symbol canonicalSymbol;
1882 
1883  string alias;
1884  if (!string.IsNullOrEmpty(targetOption))
1885  {
1886  alias = $"?{targetOption}";
1887  }
1888  else
1889  {
1890  alias = $"?{underlying.Value}";
1891  }
1892  if (!SymbolCache.TryGetSymbol(alias, out canonicalSymbol) ||
1893  canonicalSymbol.ID.Market != market ||
1894  !canonicalSymbol.SecurityType.IsOption())
1895  {
1896  canonicalSymbol = QuantConnect.Symbol.CreateCanonicalOption(underlying, targetOption, market, alias);
1897  }
1898 
1899  return (Option)AddSecurity(canonicalSymbol, resolution, fillForward, leverage);
1900  }
1901 
1902  /// <summary>
1903  /// Creates and adds a new <see cref="Future"/> security to the algorithm
1904  /// </summary>
1905  /// <param name="ticker">The future ticker</param>
1906  /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
1907  /// <param name="market">The futures market, <seealso cref="Market"/>. Default is value null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
1908  /// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
1909  /// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
1910  /// <param name="extendedMarketHours">Use extended market hours data</param>
1911  /// <param name="dataMappingMode">The contract mapping mode to use for the continuous future contract</param>
1912  /// <param name="dataNormalizationMode">The price scaling mode to use for the continuous future contract</param>
1913  /// <param name="contractDepthOffset">The continuous future contract desired offset from the current front month.
1914  /// For example, 0 (default) will use the front month, 1 will use the back month contract</param>
1915  /// <returns>The new <see cref="Future"/> security</returns>
1916  [DocumentationAttribute(AddingData)]
1917  public Future AddFuture(string ticker, Resolution? resolution = null, string market = null,
1918  bool fillForward = true, decimal leverage = Security.NullLeverage, bool extendedMarketHours = false,
1919  DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null, int contractDepthOffset = 0)
1920  {
1921  if (market == null)
1922  {
1923  if (!SymbolPropertiesDatabase.TryGetMarket(ticker, SecurityType.Future, out market)
1924  && !BrokerageModel.DefaultMarkets.TryGetValue(SecurityType.Future, out market))
1925  {
1926  throw new KeyNotFoundException($"No default market set for security type: {SecurityType.Future}");
1927  }
1928  }
1929 
1930  Symbol canonicalSymbol;
1931  var alias = "/" + ticker;
1932  if (!SymbolCache.TryGetSymbol(alias, out canonicalSymbol) ||
1933  canonicalSymbol.ID.Market != market ||
1934  canonicalSymbol.SecurityType != SecurityType.Future)
1935  {
1936  canonicalSymbol = QuantConnect.Symbol.Create(ticker, SecurityType.Future, market, alias);
1937  }
1938 
1939  return (Future)AddSecurity(canonicalSymbol, resolution, fillForward, leverage, extendedMarketHours, dataMappingMode: dataMappingMode,
1940  dataNormalizationMode: dataNormalizationMode, contractDepthOffset: contractDepthOffset);
1941  }
1942 
1943  /// <summary>
1944  /// Creates and adds a new single <see cref="Future"/> contract to the algorithm
1945  /// </summary>
1946  /// <param name="symbol">The futures contract symbol</param>
1947  /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
1948  /// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
1949  /// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
1950  /// <param name="extendedMarketHours">Use extended market hours data</param>
1951  /// <returns>The new <see cref="Future"/> security</returns>
1952  [DocumentationAttribute(AddingData)]
1953  public Future AddFutureContract(Symbol symbol, Resolution? resolution = null, bool fillForward = true,
1954  decimal leverage = Security.NullLeverage, bool extendedMarketHours = false)
1955  {
1956  return (Future)AddSecurity(symbol, resolution, fillForward, leverage, extendedMarketHours);
1957  }
1958 
1959  /// <summary>
1960  /// Creates and adds a new Future Option contract to the algorithm.
1961  /// </summary>
1962  /// <param name="symbol">The <see cref="Future"/> canonical symbol (i.e. Symbol returned from <see cref="AddFuture"/>)</param>
1963  /// <param name="optionFilter">Filter to apply to option contracts loaded as part of the universe</param>
1964  /// <returns>The new <see cref="Option"/> security, containing a <see cref="Future"/> as its underlying.</returns>
1965  /// <exception cref="ArgumentException">The symbol provided is not canonical.</exception>
1966  [DocumentationAttribute(AddingData)]
1967  public void AddFutureOption(Symbol symbol, Func<OptionFilterUniverse, OptionFilterUniverse> optionFilter = null)
1968  {
1969  if (!symbol.IsCanonical())
1970  {
1971  throw new ArgumentException("Symbol provided must be canonical (i.e. the Symbol returned from AddFuture(), not AddFutureContract().");
1972  }
1973 
1974  AddUniverseOptions(symbol, optionFilter);
1975  }
1976 
1977  /// <summary>
1978  /// Adds a future option contract to the algorithm.
1979  /// </summary>
1980  /// <param name="symbol">Option contract Symbol</param>
1981  /// <param name="resolution">Resolution of the option contract, i.e. the granularity of the data</param>
1982  /// <param name="fillForward">If true, this will fill in missing data points with the previous data point</param>
1983  /// <param name="leverage">The leverage to apply to the option contract</param>
1984  /// <param name="extendedMarketHours">Use extended market hours data</param>
1985  /// <returns>Option security</returns>
1986  /// <exception cref="ArgumentException">Symbol is canonical (i.e. a generic Symbol returned from <see cref="AddFuture"/> or <see cref="AddOption(string, Resolution?, string, bool, decimal)"/>)</exception>
1987  [DocumentationAttribute(AddingData)]
1988  public Option AddFutureOptionContract(Symbol symbol, Resolution? resolution = null, bool fillForward = true,
1989  decimal leverage = Security.NullLeverage, bool extendedMarketHours = false)
1990  {
1991  if (symbol.IsCanonical())
1992  {
1993  throw new ArgumentException("Expected non-canonical Symbol (i.e. a Symbol representing a specific Future contract");
1994  }
1995 
1996  return AddOptionContract(symbol, resolution, fillForward, leverage, extendedMarketHours);
1997  }
1998 
1999  /// <summary>
2000  /// Creates and adds index options to the algorithm.
2001  /// </summary>
2002  /// <param name="ticker">The ticker of the Index Option</param>
2003  /// <param name="resolution">Resolution of the index option contracts, i.e. the granularity of the data</param>
2004  /// <param name="market">Market of the index option. If no market is provided, we default to <see cref="Market.USA"/> </param>
2005  /// <param name="fillForward">If true, this will fill in missing data points with the previous data point</param>
2006  /// <returns>Canonical Option security</returns>
2007  [DocumentationAttribute(AddingData)]
2008  public Option AddIndexOption(string ticker, Resolution? resolution = null, string market = Market.USA, bool fillForward = true)
2009  {
2010  return AddIndexOption(
2011  QuantConnect.Symbol.Create(ticker, SecurityType.Index, market),
2012  resolution,
2013  fillForward);
2014  }
2015 
2016  /// <summary>
2017  /// Creates and adds index options to the algorithm.
2018  /// </summary>
2019  /// <param name="symbol">The Symbol of the <see cref="Security"/> returned from <see cref="AddIndex"/></param>
2020  /// <param name="resolution">Resolution of the index option contracts, i.e. the granularity of the data</param>
2021  /// <param name="fillForward">If true, this will fill in missing data points with the previous data point</param>
2022  /// <returns>Canonical Option security</returns>
2023  [DocumentationAttribute(AddingData)]
2024  public Option AddIndexOption(Symbol symbol, Resolution? resolution = null, bool fillForward = true)
2025  {
2026  return AddIndexOption(symbol, null, resolution, fillForward);
2027  }
2028 
2029  /// <summary>
2030  /// Creates and adds index options to the algorithm.
2031  /// </summary>
2032  /// <param name="symbol">The Symbol of the <see cref="Security"/> returned from <see cref="AddIndex"/></param>
2033  /// <param name="targetOption">The target option ticker. This is useful when the option ticker does not match the underlying, e.g. SPX index and the SPXW weekly option. If null is provided will use underlying</param>
2034  /// <param name="resolution">Resolution of the index option contracts, i.e. the granularity of the data</param>
2035  /// <param name="fillForward">If true, this will fill in missing data points with the previous data point</param>
2036  /// <returns>Canonical Option security</returns>
2037  [DocumentationAttribute(AddingData)]
2038  public Option AddIndexOption(Symbol symbol, string targetOption, Resolution? resolution = null, bool fillForward = true)
2039  {
2040  if (symbol.SecurityType != SecurityType.Index)
2041  {
2042  throw new ArgumentException("Symbol provided must be of type SecurityType.Index");
2043  }
2044 
2045  return AddOption(symbol, targetOption, resolution, symbol.ID.Market, fillForward);
2046  }
2047 
2048  /// <summary>
2049  /// Adds an index option contract to the algorithm.
2050  /// </summary>
2051  /// <param name="symbol">Symbol of the index option contract</param>
2052  /// <param name="resolution">Resolution of the index option contract, i.e. the granularity of the data</param>
2053  /// <param name="fillForward">If true, this will fill in missing data points with the previous data point</param>
2054  /// <returns>Index Option Contract</returns>
2055  /// <exception cref="ArgumentException">The provided Symbol is not an Index Option</exception>
2056  [DocumentationAttribute(AddingData)]
2057  public Option AddIndexOptionContract(Symbol symbol, Resolution? resolution = null, bool fillForward = true)
2058  {
2059  if (symbol.SecurityType != SecurityType.IndexOption)
2060  {
2061  throw new ArgumentException("Symbol provided must be of type SecurityType.IndexOption");
2062  }
2063 
2064  return AddOptionContract(symbol, resolution, fillForward);
2065  }
2066 
2067  /// <summary>
2068  /// Creates and adds a new single <see cref="Option"/> contract to the algorithm
2069  /// </summary>
2070  /// <param name="symbol">The option contract symbol</param>
2071  /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
2072  /// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
2073  /// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
2074  /// <param name="extendedMarketHours">Use extended market hours data</param>
2075  /// <returns>The new <see cref="Option"/> security</returns>
2076  [DocumentationAttribute(AddingData)]
2077  public Option AddOptionContract(Symbol symbol, Resolution? resolution = null, bool fillForward = true,
2078  decimal leverage = Security.NullLeverage, bool extendedMarketHours = false)
2079  {
2080  if(symbol == null || !symbol.SecurityType.IsOption() || symbol.Underlying == null)
2081  {
2082  throw new ArgumentException($"Unexpected option symbol {symbol}. " +
2083  $"Please provide a valid option contract with it's underlying symbol set.");
2084  }
2085 
2086  // add underlying if not present
2087  var underlying = symbol.Underlying;
2088  Security underlyingSecurity;
2089  List<SubscriptionDataConfig> underlyingConfigs;
2090  if (!Securities.TryGetValue(underlying, out underlyingSecurity) || !underlyingSecurity.IsTradable)
2091  {
2092  underlyingSecurity = AddSecurity(underlying, resolution, fillForward, leverage, extendedMarketHours);
2094  .GetSubscriptionDataConfigs(underlying);
2095  }
2096  else
2097  {
2099  .GetSubscriptionDataConfigs(underlying);
2100 
2101  var dataNormalizationMode = underlyingConfigs.DataNormalizationMode();
2102  if (dataNormalizationMode != DataNormalizationMode.Raw && _locked)
2103  {
2104  // We check the "locked" flag here because during initialization we need to load existing open orders and holdings from brokerages.
2105  // There is no data streaming yet, so it is safe to change the data normalization mode to Raw.
2106  throw new ArgumentException($"The underlying {underlying.SecurityType} asset ({underlying.Value}) is set to " +
2107  $"{dataNormalizationMode}, please change this to DataNormalizationMode.Raw with the " +
2108  "SetDataNormalization() method"
2109  );
2110  }
2111  }
2112 
2113  var configs = SubscriptionManager.SubscriptionDataConfigService.Add(symbol, resolution, fillForward, extendedMarketHours,
2114  dataNormalizationMode: DataNormalizationMode.Raw);
2115  var option = (Option)Securities.CreateSecurity(symbol, configs, leverage, underlying: underlyingSecurity);
2116 
2117  underlyingConfigs.SetDataNormalizationMode(DataNormalizationMode.Raw);
2118  // For backward compatibility we need to refresh the security DataNormalizationMode Property
2119  underlyingSecurity.RefreshDataNormalizationModeProperty();
2120 
2121  Securities.Add(option);
2122 
2123  // get or create the universe
2124  var universeSymbol = OptionContractUniverse.CreateSymbol(symbol.ID.Market, symbol.Underlying.SecurityType);
2125  Universe universe;
2126  if (!UniverseManager.TryGetValue(universeSymbol, out universe))
2127  {
2128  var settings = new UniverseSettings(UniverseSettings) {
2130  Resolution = underlyingConfigs.GetHighestResolution(),
2131  ExtendedMarketHours = extendedMarketHours
2132  };
2133  lock (_pendingUniverseAdditionsLock)
2134  {
2135  universe = _pendingUniverseAdditions.FirstOrDefault(u => u.Configuration.Symbol == universeSymbol)
2136  ?? AddUniverse(new OptionContractUniverse(new SubscriptionDataConfig(configs.First(), symbol: universeSymbol), settings));
2137  }
2138  }
2139 
2140  // update the universe
2141  var optionUniverse = universe as OptionContractUniverse;
2142  if (optionUniverse != null)
2143  {
2144  foreach (var subscriptionDataConfig in configs.Concat(underlyingConfigs))
2145  {
2146  optionUniverse.Add(subscriptionDataConfig);
2147  }
2148  }
2149 
2150  return option;
2151  }
2152 
2153  /// <summary>
2154  /// Creates and adds a new <see cref="Forex"/> security to the algorithm
2155  /// </summary>
2156  /// <param name="ticker">The currency pair</param>
2157  /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
2158  /// <param name="market">The foreign exchange trading market, <seealso cref="Market"/>. Default value is null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
2159  /// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
2160  /// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
2161  /// <returns>The new <see cref="Forex"/> security</returns>
2162  [DocumentationAttribute(AddingData)]
2163  public Forex AddForex(string ticker, Resolution? resolution = null, string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
2164  {
2165  return AddSecurity<Forex>(SecurityType.Forex, ticker, resolution, market, fillForward, leverage, false);
2166  }
2167 
2168  /// <summary>
2169  /// Creates and adds a new <see cref="Cfd"/> security to the algorithm
2170  /// </summary>
2171  /// <param name="ticker">The currency pair</param>
2172  /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
2173  /// <param name="market">The cfd trading market, <seealso cref="Market"/>. Default value is null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
2174  /// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
2175  /// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
2176  /// <returns>The new <see cref="Cfd"/> security</returns>
2177  [DocumentationAttribute(AddingData)]
2178  public Cfd AddCfd(string ticker, Resolution? resolution = null, string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
2179  {
2180  return AddSecurity<Cfd>(SecurityType.Cfd, ticker, resolution, market, fillForward, leverage, false);
2181  }
2182 
2183 
2184  /// <summary>
2185  /// Creates and adds a new <see cref="Index"/> security to the algorithm
2186  /// </summary>
2187  /// <param name="ticker">The currency pair</param>
2188  /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
2189  /// <param name="market">The index trading market, <seealso cref="Market"/>. Default value is null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
2190  /// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
2191  /// <returns>The new <see cref="Index"/> security</returns>
2192  [DocumentationAttribute(AddingData)]
2193  public Index AddIndex(string ticker, Resolution? resolution = null, string market = null, bool fillForward = true)
2194  {
2195  var index = AddSecurity<Index>(SecurityType.Index, ticker, resolution, market, fillForward, 1, false);
2196  return index;
2197  }
2198 
2199  /// <summary>
2200  /// Creates and adds a new <see cref="Crypto"/> security to the algorithm
2201  /// </summary>
2202  /// <param name="ticker">The currency pair</param>
2203  /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
2204  /// <param name="market">The cfd trading market, <seealso cref="Market"/>. Default value is null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
2205  /// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
2206  /// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
2207  /// <returns>The new <see cref="Crypto"/> security</returns>
2208  [DocumentationAttribute(AddingData)]
2209  public Crypto AddCrypto(string ticker, Resolution? resolution = null, string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
2210  {
2211  return AddSecurity<Crypto>(SecurityType.Crypto, ticker, resolution, market, fillForward, leverage, false);
2212  }
2213 
2214  /// <summary>
2215  /// Creates and adds a new <see cref="CryptoFuture"/> security to the algorithm
2216  /// </summary>
2217  /// <param name="ticker">The currency pair</param>
2218  /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param>
2219  /// <param name="market">The cfd trading market, <seealso cref="Market"/>. Default value is null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param>
2220  /// <param name="fillForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param>
2221  /// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param>
2222  /// <returns>The new <see cref="CryptoFuture"/> security</returns>
2223  [DocumentationAttribute(AddingData)]
2224  public CryptoFuture AddCryptoFuture(string ticker, Resolution? resolution = null, string market = null, bool fillForward = true, decimal leverage = Security.NullLeverage)
2225  {
2226  return AddSecurity<CryptoFuture>(SecurityType.CryptoFuture, ticker, resolution, market, fillForward, leverage, false);
2227  }
2228 
2229  /// <summary>
2230  /// Removes the security with the specified symbol. This will cancel all
2231  /// open orders and then liquidate any existing holdings
2232  /// </summary>
2233  /// <param name="symbol">The symbol of the security to be removed</param>
2234  /// <remarks>Sugar syntax for <see cref="AddOptionContract"/></remarks>
2235  [DocumentationAttribute(AddingData)]
2236  public bool RemoveOptionContract(Symbol symbol)
2237  {
2238  return RemoveSecurity(symbol);
2239  }
2240 
2241  /// <summary>
2242  /// Removes the security with the specified symbol. This will cancel all
2243  /// open orders and then liquidate any existing holdings
2244  /// </summary>
2245  /// <param name="symbol">The symbol of the security to be removed</param>
2246  [DocumentationAttribute(AddingData)]
2247  public bool RemoveSecurity(Symbol symbol)
2248  {
2249  Security security;
2250  if (!Securities.TryGetValue(symbol, out security))
2251  {
2252  return false;
2253  }
2254 
2255  if (!IsWarmingUp)
2256  {
2257  // cancel open orders
2258  Transactions.CancelOpenOrders(security.Symbol);
2259  }
2260 
2261  // liquidate if invested
2262  if (security.Invested)
2263  {
2264  Liquidate(security.Symbol);
2265  }
2266 
2267  // Clear cache
2268  security.Cache.Reset();
2269 
2270  // Mark security as not tradable
2271  security.IsTradable = false;
2272  if (symbol.IsCanonical())
2273  {
2274  // remove underlying equity data if it's marked as internal
2275  foreach (var kvp in UniverseManager.Where(x => x.Value.Configuration.Symbol == symbol
2276  || x.Value.Configuration.Symbol == ContinuousContractUniverse.CreateSymbol(symbol)))
2277  {
2278  var universe = kvp.Value;
2279  // remove underlying if not used by other universes
2280  var otherUniverses = UniverseManager.Select(ukvp => ukvp.Value).Where(u => !ReferenceEquals(u, universe)).ToList();
2281  if (symbol.HasUnderlying)
2282  {
2283  var underlying = Securities[symbol.Underlying];
2284  if (!otherUniverses.Any(u => u.Members.ContainsKey(underlying.Symbol)))
2285  {
2286  RemoveSecurity(underlying.Symbol);
2287  }
2288  }
2289 
2290  // remove child securities (option contracts for option chain universes) if not used in other universes
2291  // we order the securities so that the removal is deterministic, it will liquidate any holdings
2292  foreach (var child in universe.Members.Values.OrderBy(security1 => security1.Symbol))
2293  {
2294  if (!otherUniverses.Any(u => u.Members.ContainsKey(child.Symbol)) && !child.Symbol.IsCanonical())
2295  {
2296  RemoveSecurity(child.Symbol);
2297  }
2298  }
2299 
2300  // finally, dispose and remove the canonical security from the universe manager
2301  UniverseManager.Remove(kvp.Key);
2302  _userAddedUniverses.Remove(kvp.Key);
2303  }
2304  }
2305  else
2306  {
2307  lock (_pendingUniverseAdditionsLock)
2308  {
2309  // we need to handle existing universes and pending to be added universes, that will be pushed
2310  // at the end of this time step see OnEndOfTimeStep()
2311  foreach (var universe in UniverseManager.Select(x => x.Value)
2312  .Concat(_pendingUniverseAdditions)
2313  .OfType<UserDefinedUniverse>())
2314  {
2315  universe.Remove(symbol);
2316  }
2317  // for existing universes we need to purge pending additions too, also handled at OnEndOfTimeStep()
2318  _pendingUserDefinedUniverseSecurityAdditions.RemoveAll(addition => addition.Security.Symbol == symbol);
2319  }
2320  }
2321 
2322  return true;
2323  }
2324 
2325  /// <summary>
2326  /// AddData<typeparam name="T"/> a new user defined data source, requiring only the minimum config options.
2327  /// The data is added with a default time zone of NewYork (Eastern Daylight Savings Time)
2328  /// </summary>
2329  /// <param name="ticker">Key/Ticker for data</param>
2330  /// <param name="resolution">Resolution of the data</param>
2331  /// <returns>The new <see cref="Security"/></returns>
2332  /// <remarks>Generic type T must implement base data</remarks>
2333  [DocumentationAttribute(AddingData)]
2334  public Security AddData<T>(string ticker, Resolution? resolution = null)
2335  where T : IBaseData, new()
2336  {
2337  //Add this new generic data as a tradeable security:
2338  // Defaults:extended market hours" = true because we want events 24 hours,
2339  // fillforward = false because only want to trigger when there's new custom data.
2340  // leverage = 1 because no leverage on nonmarket data?
2341  return AddData<T>(ticker, resolution, fillForward: false, leverage: 1m);
2342  }
2343 
2344  /// <summary>
2345  /// AddData<typeparam name="T"/> a new user defined data source, requiring only the minimum config options.
2346  /// The data is added with a default time zone of NewYork (Eastern Daylight Savings Time)
2347  /// </summary>
2348  /// <param name="underlying">The underlying symbol for the custom data</param>
2349  /// <param name="resolution">Resolution of the data</param>
2350  /// <returns>The new <see cref="Security"/></returns>
2351  /// <remarks>Generic type T must implement base data</remarks>
2352  [DocumentationAttribute(AddingData)]
2353  public Security AddData<T>(Symbol underlying, Resolution? resolution = null)
2354  where T : IBaseData, new()
2355  {
2356  //Add this new generic data as a tradeable security:
2357  // Defaults:extended market hours" = true because we want events 24 hours,
2358  // fillforward = false because only want to trigger when there's new custom data.
2359  // leverage = 1 because no leverage on nonmarket data?
2360  return AddData<T>(underlying, resolution, fillForward: false, leverage: 1m);
2361  }
2362 
2363 
2364  /// <summary>
2365  /// AddData<typeparam name="T"/> a new user defined data source, requiring only the minimum config options.
2366  /// The data is added with a default time zone of NewYork (Eastern Daylight Savings Time)
2367  /// </summary>
2368  /// <param name="ticker">Key/Ticker for data</param>
2369  /// <param name="resolution">Resolution of the Data Required</param>
2370  /// <param name="fillForward">When no data available on a tradebar, return the last data that was generated</param>
2371  /// <param name="leverage">Custom leverage per security</param>
2372  /// <returns>The new <see cref="Security"/></returns>
2373  /// <remarks>Generic type T must implement base data</remarks>
2374  [DocumentationAttribute(AddingData)]
2375  public Security AddData<T>(string ticker, Resolution? resolution, bool fillForward, decimal leverage = 1.0m)
2376  where T : IBaseData, new()
2377  {
2378  return AddData<T>(ticker, resolution, null, fillForward, leverage);
2379  }
2380 
2381  /// <summary>
2382  /// AddData<typeparam name="T"/> a new user defined data source, requiring only the minimum config options.
2383  /// The data is added with a default time zone of NewYork (Eastern Daylight Savings Time)
2384  /// </summary>
2385  /// <param name="underlying">The underlying symbol for the custom data</param>
2386  /// <param name="resolution">Resolution of the Data Required</param>
2387  /// <param name="fillForward">When no data available on a tradebar, return the last data that was generated</param>
2388  /// <param name="leverage">Custom leverage per security</param>
2389  /// <returns>The new <see cref="Security"/></returns>
2390  /// <remarks>Generic type T must implement base data</remarks>
2391  [DocumentationAttribute(AddingData)]
2392  public Security AddData<T>(Symbol underlying, Resolution? resolution, bool fillForward, decimal leverage = 1.0m)
2393  where T : IBaseData, new()
2394  {
2395  return AddData<T>(underlying, resolution, null, fillForward, leverage);
2396  }
2397 
2398  /// <summary>
2399  /// AddData<typeparam name="T"/> a new user defined data source, requiring only the minimum config options.
2400  /// </summary>
2401  /// <param name="ticker">Key/Ticker for data</param>
2402  /// <param name="resolution">Resolution of the Data Required</param>
2403  /// <param name="timeZone">Specifies the time zone of the raw data</param>
2404  /// <param name="fillForward">When no data available on a tradebar, return the last data that was generated</param>
2405  /// <param name="leverage">Custom leverage per security</param>
2406  /// <returns>The new <see cref="Security"/></returns>
2407  /// <remarks>Generic type T must implement base data</remarks>
2408  [DocumentationAttribute(AddingData)]
2409  public Security AddData<T>(string ticker, Resolution? resolution, DateTimeZone timeZone, bool fillForward = false, decimal leverage = 1.0m)
2410  where T : IBaseData, new()
2411  {
2412  return AddData(typeof(T), ticker, resolution, timeZone, fillForward, leverage);
2413  }
2414 
2415  /// <summary>
2416  /// AddData<typeparam name="T"/> a new user defined data source, requiring only the minimum config options.
2417  /// </summary>
2418  /// <param name="underlying">The underlying symbol for the custom data</param>
2419  /// <param name="resolution">Resolution of the Data Required</param>
2420  /// <param name="timeZone">Specifies the time zone of the raw data</param>
2421  /// <param name="fillForward">When no data available on a tradebar, return the last data that was generated</param>
2422  /// <param name="leverage">Custom leverage per security</param>
2423  /// <returns>The new <see cref="Security"/></returns>
2424  /// <remarks>Generic type T must implement base data</remarks>
2425  [DocumentationAttribute(AddingData)]
2426  public Security AddData<T>(Symbol underlying, Resolution? resolution, DateTimeZone timeZone, bool fillForward = false, decimal leverage = 1.0m)
2427  where T : IBaseData, new()
2428  {
2429  return AddData(typeof(T), underlying, resolution, timeZone, fillForward, leverage);
2430  }
2431 
2432  /// <summary>
2433  /// AddData<typeparam name="T"/> a new user defined data source including symbol properties and exchange hours,
2434  /// all other vars are not required and will use defaults.
2435  /// </summary>
2436  /// <param name="ticker">Key/Ticker for data</param>
2437  /// <param name="properties">The properties of this new custom data</param>
2438  /// <param name="exchangeHours">The Exchange hours of this symbol</param>
2439  /// <param name="resolution">Resolution of the Data Required</param>
2440  /// <param name="fillForward">When no data available on a tradebar, return the last data that was generated</param>
2441  /// <param name="leverage">Custom leverage per security</param>
2442  /// <returns>The new <see cref="Security"/></returns>
2443  [DocumentationAttribute(AddingData)]
2444  public Security AddData<T>(string ticker, SymbolProperties properties, SecurityExchangeHours exchangeHours, Resolution? resolution = null, bool fillForward = false, decimal leverage = 1.0m)
2445  where T : IBaseData, new()
2446  {
2447  // Get the right key for storage of base type symbols
2448  var key = SecurityIdentifier.GenerateBaseSymbol(typeof(T), ticker);
2449 
2450  // Set our database entries for this data type
2451  SetDatabaseEntries(key, properties, exchangeHours);
2452 
2453  // Then add the data
2454  return AddData(typeof(T), ticker, resolution, null, fillForward, leverage);
2455  }
2456 
2457  /// <summary>
2458  /// Send a debug message to the web console:
2459  /// </summary>
2460  /// <param name="message">Message to send to debug console</param>
2461  /// <seealso cref="Log(string)"/>
2462  /// <seealso cref="Error(string)"/>
2463  [DocumentationAttribute(Logging)]
2464  public void Debug(string message)
2465  {
2466  if (!_liveMode && (message == "" || _previousDebugMessage == message)) return;
2467  _debugMessages.Enqueue(message);
2468  _previousDebugMessage = message;
2469  }
2470 
2471  /// <summary>
2472  /// Send a debug message to the web console:
2473  /// </summary>
2474  /// <param name="message">Message to send to debug console</param>
2475  /// <seealso cref="Log(int)"/>
2476  /// <seealso cref="Error(int)"/>
2477  [DocumentationAttribute(Logging)]
2478  public void Debug(int message)
2479  {
2480  Debug(message.ToStringInvariant());
2481  }
2482 
2483  /// <summary>
2484  /// Send a debug message to the web console:
2485  /// </summary>
2486  /// <param name="message">Message to send to debug console</param>
2487  /// <seealso cref="Log(double)"/>
2488  /// <seealso cref="Error(double)"/>
2489  [DocumentationAttribute(Logging)]
2490  public void Debug(double message)
2491  {
2492  Debug(message.ToStringInvariant());
2493  }
2494 
2495  /// <summary>
2496  /// Send a debug message to the web console:
2497  /// </summary>
2498  /// <param name="message">Message to send to debug console</param>
2499  /// <seealso cref="Log(decimal)"/>
2500  /// <seealso cref="Error(decimal)"/>
2501  [DocumentationAttribute(Logging)]
2502  public void Debug(decimal message)
2503  {
2504  Debug(message.ToStringInvariant());
2505  }
2506 
2507  /// <summary>
2508  /// Added another method for logging if user guessed.
2509  /// </summary>
2510  /// <param name="message">String message to log.</param>
2511  /// <seealso cref="Debug(string)"/>
2512  /// <seealso cref="Error(string)"/>
2513  [DocumentationAttribute(Logging)]
2514  public void Log(string message)
2515  {
2516  if (!_liveMode && message == "") return;
2517  _logMessages.Enqueue(message);
2518  }
2519 
2520  /// <summary>
2521  /// Added another method for logging if user guessed.
2522  /// </summary>
2523  /// <param name="message">Int message to log.</param>
2524  /// <seealso cref="Debug(int)"/>
2525  /// <seealso cref="Error(int)"/>
2526  [DocumentationAttribute(Logging)]
2527  public void Log(int message)
2528  {
2529  Log(message.ToStringInvariant());
2530  }
2531 
2532  /// <summary>
2533  /// Added another method for logging if user guessed.
2534  /// </summary>
2535  /// <param name="message">Double message to log.</param>
2536  /// <seealso cref="Debug(double)"/>
2537  /// <seealso cref="Error(double)"/>
2538  [DocumentationAttribute(Logging)]
2539  public void Log(double message)
2540  {
2541  Log(message.ToStringInvariant());
2542  }
2543 
2544  /// <summary>
2545  /// Added another method for logging if user guessed.
2546  /// </summary>
2547  /// <param name="message">Decimal message to log.</param>
2548  /// <seealso cref="Debug(decimal)"/>
2549  /// <seealso cref="Error(decimal)"/>
2550  [DocumentationAttribute(Logging)]
2551  public void Log(decimal message)
2552  {
2553  Log(message.ToStringInvariant());
2554  }
2555 
2556  /// <summary>
2557  /// Send a string error message to the Console.
2558  /// </summary>
2559  /// <param name="message">Message to display in errors grid</param>
2560  /// <seealso cref="Debug(string)"/>
2561  /// <seealso cref="Log(string)"/>
2562  [DocumentationAttribute(Logging)]
2563  public void Error(string message)
2564  {
2565  if (!_liveMode && (message == "" || _previousErrorMessage == message)) return;
2566  _errorMessages.Enqueue(message);
2567  _previousErrorMessage = message;
2568  }
2569 
2570  /// <summary>
2571  /// Send a int error message to the Console.
2572  /// </summary>
2573  /// <param name="message">Message to display in errors grid</param>
2574  /// <seealso cref="Debug(int)"/>
2575  /// <seealso cref="Log(int)"/>
2576  [DocumentationAttribute(Logging)]
2577  public void Error(int message)
2578  {
2579  Error(message.ToStringInvariant());
2580  }
2581 
2582  /// <summary>
2583  /// Send a double error message to the Console.
2584  /// </summary>
2585  /// <param name="message">Message to display in errors grid</param>
2586  /// <seealso cref="Debug(double)"/>
2587  /// <seealso cref="Log(double)"/>
2588  [DocumentationAttribute(Logging)]
2589  public void Error(double message)
2590  {
2591  Error(message.ToStringInvariant());
2592  }
2593 
2594  /// <summary>
2595  /// Send a decimal error message to the Console.
2596  /// </summary>
2597  /// <param name="message">Message to display in errors grid</param>
2598  /// <seealso cref="Debug(decimal)"/>
2599  /// <seealso cref="Log(decimal)"/>
2600  [DocumentationAttribute(Logging)]
2601  public void Error(decimal message)
2602  {
2603  Error(message.ToStringInvariant());
2604  }
2605 
2606  /// <summary>
2607  /// Send a string error message to the Console.
2608  /// </summary>
2609  /// <param name="error">Exception object captured from a try catch loop</param>
2610  /// <seealso cref="Debug(string)"/>
2611  /// <seealso cref="Log(string)"/>
2612  [DocumentationAttribute(Logging)]
2613  public void Error(Exception error)
2614  {
2615  var message = error.Message;
2616  if (!_liveMode && (message == "" || _previousErrorMessage == message)) return;
2617  _errorMessages.Enqueue(message);
2618  _previousErrorMessage = message;
2619  }
2620 
2621  /// <summary>
2622  /// Terminate the algorithm after processing the current event handler.
2623  /// </summary>
2624  /// <param name="message">Exit message to display on quitting</param>
2625  [DocumentationAttribute(Logging)]
2626  public void Quit(string message = "")
2627  {
2628  Debug("Quit(): " + message);
2629  Status = AlgorithmStatus.Stopped;
2630  }
2631 
2632  /// <summary>
2633  /// Set the Quit flag property of the algorithm.
2634  /// </summary>
2635  /// <remarks>Intended for internal use by the QuantConnect Lean Engine only.</remarks>
2636  /// <param name="quit">Boolean quit state</param>
2637  /// <seealso cref="Quit(String)"/>
2638  [DocumentationAttribute(Logging)]
2639  public void SetQuit(bool quit)
2640  {
2641  if (quit)
2642  {
2643  Status = AlgorithmStatus.Stopped;
2644  }
2645  }
2646 
2647  /// <summary>
2648  /// Converts the string 'ticker' symbol into a full <see cref="Symbol"/> object
2649  /// This requires that the string 'ticker' has been added to the algorithm
2650  /// </summary>
2651  /// <param name="ticker">The ticker symbol. This should be the ticker symbol
2652  /// as it was added to the algorithm</param>
2653  /// <returns>The symbol object mapped to the specified ticker</returns>
2654  [DocumentationAttribute(AddingData)]
2655  [DocumentationAttribute(HandlingData)]
2656  public Symbol Symbol(string ticker)
2657  {
2658  return SymbolCache.GetSymbol(ticker);
2659  }
2660 
2661  /// <summary>
2662  /// For the given symbol will resolve the ticker it used at the current algorithm date
2663  /// </summary>
2664  /// <param name="symbol">The symbol to get the ticker for</param>
2665  /// <returns>The mapped ticker for a symbol</returns>
2666  [DocumentationAttribute(AddingData)]
2667  [DocumentationAttribute(HandlingData)]
2668  public string Ticker(Symbol symbol)
2669  {
2670  return SecurityIdentifier.Ticker(symbol, Time);
2671  }
2672 
2673  /// <summary>
2674  /// Creates and adds a new <see cref="Security"/> to the algorithm
2675  /// </summary>
2676  [DocumentationAttribute(AddingData)]
2677  private T AddSecurity<T>(SecurityType securityType, string ticker, Resolution? resolution, string market, bool fillForward, decimal leverage, bool extendedMarketHours,
2678  DataMappingMode? mappingMode = null, DataNormalizationMode? normalizationMode = null)
2679  where T : Security
2680  {
2681  if (market == null)
2682  {
2683  if (!BrokerageModel.DefaultMarkets.TryGetValue(securityType, out market))
2684  {
2685  throw new Exception("No default market set for security type: " + securityType);
2686  }
2687  }
2688 
2689  Symbol symbol;
2690  if (!SymbolCache.TryGetSymbol(ticker, out symbol) ||
2691  symbol.ID.Market != market ||
2692  symbol.SecurityType != securityType)
2693  {
2694  symbol = QuantConnect.Symbol.Create(ticker, securityType, market);
2695  }
2696 
2697  var configs = SubscriptionManager.SubscriptionDataConfigService.Add(symbol, resolution, fillForward, extendedMarketHours,
2698  dataNormalizationMode: normalizationMode ?? UniverseSettings.DataNormalizationMode,
2699  dataMappingMode: mappingMode ?? UniverseSettings.DataMappingMode);
2700  var security = Securities.CreateSecurity(symbol, configs, leverage);
2701 
2702  return (T) AddToUserDefinedUniverse(security, configs);
2703  }
2704 
2705  /// <summary>
2706  /// Set the historical data provider
2707  /// </summary>
2708  /// <param name="historyProvider">Historical data provider</param>
2709  [DocumentationAttribute(HistoricalData)]
2710  public void SetHistoryProvider(IHistoryProvider historyProvider)
2711  {
2712  if (historyProvider == null)
2713  {
2714  throw new ArgumentNullException(nameof(historyProvider), "Algorithm.SetHistoryProvider(): Historical data provider cannot be null.");
2715  }
2716  HistoryProvider = historyProvider;
2717  }
2718 
2719  /// <summary>
2720  /// Set the runtime error
2721  /// </summary>
2722  /// <param name="exception">Represents error that occur during execution</param>
2723  [DocumentationAttribute(HandlingData)]
2724  [DocumentationAttribute(LiveTrading)]
2725  public void SetRunTimeError(Exception exception)
2726  {
2727  if (exception == null)
2728  {
2729  throw new ArgumentNullException(nameof(exception), "Algorithm.SetRunTimeError(): Algorithm.RunTimeError cannot be set to null.");
2730  }
2731 
2732  RunTimeError = exception;
2733  }
2734 
2735  /// <summary>
2736  /// Set the state of a live deployment
2737  /// </summary>
2738  /// <param name="status">Live deployment status</param>
2739  [DocumentationAttribute(LiveTrading)]
2740  public void SetStatus(AlgorithmStatus status)
2741  {
2742  Status = status;
2743  }
2744 
2745  /// <summary>
2746  /// Downloads the requested resource as a <see cref="string"/>.
2747  /// The resource to download is specified as a <see cref="string"/> containing the URI.
2748  /// </summary>
2749  /// <param name="address">A string containing the URI to download</param>
2750  /// <returns>The requested resource as a <see cref="string"/></returns>
2751  [DocumentationAttribute(AddingData)]
2752  [DocumentationAttribute(MachineLearning)]
2753  public string Download(string address) => Download(address, Enumerable.Empty<KeyValuePair<string, string>>());
2754 
2755  /// <summary>
2756  /// Downloads the requested resource as a <see cref="string"/>.
2757  /// The resource to download is specified as a <see cref="string"/> containing the URI.
2758  /// </summary>
2759  /// <param name="address">A string containing the URI to download</param>
2760  /// <param name="headers">Defines header values to add to the request</param>
2761  /// <returns>The requested resource as a <see cref="string"/></returns>
2762  [DocumentationAttribute(AddingData)]
2763  [DocumentationAttribute(MachineLearning)]
2764  public string Download(string address, IEnumerable<KeyValuePair<string, string>> headers) => Download(address, headers, null, null);
2765 
2766  /// <summary>
2767  /// Downloads the requested resource as a <see cref="string"/>.
2768  /// The resource to download is specified as a <see cref="string"/> containing the URI.
2769  /// </summary>
2770  /// <param name="address">A string containing the URI to download</param>
2771  /// <param name="headers">Defines header values to add to the request</param>
2772  /// <param name="userName">The user name associated with the credentials</param>
2773  /// <param name="password">The password for the user name associated with the credentials</param>
2774  /// <returns>The requested resource as a <see cref="string"/></returns>
2775  [DocumentationAttribute(AddingData)]
2776  [DocumentationAttribute(MachineLearning)]
2777  public string Download(string address, IEnumerable<KeyValuePair<string, string>> headers, string userName, string password)
2778  {
2779  return _api.Download(address, headers, userName, password);
2780  }
2781 
2782  /// <summary>
2783  /// Schedules the provided training code to execute immediately
2784  /// </summary>
2785  /// <param name="trainingCode">The training code to be invoked</param>
2786  [DocumentationAttribute(MachineLearning)]
2787  [DocumentationAttribute(ScheduledEvents)]
2788  public ScheduledEvent Train(Action trainingCode)
2789  {
2790  return Schedule.TrainingNow(trainingCode);
2791  }
2792 
2793  /// <summary>
2794  /// Schedules the training code to run using the specified date and time rules
2795  /// </summary>
2796  /// <param name="dateRule">Specifies what dates the event should run</param>
2797  /// <param name="timeRule">Specifies the times on those dates the event should run</param>
2798  /// <param name="trainingCode">The training code to be invoked</param>
2799  [DocumentationAttribute(MachineLearning)]
2800  [DocumentationAttribute(ScheduledEvents)]
2801  public ScheduledEvent Train(IDateRule dateRule, ITimeRule timeRule, Action trainingCode)
2802  {
2803  return Schedule.Training(dateRule, timeRule, trainingCode);
2804  }
2805 
2806  /// <summary>
2807  /// Event invocator for the <see cref="InsightsGenerated"/> event
2808  /// </summary>
2809  /// <param name="insights">The collection of insights generaed at the current time step</param>
2810  /// <param name="clone">Will emit a clone of the generated insights</param>
2811  [DocumentationAttribute(AlgorithmFramework)]
2812  private void OnInsightsGenerated(Insight[] insights)
2813  {
2814  // debug printing of generated insights
2815  if (DebugMode)
2816  {
2817  Log($"{Time}: ALPHA: {string.Join(" | ", insights.Select(i => i.ToString()).OrderBy(i => i))}");
2818  }
2819 
2820  Insights.AddRange(insights);
2821 
2822  InsightsGenerated?.Invoke(this, new GeneratedInsightsCollection(UtcTime, insights));
2823  }
2824 
2825  /// <summary>
2826  /// Sets the current slice
2827  /// </summary>
2828  /// <param name="slice">The Slice object</param>
2829  [DocumentationAttribute(HandlingData)]
2830  public void SetCurrentSlice(Slice slice)
2831  {
2832  CurrentSlice = slice;
2833  }
2834 
2835 
2836  /// <summary>
2837  /// Provide the API for the algorithm.
2838  /// </summary>
2839  /// <param name="api">Initiated API</param>
2840  [DocumentationAttribute(HandlingData)]
2841  public void SetApi(IApi api)
2842  {
2843  _api = api;
2844  }
2845 
2846  /// <summary>
2847  /// Sets the object store
2848  /// </summary>
2849  /// <param name="objectStore">The object store</param>
2850  [DocumentationAttribute(HandlingData)]
2851  [DocumentationAttribute(MachineLearning)]
2852  public void SetObjectStore(IObjectStore objectStore)
2853  {
2854  ObjectStore = new ObjectStore(objectStore);
2855  }
2856 
2857  /// <summary>
2858  /// Determines if the Symbol is shortable at the brokerage
2859  /// </summary>
2860  /// <param name="symbol">Symbol to check if shortable</param>
2861  /// <returns>True if shortable</returns>
2862  [DocumentationAttribute(TradingAndOrders)]
2863  public bool Shortable(Symbol symbol)
2864  {
2865  return Shortable(symbol, 0);
2866  }
2867 
2868  /// <summary>
2869  /// Determines if the Symbol is shortable at the brokerage
2870  /// </summary>
2871  /// <param name="symbol">Symbol to check if shortable</param>
2872  /// <param name="shortQuantity">Order's quantity to check if it is currently shortable, taking into account current holdings and open orders</param>
2873  /// <returns>True if shortable</returns>
2874  [DocumentationAttribute(TradingAndOrders)]
2875  public bool Shortable(Symbol symbol, decimal shortQuantity)
2876  {
2877  var shortableQuantity = Securities[symbol].ShortableProvider.ShortableQuantity(symbol, Time);
2878  if (shortableQuantity == null)
2879  {
2880  return true;
2881  }
2882 
2883  var openOrderQuantity = Transactions.GetOpenOrdersRemainingQuantity(symbol);
2884  var portfolioQuantity = Portfolio.ContainsKey(symbol) ? Portfolio[symbol].Quantity : 0;
2885  // We check portfolio and open orders beforehand to ensure that orderQuantity == 0 case does not return
2886  // a true result whenever we have no more shares left to short.
2887  if (portfolioQuantity + openOrderQuantity <= -shortableQuantity)
2888  {
2889  return false;
2890  }
2891 
2892  shortQuantity = -Math.Abs(shortQuantity);
2893  return portfolioQuantity + shortQuantity + openOrderQuantity >= -shortableQuantity;
2894  }
2895 
2896  /// <summary>
2897  /// Gets the quantity shortable for the given asset
2898  /// </summary>
2899  /// <returns>
2900  /// Quantity shortable for the given asset. Zero if not
2901  /// shortable, or a number greater than zero if shortable.
2902  /// </returns>
2903  [DocumentationAttribute(TradingAndOrders)]
2904  public long ShortableQuantity(Symbol symbol)
2905  {
2906  return Securities[symbol].ShortableProvider.ShortableQuantity(symbol, Time) ?? 0;
2907  }
2908 
2909  /// <summary>
2910  /// Converts an ISIN identifier into a <see cref="Symbol"/>
2911  /// </summary>
2912  /// <param name="isin">The International Securities Identification Number (ISIN) of an asset</param>
2913  /// <param name="tradingDate">
2914  /// The date that the stock being looked up is/was traded at.
2915  /// The date is used to create a Symbol with the ticker set to the ticker the asset traded under on the trading date.
2916  /// </param>
2917  /// <returns>Symbol corresponding to the ISIN. If no Symbol with a matching ISIN was found, returns null.</returns>
2918  [DocumentationAttribute(HandlingData)]
2919  [DocumentationAttribute(SecuritiesAndPortfolio)]
2920  public Symbol ISIN(string isin, DateTime? tradingDate = null)
2921  {
2922  return _securityDefinitionSymbolResolver.ISIN(isin, GetVerifiedTradingDate(tradingDate));
2923  }
2924 
2925  /// <summary>
2926  /// Converts a <see cref="Symbol"/> into an ISIN identifier
2927  /// </summary>
2928  /// <param name="symbol">The <see cref="Symbol"/></param>
2929  /// <returns>ISIN corresponding to the Symbol. If no matching ISIN is found, returns null.</returns>
2930  [DocumentationAttribute(HandlingData)]
2931  [DocumentationAttribute(SecuritiesAndPortfolio)]
2932  public string ISIN(Symbol symbol)
2933  {
2934  return _securityDefinitionSymbolResolver.ISIN(symbol);
2935  }
2936 
2937  /// <summary>
2938  /// Converts a composite FIGI identifier into a <see cref="Symbol"/>
2939  /// </summary>
2940  /// <param name="compositeFigi">The composite Financial Instrument Global Identifier (FIGI) of an asset</param>
2941  /// <param name="tradingDate">
2942  /// The date that the stock being looked up is/was traded at.
2943  /// The date is used to create a Symbol with the ticker set to the ticker the asset traded under on the trading date.
2944  /// </param>
2945  /// <returns>Symbol corresponding to the composite FIGI. If no Symbol with a matching composite FIGI was found, returns null.</returns>
2946  /// <remarks>
2947  /// The composite FIGI differs from an exchange-level FIGI, in that it identifies
2948  /// an asset across all exchanges in a single country that the asset trades in.
2949  /// </remarks>
2950  [DocumentationAttribute(HandlingData)]
2951  [DocumentationAttribute(SecuritiesAndPortfolio)]
2952  public Symbol CompositeFIGI(string compositeFigi, DateTime? tradingDate = null)
2953  {
2954  return _securityDefinitionSymbolResolver.CompositeFIGI(compositeFigi, GetVerifiedTradingDate(tradingDate));
2955  }
2956 
2957  /// <summary>
2958  /// Converts a <see cref="Symbol"/> into a composite FIGI identifier
2959  /// </summary>
2960  /// <param name="symbol">The <see cref="Symbol"/></param>
2961  /// <returns>Composite FIGI corresponding to the Symbol. If no matching composite FIGI is found, returns null.</returns>
2962  [DocumentationAttribute(HandlingData)]
2963  [DocumentationAttribute(SecuritiesAndPortfolio)]
2964  public string CompositeFIGI(Symbol symbol)
2965  {
2966  return _securityDefinitionSymbolResolver.CompositeFIGI(symbol);
2967  }
2968 
2969  /// <summary>
2970  /// Converts a CUSIP identifier into a <see cref="Symbol"/>
2971  /// </summary>
2972  /// <param name="cusip">The CUSIP number of an asset</param>
2973  /// <param name="tradingDate">
2974  /// The date that the stock being looked up is/was traded at.
2975  /// The date is used to create a Symbol with the ticker set to the ticker the asset traded under on the trading date.
2976  /// </param>
2977  /// <returns>Symbol corresponding to the CUSIP. If no Symbol with a matching CUSIP was found, returns null.</returns>
2978  [DocumentationAttribute(HandlingData)]
2979  [DocumentationAttribute(SecuritiesAndPortfolio)]
2980  public Symbol CUSIP(string cusip, DateTime? tradingDate = null)
2981  {
2982  return _securityDefinitionSymbolResolver.CUSIP(cusip, GetVerifiedTradingDate(tradingDate));
2983  }
2984 
2985  /// <summary>
2986  /// Converts a <see cref="Symbol"/> into a CUSIP identifier
2987  /// </summary>
2988  /// <param name="symbol">The <see cref="Symbol"/></param>
2989  /// <returns>CUSIP corresponding to the Symbol. If no matching CUSIP is found, returns null.</returns>
2990  [DocumentationAttribute(HandlingData)]
2991  [DocumentationAttribute(SecuritiesAndPortfolio)]
2992  public string CUSIP(Symbol symbol)
2993  {
2994  return _securityDefinitionSymbolResolver.CUSIP(symbol);
2995  }
2996 
2997  /// <summary>
2998  /// Converts a SEDOL identifier into a <see cref="Symbol"/>
2999  /// </summary>
3000  /// <param name="sedol">The SEDOL identifier of an asset</param>
3001  /// <param name="tradingDate">
3002  /// The date that the stock being looked up is/was traded at.
3003  /// The date is used to create a Symbol with the ticker set to the ticker the asset traded under on the trading date.
3004  /// </param>
3005  /// <returns>Symbol corresponding to the SEDOL. If no Symbol with a matching SEDOL was found, returns null.</returns>
3006  [DocumentationAttribute(HandlingData)]
3007  [DocumentationAttribute(SecuritiesAndPortfolio)]
3008  public Symbol SEDOL(string sedol, DateTime? tradingDate = null)
3009  {
3010  return _securityDefinitionSymbolResolver.SEDOL(sedol, GetVerifiedTradingDate(tradingDate));
3011  }
3012 
3013  /// <summary>
3014  /// Converts a <see cref="Symbol"/> into a SEDOL identifier
3015  /// </summary>
3016  /// <param name="symbol">The <see cref="Symbol"/></param>
3017  /// <returns>SEDOL corresponding to the Symbol. If no matching SEDOL is found, returns null.</returns>
3018  [DocumentationAttribute(HandlingData)]
3019  [DocumentationAttribute(SecuritiesAndPortfolio)]
3020  public string SEDOL(Symbol symbol)
3021  {
3022  return _securityDefinitionSymbolResolver.SEDOL(symbol);
3023  }
3024 
3025  /// <summary>
3026  /// Set the properties and exchange hours for a given key into our databases
3027  /// </summary>
3028  /// <param name="key">Key for database storage</param>
3029  /// <param name="properties">Properties to store</param>
3030  /// <param name="exchangeHours">Exchange hours to store</param>
3031  private void SetDatabaseEntries(string key, SymbolProperties properties, SecurityExchangeHours exchangeHours)
3032  {
3033  // Add entries to our Symbol Properties DB and MarketHours DB
3034  SymbolPropertiesDatabase.SetEntry(Market.USA, key, SecurityType.Base, properties);
3035  MarketHoursDatabase.SetEntry(Market.USA, key, SecurityType.Base, exchangeHours);
3036  }
3037 
3038  /// <summary>
3039  /// Takes a date, and verifies that it is point-in-time. If null
3040  /// time is provided, algorithm time is returned instead.
3041  /// </summary>
3042  /// <param name="tradingDate">
3043  /// The trading date to verify that it is a point-in-time
3044  /// date, or before, relative to the algorithm's current trading date.
3045  /// </param>
3046  /// <returns>The date provided if not null, otherwise the algorithm's current trading date</returns>
3047  /// <exception cref="ArgumentException">
3048  /// The trading date provided is not null and it is after the algorithm's current trading date
3049  /// </exception>
3050  private DateTime GetVerifiedTradingDate(DateTime? tradingDate)
3051  {
3052  tradingDate ??= Time.Date;
3053  if (tradingDate > Time.Date)
3054  {
3055  throw new ArgumentException($"The trading date provided: \"{tradingDate:yyyy-MM-dd}\" is after the current algorithm's trading date: \"{Time:yyyy-MM-dd}\"");
3056  }
3057 
3058  return tradingDate.Value;
3059  }
3060 
3061  /// <summary>
3062  /// Helper method to set the start date during live trading
3063  /// </summary>
3064  private void SetLiveModeStartDate()
3065  {
3066  if (!LiveMode)
3067  {
3068  throw new InvalidOperationException("SetLiveModeStartDate should only be called during live trading!");
3069  }
3070  _start = DateTime.UtcNow.ConvertFromUtc(TimeZone);
3071  // startDate is set relative to the algorithm's timezone.
3072  _startDate = _start.Date;
3073  _endDate = QuantConnect.Time.EndOfTime;
3074  }
3075 
3076  /// <summary>
3077  /// Check if a symbol is already pending to be added
3078  /// </summary>
3079  private bool IsAlreadyPending(Symbol symbol)
3080  {
3081  lock (_pendingUniverseAdditionsLock)
3082  {
3083  return _pendingUniverseAdditions.Any(u => u.Configuration.Symbol == symbol);
3084  }
3085  }
3086  }
3087 }