Lean  $LEAN_TAG$
QCAlgorithm.Indicators.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 QuantConnect.Data;
20 using System;
21 using System.Collections.Generic;
22 using System.Linq;
23 using Python.Runtime;
24 using QuantConnect.Util;
25 using static QuantConnect.StringExtensions;
27 
28 namespace QuantConnect.Algorithm
29 {
30  public partial class QCAlgorithm
31  {
32  private readonly List<Func<IBaseData, decimal>> _quoteRequiredFields = new() {
33  Field.BidPrice,
34  Field.AskPrice,
35  Field.BidClose,
36  Field.BidOpen,
37  Field.BidLow,
38  Field.BidHigh,
39  Field.AskClose,
40  Field.AskOpen,
41  Field.AskLow,
42  Field.AskHigh,
43  };
44 
45  /// <summary>
46  /// Gets whether or not WarmUpIndicator is allowed to warm up indicators
47  /// </summary>
48  [Obsolete("Please use Settings.AutomaticIndicatorWarmUp")]
50  {
51  get
52  {
53  return Settings.AutomaticIndicatorWarmUp;
54  }
55  set
56  {
57  Settings.AutomaticIndicatorWarmUp = value;
58  }
59  }
60 
61  /// <summary>
62  /// Creates a new Acceleration Bands indicator.
63  /// </summary>
64  /// <param name="symbol">The symbol whose Acceleration Bands we want.</param>
65  /// <param name="period">The period of the three moving average (middle, upper and lower band).</param>
66  /// <param name="width">A coefficient specifying the distance between the middle band and upper or lower bands.</param>
67  /// <param name="movingAverageType">Type of the moving average.</param>
68  /// <param name="resolution">The resolution.</param>
69  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar.</param>
70  /// <returns></returns>
71  [DocumentationAttribute(Indicators)]
72  public AccelerationBands ABANDS(Symbol symbol, int period, decimal width = 4, MovingAverageType movingAverageType = MovingAverageType.Simple,
73  Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
74  {
75  var name = CreateIndicatorName(symbol, $"ABANDS({period},{width})", resolution);
76  var accelerationBands = new AccelerationBands(name, period, width, movingAverageType);
77  InitializeIndicator(accelerationBands, resolution, selector, symbol);
78 
79  return accelerationBands;
80  }
81 
82  /// <summary>
83  /// Creates a new AccumulationDistribution indicator.
84  /// </summary>
85  /// <param name="symbol">The symbol whose AD we want</param>
86  /// <param name="resolution">The resolution</param>
87  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
88  /// <returns>The AccumulationDistribution indicator for the requested symbol over the specified period</returns>
89  [DocumentationAttribute(Indicators)]
90  public AccumulationDistribution AD(Symbol symbol, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
91  {
92  var name = CreateIndicatorName(symbol, "AD", resolution);
93  var accumulationDistribution = new AccumulationDistribution(name);
94  InitializeIndicator(accumulationDistribution, resolution, selector, symbol);
95 
96  return accumulationDistribution;
97  }
98 
99  /// <summary>
100  /// Creates a new AccumulationDistributionOscillator indicator.
101  /// </summary>
102  /// <param name="symbol">The symbol whose ADOSC we want</param>
103  /// <param name="fastPeriod">The fast moving average period</param>
104  /// <param name="slowPeriod">The slow moving average period</param>
105  /// <param name="resolution">The resolution</param>
106  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
107  /// <returns>The AccumulationDistributionOscillator indicator for the requested symbol over the specified period</returns>
108  [DocumentationAttribute(Indicators)]
109  public AccumulationDistributionOscillator ADOSC(Symbol symbol, int fastPeriod, int slowPeriod, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
110  {
111  var name = CreateIndicatorName(symbol, $"ADOSC({fastPeriod},{slowPeriod})", resolution);
112  var accumulationDistributionOscillator = new AccumulationDistributionOscillator(name, fastPeriod, slowPeriod);
113  InitializeIndicator(accumulationDistributionOscillator, resolution, selector, symbol);
114 
115  return accumulationDistributionOscillator;
116  }
117 
118  /// <summary>
119  /// Creates a Alpha indicator for the given target symbol in relation with the reference used.
120  /// The indicator will be automatically updated on the given resolution.
121  /// </summary>
122  /// <param name="target">The target symbol whose Alpha value we want</param>
123  /// <param name="reference">The reference symbol to compare with the target symbol</param>
124  /// <param name="alphaPeriod">The period of the Alpha indicator</param>
125  /// <param name="betaPeriod">The period of the Beta indicator</param>
126  /// <param name="resolution">The resolution</param>
127  /// <param name="riskFreeRate">The risk free rate</param>
128  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
129  /// <returns>The Alpha indicator for the given parameters</returns>
130  [DocumentationAttribute(Indicators)]
131  public Alpha A(Symbol target, Symbol reference, int alphaPeriod = 1, int betaPeriod = 252, Resolution? resolution = null, decimal? riskFreeRate = null, Func<IBaseData, IBaseDataBar> selector = null)
132  {
133  var baseBame = riskFreeRate.HasValue ? $"A({alphaPeriod},{betaPeriod},{riskFreeRate})" : $"A({alphaPeriod},{betaPeriod})";
134  var name = CreateIndicatorName(target, baseBame, resolution);
135 
136  // If risk free rate is not specified, use the default risk free rate model
137  IRiskFreeInterestRateModel riskFreeRateModel = riskFreeRate.HasValue
138  ? new ConstantRiskFreeRateInterestRateModel(riskFreeRate.Value)
140 
141  var alpha = new Alpha(name, target, reference, alphaPeriod, betaPeriod, riskFreeRateModel);
142  InitializeIndicator(alpha, resolution, selector, target, reference);
143 
144  return alpha;
145  }
146 
147  /// <summary>
148  /// Creates a new Average Range (AR) indicator.
149  /// </summary>
150  /// <param name="symbol">The symbol whose Average Range we want to calculate</param>
151  /// <param name="period">The period over which to compute the Average Range</param>
152  /// <param name="resolution">The resolution</param>
153  /// <param name="selector">Selects a value from the BaseData to send into the indicator. If null, defaults to the Value property of BaseData (x => x.Value).</param>
154  /// <returns>The Average Range indicator for the requested symbol over the specified period</returns>
155  [DocumentationAttribute(Indicators)]
156  public AverageRange AR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
157  {
158  var name = CreateIndicatorName(symbol, $"AR({period})", resolution);
159  var averageRange = new AverageRange(name, period);
160  InitializeIndicator(averageRange, resolution, selector, symbol);
161  return averageRange;
162  }
163 
164  /// <summary>
165  /// Creates a new ARIMA indicator.
166  /// </summary>
167  /// <param name="symbol">The symbol whose ARIMA indicator we want</param>
168  /// <param name="arOrder">AR order (p) -- defines the number of past values to consider in the AR component of the model.</param>
169  /// <param name="diffOrder">Difference order (d) -- defines how many times to difference the model before fitting parameters.</param>
170  /// <param name="maOrder">MA order (q) -- defines the number of past values to consider in the MA component of the model.</param>
171  /// <param name="period">Size of the rolling series to fit onto</param>
172  /// <param name="resolution">The resolution</param>
173  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
174  /// <returns>The ARIMA indicator for the requested symbol over the specified period</returns>
175  [DocumentationAttribute(Indicators)]
176  public AutoRegressiveIntegratedMovingAverage ARIMA(Symbol symbol, int arOrder, int diffOrder, int maOrder, int period,
177  Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
178  {
179  var name = CreateIndicatorName(symbol, $"ARIMA({arOrder},{diffOrder},{maOrder},{period})", resolution);
180  var arimaIndicator = new AutoRegressiveIntegratedMovingAverage(name, arOrder, diffOrder, maOrder, period);
181  InitializeIndicator(arimaIndicator, resolution, selector, symbol);
182 
183  return arimaIndicator;
184  }
185 
186  /// <summary>
187  /// Creates a new Average Directional Index indicator.
188  /// The indicator will be automatically updated on the given resolution.
189  /// </summary>
190  /// <param name="symbol">The symbol whose Average Directional Index we seek</param>
191  /// <param name="resolution">The resolution.</param>
192  /// <param name="period">The period over which to compute the Average Directional Index</param>
193  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
194  /// <returns>The Average Directional Index indicator for the requested symbol.</returns>
195  [DocumentationAttribute(Indicators)]
196  public AverageDirectionalIndex ADX(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
197  {
198  var name = CreateIndicatorName(symbol, $"ADX({period})", resolution);
199  var averageDirectionalIndex = new AverageDirectionalIndex(name, period);
200  InitializeIndicator(averageDirectionalIndex, resolution, selector, symbol);
201 
202  return averageDirectionalIndex;
203  }
204 
205  /// <summary>
206  /// Creates a new Awesome Oscillator from the specified periods.
207  /// </summary>
208  /// <param name="symbol">The symbol whose Awesome Oscillator we seek</param>
209  /// <param name="resolution">The resolution.</param>
210  /// <param name="fastPeriod">The period of the fast moving average associated with the AO</param>
211  /// <param name="slowPeriod">The period of the slow moving average associated with the AO</param>
212  /// <param name="type">The type of moving average used when computing the fast and slow term. Defaults to simple moving average.</param>
213  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
214  [DocumentationAttribute(Indicators)]
215  public AwesomeOscillator AO(Symbol symbol, int fastPeriod, int slowPeriod, MovingAverageType type, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
216  {
217  var name = CreateIndicatorName(symbol, $"AO({fastPeriod},{slowPeriod},{type})", resolution);
218  var awesomeOscillator = new AwesomeOscillator(name, fastPeriod, slowPeriod, type);
219  InitializeIndicator(awesomeOscillator, resolution, selector, symbol);
220 
221  return awesomeOscillator;
222  }
223 
224  /// <summary>
225  /// Creates a new AverageDirectionalMovementIndexRating indicator.
226  /// </summary>
227  /// <param name="symbol">The symbol whose ADXR we want</param>
228  /// <param name="period">The period over which to compute the ADXR</param>
229  /// <param name="resolution">The resolution.</param>
230  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
231  /// <returns>The AverageDirectionalMovementIndexRating indicator for the requested symbol over the specified period</returns>
232  [DocumentationAttribute(Indicators)]
233  public AverageDirectionalMovementIndexRating ADXR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
234  {
235  var name = CreateIndicatorName(symbol, $"ADXR({period})", resolution);
236  var averageDirectionalMovementIndexRating = new AverageDirectionalMovementIndexRating(name, period);
237  InitializeIndicator(averageDirectionalMovementIndexRating, resolution, selector, symbol);
238 
239  return averageDirectionalMovementIndexRating;
240  }
241 
242  /// <summary>
243  /// Creates a new ArnaudLegouxMovingAverage indicator.
244  /// </summary>
245  /// <param name="symbol">The symbol whose ALMA we want</param>
246  /// <param name="period">int - the number of periods to calculate the ALMA</param>
247  /// <param name="sigma"> int - this parameter is responsible for the shape of the curve coefficients.
248  /// </param>
249  /// <param name="offset">
250  /// decimal - This parameter allows regulating the smoothness and high sensitivity of the
251  /// Moving Average. The range for this parameter is [0, 1].
252  /// </param>
253  /// <param name="resolution">The resolution</param>
254  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
255  /// <returns>The ArnaudLegouxMovingAverage indicator for the requested symbol over the specified period</returns>
256  [DocumentationAttribute(Indicators)]
257  public ArnaudLegouxMovingAverage ALMA(Symbol symbol, int period, int sigma = 6, decimal offset = 0.85m, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
258  {
259  var name = CreateIndicatorName(symbol, $"ALMA({period},{sigma},{offset})", resolution);
260  var arnaudLegouxMovingAverage = new ArnaudLegouxMovingAverage(name, period, sigma, offset);
261  InitializeIndicator(arnaudLegouxMovingAverage, resolution, selector, symbol);
262 
263  return arnaudLegouxMovingAverage;
264  }
265 
266  /// <summary>
267  /// Creates a new AbsolutePriceOscillator indicator.
268  /// </summary>
269  /// <param name="symbol">The symbol whose APO we want</param>
270  /// <param name="fastPeriod">The fast moving average period</param>
271  /// <param name="slowPeriod">The slow moving average period</param>
272  /// <param name="movingAverageType">The type of moving average to use</param>
273  /// <param name="resolution">The resolution</param>
274  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
275  /// <returns>The AbsolutePriceOscillator indicator for the requested symbol over the specified period</returns>
276  [DocumentationAttribute(Indicators)]
277  public AbsolutePriceOscillator APO(Symbol symbol, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
278  {
279  var name = CreateIndicatorName(symbol, $"APO({fastPeriod},{slowPeriod})", resolution);
280  var absolutePriceOscillator = new AbsolutePriceOscillator(name, fastPeriod, slowPeriod, movingAverageType);
281  InitializeIndicator(absolutePriceOscillator, resolution, selector, symbol);
282 
283  return absolutePriceOscillator;
284  }
285 
286  /// <summary>
287  /// Creates a new AroonOscillator indicator which will compute the AroonUp and AroonDown (as well as the delta)
288  /// </summary>
289  /// <param name="symbol">The symbol whose Aroon we seek</param>
290  /// <param name="period">The look back period for computing number of periods since maximum and minimum</param>
291  /// <param name="resolution">The resolution</param>
292  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
293  /// <returns>An AroonOscillator configured with the specified periods</returns>
294  [DocumentationAttribute(Indicators)]
295  public AroonOscillator AROON(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
296  {
297  return AROON(symbol, period, period, resolution, selector);
298  }
299 
300  /// <summary>
301  /// Creates a new AroonOscillator indicator which will compute the AroonUp and AroonDown (as well as the delta)
302  /// </summary>
303  /// <param name="symbol">The symbol whose Aroon we seek</param>
304  /// <param name="upPeriod">The look back period for computing number of periods since maximum</param>
305  /// <param name="downPeriod">The look back period for computing number of periods since minimum</param>
306  /// <param name="resolution">The resolution</param>
307  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
308  /// <returns>An AroonOscillator configured with the specified periods</returns>
309  [DocumentationAttribute(Indicators)]
310  public AroonOscillator AROON(Symbol symbol, int upPeriod, int downPeriod, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
311  {
312  var name = CreateIndicatorName(symbol, $"AROON({upPeriod},{downPeriod})", resolution);
313  var aroonOscillator = new AroonOscillator(name, upPeriod, downPeriod);
314  InitializeIndicator(aroonOscillator, resolution, selector, symbol);
315 
316  return aroonOscillator;
317  }
318 
319  /// <summary>
320  /// Creates a new AverageTrueRange indicator for the symbol. The indicator will be automatically
321  /// updated on the given resolution.
322  /// </summary>
323  /// <param name="symbol">The symbol whose ATR we want</param>
324  /// <param name="period">The smoothing period used to smooth the computed TrueRange values</param>
325  /// <param name="type">The type of smoothing to use</param>
326  /// <param name="resolution">The resolution</param>
327  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
328  /// <returns>A new AverageTrueRange indicator with the specified smoothing type and period</returns>
329  [DocumentationAttribute(Indicators)]
330  public AverageTrueRange ATR(Symbol symbol, int period, MovingAverageType type = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
331  {
332  var name = CreateIndicatorName(symbol, $"ATR({period})", resolution);
333  var averageTrueRange = new AverageTrueRange(name, period, type);
334  InitializeIndicator(averageTrueRange, resolution, selector, symbol);
335 
336  return averageTrueRange;
337  }
338 
339  /// <summary>
340  /// Creates an AugenPriceSpike indicator for the symbol. The indicator will be automatically
341  /// updated on the given resolution.
342  /// </summary>
343  /// <param name="symbol">The symbol whose APS we want</param>
344  /// <param name="period">The period of the APS</param>
345  /// <param name="resolution">The resolution</param>
346  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
347  /// <returns>The AugenPriceSpike indicator for the given parameters</returns>
348  [DocumentationAttribute(Indicators)]
349  public AugenPriceSpike APS(Symbol symbol, int period = 3, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
350  {
351  var name = CreateIndicatorName(symbol, $"APS({period})", resolution);
352  var augenPriceSpike = new AugenPriceSpike(name, period);
353  InitializeIndicator(augenPriceSpike, resolution, selector, symbol);
354 
355  return augenPriceSpike;
356  }
357 
358  /// <summary>
359  /// Creates a new BollingerBands indicator which will compute the MiddleBand, UpperBand, LowerBand, and StandardDeviation
360  /// </summary>
361  /// <param name="symbol">The symbol whose BollingerBands we seek</param>
362  /// <param name="period">The period of the standard deviation and moving average (middle band)</param>
363  /// <param name="k">The number of standard deviations specifying the distance between the middle band and upper or lower bands</param>
364  /// <param name="movingAverageType">The type of moving average to be used</param>
365  /// <param name="resolution">The resolution</param>
366  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
367  /// <returns>A BollingerBands configured with the specified period</returns>
368  [DocumentationAttribute(Indicators)]
369  public BollingerBands BB(Symbol symbol, int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple,
370  Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
371  {
372  var name = CreateIndicatorName(symbol, $"BB({period},{k})", resolution);
373  var bollingerBands = new BollingerBands(name, period, k, movingAverageType);
374  InitializeIndicator(bollingerBands, resolution, selector, symbol);
375 
376  return bollingerBands;
377  }
378 
379  /// <summary>
380  /// Creates a Beta indicator for the given target symbol in relation with the reference used.
381  /// The indicator will be automatically updated on the given resolution.
382  /// </summary>
383  /// <param name="target">The target symbol whose Beta value we want</param>
384  /// <param name="reference">The reference symbol to compare with the target symbol</param>
385  /// <param name="period">The period of the Beta indicator</param>
386  /// <param name="resolution">The resolution</param>
387  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
388  /// <returns>The Beta indicator for the given parameters</returns>
389  [DocumentationAttribute(Indicators)]
390  public Beta B(Symbol target, Symbol reference, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
391  {
392  var name = CreateIndicatorName(QuantConnect.Symbol.None, $"B({period})", resolution);
393  var beta = new Beta(name, target, reference, period);
394  InitializeIndicator(beta, resolution, selector, target, reference);
395 
396  return beta;
397  }
398 
399  /// <summary>
400  /// Creates a new Balance Of Power indicator.
401  /// The indicator will be automatically updated on the given resolution.
402  /// </summary>
403  /// <param name="symbol">The symbol whose Balance Of Power we seek</param>
404  /// <param name="resolution">The resolution.</param>
405  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
406  /// <returns>The Balance Of Power indicator for the requested symbol.</returns>
407  [DocumentationAttribute(Indicators)]
408  public BalanceOfPower BOP(Symbol symbol, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
409  {
410  var name = CreateIndicatorName(symbol, "BOP", resolution);
411  var balanceOfPower = new BalanceOfPower(name);
412  InitializeIndicator(balanceOfPower, resolution, selector, symbol);
413 
414  return balanceOfPower;
415  }
416 
417  /// <summary>
418  /// Initializes a new instance of the <see cref="CoppockCurve"/> indicator
419  /// </summary>
420  /// <param name="symbol">The symbol whose Coppock Curve we want</param>
421  /// <param name="shortRocPeriod">The period for the short ROC</param>
422  /// <param name="longRocPeriod">The period for the long ROC</param>
423  /// <param name="lwmaPeriod">The period for the LWMA</param>
424  /// <param name="resolution">The resolution</param>
425  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
426  /// <returns>The Coppock Curve indicator for the requested symbol over the specified period</returns>
427  [DocumentationAttribute(Indicators)]
428  public CoppockCurve CC(Symbol symbol, int shortRocPeriod = 11, int longRocPeriod = 14, int lwmaPeriod = 10, Resolution? resolution = null,
429  Func<IBaseData, decimal> selector = null)
430  {
431  var name = CreateIndicatorName(symbol, $"CC({shortRocPeriod},{longRocPeriod},{lwmaPeriod})", resolution);
432  var coppockCurve = new CoppockCurve(name, shortRocPeriod, longRocPeriod, lwmaPeriod);
433  InitializeIndicator(coppockCurve, resolution, selector, symbol);
434 
435  return coppockCurve;
436  }
437 
438  /// <summary>
439  /// Creates a Correlation indicator for the given target symbol in relation with the reference used.
440  /// The indicator will be automatically updated on the given resolution.
441  /// </summary>
442  /// <param name="target">The target symbol of this indicator</param>
443  /// <param name="reference">The reference symbol of this indicator</param>
444  /// <param name="period">The period of this indicator</param>
445  /// <param name="correlationType">Correlation type</param>
446  /// <param name="resolution">The resolution</param>
447  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
448  /// <returns>The Correlation indicator for the given parameters</returns>
449  [DocumentationAttribute(Indicators)]
450  public Correlation C(Symbol target, Symbol reference, int period, CorrelationType correlationType = CorrelationType.Pearson, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
451  {
452  var name = CreateIndicatorName(QuantConnect.Symbol.None, $"C({period})", resolution);
453  var correlation = new Correlation(name, target, reference, period, correlationType);
454  InitializeIndicator(correlation, resolution, selector, target, reference);
455 
456  return correlation;
457  }
458 
459  /// <summary>
460  /// Creates a new CommodityChannelIndex indicator. The indicator will be automatically
461  /// updated on the given resolution.
462  /// </summary>
463  /// <param name="symbol">The symbol whose CCI we want</param>
464  /// <param name="period">The period over which to compute the CCI</param>
465  /// <param name="movingAverageType">The type of moving average to use in computing the typical price average</param>
466  /// <param name="resolution">The resolution</param>
467  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
468  /// <returns>The CommodityChannelIndex indicator for the requested symbol over the specified period</returns>
469  [DocumentationAttribute(Indicators)]
470  public CommodityChannelIndex CCI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
471  {
472  var name = CreateIndicatorName(symbol, $"CCI({period})", resolution);
473  var commodityChannelIndex = new CommodityChannelIndex(name, period, movingAverageType);
474  InitializeIndicator(commodityChannelIndex, resolution, selector, symbol);
475 
476  return commodityChannelIndex;
477  }
478 
479  /// <summary>
480  /// Creates a new ChoppinessIndex indicator for the symbol. The indicator will be automatically
481  /// updated on the given resolution.
482  /// </summary>
483  /// <param name="symbol">The symbol whose CHOP we want</param>
484  /// <param name="period">The input window period used to calculate max high and min low</param>
485  /// <param name="resolution">The resolution</param>
486  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
487  /// <returns>A new ChoppinessIndex indicator with the window period</returns>
488  [DocumentationAttribute(Indicators)]
489  public ChoppinessIndex CHOP(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
490  {
491  var name = CreateIndicatorName(symbol, $"CHOP({period})", resolution);
492  var indicator = new ChoppinessIndex(name, period);
493  InitializeIndicator(indicator, resolution, selector, symbol);
494  return indicator;
495  }
496 
497  /// <summary>
498  /// Creates a new Chande Kroll Stop indicator which will compute the short and lower stop.
499  /// The indicator will be automatically updated on the given resolution.
500  /// </summary>
501  /// <param name="symbol">The symbol whose Chande Kroll Stop we seek.</param>
502  /// <param name="atrPeriod">The period over which to compute the average true range.</param>
503  /// <param name="atrMult">The ATR multiplier to be used to compute stops distance.</param>
504  /// <param name="period">The period over which to compute the max of high stop and min of low stop.</param>
505  /// <param name="resolution">The resolution.</param>
506  /// <param name="movingAverageType">The type of smoothing used to smooth the true range values</param>
507  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
508  /// <returns>The Chande Kroll Stop indicator for the requested symbol.</returns>
509  [DocumentationAttribute(Indicators)]
510  public ChandeKrollStop CKS(Symbol symbol, int atrPeriod, decimal atrMult, int period, MovingAverageType movingAverageType = MovingAverageType.Wilders, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
511  {
512  var name = CreateIndicatorName(symbol, $"CKS({atrPeriod},{atrMult},{period})", resolution);
513  var indicator = new ChandeKrollStop(name, atrPeriod, atrMult, period, movingAverageType);
514  InitializeIndicator(indicator, resolution, selector, symbol);
515  return indicator;
516  }
517 
518  /// <summary>
519  /// Creates a new ChaikinMoneyFlow indicator.
520  /// </summary>
521  /// <param name="symbol">The symbol whose CMF we want</param>
522  /// <param name="period">The period over which to compute the CMF</param>
523  /// <param name="resolution">The resolution</param>
524  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
525  /// <returns>The ChaikinMoneyFlow indicator for the requested symbol over the specified period</returns>
526  [DocumentationAttribute(Indicators)]
527  public ChaikinMoneyFlow CMF(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
528  {
529  var name = CreateIndicatorName(symbol, $"CMF({period})", resolution);
530  var chaikinMoneyFlow = new ChaikinMoneyFlow(name, period);
531  InitializeIndicator(chaikinMoneyFlow, resolution, selector, symbol);
532 
533  return chaikinMoneyFlow;
534 
535  }
536 
537  /// <summary>
538  /// Creates a new ChandeMomentumOscillator indicator.
539  /// </summary>
540  /// <param name="symbol">The symbol whose CMO we want</param>
541  /// <param name="period">The period over which to compute the CMO</param>
542  /// <param name="resolution">The resolution</param>
543  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
544  /// <returns>The ChandeMomentumOscillator indicator for the requested symbol over the specified period</returns>
545  [DocumentationAttribute(Indicators)]
546  public ChandeMomentumOscillator CMO(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
547  {
548  var name = CreateIndicatorName(symbol, $"CMO({period})", resolution);
549  var chandeMomentumOscillator = new ChandeMomentumOscillator(name, period);
550  InitializeIndicator(chandeMomentumOscillator, resolution, selector, symbol);
551 
552  return chandeMomentumOscillator;
553  }
554 
555  /// <summary>
556  /// Creates a new Connors Relative Strength Index (CRSI) indicator, which combines the traditional Relative Strength Index (RSI),
557  /// Streak RSI (SRSI), and Percent Rank to provide a more robust measure of market strength.
558  /// This indicator oscillates based on momentum, streak behavior, and price change over the specified periods.
559  /// </summary>
560  /// <param name="symbol">The symbol whose CRSI is to be calculated.</param>
561  /// <param name="rsiPeriod">The period for the traditional RSI calculation.</param>
562  /// <param name="rsiPeriodStreak">The period for the Streak RSI calculation (SRSI).</param>
563  /// <param name="lookBackPeriod">The look-back period for calculating the Percent Rank.</param>
564  /// <param name="resolution">The resolution of the data (optional).</param>
565  /// <param name="selector">Function to select a value from the BaseData to input into the indicator. Defaults to using the 'Value' property of BaseData if null.</param>
566  /// <returns>The Connors Relative Strength Index (CRSI) for the specified symbol and periods.</returns>
567  [DocumentationAttribute(Indicators)]
568  public ConnorsRelativeStrengthIndex CRSI(Symbol symbol, int rsiPeriod, int rsiPeriodStreak, int lookBackPeriod, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
569  {
570  var name = CreateIndicatorName(symbol, $"CRSI({rsiPeriod},{rsiPeriodStreak},{lookBackPeriod})", resolution);
571  var connorsRelativeStrengthIndex = new ConnorsRelativeStrengthIndex(name, rsiPeriod, rsiPeriodStreak, lookBackPeriod);
572  InitializeIndicator(connorsRelativeStrengthIndex, resolution, selector, symbol);
573  return connorsRelativeStrengthIndex;
574  }
575 
576  ///<summary>
577  /// Creates a new DeMarker Indicator (DEM), an oscillator-type indicator measuring changes in terms of an asset's
578  /// High and Low tradebar values.
579  ///</summary>
580  /// <param name="symbol">The symbol whose DEM we seek.</param>
581  /// <param name="period">The period of the moving average implemented</param>
582  /// <param name="type">Specifies the type of moving average to be used</param>
583  /// <param name="resolution">The resolution.</param>
584  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
585  /// <returns>The DeMarker indicator for the requested symbol.</returns>
586  [DocumentationAttribute(Indicators)]
587  public DeMarkerIndicator DEM(Symbol symbol, int period, MovingAverageType type, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
588  {
589  var name = CreateIndicatorName(symbol, $"DEM({period},{type})", resolution);
590  var deMarkerIndicator = new DeMarkerIndicator(name, period, type);
591  InitializeIndicator(deMarkerIndicator, resolution, selector, symbol);
592  return deMarkerIndicator;
593  }
594 
595  /// <summary>
596  /// Creates a new Donchian Channel indicator which will compute the Upper Band and Lower Band.
597  /// The indicator will be automatically updated on the given resolution.
598  /// </summary>
599  /// <param name="symbol">The symbol whose Donchian Channel we seek.</param>
600  /// <param name="upperPeriod">The period over which to compute the upper Donchian Channel.</param>
601  /// <param name="lowerPeriod">The period over which to compute the lower Donchian Channel.</param>
602  /// <param name="resolution">The resolution.</param>
603  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
604  /// <returns>The Donchian Channel indicator for the requested symbol.</returns>
605  [DocumentationAttribute(Indicators)]
606  public DonchianChannel DCH(Symbol symbol, int upperPeriod, int lowerPeriod, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
607  {
608  var name = CreateIndicatorName(symbol, $"DCH({upperPeriod},{lowerPeriod})", resolution);
609  var donchianChannel = new DonchianChannel(name, upperPeriod, lowerPeriod);
610  InitializeIndicator(donchianChannel, resolution, selector, symbol);
611 
612  return donchianChannel;
613  }
614 
615  /// <summary>
616  /// Overload shorthand to create a new symmetric Donchian Channel indicator which
617  /// has the upper and lower channels set to the same period length.
618  /// </summary>
619  /// <param name="symbol">The symbol whose Donchian Channel we seek.</param>
620  /// <param name="period">The period over which to compute the Donchian Channel.</param>
621  /// <param name="resolution">The resolution.</param>
622  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
623  /// <returns>The Donchian Channel indicator for the requested symbol.</returns>
624  [DocumentationAttribute(Indicators)]
625  public DonchianChannel DCH(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
626  {
627  return DCH(symbol, period, period, resolution, selector);
628  }
629 
630  /// <summary>
631  /// Creates a new Delta indicator for the symbol The indicator will be automatically
632  /// updated on the symbol's subscription resolution
633  /// </summary>
634  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
635  /// <param name="mirrorOption">The mirror option for parity calculation</param>
636  /// <param name="riskFreeRate">The risk free rate</param>
637  /// <param name="dividendYield">The dividend yield</param>
638  /// <param name="optionModel">The option pricing model used to estimate Delta</param>
639  /// <param name="ivModel">The option pricing model used to estimate IV</param>
640  /// <param name="resolution">The desired resolution of the data</param>
641  /// <returns>A new Delta indicator for the specified symbol</returns>
642  [DocumentationAttribute(Indicators)]
643  public Delta D(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null,
644  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null, Resolution? resolution = null)
645  {
646  var name = InitializeOptionIndicator<Delta>(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution);
647 
648  var delta = new Delta(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel);
649  InitializeOptionIndicator(delta, resolution, symbol, mirrorOption);
650  return delta;
651  }
652 
653  /// <summary>
654  /// Creates a new Delta indicator for the symbol The indicator will be automatically
655  /// updated on the symbol's subscription resolution
656  /// </summary>
657  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
658  /// <param name="mirrorOption">The mirror option for parity calculation</param>
659  /// <param name="riskFreeRate">The risk free rate</param>
660  /// <param name="dividendYield">The dividend yield</param>
661  /// <param name="optionModel">The option pricing model used to estimate Delta</param>
662  /// <param name="ivModel">The option pricing model used to estimate IV</param>
663  /// <param name="resolution">The desired resolution of the data</param>
664  /// <returns>A new Delta indicator for the specified symbol</returns>
665  [DocumentationAttribute(Indicators)]
666  public Delta Δ(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes,
667  OptionPricingModelType? ivModel = null, Resolution? resolution = null)
668  {
669  return D(symbol, mirrorOption, riskFreeRate, dividendYield, optionModel, ivModel, resolution);
670  }
671 
672  /// <summary>
673  /// Creates a new DoubleExponentialMovingAverage indicator.
674  /// </summary>
675  /// <param name="symbol">The symbol whose DEMA we want</param>
676  /// <param name="period">The period over which to compute the DEMA</param>
677  /// <param name="resolution">The resolution</param>
678  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
679  /// <returns>The DoubleExponentialMovingAverage indicator for the requested symbol over the specified period</returns>
680  [DocumentationAttribute(Indicators)]
681  public DoubleExponentialMovingAverage DEMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
682  {
683  var name = CreateIndicatorName(symbol, $"DEMA({period})", resolution);
684  var doubleExponentialMovingAverage = new DoubleExponentialMovingAverage(name, period);
685  InitializeIndicator(doubleExponentialMovingAverage, resolution, selector, symbol);
686 
687  return doubleExponentialMovingAverage;
688  }
689 
690  /// <summary>
691  /// Creates a new DerivativeOscillator indicator.
692  /// </summary>
693  /// <param name="symbol">The symbol whose DO we want</param>
694  /// <param name="rsiPeriod">The period over which to compute the RSI</param>
695  /// <param name="smoothingRsiPeriod">The period over which to compute the smoothing RSI</param>
696  /// <param name="doubleSmoothingRsiPeriod">The period over which to compute the double smoothing RSI</param>
697  /// <param name="signalLinePeriod">The period over which to compute the signal line</param>
698  /// <param name="resolution">The resolution</param>
699  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x =&gt; x.Value)</param>
700  /// <returns>The DerivativeOscillator indicator for the requested symbol over the specified period</returns>
701  [DocumentationAttribute(Indicators)]
702  public DerivativeOscillator DO(Symbol symbol, int rsiPeriod, int smoothingRsiPeriod, int doubleSmoothingRsiPeriod, int signalLinePeriod, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
703  {
704  var name = CreateIndicatorName(symbol, $"DO({rsiPeriod},{smoothingRsiPeriod},{doubleSmoothingRsiPeriod},{signalLinePeriod})", resolution);
705  var derivativeOscillator = new DerivativeOscillator(name, rsiPeriod, smoothingRsiPeriod, doubleSmoothingRsiPeriod, signalLinePeriod);
706  InitializeIndicator(derivativeOscillator, resolution, selector, symbol);
707 
708  return derivativeOscillator;
709  }
710 
711  /// <summary>
712  /// Creates a new <see cref="DetrendedPriceOscillator"/> indicator.
713  /// </summary>
714  /// <param name="symbol">The symbol whose DPO we want</param>
715  /// <param name="period">The period over which to compute the DPO</param>
716  /// <param name="resolution">The resolution</param>
717  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
718  /// <returns>A new registered DetrendedPriceOscillator indicator for the requested symbol over the specified period</returns>
719  [DocumentationAttribute(Indicators)]
720  public DetrendedPriceOscillator DPO(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
721  {
722  var name = CreateIndicatorName(symbol, $"DPO({period})", resolution);
723  var detrendedPriceOscillator = new DetrendedPriceOscillator(name, period);
724  InitializeIndicator(detrendedPriceOscillator, resolution, selector, symbol);
725 
726  return detrendedPriceOscillator;
727  }
728 
729  /// <summary>
730  /// Creates an ExponentialMovingAverage indicator for the symbol. The indicator will be automatically
731  /// updated on the given resolution.
732  /// </summary>
733  /// <param name="symbol">The symbol whose EMA we want</param>
734  /// <param name="period">The period of the EMA</param>
735  /// <param name="resolution">The resolution</param>
736  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
737  /// <returns>The ExponentialMovingAverage for the given parameters</returns>
738  [DocumentationAttribute(Indicators)]
739  public ExponentialMovingAverage EMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
740  {
741  return EMA(symbol, period, ExponentialMovingAverage.SmoothingFactorDefault(period), resolution, selector);
742  }
743 
744  /// <summary>
745  /// Creates an ExponentialMovingAverage indicator for the symbol. The indicator will be automatically
746  /// updated on the given resolution.
747  /// </summary>
748  /// <param name="symbol">The symbol whose EMA we want</param>
749  /// <param name="period">The period of the EMA</param>
750  /// <param name="smoothingFactor">The percentage of data from the previous value to be carried into the next value</param>
751  /// <param name="resolution">The resolution</param>
752  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
753  /// <returns>The ExponentialMovingAverage for the given parameters</returns>
754  [DocumentationAttribute(Indicators)]
755  public ExponentialMovingAverage EMA(Symbol symbol, int period, decimal smoothingFactor, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
756  {
757  var name = CreateIndicatorName(symbol, $"EMA({period})", resolution);
758  var exponentialMovingAverage = new ExponentialMovingAverage(name, period, smoothingFactor);
759  InitializeIndicator(exponentialMovingAverage, resolution, selector, symbol);
760 
761  return exponentialMovingAverage;
762  }
763 
764  /// <summary>
765  /// Creates an EaseOfMovementValue indicator for the symbol. The indicator will be automatically
766  /// updated on the given resolution.
767  /// </summary>
768  /// <param name="symbol">The symbol whose EMV we want</param>
769  /// <param name="period">The period of the EMV</param>
770  /// <param name="scale">The length of the outputed value</param>
771  /// <param name="resolution">The resolution</param>
772  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
773  /// <returns>The EaseOfMovementValue indicator for the given parameters</returns>
774  [DocumentationAttribute(Indicators)]
775  public EaseOfMovementValue EMV(Symbol symbol, int period = 1, int scale = 10000, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
776  {
777  var name = CreateIndicatorName(symbol, $"EMV({period}, {scale})", resolution);
778  var easeOfMovementValue = new EaseOfMovementValue(name, period, scale);
779  InitializeIndicator(easeOfMovementValue, resolution, selector, symbol);
780 
781  return easeOfMovementValue;
782  }
783 
784  /// <summary>
785  /// Creates a new FilteredIdentity indicator for the symbol The indicator will be automatically
786  /// updated on the symbol's subscription resolution
787  /// </summary>
788  /// <param name="symbol">The symbol whose values we want as an indicator</param>
789  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
790  /// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
791  /// <param name="fieldName">The name of the field being selected</param>
792  /// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
793  [DocumentationAttribute(Indicators)]
794  public FilteredIdentity FilteredIdentity(Symbol symbol, Func<IBaseData, IBaseDataBar> selector = null, Func<IBaseData, bool> filter = null, string fieldName = null)
795  {
796  var resolution = GetSubscription(symbol).Resolution;
797  return FilteredIdentity(symbol, resolution, selector, filter, fieldName);
798  }
799 
800  /// <summary>
801  /// Creates a new FilteredIdentity indicator for the symbol The indicator will be automatically
802  /// updated on the symbol's subscription resolution
803  /// </summary>
804  /// <param name="symbol">The symbol whose values we want as an indicator</param>
805  /// <param name="resolution">The desired resolution of the data</param>
806  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
807  /// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
808  /// <param name="fieldName">The name of the field being selected</param>
809  /// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
810  [DocumentationAttribute(Indicators)]
811  public FilteredIdentity FilteredIdentity(Symbol symbol, Resolution resolution, Func<IBaseData, IBaseDataBar> selector = null, Func<IBaseData, bool> filter = null, string fieldName = null)
812  {
813  var name = CreateIndicatorName(symbol, fieldName ?? "close", resolution);
814  var filteredIdentity = new FilteredIdentity(name, filter);
815  RegisterIndicator<IBaseData>(symbol, filteredIdentity, resolution, selector);
816  return filteredIdentity;
817  }
818 
819  /// <summary>
820  /// Creates a new FilteredIdentity indicator for the symbol The indicator will be automatically
821  /// updated on the symbol's subscription resolution
822  /// </summary>
823  /// <param name="symbol">The symbol whose values we want as an indicator</param>
824  /// <param name="resolution">The desired resolution of the data</param>
825  /// <param name="selector">Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value)</param>
826  /// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
827  /// <param name="fieldName">The name of the field being selected</param>
828  /// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
829  [DocumentationAttribute(Indicators)]
830  public FilteredIdentity FilteredIdentity(Symbol symbol, TimeSpan resolution, Func<IBaseData, IBaseDataBar> selector = null, Func<IBaseData, bool> filter = null, string fieldName = null)
831  {
832  var name = Invariant($"{symbol}({fieldName ?? "close"}_{resolution})");
833  var filteredIdentity = new FilteredIdentity(name, filter);
834  RegisterIndicator<IBaseData>(symbol, filteredIdentity, ResolveConsolidator(symbol, resolution), selector);
835  return filteredIdentity;
836  }
837 
838  /// <summary>
839  /// Creates a new ForceIndex indicator for the symbol. The indicator will be automatically
840  /// updated on the given resolution.
841  /// </summary>
842  /// <param name="symbol">The symbol whose ForceIndex we want</param>
843  /// <param name="period">The smoothing period used to smooth the computed ForceIndex values</param>
844  /// <param name="type">The type of smoothing to use</param>
845  /// <param name="resolution">The resolution</param>
846  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
847  /// <returns>A new ForceIndex indicator with the specified smoothing type and period</returns>
848  [DocumentationAttribute(Indicators)]
849  public ForceIndex FI(Symbol symbol, int period, MovingAverageType type = MovingAverageType.Exponential, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
850  {
851  var name = CreateIndicatorName(symbol, $"FI({period})", resolution);
852  var indicator = new ForceIndex(name, period, type);
853  InitializeIndicator(indicator, resolution, selector, symbol);
854 
855  return indicator;
856  }
857 
858  /// <summary>
859  /// Creates an FisherTransform indicator for the symbol.
860  /// The indicator will be automatically updated on the given resolution.
861  /// </summary>
862  /// <param name="symbol">The symbol whose FisherTransform we want</param>
863  /// <param name="period">The period of the FisherTransform</param>
864  /// <param name="resolution">The resolution</param>
865  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
866  /// <returns>The FisherTransform for the given parameters</returns>
867  [DocumentationAttribute(Indicators)]
868  public FisherTransform FISH(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
869  {
870  var name = CreateIndicatorName(symbol, $"FISH({period})", resolution);
871  var fisherTransform = new FisherTransform(name, period);
872  InitializeIndicator(fisherTransform, resolution, selector, symbol);
873 
874  return fisherTransform;
875  }
876 
877 
878  /// <summary>
879  /// Creates an FractalAdaptiveMovingAverage (FRAMA) indicator for the symbol. The indicator will be automatically
880  /// updated on the given resolution.
881  /// </summary>
882  /// <param name="symbol">The symbol whose FRAMA we want</param>
883  /// <param name="period">The period of the FRAMA</param>
884  /// <param name="longPeriod">The long period of the FRAMA</param>
885  /// <param name="resolution">The resolution</param>
886  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
887  /// <returns>The FRAMA for the given parameters</returns>
888  [DocumentationAttribute(Indicators)]
889  public FractalAdaptiveMovingAverage FRAMA(Symbol symbol, int period, int longPeriod = 198, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
890  {
891  var name = CreateIndicatorName(symbol, $"FRAMA({period},{longPeriod})", resolution);
892  var fractalAdaptiveMovingAverage = new FractalAdaptiveMovingAverage(name, period, longPeriod);
893  InitializeIndicator(fractalAdaptiveMovingAverage, resolution, selector, symbol);
894 
895  return fractalAdaptiveMovingAverage;
896  }
897 
898  /// <summary>
899  /// Creates a new Gamma indicator for the symbol The indicator will be automatically
900  /// updated on the symbol's subscription resolution
901  /// </summary>
902  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
903  /// <param name="mirrorOption">The mirror option for parity calculation</param>
904  /// <param name="riskFreeRate">The risk free rate</param>
905  /// <param name="dividendYield">The dividend yield</param>
906  /// <param name="optionModel">The option pricing model used to estimate Gamma</param>
907  /// <param name="ivModel">The option pricing model used to estimate IV</param>
908  /// <param name="resolution">The desired resolution of the data</param>
909  /// <returns>A new Gamma indicator for the specified symbol</returns>
910  [DocumentationAttribute(Indicators)]
911  public Gamma G(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null,
912  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null, Resolution? resolution = null)
913  {
914  var name = InitializeOptionIndicator<Gamma>(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution);
915 
916  var gamma = new Gamma(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel);
917  InitializeOptionIndicator(gamma, resolution, symbol, mirrorOption);
918  return gamma;
919  }
920 
921  /// <summary>
922  /// Creates a new Gamma indicator for the symbol The indicator will be automatically
923  /// updated on the symbol's subscription resolution
924  /// </summary>
925  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
926  /// <param name="mirrorOption">The mirror option for parity calculation</param>
927  /// <param name="riskFreeRate">The risk free rate</param>
928  /// <param name="dividendYield">The dividend yield</param>
929  /// <param name="optionModel">The option pricing model used to estimate Gamma</param>
930  /// <param name="ivModel">The option pricing model used to estimate IV</param>
931  /// <param name="resolution">The desired resolution of the data</param>
932  /// <returns>A new Gamma indicator for the specified symbol</returns>
933  [DocumentationAttribute(Indicators)]
934  public Gamma Γ(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes,
935  OptionPricingModelType? ivModel = null, Resolution? resolution = null)
936  {
937  return G(symbol, mirrorOption, riskFreeRate, dividendYield, optionModel, ivModel, resolution);
938  }
939 
940  /// <summary>
941  /// Creates a new Heikin-Ashi indicator.
942  /// </summary>
943  /// <param name="symbol">The symbol whose Heikin-Ashi we want</param>
944  /// <param name="resolution">The resolution</param>
945  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
946  /// <returns>The Heikin-Ashi indicator for the requested symbol over the specified period</returns>
947  [DocumentationAttribute(Indicators)]
948  public HeikinAshi HeikinAshi(Symbol symbol, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
949  {
950  var name = CreateIndicatorName(symbol, "HA", resolution);
951  var heikinAshi = new HeikinAshi(name);
952  InitializeIndicator(heikinAshi, resolution, selector, symbol);
953 
954  return heikinAshi;
955  }
956 
957  /// <summary>
958  /// Creates a new Hurst Exponent indicator for the specified symbol.
959  /// The Hurst Exponent measures the long-term memory or self-similarity in a time series.
960  /// The default maxLag value of 20 is chosen for reliable and accurate results, but using a higher lag may reduce precision.
961  /// </summary>
962  /// <param name="symbol">The symbol for which the Hurst Exponent is calculated.</param>
963  /// <param name="period">The number of data points used to calculate the indicator at each step.</param>
964  /// <param name="maxLag">The maximum time lag used to compute the tau values for the Hurst Exponent calculation.</param>
965  /// <param name="resolution">The resolution</param>
966  /// <param name="selector">Function to select a value from the BaseData to input into the indicator. Defaults to using the 'Value' property of BaseData if null.</param>
967  /// <returns>The Hurst Exponent indicator for the specified symbol.</returns>
968  [DocumentationAttribute(Indicators)]
969  public HurstExponent HE(Symbol symbol, int period, int maxLag = 20, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
970  {
971  var name = CreateIndicatorName(symbol, $"HE({period},{maxLag})", resolution);
972  var hurstExponent = new HurstExponent(name, period, maxLag);
973  InitializeIndicator(hurstExponent, resolution, selector, symbol);
974  return hurstExponent;
975  }
976 
977  /// <summary>
978  /// Creates a new Hilbert Transform indicator
979  /// </summary>
980  /// <param name="symbol">The symbol whose Hilbert transform we want</param>
981  /// <param name="length">The length of the FIR filter used in the calculation of the Hilbert Transform.
982  /// This parameter determines the number of filter coefficients in the FIR filter.</param>
983  /// <param name="inPhaseMultiplicationFactor">The multiplication factor used in the calculation of the in-phase component
984  /// of the Hilbert Transform. This parameter adjusts the sensitivity and responsiveness of
985  /// the transform to changes in the input signal.</param>
986  /// <param name="quadratureMultiplicationFactor">The multiplication factor used in the calculation of the quadrature component of
987  /// the Hilbert Transform. This parameter also adjusts the sensitivity and responsiveness of the
988  /// transform to changes in the input signal.</param>
989  /// <param name="resolution">The resolution</param>
990  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
991  [DocumentationAttribute(Indicators)]
992  public HilbertTransform HT(Symbol symbol, int length, decimal inPhaseMultiplicationFactor, decimal quadratureMultiplicationFactor, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
993  {
994  var name = CreateIndicatorName(symbol, $"HT({length}, {inPhaseMultiplicationFactor}, {quadratureMultiplicationFactor})", resolution);
995  var hilbertTransform = new HilbertTransform(length, inPhaseMultiplicationFactor, quadratureMultiplicationFactor);
996  InitializeIndicator(hilbertTransform, resolution, selector, symbol);
997 
998  return hilbertTransform;
999  }
1000 
1001  /// <summary>
1002  /// Creates a new HullMovingAverage indicator. The Hull moving average is a series of nested weighted moving averages, is fast and smooth.
1003  /// </summary>
1004  /// <param name="symbol">The symbol whose Hull moving average we want</param>
1005  /// <param name="period">The period over which to compute the Hull moving average</param>
1006  /// <param name="resolution">The resolution</param>
1007  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1008  /// <returns></returns>
1009  [DocumentationAttribute(Indicators)]
1010  public HullMovingAverage HMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1011  {
1012  var name = CreateIndicatorName(symbol, $"HMA({period})", resolution);
1013  var hullMovingAverage = new HullMovingAverage(name, period);
1014  InitializeIndicator(hullMovingAverage, resolution, selector, symbol);
1015 
1016  return hullMovingAverage;
1017  }
1018 
1019  /// <summary>
1020  /// Creates a new InternalBarStrength indicator for the symbol. The indicator will be automatically
1021  /// updated on the given resolution.
1022  /// </summary>
1023  /// <param name="symbol">The symbol whose IBS we want</param>
1024  /// <param name="resolution">The resolution</param>
1025  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1026  /// <returns>A new InternalBarStrength indicator</returns>
1027  [DocumentationAttribute(Indicators)]
1028  public InternalBarStrength IBS(Symbol symbol, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
1029  {
1030  var name = CreateIndicatorName(symbol, "IBS", resolution);
1031  var indicator = new InternalBarStrength(name);
1032  InitializeIndicator(indicator, resolution, selector, symbol);
1033 
1034  return indicator;
1035  }
1036 
1037  /// <summary>
1038  /// Creates a new IchimokuKinkoHyo indicator for the symbol. The indicator will be automatically
1039  /// updated on the given resolution.
1040  /// </summary>
1041  /// <param name="symbol">The symbol whose ICHIMOKU we want</param>
1042  /// <param name="tenkanPeriod">The period to calculate the Tenkan-sen period</param>
1043  /// <param name="kijunPeriod">The period to calculate the Kijun-sen period</param>
1044  /// <param name="senkouAPeriod">The period to calculate the Tenkan-sen period</param>
1045  /// <param name="senkouBPeriod">The period to calculate the Tenkan-sen period</param>
1046  /// <param name="senkouADelayPeriod">The period to calculate the Tenkan-sen period</param>
1047  /// <param name="senkouBDelayPeriod">The period to calculate the Tenkan-sen period</param>
1048  /// <param name="resolution">The resolution</param>
1049  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1050  /// <returns>A new IchimokuKinkoHyo indicator with the specified periods and delays</returns>
1051  [DocumentationAttribute(Indicators)]
1052  public IchimokuKinkoHyo ICHIMOKU(Symbol symbol, int tenkanPeriod, int kijunPeriod, int senkouAPeriod, int senkouBPeriod,
1053  int senkouADelayPeriod, int senkouBDelayPeriod, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
1054  {
1055  var name = CreateIndicatorName(symbol, $"ICHIMOKU({tenkanPeriod},{kijunPeriod},{senkouAPeriod},{senkouBPeriod},{senkouADelayPeriod},{senkouBDelayPeriod})", resolution);
1056  var ichimokuKinkoHyo = new IchimokuKinkoHyo(name, tenkanPeriod, kijunPeriod, senkouAPeriod, senkouBPeriod, senkouADelayPeriod, senkouBDelayPeriod);
1057  InitializeIndicator(ichimokuKinkoHyo, resolution, selector, symbol);
1058 
1059  return ichimokuKinkoHyo;
1060  }
1061 
1062  /// <summary>
1063  /// Creates a new Identity indicator for the symbol The indicator will be automatically
1064  /// updated on the symbol's subscription resolution
1065  /// </summary>
1066  /// <param name="symbol">The symbol whose values we want as an indicator</param>
1067  /// <param name="selector">Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value)</param>
1068  /// <param name="fieldName">The name of the field being selected</param>
1069  /// <returns>A new Identity indicator for the specified symbol and selector</returns>
1070  [DocumentationAttribute(Indicators)]
1071  public Identity Identity(Symbol symbol, Func<IBaseData, decimal> selector = null, string fieldName = null)
1072  {
1073  var resolution = GetSubscription(symbol).Resolution;
1074  return Identity(symbol, resolution, selector, fieldName);
1075  }
1076 
1077  /// <summary>
1078  /// Creates a new Identity indicator for the symbol The indicator will be automatically
1079  /// updated on the symbol's subscription resolution
1080  /// </summary>
1081  /// <param name="symbol">The symbol whose values we want as an indicator</param>
1082  /// <param name="resolution">The desired resolution of the data</param>
1083  /// <param name="selector">Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value)</param>
1084  /// <param name="fieldName">The name of the field being selected</param>
1085  /// <returns>A new Identity indicator for the specified symbol and selector</returns>
1086  [DocumentationAttribute(Indicators)]
1087  public Identity Identity(Symbol symbol, Resolution resolution, Func<IBaseData, decimal> selector = null, string fieldName = null)
1088  {
1089  var name = CreateIndicatorName(symbol, fieldName ?? "close", resolution);
1090  var identity = new Identity(name);
1091  InitializeIndicator(identity, resolution, selector, symbol);
1092  return identity;
1093  }
1094 
1095  /// <summary>
1096  /// Creates a new Identity indicator for the symbol The indicator will be automatically
1097  /// updated on the symbol's subscription resolution
1098  /// </summary>
1099  /// <param name="symbol">The symbol whose values we want as an indicator</param>
1100  /// <param name="resolution">The desired resolution of the data</param>
1101  /// <param name="selector">Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value)</param>
1102  /// <param name="fieldName">The name of the field being selected</param>
1103  /// <returns>A new Identity indicator for the specified symbol and selector</returns>
1104  [DocumentationAttribute(Indicators)]
1105  public Identity Identity(Symbol symbol, TimeSpan resolution, Func<IBaseData, decimal> selector = null, string fieldName = null)
1106  {
1107  var name = Invariant($"{symbol}({fieldName ?? "close"},{resolution})");
1108  var identity = new Identity(name);
1109  RegisterIndicator(symbol, identity, ResolveConsolidator(symbol, resolution), selector);
1110  return identity;
1111  }
1112 
1113  /// <summary>
1114  /// Creates a new ImpliedVolatility indicator for the symbol The indicator will be automatically
1115  /// updated on the symbol's subscription resolution
1116  /// </summary>
1117  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
1118  /// <param name="mirrorOption">The mirror option contract used for parity type calculation</param>
1119  /// <param name="riskFreeRate">The risk free rate</param>
1120  /// <param name="dividendYield">The dividend yield</param>
1121  /// <param name="optionModel">The option pricing model used to estimate IV</param>
1122  /// <param name="resolution">The desired resolution of the data</param>
1123  /// <returns>A new ImpliedVolatility indicator for the specified symbol</returns>
1124  [DocumentationAttribute(Indicators)]
1125  public ImpliedVolatility IV(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null,
1126  OptionPricingModelType? optionModel = null, Resolution? resolution = null)
1127  {
1128  var name = InitializeOptionIndicator<ImpliedVolatility>(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution);
1129 
1130  var iv = new ImpliedVolatility(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel);
1131  InitializeOptionIndicator(iv, resolution, symbol, mirrorOption);
1132  return iv;
1133  }
1134 
1135  /// <summary>
1136  /// Creates a new KaufmanAdaptiveMovingAverage indicator.
1137  /// </summary>
1138  /// <param name="symbol">The symbol whose KAMA we want</param>
1139  /// <param name="period">The period of the Efficiency Ratio (ER) of KAMA</param>
1140  /// <param name="resolution">The resolution</param>
1141  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1142  /// <returns>The KaufmanAdaptiveMovingAverage indicator for the requested symbol over the specified period</returns>
1143  [DocumentationAttribute(Indicators)]
1144  public KaufmanAdaptiveMovingAverage KAMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1145  {
1146  return KAMA(symbol, period, 2, 30, resolution, selector);
1147  }
1148 
1149  /// <summary>
1150  /// Creates a new KaufmanAdaptiveMovingAverage indicator.
1151  /// </summary>
1152  /// <param name="symbol">The symbol whose KAMA we want</param>
1153  /// <param name="period">The period of the Efficiency Ratio (ER)</param>
1154  /// <param name="fastEmaPeriod">The period of the fast EMA used to calculate the Smoothing Constant (SC)</param>
1155  /// <param name="slowEmaPeriod">The period of the slow EMA used to calculate the Smoothing Constant (SC)</param>
1156  /// <param name="resolution">The resolution</param>
1157  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1158  /// <returns>The KaufmanAdaptiveMovingAverage indicator for the requested symbol over the specified period</returns>
1159  [DocumentationAttribute(Indicators)]
1160  public KaufmanAdaptiveMovingAverage KAMA(Symbol symbol, int period, int fastEmaPeriod, int slowEmaPeriod, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1161  {
1162  var name = CreateIndicatorName(symbol, $"KAMA({period},{fastEmaPeriod},{slowEmaPeriod})", resolution);
1163  var kaufmanAdaptiveMovingAverage = new KaufmanAdaptiveMovingAverage(name, period, fastEmaPeriod, slowEmaPeriod);
1164  InitializeIndicator(kaufmanAdaptiveMovingAverage, resolution, selector, symbol);
1165 
1166  return kaufmanAdaptiveMovingAverage;
1167  }
1168 
1169  /// <summary>
1170  /// Creates an KaufmanEfficiencyRatio indicator for the symbol. The indicator will be automatically
1171  /// updated on the given resolution.
1172  /// </summary>
1173  /// <param name="symbol">The symbol whose EF we want</param>
1174  /// <param name="period">The period of the EF</param>
1175  /// <param name="resolution">The resolution</param>
1176  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1177  /// <returns>The KaufmanEfficiencyRatio indicator for the given parameters</returns>
1178  [DocumentationAttribute(Indicators)]
1179  public KaufmanEfficiencyRatio KER(Symbol symbol, int period = 2, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1180  {
1181  var name = CreateIndicatorName(symbol, $"KER({period})", resolution);
1182  var kaufmanEfficiencyRatio = new KaufmanEfficiencyRatio(name, period);
1183  InitializeIndicator(kaufmanEfficiencyRatio, resolution, selector, symbol);
1184 
1185  return kaufmanEfficiencyRatio;
1186  }
1187 
1188  /// <summary>
1189  /// Creates a new Keltner Channels indicator.
1190  /// The indicator will be automatically updated on the given resolution.
1191  /// </summary>
1192  /// <param name="symbol">The symbol whose Keltner Channel we seek</param>
1193  /// <param name="period">The period over which to compute the Keltner Channels</param>
1194  /// <param name="k">The number of multiples of the <see cref="AverageTrueRange"/> from the middle band of the Keltner Channels</param>
1195  /// <param name="movingAverageType">Specifies the type of moving average to be used as the middle line of the Keltner Channel</param>
1196  /// <param name="resolution">The resolution.</param>
1197  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1198  /// <returns>The Keltner Channel indicator for the requested symbol.</returns>
1199  [DocumentationAttribute(Indicators)]
1200  public KeltnerChannels KCH(Symbol symbol, int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
1201  {
1202  var name = CreateIndicatorName(symbol, $"KCH({period},{k})", resolution);
1203  var keltnerChannels = new KeltnerChannels(name, period, k, movingAverageType);
1204  InitializeIndicator(keltnerChannels, resolution, selector, symbol);
1205 
1206  return keltnerChannels;
1207  }
1208 
1209  /// <summary>
1210  /// Creates a new LogReturn indicator.
1211  /// </summary>
1212  /// <param name="symbol">The symbol whose log return we seek</param>
1213  /// <param name="period">The period of the log return.</param>
1214  /// <param name="resolution">The resolution.</param>
1215  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar.</param>
1216  /// <returns>log return indicator for the requested symbol.</returns>
1217  [DocumentationAttribute(Indicators)]
1218  public LogReturn LOGR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1219  {
1220  var name = CreateIndicatorName(symbol, $"LOGR({period})", resolution);
1221  var logReturn = new LogReturn(name, period);
1222  InitializeIndicator(logReturn, resolution, selector, symbol);
1223 
1224  return logReturn;
1225  }
1226 
1227  /// <summary>
1228  /// Creates and registers a new Least Squares Moving Average instance.
1229  /// </summary>
1230  /// <param name="symbol">The symbol whose LSMA we seek.</param>
1231  /// <param name="period">The LSMA period. Normally 14.</param>
1232  /// <param name="resolution">The resolution.</param>
1233  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar.</param>
1234  /// <returns>A LeastSquaredMovingAverage configured with the specified period</returns>
1235  [DocumentationAttribute(Indicators)]
1236  public LeastSquaresMovingAverage LSMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1237  {
1238  var name = CreateIndicatorName(symbol, $"LSMA({period})", resolution);
1239  var leastSquaresMovingAverage = new LeastSquaresMovingAverage(name, period);
1240  InitializeIndicator(leastSquaresMovingAverage, resolution, selector, symbol);
1241 
1242  return leastSquaresMovingAverage;
1243  }
1244 
1245  /// <summary>
1246  /// Creates a new LinearWeightedMovingAverage indicator. This indicator will linearly distribute
1247  /// the weights across the periods.
1248  /// </summary>
1249  /// <param name="symbol">The symbol whose LWMA we want</param>
1250  /// <param name="period">The period over which to compute the LWMA</param>
1251  /// <param name="resolution">The resolution</param>
1252  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1253  /// <returns></returns>
1254  [DocumentationAttribute(Indicators)]
1255  public LinearWeightedMovingAverage LWMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1256  {
1257  var name = CreateIndicatorName(symbol, $"LWMA({period})", resolution);
1258  var linearWeightedMovingAverage = new LinearWeightedMovingAverage(name, period);
1259  InitializeIndicator(linearWeightedMovingAverage, resolution, selector, symbol);
1260 
1261  return linearWeightedMovingAverage;
1262  }
1263 
1264  /// <summary>
1265  /// Creates a MACD indicator for the symbol. The indicator will be automatically updated on the given resolution.
1266  /// </summary>
1267  /// <param name="symbol">The symbol whose MACD we want</param>
1268  /// <param name="fastPeriod">The period for the fast moving average</param>
1269  /// <param name="slowPeriod">The period for the slow moving average</param>
1270  /// <param name="signalPeriod">The period for the signal moving average</param>
1271  /// <param name="type">The type of moving average to use for the MACD</param>
1272  /// <param name="resolution">The resolution</param>
1273  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1274  /// <returns>The moving average convergence divergence between the fast and slow averages</returns>
1275  [DocumentationAttribute(Indicators)]
1276  public MovingAverageConvergenceDivergence MACD(Symbol symbol, int fastPeriod, int slowPeriod, int signalPeriod, MovingAverageType type = MovingAverageType.Exponential, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1277  {
1278  var name = CreateIndicatorName(symbol, $"MACD({fastPeriod},{slowPeriod},{signalPeriod})", resolution);
1279  var movingAverageConvergenceDivergence = new MovingAverageConvergenceDivergence(name, fastPeriod, slowPeriod, signalPeriod, type);
1280  InitializeIndicator(movingAverageConvergenceDivergence, resolution, selector, symbol);
1281 
1282  return movingAverageConvergenceDivergence;
1283  }
1284 
1285  /// <summary>
1286  /// Creates a new MeanAbsoluteDeviation indicator.
1287  /// </summary>
1288  /// <param name="symbol">The symbol whose MeanAbsoluteDeviation we want</param>
1289  /// <param name="period">The period over which to compute the MeanAbsoluteDeviation</param>
1290  /// <param name="resolution">The resolution</param>
1291  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1292  /// <returns>The MeanAbsoluteDeviation indicator for the requested symbol over the specified period</returns>
1293  [DocumentationAttribute(Indicators)]
1294  public MeanAbsoluteDeviation MAD(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1295  {
1296  var name = CreateIndicatorName(symbol, $"MAD({period})", resolution);
1297  var meanAbsoluteDeviation = new MeanAbsoluteDeviation(name, period);
1298  InitializeIndicator(meanAbsoluteDeviation, resolution, selector, symbol);
1299 
1300  return meanAbsoluteDeviation;
1301  }
1302 
1303  /// <summary>
1304  /// Creates a new Mesa Adaptive Moving Average (MAMA) indicator.
1305  /// The MAMA adjusts its smoothing factor based on the market's volatility, making it more adaptive than a simple moving average.
1306  /// </summary>
1307  /// <param name="symbol">The symbol for which the MAMA indicator is being created.</param>
1308  /// <param name="fastLimit">The fast limit for the adaptive moving average.</param>
1309  /// <param name="slowLimit">The slow limit for the adaptive moving average.</param>
1310  /// <param name="resolution">The resolution</param>
1311  /// <param name="selector">Optional function to select a value from the BaseData. Defaults to casting the input to a TradeBar.</param>
1312  /// <returns>The Mesa Adaptive Moving Average (MAMA) indicator for the requested symbol with the specified limits.</returns>
1313  [DocumentationAttribute(Indicators)]
1314  public MesaAdaptiveMovingAverage MAMA(Symbol symbol, decimal fastLimit = 0.5m, decimal slowLimit = 0.05m, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
1315  {
1316  var name = CreateIndicatorName(symbol, $"MAMA({fastLimit},{slowLimit})", resolution);
1317  var mesaAdaptiveMovingAverage = new MesaAdaptiveMovingAverage(name, fastLimit, slowLimit);
1318  InitializeIndicator(mesaAdaptiveMovingAverage, resolution, selector, symbol);
1319  return mesaAdaptiveMovingAverage;
1320  }
1321 
1322  /// <summary>
1323  /// Creates an Market Profile indicator for the symbol with Volume Profile (VOL) mode. The indicator will be automatically
1324  /// updated on the given resolution.
1325  /// </summary>
1326  /// <param name="symbol">The symbol whose VP we want</param>
1327  /// <param name="period">The period of the VP</param>
1328  /// <param name="valueAreaVolumePercentage">The percentage of volume contained in the value area</param>
1329  /// <param name="priceRangeRoundOff">How many digits you want to round and the precision. i.e 0.01 round to two digits exactly.</param>
1330  /// <param name="resolution">The resolution</param>
1331  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1332  /// <returns>The Volume Profile indicator for the given parameters</returns>
1333  [DocumentationAttribute(Indicators)]
1334  public VolumeProfile VP(Symbol symbol, int period = 2, decimal valueAreaVolumePercentage = 0.70m, decimal priceRangeRoundOff = 0.05m, Resolution resolution = Resolution.Daily, Func<IBaseData, TradeBar> selector = null)
1335  {
1336  var name = CreateIndicatorName(symbol, $"VP({period})", resolution);
1337  var marketProfile = new VolumeProfile(name, period, valueAreaVolumePercentage, priceRangeRoundOff);
1338  InitializeIndicator(marketProfile, resolution, selector, symbol);
1339 
1340  return marketProfile;
1341  }
1342 
1343  /// <summary>
1344  /// Creates an Market Profile indicator for the symbol with Time Price Opportunity (TPO) mode. The indicator will be automatically
1345  /// updated on the given resolution.
1346  /// </summary>
1347  /// <param name="symbol">The symbol whose TP we want</param>
1348  /// <param name="period">The period of the TP</param>
1349  /// <param name="valueAreaVolumePercentage">The percentage of volume contained in the value area</param>
1350  /// <param name="priceRangeRoundOff">How many digits you want to round and the precision. i.e 0.01 round to two digits exactly.</param>
1351  /// <param name="resolution">The resolution</param>
1352  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1353  /// <returns>The Time Profile indicator for the given parameters</returns>
1354  [DocumentationAttribute(Indicators)]
1355  public TimeProfile TP(Symbol symbol, int period = 2, decimal valueAreaVolumePercentage = 0.70m, decimal priceRangeRoundOff = 0.05m, Resolution resolution = Resolution.Daily, Func<IBaseData, TradeBar> selector = null)
1356  {
1357  var name = CreateIndicatorName(symbol, $"TP({period})", resolution);
1358  var marketProfile = new TimeProfile(name, period, valueAreaVolumePercentage, priceRangeRoundOff);
1359  InitializeIndicator(marketProfile, resolution, selector, symbol);
1360 
1361  return marketProfile;
1362  }
1363 
1364  /// <summary>
1365  /// Creates a new Time Series Forecast indicator
1366  /// </summary>
1367  /// <param name="symbol">The symbol whose TSF we want</param>
1368  /// <param name="period">The period of the TSF</param>
1369  /// <param name="resolution">The resolution</param>
1370  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to Value property of BaseData (x => x.Value)</param>
1371  /// <returns>The TimeSeriesForecast indicator for the requested symbol over the specified period</returns>
1372  [DocumentationAttribute(Indicators)]
1373  public TimeSeriesForecast TSF(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1374  {
1375  var name = CreateIndicatorName(symbol, $"TSF({period})", resolution);
1376  var timeSeriesForecast = new TimeSeriesForecast(name, period);
1377  InitializeIndicator(timeSeriesForecast, resolution, selector, symbol);
1378 
1379  return timeSeriesForecast;
1380  }
1381 
1382  /// <summary>
1383  /// Creates a new Maximum indicator to compute the maximum value
1384  /// </summary>
1385  /// <param name="symbol">The symbol whose max we want</param>
1386  /// <param name="period">The look back period over which to compute the max value</param>
1387  /// <param name="resolution">The resolution</param>
1388  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null and the symbol is of type TradeBar defaults to the High property,
1389  /// otherwise it defaults to Value property of BaseData (x => x.Value)</param>
1390  /// <returns>A Maximum indicator that compute the max value and the periods since the max value</returns>
1391  [DocumentationAttribute(Indicators)]
1392  public Maximum MAX(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1393  {
1394  var name = CreateIndicatorName(symbol, $"MAX({period})", resolution);
1395  var maximum = new Maximum(name, period);
1396 
1397  // assign a default value for the selector function
1398  if (selector == null)
1399  {
1400  var subscription = GetSubscription(symbol);
1401  if (typeof(TradeBar).IsAssignableFrom(subscription.Type))
1402  {
1403  // if we have trade bar data we'll use the High property, if not x => x.Value will be set in RegisterIndicator
1404  selector = x => ((TradeBar)x).High;
1405  }
1406  }
1407 
1408  InitializeIndicator(maximum, resolution, selector, symbol);
1409  return maximum;
1410  }
1411 
1412  /// <summary>
1413  /// Creates a new MoneyFlowIndex indicator. The indicator will be automatically
1414  /// updated on the given resolution.
1415  /// </summary>
1416  /// <param name="symbol">The symbol whose MFI we want</param>
1417  /// <param name="period">The period over which to compute the MFI</param>
1418  /// <param name="resolution">The resolution</param>
1419  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1420  /// <returns>The MoneyFlowIndex indicator for the requested symbol over the specified period</returns>
1421  [DocumentationAttribute(Indicators)]
1422  public MoneyFlowIndex MFI(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
1423  {
1424  var name = CreateIndicatorName(symbol, $"MFI({period})", resolution);
1425  var moneyFlowIndex = new MoneyFlowIndex(name, period);
1426  InitializeIndicator(moneyFlowIndex, resolution, selector, symbol);
1427 
1428  return moneyFlowIndex;
1429  }
1430 
1431  /// <summary>
1432  /// Creates a new Mass Index indicator. The indicator will be automatically
1433  /// updated on the given resolution.
1434  /// </summary>
1435  /// <param name="symbol">The symbol whose Mass Index we want.</param>
1436  /// <param name="emaPeriod">The period used by both EMA.</param>
1437  /// <param name="sumPeriod">The sum period.</param>
1438  /// <param name="resolution">The resolution.</param>
1439  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1440  /// <returns>The Mass Index indicator for the requested symbol over the specified period</returns>
1441  [DocumentationAttribute(Indicators)]
1442  public MassIndex MASS(Symbol symbol, int emaPeriod = 9, int sumPeriod = 25, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
1443  {
1444  var name = CreateIndicatorName(symbol, $"MASS({emaPeriod},{sumPeriod})", resolution);
1445  var massIndex = new MassIndex(name, emaPeriod, sumPeriod);
1446  InitializeIndicator(massIndex, resolution, selector, symbol);
1447 
1448  return massIndex;
1449  }
1450 
1451  /// <summary>
1452  /// Creates a new MidPoint indicator.
1453  /// </summary>
1454  /// <param name="symbol">The symbol whose MIDPOINT we want</param>
1455  /// <param name="period">The period over which to compute the MIDPOINT</param>
1456  /// <param name="resolution">The resolution</param>
1457  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1458  /// <returns>The MidPoint indicator for the requested symbol over the specified period</returns>
1459  [DocumentationAttribute(Indicators)]
1460  public MidPoint MIDPOINT(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1461  {
1462  var name = CreateIndicatorName(symbol, $"MIDPOINT({period})", resolution);
1463  var midPoint = new MidPoint(name, period);
1464  InitializeIndicator(midPoint, resolution, selector, symbol);
1465 
1466  return midPoint;
1467  }
1468 
1469  /// <summary>
1470  /// Creates a new MidPrice indicator.
1471  /// </summary>
1472  /// <param name="symbol">The symbol whose MIDPRICE we want</param>
1473  /// <param name="period">The period over which to compute the MIDPRICE</param>
1474  /// <param name="resolution">The resolution</param>
1475  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1476  /// <returns>The MidPrice indicator for the requested symbol over the specified period</returns>
1477  [DocumentationAttribute(Indicators)]
1478  public MidPrice MIDPRICE(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
1479  {
1480  var name = CreateIndicatorName(symbol, $"MIDPRICE({period})", resolution);
1481  var midPrice = new MidPrice(name, period);
1482  InitializeIndicator(midPrice, resolution, selector, symbol);
1483 
1484  return midPrice;
1485  }
1486 
1487  /// <summary>
1488  /// Creates a new Minimum indicator to compute the minimum value
1489  /// </summary>
1490  /// <param name="symbol">The symbol whose min we want</param>
1491  /// <param name="period">The look back period over which to compute the min value</param>
1492  /// <param name="resolution">The resolution</param>
1493  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null and the symbol is of type TradeBar defaults to the Low property,
1494  /// otherwise it defaults to Value property of BaseData (x => x.Value)</param>
1495  /// <returns>A Minimum indicator that compute the in value and the periods since the min value</returns>
1496  [DocumentationAttribute(Indicators)]
1497  public Minimum MIN(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1498  {
1499  var name = CreateIndicatorName(symbol, $"MIN({period})", resolution);
1500  var minimum = new Minimum(name, period);
1501 
1502  // assign a default value for the selector function
1503  if (selector == null)
1504  {
1505  var subscription = GetSubscription(symbol);
1506  if (typeof(TradeBar).IsAssignableFrom(subscription.Type))
1507  {
1508  // if we have trade bar data we'll use the Low property, if not x => x.Value will be set in RegisterIndicator
1509  selector = x => ((TradeBar)x).Low;
1510  }
1511  }
1512 
1513  InitializeIndicator(minimum, resolution, selector, symbol);
1514  return minimum;
1515  }
1516 
1517  /// <summary>
1518  /// Creates a new Momentum indicator. This will compute the absolute n-period change in the security.
1519  /// The indicator will be automatically updated on the given resolution.
1520  /// </summary>
1521  /// <param name="symbol">The symbol whose momentum we want</param>
1522  /// <param name="period">The period over which to compute the momentum</param>
1523  /// <param name="resolution">The resolution</param>
1524  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1525  /// <returns>The momentum indicator for the requested symbol over the specified period</returns>
1526  [DocumentationAttribute(Indicators)]
1527  public Momentum MOM(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1528  {
1529  var name = CreateIndicatorName(symbol, $"MOM({period})", resolution);
1530  var momentum = new Momentum(name, period);
1531  InitializeIndicator(momentum, resolution, selector, symbol);
1532 
1533  return momentum;
1534  }
1535 
1536  /// <summary>
1537  /// Creates a new Momersion indicator.
1538  /// </summary>
1539  /// <param name="symbol">The symbol whose Momersion we want</param>
1540  /// <param name="minPeriod">The minimum period over which to compute the Momersion. Must be greater than 3. If null, only full period will be used in computations.</param>
1541  /// <param name="fullPeriod">The full period over which to compute the Momersion</param>
1542  /// <param name="resolution">The resolution</param>
1543  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1544  /// <returns>The Momersion indicator for the requested symbol over the specified period</returns>
1545  [DocumentationAttribute(Indicators)]
1546  public MomersionIndicator MOMERSION(Symbol symbol, int? minPeriod, int fullPeriod, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1547  {
1548  var name = CreateIndicatorName(symbol, $"MOMERSION({minPeriod},{fullPeriod})", resolution);
1549  var momersion = new MomersionIndicator(name, minPeriod, fullPeriod);
1550  InitializeIndicator(momersion, resolution, selector, symbol);
1551 
1552  return momersion;
1553  }
1554 
1555  /// <summary>
1556  /// Creates a new MomentumPercent indicator. This will compute the n-period percent change in the security.
1557  /// The indicator will be automatically updated on the given resolution.
1558  /// </summary>
1559  /// <param name="symbol">The symbol whose momentum we want</param>
1560  /// <param name="period">The period over which to compute the momentum</param>
1561  /// <param name="resolution">The resolution</param>
1562  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1563  /// <returns>The momentum indicator for the requested symbol over the specified period</returns>
1564  [DocumentationAttribute(Indicators)]
1565  public MomentumPercent MOMP(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1566  {
1567  var name = CreateIndicatorName(symbol, $"MOMP({period})", resolution);
1568  var momentumPercent = new MomentumPercent(name, period);
1569  InitializeIndicator(momentumPercent, resolution, selector, symbol);
1570 
1571  return momentumPercent;
1572  }
1573 
1574  /// <summary>
1575  /// Creates a new NormalizedAverageTrueRange indicator.
1576  /// </summary>
1577  /// <param name="symbol">The symbol whose NATR we want</param>
1578  /// <param name="period">The period over which to compute the NATR</param>
1579  /// <param name="resolution">The resolution</param>
1580  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1581  /// <returns>The NormalizedAverageTrueRange indicator for the requested symbol over the specified period</returns>
1582  [DocumentationAttribute(Indicators)]
1583  public NormalizedAverageTrueRange NATR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
1584  {
1585  var name = CreateIndicatorName(symbol, $"NATR({period})", resolution);
1586  var normalizedAverageTrueRange = new NormalizedAverageTrueRange(name, period);
1587  InitializeIndicator(normalizedAverageTrueRange, resolution, selector, symbol);
1588 
1589  return normalizedAverageTrueRange;
1590  }
1591 
1592  /// <summary>
1593  /// Creates a new On Balance Volume indicator. This will compute the cumulative total volume
1594  /// based on whether the close price being higher or lower than the previous period.
1595  /// The indicator will be automatically updated on the given resolution.
1596  /// </summary>
1597  /// <param name="symbol">The symbol whose On Balance Volume we seek</param>
1598  /// <param name="resolution">The resolution.</param>
1599  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1600  /// <returns>The On Balance Volume indicator for the requested symbol.</returns>
1601  [DocumentationAttribute(Indicators)]
1602  public OnBalanceVolume OBV(Symbol symbol, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
1603  {
1604  var name = CreateIndicatorName(symbol, "OBV", resolution);
1605  var onBalanceVolume = new OnBalanceVolume(name);
1606  InitializeIndicator(onBalanceVolume, resolution, selector, symbol);
1607 
1608  return onBalanceVolume;
1609  }
1610 
1611  /// <summary>
1612  /// Creates a new PivotPointsHighLow indicator
1613  /// </summary>
1614  /// <param name="symbol">The symbol whose PPHL we seek</param>
1615  /// <param name="lengthHigh">The number of surrounding bars whose high values should be less than the current bar's for the bar high to be marked as high pivot point</param>
1616  /// <param name="lengthLow">The number of surrounding bars whose low values should be more than the current bar's for the bar low to be marked as low pivot point</param>
1617  /// <param name="lastStoredValues">The number of last stored indicator values</param>
1618  /// <param name="resolution">The resolution</param>
1619  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1620  /// <returns>The PivotPointsHighLow indicator for the requested symbol.</returns>
1621  [DocumentationAttribute(Indicators)]
1622  public PivotPointsHighLow PPHL(Symbol symbol, int lengthHigh, int lengthLow, int lastStoredValues = 100, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
1623  {
1624  var name = CreateIndicatorName(symbol, $"PPHL({lengthHigh},{lengthLow})", resolution);
1625  var pivotPointsHighLow = new PivotPointsHighLow(name, lengthHigh, lengthLow, lastStoredValues);
1626  InitializeIndicator(pivotPointsHighLow, resolution, selector, symbol);
1627 
1628  return pivotPointsHighLow;
1629  }
1630 
1631  /// <summary>
1632  /// Creates a new PercentagePriceOscillator indicator.
1633  /// </summary>
1634  /// <param name="symbol">The symbol whose PPO we want</param>
1635  /// <param name="fastPeriod">The fast moving average period</param>
1636  /// <param name="slowPeriod">The slow moving average period</param>
1637  /// <param name="movingAverageType">The type of moving average to use</param>
1638  /// <param name="resolution">The resolution</param>
1639  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1640  /// <returns>The PercentagePriceOscillator indicator for the requested symbol over the specified period</returns>
1641  [DocumentationAttribute(Indicators)]
1642  public PercentagePriceOscillator PPO(Symbol symbol, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1643  {
1644  var name = CreateIndicatorName(symbol, $"PPO({fastPeriod},{slowPeriod})", resolution);
1645  var percentagePriceOscillator = new PercentagePriceOscillator(name, fastPeriod, slowPeriod, movingAverageType);
1646  InitializeIndicator(percentagePriceOscillator, resolution, selector, symbol);
1647 
1648  return percentagePriceOscillator;
1649  }
1650 
1651  /// <summary>
1652  /// Creates a new Parabolic SAR indicator
1653  /// </summary>
1654  /// <param name="symbol">The symbol whose PSAR we seek</param>
1655  /// <param name="afStart">Acceleration factor start value. Normally 0.02</param>
1656  /// <param name="afIncrement">Acceleration factor increment value. Normally 0.02</param>
1657  /// <param name="afMax">Acceleration factor max value. Normally 0.2</param>
1658  /// <param name="resolution">The resolution</param>
1659  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1660  /// <returns>A ParabolicStopAndReverse configured with the specified periods</returns>
1661  [DocumentationAttribute(Indicators)]
1662  public ParabolicStopAndReverse PSAR(Symbol symbol, decimal afStart = 0.02m, decimal afIncrement = 0.02m, decimal afMax = 0.2m, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
1663  {
1664  var name = CreateIndicatorName(symbol, $"PSAR({afStart},{afIncrement},{afMax})", resolution);
1665  var parabolicStopAndReverse = new ParabolicStopAndReverse(name, afStart, afIncrement, afMax);
1666  InitializeIndicator(parabolicStopAndReverse, resolution, selector, symbol);
1667 
1668  return parabolicStopAndReverse;
1669  }
1670 
1671  /// <summary>
1672  /// Creates a new RegressionChannel indicator which will compute the LinearRegression, UpperChannel and LowerChannel lines, the intercept and slope
1673  /// </summary>
1674  /// <param name="symbol">The symbol whose RegressionChannel we seek</param>
1675  /// <param name="period">The period of the standard deviation and least square moving average (linear regression line)</param>
1676  /// <param name="k">The number of standard deviations specifying the distance between the linear regression and upper or lower channel lines</param>
1677  /// <param name="resolution">The resolution</param>
1678  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1679  /// <returns>A Regression Channel configured with the specified period and number of standard deviation</returns>
1680  [DocumentationAttribute(Indicators)]
1681  public RegressionChannel RC(Symbol symbol, int period, decimal k, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1682  {
1683  var name = CreateIndicatorName(symbol, $"RC({period},{k})", resolution);
1684  var regressionChannel = new RegressionChannel(name, period, k);
1685  InitializeIndicator(regressionChannel, resolution, selector, symbol);
1686 
1687  return regressionChannel;
1688  }
1689 
1690  /// <summary>
1691  /// Creates a new Relative Moving Average indicator for the symbol. The indicator will be automatically updated on the given resolution.
1692  /// </summary>
1693  /// <param name="symbol">The symbol whose relative moving average we seek</param>
1694  /// <param name="period">The period of the relative moving average</param>
1695  /// <param name="resolution">The resolution</param>
1696  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1697  /// <returns>A relative moving average configured with the specified period and number of standard deviation</returns>
1698  [DocumentationAttribute(Indicators)]
1699  public RelativeMovingAverage RMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1700  {
1701  var name = CreateIndicatorName(symbol, $"RMA({period})", resolution);
1702  var relativeMovingAverage = new RelativeMovingAverage(name, period);
1703  InitializeIndicator(relativeMovingAverage, resolution, selector, symbol);
1704 
1705  return relativeMovingAverage;
1706  }
1707 
1708 
1709  /// <summary>
1710  /// Creates a new RateOfChange indicator. This will compute the n-period rate of change in the security.
1711  /// The indicator will be automatically updated on the given resolution.
1712  /// </summary>
1713  /// <param name="symbol">The symbol whose RateOfChange we want</param>
1714  /// <param name="period">The period over which to compute the RateOfChange</param>
1715  /// <param name="resolution">The resolution</param>
1716  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1717  /// <returns>The RateOfChange indicator for the requested symbol over the specified period</returns>
1718  [DocumentationAttribute(Indicators)]
1719  public RateOfChange ROC(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1720  {
1721  var name = CreateIndicatorName(symbol, $"ROC({period})", resolution);
1722  var rateOfChange = new RateOfChange(name, period);
1723  InitializeIndicator(rateOfChange, resolution, selector, symbol);
1724 
1725  return rateOfChange;
1726  }
1727 
1728  /// <summary>
1729  /// Creates a new RateOfChangePercent indicator. This will compute the n-period percentage rate of change in the security.
1730  /// The indicator will be automatically updated on the given resolution.
1731  /// </summary>
1732  /// <param name="symbol">The symbol whose RateOfChangePercent we want</param>
1733  /// <param name="period">The period over which to compute the RateOfChangePercent</param>
1734  /// <param name="resolution">The resolution</param>
1735  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1736  /// <returns>The RateOfChangePercent indicator for the requested symbol over the specified period</returns>
1737  [DocumentationAttribute(Indicators)]
1738  public RateOfChangePercent ROCP(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1739  {
1740  var name = CreateIndicatorName(symbol, $"ROCP({period})", resolution);
1741  var rateOfChangePercent = new RateOfChangePercent(name, period);
1742  InitializeIndicator(rateOfChangePercent, resolution, selector, symbol);
1743 
1744  return rateOfChangePercent;
1745  }
1746 
1747  /// <summary>
1748  /// Creates a new RateOfChangeRatio indicator.
1749  /// </summary>
1750  /// <param name="symbol">The symbol whose ROCR we want</param>
1751  /// <param name="period">The period over which to compute the ROCR</param>
1752  /// <param name="resolution">The resolution</param>
1753  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1754  /// <returns>The RateOfChangeRatio indicator for the requested symbol over the specified period</returns>
1755  [DocumentationAttribute(Indicators)]
1756  public RateOfChangeRatio ROCR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1757  {
1758  var name = CreateIndicatorName(symbol, $"ROCR({period})", resolution);
1759  var rateOfChangeRatio = new RateOfChangeRatio(name, period);
1760  InitializeIndicator(rateOfChangeRatio, resolution, selector, symbol);
1761 
1762  return rateOfChangeRatio;
1763  }
1764 
1765  /// <summary>
1766  /// Creates a new RelativeStrengthIndex indicator. This will produce an oscillator that ranges from 0 to 100 based
1767  /// on the ratio of average gains to average losses over the specified period.
1768  /// </summary>
1769  /// <param name="symbol">The symbol whose RSI we want</param>
1770  /// <param name="period">The period over which to compute the RSI</param>
1771  /// <param name="movingAverageType">The type of moving average to use in computing the average gain/loss values</param>
1772  /// <param name="resolution">The resolution</param>
1773  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1774  /// <returns>The RelativeStrengthIndex indicator for the requested symbol over the specified period</returns>
1775  [DocumentationAttribute(Indicators)]
1776  public RelativeStrengthIndex RSI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Wilders, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1777  {
1778  var name = CreateIndicatorName(symbol, $"RSI({period},{movingAverageType})", resolution);
1779  var relativeStrengthIndex = new RelativeStrengthIndex(name, period, movingAverageType);
1780  InitializeIndicator(relativeStrengthIndex, resolution, selector, symbol);
1781 
1782  return relativeStrengthIndex;
1783  }
1784 
1785  /// <summary>
1786  /// Creates a new RelativeVigorIndex indicator.
1787  /// </summary>
1788  /// <param name="symbol">The symbol whose RVI we want</param>
1789  /// <param name="period">The period over which to compute the RVI</param>
1790  /// <param name="movingAverageType">The type of moving average to use</param>
1791  /// <param name="resolution">The resolution</param>
1792  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1793  /// <returns>The RelativeVigorIndex indicator for the requested symbol over the specified period</returns>
1794  [DocumentationAttribute(Indicators)]
1795  public RelativeVigorIndex RVI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
1796  {
1797  var name = CreateIndicatorName(symbol, $"RVI({period},{movingAverageType})", resolution);
1798  var relativeVigorIndex = new RelativeVigorIndex(name, period, movingAverageType);
1799  InitializeIndicator(relativeVigorIndex, resolution, selector, symbol);
1800 
1801  return relativeVigorIndex;
1802  }
1803 
1804  /// <summary>
1805  /// Creates an RelativeDailyVolume indicator for the symbol. The indicator will be automatically
1806  /// updated on the given resolution.
1807  /// </summary>
1808  /// <param name="symbol">The symbol whose RDV we want</param>
1809  /// <param name="period">The period of the RDV</param>
1810  /// <param name="resolution">The resolution</param>
1811  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1812  /// <returns>The Relative Volume indicator for the given parameters</returns>
1813  [DocumentationAttribute(Indicators)]
1814  public RelativeDailyVolume RDV(Symbol symbol, int period = 2, Resolution resolution = Resolution.Daily, Func<IBaseData, TradeBar> selector = null)
1815  {
1816  var name = CreateIndicatorName(symbol, $"RDV({period})", resolution);
1817  var relativeDailyVolume = new RelativeDailyVolume(name, period);
1818  RegisterIndicator(symbol, relativeDailyVolume, resolution, selector);
1819 
1820  return relativeDailyVolume;
1821  }
1822 
1823  /// <summary>
1824  /// Creates a new Rho indicator for the symbol The indicator will be automatically
1825  /// updated on the symbol's subscription resolution
1826  /// </summary>
1827  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
1828  /// <param name="mirrorOption">The mirror option for parity calculation</param>
1829  /// <param name="riskFreeRate">The risk free rate</param>
1830  /// <param name="dividendYield">The dividend yield</param>
1831  /// <param name="optionModel">The option pricing model used to estimate Rho</param>
1832  /// <param name="ivModel">The option pricing model used to estimate IV</param>
1833  /// <param name="resolution">The desired resolution of the data</param>
1834  /// <returns>A new Rho indicator for the specified symbol</returns>
1835  [DocumentationAttribute(Indicators)]
1836  public Rho R(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null,
1837  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null, Resolution? resolution = null)
1838  {
1839  var name = InitializeOptionIndicator<Rho>(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution);
1840 
1841  var rho = new Rho(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel);
1842  InitializeOptionIndicator(rho, resolution, symbol, mirrorOption);
1843  return rho;
1844  }
1845 
1846  /// <summary>
1847  /// Creates a new Rho indicator for the symbol The indicator will be automatically
1848  /// updated on the symbol's subscription resolution
1849  /// </summary>
1850  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
1851  /// <param name="mirrorOption">The mirror option for parity calculation</param>
1852  /// <param name="riskFreeRate">The risk free rate</param>
1853  /// <param name="dividendYield">The dividend yield</param>
1854  /// <param name="optionModel">The option pricing model used to estimate Rho</param>
1855  /// <param name="ivModel">The option pricing model used to estimate IV</param>
1856  /// <param name="resolution">The desired resolution of the data</param>
1857  /// <returns>A new Rho indicator for the specified symbol</returns>
1858  [DocumentationAttribute(Indicators)]
1859  public Rho ρ(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes,
1860  OptionPricingModelType? ivModel = null, Resolution? resolution = null)
1861  {
1862  return R(symbol, mirrorOption, riskFreeRate, dividendYield, optionModel, ivModel, resolution);
1863  }
1864 
1865 
1866  /// <summary>
1867  /// Creates a new Stochastic RSI indicator which will compute the %K and %D
1868  /// </summary>
1869  /// <param name="symbol">The symbol whose Stochastic RSI we seek</param>
1870  /// <param name="rsiPeriod">The period of the relative strength index</param>
1871  /// <param name="stochPeriod">The period of the stochastic indicator</param>
1872  /// <param name="kSmoothingPeriod">The smoothing period of K output</param>
1873  /// <param name="dSmoothingPeriod">The smoothing period of D output</param>
1874  /// <param name="movingAverageType">The type of moving average to be used</param>
1875  /// <param name="resolution">The resolution</param>
1876  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1877  /// <returns>A StochasticRelativeStrengthIndex configured with the specified periods and moving average type</returns>
1878  [DocumentationAttribute(Indicators)]
1879  public StochasticRelativeStrengthIndex SRSI(Symbol symbol, int rsiPeriod, int stochPeriod, int kSmoothingPeriod, int dSmoothingPeriod, MovingAverageType movingAverageType = MovingAverageType.Simple,
1880  Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1881  {
1882  var name = CreateIndicatorName(symbol, $"SRSI({rsiPeriod},{stochPeriod},{kSmoothingPeriod},{dSmoothingPeriod})", resolution);
1883  var indicator = new StochasticRelativeStrengthIndex(name, rsiPeriod, stochPeriod, kSmoothingPeriod, dSmoothingPeriod, movingAverageType);
1884  InitializeIndicator(indicator, resolution, selector, symbol);
1885  return indicator;
1886  }
1887 
1888  /// <summary>
1889  /// Creates a new SuperTrend indicator.
1890  /// </summary>
1891  /// <param name="symbol">The symbol whose SuperTrend indicator we want.</param>
1892  /// <param name="period">The smoothing period for average true range.</param>
1893  /// <param name="multiplier">Multiplier to calculate basic upper and lower bands width.</param>
1894  /// <param name="movingAverageType">Smoother type for average true range, defaults to Wilders.</param>
1895  /// <param name="resolution">The resolution.</param>
1896  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
1897  [DocumentationAttribute(Indicators)]
1898  public SuperTrend STR(Symbol symbol, int period, decimal multiplier, MovingAverageType movingAverageType = MovingAverageType.Wilders,
1899  Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
1900  {
1901  var name = CreateIndicatorName(symbol, $"STR({period},{multiplier})", resolution);
1902  var strend = new SuperTrend(name, period, multiplier, movingAverageType);
1903  InitializeIndicator(strend, resolution, selector, symbol);
1904 
1905  return strend;
1906  }
1907 
1908  /// <summary>
1909  /// Creates a new SharpeRatio indicator.
1910  /// </summary>
1911  /// <param name="symbol">The symbol whose RSR we want</param>
1912  /// <param name="sharpePeriod">Period of historical observation for sharpe ratio calculation</param>
1913  /// <param name="riskFreeRate">
1914  /// Risk-free rate for sharpe ratio calculation. If not specified, it will use the algorithms' <see cref="RiskFreeInterestRateModel"/>
1915  /// </param>
1916  /// <param name="resolution">The resolution</param>
1917  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1918  /// <returns>The SharpeRatio indicator for the requested symbol over the specified period</returns>
1919  [DocumentationAttribute(Indicators)]
1920  public SharpeRatio SR(Symbol symbol, int sharpePeriod, decimal? riskFreeRate = null, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1921  {
1922  var baseBame = riskFreeRate.HasValue ? $"SR({sharpePeriod},{riskFreeRate})" : $"SR({sharpePeriod})";
1923  var name = CreateIndicatorName(symbol, baseBame, resolution);
1924  IRiskFreeInterestRateModel riskFreeRateModel = riskFreeRate.HasValue
1925  ? new ConstantRiskFreeRateInterestRateModel(riskFreeRate.Value)
1926  // Make it a function so it's lazily evaluated: SetRiskFreeInterestRateModel can be called after this method
1928  var sharpeRatio = new SharpeRatio(name, sharpePeriod, riskFreeRateModel);
1929  InitializeIndicator(sharpeRatio, resolution, selector, symbol);
1930 
1931  return sharpeRatio;
1932  }
1933 
1934  /// <summary>
1935  /// Creates a new Sortino indicator.
1936  /// </summary>
1937  /// <param name="symbol">The symbol whose Sortino we want</param>
1938  /// <param name="sortinoPeriod">Period of historical observation for Sortino ratio calculation</param>
1939  /// <param name="minimumAcceptableReturn">Minimum acceptable return (eg risk-free rate) for the Sortino ratio calculation</param>
1940  /// <param name="resolution">The resolution</param>
1941  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1942  /// <returns>The SortinoRatio indicator for the requested symbol over the specified period</returns>
1943  [DocumentationAttribute(Indicators)]
1944  public SortinoRatio SORTINO(Symbol symbol, int sortinoPeriod, double minimumAcceptableReturn = 0.0, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1945  {
1946  var name = CreateIndicatorName(symbol, $"SORTINO({sortinoPeriod},{minimumAcceptableReturn})", resolution);
1947  var sortinoRatio = new SortinoRatio(name, sortinoPeriod, minimumAcceptableReturn);
1948  InitializeIndicator(sortinoRatio, resolution, selector, symbol);
1949 
1950  return sortinoRatio;
1951  }
1952 
1953  /// <summary>
1954  /// Creates a Squeeze Momentum indicator to identify market squeezes and potential breakouts.
1955  /// Compares Bollinger Bands and Keltner Channels to signal low or high volatility periods.
1956  /// </summary>
1957  /// <param name="symbol">The symbol for which the indicator is calculated.</param>
1958  /// <param name="bollingerPeriod">The period for Bollinger Bands.</param>
1959  /// <param name="bollingerMultiplier">The multiplier for the Bollinger Bands' standard deviation.</param>
1960  /// <param name="keltnerPeriod">The period for Keltner Channels.</param>
1961  /// <param name="keltnerMultiplier">The multiplier for the Average True Range in Keltner Channels.</param>
1962  /// <param name="resolution">The resolution of the data.</param>
1963  /// <param name="selector">Selects a value from the BaseData to send into the indicator. If null, defaults to the Value property of BaseData (x => x.Value).</param>
1964  /// <returns>The configured Squeeze Momentum indicator.</returns>
1965  [DocumentationAttribute(Indicators)]
1966  public SqueezeMomentum SM(Symbol symbol, int bollingerPeriod = 20, decimal bollingerMultiplier = 2m, int keltnerPeriod = 20,
1967  decimal keltnerMultiplier = 1.5m, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
1968  {
1969  var name = CreateIndicatorName(symbol, $"SM({bollingerPeriod}, {bollingerMultiplier}, {keltnerPeriod}, {keltnerMultiplier})", resolution);
1970  var squeezeMomentum = new SqueezeMomentum(name, bollingerPeriod, bollingerMultiplier, keltnerPeriod, keltnerMultiplier);
1971  InitializeIndicator(squeezeMomentum, resolution, selector, symbol);
1972  return squeezeMomentum;
1973  }
1974 
1975  /// <summary>
1976  /// Creates an SimpleMovingAverage indicator for the symbol. The indicator will be automatically
1977  /// updated on the given resolution.
1978  /// </summary>
1979  /// <param name="symbol">The symbol whose SMA we want</param>
1980  /// <param name="period">The period of the SMA</param>
1981  /// <param name="resolution">The resolution</param>
1982  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
1983  /// <returns>The SimpleMovingAverage for the given parameters</returns>
1984  [DocumentationAttribute(Indicators)]
1985  public SimpleMovingAverage SMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1986  {
1987  var name = CreateIndicatorName(symbol, $"SMA({period})", resolution);
1988  var simpleMovingAverage = new SimpleMovingAverage(name, period);
1989  InitializeIndicator(simpleMovingAverage, resolution, selector, symbol);
1990 
1991  return simpleMovingAverage;
1992  }
1993 
1994 
1995  /// <summary>
1996  /// Creates a new Schaff Trend Cycle indicator
1997  /// </summary>
1998  /// <param name="symbol">The symbol for the indicator to track</param>
1999  /// <param name="fastPeriod">The fast moving average period</param>
2000  /// <param name="slowPeriod">The slow moving average period</param>
2001  /// <param name="cyclePeriod">The signal period</param>
2002  /// <param name="movingAverageType">The type of moving average to use</param>
2003  /// <param name="resolution">The resolution</param>
2004  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2005  /// <returns>The SchaffTrendCycle indicator for the requested symbol over the specified period</returns>
2006  [DocumentationAttribute(Indicators)]
2007  public SchaffTrendCycle STC(Symbol symbol, int cyclePeriod, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType = MovingAverageType.Exponential, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2008  {
2009  var name = CreateIndicatorName(symbol, $"STC({cyclePeriod},{fastPeriod},{slowPeriod})", resolution);
2010  var schaffTrendCycle = new SchaffTrendCycle(name, cyclePeriod, fastPeriod, slowPeriod, movingAverageType);
2011  InitializeIndicator(schaffTrendCycle, resolution, selector, symbol);
2012 
2013  return schaffTrendCycle;
2014  }
2015 
2016  /// <summary>
2017  /// Creates a new SmoothedOnBalanceVolume indicator for the symbol. The indicator will be automatically
2018  /// updated on the given resolution.
2019  /// </summary>
2020  /// <param name="symbol">The symbol whose SmoothedOnBalanceVolume we want</param>
2021  /// <param name="period">The smoothing period used to smooth the computed OnBalanceVolume values</param>
2022  /// <param name="type">The type of smoothing to use</param>
2023  /// <param name="resolution">The resolution</param>
2024  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2025  /// <returns>A new SmoothedOnBalanceVolume indicator with the specified smoothing type and period</returns>
2026  [DocumentationAttribute(Indicators)]
2027  public SmoothedOnBalanceVolume SOBV(Symbol symbol, int period, MovingAverageType type = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
2028  {
2029  var name = CreateIndicatorName(symbol, $"SOBV({period})", resolution);
2030  var indicator = new SmoothedOnBalanceVolume(name, period, type);
2031  InitializeIndicator(indicator, resolution, selector, symbol);
2032  return indicator;
2033  }
2034 
2035  /// <summary>
2036  /// Creates a new StandardDeviation indicator. This will return the population standard deviation of samples over the specified period.
2037  /// </summary>
2038  /// <param name="symbol">The symbol whose STD we want</param>
2039  /// <param name="period">The period over which to compute the STD</param>
2040  /// <param name="resolution">The resolution</param>
2041  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2042  /// <returns>The StandardDeviation indicator for the requested symbol over the specified period</returns>
2043  [DocumentationAttribute(Indicators)]
2044  public StandardDeviation STD(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2045  {
2046  var name = CreateIndicatorName(symbol, $"STD({period})", resolution);
2047  var standardDeviation = new StandardDeviation(name, period);
2048  InitializeIndicator(standardDeviation, resolution, selector, symbol);
2049 
2050  return standardDeviation;
2051  }
2052 
2053  /// <summary>
2054  /// Creates a new TargetDownsideDeviation indicator. The target downside deviation is defined as the root-mean-square, or RMS, of the deviations of the
2055  /// realized return’s underperformance from the target return where all returns above the target return are treated as underperformance of 0.
2056  /// </summary>
2057  /// <param name="symbol">The symbol whose TDD we want</param>
2058  /// <param name="period">The period over which to compute the TDD</param>
2059  /// <param name="resolution">The resolution</param>
2060  /// <param name="minimumAcceptableReturn">Minimum acceptable return (MAR) for the target downside deviation calculation</param>
2061  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2062  /// <returns>The TargetDownsideDeviation indicator for the requested symbol over the specified period</returns>
2063  [DocumentationAttribute(Indicators)]
2064  public TargetDownsideDeviation TDD(Symbol symbol, int period, double minimumAcceptableReturn = 0, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2065  {
2066  var name = CreateIndicatorName(symbol, $"TDD({period},{minimumAcceptableReturn})", resolution);
2067  var targetDownsideDeviation = new TargetDownsideDeviation(name, period, minimumAcceptableReturn);
2068  InitializeIndicator(targetDownsideDeviation, resolution, selector, symbol);
2069 
2070  return targetDownsideDeviation;
2071  }
2072 
2073  /// <summary>
2074  /// Creates a new Stochastic indicator.
2075  /// </summary>
2076  /// <param name="symbol">The symbol whose stochastic we seek</param>
2077  /// <param name="period">The period of the stochastic. Normally 14</param>
2078  /// <param name="kPeriod">The sum period of the stochastic. Normally 14</param>
2079  /// <param name="dPeriod">The sum period of the stochastic. Normally 3</param>
2080  /// <param name="resolution">The resolution.</param>
2081  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2082  /// <returns>Stochastic indicator for the requested symbol.</returns>
2083  [DocumentationAttribute(Indicators)]
2084  public Stochastic STO(Symbol symbol, int period, int kPeriod, int dPeriod, Resolution? resolution = null,
2085  Func<IBaseData, TradeBar> selector = null)
2086  {
2087  var name = CreateIndicatorName(symbol, $"STO({period},{kPeriod},{dPeriod})", resolution);
2088  var stochastic = new Stochastic(name, period, kPeriod, dPeriod);
2089  InitializeIndicator(stochastic, resolution, selector, symbol);
2090 
2091  return stochastic;
2092  }
2093 
2094  /// <summary>
2095  /// Overload short hand to create a new Stochastic indicator; defaulting to the 3 period for dStoch
2096  /// </summary>
2097  /// <param name="symbol">The symbol whose stochastic we seek</param>
2098  /// <param name="resolution">The resolution.</param>
2099  /// <param name="period">The period of the stochastic. Normally 14</param>
2100  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2101  /// <returns>Stochastic indicator for the requested symbol.</returns>
2102  [DocumentationAttribute(Indicators)]
2103  public Stochastic STO(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2104  {
2105  return STO(symbol, period, period, 3, resolution, selector);
2106  }
2107 
2108  /// <summary>
2109  /// Creates a new instance of the Premier Stochastic Oscillator for the specified symbol.
2110  /// </summary>
2111  /// <param name="symbol">The symbol for which the stochastic indicator is being calculated.</param>
2112  /// <param name="period">The period for calculating the Stochastic K value.</param>
2113  /// <param name="emaPeriod">The period for the Exponential Moving Average (EMA) used to smooth the Stochastic K.</param>
2114  /// <param name="resolution">The data resolution (e.g., daily, hourly) for the indicator</param>
2115  /// <param name="selector">Optional function to select a value from the BaseData. Defaults to casting the input to a TradeBar.</param>
2116  /// <returns>A PremierStochasticOscillator instance for the specified symbol.</returns>
2117  [DocumentationAttribute(Indicators)]
2118  public PremierStochasticOscillator PSO(Symbol symbol, int period, int emaPeriod, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2119  {
2120  var name = CreateIndicatorName(symbol, $"PSO({period},{emaPeriod})", resolution);
2121  var premierStochasticOscillator = new PremierStochasticOscillator(name, period, emaPeriod);
2122  InitializeIndicator(premierStochasticOscillator, resolution, selector, symbol);
2123  return premierStochasticOscillator;
2124  }
2125 
2126  /// <summary>
2127  /// Creates a new Sum indicator.
2128  /// </summary>
2129  /// <param name="symbol">The symbol whose Sum we want</param>
2130  /// <param name="period">The period over which to compute the Sum</param>
2131  /// <param name="resolution">The resolution</param>
2132  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2133  /// <returns>The Sum indicator for the requested symbol over the specified period</returns>
2134  [DocumentationAttribute(Indicators)]
2135  public Sum SUM(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2136  {
2137  var name = CreateIndicatorName(symbol, $"SUM({period})", resolution);
2138  var sum = new Sum(name, period);
2139  InitializeIndicator(sum, resolution, selector, symbol);
2140 
2141  return sum;
2142  }
2143 
2144  /// <summary>
2145  /// Creates Swiss Army Knife transformation for the symbol. The indicator will be automatically
2146  /// updated on the given resolution.
2147  /// </summary>
2148  /// <param name="symbol">The symbol to use for calculations</param>
2149  /// <param name="period">The period of the calculation</param>
2150  /// <param name="delta">The delta scale of the BandStop or BandPass</param>
2151  /// <param name="tool">The tool os the Swiss Army Knife</param>
2152  /// <param name="resolution">The resolution</param>
2153  /// <param name="selector">elects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2154  /// <returns>The calculation using the given tool</returns>
2155  [DocumentationAttribute(Indicators)]
2156  public SwissArmyKnife SWISS(Symbol symbol, int period, double delta, SwissArmyKnifeTool tool, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2157  {
2158  var name = CreateIndicatorName(symbol, $"SWISS({period},{delta},{tool})", resolution);
2159  var swissArmyKnife = new SwissArmyKnife(name, period, delta, tool);
2160  InitializeIndicator(swissArmyKnife, resolution, selector, symbol);
2161 
2162  return swissArmyKnife;
2163  }
2164 
2165  /// <summary>
2166  /// Creates a new Theta indicator for the symbol The indicator will be automatically
2167  /// updated on the symbol's subscription resolution
2168  /// </summary>
2169  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
2170  /// <param name="mirrorOption">The mirror option for parity calculation</param>
2171  /// <param name="riskFreeRate">The risk free rate</param>
2172  /// <param name="dividendYield">The dividend yield</param>
2173  /// <param name="optionModel">The option pricing model used to estimate Theta</param>
2174  /// <param name="ivModel">The option pricing model used to estimate IV</param>
2175  /// <param name="resolution">The desired resolution of the data</param>
2176  /// <returns>A new Theta indicator for the specified symbol</returns>
2177  [DocumentationAttribute(Indicators)]
2178  public Theta T(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null,
2179  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null, Resolution? resolution = null)
2180  {
2181  var name = InitializeOptionIndicator<Theta>(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution);
2182 
2183  var theta = new Theta(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel);
2184  InitializeOptionIndicator(theta, resolution, symbol, mirrorOption);
2185  return theta;
2186  }
2187 
2188  /// <summary>
2189  /// Creates a new Theta indicator for the symbol The indicator will be automatically
2190  /// updated on the symbol's subscription resolution
2191  /// </summary>
2192  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
2193  /// <param name="mirrorOption">The mirror option for parity calculation</param>
2194  /// <param name="riskFreeRate">The risk free rate</param>
2195  /// <param name="dividendYield">The dividend yield</param>
2196  /// <param name="optionModel">The option pricing model used to estimate Theta</param>
2197  /// <param name="ivModel">The option pricing model used to estimate IV</param>
2198  /// <param name="resolution">The desired resolution of the data</param>
2199  /// <returns>A new Theta indicator for the specified symbol</returns>
2200  [DocumentationAttribute(Indicators)]
2201  public Theta Θ(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes,
2202  OptionPricingModelType? ivModel = null, Resolution? resolution = null)
2203  {
2204  return T(symbol, mirrorOption, riskFreeRate, dividendYield, optionModel, ivModel, resolution);
2205  }
2206 
2207  /// <summary>
2208  /// Creates a new T3MovingAverage indicator.
2209  /// </summary>
2210  /// <param name="symbol">The symbol whose T3 we want</param>
2211  /// <param name="period">The period over which to compute the T3</param>
2212  /// <param name="volumeFactor">The volume factor to be used for the T3 (value must be in the [0,1] range, defaults to 0.7)</param>
2213  /// <param name="resolution">The resolution</param>
2214  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2215  /// <returns>The T3MovingAverage indicator for the requested symbol over the specified period</returns>
2216  [DocumentationAttribute(Indicators)]
2217  public T3MovingAverage T3(Symbol symbol, int period, decimal volumeFactor = 0.7m, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2218  {
2219  var name = CreateIndicatorName(symbol, $"T3({period},{volumeFactor})", resolution);
2220  var t3MovingAverage = new T3MovingAverage(name, period, volumeFactor);
2221  InitializeIndicator(t3MovingAverage, resolution, selector, symbol);
2222 
2223  return t3MovingAverage;
2224  }
2225 
2226  /// <summary>
2227  /// Creates a new TripleExponentialMovingAverage indicator.
2228  /// </summary>
2229  /// <param name="symbol">The symbol whose TEMA we want</param>
2230  /// <param name="period">The period over which to compute the TEMA</param>
2231  /// <param name="resolution">The resolution</param>
2232  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2233  /// <returns>The TripleExponentialMovingAverage indicator for the requested symbol over the specified period</returns>
2234  [DocumentationAttribute(Indicators)]
2235  public TripleExponentialMovingAverage TEMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2236  {
2237  var name = CreateIndicatorName(symbol, $"TEMA({period})", resolution);
2238  var tripleExponentialMovingAverage = new TripleExponentialMovingAverage(name, period);
2239  InitializeIndicator(tripleExponentialMovingAverage, resolution, selector, symbol);
2240 
2241  return tripleExponentialMovingAverage;
2242  }
2243 
2244  /// <summary>
2245  /// Creates a TrueStrengthIndex indicator for the symbol. The indicator will be automatically
2246  /// updated on the given resolution.
2247  /// </summary>
2248  /// <param name="symbol">The symbol whose TSI we want</param>
2249  /// <param name="shortTermPeriod">Period used for the first price change smoothing</param>
2250  /// <param name="longTermPeriod">Period used for the second (double) price change smoothing</param>
2251  /// <param name="signalPeriod">The signal period</param>
2252  /// <param name="signalType">The type of moving average to use for the signal</param>
2253  /// <param name="resolution">The resolution</param>
2254  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2255  /// <returns>The TrueStrengthIndex indicator for the given parameters</returns>
2256  [DocumentationAttribute(Indicators)]
2257  public TrueStrengthIndex TSI(Symbol symbol, int longTermPeriod = 25, int shortTermPeriod = 13, int signalPeriod = 7,
2258  MovingAverageType signalType = MovingAverageType.Exponential, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2259  {
2260  var name = CreateIndicatorName(symbol, $"TSI({longTermPeriod},{shortTermPeriod},{signalPeriod})", resolution);
2261  var trueStrengthIndex = new TrueStrengthIndex(name, longTermPeriod, shortTermPeriod, signalPeriod, signalType);
2262  InitializeIndicator(trueStrengthIndex, resolution, selector, symbol);
2263 
2264  return trueStrengthIndex;
2265  }
2266 
2267  /// <summary>
2268  /// Creates a new TrueRange indicator.
2269  /// </summary>
2270  /// <param name="symbol">The symbol whose TR we want</param>
2271  /// <param name="resolution">The resolution</param>
2272  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2273  /// <returns>The TrueRange indicator for the requested symbol.</returns>
2274  [DocumentationAttribute(Indicators)]
2275  public TrueRange TR(Symbol symbol, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
2276  {
2277  var name = CreateIndicatorName(symbol, "TR", resolution);
2278  var trueRange = new TrueRange(name);
2279  InitializeIndicator(trueRange, resolution, selector, symbol);
2280 
2281  return trueRange;
2282  }
2283 
2284  /// <summary>
2285  /// Creates a new TriangularMovingAverage indicator.
2286  /// </summary>
2287  /// <param name="symbol">The symbol whose TRIMA we want</param>
2288  /// <param name="period">The period over which to compute the TRIMA</param>
2289  /// <param name="resolution">The resolution</param>
2290  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2291  /// <returns>The TriangularMovingAverage indicator for the requested symbol over the specified period</returns>
2292  [DocumentationAttribute(Indicators)]
2293  public TriangularMovingAverage TRIMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2294  {
2295  var name = CreateIndicatorName(symbol, $"TRIMA({period})", resolution);
2296  var triangularMovingAverage = new TriangularMovingAverage(name, period);
2297  InitializeIndicator(triangularMovingAverage, resolution, selector, symbol);
2298 
2299  return triangularMovingAverage;
2300  }
2301 
2302  /// <summary>
2303  /// Creates a new Trix indicator.
2304  /// </summary>
2305  /// <param name="symbol">The symbol whose TRIX we want</param>
2306  /// <param name="period">The period over which to compute the TRIX</param>
2307  /// <param name="resolution">The resolution</param>
2308  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2309  /// <returns>The Trix indicator for the requested symbol over the specified period</returns>
2310  [DocumentationAttribute(Indicators)]
2311  public Trix TRIX(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2312  {
2313  var name = CreateIndicatorName(symbol, $"TRIX({period})", resolution);
2314  var trix = new Trix(name, period);
2315  InitializeIndicator(trix, resolution, selector, symbol);
2316 
2317  return trix;
2318  }
2319 
2320  /// <summary>
2321  /// Creates a new UltimateOscillator indicator.
2322  /// </summary>
2323  /// <param name="symbol">The symbol whose ULTOSC we want</param>
2324  /// <param name="period1">The first period over which to compute the ULTOSC</param>
2325  /// <param name="period2">The second period over which to compute the ULTOSC</param>
2326  /// <param name="period3">The third period over which to compute the ULTOSC</param>
2327  /// <param name="resolution">The resolution</param>
2328  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2329  /// <returns>The UltimateOscillator indicator for the requested symbol over the specified period</returns>
2330  [DocumentationAttribute(Indicators)]
2331  public UltimateOscillator ULTOSC(Symbol symbol, int period1, int period2, int period3, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
2332  {
2333  var name = CreateIndicatorName(symbol, $"ULTOSC({period1},{period2},{period3})", resolution);
2334  var ultimateOscillator = new UltimateOscillator(name, period1, period2, period3);
2335  InitializeIndicator(ultimateOscillator, resolution, selector, symbol);
2336 
2337  return ultimateOscillator;
2338  }
2339 
2340  /// <summary>
2341  /// Creates a new Vega indicator for the symbol The indicator will be automatically
2342  /// updated on the symbol's subscription resolution
2343  /// </summary>
2344  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
2345  /// <param name="mirrorOption">The mirror option for parity calculation</param>
2346  /// <param name="riskFreeRate">The risk free rate</param>
2347  /// <param name="dividendYield">The dividend yield</param>
2348  /// <param name="optionModel">The option pricing model used to estimate Vega</param>
2349  /// <param name="ivModel">The option pricing model used to estimate IV</param>
2350  /// <param name="resolution">The desired resolution of the data</param>
2351  /// <returns>A new Vega indicator for the specified symbol</returns>
2352  [DocumentationAttribute(Indicators)]
2353  public Vega V(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null,
2354  OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null, Resolution? resolution = null)
2355  {
2356  var name = InitializeOptionIndicator<Vega>(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution);
2357 
2358  var vega = new Vega(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel);
2359  InitializeOptionIndicator(vega, resolution, symbol, mirrorOption);
2360  return vega;
2361  }
2362 
2363  /// <summary>
2364  /// Creates a new Chande's Variable Index Dynamic Average indicator.
2365  /// </summary>
2366  /// <param name="symbol">The symbol whose VIDYA we want</param>
2367  /// <param name="period">The period over which to compute the VIDYA</param>
2368  /// <param name="resolution">The resolution</param>
2369  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2370  /// <returns>The VariableIndexDynamicAverage indicator for the requested symbol over the specified period</returns>
2371  [DocumentationAttribute(Indicators)]
2372  public VariableIndexDynamicAverage VIDYA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2373  {
2374  var name = CreateIndicatorName(symbol, $"VIDYA({period})", resolution);
2375  var variableIndexDynamicAverage = new VariableIndexDynamicAverage(name, period);
2376  InitializeIndicator(variableIndexDynamicAverage, resolution, selector, symbol);
2377 
2378  return variableIndexDynamicAverage;
2379  }
2380 
2381  /// <summary>
2382  /// Creates a new Variance indicator. This will return the population variance of samples over the specified period.
2383  /// </summary>
2384  /// <param name="symbol">The symbol whose VAR we want</param>
2385  /// <param name="period">The period over which to compute the VAR</param>
2386  /// <param name="resolution">The resolution</param>
2387  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2388  /// <returns>The Variance indicator for the requested symbol over the specified period</returns>
2389  [DocumentationAttribute(Indicators)]
2390  [Obsolete("'VAR' is obsolete please use 'V' instead")]
2391  public Variance VAR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2392  {
2393  return V(symbol, period, resolution, selector);
2394  }
2395 
2396  /// <summary>
2397  /// Creates a new Variance indicator. This will return the population variance of samples over the specified period.
2398  /// </summary>
2399  /// <param name="symbol">The symbol whose variance we want</param>
2400  /// <param name="period">The period over which to compute the variance</param>
2401  /// <param name="resolution">The resolution</param>
2402  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2403  /// <returns>The Variance indicator for the requested symbol over the specified period</returns>
2404  [DocumentationAttribute(Indicators)]
2405  public Variance V(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2406  {
2407  var name = CreateIndicatorName(symbol, $"V({period})", resolution);
2408  var variance = new Variance(name, period);
2409  InitializeIndicator(variance, resolution, selector, symbol);
2410 
2411  return variance;
2412  }
2413 
2414  /// <summary>
2415  /// Creates a new ValueAtRisk indicator.
2416  /// </summary>
2417  /// <param name="symbol">The symbol whose VAR we want</param>
2418  /// <param name="period">The period over which to compute the VAR</param>
2419  /// <param name="confidenceLevel">The confidence level for Value at risk calculation</param>
2420  /// <param name="resolution">The resolution</param>
2421  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2422  /// <returns>The ValueAtRisk indicator for the requested Symbol, lookback period, and confidence level</returns>
2423  public ValueAtRisk VAR(Symbol symbol, int period, double confidenceLevel, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2424  {
2425  var name = CreateIndicatorName(symbol, $"VAR({period},{confidenceLevel})", resolution);
2426  var valueAtRisk = new ValueAtRisk(name, period, confidenceLevel);
2427  InitializeIndicator(valueAtRisk, resolution, selector, symbol);
2428 
2429  return valueAtRisk;
2430  }
2431 
2432  /// <summary>
2433  /// Creates an VolumeWeightedAveragePrice (VWAP) indicator for the symbol. The indicator will be automatically
2434  /// updated on the given resolution.
2435  /// </summary>
2436  /// <param name="symbol">The symbol whose VWAP we want</param>
2437  /// <param name="period">The period of the VWAP</param>
2438  /// <param name="resolution">The resolution</param>
2439  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2440  /// <returns>The VolumeWeightedAveragePrice for the given parameters</returns>
2441  [DocumentationAttribute(Indicators)]
2442  public VolumeWeightedAveragePriceIndicator VWAP(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2443  {
2444  var name = CreateIndicatorName(symbol, $"VWAP({period})", resolution);
2445  var volumeWeightedAveragePriceIndicator = new VolumeWeightedAveragePriceIndicator(name, period);
2446  InitializeIndicator(volumeWeightedAveragePriceIndicator, resolution, selector, symbol);
2447 
2448  return volumeWeightedAveragePriceIndicator;
2449  }
2450 
2451  /// <summary>
2452  /// Creates the canonical VWAP indicator that resets each day. The indicator will be automatically
2453  /// updated on the security's configured resolution.
2454  /// </summary>
2455  /// <param name="symbol">The symbol whose VWAP we want</param>
2456  /// <returns>The IntradayVWAP for the specified symbol</returns>
2457  [DocumentationAttribute(Indicators)]
2458  public IntradayVwap VWAP(Symbol symbol)
2459  {
2460  var name = CreateIndicatorName(symbol, "VWAP", null);
2461  var intradayVwap = new IntradayVwap(name);
2462  RegisterIndicator(symbol, intradayVwap);
2463  return intradayVwap;
2464  }
2465 
2466  /// <summary>
2467  /// Creates a new VolumeWeightedMovingAverage indicator for the symbol. The indicator will be automatically
2468  /// updated on the given resolution.
2469  /// </summary>
2470  /// <param name="symbol">The symbol whose VWMA we want</param>
2471  /// <param name="period">The smoothing period used to smooth the computed VWMA values</param>
2472  /// <param name="resolution">The resolution</param>
2473  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2474  /// <returns>A new VolumeWeightedMovingAverage indicator with the specified smoothing period</returns>
2475  [DocumentationAttribute(Indicators)]
2476  public VolumeWeightedMovingAverage VWMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2477  {
2478  var name = CreateIndicatorName(symbol, $"VWMA({period})", resolution);
2479  var indicator = new VolumeWeightedMovingAverage(name, period);
2480  InitializeIndicator(indicator, resolution, selector, symbol);
2481  return indicator;
2482  }
2483 
2484  /// <summary>
2485  /// Creates a new Vortex indicator for the symbol. The indicator will be automatically
2486  /// updated on the given resolution.
2487  /// </summary>
2488  /// <param name="symbol">The symbol whose VWMA we want</param>
2489  /// <param name="period">The smoothing period used to smooth the computed VWMA values</param>
2490  /// <param name="resolution">The resolution</param>
2491  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2492  /// <returns>A new Vortex indicator with the specified smoothing period</returns>
2493  [DocumentationAttribute(Indicators)]
2494  public Vortex VTX(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
2495  {
2496  var name = CreateIndicatorName(symbol, $"VTX({period})", resolution);
2497  var indicator = new Vortex(name, period);
2498  InitializeIndicator(indicator, resolution, selector, symbol);
2499  return indicator;
2500  }
2501 
2502  /// <summary>
2503  /// Creates a new Williams %R indicator. This will compute the percentage change of
2504  /// the current closing price in relation to the high and low of the past N periods.
2505  /// The indicator will be automatically updated on the given resolution.
2506  /// </summary>
2507  /// <param name="symbol">The symbol whose Williams %R we want</param>
2508  /// <param name="period">The period over which to compute the Williams %R</param>
2509  /// <param name="resolution">The resolution</param>
2510  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2511  /// <returns>The Williams %R indicator for the requested symbol over the specified period</returns>
2512  [DocumentationAttribute(Indicators)]
2513  public WilliamsPercentR WILR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
2514  {
2515  var name = CreateIndicatorName(symbol, $"WILR({period})", resolution);
2516  var williamsPercentR = new WilliamsPercentR(name, period);
2517  InitializeIndicator(williamsPercentR, resolution, selector, symbol);
2518 
2519  return williamsPercentR;
2520  }
2521 
2522  /// <summary>
2523  /// Creates a WilderMovingAverage indicator for the symbol.
2524  /// The indicator will be automatically updated on the given resolution.
2525  /// </summary>
2526  /// <param name="symbol">The symbol whose WMA we want</param>
2527  /// <param name="period">The period of the WMA</param>
2528  /// <param name="resolution">The resolution</param>
2529  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2530  /// <returns>The WilderMovingAverage for the given parameters</returns>
2531  /// <remarks>WWMA for Welles Wilder Moving Average</remarks>
2532  [DocumentationAttribute(Indicators)]
2533  public WilderMovingAverage WWMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2534  {
2535  var name = CreateIndicatorName(symbol, $"WWMA({period})", resolution);
2536  var wilderMovingAverage = new WilderMovingAverage(name, period);
2537  InitializeIndicator(wilderMovingAverage, resolution, selector, symbol);
2538 
2539  return wilderMovingAverage;
2540  }
2541 
2542  /// <summary>
2543  /// Creates a Wilder Swing Index (SI) indicator for the symbol.
2544  /// The indicator will be automatically updated on the given resolution.
2545  /// </summary>
2546  /// <param name="symbol">The symbol whose SI we want</param>
2547  /// <param name="limitMove">The maximum daily change in price for the SI</param>
2548  /// <param name="resolution">The resolution</param>
2549  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2550  /// <returns>The WilderSwingIndex for the given parameters</returns>
2551  /// <remarks>SI for Wilder Swing Index</remarks>
2552  [DocumentationAttribute(Indicators)]
2553  public WilderSwingIndex SI(Symbol symbol, decimal limitMove, Resolution? resolution = Resolution.Daily,
2554  Func<IBaseData, TradeBar> selector = null)
2555  {
2556  var name = CreateIndicatorName(symbol, "SI", resolution);
2557  var si = new WilderSwingIndex(name, limitMove);
2558  InitializeIndicator(si, resolution, selector, symbol);
2559 
2560  return si;
2561  }
2562 
2563  /// <summary>
2564  /// Creates a Wilder Accumulative Swing Index (ASI) indicator for the symbol.
2565  /// The indicator will be automatically updated on the given resolution.
2566  /// </summary>
2567  /// <param name="symbol">The symbol whose ASI we want</param>
2568  /// <param name="limitMove">The maximum daily change in price for the ASI</param>
2569  /// <param name="resolution">The resolution</param>
2570  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2571  /// <returns>The WilderAccumulativeSwingIndex for the given parameters</returns>
2572  /// <remarks>ASI for Wilder Accumulative Swing Index</remarks>
2573  [DocumentationAttribute(Indicators)]
2574  public WilderAccumulativeSwingIndex ASI(Symbol symbol, decimal limitMove, Resolution? resolution = Resolution.Daily,
2575  Func<IBaseData, TradeBar> selector = null)
2576  {
2577  var name = CreateIndicatorName(symbol, "ASI", resolution);
2578  var asi = new WilderAccumulativeSwingIndex(name, limitMove);
2579  InitializeIndicator(asi, resolution, selector, symbol);
2580 
2581  return asi;
2582  }
2583 
2584  /// <summary>
2585  /// Creates a new Arms Index indicator
2586  /// </summary>
2587  /// <param name="symbols">The symbols whose Arms Index we want</param>
2588  /// <param name="resolution">The resolution</param>
2589  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2590  /// <returns>The Arms Index indicator for the requested symbol over the specified period</returns>
2591  [DocumentationAttribute(Indicators)]
2592  public ArmsIndex TRIN(IEnumerable<Symbol> symbols, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2593  {
2594  return TRIN(symbols.ToArray(), resolution, selector);
2595  }
2596 
2597  /// <summary>
2598  /// Creates a new Arms Index indicator
2599  /// </summary>
2600  /// <param name="symbols">The symbols whose Arms Index we want</param>
2601  /// <param name="resolution">The resolution</param>
2602  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2603  /// <returns>The Arms Index indicator for the requested symbol over the specified period</returns>
2604  [DocumentationAttribute(Indicators)]
2605  public ArmsIndex TRIN(Symbol[] symbols, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2606  {
2607  var name = CreateIndicatorName(QuantConnect.Symbol.None, "TRIN", resolution ?? GetSubscription(symbols.First()).Resolution);
2608  var trin = new ArmsIndex(name);
2609  foreach (var symbol in symbols)
2610  {
2611  trin.Add(symbol);
2612  }
2613  InitializeIndicator(trin, resolution, selector, symbols);
2614 
2615  return trin;
2616  }
2617 
2618  /// <summary>
2619  /// Creates a new Advance/Decline Ratio indicator
2620  /// </summary>
2621  /// <param name="symbols">The symbols whose A/D Ratio we want</param>
2622  /// <param name="resolution">The resolution</param>
2623  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2624  /// <returns>The Advance/Decline Ratio indicator for the requested symbol over the specified period</returns>
2625  [DocumentationAttribute(Indicators)]
2626  public AdvanceDeclineRatio ADR(IEnumerable<Symbol> symbols, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2627  {
2628  var name = CreateIndicatorName(QuantConnect.Symbol.None, "A/D Ratio", resolution ?? GetSubscription(symbols.First()).Resolution);
2629  var adr = new AdvanceDeclineRatio(name);
2630  foreach (var symbol in symbols)
2631  {
2632  adr.Add(symbol);
2633  }
2634  InitializeIndicator(adr, resolution, selector, symbols.ToArray());
2635 
2636  return adr;
2637  }
2638 
2639  /// <summary>
2640  /// Creates a new Advance/Decline Volume Ratio indicator
2641  /// </summary>
2642  /// <param name="symbols">The symbol whose A/D Volume Rate we want</param>
2643  /// <param name="resolution">The resolution</param>
2644  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2645  /// <returns>The Advance/Decline Volume Ratio indicator for the requested symbol over the specified period</returns>
2646  [DocumentationAttribute(Indicators)]
2647  public AdvanceDeclineVolumeRatio ADVR(IEnumerable<Symbol> symbols, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2648  {
2649  var name = CreateIndicatorName(QuantConnect.Symbol.None, "A/D Volume Rate", resolution ?? GetSubscription(symbols.First()).Resolution);
2650  var advr = new AdvanceDeclineVolumeRatio(name);
2651  foreach (var symbol in symbols)
2652  {
2653  advr.Add(symbol);
2654  }
2655  InitializeIndicator(advr, resolution, selector, symbols.ToArray());
2656 
2657  return advr;
2658  }
2659 
2660  /// <summary>
2661  /// Creates a new Advance/Decline Difference indicator
2662  /// </summary>
2663  /// <param name="symbols">The symbols whose A/D Difference we want</param>
2664  /// <param name="resolution">The resolution</param>
2665  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2666  /// <returns>The Advance/Decline Difference indicator for the requested symbol over the specified period</returns>
2667  [DocumentationAttribute(Indicators)]
2668  public AdvanceDeclineDifference ADDIFF(IEnumerable<Symbol> symbols, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2669  {
2670  var name = CreateIndicatorName(QuantConnect.Symbol.None, "A/D Difference", resolution ?? GetSubscription(symbols.First()).Resolution);
2671  var adDiff = new AdvanceDeclineDifference(name);
2672  foreach (var symbol in symbols)
2673  {
2674  adDiff.Add(symbol);
2675  }
2676  InitializeIndicator(adDiff, resolution, selector, symbols.ToArray());
2677 
2678  return adDiff;
2679  }
2680 
2681  /// <summary>
2682  /// Creates a new McGinley Dynamic indicator
2683  /// </summary>
2684  /// <param name="symbol">The symbol whose McGinley Dynamic indicator value we want</param>
2685  /// <param name="period">The period of the McGinley Dynamic indicator</param>
2686  /// <param name="resolution">The resolution</param>
2687  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2688  /// <returns>The McGinley Dynamic indicator for the requested symbol over the specified period</returns>
2689  [DocumentationAttribute(Indicators)]
2690  public McGinleyDynamic MGD(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2691  {
2692  var name = CreateIndicatorName(symbol, $"MGD({period})", resolution);
2693  var indicator = new McGinleyDynamic(name, period);
2694  InitializeIndicator(indicator, resolution, selector, symbol);
2695  return indicator;
2696  }
2697 
2698  /// <summary>
2699  /// Creates a new McClellan Oscillator indicator
2700  /// </summary>
2701  /// <param name="symbols">The symbols whose McClellan Oscillator we want</param>
2702  /// <param name="fastPeriod">Fast period EMA of advance decline difference</param>
2703  /// <param name="slowPeriod">Slow period EMA of advance decline difference</param>
2704  /// <param name="resolution">The resolution</param>
2705  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2706  /// <returns>The McClellan Oscillator indicator for the requested symbol over the specified period</returns>
2707  [DocumentationAttribute(Indicators)]
2708  public McClellanOscillator MOSC(IEnumerable<Symbol> symbols, int fastPeriod = 19, int slowPeriod = 39, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2709  {
2710  return MOSC(symbols.ToArray(), fastPeriod, slowPeriod, resolution, selector);
2711  }
2712 
2713  /// <summary>
2714  /// Creates a new McClellan Oscillator indicator
2715  /// </summary>
2716  /// <param name="symbols">The symbols whose McClellan Oscillator we want</param>
2717  /// <param name="fastPeriod">Fast period EMA of advance decline difference</param>
2718  /// <param name="slowPeriod">Slow period EMA of advance decline difference</param>
2719  /// <param name="resolution">The resolution</param>
2720  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2721  /// <returns>The McClellan Oscillator indicator for the requested symbol over the specified period</returns>
2722  [DocumentationAttribute(Indicators)]
2723  public McClellanOscillator MOSC(Symbol[] symbols, int fastPeriod = 19, int slowPeriod = 39, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2724  {
2725  var name = CreateIndicatorName(QuantConnect.Symbol.None, $"MO({fastPeriod},{slowPeriod})", resolution ?? GetSubscription(symbols.First()).Resolution);
2726  var mosc = new McClellanOscillator(name, fastPeriod, slowPeriod);
2727  foreach (var symbol in symbols)
2728  {
2729  mosc.Add(symbol);
2730  }
2731  InitializeIndicator(mosc, resolution, selector, symbols);
2732 
2733  return mosc;
2734  }
2735 
2736  /// <summary>
2737  /// Creates a new McClellan Summation Index indicator
2738  /// </summary>
2739  /// <param name="symbols">The symbols whose McClellan Summation Index we want</param>
2740  /// <param name="fastPeriod">Fast period EMA of advance decline difference</param>
2741  /// <param name="slowPeriod">Slow period EMA of advance decline difference</param>
2742  /// <param name="resolution">The resolution</param>
2743  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2744  /// <returns>The McClellan Summation Index indicator for the requested symbol over the specified period</returns>
2745  [DocumentationAttribute(Indicators)]
2746  public McClellanSummationIndex MSI(IEnumerable<Symbol> symbols, int fastPeriod = 19, int slowPeriod = 39, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2747  {
2748  return MSI(symbols.ToArray(), fastPeriod, slowPeriod, resolution, selector);
2749  }
2750 
2751  /// <summary>
2752  /// Creates a new McClellan Summation Index indicator
2753  /// </summary>
2754  /// <param name="symbols">The symbols whose McClellan Summation Index we want</param>
2755  /// <param name="fastPeriod">Fast period EMA of advance decline difference</param>
2756  /// <param name="slowPeriod">Slow period EMA of advance decline difference</param>
2757  /// <param name="resolution">The resolution</param>
2758  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2759  /// <returns>The McClellan Summation Index indicator for the requested symbol over the specified period</returns>
2760  [DocumentationAttribute(Indicators)]
2761  public McClellanSummationIndex MSI(Symbol[] symbols, int fastPeriod = 19, int slowPeriod = 39, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2762  {
2763  var name = CreateIndicatorName(QuantConnect.Symbol.None, $"MSI({fastPeriod},{slowPeriod})", resolution ?? GetSubscription(symbols.First()).Resolution);
2764  var msi = new McClellanSummationIndex(name, fastPeriod, slowPeriod);
2765  foreach (var symbol in symbols)
2766  {
2767  msi.Add(symbol);
2768  }
2769  InitializeIndicator(msi, resolution, selector, symbols);
2770 
2771  return msi;
2772  }
2773 
2774 
2775  /// <summary>
2776  /// Creates a new RogersSatchellVolatility indicator for the symbol. The indicator will be automatically
2777  /// updated on the given resolution.
2778  /// </summary>
2779  /// <param name="symbol">The symbol whose RogersSatchellVolatility we want</param>
2780  /// <param name="period">The period of the rolling window used to compute volatility</param>
2781  /// <param name="resolution">The resolution</param>
2782  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
2783  /// <returns>A new RogersSatchellVolatility indicator with the specified smoothing type and period</returns>
2784  [DocumentationAttribute(Indicators)]
2785  public RogersSatchellVolatility RSV(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
2786  {
2787  var name = CreateIndicatorName(symbol, $"RSV({period})", resolution);
2788  var indicator = new RogersSatchellVolatility(name, period);
2789  InitializeIndicator(indicator, resolution, selector, symbol);
2790 
2791  return indicator;
2792  }
2793 
2794  /// <summary>
2795  /// Creates a ZeroLagExponentialMovingAverage indicator for the symbol. The indicator will be automatically
2796  /// updated on the given resolution.
2797  /// </summary>
2798  /// <param name="symbol">The symbol whose ZLEMA we want</param>
2799  /// <param name="period">The period of the ZLEMA</param>
2800  /// <param name="resolution">The resolution</param>
2801  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2802  /// <returns>The ZeroLagExponentialMovingAverage for the given parameters</returns>
2803  [DocumentationAttribute(Indicators)]
2804  public ZeroLagExponentialMovingAverage ZLEMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2805  {
2806  var name = CreateIndicatorName(symbol, $"ZLEMA({period})", resolution);
2807  var zeroLagExponentialMovingAverage = new ZeroLagExponentialMovingAverage(name, period);
2808  InitializeIndicator(zeroLagExponentialMovingAverage, resolution, selector, symbol);
2809 
2810  return zeroLagExponentialMovingAverage;
2811  }
2812 
2813  /// <summary>
2814  /// Creates a ZigZag indicator for the specified symbol, with adjustable sensitivity and minimum trend length.
2815  /// </summary>
2816  /// <param name="symbol">The symbol for which to create the ZigZag indicator.</param>
2817  /// <param name="sensitivity">The sensitivity for detecting pivots.</param>
2818  /// <param name="minTrendLength">The minimum number of bars required for a trend before a pivot is confirmed.</param>
2819  /// <param name="resolution">The resolution</param>
2820  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2821  /// <returns>The configured ZigZag indicator.</returns>
2822  [DocumentationAttribute(Indicators)]
2823  public ZigZag ZZ(Symbol symbol, decimal sensitivity = 0.05m, int minTrendLength = 1, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
2824  {
2825  var name = CreateIndicatorName(symbol, $"ZZ({sensitivity},{minTrendLength})", resolution);
2826  var zigZag = new ZigZag(name, sensitivity, minTrendLength);
2827  InitializeIndicator(zigZag, resolution, selector, symbol);
2828  return zigZag;
2829  }
2830 
2831  /// <summary>
2832  /// Creates a new name for an indicator created with the convenience functions (SMA, EMA, ect...)
2833  /// </summary>
2834  /// <param name="symbol">The symbol this indicator is registered to</param>
2835  /// <param name="type">The indicator type, for example, 'SMA(5)'</param>
2836  /// <param name="resolution">The resolution requested</param>
2837  /// <returns>A unique for the given parameters</returns>
2838  [DocumentationAttribute(Indicators)]
2839  public string CreateIndicatorName(Symbol symbol, FormattableString type, Resolution? resolution)
2840  {
2841  return CreateIndicatorName(symbol, Invariant(type), resolution);
2842  }
2843 
2844  /// <summary>
2845  /// Creates a new name for an indicator created with the convenience functions (SMA, EMA, ect...)
2846  /// </summary>
2847  /// <param name="symbol">The symbol this indicator is registered to</param>
2848  /// <param name="type">The indicator type, for example, 'SMA(5)'</param>
2849  /// <param name="resolution">The resolution requested</param>
2850  /// <returns>A unique for the given parameters</returns>
2851  [DocumentationAttribute(Indicators)]
2852  public string CreateIndicatorName(Symbol symbol, string type, Resolution? resolution)
2853  {
2854  var symbolIsNotEmpty = symbol != QuantConnect.Symbol.None && symbol != QuantConnect.Symbol.Empty;
2855 
2856  if (!resolution.HasValue && symbolIsNotEmpty)
2857  {
2858  resolution = GetSubscription(symbol).Resolution;
2859  }
2860 
2861  var res = string.Empty;
2862  switch (resolution)
2863  {
2864  case Resolution.Tick:
2865  res = "tick";
2866  break;
2867 
2868  case Resolution.Second:
2869  res = "sec";
2870  break;
2871 
2872  case Resolution.Minute:
2873  res = "min";
2874  break;
2875 
2876  case Resolution.Hour:
2877  res = "hr";
2878  break;
2879 
2880  case Resolution.Daily:
2881  res = "day";
2882  break;
2883 
2884  case null:
2885  break;
2886 
2887  default:
2888  throw new ArgumentOutOfRangeException(nameof(resolution), resolution, "resolution parameter is out of range.");
2889  }
2890 
2891  var parts = new List<string>();
2892 
2893  if (symbolIsNotEmpty)
2894  {
2895  parts.Add(symbol.ToString());
2896  }
2897  parts.Add(res);
2898 
2899  return Invariant($"{type}({string.Join("_", parts)})").Replace(")(", ",");
2900  }
2901 
2902  /// <summary>
2903  /// Gets the SubscriptionDataConfig for the specified symbol and tick type
2904  /// </summary>
2905  /// <exception cref="InvalidOperationException">Thrown if no configuration is found for the requested symbol</exception>
2906  /// <param name="symbol">The symbol to retrieve configuration for</param>
2907  /// <param name="tickType">The tick type of the subscription to get. If null, will use the first ordered by TickType</param>
2908  /// <returns>The SubscriptionDataConfig for the specified symbol</returns>
2909  private SubscriptionDataConfig GetSubscription(Symbol symbol, TickType? tickType = null)
2910  {
2911  SubscriptionDataConfig subscription;
2912  try
2913  {
2914  // deterministic ordering is required here
2916  .GetSubscriptionDataConfigs(symbol)
2917  // make sure common lean data types are at the bottom
2918  .OrderByDescending(x => LeanData.IsCommonLeanDataType(x.Type))
2919  .ThenBy(x => x.TickType)
2920  .ToList();
2921 
2922  // find our subscription
2923  subscription = subscriptions.FirstOrDefault(x => tickType == null || tickType == x.TickType);
2924  if (subscription == null)
2925  {
2926  // if we can't locate the exact subscription by tick type just grab the first one we find
2927  subscription = subscriptions.First();
2928  }
2929  }
2930  catch (InvalidOperationException)
2931  {
2932  // this will happen if we did not find the subscription, let's give the user a decent error message
2933  throw new Exception($"Please register to receive data for symbol \'{symbol}\' using the AddSecurity() function.");
2934  }
2935  return subscription;
2936  }
2937 
2938  /// <summary>
2939  /// Creates and registers a new consolidator to receive automatic updates at the specified resolution as well as configures
2940  /// the indicator to receive updates from the consolidator.
2941  /// </summary>
2942  /// <param name="symbol">The symbol to register against</param>
2943  /// <param name="indicator">The indicator to receive data from the consolidator</param>
2944  /// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
2945  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2946  [DocumentationAttribute(ConsolidatingData)]
2947  [DocumentationAttribute(Indicators)]
2948  public void RegisterIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2949  {
2950  RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution), selector ?? (x => x.Value));
2951  }
2952 
2953  /// <summary>
2954  /// Creates and registers a new consolidator to receive automatic updates at the specified resolution as well as configures
2955  /// the indicator to receive updates from the consolidator.
2956  /// </summary>
2957  /// <param name="symbol">The symbol to register against</param>
2958  /// <param name="indicator">The indicator to receive data from the consolidator</param>
2959  /// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
2960  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2961  [DocumentationAttribute(ConsolidatingData)]
2962  [DocumentationAttribute(Indicators)]
2963  public void RegisterIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, TimeSpan? resolution = null, Func<IBaseData, decimal> selector = null)
2964  {
2965  RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution), selector ?? (x => x.Value));
2966  }
2967 
2968  /// <summary>
2969  /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates
2970  /// from the consolidator.
2971  /// </summary>
2972  /// <param name="symbol">The symbol to register against</param>
2973  /// <param name="indicator">The indicator to receive data from the consolidator</param>
2974  /// <param name="consolidator">The consolidator to receive raw subscription data</param>
2975  /// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
2976  [DocumentationAttribute(ConsolidatingData)]
2977  [DocumentationAttribute(Indicators)]
2978  public void RegisterIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, IDataConsolidator consolidator, Func<IBaseData, decimal> selector = null)
2979  {
2980  // default our selector to the Value property on BaseData
2981  selector = selector ?? (x => x.Value);
2982 
2983  RegisterConsolidator(symbol, consolidator, null, indicator);
2984 
2985  // attach to the DataConsolidated event so it updates our indicator
2986  consolidator.DataConsolidated += (sender, consolidated) =>
2987  {
2988  var value = selector(consolidated);
2989  indicator.Update(new IndicatorDataPoint(consolidated.Symbol, consolidated.EndTime, value));
2990  };
2991  }
2992 
2993  /// <summary>
2994  /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates
2995  /// from the consolidator.
2996  /// </summary>
2997  /// <param name="symbol">The symbol to register against</param>
2998  /// <param name="indicator">The indicator to receive data from the consolidator</param>
2999  /// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
3000  [DocumentationAttribute(ConsolidatingData)]
3001  [DocumentationAttribute(Indicators)]
3002  public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, Resolution? resolution = null)
3003  where T : IBaseData
3004  {
3005  RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution, typeof(T)));
3006  }
3007 
3008  /// <summary>
3009  /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates
3010  /// from the consolidator.
3011  /// </summary>
3012  /// <param name="symbol">The symbol to register against</param>
3013  /// <param name="indicator">The indicator to receive data from the consolidator</param>
3014  /// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
3015  /// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
3016  [DocumentationAttribute(ConsolidatingData)]
3017  [DocumentationAttribute(Indicators)]
3018  public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, Resolution? resolution, Func<IBaseData, T> selector)
3019  where T : IBaseData
3020  {
3021  RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution, typeof(T)), selector);
3022  }
3023 
3024  /// <summary>
3025  /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates
3026  /// from the consolidator.
3027  /// </summary>
3028  /// <param name="symbol">The symbol to register against</param>
3029  /// <param name="indicator">The indicator to receive data from the consolidator</param>
3030  /// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
3031  /// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
3032  [DocumentationAttribute(ConsolidatingData)]
3033  [DocumentationAttribute(Indicators)]
3034  public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, TimeSpan? resolution, Func<IBaseData, T> selector = null)
3035  where T : IBaseData
3036  {
3037  RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution, typeof(T)), selector);
3038  }
3039 
3040  /// <summary>
3041  /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates
3042  /// from the consolidator.
3043  /// </summary>
3044  /// <param name="symbol">The symbol to register against</param>
3045  /// <param name="indicator">The indicator to receive data from the consolidator</param>
3046  /// <param name="consolidator">The consolidator to receive raw subscription data</param>
3047  /// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
3048  [DocumentationAttribute(ConsolidatingData)]
3049  [DocumentationAttribute(Indicators)]
3050  public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, IDataConsolidator consolidator, Func<IBaseData, T> selector = null)
3051  where T : IBaseData
3052  {
3053  // assign default using cast
3054  var selectorToUse = selector ?? (x => (T)x);
3055 
3056  RegisterConsolidator(symbol, consolidator, null, indicator);
3057 
3058  // check the output type of the consolidator and verify we can assign it to T
3059  var type = typeof(T);
3060  if (!type.IsAssignableFrom(consolidator.OutputType))
3061  {
3062  if (type == typeof(IndicatorDataPoint) && selector == null)
3063  {
3064  // if no selector was provided and the indicator input is of 'IndicatorDataPoint', common case, a selector with a direct cast will fail
3065  // so we use a smarter selector as in other API methods
3066  selectorToUse = consolidated => (T)(object)new IndicatorDataPoint(consolidated.Symbol, consolidated.EndTime, consolidated.Value);
3067  }
3068  else
3069  {
3070  throw new ArgumentException($"Type mismatch found between consolidator and indicator for symbol: {symbol}." +
3071  $"Consolidator outputs type {consolidator.OutputType.Name} but indicator expects input type {type.Name}"
3072  );
3073  }
3074  }
3075 
3076  // attach to the DataConsolidated event so it updates our indicator
3077  consolidator.DataConsolidated += (sender, consolidated) =>
3078  {
3079  var value = selectorToUse(consolidated);
3080  indicator.Update(value);
3081  };
3082  }
3083 
3084  /// <summary>
3085  /// Will unregister an indicator and it's associated consolidator instance so they stop receiving data updates
3086  /// </summary>
3087  /// <param name="indicator">The indicator instance to unregister</param>
3088  [DocumentationAttribute(ConsolidatingData)]
3089  [DocumentationAttribute(Indicators)]
3090  public void UnregisterIndicator(IndicatorBase indicator)
3091  {
3092  DeregisterIndicator(indicator);
3093  }
3094 
3095  /// <summary>
3096  /// Will deregister an indicator and it's associated consolidator instance so they stop receiving data updates
3097  /// </summary>
3098  /// <param name="indicator">The indicator instance to deregister</param>
3099  [DocumentationAttribute(ConsolidatingData)]
3100  [DocumentationAttribute(Indicators)]
3101  public void DeregisterIndicator(IndicatorBase indicator)
3102  {
3103  foreach (var consolidator in indicator.Consolidators)
3104  {
3105  SubscriptionManager.RemoveConsolidator(null, consolidator);
3106  }
3107 
3108  indicator.Consolidators.Clear();
3109  }
3110 
3111  /// <summary>
3112  /// Warms up a given indicator with historical data
3113  /// </summary>
3114  /// <param name="symbol">The symbol whose indicator we want</param>
3115  /// <param name="indicator">The indicator we want to warm up</param>
3116  /// <param name="resolution">The resolution</param>
3117  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3118  [DocumentationAttribute(HistoricalData)]
3119  [DocumentationAttribute(Indicators)]
3120  public void WarmUpIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
3121  {
3122  WarmUpIndicator(new[] { symbol }, indicator, resolution, selector);
3123  }
3124 
3125  /// <summary>
3126  /// Warms up a given indicator with historical data
3127  /// </summary>
3128  /// <param name="symbols">The symbols whose indicator we want</param>
3129  /// <param name="indicator">The indicator we want to warm up</param>
3130  /// <param name="resolution">The resolution</param>
3131  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3132  [DocumentationAttribute(HistoricalData)]
3133  [DocumentationAttribute(Indicators)]
3134  public void WarmUpIndicator(IEnumerable<Symbol> symbols, IndicatorBase<IndicatorDataPoint> indicator, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
3135  {
3136  if (AssertIndicatorHasWarmupPeriod(indicator))
3137  {
3138  IndicatorHistory(indicator, symbols, 0, resolution, selector);
3139  }
3140  }
3141 
3142  /// <summary>
3143  /// Warms up a given indicator with historical data
3144  /// </summary>
3145  /// <param name="symbol">The symbol whose indicator we want</param>
3146  /// <param name="indicator">The indicator we want to warm up</param>
3147  /// <param name="period">The necessary period to warm up the indicator</param>
3148  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3149  [DocumentationAttribute(HistoricalData)]
3150  [DocumentationAttribute(Indicators)]
3151  public void WarmUpIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, TimeSpan period, Func<IBaseData, decimal> selector = null)
3152  {
3153  WarmUpIndicator([symbol], indicator, period, selector);
3154  }
3155 
3156  /// <summary>
3157  /// Warms up a given indicator with historical data
3158  /// </summary>
3159  /// <param name="symbols">The symbols whose indicator we want</param>
3160  /// <param name="indicator">The indicator we want to warm up</param>
3161  /// <param name="period">The necessary period to warm up the indicator</param>
3162  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3163  [DocumentationAttribute(HistoricalData)]
3164  [DocumentationAttribute(Indicators)]
3165  public void WarmUpIndicator(IEnumerable<Symbol> symbols, IndicatorBase<IndicatorDataPoint> indicator, TimeSpan period, Func<IBaseData, decimal> selector = null)
3166  {
3167  var history = GetIndicatorWarmUpHistory(symbols, indicator, period, out var identityConsolidator);
3168  if (history == Enumerable.Empty<Slice>()) return;
3169 
3170  // assign default using cast
3171  selector ??= (x => x.Value);
3172 
3173  Action<IBaseData> onDataConsolidated = bar =>
3174  {
3175  var input = new IndicatorDataPoint(bar.Symbol, bar.EndTime, selector(bar));
3176  indicator.Update(input);
3177  };
3178 
3179  WarmUpIndicatorImpl(symbols, period, onDataConsolidated, history, identityConsolidator);
3180  }
3181 
3182  /// <summary>
3183  /// Warms up a given indicator with historical data
3184  /// </summary>
3185  /// <param name="symbol">The symbol whose indicator we want</param>
3186  /// <param name="indicator">The indicator we want to warm up</param>
3187  /// <param name="resolution">The resolution</param>
3188  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3189  [DocumentationAttribute(HistoricalData)]
3190  [DocumentationAttribute(Indicators)]
3191  public void WarmUpIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, Resolution? resolution = null, Func<IBaseData, T> selector = null)
3192  where T : class, IBaseData
3193  {
3194  WarmUpIndicator(new[] { symbol }, indicator, resolution, selector);
3195  }
3196 
3197  /// <summary>
3198  /// Warms up a given indicator with historical data
3199  /// </summary>
3200  /// <param name="symbols">The symbols whose indicator we want</param>
3201  /// <param name="indicator">The indicator we want to warm up</param>
3202  /// <param name="resolution">The resolution</param>
3203  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3204  [DocumentationAttribute(HistoricalData)]
3205  [DocumentationAttribute(Indicators)]
3206  public void WarmUpIndicator<T>(IEnumerable<Symbol> symbols, IndicatorBase<T> indicator, Resolution? resolution = null, Func<IBaseData, T> selector = null)
3207  where T : class, IBaseData
3208  {
3209  if (AssertIndicatorHasWarmupPeriod(indicator))
3210  {
3211  IndicatorHistory(indicator, symbols, 0, resolution, selector);
3212  }
3213  }
3214 
3215  /// <summary>
3216  /// Warms up a given indicator with historical data
3217  /// </summary>
3218  /// <param name="symbols">The symbols whose indicator we want</param>
3219  /// <param name="indicator">The indicator we want to warm up</param>
3220  /// <param name="period">The necessary period to warm up the indicator</param>
3221  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3222  [DocumentationAttribute(HistoricalData)]
3223  [DocumentationAttribute(Indicators)]
3224  public void WarmUpIndicator<T>(IEnumerable<Symbol> symbols, IndicatorBase<T> indicator, TimeSpan period, Func<IBaseData, T> selector = null)
3225  where T : class, IBaseData
3226  {
3227  var history = GetIndicatorWarmUpHistory(symbols, indicator, period, out var identityConsolidator);
3228  if (history == Enumerable.Empty<Slice>()) return;
3229 
3230  // assign default selector
3231  selector ??= GetDefaultSelector<T>();
3232 
3233  // we expect T type as input
3234  Action<T> onDataConsolidated = bar =>
3235  {
3236  indicator.Update(selector(bar));
3237  };
3238 
3239  WarmUpIndicatorImpl(symbols, period, onDataConsolidated, history, identityConsolidator);
3240  }
3241 
3242  /// <summary>
3243  /// Warms up a given indicator with historical data
3244  /// </summary>
3245  /// <param name="symbol">The symbol whose indicator we want</param>
3246  /// <param name="indicator">The indicator we want to warm up</param>
3247  /// <param name="period">The necessary period to warm up the indicator</param>
3248  /// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
3249  [DocumentationAttribute(HistoricalData)]
3250  [DocumentationAttribute(Indicators)]
3251  public void WarmUpIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, TimeSpan period, Func<IBaseData, T> selector = null)
3252  where T : class, IBaseData
3253  {
3254  WarmUpIndicator([symbol], indicator, period, selector);
3255  }
3256 
3257  private Func<IBaseData, T> GetDefaultSelector<T>()
3258  where T : IBaseData
3259  {
3260  if (typeof(T) == typeof(IndicatorDataPoint))
3261  {
3262  return x =>
3263  {
3264  if (!(x is IndicatorDataPoint))
3265  {
3266 
3267  return (T)(object)new IndicatorDataPoint(x.Symbol, x.EndTime, x.Price);
3268  }
3269  return (T)x;
3270  };
3271  }
3272  return x => (T)x;
3273  }
3274 
3275  private IEnumerable<Slice> GetIndicatorWarmUpHistory(IEnumerable<Symbol> symbols, IIndicator indicator, TimeSpan timeSpan, out bool identityConsolidator)
3276  {
3277  identityConsolidator = false;
3278  if (!AssertIndicatorHasWarmupPeriod(indicator))
3279  {
3280  return Enumerable.Empty<Slice>();
3281  }
3282 
3283  var periods = ((IIndicatorWarmUpPeriodProvider)indicator).WarmUpPeriod;
3284  if (periods != 0)
3285  {
3286  var resolution = timeSpan.ToHigherResolutionEquivalent(false);
3287  // if they are the same, means we can use an identity consolidator
3288  identityConsolidator = resolution.ToTimeSpan() == timeSpan;
3289  var resolutionTicks = resolution.ToTimeSpan().Ticks;
3290  if (resolutionTicks != 0)
3291  {
3292  periods *= (int)(timeSpan.Ticks / resolutionTicks);
3293  }
3294 
3295  try
3296  {
3297  return History(symbols, periods, resolution, dataNormalizationMode: GetIndicatorHistoryDataNormalizationMode(indicator));
3298  }
3299  catch (ArgumentException e)
3300  {
3301  Debug($"{indicator.Name} could not be warmed up. Reason: {e.Message}");
3302  }
3303  }
3304  return Enumerable.Empty<Slice>();
3305  }
3306 
3307  private bool AssertIndicatorHasWarmupPeriod(IIndicator indicator)
3308  {
3309  if (indicator is not IIndicatorWarmUpPeriodProvider)
3310  {
3311  if (!_isEmitWarmupInsightWarningSent)
3312  {
3313  Debug($"Warning: the 'WarmUpIndicator' feature only works with indicators which inherit from '{nameof(IIndicatorWarmUpPeriodProvider)}'" +
3314  $" and define a warm up period, setting property 'WarmUpPeriod' with a value > 0." +
3315  $" The provided indicator of type '{indicator.GetType().Name}' will not be warmed up.");
3316  _isEmitWarmupInsightWarningSent = true;
3317  }
3318  return false;
3319  }
3320  return true;
3321  }
3322 
3323  private void WarmUpIndicatorImpl<T>(IEnumerable<Symbol> symbols, TimeSpan period, Action<T> handler, IEnumerable<Slice> history, bool identityConsolidator)
3324  where T : class, IBaseData
3325  {
3326  var consolidators = symbols.ToDictionary(symbol => symbol, symbol =>
3327  {
3328  IDataConsolidator consolidator;
3329  if (SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(symbol).Count > 0)
3330  {
3331  consolidator = Consolidate(symbol, period, handler);
3332  }
3333  else
3334  {
3335  if (identityConsolidator)
3336  {
3337  period = TimeSpan.Zero;
3338  }
3339 
3340  var providedType = typeof(T);
3341  if (providedType.IsAbstract)
3342  {
3343  var dataType = SubscriptionManager.LookupSubscriptionConfigDataTypes(
3344  symbol.SecurityType,
3345  Resolution.Daily,
3346  // order by tick type so that behavior is consistent with 'GetSubscription()'
3347  symbol.IsCanonical())
3348  // make sure common lean data types are at the bottom
3349  .OrderByDescending(tuple => LeanData.IsCommonLeanDataType(tuple.Item1))
3350  .ThenBy(tuple => tuple.Item2).First();
3351 
3352  consolidator = CreateConsolidator(period, dataType.Item1, dataType.Item2);
3353  }
3354  else
3355  {
3356  // if the 'providedType' is not abstract we use it instead to determine which consolidator to use
3357  var tickType = LeanData.GetCommonTickTypeForCommonDataTypes(providedType, symbol.SecurityType);
3358  consolidator = CreateConsolidator(period, providedType, tickType);
3359  }
3360  consolidator.DataConsolidated += (s, bar) => handler((T)bar);
3361  }
3362 
3363  return consolidator;
3364  });
3365 
3366  foreach (var slice in history)
3367  {
3368  foreach (var (symbol, consolidator) in consolidators)
3369  {
3370  var consolidatorInputType = consolidator.InputType;
3371  if (slice.TryGet(consolidatorInputType, symbol, out var data))
3372  {
3373  consolidator.Update(data);
3374  }
3375  }
3376  }
3377 
3378  // Scan for time after we've pumped all the data through for this consolidator
3379  foreach (var (symbol, consolidator) in consolidators)
3380  {
3381  if (consolidator.WorkingData != null)
3382  {
3383  DateTime currentTime;
3384  if (Securities.TryGetValue(symbol, out var security))
3385  {
3386  currentTime = security.LocalTime;
3387  }
3388  else
3389  {
3390  var exchangeHours = MarketHoursDatabase.GetExchangeHours(symbol.ID.Market, symbol, symbol.SecurityType);
3391  currentTime = UtcTime.ConvertFromUtc(exchangeHours.TimeZone);
3392  }
3393 
3394  consolidator.Scan(currentTime);
3395  }
3396 
3397  SubscriptionManager.RemoveConsolidator(symbol, consolidator);
3398  }
3399  }
3400 
3401  /// <summary>
3402  /// Gets the default consolidator for the specified symbol and resolution
3403  /// </summary>
3404  /// <param name="symbol">The symbol whose data is to be consolidated</param>
3405  /// <param name="resolution">The resolution for the consolidator, if null, uses the resolution from subscription</param>
3406  /// <param name="dataType">The data type for this consolidator, if null, uses TradeBar over QuoteBar if present</param>
3407  /// <returns>The new default consolidator</returns>
3408  [DocumentationAttribute(ConsolidatingData)]
3409  [DocumentationAttribute(Indicators)]
3410  public IDataConsolidator ResolveConsolidator(Symbol symbol, Resolution? resolution, Type dataType = null)
3411  {
3412  var tickType = dataType != null ? LeanData.GetCommonTickTypeForCommonDataTypes(dataType, symbol.SecurityType) : (TickType?)null;
3413  return CreateConsolidator(symbol, null, tickType, null, resolution, null);
3414  }
3415 
3416  /// <summary>
3417  /// Gets the default consolidator for the specified symbol and resolution
3418  /// </summary>
3419  /// <param name="symbol">The symbol whose data is to be consolidated</param>
3420  /// <param name="timeSpan">The requested time span for the consolidator, if null, uses the resolution from subscription</param>
3421  /// <param name="dataType">The data type for this consolidator, if null, uses TradeBar over QuoteBar if present</param>
3422  /// <returns>The new default consolidator</returns>
3423  [DocumentationAttribute(ConsolidatingData)]
3424  [DocumentationAttribute(Indicators)]
3425  public IDataConsolidator ResolveConsolidator(Symbol symbol, TimeSpan? timeSpan, Type dataType = null)
3426  {
3427  var tickType = dataType != null ? LeanData.GetCommonTickTypeForCommonDataTypes(dataType, symbol.SecurityType) : (TickType?)null;
3428  return CreateConsolidator(symbol, null, tickType, timeSpan, null, null);
3429  }
3430 
3431  /// <summary>
3432  /// Creates a new consolidator for the specified period, generating the requested output type.
3433  /// </summary>
3434  /// <param name="period">The consolidation period</param>
3435  /// <param name="consolidatorInputType">The desired input type of the consolidator, such as TradeBar or QuoteBar</param>
3436  /// <param name="tickType">Trade or Quote. Optional, defaults to trade</param>
3437  /// <returns>A new consolidator matching the requested parameters</returns>
3438  [DocumentationAttribute(ConsolidatingData)]
3439  public static IDataConsolidator CreateConsolidator(TimeSpan period, Type consolidatorInputType, TickType? tickType = null)
3440  {
3441  if (period.Ticks == 0)
3442  {
3443  return CreateIdentityConsolidator(consolidatorInputType);
3444  }
3445 
3446  // if our type can be used as a trade bar, then let's just make one of those
3447  // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to TradeBar
3448  if (typeof(TradeBar).IsAssignableFrom(consolidatorInputType))
3449  {
3450  return new TradeBarConsolidator(period);
3451  }
3452 
3453  // if our type can be used as a quote bar, then let's just make one of those
3454  // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to QuoteBar
3455  if (typeof(QuoteBar).IsAssignableFrom(consolidatorInputType))
3456  {
3457  return new QuoteBarConsolidator(period);
3458  }
3459 
3460  // if our type can be used as a tick then we'll use a consolidator that keeps the TickType
3461  // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to Tick
3462  if (typeof(Tick).IsAssignableFrom(consolidatorInputType))
3463  {
3464  switch (tickType)
3465  {
3466  case TickType.OpenInterest:
3467  return new OpenInterestConsolidator(period);
3468 
3469  case TickType.Quote:
3470  return new TickQuoteBarConsolidator(period);
3471 
3472  default:
3473  return new TickConsolidator(period);
3474  }
3475  }
3476 
3477  // if our type can be used as a DynamicData then we'll use the DynamicDataConsolidator
3478  if (typeof(DynamicData).IsAssignableFrom(consolidatorInputType))
3479  {
3480  return new DynamicDataConsolidator(period);
3481  }
3482 
3483  // no matter what we can always consolidate based on the time-value pair of BaseData
3484  return new BaseDataConsolidator(period);
3485  }
3486 
3487  /// <summary>
3488  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol
3489  /// </summary>
3490  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3491  /// <param name="period">The consolidation period</param>
3492  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3493  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3494  [DocumentationAttribute(ConsolidatingData)]
3495  public IDataConsolidator Consolidate(Symbol symbol, Resolution period, Action<TradeBar> handler)
3496  {
3497  return Consolidate(symbol, period, TickType.Trade, handler);
3498  }
3499 
3500  /// <summary>
3501  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol
3502  /// </summary>
3503  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3504  /// <param name="period">The consolidation period</param>
3505  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3506  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3507  [DocumentationAttribute(ConsolidatingData)]
3508  public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, Action<TradeBar> handler)
3509  {
3510  return Consolidate(symbol, period, TickType.Trade, handler);
3511  }
3512 
3513  /// <summary>
3514  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol
3515  /// </summary>
3516  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3517  /// <param name="period">The consolidation period</param>
3518  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3519  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3520  [DocumentationAttribute(ConsolidatingData)]
3521  public IDataConsolidator Consolidate(Symbol symbol, Resolution period, Action<QuoteBar> handler)
3522  {
3523  return Consolidate(symbol, period.ToTimeSpan(), TickType.Quote, handler);
3524  }
3525 
3526  /// <summary>
3527  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol
3528  /// </summary>
3529  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3530  /// <param name="period">The consolidation period</param>
3531  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3532  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3533  [DocumentationAttribute(ConsolidatingData)]
3534  public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, Action<QuoteBar> handler)
3535  {
3536  return Consolidate(symbol, period, TickType.Quote, handler);
3537  }
3538 
3539  /// <summary>
3540  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol and tick type.
3541  /// The handler and tick type must match.
3542  /// </summary>
3543  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3544  /// <param name="period">The consolidation period</param>
3545  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3546  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3547  [DocumentationAttribute(ConsolidatingData)]
3548  public IDataConsolidator Consolidate<T>(Symbol symbol, TimeSpan period, Action<T> handler)
3549  where T : class, IBaseData
3550  {
3551  // only infer TickType from T if it's not abstract (for example IBaseData, BaseData), else if will end up being TradeBar let's not take that
3552  // decision here (default type), it will be taken later by 'GetSubscription' so we keep it centralized
3553  // This could happen when a user passes in a generic 'Action<BaseData>' handler
3554  var tickType = typeof(T).IsAbstract ? (TickType?)null : LeanData.GetCommonTickTypeForCommonDataTypes(typeof(T), symbol.SecurityType);
3555  return Consolidate(symbol, period, tickType, handler);
3556  }
3557 
3558  /// <summary>
3559  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol and tick type.
3560  /// The handler and tick type must match.
3561  /// </summary>
3562  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3563  /// <param name="period">The consolidation period</param>
3564  /// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
3565  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3566  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3567  [DocumentationAttribute(ConsolidatingData)]
3568  public IDataConsolidator Consolidate<T>(Symbol symbol, Resolution period, TickType? tickType, Action<T> handler)
3569  where T : class, IBaseData
3570  {
3571  return Consolidate(symbol, null, tickType, handler, null, period);
3572  }
3573 
3574  /// <summary>
3575  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol and tick type.
3576  /// The handler and tick type must match.
3577  /// </summary>
3578  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3579  /// <param name="period">The consolidation period</param>
3580  /// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
3581  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3582  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3583  [DocumentationAttribute(ConsolidatingData)]
3584  public IDataConsolidator Consolidate<T>(Symbol symbol, TimeSpan period, TickType? tickType, Action<T> handler)
3585  where T : class, IBaseData
3586  {
3587  return Consolidate(symbol, null, tickType, handler, period, null);
3588  }
3589 
3590  /// <summary>
3591  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol
3592  /// </summary>
3593  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3594  /// <param name="calendar">The consolidation calendar</param>
3595  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3596  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3597  [DocumentationAttribute(ConsolidatingData)]
3598  public IDataConsolidator Consolidate(Symbol symbol, Func<DateTime, CalendarInfo> calendar, Action<QuoteBar> handler)
3599  {
3600  return Consolidate(symbol, calendar, TickType.Quote, handler);
3601  }
3602 
3603  /// <summary>
3604  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol
3605  /// </summary>
3606  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3607  /// <param name="calendar">The consolidation calendar</param>
3608  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3609  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3610  [DocumentationAttribute(ConsolidatingData)]
3611  public IDataConsolidator Consolidate(Symbol symbol, Func<DateTime, CalendarInfo> calendar, Action<TradeBar> handler)
3612  {
3613  return Consolidate(symbol, calendar, TickType.Trade, handler);
3614  }
3615 
3616  /// <summary>
3617  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol and tick type.
3618  /// The handler and tick type must match.
3619  /// </summary>
3620  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3621  /// <param name="calendar">The consolidation calendar</param>
3622  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3623  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3624  [DocumentationAttribute(ConsolidatingData)]
3625  public IDataConsolidator Consolidate<T>(Symbol symbol, Func<DateTime, CalendarInfo> calendar, Action<T> handler)
3626  where T : class, IBaseData
3627  {
3628  // only infer TickType from T if it's not abstract (for example IBaseData, BaseData), else if will end up being TradeBar let's not take that
3629  // decision here (default type), it will be taken later by 'GetSubscription' so we keep it centralized
3630  // This could happen when a user passes in a generic 'Action<BaseData>' handler
3631  var tickType = typeof(T).IsAbstract ? (TickType?)null : LeanData.GetCommonTickTypeForCommonDataTypes(typeof(T), symbol.SecurityType);
3632  return Consolidate(symbol, calendar, tickType, handler);
3633  }
3634 
3635  /// <summary>
3636  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol and tick type.
3637  /// The handler and tick type must match.
3638  /// </summary>
3639  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3640  /// <param name="calendar">The consolidation calendar</param>
3641  /// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
3642  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3643  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3644  [DocumentationAttribute(ConsolidatingData)]
3645  public IDataConsolidator Consolidate<T>(Symbol symbol, Func<DateTime, CalendarInfo> calendar, TickType? tickType, Action<T> handler)
3646  where T : class, IBaseData
3647  {
3648  return Consolidate(symbol, calendar, tickType, handler, null, null);
3649  }
3650 
3651  /// <summary>
3652  /// Gets the historical data of an indicator for the specified symbol. The exact number of bars will be returned.
3653  /// The symbol must exist in the Securities collection.
3654  /// </summary>
3655  /// <param name="indicator">The target indicator</param>
3656  /// <param name="symbol">The symbol to retrieve historical data for</param>
3657  /// <param name="period">The number of bars to request</param>
3658  /// <param name="resolution">The resolution to request</param>
3659  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3660  /// <returns>pandas.DataFrame of historical data of an indicator</returns>
3661  public IndicatorHistory IndicatorHistory(IndicatorBase<IndicatorDataPoint> indicator, Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
3662  {
3663  return IndicatorHistory(indicator, new[] { symbol }, period, resolution, selector);
3664  }
3665 
3666  /// <summary>
3667  /// Gets the historical data of an indicator for the specified symbols. The exact number of bars will be returned.
3668  /// The symbol must exist in the Securities collection.
3669  /// </summary>
3670  /// <param name="indicator">The target indicator</param>
3671  /// <param name="symbols">The symbols to retrieve historical data for</param>
3672  /// <param name="period">The number of bars to request</param>
3673  /// <param name="resolution">The resolution to request</param>
3674  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3675  /// <returns>pandas.DataFrame of historical data of an indicator</returns>
3676  public IndicatorHistory IndicatorHistory(IndicatorBase<IndicatorDataPoint> indicator, IEnumerable<Symbol> symbols, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
3677  {
3678  var warmupPeriod = (indicator as IIndicatorWarmUpPeriodProvider)?.WarmUpPeriod ?? 0;
3679  if (warmupPeriod > 0 && period > 0)
3680  {
3681  warmupPeriod -= 1;
3682  }
3683  var history = History(symbols, period + warmupPeriod, resolution, dataNormalizationMode: GetIndicatorHistoryDataNormalizationMode(indicator));
3684  return IndicatorHistory(indicator, history, selector);
3685  }
3686 
3687  /// <summary>
3688  /// Gets the historical data of a bar indicator for the specified symbol. The exact number of bars will be returned.
3689  /// The symbol must exist in the Securities collection.
3690  /// </summary>
3691  /// <param name="indicator">The target indicator</param>
3692  /// <param name="symbol">The symbol to retrieve historical data for</param>
3693  /// <param name="period">The number of bars to request</param>
3694  /// <param name="resolution">The resolution to request</param>
3695  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3696  /// <returns>pandas.DataFrame of historical data of a bar indicator</returns>
3697  public IndicatorHistory IndicatorHistory<T>(IndicatorBase<T> indicator, Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, T> selector = null)
3698  where T : IBaseData
3699  {
3700  return IndicatorHistory(indicator, new[] { symbol }, period, resolution, selector);
3701  }
3702 
3703  /// <summary>
3704  /// Gets the historical data of a bar indicator for the specified symbols. The exact number of bars will be returned.
3705  /// The symbol must exist in the Securities collection.
3706  /// </summary>
3707  /// <param name="indicator">The target indicator</param>
3708  /// <param name="symbols">The symbols to retrieve historical data for</param>
3709  /// <param name="period">The number of bars to request</param>
3710  /// <param name="resolution">The resolution to request</param>
3711  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3712  /// <returns>pandas.DataFrame of historical data of a bar indicator</returns>
3713  public IndicatorHistory IndicatorHistory<T>(IndicatorBase<T> indicator, IEnumerable<Symbol> symbols, int period, Resolution? resolution = null, Func<IBaseData, T> selector = null)
3714  where T : IBaseData
3715  {
3716  var warmupPeriod = (indicator as IIndicatorWarmUpPeriodProvider)?.WarmUpPeriod ?? 0;
3717  if (warmupPeriod > 0 && period > 0)
3718  {
3719  warmupPeriod -= 1;
3720  }
3721  var history = History(symbols, period + warmupPeriod, resolution, dataNormalizationMode: GetIndicatorHistoryDataNormalizationMode(indicator));
3722  return IndicatorHistory(indicator, history, selector);
3723  }
3724 
3725  /// <summary>
3726  /// Gets the historical data of an indicator for the specified symbol. The exact number of bars will be returned.
3727  /// The symbol must exist in the Securities collection.
3728  /// </summary>
3729  /// <param name="indicator">The target indicator</param>
3730  /// <param name="symbol">The symbol to retrieve historical data for</param>
3731  /// <param name="span">The span over which to retrieve recent historical data</param>
3732  /// <param name="resolution">The resolution to request</param>
3733  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3734  /// <returns>pandas.DataFrame of historical data of an indicator</returns>
3735  public IndicatorHistory IndicatorHistory(IndicatorBase<IndicatorDataPoint> indicator, Symbol symbol, TimeSpan span, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
3736  {
3737  return IndicatorHistory(indicator, new[] { symbol }, span, resolution, selector);
3738  }
3739 
3740  /// <summary>
3741  /// Gets the historical data of an indicator for the specified symbol. The exact number of bars will be returned.
3742  /// The symbol must exist in the Securities collection.
3743  /// </summary>
3744  /// <param name="indicator">The target indicator</param>
3745  /// <param name="symbols">The symbols to retrieve historical data for</param>
3746  /// <param name="span">The span over which to retrieve recent historical data</param>
3747  /// <param name="resolution">The resolution to request</param>
3748  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3749  /// <returns>pandas.DataFrame of historical data of an indicator</returns>
3750  public IndicatorHistory IndicatorHistory(IndicatorBase<IndicatorDataPoint> indicator, IEnumerable<Symbol> symbols, TimeSpan span, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
3751  {
3752  return IndicatorHistory(indicator, symbols, Time - span, Time, resolution, selector);
3753  }
3754 
3755  /// <summary>
3756  /// Gets the historical data of a bar indicator for the specified symbol. The exact number of bars will be returned.
3757  /// The symbol must exist in the Securities collection.
3758  /// </summary>
3759  /// <param name="indicator">The target indicator</param>
3760  /// <param name="symbols">The symbols to retrieve historical data for</param>
3761  /// <param name="span">The span over which to retrieve recent historical data</param>
3762  /// <param name="resolution">The resolution to request</param>
3763  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3764  /// <returns>pandas.DataFrame of historical data of a bar indicator</returns>
3765  public IndicatorHistory IndicatorHistory<T>(IndicatorBase<T> indicator, IEnumerable<Symbol> symbols, TimeSpan span, Resolution? resolution = null, Func<IBaseData, T> selector = null)
3766  where T : IBaseData
3767  {
3768  return IndicatorHistory(indicator, symbols, Time - span, Time, resolution, selector);
3769  }
3770 
3771  /// <summary>
3772  /// Gets the historical data of a bar indicator for the specified symbol. The exact number of bars will be returned.
3773  /// The symbol must exist in the Securities collection.
3774  /// </summary>
3775  /// <param name="indicator">The target indicator</param>
3776  /// <param name="symbol">The symbol to retrieve historical data for</param>
3777  /// <param name="span">The span over which to retrieve recent historical data</param>
3778  /// <param name="resolution">The resolution to request</param>
3779  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3780  /// <returns>pandas.DataFrame of historical data of a bar indicator</returns>
3781  public IndicatorHistory IndicatorHistory<T>(IndicatorBase<T> indicator, Symbol symbol, TimeSpan span, Resolution? resolution = null, Func<IBaseData, T> selector = null)
3782  where T : IBaseData
3783  {
3784  return IndicatorHistory(indicator, new[] { symbol }, span, resolution, selector);
3785  }
3786 
3787  /// <summary>
3788  /// Gets the historical data of an indicator for the specified symbols. The exact number of bars will be returned.
3789  /// The symbol must exist in the Securities collection.
3790  /// </summary>
3791  /// <param name="indicator">The target indicator</param>
3792  /// <param name="symbols">The symbols to retrieve historical data for</param>
3793  /// <param name="start">The start time in the algorithm's time zone</param>
3794  /// <param name="end">The end time in the algorithm's time zone</param>
3795  /// <param name="resolution">The resolution to request</param>
3796  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3797  /// <returns>pandas.DataFrame of historical data of an indicator</returns>
3798  public IndicatorHistory IndicatorHistory(IndicatorBase<IndicatorDataPoint> indicator, IEnumerable<Symbol> symbols, DateTime start, DateTime end, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
3799  {
3800  var history = History(symbols, GetIndicatorAdjustedHistoryStart(indicator, symbols, start, end, resolution), end, resolution, dataNormalizationMode: GetIndicatorHistoryDataNormalizationMode(indicator));
3801  return IndicatorHistory(indicator, history, selector);
3802  }
3803 
3804  /// <summary>
3805  /// Gets the historical data of an indicator for the specified symbol. The exact number of bars will be returned.
3806  /// The symbol must exist in the Securities collection.
3807  /// </summary>
3808  /// <param name="indicator">The target indicator</param>
3809  /// <param name="symbol">The symbol to retrieve historical data for</param>
3810  /// <param name="start">The start time in the algorithm's time zone</param>
3811  /// <param name="end">The end time in the algorithm's time zone</param>
3812  /// <param name="resolution">The resolution to request</param>
3813  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3814  /// <returns>pandas.DataFrame of historical data of an indicator</returns>
3815  public IndicatorHistory IndicatorHistory(IndicatorBase<IndicatorDataPoint> indicator, Symbol symbol, DateTime start, DateTime end, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
3816  {
3817  return IndicatorHistory(indicator, new[] { symbol }, start, end, resolution, selector);
3818  }
3819 
3820  /// <summary>
3821  /// Gets the historical data of a bar indicator for the specified symbol. The exact number of bars will be returned.
3822  /// The symbol must exist in the Securities collection.
3823  /// </summary>
3824  /// <param name="indicator">The target indicator</param>
3825  /// <param name="symbol">The symbol to retrieve historical data for</param>
3826  /// <param name="start">The start time in the algorithm's time zone</param>
3827  /// <param name="end">The end time in the algorithm's time zone</param>
3828  /// <param name="resolution">The resolution to request</param>
3829  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3830  /// <returns>pandas.DataFrame of historical data of a bar indicator</returns>
3831  public IndicatorHistory IndicatorHistory<T>(IndicatorBase<T> indicator, Symbol symbol, DateTime start, DateTime end, Resolution? resolution = null, Func<IBaseData, T> selector = null)
3832  where T : IBaseData
3833  {
3834  return IndicatorHistory(indicator, new[] { symbol }, start, end, resolution, selector);
3835  }
3836 
3837  /// <summary>
3838  /// Gets the historical data of a bar indicator for the specified symbols. The exact number of bars will be returned.
3839  /// The symbol must exist in the Securities collection.
3840  /// </summary>
3841  /// <param name="indicator">The target indicator</param>
3842  /// <param name="symbols">The symbols to retrieve historical data for</param>
3843  /// <param name="start">The start time in the algorithm's time zone</param>
3844  /// <param name="end">The end time in the algorithm's time zone</param>
3845  /// <param name="resolution">The resolution to request</param>
3846  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3847  /// <returns>pandas.DataFrame of historical data of a bar indicator</returns>
3848  public IndicatorHistory IndicatorHistory<T>(IndicatorBase<T> indicator, IEnumerable<Symbol> symbols, DateTime start, DateTime end, Resolution? resolution = null, Func<IBaseData, T> selector = null)
3849  where T : IBaseData
3850  {
3851  var history = History(symbols, GetIndicatorAdjustedHistoryStart(indicator, symbols, start, end, resolution), end, resolution, dataNormalizationMode: GetIndicatorHistoryDataNormalizationMode(indicator));
3852  return IndicatorHistory(indicator, history, selector);
3853  }
3854 
3855  /// <summary>
3856  /// Gets the historical data of an indicator and convert it into pandas.DataFrame
3857  /// </summary>
3858  /// <param name="indicator">The target indicator</param>
3859  /// <param name="history">Historical data used to calculate the indicator</param>
3860  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3861  /// <returns>pandas.DataFrame containing the historical data of <paramref name="indicator"/></returns>
3862  public IndicatorHistory IndicatorHistory(IndicatorBase<IndicatorDataPoint> indicator, IEnumerable<Slice> history, Func<IBaseData, decimal> selector = null)
3863  {
3864  selector ??= (x => x.Value);
3865  return IndicatorHistory(indicator, history, (bar) => indicator.Update(new IndicatorDataPoint(bar.Symbol, bar.EndTime, selector(bar))), GetDataTypeFromSelector(selector));
3866  }
3867 
3868  /// <summary>
3869  /// Gets the historical data of an bar indicator and convert it into pandas.DataFrame
3870  /// </summary>
3871  /// <param name="indicator">Bar indicator</param>
3872  /// <param name="history">Historical data used to calculate the indicator</param>
3873  /// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
3874  /// <returns>pandas.DataFrame containing the historical data of <paramref name="indicator"/></returns>
3875  public IndicatorHistory IndicatorHistory<T>(IndicatorBase<T> indicator, IEnumerable<Slice> history, Func<IBaseData, T> selector = null)
3876  where T : IBaseData
3877  {
3878  selector ??= GetDefaultSelector<T>();
3879  return IndicatorHistory(indicator, history, (bar) => indicator.Update(selector(bar)));
3880  }
3881 
3882  /// <summary>
3883  /// Adds the provided consolidator and asserts the handler T type is assignable from the consolidator output,
3884  /// if not will throw <see cref="ArgumentException"/>
3885  /// </summary>
3886  private IDataConsolidator Consolidate<T>(Symbol symbol, Func<DateTime, CalendarInfo> calendar, TickType? tickType, Action<T> handler, TimeSpan? period, Resolution? resolution)
3887  where T : class, IBaseData
3888  {
3889  var consolidator = CreateConsolidator(symbol, calendar, tickType, period, resolution, typeof(T));
3890  if (handler != null)
3891  {
3892  // register user-defined handler to receive consolidated data events
3893  consolidator.DataConsolidated += (sender, consolidated) => handler((T)consolidated);
3894 
3895  // register the consolidator for automatic updates via SubscriptionManager
3896  RegisterConsolidator(symbol, consolidator, tickType, indicatorBase: null);
3897  }
3898  return consolidator;
3899  }
3900 
3901  private IDataConsolidator CreateConsolidator(Symbol symbol, Func<DateTime, CalendarInfo> calendar, TickType? tickType, TimeSpan? period, Resolution? resolution, Type consolidatorType)
3902  {
3903  // resolve consolidator input subscription
3904  var subscription = GetSubscription(symbol, tickType);
3905 
3906  // verify this consolidator will give reasonable results, if someone asks for second consolidation but we have minute
3907  // data we won't be able to do anything good, we'll call it second, but it would really just be minute!
3908  if (period.HasValue && period.Value < subscription.Increment || resolution.HasValue && resolution.Value < subscription.Resolution)
3909  {
3910  throw new ArgumentException($"Unable to create {symbol} consolidator because {symbol} is registered for " +
3911  Invariant($"{subscription.Resolution.ToStringInvariant()} data. Consolidators require higher resolution data to produce lower resolution data.")
3912  );
3913  }
3914 
3915  IDataConsolidator consolidator = null;
3916  if (calendar != null)
3917  {
3918  // create requested consolidator
3919  consolidator = CreateConsolidator(calendar, subscription.Type, subscription.TickType);
3920  }
3921  else
3922  {
3923  // if not specified, default to the subscription resolution
3924  if (!period.HasValue && !resolution.HasValue)
3925  {
3926  period = subscription.Increment;
3927  }
3928 
3929  if (period.HasValue && period.Value == subscription.Increment || resolution.HasValue && resolution.Value == subscription.Resolution)
3930  {
3931  consolidator = CreateIdentityConsolidator(subscription.Type);
3932  }
3933  else
3934  {
3935  if (resolution.HasValue)
3936  {
3937  if (resolution.Value == Resolution.Daily)
3938  {
3939  consolidator = new MarketHourAwareConsolidator(Settings.DailyPreciseEndTime, resolution.Value, subscription.Type, subscription.TickType,
3940  Settings.DailyConsolidationUseExtendedMarketHours && subscription.ExtendedMarketHours);
3941  }
3942  period = resolution.Value.ToTimeSpan();
3943  }
3944  consolidator ??= CreateConsolidator(period.Value, subscription.Type, subscription.TickType);
3945  }
3946  }
3947 
3948  if (consolidatorType != null && !consolidatorType.IsAssignableFrom(consolidator.OutputType))
3949  {
3950  throw new ArgumentException(
3951  $"Unable to consolidate with the specified handler because the consolidator's output type " +
3952  $"is {consolidator.OutputType.Name} but the handler's input type is {subscription.Type.Name}.");
3953  }
3954  return consolidator;
3955  }
3956 
3957  private IDataConsolidator CreateConsolidator(Func<DateTime, CalendarInfo> calendar, Type consolidatorInputType, TickType tickType)
3958  {
3959  // if our type can be used as a trade bar, then let's just make one of those
3960  // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to TradeBar
3961  if (typeof(TradeBar).IsAssignableFrom(consolidatorInputType))
3962  {
3963  return new TradeBarConsolidator(calendar);
3964  }
3965 
3966  // if our type can be used as a quote bar, then let's just make one of those
3967  // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to QuoteBar
3968  if (typeof(QuoteBar).IsAssignableFrom(consolidatorInputType))
3969  {
3970  return new QuoteBarConsolidator(calendar);
3971  }
3972 
3973  // if our type can be used as a tick then we'll use a consolidator that keeps the TickType
3974  // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to Tick
3975  if (typeof(Tick).IsAssignableFrom(consolidatorInputType))
3976  {
3977  if (tickType == TickType.Quote)
3978  {
3979  return new TickQuoteBarConsolidator(calendar);
3980  }
3981  return new TickConsolidator(calendar);
3982  }
3983 
3984  // if our type can be used as a DynamicData then we'll use the DynamicDataConsolidator
3985  if (typeof(DynamicData).IsAssignableFrom(consolidatorInputType))
3986  {
3987  return new DynamicDataConsolidator(calendar);
3988  }
3989 
3990  // no matter what we can always consolidate based on the time-value pair of BaseData
3991  return new BaseDataConsolidator(calendar);
3992  }
3993 
3994  /// <summary>
3995  /// Creates a new consolidator identity consolidator for the requested output type.
3996  /// </summary>
3997  private static IDataConsolidator CreateIdentityConsolidator(Type consolidatorInputType)
3998  {
3999  if (typeof(TradeBar).IsAssignableFrom(consolidatorInputType))
4000  {
4002  }
4003  else if (typeof(QuoteBar).IsAssignableFrom(consolidatorInputType))
4004  {
4006  }
4007  else if (typeof(Tick).IsAssignableFrom(consolidatorInputType))
4008  {
4009  return new IdentityDataConsolidator<Tick>();
4010  }
4011  else if (typeof(DynamicData).IsAssignableFrom(consolidatorInputType))
4012  {
4013  return new DynamicDataConsolidator(1);
4014  }
4016  }
4017 
4018  /// <summary>
4019  /// Registers and warms up (if EnableAutomaticIndicatorWarmUp is set) the indicator
4020  /// </summary>
4021  private void InitializeIndicator(IndicatorBase<IndicatorDataPoint> indicator, Resolution? resolution = null,
4022  Func<IBaseData, decimal> selector = null, params Symbol[] symbols)
4023  {
4024  var dataType = GetDataTypeFromSelector(selector);
4025  foreach (var symbol in symbols)
4026  {
4027  RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution, dataType), selector);
4028  }
4029 
4030  if (Settings.AutomaticIndicatorWarmUp)
4031  {
4032  WarmUpIndicator(symbols, indicator, resolution, selector);
4033  }
4034  }
4035 
4036  private void InitializeIndicator<T>(IndicatorBase<T> indicator, Resolution? resolution = null,
4037  Func<IBaseData, T> selector = null, params Symbol[] symbols)
4038  where T : class, IBaseData
4039  {
4040  foreach (var symbol in symbols)
4041  {
4042  RegisterIndicator(symbol, indicator, resolution, selector);
4043  }
4044 
4045  if (Settings.AutomaticIndicatorWarmUp)
4046  {
4047  WarmUpIndicator(symbols, indicator, resolution, selector);
4048  }
4049  }
4050 
4051  private void InitializeOptionIndicator(IndicatorBase<IBaseData> indicator, Resolution? resolution, Symbol symbol, Symbol mirrorOption)
4052  {
4053  RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution, typeof(QuoteBar)));
4054  RegisterIndicator(symbol.Underlying, indicator, ResolveConsolidator(symbol.Underlying, resolution));
4055  var symbols = new List<Symbol> { symbol, symbol.Underlying };
4056  if (mirrorOption != null)
4057  {
4058  RegisterIndicator(mirrorOption, indicator, ResolveConsolidator(mirrorOption, resolution, typeof(QuoteBar)));
4059  symbols.Add(mirrorOption);
4060  }
4061 
4062  if (Settings.AutomaticIndicatorWarmUp)
4063  {
4064  WarmUpIndicator(symbols, indicator, resolution);
4065  }
4066  }
4067 
4068  private string InitializeOptionIndicator<T>(Symbol symbol, out IRiskFreeInterestRateModel riskFreeRateModel, out IDividendYieldModel dividendYieldModel,
4069  decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType? optionModel = null, Resolution? resolution = null)
4070  where T : OptionIndicatorBase
4071  {
4072  var name = CreateIndicatorName(symbol,
4073  $"{typeof(T).Name}({riskFreeRate},{dividendYield},{OptionIndicatorBase.GetOptionModel(optionModel, symbol.ID.OptionStyle)})",
4074  resolution);
4075 
4076  riskFreeRateModel = riskFreeRate.HasValue
4077  ? new ConstantRiskFreeRateInterestRateModel(riskFreeRate.Value)
4078  // Make it a function so it's lazily evaluated: SetRiskFreeInterestRateModel can be called after this method
4079  : new FuncRiskFreeRateInterestRateModel((datetime) => RiskFreeInterestRateModel.GetInterestRate(datetime));
4080 
4081  if (dividendYield.HasValue)
4082  {
4083  dividendYieldModel = new ConstantDividendYieldModel(dividendYield.Value);
4084  }
4085  else
4086  {
4087  dividendYieldModel = DividendYieldProvider.CreateForOption(symbol);
4088  }
4089 
4090  return name;
4091  }
4092 
4093  private void RegisterConsolidator(Symbol symbol, IDataConsolidator consolidator, TickType? tickType, IndicatorBase indicatorBase)
4094  {
4095  // keep a reference of the consolidator so we can unregister it later using only a reference to the indicator
4096  indicatorBase?.Consolidators.Add(consolidator);
4097 
4098  // register the consolidator for automatic updates via SubscriptionManager
4099  SubscriptionManager.AddConsolidator(symbol, consolidator, tickType);
4100  }
4101 
4102  private DateTime GetIndicatorAdjustedHistoryStart(IndicatorBase indicator, IEnumerable<Symbol> symbols, DateTime start, DateTime end, Resolution? resolution = null)
4103  {
4104  var warmupPeriod = (indicator as IIndicatorWarmUpPeriodProvider)?.WarmUpPeriod ?? 0;
4105  if (warmupPeriod != 0)
4106  {
4107  warmupPeriod -= 1;
4108  if (warmupPeriod > 0)
4109  {
4110  foreach (var request in CreateDateRangeHistoryRequests(symbols, start, end, resolution))
4111  {
4112  var adjustedStart = _historyRequestFactory.GetStartTimeAlgoTz(request.StartTimeUtc, request.Symbol, warmupPeriod, request.Resolution,
4113  request.ExchangeHours, request.DataTimeZone, request.DataType, request.IncludeExtendedMarketHours);
4114  if (adjustedStart < start)
4115  {
4116  start = adjustedStart;
4117  }
4118  }
4119  }
4120  }
4121  return start;
4122  }
4123 
4124  private DataNormalizationMode? GetIndicatorHistoryDataNormalizationMode(IIndicator indicator)
4125  {
4126  DataNormalizationMode? dataNormalizationMode = null;
4127  if (indicator is OptionIndicatorBase optionIndicator && optionIndicator.OptionSymbol.Underlying.SecurityType == SecurityType.Equity)
4128  {
4129  // we use point in time raw data to warmup option indicators which use underlying prices and strikes
4130  dataNormalizationMode = DataNormalizationMode.ScaledRaw;
4131  }
4132  return dataNormalizationMode;
4133  }
4134 
4135  private IndicatorHistory IndicatorHistory<T>(IndicatorBase<T> indicator, IEnumerable<Slice> history, Action<IBaseData> updateIndicator, Type dataType = null)
4136  where T : IBaseData
4137  {
4138  // Reset the indicator
4139  indicator.Reset();
4140 
4141  var indicatorType = indicator.GetType();
4142  // Create a dictionary of the indicator properties & the indicator value itself
4143  var indicatorsDataPointPerProperty = indicatorType.GetProperties()
4144  .Where(x => x.PropertyType.IsGenericType && x.Name != "Consolidators" && x.Name != "Window")
4145  .Select(x => InternalIndicatorValues.Create(indicator, x))
4146  .Concat(new[] { InternalIndicatorValues.Create(indicator, "Current") })
4147  .ToList();
4148 
4149  var indicatorsDataPointsByTime = new List<IndicatorDataPoints>();
4150  var lastConsumedTime = DateTime.MinValue;
4151  IndicatorDataPoint lastPoint = null;
4152  void consumeLastPoint(IndicatorDataPoint newInputPoint)
4153  {
4154  if (newInputPoint == null || lastConsumedTime == newInputPoint.EndTime)
4155  {
4156  return;
4157  }
4158  lastConsumedTime = newInputPoint.EndTime;
4159 
4160  var IndicatorDataPoints = new IndicatorDataPoints { Time = newInputPoint.Time, EndTime = newInputPoint.EndTime };
4161  indicatorsDataPointsByTime.Add(IndicatorDataPoints);
4162  for (var i = 0; i < indicatorsDataPointPerProperty.Count; i++)
4163  {
4164  var newPoint = indicatorsDataPointPerProperty[i].UpdateValue();
4165  IndicatorDataPoints.SetProperty(indicatorsDataPointPerProperty[i].Name, newPoint);
4166  }
4167  }
4168 
4169  IndicatorUpdatedHandler callback = (object _, IndicatorDataPoint newInputPoint) =>
4170  {
4171  if (!indicator.IsReady)
4172  {
4173  return;
4174  }
4175 
4176  if (lastPoint == null || lastPoint.Time != newInputPoint.Time)
4177  {
4178  // if null, it's the first point, we transitions from not ready to ready
4179  // else when the time changes we fetch the indicators values, some indicators which consume data from multiple symbols might trigger the Updated event
4180  // even if their value has not changed yet
4181  consumeLastPoint(newInputPoint);
4182  }
4183  lastPoint = newInputPoint;
4184  };
4185 
4186  // register the callback, update the indicator and unregister finally
4187  indicator.Updated += callback;
4188 
4189  if (typeof(T) == typeof(IndicatorDataPoint) || typeof(T).IsAbstract)
4190  {
4191  history.PushThrough(bar => updateIndicator(bar), dataType);
4192  }
4193  else
4194  {
4195  // if the indicator requires a specific type, like a QuoteBar for an equity symbol, we need to fetch it directly
4196  foreach (var dataDictionary in history.Get<T>())
4197  {
4198  foreach (var dataPoint in dataDictionary.Values)
4199  {
4200  updateIndicator(dataPoint);
4201  }
4202  }
4203  }
4204  // flush the last point, this will be useful for indicator consuming time from multiple symbols
4205  consumeLastPoint(lastPoint);
4206  indicator.Updated -= callback;
4207 
4208  return new IndicatorHistory(indicatorsDataPointsByTime, indicatorsDataPointPerProperty,
4209  new Lazy<PyObject>(
4210  () => PandasConverter.GetIndicatorDataFrame(indicatorsDataPointPerProperty.Select(x => new KeyValuePair<string, List<IndicatorDataPoint>>(x.Name, x.Values))),
4211  isThreadSafe: false));
4212  }
4213 
4214  private Type GetDataTypeFromSelector(Func<IBaseData, decimal> selector)
4215  {
4216  Type dataType = null;
4217  if (_quoteRequiredFields.Any(x => ReferenceEquals(selector, x)))
4218  {
4219  dataType = typeof(QuoteBar);
4220  }
4221  else if (ReferenceEquals(selector, Field.Volume))
4222  {
4223  dataType = typeof(TradeBar);
4224  }
4225 
4226  return dataType;
4227  }
4228  }
4229 }