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