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 QuantConnect.Util;
24 using static QuantConnect.StringExtensions;
25 
26 namespace QuantConnect.Algorithm
27 {
28  public partial class QCAlgorithm
29  {
30  /// <summary>
31  /// Gets whether or not WarmUpIndicator is allowed to warm up indicators/>
32  /// </summary>
33  [DocumentationAttribute(Indicators)]
34  public bool EnableAutomaticIndicatorWarmUp { get; set; } = false;
35 
36  /// <summary>
37  /// Creates a new Acceleration Bands indicator.
38  /// </summary>
39  /// <param name="symbol">The symbol whose Acceleration Bands we want.</param>
40  /// <param name="period">The period of the three moving average (middle, upper and lower band).</param>
41  /// <param name="width">A coefficient specifying the distance between the middle band and upper or lower bands.</param>
42  /// <param name="movingAverageType">Type of the moving average.</param>
43  /// <param name="resolution">The resolution.</param>
44  /// <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>
45  /// <returns></returns>
46  [DocumentationAttribute(Indicators)]
47  public AccelerationBands ABANDS(Symbol symbol, int period, decimal width = 4, MovingAverageType movingAverageType = MovingAverageType.Simple,
48  Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
49  {
50  var name = CreateIndicatorName(symbol, $"ABANDS({period},{width})", resolution);
51  var accelerationBands = new AccelerationBands(name, period, width, movingAverageType);
52  InitializeIndicator(symbol, accelerationBands, resolution, selector);
53 
54  return accelerationBands;
55  }
56 
57  /// <summary>
58  /// Creates a new AccumulationDistribution indicator.
59  /// </summary>
60  /// <param name="symbol">The symbol whose AD we want</param>
61  /// <param name="resolution">The resolution</param>
62  /// <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>
63  /// <returns>The AccumulationDistribution indicator for the requested symbol over the specified period</returns>
64  [DocumentationAttribute(Indicators)]
65  public AccumulationDistribution AD(Symbol symbol, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
66  {
67  var name = CreateIndicatorName(symbol, "AD", resolution);
68  var accumulationDistribution = new AccumulationDistribution(name);
69  InitializeIndicator(symbol, accumulationDistribution, resolution, selector);
70 
71  return accumulationDistribution;
72  }
73 
74  /// <summary>
75  /// Creates a new AccumulationDistributionOscillator indicator.
76  /// </summary>
77  /// <param name="symbol">The symbol whose ADOSC we want</param>
78  /// <param name="fastPeriod">The fast moving average period</param>
79  /// <param name="slowPeriod">The slow moving average period</param>
80  /// <param name="resolution">The resolution</param>
81  /// <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>
82  /// <returns>The AccumulationDistributionOscillator indicator for the requested symbol over the specified period</returns>
83  [DocumentationAttribute(Indicators)]
84  public AccumulationDistributionOscillator ADOSC(Symbol symbol, int fastPeriod, int slowPeriod, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
85  {
86  var name = CreateIndicatorName(symbol, $"ADOSC({fastPeriod},{slowPeriod})", resolution);
87  var accumulationDistributionOscillator = new AccumulationDistributionOscillator(name, fastPeriod, slowPeriod);
88  InitializeIndicator(symbol, accumulationDistributionOscillator, resolution, selector);
89 
90  return accumulationDistributionOscillator;
91  }
92 
93  /// <summary>
94  /// Creates a Alpha indicator for the given target symbol in relation with the reference used.
95  /// The indicator will be automatically updated on the given resolution.
96  /// </summary>
97  /// <param name="target">The target symbol whose Alpha value we want</param>
98  /// <param name="reference">The reference symbol to compare with the target symbol</param>
99  /// <param name="alphaPeriod">The period of the Alpha indicator</param>
100  /// <param name="betaPeriod">The period of the Beta indicator</param>
101  /// <param name="resolution">The resolution</param>
102  /// <param name="riskFreeRate">The risk free rate</param>
103  /// <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>
104  /// <returns>The Alpha indicator for the given parameters</returns>
105  [DocumentationAttribute(Indicators)]
106  public Alpha A(Symbol target, Symbol reference, int alphaPeriod = 1, int betaPeriod = 252, Resolution? resolution = null, decimal? riskFreeRate = null, Func<IBaseData, IBaseDataBar> selector = null)
107  {
108  var baseBame = riskFreeRate.HasValue ? $"A({alphaPeriod},{betaPeriod},{riskFreeRate})" : $"A({alphaPeriod},{betaPeriod})";
109  var name = CreateIndicatorName(target, baseBame, resolution);
110 
111  // If risk free rate is not specified, use the default risk free rate model
112  IRiskFreeInterestRateModel riskFreeRateModel = riskFreeRate.HasValue
113  ? new ConstantRiskFreeRateInterestRateModel(riskFreeRate.Value)
115 
116  var alpha = new Alpha(name, target, reference, alphaPeriod, betaPeriod, riskFreeRateModel);
117  InitializeIndicator(target, alpha, resolution, selector);
118  InitializeIndicator(reference, alpha, resolution, selector);
119 
120  return alpha;
121  }
122 
123  /// <summary>
124  /// Creates a new ARIMA indicator.
125  /// </summary>
126  /// <param name="symbol">The symbol whose ARIMA indicator we want</param>
127  /// <param name="arOrder">AR order (p) -- defines the number of past values to consider in the AR component of the model.</param>
128  /// <param name="diffOrder">Difference order (d) -- defines how many times to difference the model before fitting parameters.</param>
129  /// <param name="maOrder">MA order (q) -- defines the number of past values to consider in the MA component of the model.</param>
130  /// <param name="period">Size of the rolling series to fit onto</param>
131  /// <param name="resolution">The resolution</param>
132  /// <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>
133  /// <returns>The ARIMA indicator for the requested symbol over the specified period</returns>
134  [DocumentationAttribute(Indicators)]
135  public AutoRegressiveIntegratedMovingAverage ARIMA(Symbol symbol, int arOrder, int diffOrder, int maOrder, int period,
136  Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
137  {
138  var name = CreateIndicatorName(symbol, $"ARIMA({arOrder},{diffOrder},{maOrder},{period})", resolution);
139  var arimaIndicator = new AutoRegressiveIntegratedMovingAverage(name, arOrder, diffOrder, maOrder, period);
140  InitializeIndicator(symbol, arimaIndicator, resolution, selector);
141 
142  return arimaIndicator;
143  }
144 
145  /// <summary>
146  /// Creates a new Average Directional Index indicator.
147  /// The indicator will be automatically updated on the given resolution.
148  /// </summary>
149  /// <param name="symbol">The symbol whose Average Directional Index we seek</param>
150  /// <param name="resolution">The resolution.</param>
151  /// <param name="period">The period over which to compute the Average Directional Index</param>
152  /// <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>
153  /// <returns>The Average Directional Index indicator for the requested symbol.</returns>
154  [DocumentationAttribute(Indicators)]
155  public AverageDirectionalIndex ADX(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
156  {
157  var name = CreateIndicatorName(symbol, $"ADX({period})", resolution);
158  var averageDirectionalIndex = new AverageDirectionalIndex(name, period);
159  InitializeIndicator(symbol, averageDirectionalIndex, resolution, selector);
160 
161  return averageDirectionalIndex;
162  }
163 
164  /// <summary>
165  /// Creates a new Awesome Oscillator from the specified periods.
166  /// </summary>
167  /// <param name="symbol">The symbol whose Awesome Oscillator we seek</param>
168  /// <param name="resolution">The resolution.</param>
169  /// <param name="fastPeriod">The period of the fast moving average associated with the AO</param>
170  /// <param name="slowPeriod">The period of the slow moving average associated with the AO</param>
171  /// <param name="type">The type of moving average used when computing the fast and slow term. Defaults to simple moving average.</param>
172  /// <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>
173  [DocumentationAttribute(Indicators)]
174  public AwesomeOscillator AO(Symbol symbol, int slowPeriod, int fastPeriod, MovingAverageType type, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
175  {
176  var name = CreateIndicatorName(symbol, $"AO({fastPeriod},{slowPeriod},{type})", resolution);
177  var awesomeOscillator = new AwesomeOscillator(name, fastPeriod, slowPeriod, type);
178  InitializeIndicator(symbol, awesomeOscillator, resolution, selector);
179 
180  return awesomeOscillator;
181  }
182 
183  /// <summary>
184  /// Creates a new AverageDirectionalMovementIndexRating indicator.
185  /// </summary>
186  /// <param name="symbol">The symbol whose ADXR we want</param>
187  /// <param name="period">The period over which to compute the ADXR</param>
188  /// <param name="resolution">The resolution.</param>
189  /// <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>
190  /// <returns>The AverageDirectionalMovementIndexRating indicator for the requested symbol over the specified period</returns>
191  [DocumentationAttribute(Indicators)]
192  public AverageDirectionalMovementIndexRating ADXR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
193  {
194  var name = CreateIndicatorName(symbol, $"ADXR({period})", resolution);
195  var averageDirectionalMovementIndexRating = new AverageDirectionalMovementIndexRating(name, period);
196  InitializeIndicator(symbol, averageDirectionalMovementIndexRating, resolution, selector);
197 
198  return averageDirectionalMovementIndexRating;
199  }
200 
201  /// <summary>
202  /// Creates a new ArnaudLegouxMovingAverage indicator.
203  /// </summary>
204  /// <param name="symbol">The symbol whose ALMA we want</param>
205  /// <param name="period">int - the number of periods to calculate the ALMA</param>
206  /// <param name="sigma"> int - this parameter is responsible for the shape of the curve coefficients.
207  /// </param>
208  /// <param name="offset">
209  /// decimal - This parameter allows regulating the smoothness and high sensitivity of the
210  /// Moving Average. The range for this parameter is [0, 1].
211  /// </param>
212  /// <param name="resolution">The resolution</param>
213  /// <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>
214  /// <returns>The ArnaudLegouxMovingAverage indicator for the requested symbol over the specified period</returns>
215  [DocumentationAttribute(Indicators)]
216  public ArnaudLegouxMovingAverage ALMA(Symbol symbol, int period, int sigma = 6, decimal offset = 0.85m, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
217  {
218  var name = CreateIndicatorName(symbol, $"ALMA({period},{sigma},{offset})", resolution);
219  var arnaudLegouxMovingAverage = new ArnaudLegouxMovingAverage(name, period, sigma, offset);
220  InitializeIndicator(symbol, arnaudLegouxMovingAverage, resolution, selector);
221 
222  return arnaudLegouxMovingAverage;
223  }
224 
225  /// <summary>
226  /// Creates a new AbsolutePriceOscillator indicator.
227  /// </summary>
228  /// <param name="symbol">The symbol whose APO we want</param>
229  /// <param name="fastPeriod">The fast moving average period</param>
230  /// <param name="slowPeriod">The slow moving average period</param>
231  /// <param name="movingAverageType">The type of moving average to use</param>
232  /// <param name="resolution">The resolution</param>
233  /// <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>
234  /// <returns>The AbsolutePriceOscillator indicator for the requested symbol over the specified period</returns>
235  [DocumentationAttribute(Indicators)]
236  public AbsolutePriceOscillator APO(Symbol symbol, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
237  {
238  var name = CreateIndicatorName(symbol, $"APO({fastPeriod},{slowPeriod})", resolution);
239  var absolutePriceOscillator = new AbsolutePriceOscillator(name, fastPeriod, slowPeriod, movingAverageType);
240  InitializeIndicator(symbol, absolutePriceOscillator, resolution, selector);
241 
242  return absolutePriceOscillator;
243  }
244 
245  /// <summary>
246  /// Creates a new AroonOscillator indicator which will compute the AroonUp and AroonDown (as well as the delta)
247  /// </summary>
248  /// <param name="symbol">The symbol whose Aroon we seek</param>
249  /// <param name="period">The look back period for computing number of periods since maximum and minimum</param>
250  /// <param name="resolution">The resolution</param>
251  /// <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>
252  /// <returns>An AroonOscillator configured with the specified periods</returns>
253  [DocumentationAttribute(Indicators)]
254  public AroonOscillator AROON(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
255  {
256  return AROON(symbol, period, period, resolution, selector);
257  }
258 
259  /// <summary>
260  /// Creates a new AroonOscillator indicator which will compute the AroonUp and AroonDown (as well as the delta)
261  /// </summary>
262  /// <param name="symbol">The symbol whose Aroon we seek</param>
263  /// <param name="upPeriod">The look back period for computing number of periods since maximum</param>
264  /// <param name="downPeriod">The look back period for computing number of periods since minimum</param>
265  /// <param name="resolution">The resolution</param>
266  /// <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>
267  /// <returns>An AroonOscillator configured with the specified periods</returns>
268  [DocumentationAttribute(Indicators)]
269  public AroonOscillator AROON(Symbol symbol, int upPeriod, int downPeriod, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
270  {
271  var name = CreateIndicatorName(symbol, $"AROON({upPeriod},{downPeriod})", resolution);
272  var aroonOscillator = new AroonOscillator(name, upPeriod, downPeriod);
273  InitializeIndicator(symbol, aroonOscillator, resolution, selector);
274 
275  return aroonOscillator;
276  }
277 
278  /// <summary>
279  /// Creates a new AverageTrueRange indicator for the symbol. The indicator will be automatically
280  /// updated on the given resolution.
281  /// </summary>
282  /// <param name="symbol">The symbol whose ATR we want</param>
283  /// <param name="period">The smoothing period used to smooth the computed TrueRange values</param>
284  /// <param name="type">The type of smoothing to use</param>
285  /// <param name="resolution">The resolution</param>
286  /// <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>
287  /// <returns>A new AverageTrueRange indicator with the specified smoothing type and period</returns>
288  [DocumentationAttribute(Indicators)]
289  public AverageTrueRange ATR(Symbol symbol, int period, MovingAverageType type = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
290  {
291  var name = CreateIndicatorName(symbol, $"ATR({period})", resolution);
292  var averageTrueRange = new AverageTrueRange(name, period, type);
293  InitializeIndicator(symbol, averageTrueRange, resolution, selector);
294 
295  return averageTrueRange;
296  }
297 
298  /// <summary>
299  /// Creates an AugenPriceSpike indicator for the symbol. The indicator will be automatically
300  /// updated on the given resolution.
301  /// </summary>
302  /// <param name="symbol">The symbol whose APS we want</param>
303  /// <param name="period">The period of the APS</param>
304  /// <param name="resolution">The resolution</param>
305  /// <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>
306  /// <returns>The AugenPriceSpike indicator for the given parameters</returns>
307  [DocumentationAttribute(Indicators)]
308  public AugenPriceSpike APS(Symbol symbol, int period = 3, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
309  {
310  var name = CreateIndicatorName(symbol, $"APS({period})", resolution);
311  var augenPriceSpike = new AugenPriceSpike(name, period);
312  InitializeIndicator(symbol, augenPriceSpike, resolution, selector);
313 
314  return augenPriceSpike;
315  }
316 
317  /// <summary>
318  /// Creates a new BollingerBands indicator which will compute the MiddleBand, UpperBand, LowerBand, and StandardDeviation
319  /// </summary>
320  /// <param name="symbol">The symbol whose BollingerBands we seek</param>
321  /// <param name="period">The period of the standard deviation and moving average (middle band)</param>
322  /// <param name="k">The number of standard deviations specifying the distance between the middle band and upper or lower bands</param>
323  /// <param name="movingAverageType">The type of moving average to be used</param>
324  /// <param name="resolution">The resolution</param>
325  /// <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>
326  /// <returns>A BollingerBands configured with the specified period</returns>
327  [DocumentationAttribute(Indicators)]
328  public BollingerBands BB(Symbol symbol, int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple,
329  Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
330  {
331  var name = CreateIndicatorName(symbol, $"BB({period},{k})", resolution);
332  var bollingerBands = new BollingerBands(name, period, k, movingAverageType);
333  InitializeIndicator(symbol, bollingerBands, resolution, selector);
334 
335  return bollingerBands;
336  }
337 
338  /// <summary>
339  /// Creates a Beta indicator for the given target symbol in relation with the reference used.
340  /// The indicator will be automatically updated on the given resolution.
341  /// </summary>
342  /// <param name="target">The target symbol whose Beta value we want</param>
343  /// <param name="reference">The reference symbol to compare with the target symbol</param>
344  /// <param name="period">The period of the Beta indicator</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 casting the input value to a TradeBar</param>
347  /// <returns>The Beta indicator for the given parameters</returns>
348  [DocumentationAttribute(Indicators)]
349  public Beta B(Symbol target, Symbol reference, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
350  {
351  var name = CreateIndicatorName(QuantConnect.Symbol.None, $"B({period})", resolution);
352  var beta = new Beta(name, target, reference, period);
353  InitializeIndicator(target, beta, resolution, selector);
354  InitializeIndicator(reference, beta, resolution, selector);
355 
356  return beta;
357  }
358 
359  /// <summary>
360  /// Creates a new Balance Of Power indicator.
361  /// The indicator will be automatically updated on the given resolution.
362  /// </summary>
363  /// <param name="symbol">The symbol whose Balance Of Power we seek</param>
364  /// <param name="resolution">The resolution.</param>
365  /// <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>
366  /// <returns>The Balance Of Power indicator for the requested symbol.</returns>
367  [DocumentationAttribute(Indicators)]
368  public BalanceOfPower BOP(Symbol symbol, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
369  {
370  var name = CreateIndicatorName(symbol, "BOP", resolution);
371  var balanceOfPower = new BalanceOfPower(name);
372  InitializeIndicator(symbol, balanceOfPower, resolution, selector);
373 
374  return balanceOfPower;
375  }
376 
377  /// <summary>
378  /// Initializes a new instance of the <see cref="CoppockCurve"/> indicator
379  /// </summary>
380  /// <param name="symbol">The symbol whose Coppock Curve we want</param>
381  /// <param name="shortRocPeriod">The period for the short ROC</param>
382  /// <param name="longRocPeriod">The period for the long ROC</param>
383  /// <param name="lwmaPeriod">The period for the LWMA</param>
384  /// <param name="resolution">The resolution</param>
385  /// <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>
386  /// <returns>The Coppock Curve indicator for the requested symbol over the specified period</returns>
387  [DocumentationAttribute(Indicators)]
388  public CoppockCurve CC(Symbol symbol, int shortRocPeriod = 11, int longRocPeriod = 14, int lwmaPeriod = 10, Resolution? resolution = null,
389  Func<IBaseData, decimal> selector = null)
390  {
391  var name = CreateIndicatorName(symbol, $"CC({shortRocPeriod},{longRocPeriod},{lwmaPeriod})", resolution);
392  var coppockCurve = new CoppockCurve(name, shortRocPeriod, longRocPeriod, lwmaPeriod);
393  InitializeIndicator(symbol, coppockCurve, resolution, selector);
394 
395  return coppockCurve;
396  }
397 
398  /// <summary>
399  /// Creates a Correlation indicator for the given target symbol in relation with the reference used.
400  /// The indicator will be automatically updated on the given resolution.
401  /// </summary>
402  /// <param name="target">The target symbol of this indicator</param>
403  /// <param name="reference">The reference symbol of this indicator</param>
404  /// <param name="period">The period of this indicator</param>
405  /// <param name="correlationType">Correlation type</param>
406  /// <param name="resolution">The resolution</param>
407  /// <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>
408  /// <returns>The Correlation indicator for the given parameters</returns>
409  [DocumentationAttribute(Indicators)]
410  public Correlation C(Symbol target, Symbol reference, int period, CorrelationType correlationType = CorrelationType.Pearson, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
411  {
412  var name = CreateIndicatorName(QuantConnect.Symbol.None, $"C({period})", resolution);
413  var correlation = new Correlation(name, target, reference, period);
414  InitializeIndicator(target, correlation, resolution, selector);
415  InitializeIndicator(reference, correlation, resolution, selector);
416 
417  return correlation;
418  }
419 
420  /// <summary>
421  /// Creates a new CommodityChannelIndex indicator. The indicator will be automatically
422  /// updated on the given resolution.
423  /// </summary>
424  /// <param name="symbol">The symbol whose CCI we want</param>
425  /// <param name="period">The period over which to compute the CCI</param>
426  /// <param name="movingAverageType">The type of moving average to use in computing the typical price average</param>
427  /// <param name="resolution">The resolution</param>
428  /// <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>
429  /// <returns>The CommodityChannelIndex indicator for the requested symbol over the specified period</returns>
430  [DocumentationAttribute(Indicators)]
431  public CommodityChannelIndex CCI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
432  {
433  var name = CreateIndicatorName(symbol, $"CCI({period})", resolution);
434  var commodityChannelIndex = new CommodityChannelIndex(name, period, movingAverageType);
435  InitializeIndicator(symbol, commodityChannelIndex, resolution, selector);
436 
437  return commodityChannelIndex;
438  }
439 
440  /// <summary>
441  /// Creates a new ChaikinMoneyFlow indicator.
442  /// </summary>
443  /// <param name="symbol">The symbol whose CMF we want</param>
444  /// <param name="period">The period over which to compute the CMF</param>
445  /// <param name="resolution">The resolution</param>
446  /// <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>
447  /// <returns>The ChaikinMoneyFlow indicator for the requested symbol over the specified period</returns>
448  [DocumentationAttribute(Indicators)]
449  public ChaikinMoneyFlow CMF(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
450  {
451  var name = CreateIndicatorName(symbol, $"CMF({period})", resolution);
452  var chaikinMoneyFlow = new ChaikinMoneyFlow(name, period);
453  InitializeIndicator(symbol, chaikinMoneyFlow, resolution, selector);
454 
455  return chaikinMoneyFlow;
456 
457  }
458 
459  /// <summary>
460  /// Creates a new ChandeMomentumOscillator indicator.
461  /// </summary>
462  /// <param name="symbol">The symbol whose CMO we want</param>
463  /// <param name="period">The period over which to compute the CMO</param>
464  /// <param name="resolution">The resolution</param>
465  /// <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>
466  /// <returns>The ChandeMomentumOscillator indicator for the requested symbol over the specified period</returns>
467  [DocumentationAttribute(Indicators)]
468  public ChandeMomentumOscillator CMO(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
469  {
470  var name = CreateIndicatorName(symbol, $"CMO({period})", resolution);
471  var chandeMomentumOscillator = new ChandeMomentumOscillator(name, period);
472  InitializeIndicator(symbol, chandeMomentumOscillator, resolution, selector);
473 
474  return chandeMomentumOscillator;
475  }
476 
477  ///<summary>
478  /// Creates a new DeMarker Indicator (DEM), an oscillator-type indicator measuring changes in terms of an asset's
479  /// High and Low tradebar values.
480  ///</summary>
481  /// <param name="symbol">The symbol whose DEM we seek.</param>
482  /// <param name="period">The period of the moving average implemented</param>
483  /// <param name="type">Specifies the type of moving average to be used</param>
484  /// <param name="resolution">The resolution.</param>
485  /// <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>
486  /// <returns>The DeMarker indicator for the requested symbol.</returns>
487  [DocumentationAttribute(Indicators)]
488  public DeMarkerIndicator DEM(Symbol symbol, int period, MovingAverageType type, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
489  {
490  var name = CreateIndicatorName(symbol, $"DEM({period},{type})", resolution);
491  var deMarkerIndicator = new DeMarkerIndicator(name, period, type);
492  InitializeIndicator(symbol, deMarkerIndicator, resolution, selector);
493  return deMarkerIndicator;
494  }
495 
496  /// <summary>
497  /// Creates a new Donchian Channel indicator which will compute the Upper Band and Lower Band.
498  /// The indicator will be automatically updated on the given resolution.
499  /// </summary>
500  /// <param name="symbol">The symbol whose Donchian Channel we seek.</param>
501  /// <param name="upperPeriod">The period over which to compute the upper Donchian Channel.</param>
502  /// <param name="lowerPeriod">The period over which to compute the lower Donchian Channel.</param>
503  /// <param name="resolution">The resolution.</param>
504  /// <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>
505  /// <returns>The Donchian Channel indicator for the requested symbol.</returns>
506  [DocumentationAttribute(Indicators)]
507  public DonchianChannel DCH(Symbol symbol, int upperPeriod, int lowerPeriod, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
508  {
509  var name = CreateIndicatorName(symbol, $"DCH({upperPeriod},{lowerPeriod})", resolution);
510  var donchianChannel = new DonchianChannel(name, upperPeriod, lowerPeriod);
511  InitializeIndicator(symbol, donchianChannel, resolution, selector);
512 
513  return donchianChannel;
514  }
515 
516  /// <summary>
517  /// Overload shorthand to create a new symmetric Donchian Channel indicator which
518  /// has the upper and lower channels set to the same period length.
519  /// </summary>
520  /// <param name="symbol">The symbol whose Donchian Channel we seek.</param>
521  /// <param name="period">The period over which to compute the Donchian Channel.</param>
522  /// <param name="resolution">The resolution.</param>
523  /// <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>
524  /// <returns>The Donchian Channel indicator for the requested symbol.</returns>
525  [DocumentationAttribute(Indicators)]
526  public DonchianChannel DCH(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
527  {
528  return DCH(symbol, period, period, resolution, selector);
529  }
530 
531  /// <summary>
532  /// Creates a new Delta indicator for the symbol The indicator will be automatically
533  /// updated on the symbol's subscription resolution
534  /// </summary>
535  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
536  /// <param name="mirrorOption">The mirror option for parity calculation</param>
537  /// <param name="riskFreeRate">The risk free rate</param>
538  /// <param name="dividendYield">The dividend yield</param>
539  /// <param name="optionModel">The option pricing model used to estimate Delta</param>
540  /// <param name="ivModel">The option pricing model used to estimate IV</param>
541  /// <param name="resolution">The desired resolution of the data</param>
542  /// <returns>A new Delta indicator for the specified symbol</returns>
543  [DocumentationAttribute(Indicators)]
544  public Delta D(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes,
545  OptionPricingModelType? ivModel = null, Resolution? resolution = null)
546  {
547  var name = InitializeOptionIndicator<Delta>(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution);
548 
549  var delta = new Delta(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel);
550  RegisterIndicator(symbol, delta, ResolveConsolidator(symbol, resolution, typeof(QuoteBar)));
551  RegisterIndicator(symbol.Underlying, delta, ResolveConsolidator(symbol.Underlying, resolution));
552  if (mirrorOption != null)
553  {
554  RegisterIndicator(mirrorOption, delta, ResolveConsolidator(mirrorOption, resolution, typeof(QuoteBar)));
555  }
556  return delta;
557  }
558 
559  /// <summary>
560  /// Creates a new Delta indicator for the symbol The indicator will be automatically
561  /// updated on the symbol's subscription resolution
562  /// </summary>
563  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
564  /// <param name="mirrorOption">The mirror option for parity calculation</param>
565  /// <param name="riskFreeRate">The risk free rate</param>
566  /// <param name="dividendYield">The dividend yield</param>
567  /// <param name="optionModel">The option pricing model used to estimate Delta</param>
568  /// <param name="ivModel">The option pricing model used to estimate IV</param>
569  /// <param name="resolution">The desired resolution of the data</param>
570  /// <returns>A new Delta indicator for the specified symbol</returns>
571  [DocumentationAttribute(Indicators)]
572  public Delta Δ(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes,
573  OptionPricingModelType? ivModel = null, Resolution? resolution = null)
574  {
575  return D(symbol, mirrorOption, riskFreeRate, dividendYield, optionModel, ivModel, resolution);
576  }
577 
578  /// <summary>
579  /// Creates a new DoubleExponentialMovingAverage indicator.
580  /// </summary>
581  /// <param name="symbol">The symbol whose DEMA we want</param>
582  /// <param name="period">The period over which to compute the DEMA</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 the Value property of BaseData (x => x.Value)</param>
585  /// <returns>The DoubleExponentialMovingAverage indicator for the requested symbol over the specified period</returns>
586  [DocumentationAttribute(Indicators)]
587  public DoubleExponentialMovingAverage DEMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
588  {
589  var name = CreateIndicatorName(symbol, $"DEMA({period})", resolution);
590  var doubleExponentialMovingAverage = new DoubleExponentialMovingAverage(name, period);
591  InitializeIndicator(symbol, doubleExponentialMovingAverage, resolution, selector);
592 
593  return doubleExponentialMovingAverage;
594  }
595 
596  /// <summary>
597  /// Creates a new DerivativeOscillator indicator.
598  /// </summary>
599  /// <param name="symbol">The symbol whose DO we want</param>
600  /// <param name="rsiPeriod">The period over which to compute the RSI</param>
601  /// <param name="smoothingRsiPeriod">The period over which to compute the smoothing RSI</param>
602  /// <param name="doubleSmoothingRsiPeriod">The period over which to compute the double smoothing RSI</param>
603  /// <param name="signalLinePeriod">The period over which to compute the signal line</param>
604  /// <param name="resolution">The resolution</param>
605  /// <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>
606  /// <returns>The DerivativeOscillator indicator for the requested symbol over the specified period</returns>
607  [DocumentationAttribute(Indicators)]
608  public DerivativeOscillator DO(Symbol symbol, int rsiPeriod, int smoothingRsiPeriod, int doubleSmoothingRsiPeriod, int signalLinePeriod, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
609  {
610  var name = CreateIndicatorName(symbol, $"DO({rsiPeriod},{smoothingRsiPeriod},{doubleSmoothingRsiPeriod},{signalLinePeriod})", resolution);
611  var derivativeOscillator = new DerivativeOscillator(name, rsiPeriod, smoothingRsiPeriod, doubleSmoothingRsiPeriod, signalLinePeriod);
612  InitializeIndicator(symbol, derivativeOscillator, resolution, selector);
613 
614  return derivativeOscillator;
615  }
616 
617  /// <summary>
618  /// Creates a new <see cref="DetrendedPriceOscillator"/> indicator.
619  /// </summary>
620  /// <param name="symbol">The symbol whose DPO we want</param>
621  /// <param name="period">The period over which to compute the DPO</param>
622  /// <param name="resolution">The resolution</param>
623  /// <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>
624  /// <returns>A new registered DetrendedPriceOscillator indicator for the requested symbol over the specified period</returns>
625  [DocumentationAttribute(Indicators)]
626  public DetrendedPriceOscillator DPO(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
627  {
628  var name = CreateIndicatorName(symbol, $"DPO({period})", resolution);
629  var detrendedPriceOscillator = new DetrendedPriceOscillator(name, period);
630  InitializeIndicator(symbol, detrendedPriceOscillator, resolution, selector);
631 
632  return detrendedPriceOscillator;
633  }
634 
635  /// <summary>
636  /// Creates an ExponentialMovingAverage indicator for the symbol. The indicator will be automatically
637  /// updated on the given resolution.
638  /// </summary>
639  /// <param name="symbol">The symbol whose EMA we want</param>
640  /// <param name="period">The period of the EMA</param>
641  /// <param name="resolution">The resolution</param>
642  /// <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>
643  /// <returns>The ExponentialMovingAverage for the given parameters</returns>
644  [DocumentationAttribute(Indicators)]
645  public ExponentialMovingAverage EMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
646  {
647  return EMA(symbol, period, ExponentialMovingAverage.SmoothingFactorDefault(period), resolution, selector);
648  }
649 
650  /// <summary>
651  /// Creates an ExponentialMovingAverage indicator for the symbol. The indicator will be automatically
652  /// updated on the given resolution.
653  /// </summary>
654  /// <param name="symbol">The symbol whose EMA we want</param>
655  /// <param name="period">The period of the EMA</param>
656  /// <param name="smoothingFactor">The percentage of data from the previous value to be carried into the next value</param>
657  /// <param name="resolution">The resolution</param>
658  /// <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>
659  /// <returns>The ExponentialMovingAverage for the given parameters</returns>
660  [DocumentationAttribute(Indicators)]
661  public ExponentialMovingAverage EMA(Symbol symbol, int period, decimal smoothingFactor, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
662  {
663  var name = CreateIndicatorName(symbol, $"EMA({period})", resolution);
664  var exponentialMovingAverage = new ExponentialMovingAverage(name, period, smoothingFactor);
665  InitializeIndicator(symbol, exponentialMovingAverage, resolution, selector);
666 
667  return exponentialMovingAverage;
668  }
669 
670  /// <summary>
671  /// Creates an EaseOfMovementValue indicator for the symbol. The indicator will be automatically
672  /// updated on the given resolution.
673  /// </summary>
674  /// <param name="symbol">The symbol whose EMV we want</param>
675  /// <param name="period">The period of the EMV</param>
676  /// <param name="scale">The length of the outputed value</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 casting the input value to a TradeBar</param>
679  /// <returns>The EaseOfMovementValue indicator for the given parameters</returns>
680  [DocumentationAttribute(Indicators)]
681  public EaseOfMovementValue EMV(Symbol symbol, int period = 1, int scale = 10000, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
682  {
683  var name = CreateIndicatorName(symbol, $"EMV({period}, {scale})", resolution);
684  var easeOfMovementValue = new EaseOfMovementValue(name, period, scale);
685  InitializeIndicator(symbol, easeOfMovementValue, resolution, selector);
686 
687  return easeOfMovementValue;
688  }
689 
690  /// <summary>
691  /// Creates a new FilteredIdentity indicator for the symbol The indicator will be automatically
692  /// updated on the symbol's subscription resolution
693  /// </summary>
694  /// <param name="symbol">The symbol whose values we want as an indicator</param>
695  /// <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>
696  /// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
697  /// <param name="fieldName">The name of the field being selected</param>
698  /// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
699  [DocumentationAttribute(Indicators)]
700  public FilteredIdentity FilteredIdentity(Symbol symbol, Func<IBaseData, IBaseDataBar> selector = null, Func<IBaseData, bool> filter = null, string fieldName = null)
701  {
702  var resolution = GetSubscription(symbol).Resolution;
703  return FilteredIdentity(symbol, resolution, selector, filter, fieldName);
704  }
705 
706  /// <summary>
707  /// Creates a new FilteredIdentity indicator for the symbol The indicator will be automatically
708  /// updated on the symbol's subscription resolution
709  /// </summary>
710  /// <param name="symbol">The symbol whose values we want as an indicator</param>
711  /// <param name="resolution">The desired resolution of the data</param>
712  /// <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>
713  /// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
714  /// <param name="fieldName">The name of the field being selected</param>
715  /// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
716  [DocumentationAttribute(Indicators)]
717  public FilteredIdentity FilteredIdentity(Symbol symbol, Resolution resolution, Func<IBaseData, IBaseDataBar> selector = null, Func<IBaseData, bool> filter = null, string fieldName = null)
718  {
719  var name = CreateIndicatorName(symbol, fieldName ?? "close", resolution);
720  var filteredIdentity = new FilteredIdentity(name, filter);
721  RegisterIndicator<IBaseData>(symbol, filteredIdentity, resolution, selector);
722  return filteredIdentity;
723  }
724 
725  /// <summary>
726  /// Creates a new FilteredIdentity indicator for the symbol The indicator will be automatically
727  /// updated on the symbol's subscription resolution
728  /// </summary>
729  /// <param name="symbol">The symbol whose values we want as an indicator</param>
730  /// <param name="resolution">The desired resolution of the data</param>
731  /// <param name="selector">Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value)</param>
732  /// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
733  /// <param name="fieldName">The name of the field being selected</param>
734  /// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
735  [DocumentationAttribute(Indicators)]
736  public FilteredIdentity FilteredIdentity(Symbol symbol, TimeSpan resolution, Func<IBaseData, IBaseDataBar> selector = null, Func<IBaseData, bool> filter = null, string fieldName = null)
737  {
738  var name = Invariant($"{symbol}({fieldName ?? "close"}_{resolution})");
739  var filteredIdentity = new FilteredIdentity(name, filter);
740  RegisterIndicator<IBaseData>(symbol, filteredIdentity, ResolveConsolidator(symbol, resolution), selector);
741  return filteredIdentity;
742  }
743 
744  /// <summary>
745  /// Creates an FisherTransform indicator for the symbol.
746  /// The indicator will be automatically updated on the given resolution.
747  /// </summary>
748  /// <param name="symbol">The symbol whose FisherTransform we want</param>
749  /// <param name="period">The period of the FisherTransform</param>
750  /// <param name="resolution">The resolution</param>
751  /// <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>
752  /// <returns>The FisherTransform for the given parameters</returns>
753  [DocumentationAttribute(Indicators)]
754  public FisherTransform FISH(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
755  {
756  var name = CreateIndicatorName(symbol, $"FISH({period})", resolution);
757  var fisherTransform = new FisherTransform(name, period);
758  InitializeIndicator(symbol, fisherTransform, resolution, selector);
759 
760  return fisherTransform;
761  }
762 
763  /// <summary>
764  /// Creates an FractalAdaptiveMovingAverage (FRAMA) indicator for the symbol. The indicator will be automatically
765  /// updated on the given resolution.
766  /// </summary>
767  /// <param name="symbol">The symbol whose FRAMA we want</param>
768  /// <param name="period">The period of the FRAMA</param>
769  /// <param name="longPeriod">The long period of the FRAMA</param>
770  /// <param name="resolution">The resolution</param>
771  /// <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>
772  /// <returns>The FRAMA for the given parameters</returns>
773  [DocumentationAttribute(Indicators)]
774  public FractalAdaptiveMovingAverage FRAMA(Symbol symbol, int period, int longPeriod = 198, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
775  {
776  var name = CreateIndicatorName(symbol, $"FRAMA({period},{longPeriod})", resolution);
777  var fractalAdaptiveMovingAverage = new FractalAdaptiveMovingAverage(name, period, longPeriod);
778  InitializeIndicator(symbol, fractalAdaptiveMovingAverage, resolution, selector);
779 
780  return fractalAdaptiveMovingAverage;
781  }
782 
783  /// <summary>
784  /// Creates a new Gamma indicator for the symbol The indicator will be automatically
785  /// updated on the symbol's subscription resolution
786  /// </summary>
787  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
788  /// <param name="mirrorOption">The mirror option for parity calculation</param>
789  /// <param name="riskFreeRate">The risk free rate</param>
790  /// <param name="dividendYield">The dividend yield</param>
791  /// <param name="optionModel">The option pricing model used to estimate Gamma</param>
792  /// <param name="ivModel">The option pricing model used to estimate IV</param>
793  /// <param name="resolution">The desired resolution of the data</param>
794  /// <returns>A new Gamma indicator for the specified symbol</returns>
795  [DocumentationAttribute(Indicators)]
796  public Gamma G(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes,
797  OptionPricingModelType? ivModel = null, Resolution? resolution = null)
798  {
799  var name = InitializeOptionIndicator<Gamma>(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution);
800 
801  var gamma = new Gamma(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel);
802  RegisterIndicator(symbol, gamma, ResolveConsolidator(symbol, resolution, typeof(QuoteBar)));
803  RegisterIndicator(symbol.Underlying, gamma, ResolveConsolidator(symbol.Underlying, resolution));
804  if (mirrorOption != null)
805  {
806  RegisterIndicator(mirrorOption, gamma, ResolveConsolidator(mirrorOption, resolution, typeof(QuoteBar)));
807  }
808  return gamma;
809  }
810 
811  /// <summary>
812  /// Creates a new Gamma indicator for the symbol The indicator will be automatically
813  /// updated on the symbol's subscription resolution
814  /// </summary>
815  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
816  /// <param name="mirrorOption">The mirror option for parity calculation</param>
817  /// <param name="riskFreeRate">The risk free rate</param>
818  /// <param name="dividendYield">The dividend yield</param>
819  /// <param name="optionModel">The option pricing model used to estimate Gamma</param>
820  /// <param name="ivModel">The option pricing model used to estimate IV</param>
821  /// <param name="resolution">The desired resolution of the data</param>
822  /// <returns>A new Gamma indicator for the specified symbol</returns>
823  [DocumentationAttribute(Indicators)]
824  public Gamma Γ(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes,
825  OptionPricingModelType? ivModel = null, Resolution? resolution = null)
826  {
827  return G(symbol, mirrorOption, riskFreeRate, dividendYield, optionModel, ivModel, resolution);
828  }
829 
830  /// <summary>
831  /// Creates a new Heikin-Ashi indicator.
832  /// </summary>
833  /// <param name="symbol">The symbol whose Heikin-Ashi we want</param>
834  /// <param name="resolution">The resolution</param>
835  /// <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>
836  /// <returns>The Heikin-Ashi indicator for the requested symbol over the specified period</returns>
837  [DocumentationAttribute(Indicators)]
838  public HeikinAshi HeikinAshi(Symbol symbol, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
839  {
840  var name = CreateIndicatorName(symbol, "HA", resolution);
841  var heikinAshi = new HeikinAshi(name);
842  InitializeIndicator(symbol, heikinAshi, resolution, selector);
843 
844  return heikinAshi;
845  }
846 
847  /// <summary>
848  /// Creates a new Hilbert Transform indicator
849  /// </summary>
850  /// <param name="symbol">The symbol whose Hilbert transform we want</param>
851  /// <param name="length">The length of the FIR filter used in the calculation of the Hilbert Transform.
852  /// This parameter determines the number of filter coefficients in the FIR filter.</param>
853  /// <param name="inPhaseMultiplicationFactor">The multiplication factor used in the calculation of the in-phase component
854  /// of the Hilbert Transform. This parameter adjusts the sensitivity and responsiveness of
855  /// the transform to changes in the input signal.</param>
856  /// <param name="quadratureMultiplicationFactor">The multiplication factor used in the calculation of the quadrature component of
857  /// the Hilbert Transform. This parameter also adjusts the sensitivity and responsiveness of the
858  /// transform to changes in the input signal.</param>
859  /// <param name="resolution">The resolution</param>
860  /// <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>
861  [DocumentationAttribute(Indicators)]
862  public HilbertTransform HT(Symbol symbol, int length, decimal inPhaseMultiplicationFactor, decimal quadratureMultiplicationFactor, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
863  {
864  var name = CreateIndicatorName(symbol, $"HT({length}, {inPhaseMultiplicationFactor}, {quadratureMultiplicationFactor})", resolution);
865  var hilbertTransform = new HilbertTransform(length, inPhaseMultiplicationFactor, quadratureMultiplicationFactor);
866  InitializeIndicator(symbol, hilbertTransform, resolution, selector);
867 
868  return hilbertTransform;
869  }
870 
871  /// <summary>
872  /// Creates a new HullMovingAverage indicator. The Hull moving average is a series of nested weighted moving averages, is fast and smooth.
873  /// </summary>
874  /// <param name="symbol">The symbol whose Hull moving average we want</param>
875  /// <param name="period">The period over which to compute the Hull moving average</param>
876  /// <param name="resolution">The resolution</param>
877  /// <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>
878  /// <returns></returns>
879  [DocumentationAttribute(Indicators)]
880  public HullMovingAverage HMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
881  {
882  var name = CreateIndicatorName(symbol, $"HMA({period})", resolution);
883  var hullMovingAverage = new HullMovingAverage(name, period);
884  InitializeIndicator(symbol, hullMovingAverage, resolution, selector);
885 
886  return hullMovingAverage;
887  }
888 
889  /// <summary>
890  /// Creates a new IchimokuKinkoHyo indicator for the symbol. The indicator will be automatically
891  /// updated on the given resolution.
892  /// </summary>
893  /// <param name="symbol">The symbol whose ICHIMOKU we want</param>
894  /// <param name="tenkanPeriod">The period to calculate the Tenkan-sen period</param>
895  /// <param name="kijunPeriod">The period to calculate the Kijun-sen period</param>
896  /// <param name="senkouAPeriod">The period to calculate the Tenkan-sen period</param>
897  /// <param name="senkouBPeriod">The period to calculate the Tenkan-sen period</param>
898  /// <param name="senkouADelayPeriod">The period to calculate the Tenkan-sen period</param>
899  /// <param name="senkouBDelayPeriod">The period to calculate the Tenkan-sen period</param>
900  /// <param name="resolution">The resolution</param>
901  /// <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>
902  /// <returns>A new IchimokuKinkoHyo indicator with the specified periods and delays</returns>
903  [DocumentationAttribute(Indicators)]
904  public IchimokuKinkoHyo ICHIMOKU(Symbol symbol, int tenkanPeriod, int kijunPeriod, int senkouAPeriod, int senkouBPeriod,
905  int senkouADelayPeriod, int senkouBDelayPeriod, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
906  {
907  var name = CreateIndicatorName(symbol, $"ICHIMOKU({tenkanPeriod},{kijunPeriod},{senkouAPeriod},{senkouBPeriod},{senkouADelayPeriod},{senkouBDelayPeriod})", resolution);
908  var ichimokuKinkoHyo = new IchimokuKinkoHyo(name, tenkanPeriod, kijunPeriod, senkouAPeriod, senkouBPeriod, senkouADelayPeriod, senkouBDelayPeriod);
909  InitializeIndicator(symbol, ichimokuKinkoHyo, resolution, selector);
910 
911  return ichimokuKinkoHyo;
912  }
913 
914  /// <summary>
915  /// Creates a new Identity indicator for the symbol The indicator will be automatically
916  /// updated on the symbol's subscription resolution
917  /// </summary>
918  /// <param name="symbol">The symbol whose values we want as an indicator</param>
919  /// <param name="selector">Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value)</param>
920  /// <param name="fieldName">The name of the field being selected</param>
921  /// <returns>A new Identity indicator for the specified symbol and selector</returns>
922  [DocumentationAttribute(Indicators)]
923  public Identity Identity(Symbol symbol, Func<IBaseData, decimal> selector = null, string fieldName = null)
924  {
925  var resolution = GetSubscription(symbol).Resolution;
926  return Identity(symbol, resolution, selector, fieldName);
927  }
928 
929  /// <summary>
930  /// Creates a new Identity indicator for the symbol The indicator will be automatically
931  /// updated on the symbol's subscription resolution
932  /// </summary>
933  /// <param name="symbol">The symbol whose values we want as an indicator</param>
934  /// <param name="resolution">The desired resolution of the data</param>
935  /// <param name="selector">Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value)</param>
936  /// <param name="fieldName">The name of the field being selected</param>
937  /// <returns>A new Identity indicator for the specified symbol and selector</returns>
938  [DocumentationAttribute(Indicators)]
939  public Identity Identity(Symbol symbol, Resolution resolution, Func<IBaseData, decimal> selector = null, string fieldName = null)
940  {
941  var name = CreateIndicatorName(symbol, fieldName ?? "close", resolution);
942  var identity = new Identity(name);
943  RegisterIndicator(symbol, identity, resolution, selector);
944  return identity;
945  }
946 
947  /// <summary>
948  /// Creates a new Identity indicator for the symbol The indicator will be automatically
949  /// updated on the symbol's subscription resolution
950  /// </summary>
951  /// <param name="symbol">The symbol whose values we want as an indicator</param>
952  /// <param name="resolution">The desired resolution of the data</param>
953  /// <param name="selector">Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value)</param>
954  /// <param name="fieldName">The name of the field being selected</param>
955  /// <returns>A new Identity indicator for the specified symbol and selector</returns>
956  [DocumentationAttribute(Indicators)]
957  public Identity Identity(Symbol symbol, TimeSpan resolution, Func<IBaseData, decimal> selector = null, string fieldName = null)
958  {
959  var name = Invariant($"{symbol}({fieldName ?? "close"},{resolution})");
960  var identity = new Identity(name);
961  RegisterIndicator(symbol, identity, ResolveConsolidator(symbol, resolution), selector);
962  return identity;
963  }
964 
965  /// <summary>
966  /// Creates a new ImpliedVolatility indicator for the symbol The indicator will be automatically
967  /// updated on the symbol's subscription resolution
968  /// </summary>
969  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
970  /// <param name="mirrorOption">The mirror option contract used for parity type calculation</param>
971  /// <param name="riskFreeRate">The risk free rate</param>
972  /// <param name="dividendYield">The dividend yield</param>
973  /// <param name="optionModel">The option pricing model used to estimate IV</param>
974  /// <param name="period">The lookback period of historical volatility</param>
975  /// <param name="resolution">The desired resolution of the data</param>
976  /// <returns>A new ImpliedVolatility indicator for the specified symbol</returns>
977  [DocumentationAttribute(Indicators)]
978  public ImpliedVolatility IV(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null,
979  OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes, int period = 252, Resolution? resolution = null)
980  {
981  var name = InitializeOptionIndicator<ImpliedVolatility>(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution);
982 
983  var iv = new ImpliedVolatility(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel);
984  RegisterIndicator(symbol, iv, ResolveConsolidator(symbol, resolution, typeof(QuoteBar)));
985  RegisterIndicator(symbol.Underlying, iv, ResolveConsolidator(symbol.Underlying, resolution));
986  if (mirrorOption != null)
987  {
988  RegisterIndicator(mirrorOption, iv, ResolveConsolidator(mirrorOption, resolution, typeof(QuoteBar)));
989  }
990  return iv;
991  }
992 
993  /// <summary>
994  /// Creates a new KaufmanAdaptiveMovingAverage indicator.
995  /// </summary>
996  /// <param name="symbol">The symbol whose KAMA we want</param>
997  /// <param name="period">The period of the Efficiency Ratio (ER) of KAMA</param>
998  /// <param name="resolution">The resolution</param>
999  /// <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>
1000  /// <returns>The KaufmanAdaptiveMovingAverage indicator for the requested symbol over the specified period</returns>
1001  [DocumentationAttribute(Indicators)]
1002  public KaufmanAdaptiveMovingAverage KAMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1003  {
1004  return KAMA(symbol, period, 2, 30, resolution, selector);
1005  }
1006 
1007  /// <summary>
1008  /// Creates a new KaufmanAdaptiveMovingAverage indicator.
1009  /// </summary>
1010  /// <param name="symbol">The symbol whose KAMA we want</param>
1011  /// <param name="period">The period of the Efficiency Ratio (ER)</param>
1012  /// <param name="fastEmaPeriod">The period of the fast EMA used to calculate the Smoothing Constant (SC)</param>
1013  /// <param name="slowEmaPeriod">The period of the slow EMA used to calculate the Smoothing Constant (SC)</param>
1014  /// <param name="resolution">The resolution</param>
1015  /// <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>
1016  /// <returns>The KaufmanAdaptiveMovingAverage indicator for the requested symbol over the specified period</returns>
1017  [DocumentationAttribute(Indicators)]
1018  public KaufmanAdaptiveMovingAverage KAMA(Symbol symbol, int period, int fastEmaPeriod, int slowEmaPeriod, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1019  {
1020  var name = CreateIndicatorName(symbol, $"KAMA({period},{fastEmaPeriod},{slowEmaPeriod})", resolution);
1021  var kaufmanAdaptiveMovingAverage = new KaufmanAdaptiveMovingAverage(name, period, fastEmaPeriod, slowEmaPeriod);
1022  InitializeIndicator(symbol, kaufmanAdaptiveMovingAverage, resolution, selector);
1023 
1024  return kaufmanAdaptiveMovingAverage;
1025  }
1026 
1027  /// <summary>
1028  /// Creates an KaufmanEfficiencyRatio indicator for the symbol. The indicator will be automatically
1029  /// updated on the given resolution.
1030  /// </summary>
1031  /// <param name="symbol">The symbol whose EF we want</param>
1032  /// <param name="period">The period of the EF</param>
1033  /// <param name="resolution">The resolution</param>
1034  /// <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>
1035  /// <returns>The KaufmanEfficiencyRatio indicator for the given parameters</returns>
1036  [DocumentationAttribute(Indicators)]
1037  public KaufmanEfficiencyRatio KER(Symbol symbol, int period = 2, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1038  {
1039  var name = CreateIndicatorName(symbol, $"KER({period})", resolution);
1040  var kaufmanEfficiencyRatio = new KaufmanEfficiencyRatio(name, period);
1041  InitializeIndicator(symbol, kaufmanEfficiencyRatio, resolution, selector);
1042 
1043  return kaufmanEfficiencyRatio;
1044  }
1045 
1046  /// <summary>
1047  /// Creates a new Keltner Channels indicator.
1048  /// The indicator will be automatically updated on the given resolution.
1049  /// </summary>
1050  /// <param name="symbol">The symbol whose Keltner Channel we seek</param>
1051  /// <param name="period">The period over which to compute the Keltner Channels</param>
1052  /// <param name="k">The number of multiples of the <see cref="AverageTrueRange"/> from the middle band of the Keltner Channels</param>
1053  /// <param name="movingAverageType">Specifies the type of moving average to be used as the middle line of the Keltner Channel</param>
1054  /// <param name="resolution">The resolution.</param>
1055  /// <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>
1056  /// <returns>The Keltner Channel indicator for the requested symbol.</returns>
1057  [DocumentationAttribute(Indicators)]
1058  public KeltnerChannels KCH(Symbol symbol, int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
1059  {
1060  var name = CreateIndicatorName(symbol, $"KCH({period},{k})", resolution);
1061  var keltnerChannels = new KeltnerChannels(name, period, k, movingAverageType);
1062  InitializeIndicator(symbol, keltnerChannels, resolution, selector);
1063 
1064  return keltnerChannels;
1065  }
1066 
1067  /// <summary>
1068  /// Creates a new LogReturn indicator.
1069  /// </summary>
1070  /// <param name="symbol">The symbol whose log return we seek</param>
1071  /// <param name="period">The period of the log return.</param>
1072  /// <param name="resolution">The resolution.</param>
1073  /// <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>
1074  /// <returns>log return indicator for the requested symbol.</returns>
1075  [DocumentationAttribute(Indicators)]
1076  public LogReturn LOGR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1077  {
1078  var name = CreateIndicatorName(symbol, $"LOGR({period})", resolution);
1079  var logReturn = new LogReturn(name, period);
1080  InitializeIndicator(symbol, logReturn, resolution, selector);
1081 
1082  return logReturn;
1083  }
1084 
1085  /// <summary>
1086  /// Creates and registers a new Least Squares Moving Average instance.
1087  /// </summary>
1088  /// <param name="symbol">The symbol whose LSMA we seek.</param>
1089  /// <param name="period">The LSMA period. Normally 14.</param>
1090  /// <param name="resolution">The resolution.</param>
1091  /// <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>
1092  /// <returns>A LeastSquaredMovingAverage configured with the specified period</returns>
1093  [DocumentationAttribute(Indicators)]
1094  public LeastSquaresMovingAverage LSMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1095  {
1096  var name = CreateIndicatorName(symbol, $"LSMA({period})", resolution);
1097  var leastSquaresMovingAverage = new LeastSquaresMovingAverage(name, period);
1098  InitializeIndicator(symbol, leastSquaresMovingAverage, resolution, selector);
1099 
1100  return leastSquaresMovingAverage;
1101  }
1102 
1103  /// <summary>
1104  /// Creates a new LinearWeightedMovingAverage indicator. This indicator will linearly distribute
1105  /// the weights across the periods.
1106  /// </summary>
1107  /// <param name="symbol">The symbol whose LWMA we want</param>
1108  /// <param name="period">The period over which to compute the LWMA</param>
1109  /// <param name="resolution">The resolution</param>
1110  /// <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>
1111  /// <returns></returns>
1112  [DocumentationAttribute(Indicators)]
1113  public LinearWeightedMovingAverage LWMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1114  {
1115  var name = CreateIndicatorName(symbol, $"LWMA({period})", resolution);
1116  var linearWeightedMovingAverage = new LinearWeightedMovingAverage(name, period);
1117  InitializeIndicator(symbol, linearWeightedMovingAverage, resolution, selector);
1118 
1119  return linearWeightedMovingAverage;
1120  }
1121 
1122  /// <summary>
1123  /// Creates a MACD indicator for the symbol. The indicator will be automatically updated on the given resolution.
1124  /// </summary>
1125  /// <param name="symbol">The symbol whose MACD we want</param>
1126  /// <param name="fastPeriod">The period for the fast moving average</param>
1127  /// <param name="slowPeriod">The period for the slow moving average</param>
1128  /// <param name="signalPeriod">The period for the signal moving average</param>
1129  /// <param name="type">The type of moving average to use for the MACD</param>
1130  /// <param name="resolution">The resolution</param>
1131  /// <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>
1132  /// <returns>The moving average convergence divergence between the fast and slow averages</returns>
1133  [DocumentationAttribute(Indicators)]
1134  public MovingAverageConvergenceDivergence MACD(Symbol symbol, int fastPeriod, int slowPeriod, int signalPeriod, MovingAverageType type = MovingAverageType.Exponential, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1135  {
1136  var name = CreateIndicatorName(symbol, $"MACD({fastPeriod},{slowPeriod},{signalPeriod})", resolution);
1137  var movingAverageConvergenceDivergence = new MovingAverageConvergenceDivergence(name, fastPeriod, slowPeriod, signalPeriod, type);
1138  InitializeIndicator(symbol, movingAverageConvergenceDivergence, resolution, selector);
1139 
1140  return movingAverageConvergenceDivergence;
1141  }
1142 
1143  /// <summary>
1144  /// Creates a new MeanAbsoluteDeviation indicator.
1145  /// </summary>
1146  /// <param name="symbol">The symbol whose MeanAbsoluteDeviation we want</param>
1147  /// <param name="period">The period over which to compute the MeanAbsoluteDeviation</param>
1148  /// <param name="resolution">The resolution</param>
1149  /// <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>
1150  /// <returns>The MeanAbsoluteDeviation indicator for the requested symbol over the specified period</returns>
1151  [DocumentationAttribute(Indicators)]
1152  public MeanAbsoluteDeviation MAD(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1153  {
1154  var name = CreateIndicatorName(symbol, $"MAD({period})", resolution);
1155  var meanAbsoluteDeviation = new MeanAbsoluteDeviation(name, period);
1156  InitializeIndicator(symbol, meanAbsoluteDeviation, resolution, selector);
1157 
1158  return meanAbsoluteDeviation;
1159  }
1160 
1161  /// <summary>
1162  /// Creates an Market Profile indicator for the symbol with Volume Profile (VOL) mode. The indicator will be automatically
1163  /// updated on the given resolution.
1164  /// </summary>
1165  /// <param name="symbol">The symbol whose VP we want</param>
1166  /// <param name="period">The period of the VP</param>
1167  /// <param name="valueAreaVolumePercentage">The percentage of volume contained in the value area</param>
1168  /// <param name="priceRangeRoundOff">How many digits you want to round and the precision. i.e 0.01 round to two digits exactly.</param>
1169  /// <param name="resolution">The resolution</param>
1170  /// <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>
1171  /// <returns>The Volume Profile indicator for the given parameters</returns>
1172  [DocumentationAttribute(Indicators)]
1173  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)
1174  {
1175  var name = CreateIndicatorName(symbol, $"VP({period})", resolution);
1176  var marketProfile = new VolumeProfile(name, period, valueAreaVolumePercentage, priceRangeRoundOff);
1177  InitializeIndicator(symbol, marketProfile, resolution, selector);
1178 
1179  return marketProfile;
1180  }
1181 
1182  /// <summary>
1183  /// Creates an Market Profile indicator for the symbol with Time Price Opportunity (TPO) mode. The indicator will be automatically
1184  /// updated on the given resolution.
1185  /// </summary>
1186  /// <param name="symbol">The symbol whose TP we want</param>
1187  /// <param name="period">The period of the TP</param>
1188  /// <param name="valueAreaVolumePercentage">The percentage of volume contained in the value area</param>
1189  /// <param name="priceRangeRoundOff">How many digits you want to round and the precision. i.e 0.01 round to two digits exactly.</param>
1190  /// <param name="resolution">The resolution</param>
1191  /// <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>
1192  /// <returns>The Time Profile indicator for the given parameters</returns>
1193  [DocumentationAttribute(Indicators)]
1194  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)
1195  {
1196  var name = CreateIndicatorName(symbol, $"TP({period})", resolution);
1197  var marketProfile = new TimeProfile(name, period, valueAreaVolumePercentage, priceRangeRoundOff);
1198  InitializeIndicator(symbol, marketProfile, resolution, selector);
1199 
1200  return marketProfile;
1201  }
1202 
1203  /// <summary>
1204  /// Creates a new Time Series Forecast indicator
1205  /// </summary>
1206  /// <param name="symbol">The symbol whose TSF we want</param>
1207  /// <param name="period">The period of the TSF</param>
1208  /// <param name="resolution">The resolution</param>
1209  /// <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>
1210  /// <returns>The TimeSeriesForecast indicator for the requested symbol over the specified period</returns>
1211  [DocumentationAttribute(Indicators)]
1212  public TimeSeriesForecast TSF(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1213  {
1214  var name = CreateIndicatorName(symbol, $"TSF({period})", resolution);
1215  var timeSeriesForecast = new TimeSeriesForecast(name, period);
1216  InitializeIndicator(symbol, timeSeriesForecast, resolution, selector);
1217 
1218  return timeSeriesForecast;
1219  }
1220 
1221  /// <summary>
1222  /// Creates a new Maximum indicator to compute the maximum value
1223  /// </summary>
1224  /// <param name="symbol">The symbol whose max we want</param>
1225  /// <param name="period">The look back period over which to compute the max value</param>
1226  /// <param name="resolution">The resolution</param>
1227  /// <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,
1228  /// otherwise it defaults to Value property of BaseData (x => x.Value)</param>
1229  /// <returns>A Maximum indicator that compute the max value and the periods since the max value</returns>
1230  [DocumentationAttribute(Indicators)]
1231  public Maximum MAX(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1232  {
1233  var name = CreateIndicatorName(symbol, $"MAX({period})", resolution);
1234  var maximum = new Maximum(name, period);
1235 
1236  // assign a default value for the selector function
1237  if (selector == null)
1238  {
1239  var subscription = GetSubscription(symbol);
1240  if (typeof(TradeBar).IsAssignableFrom(subscription.Type))
1241  {
1242  // if we have trade bar data we'll use the High property, if not x => x.Value will be set in RegisterIndicator
1243  selector = x => ((TradeBar)x).High;
1244  }
1245  }
1246 
1247  RegisterIndicator(symbol, maximum, ResolveConsolidator(symbol, resolution), selector);
1248 
1250  {
1251  WarmUpIndicator(symbol, maximum, resolution, selector);
1252  }
1253 
1254  return maximum;
1255  }
1256 
1257  /// <summary>
1258  /// Creates a new MoneyFlowIndex indicator. The indicator will be automatically
1259  /// updated on the given resolution.
1260  /// </summary>
1261  /// <param name="symbol">The symbol whose MFI we want</param>
1262  /// <param name="period">The period over which to compute the MFI</param>
1263  /// <param name="resolution">The resolution</param>
1264  /// <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>
1265  /// <returns>The MoneyFlowIndex indicator for the requested symbol over the specified period</returns>
1266  [DocumentationAttribute(Indicators)]
1267  public MoneyFlowIndex MFI(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
1268  {
1269  var name = CreateIndicatorName(symbol, $"MFI({period})", resolution);
1270  var moneyFlowIndex = new MoneyFlowIndex(name, period);
1271  InitializeIndicator(symbol, moneyFlowIndex, resolution, selector);
1272 
1273  return moneyFlowIndex;
1274  }
1275 
1276  /// <summary>
1277  /// Creates a new Mass Index indicator. The indicator will be automatically
1278  /// updated on the given resolution.
1279  /// </summary>
1280  /// <param name="symbol">The symbol whose Mass Index we want.</param>
1281  /// <param name="emaPeriod">The period used by both EMA.</param>
1282  /// <param name="sumPeriod">The sum period.</param>
1283  /// <param name="resolution">The resolution.</param>
1284  /// <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>
1285  /// <returns>The Mass Index indicator for the requested symbol over the specified period</returns>
1286  [DocumentationAttribute(Indicators)]
1287  public MassIndex MASS(Symbol symbol, int emaPeriod = 9, int sumPeriod = 25, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
1288  {
1289  var name = CreateIndicatorName(symbol, $"MASS({emaPeriod},{sumPeriod})", resolution);
1290  var massIndex = new MassIndex(name, emaPeriod, sumPeriod);
1291  InitializeIndicator(symbol, massIndex, resolution, selector);
1292 
1293  return massIndex;
1294  }
1295 
1296  /// <summary>
1297  /// Creates a new MidPoint indicator.
1298  /// </summary>
1299  /// <param name="symbol">The symbol whose MIDPOINT we want</param>
1300  /// <param name="period">The period over which to compute the MIDPOINT</param>
1301  /// <param name="resolution">The resolution</param>
1302  /// <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>
1303  /// <returns>The MidPoint indicator for the requested symbol over the specified period</returns>
1304  [DocumentationAttribute(Indicators)]
1305  public MidPoint MIDPOINT(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1306  {
1307  var name = CreateIndicatorName(symbol, $"MIDPOINT({period})", resolution);
1308  var midPoint = new MidPoint(name, period);
1309  InitializeIndicator(symbol, midPoint, resolution, selector);
1310 
1311  return midPoint;
1312  }
1313 
1314  /// <summary>
1315  /// Creates a new MidPrice indicator.
1316  /// </summary>
1317  /// <param name="symbol">The symbol whose MIDPRICE we want</param>
1318  /// <param name="period">The period over which to compute the MIDPRICE</param>
1319  /// <param name="resolution">The resolution</param>
1320  /// <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>
1321  /// <returns>The MidPrice indicator for the requested symbol over the specified period</returns>
1322  [DocumentationAttribute(Indicators)]
1323  public MidPrice MIDPRICE(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
1324  {
1325  var name = CreateIndicatorName(symbol, $"MIDPRICE({period})", resolution);
1326  var midPrice = new MidPrice(name, period);
1327  InitializeIndicator(symbol, midPrice, resolution, selector);
1328 
1329  return midPrice;
1330  }
1331 
1332  /// <summary>
1333  /// Creates a new Minimum indicator to compute the minimum value
1334  /// </summary>
1335  /// <param name="symbol">The symbol whose min we want</param>
1336  /// <param name="period">The look back period over which to compute the min value</param>
1337  /// <param name="resolution">The resolution</param>
1338  /// <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,
1339  /// otherwise it defaults to Value property of BaseData (x => x.Value)</param>
1340  /// <returns>A Minimum indicator that compute the in value and the periods since the min value</returns>
1341  [DocumentationAttribute(Indicators)]
1342  public Minimum MIN(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1343  {
1344  var name = CreateIndicatorName(symbol, $"MIN({period})", resolution);
1345  var minimum = new Minimum(name, period);
1346 
1347  // assign a default value for the selector function
1348  if (selector == null)
1349  {
1350  var subscription = GetSubscription(symbol);
1351  if (typeof(TradeBar).IsAssignableFrom(subscription.Type))
1352  {
1353  // if we have trade bar data we'll use the Low property, if not x => x.Value will be set in RegisterIndicator
1354  selector = x => ((TradeBar)x).Low;
1355  }
1356  }
1357 
1358  RegisterIndicator(symbol, minimum, ResolveConsolidator(symbol, resolution), selector);
1359 
1361  {
1362  WarmUpIndicator(symbol, minimum, resolution, selector);
1363  }
1364 
1365  return minimum;
1366  }
1367 
1368  /// <summary>
1369  /// Creates a new Momentum indicator. This will compute the absolute n-period change in the security.
1370  /// The indicator will be automatically updated on the given resolution.
1371  /// </summary>
1372  /// <param name="symbol">The symbol whose momentum we want</param>
1373  /// <param name="period">The period over which to compute the momentum</param>
1374  /// <param name="resolution">The resolution</param>
1375  /// <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>
1376  /// <returns>The momentum indicator for the requested symbol over the specified period</returns>
1377  [DocumentationAttribute(Indicators)]
1378  public Momentum MOM(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1379  {
1380  var name = CreateIndicatorName(symbol, $"MOM({period})", resolution);
1381  var momentum = new Momentum(name, period);
1382  InitializeIndicator(symbol, momentum, resolution, selector);
1383 
1384  return momentum;
1385  }
1386 
1387  /// <summary>
1388  /// Creates a new Momersion indicator.
1389  /// </summary>
1390  /// <param name="symbol">The symbol whose Momersion we want</param>
1391  /// <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>
1392  /// <param name="fullPeriod">The full period over which to compute the Momersion</param>
1393  /// <param name="resolution">The resolution</param>
1394  /// <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>
1395  /// <returns>The Momersion indicator for the requested symbol over the specified period</returns>
1396  [DocumentationAttribute(Indicators)]
1397  public MomersionIndicator MOMERSION(Symbol symbol, int? minPeriod, int fullPeriod, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1398  {
1399  var name = CreateIndicatorName(symbol, $"MOMERSION({minPeriod},{fullPeriod})", resolution);
1400  var momersion = new MomersionIndicator(name, minPeriod, fullPeriod);
1401  InitializeIndicator(symbol, momersion, resolution, selector);
1402 
1403  return momersion;
1404  }
1405 
1406  /// <summary>
1407  /// Creates a new MomentumPercent indicator. This will compute the n-period percent change in the security.
1408  /// The indicator will be automatically updated on the given resolution.
1409  /// </summary>
1410  /// <param name="symbol">The symbol whose momentum we want</param>
1411  /// <param name="period">The period over which to compute the momentum</param>
1412  /// <param name="resolution">The resolution</param>
1413  /// <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>
1414  /// <returns>The momentum indicator for the requested symbol over the specified period</returns>
1415  [DocumentationAttribute(Indicators)]
1416  public MomentumPercent MOMP(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1417  {
1418  var name = CreateIndicatorName(symbol, $"MOMP({period})", resolution);
1419  var momentumPercent = new MomentumPercent(name, period);
1420  InitializeIndicator(symbol, momentumPercent, resolution, selector);
1421 
1422  return momentumPercent;
1423  }
1424 
1425  /// <summary>
1426  /// Creates a new NormalizedAverageTrueRange indicator.
1427  /// </summary>
1428  /// <param name="symbol">The symbol whose NATR we want</param>
1429  /// <param name="period">The period over which to compute the NATR</param>
1430  /// <param name="resolution">The resolution</param>
1431  /// <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>
1432  /// <returns>The NormalizedAverageTrueRange indicator for the requested symbol over the specified period</returns>
1433  [DocumentationAttribute(Indicators)]
1434  public NormalizedAverageTrueRange NATR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
1435  {
1436  var name = CreateIndicatorName(symbol, $"NATR({period})", resolution);
1437  var normalizedAverageTrueRange = new NormalizedAverageTrueRange(name, period);
1438  InitializeIndicator(symbol, normalizedAverageTrueRange, resolution, selector);
1439 
1440  return normalizedAverageTrueRange;
1441  }
1442 
1443  /// <summary>
1444  /// Creates a new On Balance Volume indicator. This will compute the cumulative total volume
1445  /// based on whether the close price being higher or lower than the previous period.
1446  /// The indicator will be automatically updated on the given resolution.
1447  /// </summary>
1448  /// <param name="symbol">The symbol whose On Balance Volume we seek</param>
1449  /// <param name="resolution">The resolution.</param>
1450  /// <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>
1451  /// <returns>The On Balance Volume indicator for the requested symbol.</returns>
1452  [DocumentationAttribute(Indicators)]
1453  public OnBalanceVolume OBV(Symbol symbol, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
1454  {
1455  var name = CreateIndicatorName(symbol, "OBV", resolution);
1456  var onBalanceVolume = new OnBalanceVolume(name);
1457  InitializeIndicator(symbol, onBalanceVolume, resolution, selector);
1458 
1459  return onBalanceVolume;
1460  }
1461 
1462  /// <summary>
1463  /// Creates a new PivotPointsHighLow indicator
1464  /// </summary>
1465  /// <param name="symbol">The symbol whose PPHL we seek</param>
1466  /// <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>
1467  /// <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>
1468  /// <param name="lastStoredValues">The number of last stored indicator values</param>
1469  /// <param name="resolution">The resolution</param>
1470  /// <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>
1471  /// <returns>The PivotPointsHighLow indicator for the requested symbol.</returns>
1472  [DocumentationAttribute(Indicators)]
1473  public PivotPointsHighLow PPHL(Symbol symbol, int lengthHigh, int lengthLow, int lastStoredValues = 100, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
1474  {
1475  var name = CreateIndicatorName(symbol, $"PPHL({lengthHigh},{lengthLow})", resolution);
1476  var pivotPointsHighLow = new PivotPointsHighLow(name, lengthHigh, lengthLow, lastStoredValues);
1477  InitializeIndicator(symbol, pivotPointsHighLow, resolution, selector);
1478 
1479  return pivotPointsHighLow;
1480  }
1481 
1482  /// <summary>
1483  /// Creates a new PercentagePriceOscillator indicator.
1484  /// </summary>
1485  /// <param name="symbol">The symbol whose PPO we want</param>
1486  /// <param name="fastPeriod">The fast moving average period</param>
1487  /// <param name="slowPeriod">The slow moving average period</param>
1488  /// <param name="movingAverageType">The type of moving average to use</param>
1489  /// <param name="resolution">The resolution</param>
1490  /// <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>
1491  /// <returns>The PercentagePriceOscillator indicator for the requested symbol over the specified period</returns>
1492  [DocumentationAttribute(Indicators)]
1493  public PercentagePriceOscillator PPO(Symbol symbol, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1494  {
1495  var name = CreateIndicatorName(symbol, $"PPO({fastPeriod},{slowPeriod})", resolution);
1496  var percentagePriceOscillator = new PercentagePriceOscillator(name, fastPeriod, slowPeriod, movingAverageType);
1497  InitializeIndicator(symbol, percentagePriceOscillator, resolution, selector);
1498 
1499  return percentagePriceOscillator;
1500  }
1501 
1502  /// <summary>
1503  /// Creates a new Parabolic SAR indicator
1504  /// </summary>
1505  /// <param name="symbol">The symbol whose PSAR we seek</param>
1506  /// <param name="afStart">Acceleration factor start value. Normally 0.02</param>
1507  /// <param name="afIncrement">Acceleration factor increment value. Normally 0.02</param>
1508  /// <param name="afMax">Acceleration factor max value. Normally 0.2</param>
1509  /// <param name="resolution">The resolution</param>
1510  /// <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>
1511  /// <returns>A ParabolicStopAndReverse configured with the specified periods</returns>
1512  [DocumentationAttribute(Indicators)]
1513  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)
1514  {
1515  var name = CreateIndicatorName(symbol, $"PSAR({afStart},{afIncrement},{afMax})", resolution);
1516  var parabolicStopAndReverse = new ParabolicStopAndReverse(name, afStart, afIncrement, afMax);
1517  InitializeIndicator(symbol, parabolicStopAndReverse, resolution, selector);
1518 
1519  return parabolicStopAndReverse;
1520  }
1521 
1522  /// <summary>
1523  /// Creates a new RegressionChannel indicator which will compute the LinearRegression, UpperChannel and LowerChannel lines, the intercept and slope
1524  /// </summary>
1525  /// <param name="symbol">The symbol whose RegressionChannel we seek</param>
1526  /// <param name="period">The period of the standard deviation and least square moving average (linear regression line)</param>
1527  /// <param name="k">The number of standard deviations specifying the distance between the linear regression and upper or lower channel lines</param>
1528  /// <param name="resolution">The resolution</param>
1529  /// <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>
1530  /// <returns>A Regression Channel configured with the specified period and number of standard deviation</returns>
1531  [DocumentationAttribute(Indicators)]
1532  public RegressionChannel RC(Symbol symbol, int period, decimal k, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1533  {
1534  var name = CreateIndicatorName(symbol, $"RC({period},{k})", resolution);
1535  var regressionChannel = new RegressionChannel(name, period, k);
1536  InitializeIndicator(symbol, regressionChannel, resolution, selector);
1537 
1538  return regressionChannel;
1539  }
1540 
1541  /// <summary>
1542  /// Creates a new Relative Moving Average indicator for the symbol. The indicator will be automatically updated on the given resolution.
1543  /// </summary>
1544  /// <param name="symbol">The symbol whose relative moving average we seek</param>
1545  /// <param name="period">The period of the relative moving average</param>
1546  /// <param name="resolution">The resolution</param>
1547  /// <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>
1548  /// <returns>A relative moving average configured with the specified period and number of standard deviation</returns>
1549  [DocumentationAttribute(Indicators)]
1550  public RelativeMovingAverage RMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1551  {
1552  var name = CreateIndicatorName(symbol, $"RMA({period})", resolution);
1553  var relativeMovingAverage = new RelativeMovingAverage(name, period);
1554  InitializeIndicator(symbol, relativeMovingAverage, resolution, selector);
1555 
1556  return relativeMovingAverage;
1557  }
1558 
1559 
1560  /// <summary>
1561  /// Creates a new RateOfChange indicator. This will compute the n-period rate of change in the security.
1562  /// The indicator will be automatically updated on the given resolution.
1563  /// </summary>
1564  /// <param name="symbol">The symbol whose RateOfChange we want</param>
1565  /// <param name="period">The period over which to compute the RateOfChange</param>
1566  /// <param name="resolution">The resolution</param>
1567  /// <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>
1568  /// <returns>The RateOfChange indicator for the requested symbol over the specified period</returns>
1569  [DocumentationAttribute(Indicators)]
1570  public RateOfChange ROC(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1571  {
1572  var name = CreateIndicatorName(symbol, $"ROC({period})", resolution);
1573  var rateOfChange = new RateOfChange(name, period);
1574  InitializeIndicator(symbol, rateOfChange, resolution, selector);
1575 
1576  return rateOfChange;
1577  }
1578 
1579  /// <summary>
1580  /// Creates a new RateOfChangePercent indicator. This will compute the n-period percentage rate of change in the security.
1581  /// The indicator will be automatically updated on the given resolution.
1582  /// </summary>
1583  /// <param name="symbol">The symbol whose RateOfChangePercent we want</param>
1584  /// <param name="period">The period over which to compute the RateOfChangePercent</param>
1585  /// <param name="resolution">The resolution</param>
1586  /// <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>
1587  /// <returns>The RateOfChangePercent indicator for the requested symbol over the specified period</returns>
1588  [DocumentationAttribute(Indicators)]
1589  public RateOfChangePercent ROCP(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1590  {
1591  var name = CreateIndicatorName(symbol, $"ROCP({period})", resolution);
1592  var rateOfChangePercent = new RateOfChangePercent(name, period);
1593  InitializeIndicator(symbol, rateOfChangePercent, resolution, selector);
1594 
1595  return rateOfChangePercent;
1596  }
1597 
1598  /// <summary>
1599  /// Creates a new RateOfChangeRatio indicator.
1600  /// </summary>
1601  /// <param name="symbol">The symbol whose ROCR we want</param>
1602  /// <param name="period">The period over which to compute the ROCR</param>
1603  /// <param name="resolution">The resolution</param>
1604  /// <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>
1605  /// <returns>The RateOfChangeRatio indicator for the requested symbol over the specified period</returns>
1606  [DocumentationAttribute(Indicators)]
1607  public RateOfChangeRatio ROCR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1608  {
1609  var name = CreateIndicatorName(symbol, $"ROCR({period})", resolution);
1610  var rateOfChangeRatio = new RateOfChangeRatio(name, period);
1611  InitializeIndicator(symbol, rateOfChangeRatio, resolution, selector);
1612 
1613  return rateOfChangeRatio;
1614  }
1615 
1616  /// <summary>
1617  /// Creates a new RelativeStrengthIndex indicator. This will produce an oscillator that ranges from 0 to 100 based
1618  /// on the ratio of average gains to average losses over the specified period.
1619  /// </summary>
1620  /// <param name="symbol">The symbol whose RSI we want</param>
1621  /// <param name="period">The period over which to compute the RSI</param>
1622  /// <param name="movingAverageType">The type of moving average to use in computing the average gain/loss values</param>
1623  /// <param name="resolution">The resolution</param>
1624  /// <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>
1625  /// <returns>The RelativeStrengthIndex indicator for the requested symbol over the specified period</returns>
1626  [DocumentationAttribute(Indicators)]
1627  public RelativeStrengthIndex RSI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Wilders, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1628  {
1629  var name = CreateIndicatorName(symbol, $"RSI({period},{movingAverageType})", resolution);
1630  var relativeStrengthIndex = new RelativeStrengthIndex(name, period, movingAverageType);
1631  InitializeIndicator(symbol, relativeStrengthIndex, resolution, selector);
1632 
1633  return relativeStrengthIndex;
1634  }
1635 
1636  /// <summary>
1637  /// Creates a new RelativeVigorIndex indicator.
1638  /// </summary>
1639  /// <param name="symbol">The symbol whose RVI we want</param>
1640  /// <param name="period">The period over which to compute the RVI</param>
1641  /// <param name="movingAverageType">The type of moving average to use</param>
1642  /// <param name="resolution">The resolution</param>
1643  /// <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>
1644  /// <returns>The RelativeVigorIndex indicator for the requested symbol over the specified period</returns>
1645  [DocumentationAttribute(Indicators)]
1646  public RelativeVigorIndex RVI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
1647  {
1648  var name = CreateIndicatorName(symbol, $"RVI({period},{movingAverageType})", resolution);
1649  var relativeVigorIndex = new RelativeVigorIndex(name, period, movingAverageType);
1650  InitializeIndicator(symbol, relativeVigorIndex, resolution, selector);
1651 
1652  return relativeVigorIndex;
1653  }
1654 
1655  /// <summary>
1656  /// Creates an RelativeDailyVolume indicator for the symbol. The indicator will be automatically
1657  /// updated on the given resolution.
1658  /// </summary>
1659  /// <param name="symbol">The symbol whose RDV we want</param>
1660  /// <param name="period">The period of the RDV</param>
1661  /// <param name="resolution">The resolution</param>
1662  /// <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>
1663  /// <returns>The Relative Volume indicator for the given parameters</returns>
1664  [DocumentationAttribute(Indicators)]
1665  public RelativeDailyVolume RDV(Symbol symbol, int period = 2, Resolution resolution = Resolution.Daily, Func<IBaseData, TradeBar> selector = null)
1666  {
1667  var name = CreateIndicatorName(symbol, $"RDV({period})", resolution);
1668  var relativeDailyVolume = new RelativeDailyVolume(name, period);
1669  RegisterIndicator(symbol, relativeDailyVolume, resolution, selector);
1670 
1671  return relativeDailyVolume;
1672  }
1673 
1674  /// <summary>
1675  /// Creates a new Rho indicator for the symbol The indicator will be automatically
1676  /// updated on the symbol's subscription resolution
1677  /// </summary>
1678  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
1679  /// <param name="mirrorOption">The mirror option for parity calculation</param>
1680  /// <param name="riskFreeRate">The risk free rate</param>
1681  /// <param name="dividendYield">The dividend yield</param>
1682  /// <param name="optionModel">The option pricing model used to estimate Rho</param>
1683  /// <param name="ivModel">The option pricing model used to estimate IV</param>
1684  /// <param name="resolution">The desired resolution of the data</param>
1685  /// <returns>A new Rho indicator for the specified symbol</returns>
1686  [DocumentationAttribute(Indicators)]
1687  public Rho R(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes,
1688  OptionPricingModelType? ivModel = null, Resolution? resolution = null)
1689  {
1690  var name = InitializeOptionIndicator<Rho>(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution);
1691 
1692  var rho = new Rho(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel);
1693  RegisterIndicator(symbol, rho, ResolveConsolidator(symbol, resolution, typeof(QuoteBar)));
1694  RegisterIndicator(symbol.Underlying, rho, ResolveConsolidator(symbol.Underlying, resolution));
1695  if (mirrorOption != null)
1696  {
1697  RegisterIndicator(mirrorOption, rho, ResolveConsolidator(mirrorOption, resolution, typeof(QuoteBar)));
1698  }
1699  return rho;
1700  }
1701 
1702  /// <summary>
1703  /// Creates a new Rho indicator for the symbol The indicator will be automatically
1704  /// updated on the symbol's subscription resolution
1705  /// </summary>
1706  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
1707  /// <param name="mirrorOption">The mirror option for parity calculation</param>
1708  /// <param name="riskFreeRate">The risk free rate</param>
1709  /// <param name="dividendYield">The dividend yield</param>
1710  /// <param name="optionModel">The option pricing model used to estimate Rho</param>
1711  /// <param name="ivModel">The option pricing model used to estimate IV</param>
1712  /// <param name="resolution">The desired resolution of the data</param>
1713  /// <returns>A new Rho indicator for the specified symbol</returns>
1714  [DocumentationAttribute(Indicators)]
1715  public Rho ρ(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes,
1716  OptionPricingModelType? ivModel = null, Resolution? resolution = null)
1717  {
1718  return R(symbol, mirrorOption, riskFreeRate, dividendYield, optionModel, ivModel, resolution);
1719  }
1720 
1721  /// <summary>
1722  /// Creates a new SuperTrend indicator.
1723  /// </summary>
1724  /// <param name="symbol">The symbol whose SuperTrend indicator we want.</param>
1725  /// <param name="period">The smoothing period for average true range.</param>
1726  /// <param name="multiplier">Multiplier to calculate basic upper and lower bands width.</param>
1727  /// <param name="movingAverageType">Smoother type for average true range, defaults to Wilders.</param>
1728  /// <param name="resolution">The resolution.</param>
1729  /// <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>
1730  [DocumentationAttribute(Indicators)]
1731  public SuperTrend STR(Symbol symbol, int period, decimal multiplier, MovingAverageType movingAverageType = MovingAverageType.Wilders,
1732  Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
1733  {
1734  var name = CreateIndicatorName(symbol, $"STR({period},{multiplier})", resolution);
1735  var strend = new SuperTrend(name, period, multiplier, movingAverageType);
1736  InitializeIndicator(symbol, strend, resolution, selector);
1737 
1738  return strend;
1739  }
1740 
1741  /// <summary>
1742  /// Creates a new SharpeRatio indicator.
1743  /// </summary>
1744  /// <param name="symbol">The symbol whose RSR we want</param>
1745  /// <param name="sharpePeriod">Period of historical observation for sharpe ratio calculation</param>
1746  /// <param name="riskFreeRate">
1747  /// Risk-free rate for sharpe ratio calculation. If not specified, it will use the algorithms' <see cref="RiskFreeInterestRateModel"/>
1748  /// </param>
1749  /// <param name="resolution">The resolution</param>
1750  /// <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>
1751  /// <returns>The SharpeRatio indicator for the requested symbol over the specified period</returns>
1752  [DocumentationAttribute(Indicators)]
1753  public SharpeRatio SR(Symbol symbol, int sharpePeriod, decimal? riskFreeRate = null, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1754  {
1755  var baseBame = riskFreeRate.HasValue ? $"SR({sharpePeriod},{riskFreeRate})" : $"SR({sharpePeriod})";
1756  var name = CreateIndicatorName(symbol, baseBame, resolution);
1757  IRiskFreeInterestRateModel riskFreeRateModel = riskFreeRate.HasValue
1758  ? new ConstantRiskFreeRateInterestRateModel(riskFreeRate.Value)
1759  // Make it a function so it's lazily evaluated: SetRiskFreeInterestRateModel can be called after this method
1761  var sharpeRatio = new SharpeRatio(name, sharpePeriod, riskFreeRateModel);
1762  InitializeIndicator(symbol, sharpeRatio, resolution, selector);
1763 
1764  return sharpeRatio;
1765  }
1766 
1767  /// <summary>
1768  /// Creates a new Sortino indicator.
1769  /// </summary>
1770  /// <param name="symbol">The symbol whose Sortino we want</param>
1771  /// <param name="sortinoPeriod">Period of historical observation for Sortino ratio calculation</param>
1772  /// <param name="minimumAcceptableReturn">Minimum acceptable return (eg risk-free rate) for the Sortino ratio calculation</param>
1773  /// <param name="resolution">The resolution</param>
1774  /// <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>
1775  /// <returns>The SortinoRatio indicator for the requested symbol over the specified period</returns>
1776  [DocumentationAttribute(Indicators)]
1777  public SortinoRatio SORTINO(Symbol symbol, int sortinoPeriod, double minimumAcceptableReturn = 0.0, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1778  {
1779  var name = CreateIndicatorName(symbol, $"SORTINO({sortinoPeriod},{minimumAcceptableReturn})", resolution);
1780  var sortinoRatio = new SortinoRatio(name, sortinoPeriod, minimumAcceptableReturn);
1781  InitializeIndicator(symbol, sortinoRatio, resolution, selector);
1782 
1783  return sortinoRatio;
1784  }
1785 
1786 
1787  /// <summary>
1788  /// Creates an SimpleMovingAverage indicator for the symbol. The indicator will be automatically
1789  /// updated on the given resolution.
1790  /// </summary>
1791  /// <param name="symbol">The symbol whose SMA we want</param>
1792  /// <param name="period">The period of the SMA</param>
1793  /// <param name="resolution">The resolution</param>
1794  /// <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>
1795  /// <returns>The SimpleMovingAverage for the given parameters</returns>
1796  [DocumentationAttribute(Indicators)]
1797  public SimpleMovingAverage SMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1798  {
1799  var name = CreateIndicatorName(symbol, $"SMA({period})", resolution);
1800  var simpleMovingAverage = new SimpleMovingAverage(name, period);
1801  InitializeIndicator(symbol, simpleMovingAverage, resolution, selector);
1802 
1803  return simpleMovingAverage;
1804  }
1805 
1806  /// <summary>
1807  /// Creates a new Schaff Trend Cycle indicator
1808  /// </summary>
1809  /// <param name="symbol">The symbol for the indicator to track</param>
1810  /// <param name="fastPeriod">The fast moving average period</param>
1811  /// <param name="slowPeriod">The slow moving average period</param>
1812  /// <param name="cyclePeriod">The signal period</param>
1813  /// <param name="movingAverageType">The type of moving average to use</param>
1814  /// <param name="resolution">The resolution</param>
1815  /// <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>
1816  /// <returns>The SchaffTrendCycle indicator for the requested symbol over the specified period</returns>
1817  [DocumentationAttribute(Indicators)]
1818  public SchaffTrendCycle STC(Symbol symbol, int cyclePeriod, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType = MovingAverageType.Exponential, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1819  {
1820  var name = CreateIndicatorName(symbol, $"STC({cyclePeriod},{fastPeriod},{slowPeriod})", resolution);
1821  var schaffTrendCycle = new SchaffTrendCycle(name, cyclePeriod, fastPeriod, slowPeriod, movingAverageType);
1822  InitializeIndicator(symbol, schaffTrendCycle, resolution, selector);
1823 
1824  return schaffTrendCycle;
1825  }
1826 
1827  /// <summary>
1828  /// Creates a new StandardDeviation indicator. This will return the population standard deviation of samples over the specified period.
1829  /// </summary>
1830  /// <param name="symbol">The symbol whose STD we want</param>
1831  /// <param name="period">The period over which to compute the STD</param>
1832  /// <param name="resolution">The resolution</param>
1833  /// <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>
1834  /// <returns>The StandardDeviation indicator for the requested symbol over the specified period</returns>
1835  [DocumentationAttribute(Indicators)]
1836  public StandardDeviation STD(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1837  {
1838  var name = CreateIndicatorName(symbol, $"STD({period})", resolution);
1839  var standardDeviation = new StandardDeviation(name, period);
1840  InitializeIndicator(symbol, standardDeviation, resolution, selector);
1841 
1842  return standardDeviation;
1843  }
1844 
1845  /// <summary>
1846  /// Creates a new TargetDownsideDeviation indicator. The target downside deviation is defined as the root-mean-square, or RMS, of the deviations of the
1847  /// realized return’s underperformance from the target return where all returns above the target return are treated as underperformance of 0.
1848  /// </summary>
1849  /// <param name="symbol">The symbol whose TDD we want</param>
1850  /// <param name="period">The period over which to compute the TDD</param>
1851  /// <param name="resolution">The resolution</param>
1852  /// <param name="minimumAcceptableReturn">Minimum acceptable return (MAR) for the target downside deviation calculation</param>
1853  /// <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>
1854  /// <returns>The TargetDownsideDeviation indicator for the requested symbol over the specified period</returns>
1855  [DocumentationAttribute(Indicators)]
1856  public TargetDownsideDeviation TDD(Symbol symbol, int period, double minimumAcceptableReturn = 0, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1857  {
1858  var name = CreateIndicatorName(symbol, $"TDD({period},{minimumAcceptableReturn})", resolution);
1859  var targetDownsideDeviation = new TargetDownsideDeviation(name, period, minimumAcceptableReturn);
1860  InitializeIndicator(symbol, targetDownsideDeviation, resolution, selector);
1861 
1862  return targetDownsideDeviation;
1863  }
1864 
1865  /// <summary>
1866  /// Creates a new Stochastic indicator.
1867  /// </summary>
1868  /// <param name="symbol">The symbol whose stochastic we seek</param>
1869  /// <param name="period">The period of the stochastic. Normally 14</param>
1870  /// <param name="kPeriod">The sum period of the stochastic. Normally 14</param>
1871  /// <param name="dPeriod">The sum period of the stochastic. Normally 3</param>
1872  /// <param name="resolution">The resolution.</param>
1873  /// <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>
1874  /// <returns>Stochastic indicator for the requested symbol.</returns>
1875  [DocumentationAttribute(Indicators)]
1876  public Stochastic STO(Symbol symbol, int period, int kPeriod, int dPeriod, Resolution? resolution = null,
1877  Func<IBaseData, TradeBar> selector = null)
1878  {
1879  var name = CreateIndicatorName(symbol, $"STO({period},{kPeriod},{dPeriod})", resolution);
1880  var stochastic = new Stochastic(name, period, kPeriod, dPeriod);
1881  InitializeIndicator(symbol, stochastic, resolution, selector);
1882 
1883  return stochastic;
1884  }
1885 
1886  /// <summary>
1887  /// Overload short hand to create a new Stochastic indicator; defaulting to the 3 period for dStoch
1888  /// </summary>
1889  /// <param name="symbol">The symbol whose stochastic we seek</param>
1890  /// <param name="resolution">The resolution.</param>
1891  /// <param name="period">The period of the stochastic. Normally 14</param>
1892  /// <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>
1893  /// <returns>Stochastic indicator for the requested symbol.</returns>
1894  [DocumentationAttribute(Indicators)]
1895  public Stochastic STO(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
1896  {
1897  return STO(symbol, period, period, 3, resolution, selector);
1898  }
1899 
1900  /// <summary>
1901  /// Creates a new Sum indicator.
1902  /// </summary>
1903  /// <param name="symbol">The symbol whose Sum we want</param>
1904  /// <param name="period">The period over which to compute the Sum</param>
1905  /// <param name="resolution">The resolution</param>
1906  /// <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>
1907  /// <returns>The Sum indicator for the requested symbol over the specified period</returns>
1908  [DocumentationAttribute(Indicators)]
1909  public Sum SUM(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1910  {
1911  var name = CreateIndicatorName(symbol, $"SUM({period})", resolution);
1912  var sum = new Sum(name, period);
1913  InitializeIndicator(symbol, sum, resolution, selector);
1914 
1915  return sum;
1916  }
1917 
1918  /// <summary>
1919  /// Creates Swiss Army Knife transformation for the symbol. The indicator will be automatically
1920  /// updated on the given resolution.
1921  /// </summary>
1922  /// <param name="symbol">The symbol to use for calculations</param>
1923  /// <param name="period">The period of the calculation</param>
1924  /// <param name="delta">The delta scale of the BandStop or BandPass</param>
1925  /// <param name="tool">The tool os the Swiss Army Knife</param>
1926  /// <param name="resolution">The resolution</param>
1927  /// <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>
1928  /// <returns>The calculation using the given tool</returns>
1929  [DocumentationAttribute(Indicators)]
1930  public SwissArmyKnife SWISS(Symbol symbol, int period, double delta, SwissArmyKnifeTool tool, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1931  {
1932  var name = CreateIndicatorName(symbol, $"SWISS({period},{delta},{tool})", resolution);
1933  var swissArmyKnife = new SwissArmyKnife(name, period, delta, tool);
1934  InitializeIndicator(symbol, swissArmyKnife, resolution, selector);
1935 
1936  return swissArmyKnife;
1937  }
1938 
1939  /// <summary>
1940  /// Creates a new Theta indicator for the symbol The indicator will be automatically
1941  /// updated on the symbol's subscription resolution
1942  /// </summary>
1943  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
1944  /// <param name="mirrorOption">The mirror option for parity calculation</param>
1945  /// <param name="riskFreeRate">The risk free rate</param>
1946  /// <param name="dividendYield">The dividend yield</param>
1947  /// <param name="optionModel">The option pricing model used to estimate Theta</param>
1948  /// <param name="ivModel">The option pricing model used to estimate IV</param>
1949  /// <param name="resolution">The desired resolution of the data</param>
1950  /// <returns>A new Theta indicator for the specified symbol</returns>
1951  [DocumentationAttribute(Indicators)]
1952  public Theta T(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes,
1953  OptionPricingModelType? ivModel = null, Resolution? resolution = null)
1954  {
1955  var name = InitializeOptionIndicator<Theta>(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution);
1956 
1957  var theta = new Theta(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel);
1958  RegisterIndicator(symbol, theta, ResolveConsolidator(symbol, resolution, typeof(QuoteBar)));
1959  RegisterIndicator(symbol.Underlying, theta, ResolveConsolidator(symbol.Underlying, resolution));
1960  if (mirrorOption != null)
1961  {
1962  RegisterIndicator(mirrorOption, theta, ResolveConsolidator(mirrorOption, resolution, typeof(QuoteBar)));
1963  }
1964  return theta;
1965  }
1966 
1967  /// <summary>
1968  /// Creates a new Theta indicator for the symbol The indicator will be automatically
1969  /// updated on the symbol's subscription resolution
1970  /// </summary>
1971  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
1972  /// <param name="mirrorOption">The mirror option for parity calculation</param>
1973  /// <param name="riskFreeRate">The risk free rate</param>
1974  /// <param name="dividendYield">The dividend yield</param>
1975  /// <param name="optionModel">The option pricing model used to estimate Theta</param>
1976  /// <param name="ivModel">The option pricing model used to estimate IV</param>
1977  /// <param name="resolution">The desired resolution of the data</param>
1978  /// <returns>A new Theta indicator for the specified symbol</returns>
1979  [DocumentationAttribute(Indicators)]
1980  public Theta Θ(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes,
1981  OptionPricingModelType? ivModel = null, Resolution? resolution = null)
1982  {
1983  return T(symbol, mirrorOption, riskFreeRate, dividendYield, optionModel, ivModel, resolution);
1984  }
1985 
1986  /// <summary>
1987  /// Creates a new T3MovingAverage indicator.
1988  /// </summary>
1989  /// <param name="symbol">The symbol whose T3 we want</param>
1990  /// <param name="period">The period over which to compute the T3</param>
1991  /// <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>
1992  /// <param name="resolution">The resolution</param>
1993  /// <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>
1994  /// <returns>The T3MovingAverage indicator for the requested symbol over the specified period</returns>
1995  [DocumentationAttribute(Indicators)]
1996  public T3MovingAverage T3(Symbol symbol, int period, decimal volumeFactor = 0.7m, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
1997  {
1998  var name = CreateIndicatorName(symbol, $"T3({period},{volumeFactor})", resolution);
1999  var t3MovingAverage = new T3MovingAverage(name, period, volumeFactor);
2000  InitializeIndicator(symbol, t3MovingAverage, resolution, selector);
2001 
2002  return t3MovingAverage;
2003  }
2004 
2005  /// <summary>
2006  /// Creates a new TripleExponentialMovingAverage indicator.
2007  /// </summary>
2008  /// <param name="symbol">The symbol whose TEMA we want</param>
2009  /// <param name="period">The period over which to compute the TEMA</param>
2010  /// <param name="resolution">The resolution</param>
2011  /// <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>
2012  /// <returns>The TripleExponentialMovingAverage indicator for the requested symbol over the specified period</returns>
2013  [DocumentationAttribute(Indicators)]
2014  public TripleExponentialMovingAverage TEMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2015  {
2016  var name = CreateIndicatorName(symbol, $"TEMA({period})", resolution);
2017  var tripleExponentialMovingAverage = new TripleExponentialMovingAverage(name, period);
2018  InitializeIndicator(symbol, tripleExponentialMovingAverage, resolution, selector);
2019 
2020  return tripleExponentialMovingAverage;
2021  }
2022 
2023  /// <summary>
2024  /// Creates a TrueStrengthIndex indicator for the symbol. The indicator will be automatically
2025  /// updated on the given resolution.
2026  /// </summary>
2027  /// <param name="symbol">The symbol whose TSI we want</param>
2028  /// <param name="shortTermPeriod">Period used for the first price change smoothing</param>
2029  /// <param name="longTermPeriod">Period used for the second (double) price change smoothing</param>
2030  /// <param name="signalPeriod">The signal period</param>
2031  /// <param name="signalType">The type of moving average to use for the signal</param>
2032  /// <param name="resolution">The resolution</param>
2033  /// <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>
2034  /// <returns>The TrueStrengthIndex indicator for the given parameters</returns>
2035  [DocumentationAttribute(Indicators)]
2036  public TrueStrengthIndex TSI(Symbol symbol, int longTermPeriod = 25, int shortTermPeriod = 13, int signalPeriod = 7,
2037  MovingAverageType signalType = MovingAverageType.Exponential, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2038  {
2039  var name = CreateIndicatorName(symbol, $"TSI({longTermPeriod},{shortTermPeriod},{signalPeriod})", resolution);
2040  var trueStrengthIndex = new TrueStrengthIndex(name, longTermPeriod, shortTermPeriod, signalPeriod, signalType);
2041  InitializeIndicator(symbol, trueStrengthIndex, resolution, selector);
2042 
2043  return trueStrengthIndex;
2044  }
2045 
2046  /// <summary>
2047  /// Creates a new TrueRange indicator.
2048  /// </summary>
2049  /// <param name="symbol">The symbol whose TR we want</param>
2050  /// <param name="resolution">The resolution</param>
2051  /// <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>
2052  /// <returns>The TrueRange indicator for the requested symbol.</returns>
2053  [DocumentationAttribute(Indicators)]
2054  public TrueRange TR(Symbol symbol, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
2055  {
2056  var name = CreateIndicatorName(symbol, "TR", resolution);
2057  var trueRange = new TrueRange(name);
2058  InitializeIndicator(symbol, trueRange, resolution, selector);
2059 
2060  return trueRange;
2061  }
2062 
2063  /// <summary>
2064  /// Creates a new TriangularMovingAverage indicator.
2065  /// </summary>
2066  /// <param name="symbol">The symbol whose TRIMA we want</param>
2067  /// <param name="period">The period over which to compute the TRIMA</param>
2068  /// <param name="resolution">The resolution</param>
2069  /// <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>
2070  /// <returns>The TriangularMovingAverage indicator for the requested symbol over the specified period</returns>
2071  [DocumentationAttribute(Indicators)]
2072  public TriangularMovingAverage TRIMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2073  {
2074  var name = CreateIndicatorName(symbol, $"TRIMA({period})", resolution);
2075  var triangularMovingAverage = new TriangularMovingAverage(name, period);
2076  InitializeIndicator(symbol, triangularMovingAverage, resolution, selector);
2077 
2078  return triangularMovingAverage;
2079  }
2080 
2081  /// <summary>
2082  /// Creates a new Trix indicator.
2083  /// </summary>
2084  /// <param name="symbol">The symbol whose TRIX we want</param>
2085  /// <param name="period">The period over which to compute the TRIX</param>
2086  /// <param name="resolution">The resolution</param>
2087  /// <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>
2088  /// <returns>The Trix indicator for the requested symbol over the specified period</returns>
2089  [DocumentationAttribute(Indicators)]
2090  public Trix TRIX(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2091  {
2092  var name = CreateIndicatorName(symbol, $"TRIX({period})", resolution);
2093  var trix = new Trix(name, period);
2094  InitializeIndicator(symbol, trix, resolution, selector);
2095 
2096  return trix;
2097  }
2098 
2099  /// <summary>
2100  /// Creates a new UltimateOscillator indicator.
2101  /// </summary>
2102  /// <param name="symbol">The symbol whose ULTOSC we want</param>
2103  /// <param name="period1">The first period over which to compute the ULTOSC</param>
2104  /// <param name="period2">The second period over which to compute the ULTOSC</param>
2105  /// <param name="period3">The third period over which to compute the ULTOSC</param>
2106  /// <param name="resolution">The resolution</param>
2107  /// <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>
2108  /// <returns>The UltimateOscillator indicator for the requested symbol over the specified period</returns>
2109  [DocumentationAttribute(Indicators)]
2110  public UltimateOscillator ULTOSC(Symbol symbol, int period1, int period2, int period3, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
2111  {
2112  var name = CreateIndicatorName(symbol, $"ULTOSC({period1},{period2},{period3})", resolution);
2113  var ultimateOscillator = new UltimateOscillator(name, period1, period2, period3);
2114  InitializeIndicator(symbol, ultimateOscillator, resolution, selector);
2115 
2116  return ultimateOscillator;
2117  }
2118 
2119  /// <summary>
2120  /// Creates a new Vega indicator for the symbol The indicator will be automatically
2121  /// updated on the symbol's subscription resolution
2122  /// </summary>
2123  /// <param name="symbol">The option symbol whose values we want as an indicator</param>
2124  /// <param name="mirrorOption">The mirror option for parity calculation</param>
2125  /// <param name="riskFreeRate">The risk free rate</param>
2126  /// <param name="dividendYield">The dividend yield</param>
2127  /// <param name="optionModel">The option pricing model used to estimate Vega</param>
2128  /// <param name="ivModel">The option pricing model used to estimate IV</param>
2129  /// <param name="resolution">The desired resolution of the data</param>
2130  /// <returns>A new Vega indicator for the specified symbol</returns>
2131  [DocumentationAttribute(Indicators)]
2132  public Vega V(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes,
2133  OptionPricingModelType? ivModel = null, Resolution? resolution = null)
2134  {
2135  var name = InitializeOptionIndicator<Vega>(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution);
2136 
2137  var vega = new Vega(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel);
2138  RegisterIndicator(symbol, vega, ResolveConsolidator(symbol, resolution, typeof(QuoteBar)));
2139  RegisterIndicator(symbol.Underlying, vega, ResolveConsolidator(symbol.Underlying, resolution));
2140  if (mirrorOption != null)
2141  {
2142  RegisterIndicator(mirrorOption, vega, ResolveConsolidator(mirrorOption, resolution, typeof(QuoteBar)));
2143  }
2144  return vega;
2145  }
2146 
2147  /// <summary>
2148  /// Creates a new Chande's Variable Index Dynamic Average indicator.
2149  /// </summary>
2150  /// <param name="symbol">The symbol whose VIDYA we want</param>
2151  /// <param name="period">The period over which to compute the VIDYA</param>
2152  /// <param name="resolution">The resolution</param>
2153  /// <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>
2154  /// <returns>The VariableIndexDynamicAverage indicator for the requested symbol over the specified period</returns>
2155  [DocumentationAttribute(Indicators)]
2156  public VariableIndexDynamicAverage VIDYA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2157  {
2158  var name = CreateIndicatorName(symbol, $"VIDYA({period})", resolution);
2159  var variableIndexDynamicAverage = new VariableIndexDynamicAverage(name, period);
2160  InitializeIndicator(symbol, variableIndexDynamicAverage, resolution, selector);
2161 
2162  return variableIndexDynamicAverage;
2163  }
2164 
2165  /// <summary>
2166  /// Creates a new Variance indicator. This will return the population variance of samples over the specified period.
2167  /// </summary>
2168  /// <param name="symbol">The symbol whose VAR we want</param>
2169  /// <param name="period">The period over which to compute the VAR</param>
2170  /// <param name="resolution">The resolution</param>
2171  /// <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>
2172  /// <returns>The Variance indicator for the requested symbol over the specified period</returns>
2173  [DocumentationAttribute(Indicators)]
2174  [Obsolete("'VAR' is obsolete please use 'V' instead")]
2175  public Variance VAR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2176  {
2177  return V(symbol, period, resolution, selector);
2178  }
2179 
2180  /// <summary>
2181  /// Creates a new Variance indicator. This will return the population variance of samples over the specified period.
2182  /// </summary>
2183  /// <param name="symbol">The symbol whose variance we want</param>
2184  /// <param name="period">The period over which to compute the variance</param>
2185  /// <param name="resolution">The resolution</param>
2186  /// <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>
2187  /// <returns>The Variance indicator for the requested symbol over the specified period</returns>
2188  [DocumentationAttribute(Indicators)]
2189  public Variance V(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2190  {
2191  var name = CreateIndicatorName(symbol, $"V({period})", resolution);
2192  var variance = new Variance(name, period);
2193  InitializeIndicator(symbol, variance, resolution, selector);
2194 
2195  return variance;
2196  }
2197 
2198  /// <summary>
2199  /// Creates a new ValueAtRisk indicator.
2200  /// </summary>
2201  /// <param name="symbol">The symbol whose VAR we want</param>
2202  /// <param name="period">The period over which to compute the VAR</param>
2203  /// <param name="confidenceLevel">The confidence level for Value at risk calculation</param>
2204  /// <param name="resolution">The resolution</param>
2205  /// <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>
2206  /// <returns>The ValueAtRisk indicator for the requested Symbol, lookback period, and confidence level</returns>
2207  public ValueAtRisk VAR(Symbol symbol, int period, double confidenceLevel, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2208  {
2209  var name = CreateIndicatorName(symbol, $"VAR({period},{confidenceLevel})", resolution);
2210  var valueAtRisk = new ValueAtRisk(name, period, confidenceLevel);
2211  InitializeIndicator(symbol, valueAtRisk, resolution, selector);
2212 
2213  return valueAtRisk;
2214  }
2215 
2216  /// <summary>
2217  /// Creates an VolumeWeightedAveragePrice (VWAP) indicator for the symbol. The indicator will be automatically
2218  /// updated on the given resolution.
2219  /// </summary>
2220  /// <param name="symbol">The symbol whose VWAP we want</param>
2221  /// <param name="period">The period of the VWAP</param>
2222  /// <param name="resolution">The resolution</param>
2223  /// <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>
2224  /// <returns>The VolumeWeightedAveragePrice for the given parameters</returns>
2225  [DocumentationAttribute(Indicators)]
2226  public VolumeWeightedAveragePriceIndicator VWAP(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2227  {
2228  var name = CreateIndicatorName(symbol, $"VWAP({period})", resolution);
2229  var volumeWeightedAveragePriceIndicator = new VolumeWeightedAveragePriceIndicator(name, period);
2230  InitializeIndicator(symbol, volumeWeightedAveragePriceIndicator, resolution, selector);
2231 
2232  return volumeWeightedAveragePriceIndicator;
2233  }
2234 
2235  /// <summary>
2236  /// Creates the canonical VWAP indicator that resets each day. The indicator will be automatically
2237  /// updated on the security's configured resolution.
2238  /// </summary>
2239  /// <param name="symbol">The symbol whose VWAP we want</param>
2240  /// <returns>The IntradayVWAP for the specified symbol</returns>
2241  [DocumentationAttribute(Indicators)]
2242  public IntradayVwap VWAP(Symbol symbol)
2243  {
2244  var name = CreateIndicatorName(symbol, "VWAP", null);
2245  var intradayVwap = new IntradayVwap(name);
2246  RegisterIndicator(symbol, intradayVwap);
2247  return intradayVwap;
2248  }
2249 
2250  /// <summary>
2251  /// Creates a new Williams %R indicator. This will compute the percentage change of
2252  /// the current closing price in relation to the high and low of the past N periods.
2253  /// The indicator will be automatically updated on the given resolution.
2254  /// </summary>
2255  /// <param name="symbol">The symbol whose Williams %R we want</param>
2256  /// <param name="period">The period over which to compute the Williams %R</param>
2257  /// <param name="resolution">The resolution</param>
2258  /// <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>
2259  /// <returns>The Williams %R indicator for the requested symbol over the specified period</returns>
2260  [DocumentationAttribute(Indicators)]
2261  public WilliamsPercentR WILR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
2262  {
2263  var name = CreateIndicatorName(symbol, $"WILR({period})", resolution);
2264  var williamsPercentR = new WilliamsPercentR(name, period);
2265  InitializeIndicator(symbol, williamsPercentR, resolution, selector);
2266 
2267  return williamsPercentR;
2268  }
2269 
2270  /// <summary>
2271  /// Creates a WilderMovingAverage indicator for the symbol.
2272  /// The indicator will be automatically updated on the given resolution.
2273  /// </summary>
2274  /// <param name="symbol">The symbol whose WMA we want</param>
2275  /// <param name="period">The period of the WMA</param>
2276  /// <param name="resolution">The resolution</param>
2277  /// <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>
2278  /// <returns>The WilderMovingAverage for the given parameters</returns>
2279  /// <remarks>WWMA for Welles Wilder Moving Average</remarks>
2280  [DocumentationAttribute(Indicators)]
2281  public WilderMovingAverage WWMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2282  {
2283  var name = CreateIndicatorName(symbol, $"WWMA({period})", resolution);
2284  var wilderMovingAverage = new WilderMovingAverage(name, period);
2285  InitializeIndicator(symbol, wilderMovingAverage, resolution, selector);
2286 
2287  return wilderMovingAverage;
2288  }
2289 
2290  /// <summary>
2291  /// Creates a Wilder Swing Index (SI) indicator for the symbol.
2292  /// The indicator will be automatically updated on the given resolution.
2293  /// </summary>
2294  /// <param name="symbol">The symbol whose SI we want</param>
2295  /// <param name="limitMove">The maximum daily change in price for the SI</param>
2296  /// <param name="resolution">The resolution</param>
2297  /// <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>
2298  /// <returns>The WilderSwingIndex for the given parameters</returns>
2299  /// <remarks>SI for Wilder Swing Index</remarks>
2300  [DocumentationAttribute(Indicators)]
2301  public WilderSwingIndex SI(Symbol symbol, decimal limitMove, Resolution? resolution = Resolution.Daily,
2302  Func<IBaseData, TradeBar> selector = null)
2303  {
2304  var name = CreateIndicatorName(symbol, "SI", resolution);
2305  var si = new WilderSwingIndex(name, limitMove);
2306  InitializeIndicator(symbol, si, resolution, selector);
2307 
2308  return si;
2309  }
2310 
2311  /// <summary>
2312  /// Creates a Wilder Accumulative Swing Index (ASI) indicator for the symbol.
2313  /// The indicator will be automatically updated on the given resolution.
2314  /// </summary>
2315  /// <param name="symbol">The symbol whose ASI we want</param>
2316  /// <param name="limitMove">The maximum daily change in price for the ASI</param>
2317  /// <param name="resolution">The resolution</param>
2318  /// <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>
2319  /// <returns>The WilderAccumulativeSwingIndex for the given parameters</returns>
2320  /// <remarks>ASI for Wilder Accumulative Swing Index</remarks>
2321  [DocumentationAttribute(Indicators)]
2322  public WilderAccumulativeSwingIndex ASI(Symbol symbol, decimal limitMove, Resolution? resolution = Resolution.Daily,
2323  Func<IBaseData, TradeBar> selector = null)
2324  {
2325  var name = CreateIndicatorName(symbol, "ASI", resolution);
2326  var asi = new WilderAccumulativeSwingIndex(name, limitMove);
2327  InitializeIndicator(symbol, asi, resolution, selector);
2328 
2329  return asi;
2330  }
2331 
2332  /// <summary>
2333  /// Creates a new Arms Index indicator
2334  /// </summary>
2335  /// <param name="symbols">The symbols whose Arms Index we want</param>
2336  /// <param name="resolution">The resolution</param>
2337  /// <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>
2338  /// <returns>The Arms Index indicator for the requested symbol over the specified period</returns>
2339  [DocumentationAttribute(Indicators)]
2340  public ArmsIndex TRIN(IEnumerable<Symbol> symbols, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2341  {
2342  return TRIN(symbols.ToArray(), resolution, selector);
2343  }
2344 
2345  /// <summary>
2346  /// Creates a new Arms Index indicator
2347  /// </summary>
2348  /// <param name="symbols">The symbols whose Arms Index we want</param>
2349  /// <param name="resolution">The resolution</param>
2350  /// <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>
2351  /// <returns>The Arms Index indicator for the requested symbol over the specified period</returns>
2352  [DocumentationAttribute(Indicators)]
2353  public ArmsIndex TRIN(Symbol[] symbols, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2354  {
2355  var name = CreateIndicatorName(QuantConnect.Symbol.None, "TRIN", resolution ?? GetSubscription(symbols.First()).Resolution);
2356  var trin = new ArmsIndex(name);
2357  foreach (var symbol in symbols)
2358  {
2359  trin.Add(symbol);
2360  InitializeIndicator(symbol, trin, resolution, selector);
2361  }
2362 
2363  return trin;
2364  }
2365 
2366  /// <summary>
2367  /// Creates a new Advance/Decline Ratio indicator
2368  /// </summary>
2369  /// <param name="symbols">The symbols whose A/D Ratio we want</param>
2370  /// <param name="resolution">The resolution</param>
2371  /// <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>
2372  /// <returns>The Advance/Decline Ratio indicator for the requested symbol over the specified period</returns>
2373  [DocumentationAttribute(Indicators)]
2374  public AdvanceDeclineRatio ADR(IEnumerable<Symbol> symbols, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2375  {
2376  var name = CreateIndicatorName(QuantConnect.Symbol.None, "A/D Ratio", resolution ?? GetSubscription(symbols.First()).Resolution);
2377  var adr = new AdvanceDeclineRatio(name);
2378  foreach (var symbol in symbols)
2379  {
2380  adr.Add(symbol);
2381  InitializeIndicator(symbol, adr, resolution, selector);
2382  }
2383 
2384  return adr;
2385  }
2386 
2387  /// <summary>
2388  /// Creates a new Advance/Decline Volume Ratio indicator
2389  /// </summary>
2390  /// <param name="symbols">The symbol whose A/D Volume Rate we want</param>
2391  /// <param name="resolution">The resolution</param>
2392  /// <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>
2393  /// <returns>The Advance/Decline Volume Ratio indicator for the requested symbol over the specified period</returns>
2394  [DocumentationAttribute(Indicators)]
2395  public AdvanceDeclineVolumeRatio ADVR(IEnumerable<Symbol> symbols, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2396  {
2397  var name = CreateIndicatorName(QuantConnect.Symbol.None, "A/D Volume Rate", resolution ?? GetSubscription(symbols.First()).Resolution);
2398  var advr = new AdvanceDeclineVolumeRatio(name);
2399  foreach (var symbol in symbols)
2400  {
2401  advr.Add(symbol);
2402  InitializeIndicator(symbol, advr, resolution, selector);
2403  }
2404 
2405  return advr;
2406  }
2407 
2408  /// <summary>
2409  /// Creates a new Advance/Decline Difference indicator
2410  /// </summary>
2411  /// <param name="symbols">The symbols whose A/D Difference we want</param>
2412  /// <param name="resolution">The resolution</param>
2413  /// <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>
2414  /// <returns>The Advance/Decline Difference indicator for the requested symbol over the specified period</returns>
2415  [DocumentationAttribute(Indicators)]
2416  public AdvanceDeclineDifference ADDIFF(IEnumerable<Symbol> symbols, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2417  {
2418  var name = CreateIndicatorName(QuantConnect.Symbol.None, "A/D Difference", resolution ?? GetSubscription(symbols.First()).Resolution);
2419  var adDiff = new AdvanceDeclineDifference(name);
2420  foreach (var symbol in symbols)
2421  {
2422  adDiff.Add(symbol);
2423  InitializeIndicator(symbol, adDiff, resolution, selector);
2424  }
2425 
2426  return adDiff;
2427  }
2428 
2429  /// <summary>
2430  /// Creates a new McClellan Oscillator indicator
2431  /// </summary>
2432  /// <param name="symbols">The symbols whose McClellan Oscillator we want</param>
2433  /// <param name="fastPeriod">Fast period EMA of advance decline difference</param>
2434  /// <param name="slowPeriod">Slow period EMA of advance decline difference</param>
2435  /// <param name="resolution">The resolution</param>
2436  /// <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>
2437  /// <returns>The McClellan Oscillator indicator for the requested symbol over the specified period</returns>
2438  [DocumentationAttribute(Indicators)]
2439  public McClellanOscillator MOSC(IEnumerable<Symbol> symbols, int fastPeriod = 19, int slowPeriod = 39, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2440  {
2441  return MOSC(symbols.ToArray(), fastPeriod, slowPeriod, resolution, selector);
2442  }
2443 
2444  /// <summary>
2445  /// Creates a new McClellan Oscillator indicator
2446  /// </summary>
2447  /// <param name="symbols">The symbols whose McClellan Oscillator we want</param>
2448  /// <param name="fastPeriod">Fast period EMA of advance decline difference</param>
2449  /// <param name="slowPeriod">Slow period EMA of advance decline difference</param>
2450  /// <param name="resolution">The resolution</param>
2451  /// <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>
2452  /// <returns>The McClellan Oscillator indicator for the requested symbol over the specified period</returns>
2453  [DocumentationAttribute(Indicators)]
2454  public McClellanOscillator MOSC(Symbol[] symbols, int fastPeriod = 19, int slowPeriod = 39, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2455  {
2456  var name = CreateIndicatorName(QuantConnect.Symbol.None, $"MO({fastPeriod},{slowPeriod})", resolution ?? GetSubscription(symbols.First()).Resolution);
2457  var mosc = new McClellanOscillator(name, fastPeriod, slowPeriod);
2458  foreach (var symbol in symbols)
2459  {
2460  mosc.Add(symbol);
2461  InitializeIndicator(symbol, mosc, resolution, selector);
2462  }
2463 
2464  return mosc;
2465  }
2466 
2467  /// <summary>
2468  /// Creates a new McClellan Summation Index indicator
2469  /// </summary>
2470  /// <param name="symbols">The symbols whose McClellan Summation Index we want</param>
2471  /// <param name="fastPeriod">Fast period EMA of advance decline difference</param>
2472  /// <param name="slowPeriod">Slow period EMA of advance decline difference</param>
2473  /// <param name="resolution">The resolution</param>
2474  /// <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>
2475  /// <returns>The McClellan Summation Index indicator for the requested symbol over the specified period</returns>
2476  [DocumentationAttribute(Indicators)]
2477  public McClellanSummationIndex MSI(IEnumerable<Symbol> symbols, int fastPeriod = 19, int slowPeriod = 39, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2478  {
2479  return MSI(symbols.ToArray(), fastPeriod, slowPeriod, resolution, selector);
2480  }
2481 
2482  /// <summary>
2483  /// Creates a new McClellan Summation Index indicator
2484  /// </summary>
2485  /// <param name="symbols">The symbols whose McClellan Summation Index we want</param>
2486  /// <param name="fastPeriod">Fast period EMA of advance decline difference</param>
2487  /// <param name="slowPeriod">Slow period EMA of advance decline difference</param>
2488  /// <param name="resolution">The resolution</param>
2489  /// <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>
2490  /// <returns>The McClellan Summation Index indicator for the requested symbol over the specified period</returns>
2491  [DocumentationAttribute(Indicators)]
2492  public McClellanSummationIndex MSI(Symbol[] symbols, int fastPeriod = 19, int slowPeriod = 39, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
2493  {
2494  var name = CreateIndicatorName(QuantConnect.Symbol.None, $"MSI({fastPeriod},{slowPeriod})", resolution ?? GetSubscription(symbols.First()).Resolution);
2495  var msi = new McClellanSummationIndex(name, fastPeriod, slowPeriod);
2496  foreach (var symbol in symbols)
2497  {
2498  msi.Add(symbol);
2499  InitializeIndicator(symbol, msi, resolution, selector);
2500  }
2501 
2502  return msi;
2503  }
2504 
2505  /// <summary>
2506  /// Creates a new name for an indicator created with the convenience functions (SMA, EMA, ect...)
2507  /// </summary>
2508  /// <param name="symbol">The symbol this indicator is registered to</param>
2509  /// <param name="type">The indicator type, for example, 'SMA(5)'</param>
2510  /// <param name="resolution">The resolution requested</param>
2511  /// <returns>A unique for the given parameters</returns>
2512  [DocumentationAttribute(Indicators)]
2513  public string CreateIndicatorName(Symbol symbol, FormattableString type, Resolution? resolution)
2514  {
2515  return CreateIndicatorName(symbol, Invariant(type), resolution);
2516  }
2517 
2518  /// <summary>
2519  /// Creates a new name for an indicator created with the convenience functions (SMA, EMA, ect...)
2520  /// </summary>
2521  /// <param name="symbol">The symbol this indicator is registered to</param>
2522  /// <param name="type">The indicator type, for example, 'SMA(5)'</param>
2523  /// <param name="resolution">The resolution requested</param>
2524  /// <returns>A unique for the given parameters</returns>
2525  [DocumentationAttribute(Indicators)]
2526  public string CreateIndicatorName(Symbol symbol, string type, Resolution? resolution)
2527  {
2528  var symbolIsNotEmpty = symbol != QuantConnect.Symbol.None && symbol != QuantConnect.Symbol.Empty;
2529 
2530  if (!resolution.HasValue && symbolIsNotEmpty)
2531  {
2532  resolution = GetSubscription(symbol).Resolution;
2533  }
2534 
2535  var res = string.Empty;
2536  switch (resolution)
2537  {
2538  case Resolution.Tick:
2539  res = "tick";
2540  break;
2541 
2542  case Resolution.Second:
2543  res = "sec";
2544  break;
2545 
2546  case Resolution.Minute:
2547  res = "min";
2548  break;
2549 
2550  case Resolution.Hour:
2551  res = "hr";
2552  break;
2553 
2554  case Resolution.Daily:
2555  res = "day";
2556  break;
2557 
2558  case null:
2559  break;
2560 
2561  default:
2562  throw new ArgumentOutOfRangeException(nameof(resolution), resolution, "resolution parameter is out of range.");
2563  }
2564 
2565  var parts = new List<string>();
2566 
2567  if (symbolIsNotEmpty)
2568  {
2569  parts.Add(symbol.ToString());
2570  }
2571  parts.Add(res);
2572 
2573  return Invariant($"{type}({string.Join("_", parts)})").Replace(")(", ",");
2574  }
2575 
2576  /// <summary>
2577  /// Gets the SubscriptionDataConfig for the specified symbol and tick type
2578  /// </summary>
2579  /// <exception cref="InvalidOperationException">Thrown if no configuration is found for the requested symbol</exception>
2580  /// <param name="symbol">The symbol to retrieve configuration for</param>
2581  /// <param name="tickType">The tick type of the subscription to get. If null, will use the first ordered by TickType</param>
2582  /// <returns>The SubscriptionDataConfig for the specified symbol</returns>
2583  private SubscriptionDataConfig GetSubscription(Symbol symbol, TickType? tickType = null)
2584  {
2585  SubscriptionDataConfig subscription;
2586  try
2587  {
2588  // deterministic ordering is required here
2590  .GetSubscriptionDataConfigs(symbol)
2591  // make sure common lean data types are at the bottom
2592  .OrderByDescending(x => LeanData.IsCommonLeanDataType(x.Type))
2593  .ThenBy(x => x.TickType)
2594  .ToList();
2595 
2596  // find our subscription
2597  subscription = subscriptions.FirstOrDefault(x => tickType == null || tickType == x.TickType);
2598  if (subscription == null)
2599  {
2600  // if we can't locate the exact subscription by tick type just grab the first one we find
2601  subscription = subscriptions.First();
2602  }
2603  }
2604  catch (InvalidOperationException)
2605  {
2606  // this will happen if we did not find the subscription, let's give the user a decent error message
2607  throw new Exception($"Please register to receive data for symbol \'{symbol}\' using the AddSecurity() function.");
2608  }
2609  return subscription;
2610  }
2611 
2612  /// <summary>
2613  /// Creates and registers a new consolidator to receive automatic updates at the specified resolution as well as configures
2614  /// the indicator to receive updates from the consolidator.
2615  /// </summary>
2616  /// <param name="symbol">The symbol to register against</param>
2617  /// <param name="indicator">The indicator to receive data from the consolidator</param>
2618  /// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
2619  /// <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>
2620  [DocumentationAttribute(ConsolidatingData)]
2621  [DocumentationAttribute(Indicators)]
2622  public void RegisterIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2623  {
2624  RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution), selector ?? (x => x.Value));
2625  }
2626 
2627  /// <summary>
2628  /// Creates and registers a new consolidator to receive automatic updates at the specified resolution as well as configures
2629  /// the indicator to receive updates from the consolidator.
2630  /// </summary>
2631  /// <param name="symbol">The symbol to register against</param>
2632  /// <param name="indicator">The indicator to receive data from the consolidator</param>
2633  /// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
2634  /// <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>
2635  [DocumentationAttribute(ConsolidatingData)]
2636  [DocumentationAttribute(Indicators)]
2637  public void RegisterIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, TimeSpan? resolution = null, Func<IBaseData, decimal> selector = null)
2638  {
2639  RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution), selector ?? (x => x.Value));
2640  }
2641 
2642  /// <summary>
2643  /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates
2644  /// from the consolidator.
2645  /// </summary>
2646  /// <param name="symbol">The symbol to register against</param>
2647  /// <param name="indicator">The indicator to receive data from the consolidator</param>
2648  /// <param name="consolidator">The consolidator to receive raw subscription data</param>
2649  /// <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>
2650  [DocumentationAttribute(ConsolidatingData)]
2651  [DocumentationAttribute(Indicators)]
2652  public void RegisterIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, IDataConsolidator consolidator, Func<IBaseData, decimal> selector = null)
2653  {
2654  // default our selector to the Value property on BaseData
2655  selector = selector ?? (x => x.Value);
2656 
2657  RegisterConsolidator(indicator, symbol, consolidator);
2658 
2659  // attach to the DataConsolidated event so it updates our indicator
2660  consolidator.DataConsolidated += (sender, consolidated) =>
2661  {
2662  var value = selector(consolidated);
2663  indicator.Update(new IndicatorDataPoint(consolidated.Symbol, consolidated.EndTime, value));
2664  };
2665  }
2666 
2667  /// <summary>
2668  /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates
2669  /// from the consolidator.
2670  /// </summary>
2671  /// <param name="symbol">The symbol to register against</param>
2672  /// <param name="indicator">The indicator to receive data from the consolidator</param>
2673  /// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
2674  [DocumentationAttribute(ConsolidatingData)]
2675  [DocumentationAttribute(Indicators)]
2676  public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, Resolution? resolution = null)
2677  where T : IBaseData
2678  {
2679  RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution, typeof(T)));
2680  }
2681 
2682  /// <summary>
2683  /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates
2684  /// from the consolidator.
2685  /// </summary>
2686  /// <param name="symbol">The symbol to register against</param>
2687  /// <param name="indicator">The indicator to receive data from the consolidator</param>
2688  /// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
2689  /// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
2690  [DocumentationAttribute(ConsolidatingData)]
2691  [DocumentationAttribute(Indicators)]
2692  public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, Resolution? resolution, Func<IBaseData, T> selector)
2693  where T : IBaseData
2694  {
2695  RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution, typeof(T)), selector);
2696  }
2697 
2698  /// <summary>
2699  /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates
2700  /// from the consolidator.
2701  /// </summary>
2702  /// <param name="symbol">The symbol to register against</param>
2703  /// <param name="indicator">The indicator to receive data from the consolidator</param>
2704  /// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
2705  /// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
2706  [DocumentationAttribute(ConsolidatingData)]
2707  [DocumentationAttribute(Indicators)]
2708  public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, TimeSpan? resolution, Func<IBaseData, T> selector = null)
2709  where T : IBaseData
2710  {
2711  RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution, typeof(T)), selector);
2712  }
2713 
2714  /// <summary>
2715  /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates
2716  /// from the consolidator.
2717  /// </summary>
2718  /// <param name="symbol">The symbol to register against</param>
2719  /// <param name="indicator">The indicator to receive data from the consolidator</param>
2720  /// <param name="consolidator">The consolidator to receive raw subscription data</param>
2721  /// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
2722  [DocumentationAttribute(ConsolidatingData)]
2723  [DocumentationAttribute(Indicators)]
2724  public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, IDataConsolidator consolidator, Func<IBaseData, T> selector = null)
2725  where T : IBaseData
2726  {
2727  // assign default using cast
2728  var selectorToUse = selector ?? (x => (T)x);
2729 
2730  RegisterConsolidator(indicator, symbol, consolidator);
2731 
2732  // check the output type of the consolidator and verify we can assign it to T
2733  var type = typeof(T);
2734  if (!type.IsAssignableFrom(consolidator.OutputType))
2735  {
2736  if (type == typeof(IndicatorDataPoint) && selector == null)
2737  {
2738  // if no selector was provided and the indicator input is of 'IndicatorDataPoint', common case, a selector with a direct cast will fail
2739  // so we use a smarter selector as in other API methods
2740  selectorToUse = consolidated => (T)(object)new IndicatorDataPoint(consolidated.Symbol, consolidated.EndTime, consolidated.Value);
2741  }
2742  else
2743  {
2744  throw new ArgumentException($"Type mismatch found between consolidator and indicator for symbol: {symbol}." +
2745  $"Consolidator outputs type {consolidator.OutputType.Name} but indicator expects input type {type.Name}"
2746  );
2747  }
2748  }
2749 
2750  // attach to the DataConsolidated event so it updates our indicator
2751  consolidator.DataConsolidated += (sender, consolidated) =>
2752  {
2753  var value = selectorToUse(consolidated);
2754  indicator.Update(value);
2755  };
2756  }
2757 
2758  /// <summary>
2759  /// Will unregister an indicator and it's associated consolidator instance so they stop receiving data updates
2760  /// </summary>
2761  /// <param name="indicator">The indicator instance to unregister</param>
2762  [DocumentationAttribute(ConsolidatingData)]
2763  [DocumentationAttribute(Indicators)]
2764  public void UnregisterIndicator(IndicatorBase indicator)
2765  {
2766  DeregisterIndicator(indicator);
2767  }
2768 
2769  /// <summary>
2770  /// Will deregister an indicator and it's associated consolidator instance so they stop receiving data updates
2771  /// </summary>
2772  /// <param name="indicator">The indicator instance to deregister</param>
2773  [DocumentationAttribute(ConsolidatingData)]
2774  [DocumentationAttribute(Indicators)]
2775  public void DeregisterIndicator(IndicatorBase indicator)
2776  {
2777  foreach (var consolidator in indicator.Consolidators)
2778  {
2779  SubscriptionManager.RemoveConsolidator(null, consolidator);
2780  }
2781 
2782  indicator.Consolidators.Clear();
2783  }
2784 
2785  /// <summary>
2786  /// Warms up a given indicator with historical data
2787  /// </summary>
2788  /// <param name="symbol">The symbol whose indicator we want</param>
2789  /// <param name="indicator">The indicator we want to warm up</param>
2790  /// <param name="resolution">The resolution</param>
2791  /// <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>
2792  [DocumentationAttribute(HistoricalData)]
2793  [DocumentationAttribute(Indicators)]
2794  public void WarmUpIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
2795  {
2796  resolution = GetResolution(symbol, resolution, null);
2797  var period = resolution.Value.ToTimeSpan();
2798  WarmUpIndicator(symbol, indicator, period, selector);
2799  }
2800 
2801  /// <summary>
2802  /// Warms up a given indicator with historical data
2803  /// </summary>
2804  /// <param name="symbol">The symbol whose indicator we want</param>
2805  /// <param name="indicator">The indicator we want to warm up</param>
2806  /// <param name="period">The necessary period to warm up the indicator</param>
2807  /// <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>
2808  [DocumentationAttribute(HistoricalData)]
2809  [DocumentationAttribute(Indicators)]
2810  public void WarmUpIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, TimeSpan period, Func<IBaseData, decimal> selector = null)
2811  {
2812  var history = GetIndicatorWarmUpHistory(symbol, indicator, period, out var identityConsolidator);
2813  if (history == Enumerable.Empty<Slice>()) return;
2814 
2815  // assign default using cast
2816  selector ??= (x => x.Value);
2817 
2818  Action<IBaseData> onDataConsolidated = bar =>
2819  {
2820  var input = new IndicatorDataPoint(bar.Symbol, bar.EndTime, selector(bar));
2821  indicator.Update(input);
2822  };
2823 
2824  WarmUpIndicatorImpl(symbol, period, onDataConsolidated, history, identityConsolidator);
2825  }
2826 
2827  /// <summary>
2828  /// Warms up a given indicator with historical data
2829  /// </summary>
2830  /// <param name="symbol">The symbol whose indicator we want</param>
2831  /// <param name="indicator">The indicator we want to warm up</param>
2832  /// <param name="resolution">The resolution</param>
2833  /// <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>
2834  [DocumentationAttribute(HistoricalData)]
2835  [DocumentationAttribute(Indicators)]
2836  public void WarmUpIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, Resolution? resolution = null, Func<IBaseData, T> selector = null)
2837  where T : class, IBaseData
2838  {
2839  resolution = GetResolution(symbol, resolution, typeof(T));
2840  var period = resolution.Value.ToTimeSpan();
2841  WarmUpIndicator(symbol, indicator, period, selector);
2842  }
2843 
2844  /// <summary>
2845  /// Warms up a given indicator with historical data
2846  /// </summary>
2847  /// <param name="symbol">The symbol whose indicator we want</param>
2848  /// <param name="indicator">The indicator we want to warm up</param>
2849  /// <param name="period">The necessary period to warm up the indicator</param>
2850  /// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
2851  [DocumentationAttribute(HistoricalData)]
2852  [DocumentationAttribute(Indicators)]
2853  public void WarmUpIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, TimeSpan period, Func<IBaseData, T> selector = null)
2854  where T : class, IBaseData
2855  {
2856  var history = GetIndicatorWarmUpHistory(symbol, indicator, period, out var identityConsolidator);
2857  if (history == Enumerable.Empty<Slice>()) return;
2858 
2859  // assign default using cast
2860  selector ??= (x => (T)x);
2861 
2862  // we expect T type as input
2863  Action<T> onDataConsolidated = bar =>
2864  {
2865  indicator.Update(selector(bar));
2866  };
2867 
2868  WarmUpIndicatorImpl(symbol, period, onDataConsolidated, history, identityConsolidator);
2869  }
2870 
2871  private IEnumerable<Slice> GetIndicatorWarmUpHistory(Symbol symbol, IIndicator indicator, TimeSpan timeSpan, out bool identityConsolidator)
2872  {
2873  identityConsolidator = false;
2874  var periods = (indicator as IIndicatorWarmUpPeriodProvider)?.WarmUpPeriod;
2875 
2876  if (periods.HasValue && periods != 0)
2877  {
2878  var resolution = timeSpan.ToHigherResolutionEquivalent(false);
2879  // if they are the same, means we can use an identity consolidator
2880  identityConsolidator = resolution.ToTimeSpan() == timeSpan;
2881  var resolutionTicks = resolution.ToTimeSpan().Ticks;
2882  if (resolutionTicks != 0)
2883  {
2884  periods *= (int)(timeSpan.Ticks / resolutionTicks);
2885  }
2886 
2887  try
2888  {
2889  return History(new[] { symbol }, periods.Value, resolution);
2890  }
2891  catch (ArgumentException e)
2892  {
2893  Debug($"{indicator.Name} could not be warmed up. Reason: {e.Message}");
2894  }
2895  }
2896  else if (!_isEmitWarmupInsightWarningSent)
2897  {
2898  Debug($"Warning: the 'WarmUpIndicator' feature only works with indicators which inherit from '{nameof(IIndicatorWarmUpPeriodProvider)}'" +
2899  $" and define a warm up period, setting property 'WarmUpPeriod' with a value > 0." +
2900  $" The provided indicator of type '{indicator.GetType().Name}' will not be warmed up.");
2901  _isEmitWarmupInsightWarningSent = true;
2902  }
2903 
2904  return Enumerable.Empty<Slice>();
2905  }
2906 
2907  private void WarmUpIndicatorImpl<T>(Symbol symbol, TimeSpan period, Action<T> handler, IEnumerable<Slice> history, bool identityConsolidator)
2908  where T : class, IBaseData
2909  {
2910  IDataConsolidator consolidator;
2911  if (identityConsolidator)
2912  {
2913  period = TimeSpan.Zero;
2914  }
2915  if (SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(symbol).Count > 0)
2916  {
2917  consolidator = Consolidate(symbol, period, handler);
2918  }
2919  else
2920  {
2921  var providedType = typeof(T);
2922  if (providedType.IsAbstract)
2923  {
2925  symbol.SecurityType,
2926  Resolution.Daily,
2927  // order by tick type so that behavior is consistent with 'GetSubscription()'
2928  symbol.IsCanonical())
2929  // make sure common lean data types are at the bottom
2930  .OrderByDescending(tuple => LeanData.IsCommonLeanDataType(tuple.Item1))
2931  .ThenBy(tuple => tuple.Item2).First();
2932 
2933  consolidator = CreateConsolidator(period, dataType.Item1, dataType.Item2);
2934  }
2935  else
2936  {
2937  // if the 'providedType' is not abstract we use it instead to determine which consolidator to use
2938  var tickType = LeanData.GetCommonTickTypeForCommonDataTypes(providedType, symbol.SecurityType);
2939  consolidator = CreateConsolidator(period, providedType, tickType);
2940  }
2941  consolidator.DataConsolidated += (s, bar) => handler((T)bar);
2942  }
2943 
2944  var consolidatorInputType = consolidator.InputType;
2945  IBaseData lastBar = null;
2946  foreach (var slice in history)
2947  {
2948  if (slice.TryGet(consolidatorInputType, symbol, out var data))
2949  {
2950  lastBar = data;
2951  consolidator.Update(lastBar);
2952  }
2953  }
2954 
2955  // Scan for time after we've pumped all the data through for this consolidator
2956  if (lastBar != null)
2957  {
2958  consolidator.Scan(lastBar.EndTime);
2959  }
2960 
2961  SubscriptionManager.RemoveConsolidator(symbol, consolidator);
2962  }
2963 
2964  /// <summary>
2965  /// Gets the default consolidator for the specified symbol and resolution
2966  /// </summary>
2967  /// <param name="symbol">The symbol whose data is to be consolidated</param>
2968  /// <param name="resolution">The resolution for the consolidator, if null, uses the resolution from subscription</param>
2969  /// <param name="dataType">The data type for this consolidator, if null, uses TradeBar over QuoteBar if present</param>
2970  /// <returns>The new default consolidator</returns>
2971  [DocumentationAttribute(ConsolidatingData)]
2972  [DocumentationAttribute(Indicators)]
2973  public IDataConsolidator ResolveConsolidator(Symbol symbol, Resolution? resolution, Type dataType = null)
2974  {
2975  TimeSpan? timeSpan = null;
2976  if (resolution.HasValue)
2977  {
2978  timeSpan = resolution.Value.ToTimeSpan();
2979  }
2980  return ResolveConsolidator(symbol, timeSpan, dataType);
2981  }
2982 
2983  /// <summary>
2984  /// Gets the default consolidator for the specified symbol and resolution
2985  /// </summary>
2986  /// <param name="symbol">The symbol whose data is to be consolidated</param>
2987  /// <param name="timeSpan">The requested time span for the consolidator, if null, uses the resolution from subscription</param>
2988  /// <param name="dataType">The data type for this consolidator, if null, uses TradeBar over QuoteBar if present</param>
2989  /// <returns>The new default consolidator</returns>
2990  [DocumentationAttribute(ConsolidatingData)]
2991  [DocumentationAttribute(Indicators)]
2992  public IDataConsolidator ResolveConsolidator(Symbol symbol, TimeSpan? timeSpan, Type dataType = null)
2993  {
2994  var tickType = dataType != null ? LeanData.GetCommonTickTypeForCommonDataTypes(dataType, symbol.SecurityType) : (TickType?)null;
2995  var subscription = GetSubscription(symbol, tickType);
2996  var subscriptionTimeSpan = subscription.Resolution.ToTimeSpan();
2997 
2998  // if not specified, default to the subscription resolution
2999  if (!timeSpan.HasValue)
3000  {
3001  timeSpan = subscriptionTimeSpan;
3002  }
3003 
3004  // verify this consolidator will give reasonable results, if someone asks for second consolidation but we have minute
3005  // data we won't be able to do anything good, we'll call it second, but it would really just be minute!
3006  if (timeSpan.Value < subscriptionTimeSpan)
3007  {
3008  throw new ArgumentException($"Unable to create {symbol} consolidator because {symbol} is registered for " +
3009  Invariant($"{subscription.Resolution.ToStringInvariant()} data. Consolidators require higher resolution data to produce lower resolution data.")
3010  );
3011  }
3012  else if (timeSpan.Value == subscriptionTimeSpan)
3013  {
3014  // input and expected output share the same time span, means we just want an identity consolidator
3015  timeSpan = TimeSpan.Zero;
3016  }
3017 
3018  return CreateConsolidator(timeSpan.Value, subscription.Type, subscription.TickType);
3019  }
3020 
3021  /// <summary>
3022  /// Creates a new consolidator for the specified period, generating the requested output type.
3023  /// </summary>
3024  /// <param name="period">The consolidation period</param>
3025  /// <param name="consolidatorInputType">The desired input type of the consolidator, such as TradeBar or QuoteBar</param>
3026  /// <param name="tickType">Trade or Quote. Optional, defaults to trade</param>
3027  /// <returns>A new consolidator matching the requested parameters</returns>
3028  [DocumentationAttribute(ConsolidatingData)]
3029  public static IDataConsolidator CreateConsolidator(TimeSpan period, Type consolidatorInputType, TickType? tickType = null)
3030  {
3031  // if our type can be used as a trade bar, then let's just make one of those
3032  // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to TradeBar
3033  if (typeof(TradeBar).IsAssignableFrom(consolidatorInputType))
3034  {
3035  // Use IdentityDataConsolidator when data are not meant to consolidated into bars
3036  if (period.Ticks == 0)
3037  {
3039  }
3040  return new TradeBarConsolidator(period);
3041  }
3042 
3043  // if our type can be used as a quote bar, then let's just make one of those
3044  // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to QuoteBar
3045  if (typeof(QuoteBar).IsAssignableFrom(consolidatorInputType))
3046  {
3047  // Use IdentityDataConsolidator when data are not meant to consolidated into bars
3048  if (period.Ticks == 0)
3049  {
3051  }
3052  return new QuoteBarConsolidator(period);
3053  }
3054 
3055  // if our type can be used as a tick then we'll use a consolidator that keeps the TickType
3056  // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to Tick
3057  if (typeof(Tick).IsAssignableFrom(consolidatorInputType))
3058  {
3059  // Use IdentityDataConsolidator when ticks are not meant to consolidated into bars
3060  if (period.Ticks == 0)
3061  {
3062  return new IdentityDataConsolidator<Tick>();
3063  }
3064 
3065  switch (tickType)
3066  {
3067  case TickType.OpenInterest:
3068  return new OpenInterestConsolidator(period);
3069 
3070  case TickType.Quote:
3071  return new TickQuoteBarConsolidator(period);
3072 
3073  default:
3074  return new TickConsolidator(period);
3075  }
3076  }
3077 
3078  // if our type can be used as a DynamicData then we'll use the DynamicDataConsolidator
3079  if (typeof(DynamicData).IsAssignableFrom(consolidatorInputType))
3080  {
3081  // Use IdentityDataConsolidator when data are not meant to consolidated into bars
3082  if (period.Ticks == 0)
3083  {
3084  return new DynamicDataConsolidator(1);
3085  }
3086  return new DynamicDataConsolidator(period);
3087  }
3088 
3089  // Use IdentityDataConsolidator when data are not meant to consolidated into bars
3090  if (period.Ticks == 0)
3091  {
3093  }
3094  // no matter what we can always consolidate based on the time-value pair of BaseData
3095  return new BaseDataConsolidator(period);
3096  }
3097 
3098  /// <summary>
3099  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol
3100  /// </summary>
3101  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3102  /// <param name="period">The consolidation period</param>
3103  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3104  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3105  [DocumentationAttribute(ConsolidatingData)]
3106  public IDataConsolidator Consolidate(Symbol symbol, Resolution period, Action<TradeBar> handler)
3107  {
3108  return Consolidate(symbol, period.ToTimeSpan(), TickType.Trade, handler);
3109  }
3110 
3111  /// <summary>
3112  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol
3113  /// </summary>
3114  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3115  /// <param name="period">The consolidation period</param>
3116  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3117  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3118  [DocumentationAttribute(ConsolidatingData)]
3119  public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, Action<TradeBar> handler)
3120  {
3121  return Consolidate(symbol, period, TickType.Trade, handler);
3122  }
3123 
3124  /// <summary>
3125  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol
3126  /// </summary>
3127  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3128  /// <param name="period">The consolidation period</param>
3129  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3130  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3131  [DocumentationAttribute(ConsolidatingData)]
3132  public IDataConsolidator Consolidate(Symbol symbol, Resolution period, Action<QuoteBar> handler)
3133  {
3134  return Consolidate(symbol, period.ToTimeSpan(), TickType.Quote, handler);
3135  }
3136 
3137  /// <summary>
3138  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol
3139  /// </summary>
3140  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3141  /// <param name="period">The consolidation period</param>
3142  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3143  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3144  [DocumentationAttribute(ConsolidatingData)]
3145  public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, Action<QuoteBar> handler)
3146  {
3147  return Consolidate(symbol, period, TickType.Quote, handler);
3148  }
3149 
3150  /// <summary>
3151  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol and tick type.
3152  /// The handler and tick type must match.
3153  /// </summary>
3154  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3155  /// <param name="period">The consolidation period</param>
3156  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3157  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3158  [DocumentationAttribute(ConsolidatingData)]
3159  public IDataConsolidator Consolidate<T>(Symbol symbol, TimeSpan period, Action<T> handler)
3160  where T : class, IBaseData
3161  {
3162  // 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
3163  // decision here (default type), it will be taken later by 'GetSubscription' so we keep it centralized
3164  // This could happen when a user passes in a generic 'Action<BaseData>' handler
3165  var tickType = typeof(T).IsAbstract ? (TickType?)null : LeanData.GetCommonTickTypeForCommonDataTypes(typeof(T), symbol.SecurityType);
3166  return Consolidate(symbol, period, tickType, handler);
3167  }
3168 
3169  /// <summary>
3170  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol and tick type.
3171  /// The handler and tick type must match.
3172  /// </summary>
3173  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3174  /// <param name="period">The consolidation period</param>
3175  /// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
3176  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3177  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3178  [DocumentationAttribute(ConsolidatingData)]
3179  public IDataConsolidator Consolidate<T>(Symbol symbol, Resolution period, TickType? tickType, Action<T> handler)
3180  where T : class, IBaseData
3181  {
3182  return Consolidate(symbol, period.ToTimeSpan(), tickType, handler);
3183  }
3184 
3185  /// <summary>
3186  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol and tick type.
3187  /// The handler and tick type must match.
3188  /// </summary>
3189  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3190  /// <param name="period">The consolidation period</param>
3191  /// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
3192  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3193  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3194  [DocumentationAttribute(ConsolidatingData)]
3195  public IDataConsolidator Consolidate<T>(Symbol symbol, TimeSpan period, TickType? tickType, Action<T> handler)
3196  where T : class, IBaseData
3197  {
3198  // resolve consolidator input subscription
3199  var subscription = GetSubscription(symbol, tickType);
3200 
3201  // create requested consolidator
3202  var consolidator = CreateConsolidator(period, subscription.Type, subscription.TickType);
3203 
3204  AddConsolidator(symbol, consolidator, handler, tickType);
3205  return consolidator;
3206  }
3207 
3208  /// <summary>
3209  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol
3210  /// </summary>
3211  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3212  /// <param name="calendar">The consolidation calendar</param>
3213  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3214  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3215  [DocumentationAttribute(ConsolidatingData)]
3216  public IDataConsolidator Consolidate(Symbol symbol, Func<DateTime, CalendarInfo> calendar, Action<QuoteBar> handler)
3217  {
3218  return Consolidate(symbol, calendar, TickType.Quote, handler);
3219  }
3220 
3221  /// <summary>
3222  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol
3223  /// </summary>
3224  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3225  /// <param name="calendar">The consolidation calendar</param>
3226  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3227  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3228  [DocumentationAttribute(ConsolidatingData)]
3229  public IDataConsolidator Consolidate(Symbol symbol, Func<DateTime, CalendarInfo> calendar, Action<TradeBar> handler)
3230  {
3231  return Consolidate(symbol, calendar, TickType.Trade, handler);
3232  }
3233 
3234  /// <summary>
3235  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol and tick type.
3236  /// The handler and tick type must match.
3237  /// </summary>
3238  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3239  /// <param name="calendar">The consolidation calendar</param>
3240  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3241  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3242  [DocumentationAttribute(ConsolidatingData)]
3243  public IDataConsolidator Consolidate<T>(Symbol symbol, Func<DateTime, CalendarInfo> calendar, Action<T> handler)
3244  where T : class, IBaseData
3245  {
3246  // 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
3247  // decision here (default type), it will be taken later by 'GetSubscription' so we keep it centralized
3248  // This could happen when a user passes in a generic 'Action<BaseData>' handler
3249  var tickType = typeof(T).IsAbstract ? (TickType?)null : LeanData.GetCommonTickTypeForCommonDataTypes(typeof(T), symbol.SecurityType);
3250  return Consolidate(symbol, calendar, tickType, handler);
3251  }
3252 
3253  /// <summary>
3254  /// Registers the <paramref name="handler"/> to receive consolidated data for the specified symbol and tick type.
3255  /// The handler and tick type must match.
3256  /// </summary>
3257  /// <param name="symbol">The symbol who's data is to be consolidated</param>
3258  /// <param name="calendar">The consolidation calendar</param>
3259  /// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
3260  /// <param name="handler">Data handler receives new consolidated data when generated</param>
3261  /// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
3262  [DocumentationAttribute(ConsolidatingData)]
3263  public IDataConsolidator Consolidate<T>(Symbol symbol, Func<DateTime, CalendarInfo> calendar, TickType? tickType, Action<T> handler)
3264  where T : class, IBaseData
3265  {
3266  // resolve consolidator input subscription
3267  var subscription = GetSubscription(symbol, tickType);
3268 
3269  // create requested consolidator
3270  var consolidator = CreateConsolidator(calendar, subscription.Type, subscription.TickType);
3271 
3272  AddConsolidator(symbol, consolidator, handler);
3273  return consolidator;
3274  }
3275 
3276  /// <summary>
3277  /// Adds the provided consolidator and asserts the handler T type is assignable from the consolidator output,
3278  /// if not will throw <see cref="ArgumentException"/>
3279  /// </summary>
3280  [DocumentationAttribute(ConsolidatingData)]
3281  private void AddConsolidator<T>(Symbol symbol, IDataConsolidator consolidator, Action<T> handler, TickType? tickType = null)
3282  {
3283  if (!typeof(T).IsAssignableFrom(consolidator.OutputType))
3284  {
3285  // special case downgrading of QuoteBar -> TradeBar
3286  if (typeof(T) == typeof(TradeBar) && consolidator.OutputType == typeof(QuoteBar))
3287  {
3288  // collapse quote bar into trade bar (ignore the funky casting, required due to generics)
3289  consolidator.DataConsolidated += (sender, consolidated) => handler((T)(object)((QuoteBar)consolidated).Collapse());
3290  }
3291 
3292  throw new ArgumentException(
3293  $"Unable to consolidate with the specified handler because the consolidator's output type " +
3294  $"is {consolidator.OutputType.Name} but the handler's input type is {typeof(T).Name}.");
3295  }
3296 
3297  // register user-defined handler to receive consolidated data events
3298  consolidator.DataConsolidated += (sender, consolidated) => handler((T)consolidated);
3299 
3300  // register the consolidator for automatic updates via SubscriptionManager
3301  SubscriptionManager.AddConsolidator(symbol, consolidator, tickType);
3302  }
3303 
3304  [DocumentationAttribute(ConsolidatingData)]
3305  private IDataConsolidator CreateConsolidator(Func<DateTime, CalendarInfo> calendar, Type consolidatorInputType, TickType tickType)
3306  {
3307  // if our type can be used as a trade bar, then let's just make one of those
3308  // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to TradeBar
3309  if (typeof(TradeBar).IsAssignableFrom(consolidatorInputType))
3310  {
3311  return new TradeBarConsolidator(calendar);
3312  }
3313 
3314  // if our type can be used as a quote bar, then let's just make one of those
3315  // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to QuoteBar
3316  if (typeof(QuoteBar).IsAssignableFrom(consolidatorInputType))
3317  {
3318  return new QuoteBarConsolidator(calendar);
3319  }
3320 
3321  // if our type can be used as a tick then we'll use a consolidator that keeps the TickType
3322  // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to Tick
3323  if (typeof(Tick).IsAssignableFrom(consolidatorInputType))
3324  {
3325  if (tickType == TickType.Quote)
3326  {
3327  return new TickQuoteBarConsolidator(calendar);
3328  }
3329  return new TickConsolidator(calendar);
3330  }
3331 
3332  // if our type can be used as a DynamicData then we'll use the DynamicDataConsolidator
3333  if (typeof(DynamicData).IsAssignableFrom(consolidatorInputType))
3334  {
3335  return new DynamicDataConsolidator(calendar);
3336  }
3337 
3338  // no matter what we can always consolidate based on the time-value pair of BaseData
3339  return new BaseDataConsolidator(calendar);
3340  }
3341 
3342  /// <summary>
3343  /// Registers and warms up (if EnableAutomaticIndicatorWarmUp is set) the indicator
3344  /// </summary>
3345  private void InitializeIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, Resolution? resolution = null,
3346  Func<IBaseData, decimal> selector = null)
3347  {
3348  RegisterIndicator(symbol, indicator, resolution, selector);
3349 
3351  {
3352  WarmUpIndicator(symbol, indicator, resolution, selector);
3353  }
3354  }
3355 
3356  private void InitializeIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, Resolution? resolution = null,
3357  Func<IBaseData, T> selector = null)
3358  where T : class, IBaseData
3359  {
3360  RegisterIndicator(symbol, indicator, resolution, selector);
3361 
3363  {
3364  WarmUpIndicator(symbol, indicator, resolution, selector);
3365  }
3366  }
3367 
3368  private string InitializeOptionIndicator<T>(Symbol symbol, out IRiskFreeInterestRateModel riskFreeRateModel, out IDividendYieldModel dividendYieldModel,
3369  decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes, Resolution? resolution = null)
3370  where T : OptionIndicatorBase
3371  {
3372  var name = CreateIndicatorName(symbol, $"{typeof(T).Name}({riskFreeRate},{dividendYield},{optionModel})", resolution);
3373 
3374  riskFreeRateModel = riskFreeRate.HasValue
3375  ? new ConstantRiskFreeRateInterestRateModel(riskFreeRate.Value)
3376  // Make it a function so it's lazily evaluated: SetRiskFreeInterestRateModel can be called after this method
3377  : new FuncRiskFreeRateInterestRateModel((datetime) => RiskFreeInterestRateModel.GetInterestRate(datetime));
3378 
3379  if (dividendYield.HasValue)
3380  {
3381  dividendYieldModel = new ConstantDividendYieldModel(dividendYield.Value);
3382  }
3383  else if (symbol.ID.SecurityType == SecurityType.FutureOption || symbol.ID.SecurityType == SecurityType.IndexOption)
3384  {
3385  dividendYieldModel = new ConstantDividendYieldModel(0m);
3386  }
3387  else
3388  {
3389  dividendYieldModel = new DividendYieldProvider(symbol.Underlying);
3390  }
3391 
3392  return name;
3393  }
3394 
3395  private void RegisterConsolidator(IndicatorBase indicatorBase, Symbol symbol, IDataConsolidator consolidator)
3396  {
3397  // keep a reference of the consolidator so we can unregister it later using only a reference to the indicator
3398  indicatorBase.Consolidators.Add(consolidator);
3399 
3400  // register the consolidator for automatic updates via SubscriptionManager
3401  SubscriptionManager.AddConsolidator(symbol, consolidator);
3402  }
3403  }
3404 }