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