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