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