/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using QuantConnect.Data; using QuantConnect.Data.Consolidators; using QuantConnect.Data.Market; using QuantConnect.Indicators; using System; using System.Collections.Generic; using System.Linq; using Python.Runtime; using QuantConnect.Util; using static QuantConnect.StringExtensions; using QuantConnect.Data.Common; using QuantConnect.Python; namespace QuantConnect.Algorithm { public partial class QCAlgorithm { private readonly List> _quoteRequiredFields = new() { Field.BidPrice, Field.AskPrice, Field.BidClose, Field.BidOpen, Field.BidLow, Field.BidHigh, Field.AskClose, Field.AskOpen, Field.AskLow, Field.AskHigh, }; private static readonly HashSet _ignoredProperties = new HashSet { "Consolidators", "Current", "Previous", "Name", "Samples", "IsReady", "Window", "Item", "WarmUpPeriod" }; /// /// Gets whether or not WarmUpIndicator is allowed to warm up indicators /// [Obsolete("Please use Settings.AutomaticIndicatorWarmUp")] public bool EnableAutomaticIndicatorWarmUp { get { return Settings.AutomaticIndicatorWarmUp; } set { Settings.AutomaticIndicatorWarmUp = value; } } /// /// Creates a new Acceleration Bands indicator. /// /// The symbol whose Acceleration Bands we want. /// The period of the three moving average (middle, upper and lower band). /// A coefficient specifying the distance between the middle band and upper or lower bands. /// Type of the moving average. /// The resolution. /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar. /// [DocumentationAttribute(Indicators)] public AccelerationBands ABANDS(Symbol symbol, int period, decimal width = 4, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"ABANDS({period},{width})", resolution); var accelerationBands = new AccelerationBands(name, period, width, movingAverageType); InitializeIndicator(accelerationBands, resolution, selector, symbol); return accelerationBands; } /// /// Creates a new AccumulationDistribution indicator. /// /// The symbol whose AD we want /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The AccumulationDistribution indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public AccumulationDistribution AD(Symbol symbol, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, "AD", resolution); var accumulationDistribution = new AccumulationDistribution(name); InitializeIndicator(accumulationDistribution, resolution, selector, symbol); return accumulationDistribution; } /// /// Creates a new AccumulationDistributionOscillator indicator. /// /// The symbol whose ADOSC we want /// The fast moving average period /// The slow moving average period /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The AccumulationDistributionOscillator indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public AccumulationDistributionOscillator ADOSC(Symbol symbol, int fastPeriod, int slowPeriod, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"ADOSC({fastPeriod},{slowPeriod})", resolution); var accumulationDistributionOscillator = new AccumulationDistributionOscillator(name, fastPeriod, slowPeriod); InitializeIndicator(accumulationDistributionOscillator, resolution, selector, symbol); return accumulationDistributionOscillator; } /// /// Creates a Alpha indicator for the given target symbol in relation with the reference used. /// The indicator will be automatically updated on the given resolution. /// /// The target symbol whose Alpha value we want /// The reference symbol to compare with the target symbol /// The period of the Alpha indicator /// The period of the Beta indicator /// The resolution /// The risk free rate /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Alpha indicator for the given parameters [DocumentationAttribute(Indicators)] public Alpha A(Symbol target, Symbol reference, int alphaPeriod = 1, int betaPeriod = 252, Resolution? resolution = null, decimal? riskFreeRate = null, Func selector = null) { var baseBame = riskFreeRate.HasValue ? $"A({alphaPeriod},{betaPeriod},{riskFreeRate})" : $"A({alphaPeriod},{betaPeriod})"; var name = CreateIndicatorName(target, baseBame, resolution); // If risk free rate is not specified, use the default risk free rate model IRiskFreeInterestRateModel riskFreeRateModel = riskFreeRate.HasValue ? new ConstantRiskFreeRateInterestRateModel(riskFreeRate.Value) : new FuncRiskFreeRateInterestRateModel((datetime) => RiskFreeInterestRateModel.GetInterestRate(datetime)); var alpha = new Alpha(name, target, reference, alphaPeriod, betaPeriod, riskFreeRateModel); InitializeIndicator(alpha, resolution, selector, target, reference); return alpha; } /// /// Creates a new Average Range (AR) indicator. /// /// The symbol whose Average Range we want to calculate /// The period over which to compute the Average Range /// The resolution /// Selects a value from the BaseData to send into the indicator. If null, defaults to the Value property of BaseData (x => x.Value). /// The Average Range indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public AverageRange AR(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"AR({period})", resolution); var averageRange = new AverageRange(name, period); InitializeIndicator(averageRange, resolution, selector, symbol); return averageRange; } /// /// Creates a new ARIMA indicator. /// /// The symbol whose ARIMA indicator we want /// AR order (p) -- defines the number of past values to consider in the AR component of the model. /// Difference order (d) -- defines how many times to difference the model before fitting parameters. /// MA order (q) -- defines the number of past values to consider in the MA component of the model. /// Size of the rolling series to fit onto /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The ARIMA indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public AutoRegressiveIntegratedMovingAverage ARIMA(Symbol symbol, int arOrder, int diffOrder, int maOrder, int period, Resolution? resolution = null, Func selector = null) { return ARIMA(symbol, arOrder, diffOrder, maOrder, period, true, resolution, selector); } /// /// Creates a new ARIMA indicator. /// /// The symbol whose ARIMA indicator we want /// AR order (p) -- defines the number of past values to consider in the AR component of the model. /// Difference order (d) -- defines how many times to difference the model before fitting parameters. /// MA order (q) -- defines the number of past values to consider in the MA component of the model. /// Size of the rolling series to fit onto /// Whether or not to include the intercept term /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The ARIMA indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public AutoRegressiveIntegratedMovingAverage ARIMA(Symbol symbol, int arOrder, int diffOrder, int maOrder, int period, bool intercept, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"ARIMA({arOrder},{diffOrder},{maOrder},{period})", resolution); var arimaIndicator = new AutoRegressiveIntegratedMovingAverage(name, arOrder, diffOrder, maOrder, period, intercept); InitializeIndicator(arimaIndicator, resolution, selector, symbol); return arimaIndicator; } /// /// Creates a new Average Directional Index indicator. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose Average Directional Index we seek /// The resolution. /// The period over which to compute the Average Directional Index /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Average Directional Index indicator for the requested symbol. [DocumentationAttribute(Indicators)] public AverageDirectionalIndex ADX(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"ADX({period})", resolution); var averageDirectionalIndex = new AverageDirectionalIndex(name, period); InitializeIndicator(averageDirectionalIndex, resolution, selector, symbol); return averageDirectionalIndex; } /// /// Creates a new Awesome Oscillator from the specified periods. /// /// The symbol whose Awesome Oscillator we seek /// The resolution. /// The period of the fast moving average associated with the AO /// The period of the slow moving average associated with the AO /// The type of moving average used when computing the fast and slow term. Defaults to simple moving average. /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar [DocumentationAttribute(Indicators)] public AwesomeOscillator AO(Symbol symbol, int fastPeriod, int slowPeriod, MovingAverageType type, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"AO({fastPeriod},{slowPeriod},{type})", resolution); var awesomeOscillator = new AwesomeOscillator(name, fastPeriod, slowPeriod, type); InitializeIndicator(awesomeOscillator, resolution, selector, symbol); return awesomeOscillator; } /// /// Creates a new AverageDirectionalMovementIndexRating indicator. /// /// The symbol whose ADXR we want /// The period over which to compute the ADXR /// The resolution. /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The AverageDirectionalMovementIndexRating indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public AverageDirectionalMovementIndexRating ADXR(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"ADXR({period})", resolution); var averageDirectionalMovementIndexRating = new AverageDirectionalMovementIndexRating(name, period); InitializeIndicator(averageDirectionalMovementIndexRating, resolution, selector, symbol); return averageDirectionalMovementIndexRating; } /// /// Creates a new ArnaudLegouxMovingAverage indicator. /// /// The symbol whose ALMA we want /// int - the number of periods to calculate the ALMA /// int - this parameter is responsible for the shape of the curve coefficients. /// /// /// decimal - This parameter allows regulating the smoothness and high sensitivity of the /// Moving Average. The range for this parameter is [0, 1]. /// /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The ArnaudLegouxMovingAverage indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public ArnaudLegouxMovingAverage ALMA(Symbol symbol, int period, int sigma = 6, decimal offset = 0.85m, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"ALMA({period},{sigma},{offset})", resolution); var arnaudLegouxMovingAverage = new ArnaudLegouxMovingAverage(name, period, sigma, offset); InitializeIndicator(arnaudLegouxMovingAverage, resolution, selector, symbol); return arnaudLegouxMovingAverage; } /// /// Creates a new AbsolutePriceOscillator indicator. /// /// The symbol whose APO we want /// The fast moving average period /// The slow moving average period /// The type of moving average to use /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The AbsolutePriceOscillator indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public AbsolutePriceOscillator APO(Symbol symbol, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"APO({fastPeriod},{slowPeriod})", resolution); var absolutePriceOscillator = new AbsolutePriceOscillator(name, fastPeriod, slowPeriod, movingAverageType); InitializeIndicator(absolutePriceOscillator, resolution, selector, symbol); return absolutePriceOscillator; } /// /// Creates a new AroonOscillator indicator which will compute the AroonUp and AroonDown (as well as the delta) /// /// The symbol whose Aroon we seek /// The look back period for computing number of periods since maximum and minimum /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// An AroonOscillator configured with the specified periods [DocumentationAttribute(Indicators)] public AroonOscillator AROON(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { return AROON(symbol, period, period, resolution, selector); } /// /// Creates a new AroonOscillator indicator which will compute the AroonUp and AroonDown (as well as the delta) /// /// The symbol whose Aroon we seek /// The look back period for computing number of periods since maximum /// The look back period for computing number of periods since minimum /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// An AroonOscillator configured with the specified periods [DocumentationAttribute(Indicators)] public AroonOscillator AROON(Symbol symbol, int upPeriod, int downPeriod, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"AROON({upPeriod},{downPeriod})", resolution); var aroonOscillator = new AroonOscillator(name, upPeriod, downPeriod); InitializeIndicator(aroonOscillator, resolution, selector, symbol); return aroonOscillator; } /// /// Creates a new AverageTrueRange indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose ATR we want /// The smoothing period used to smooth the computed TrueRange values /// The type of smoothing to use /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// A new AverageTrueRange indicator with the specified smoothing type and period [DocumentationAttribute(Indicators)] public AverageTrueRange ATR(Symbol symbol, int period, MovingAverageType type = MovingAverageType.Simple, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"ATR({period})", resolution); var averageTrueRange = new AverageTrueRange(name, period, type); InitializeIndicator(averageTrueRange, resolution, selector, symbol); return averageTrueRange; } /// /// Creates an AugenPriceSpike indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose APS we want /// The period of the APS /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The AugenPriceSpike indicator for the given parameters [DocumentationAttribute(Indicators)] public AugenPriceSpike APS(Symbol symbol, int period = 3, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"APS({period})", resolution); var augenPriceSpike = new AugenPriceSpike(name, period); InitializeIndicator(augenPriceSpike, resolution, selector, symbol); return augenPriceSpike; } /// /// Creates a new BollingerBands indicator which will compute the MiddleBand, UpperBand, LowerBand, and StandardDeviation /// /// The symbol whose BollingerBands we seek /// The period of the standard deviation and moving average (middle band) /// The number of standard deviations specifying the distance between the middle band and upper or lower bands /// The type of moving average to be used /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// A BollingerBands configured with the specified period [DocumentationAttribute(Indicators)] public BollingerBands BB(Symbol symbol, int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"BB({period},{k})", resolution); var bollingerBands = new BollingerBands(name, period, k, movingAverageType); InitializeIndicator(bollingerBands, resolution, selector, symbol); return bollingerBands; } /// /// Creates a Beta indicator for the given target symbol in relation with the reference used. /// The indicator will be automatically updated on the given resolution. /// /// The target symbol whose Beta value we want /// The reference symbol to compare with the target symbol /// The period of the Beta indicator /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Beta indicator for the given parameters [DocumentationAttribute(Indicators)] public Beta B(Symbol target, Symbol reference, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(QuantConnect.Symbol.None, $"B({period})", resolution); var beta = new Beta(name, target, reference, period); InitializeIndicator(beta, resolution, selector, target, reference); return beta; } /// /// Creates a new Balance Of Power indicator. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose Balance Of Power we seek /// The resolution. /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Balance Of Power indicator for the requested symbol. [DocumentationAttribute(Indicators)] public BalanceOfPower BOP(Symbol symbol, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, "BOP", resolution); var balanceOfPower = new BalanceOfPower(name); InitializeIndicator(balanceOfPower, resolution, selector, symbol); return balanceOfPower; } /// /// Initializes a new instance of the indicator /// /// The symbol whose Coppock Curve we want /// The period for the short ROC /// The period for the long ROC /// The period for the LWMA /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Coppock Curve indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public CoppockCurve CC(Symbol symbol, int shortRocPeriod = 11, int longRocPeriod = 14, int lwmaPeriod = 10, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"CC({shortRocPeriod},{longRocPeriod},{lwmaPeriod})", resolution); var coppockCurve = new CoppockCurve(name, shortRocPeriod, longRocPeriod, lwmaPeriod); InitializeIndicator(coppockCurve, resolution, selector, symbol); return coppockCurve; } /// /// Creates a Correlation indicator for the given target symbol in relation with the reference used. /// The indicator will be automatically updated on the given resolution. /// /// The target symbol of this indicator /// The reference symbol of this indicator /// The period of this indicator /// Correlation type /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Correlation indicator for the given parameters [DocumentationAttribute(Indicators)] public Correlation C(Symbol target, Symbol reference, int period, CorrelationType correlationType = CorrelationType.Pearson, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(QuantConnect.Symbol.None, $"C({period})", resolution); var correlation = new Correlation(name, target, reference, period, correlationType); InitializeIndicator(correlation, resolution, selector, target, reference); return correlation; } /// /// Creates a new CommodityChannelIndex indicator. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose CCI we want /// The period over which to compute the CCI /// The type of moving average to use in computing the typical price average /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The CommodityChannelIndex indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public CommodityChannelIndex CCI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"CCI({period})", resolution); var commodityChannelIndex = new CommodityChannelIndex(name, period, movingAverageType); InitializeIndicator(commodityChannelIndex, resolution, selector, symbol); return commodityChannelIndex; } /// /// Creates a new ChoppinessIndex indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose CHOP we want /// The input window period used to calculate max high and min low /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// A new ChoppinessIndex indicator with the window period [DocumentationAttribute(Indicators)] public ChoppinessIndex CHOP(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"CHOP({period})", resolution); var indicator = new ChoppinessIndex(name, period); InitializeIndicator(indicator, resolution, selector, symbol); return indicator; } /// /// Creates a new Chande Kroll Stop indicator which will compute the short and lower stop. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose Chande Kroll Stop we seek. /// The period over which to compute the average true range. /// The ATR multiplier to be used to compute stops distance. /// The period over which to compute the max of high stop and min of low stop. /// The resolution. /// The type of smoothing used to smooth the true range values /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Chande Kroll Stop indicator for the requested symbol. [DocumentationAttribute(Indicators)] public ChandeKrollStop CKS(Symbol symbol, int atrPeriod, decimal atrMult, int period, MovingAverageType movingAverageType = MovingAverageType.Wilders, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"CKS({atrPeriod},{atrMult},{period})", resolution); var indicator = new ChandeKrollStop(name, atrPeriod, atrMult, period, movingAverageType); InitializeIndicator(indicator, resolution, selector, symbol); return indicator; } /// /// Creates a new ChaikinMoneyFlow indicator. /// /// The symbol whose CMF we want /// The period over which to compute the CMF /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The ChaikinMoneyFlow indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public ChaikinMoneyFlow CMF(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"CMF({period})", resolution); var chaikinMoneyFlow = new ChaikinMoneyFlow(name, period); InitializeIndicator(chaikinMoneyFlow, resolution, selector, symbol); return chaikinMoneyFlow; } /// /// Creates a new Chaikin Oscillator indicator. /// /// The symbol whose CO we want /// The fast moving average period /// The slow moving average period /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The Chaikin Oscillator indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public ChaikinOscillator CO(Symbol symbol, int fastPeriod, int slowPeriod, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"CO({fastPeriod},{slowPeriod})", resolution); var chaikinOscillator = new ChaikinOscillator(name, fastPeriod, slowPeriod); InitializeIndicator(chaikinOscillator, resolution, selector, symbol); return chaikinOscillator; } /// /// Creates a new ChandeMomentumOscillator indicator. /// /// The symbol whose CMO we want /// The period over which to compute the CMO /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The ChandeMomentumOscillator indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public ChandeMomentumOscillator CMO(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"CMO({period})", resolution); var chandeMomentumOscillator = new ChandeMomentumOscillator(name, period); InitializeIndicator(chandeMomentumOscillator, resolution, selector, symbol); return chandeMomentumOscillator; } /// /// Creates a new Connors Relative Strength Index (CRSI) indicator, which combines the traditional Relative Strength Index (RSI), /// Streak RSI (SRSI), and Percent Rank to provide a more robust measure of market strength. /// This indicator oscillates based on momentum, streak behavior, and price change over the specified periods. /// /// The symbol whose CRSI is to be calculated. /// The period for the traditional RSI calculation. /// The period for the Streak RSI calculation (SRSI). /// The look-back period for calculating the Percent Rank. /// The resolution of the data (optional). /// Function to select a value from the BaseData to input into the indicator. Defaults to using the 'Value' property of BaseData if null. /// The Connors Relative Strength Index (CRSI) for the specified symbol and periods. [DocumentationAttribute(Indicators)] public ConnorsRelativeStrengthIndex CRSI(Symbol symbol, int rsiPeriod, int rsiPeriodStreak, int lookBackPeriod, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"CRSI({rsiPeriod},{rsiPeriodStreak},{lookBackPeriod})", resolution); var connorsRelativeStrengthIndex = new ConnorsRelativeStrengthIndex(name, rsiPeriod, rsiPeriodStreak, lookBackPeriod); InitializeIndicator(connorsRelativeStrengthIndex, resolution, selector, symbol); return connorsRelativeStrengthIndex; } /// /// Creates a new DeMarker Indicator (DEM), an oscillator-type indicator measuring changes in terms of an asset's /// High and Low tradebar values. /// /// The symbol whose DEM we seek. /// The period of the moving average implemented /// Specifies the type of moving average to be used /// The resolution. /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The DeMarker indicator for the requested symbol. [DocumentationAttribute(Indicators)] public DeMarkerIndicator DEM(Symbol symbol, int period, MovingAverageType type, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"DEM({period},{type})", resolution); var deMarkerIndicator = new DeMarkerIndicator(name, period, type); InitializeIndicator(deMarkerIndicator, resolution, selector, symbol); return deMarkerIndicator; } /// /// Creates a new Donchian Channel indicator which will compute the Upper Band and Lower Band. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose Donchian Channel we seek. /// The period over which to compute the upper Donchian Channel. /// The period over which to compute the lower Donchian Channel. /// The resolution. /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Donchian Channel indicator for the requested symbol. [DocumentationAttribute(Indicators)] public DonchianChannel DCH(Symbol symbol, int upperPeriod, int lowerPeriod, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"DCH({upperPeriod},{lowerPeriod})", resolution); var donchianChannel = new DonchianChannel(name, upperPeriod, lowerPeriod); InitializeIndicator(donchianChannel, resolution, selector, symbol); return donchianChannel; } /// /// Overload shorthand to create a new symmetric Donchian Channel indicator which /// has the upper and lower channels set to the same period length. /// /// The symbol whose Donchian Channel we seek. /// The period over which to compute the Donchian Channel. /// The resolution. /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a IBaseDataBar /// The Donchian Channel indicator for the requested symbol. [DocumentationAttribute(Indicators)] public DonchianChannel DCH(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { return DCH(symbol, period, period, resolution, selector); } /// /// Creates a new Delta indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The option symbol whose values we want as an indicator /// The mirror option for parity calculation /// The risk free rate /// The dividend yield /// The option pricing model used to estimate Delta /// The option pricing model used to estimate IV /// The desired resolution of the data /// A new Delta indicator for the specified symbol [DocumentationAttribute(Indicators)] public Delta D(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null, Resolution? resolution = null) { var name = InitializeOptionIndicator(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution); var delta = new Delta(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel); InitializeOptionIndicator(delta, resolution, symbol, mirrorOption); return delta; } /// /// Creates a new Delta indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The option symbol whose values we want as an indicator /// The mirror option for parity calculation /// The risk free rate /// The dividend yield /// The option pricing model used to estimate Delta /// The option pricing model used to estimate IV /// The desired resolution of the data /// A new Delta indicator for the specified symbol [DocumentationAttribute(Indicators)] public Delta Δ(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes, OptionPricingModelType? ivModel = null, Resolution? resolution = null) { return D(symbol, mirrorOption, riskFreeRate, dividendYield, optionModel, ivModel, resolution); } /// /// Creates a new DoubleExponentialMovingAverage indicator. /// /// The symbol whose DEMA we want /// The period over which to compute the DEMA /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The DoubleExponentialMovingAverage indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public DoubleExponentialMovingAverage DEMA(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"DEMA({period})", resolution); var doubleExponentialMovingAverage = new DoubleExponentialMovingAverage(name, period); InitializeIndicator(doubleExponentialMovingAverage, resolution, selector, symbol); return doubleExponentialMovingAverage; } /// /// Creates a new DerivativeOscillator indicator. /// /// The symbol whose DO we want /// The period over which to compute the RSI /// The period over which to compute the smoothing RSI /// The period over which to compute the double smoothing RSI /// The period over which to compute the signal line /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The DerivativeOscillator indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public DerivativeOscillator DO(Symbol symbol, int rsiPeriod, int smoothingRsiPeriod, int doubleSmoothingRsiPeriod, int signalLinePeriod, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"DO({rsiPeriod},{smoothingRsiPeriod},{doubleSmoothingRsiPeriod},{signalLinePeriod})", resolution); var derivativeOscillator = new DerivativeOscillator(name, rsiPeriod, smoothingRsiPeriod, doubleSmoothingRsiPeriod, signalLinePeriod); InitializeIndicator(derivativeOscillator, resolution, selector, symbol); return derivativeOscillator; } /// /// Creates a new indicator. /// /// The symbol whose DPO we want /// The period over which to compute the DPO /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// A new registered DetrendedPriceOscillator indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public DetrendedPriceOscillator DPO(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"DPO({period})", resolution); var detrendedPriceOscillator = new DetrendedPriceOscillator(name, period); InitializeIndicator(detrendedPriceOscillator, resolution, selector, symbol); return detrendedPriceOscillator; } /// /// Creates an ExponentialMovingAverage indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose EMA we want /// The period of the EMA /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The ExponentialMovingAverage for the given parameters [DocumentationAttribute(Indicators)] public ExponentialMovingAverage EMA(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { return EMA(symbol, period, ExponentialMovingAverage.SmoothingFactorDefault(period), resolution, selector); } /// /// Creates an ExponentialMovingAverage indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose EMA we want /// The period of the EMA /// The percentage of data from the previous value to be carried into the next value /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The ExponentialMovingAverage for the given parameters [DocumentationAttribute(Indicators)] public ExponentialMovingAverage EMA(Symbol symbol, int period, decimal smoothingFactor, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"EMA({period})", resolution); var exponentialMovingAverage = new ExponentialMovingAverage(name, period, smoothingFactor); InitializeIndicator(exponentialMovingAverage, resolution, selector, symbol); return exponentialMovingAverage; } /// /// Creates an EaseOfMovementValue indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose EMV we want /// The period of the EMV /// The length of the outputed value /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The EaseOfMovementValue indicator for the given parameters [DocumentationAttribute(Indicators)] public EaseOfMovementValue EMV(Symbol symbol, int period = 1, int scale = 10000, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"EMV({period}, {scale})", resolution); var easeOfMovementValue = new EaseOfMovementValue(name, period, scale); InitializeIndicator(easeOfMovementValue, resolution, selector, symbol); return easeOfMovementValue; } /// /// Creates a new FilteredIdentity indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The symbol whose values we want as an indicator /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter /// The name of the field being selected /// A new FilteredIdentity indicator for the specified symbol and selector [DocumentationAttribute(Indicators)] public FilteredIdentity FilteredIdentity(Symbol symbol, Func selector = null, Func filter = null, string fieldName = null) { var resolution = GetSubscription(symbol).Resolution; return FilteredIdentity(symbol, resolution, selector, filter, fieldName); } /// /// Creates a new FilteredIdentity indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The symbol whose values we want as an indicator /// The desired resolution of the data /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter /// The name of the field being selected /// A new FilteredIdentity indicator for the specified symbol and selector [DocumentationAttribute(Indicators)] public FilteredIdentity FilteredIdentity(Symbol symbol, Resolution resolution, Func selector = null, Func filter = null, string fieldName = null) { var name = CreateIndicatorName(symbol, fieldName ?? "close", resolution); var filteredIdentity = new FilteredIdentity(name, filter); RegisterIndicator(symbol, filteredIdentity, resolution, selector); return filteredIdentity; } /// /// Creates a new FilteredIdentity indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The symbol whose values we want as an indicator /// The desired resolution of the data /// Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value) /// Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter /// The name of the field being selected /// A new FilteredIdentity indicator for the specified symbol and selector [DocumentationAttribute(Indicators)] public FilteredIdentity FilteredIdentity(Symbol symbol, TimeSpan resolution, Func selector = null, Func filter = null, string fieldName = null) { var name = Invariant($"{symbol}({fieldName ?? "close"}_{resolution})"); var filteredIdentity = new FilteredIdentity(name, filter); RegisterIndicator(symbol, filteredIdentity, ResolveConsolidator(symbol, resolution), selector); return filteredIdentity; } /// /// Creates a new ForceIndex indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose ForceIndex we want /// The smoothing period used to smooth the computed ForceIndex values /// The type of smoothing to use /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// A new ForceIndex indicator with the specified smoothing type and period [DocumentationAttribute(Indicators)] public ForceIndex FI(Symbol symbol, int period, MovingAverageType type = MovingAverageType.Exponential, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"FI({period})", resolution); var indicator = new ForceIndex(name, period, type); InitializeIndicator(indicator, resolution, selector, symbol); return indicator; } /// /// Creates an FisherTransform indicator for the symbol. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose FisherTransform we want /// The period of the FisherTransform /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The FisherTransform for the given parameters [DocumentationAttribute(Indicators)] public FisherTransform FISH(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"FISH({period})", resolution); var fisherTransform = new FisherTransform(name, period); InitializeIndicator(fisherTransform, resolution, selector, symbol); return fisherTransform; } /// /// Creates an FractalAdaptiveMovingAverage (FRAMA) indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose FRAMA we want /// The period of the FRAMA /// The long period of the FRAMA /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The FRAMA for the given parameters [DocumentationAttribute(Indicators)] public FractalAdaptiveMovingAverage FRAMA(Symbol symbol, int period, int longPeriod = 198, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"FRAMA({period},{longPeriod})", resolution); var fractalAdaptiveMovingAverage = new FractalAdaptiveMovingAverage(name, period, longPeriod); InitializeIndicator(fractalAdaptiveMovingAverage, resolution, selector, symbol); return fractalAdaptiveMovingAverage; } /// /// Creates a new Gamma indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The option symbol whose values we want as an indicator /// The mirror option for parity calculation /// The risk free rate /// The dividend yield /// The option pricing model used to estimate Gamma /// The option pricing model used to estimate IV /// The desired resolution of the data /// A new Gamma indicator for the specified symbol [DocumentationAttribute(Indicators)] public Gamma G(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null, Resolution? resolution = null) { var name = InitializeOptionIndicator(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution); var gamma = new Gamma(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel); InitializeOptionIndicator(gamma, resolution, symbol, mirrorOption); return gamma; } /// /// Creates a new Gamma indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The option symbol whose values we want as an indicator /// The mirror option for parity calculation /// The risk free rate /// The dividend yield /// The option pricing model used to estimate Gamma /// The option pricing model used to estimate IV /// The desired resolution of the data /// A new Gamma indicator for the specified symbol [DocumentationAttribute(Indicators)] public Gamma Γ(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes, OptionPricingModelType? ivModel = null, Resolution? resolution = null) { return G(symbol, mirrorOption, riskFreeRate, dividendYield, optionModel, ivModel, resolution); } /// /// Creates a new Heikin-Ashi indicator. /// /// The symbol whose Heikin-Ashi we want /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Heikin-Ashi indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public HeikinAshi HeikinAshi(Symbol symbol, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, "HA", resolution); var heikinAshi = new HeikinAshi(name); InitializeIndicator(heikinAshi, resolution, selector, symbol); return heikinAshi; } /// /// Creates a new Hurst Exponent indicator for the specified symbol. /// The Hurst Exponent measures the long-term memory or self-similarity in a time series. /// The default maxLag value of 20 is chosen for reliable and accurate results, but using a higher lag may reduce precision. /// /// The symbol for which the Hurst Exponent is calculated. /// The number of data points used to calculate the indicator at each step. /// The maximum time lag used to compute the tau values for the Hurst Exponent calculation. /// The resolution /// Function to select a value from the BaseData to input into the indicator. Defaults to using the 'Value' property of BaseData if null. /// The Hurst Exponent indicator for the specified symbol. [DocumentationAttribute(Indicators)] public HurstExponent HE(Symbol symbol, int period, int maxLag = 20, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"HE({period},{maxLag})", resolution); var hurstExponent = new HurstExponent(name, period, maxLag); InitializeIndicator(hurstExponent, resolution, selector, symbol); return hurstExponent; } /// /// Creates a new Hilbert Transform indicator /// /// The symbol whose Hilbert transform we want /// The length of the FIR filter used in the calculation of the Hilbert Transform. /// This parameter determines the number of filter coefficients in the FIR filter. /// The multiplication factor used in the calculation of the in-phase component /// of the Hilbert Transform. This parameter adjusts the sensitivity and responsiveness of /// the transform to changes in the input signal. /// The multiplication factor used in the calculation of the quadrature component of /// the Hilbert Transform. This parameter also adjusts the sensitivity and responsiveness of the /// transform to changes in the input signal. /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) [DocumentationAttribute(Indicators)] public HilbertTransform HT(Symbol symbol, int length, decimal inPhaseMultiplicationFactor, decimal quadratureMultiplicationFactor, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"HT({length}, {inPhaseMultiplicationFactor}, {quadratureMultiplicationFactor})", resolution); var hilbertTransform = new HilbertTransform(length, inPhaseMultiplicationFactor, quadratureMultiplicationFactor); InitializeIndicator(hilbertTransform, resolution, selector, symbol); return hilbertTransform; } /// /// Creates a new HullMovingAverage indicator. The Hull moving average is a series of nested weighted moving averages, is fast and smooth. /// /// The symbol whose Hull moving average we want /// The period over which to compute the Hull moving average /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// [DocumentationAttribute(Indicators)] public HullMovingAverage HMA(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"HMA({period})", resolution); var hullMovingAverage = new HullMovingAverage(name, period); InitializeIndicator(hullMovingAverage, resolution, selector, symbol); return hullMovingAverage; } /// /// Creates a new InternalBarStrength indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose IBS we want /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// A new InternalBarStrength indicator [DocumentationAttribute(Indicators)] public InternalBarStrength IBS(Symbol symbol, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, "IBS", resolution); var indicator = new InternalBarStrength(name); InitializeIndicator(indicator, resolution, selector, symbol); return indicator; } /// /// Creates a new IchimokuKinkoHyo indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose ICHIMOKU we want /// The period to calculate the Tenkan-sen period /// The period to calculate the Kijun-sen period /// The period to calculate the Tenkan-sen period /// The period to calculate the Tenkan-sen period /// The period to calculate the Tenkan-sen period /// The period to calculate the Tenkan-sen period /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// A new IchimokuKinkoHyo indicator with the specified periods and delays [DocumentationAttribute(Indicators)] public IchimokuKinkoHyo ICHIMOKU(Symbol symbol, int tenkanPeriod, int kijunPeriod, int senkouAPeriod, int senkouBPeriod, int senkouADelayPeriod, int senkouBDelayPeriod, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"ICHIMOKU({tenkanPeriod},{kijunPeriod},{senkouAPeriod},{senkouBPeriod},{senkouADelayPeriod},{senkouBDelayPeriod})", resolution); var ichimokuKinkoHyo = new IchimokuKinkoHyo(name, tenkanPeriod, kijunPeriod, senkouAPeriod, senkouBPeriod, senkouADelayPeriod, senkouBDelayPeriod); InitializeIndicator(ichimokuKinkoHyo, resolution, selector, symbol); return ichimokuKinkoHyo; } /// /// Creates a new Identity indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The symbol whose values we want as an indicator /// Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value) /// The name of the field being selected /// A new Identity indicator for the specified symbol and selector [DocumentationAttribute(Indicators)] public Identity Identity(Symbol symbol, Func selector = null, string fieldName = null) { var resolution = GetSubscription(symbol).Resolution; return Identity(symbol, resolution, selector, fieldName); } /// /// Creates a new Identity indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The symbol whose values we want as an indicator /// The desired resolution of the data /// Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value) /// The name of the field being selected /// A new Identity indicator for the specified symbol and selector [DocumentationAttribute(Indicators)] public Identity Identity(Symbol symbol, Resolution resolution, Func selector = null, string fieldName = null) { var name = CreateIndicatorName(symbol, fieldName ?? "close", resolution); var identity = new Identity(name); InitializeIndicator(identity, resolution, selector, symbol); return identity; } /// /// Creates a new Identity indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The symbol whose values we want as an indicator /// The desired resolution of the data /// Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value) /// The name of the field being selected /// A new Identity indicator for the specified symbol and selector [DocumentationAttribute(Indicators)] public Identity Identity(Symbol symbol, TimeSpan resolution, Func selector = null, string fieldName = null) { var name = Invariant($"{symbol}({fieldName ?? "close"},{resolution})"); var identity = new Identity(name); RegisterIndicator(symbol, identity, ResolveConsolidator(symbol, resolution), selector); return identity; } /// /// Creates a new ImpliedVolatility indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The option symbol whose values we want as an indicator /// The mirror option contract used for parity type calculation /// The risk free rate /// The dividend yield /// The option pricing model used to estimate IV /// The desired resolution of the data /// A new ImpliedVolatility indicator for the specified symbol [DocumentationAttribute(Indicators)] public ImpliedVolatility IV(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType? optionModel = null, Resolution? resolution = null) { var name = InitializeOptionIndicator(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution); var iv = new ImpliedVolatility(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel); InitializeOptionIndicator(iv, resolution, symbol, mirrorOption); return iv; } /// /// Creates a new KaufmanAdaptiveMovingAverage indicator. /// /// The symbol whose KAMA we want /// The period of the Efficiency Ratio (ER) of KAMA /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The KaufmanAdaptiveMovingAverage indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public KaufmanAdaptiveMovingAverage KAMA(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { return KAMA(symbol, period, 2, 30, resolution, selector); } /// /// Creates a new KaufmanAdaptiveMovingAverage indicator. /// /// The symbol whose KAMA we want /// The period of the Efficiency Ratio (ER) /// The period of the fast EMA used to calculate the Smoothing Constant (SC) /// The period of the slow EMA used to calculate the Smoothing Constant (SC) /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The KaufmanAdaptiveMovingAverage indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public KaufmanAdaptiveMovingAverage KAMA(Symbol symbol, int period, int fastEmaPeriod, int slowEmaPeriod, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"KAMA({period},{fastEmaPeriod},{slowEmaPeriod})", resolution); var kaufmanAdaptiveMovingAverage = new KaufmanAdaptiveMovingAverage(name, period, fastEmaPeriod, slowEmaPeriod); InitializeIndicator(kaufmanAdaptiveMovingAverage, resolution, selector, symbol); return kaufmanAdaptiveMovingAverage; } /// /// Creates an KaufmanEfficiencyRatio indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose EF we want /// The period of the EF /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The KaufmanEfficiencyRatio indicator for the given parameters [DocumentationAttribute(Indicators)] public KaufmanEfficiencyRatio KER(Symbol symbol, int period = 2, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"KER({period})", resolution); var kaufmanEfficiencyRatio = new KaufmanEfficiencyRatio(name, period); InitializeIndicator(kaufmanEfficiencyRatio, resolution, selector, symbol); return kaufmanEfficiencyRatio; } /// /// Creates a new Keltner Channels indicator. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose Keltner Channel we seek /// The period over which to compute the Keltner Channels /// The number of multiples of the from the middle band of the Keltner Channels /// Specifies the type of moving average to be used as the middle line of the Keltner Channel /// The resolution. /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Keltner Channel indicator for the requested symbol. [DocumentationAttribute(Indicators)] public KeltnerChannels KCH(Symbol symbol, int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"KCH({period},{k})", resolution); var keltnerChannels = new KeltnerChannels(name, period, k, movingAverageType); InitializeIndicator(keltnerChannels, resolution, selector, symbol); return keltnerChannels; } /// /// Creates a new KnowSureThing indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose KST we want /// The period over which to compute ROC1 /// The smoothing period used to smooth the computed ROC1 values /// The period over which to compute ROC2 /// The smoothing period used to smooth the computed ROC2 values /// The period over which to compute ROC3 /// The smoothing period used to smooth the computed ROC3 values /// The period over which to compute ROC4 /// The smoothing period used to smooth the computed ROC4 values /// The smoothing period used to smooth the signal values /// Specifies the type of moving average to be used as smoother for KnowSureThing values /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// A new KnowSureThing indicator with the specified smoothing type and period [DocumentationAttribute(Indicators)] public KnowSureThing KST(Symbol symbol, int roc1Period = 10, int roc1MaPeriod = 10, int roc2Period = 15, int roc2MaPeriod = 10, int roc3Period = 20, int roc3MaPeriod = 10, int roc4Period = 30, int roc4MaPeriod = 15, int signalPeriod = 9, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"KST({roc1Period},{roc1MaPeriod},{roc2Period},{roc2MaPeriod},{roc3Period},{roc3MaPeriod},{roc4Period},{roc4MaPeriod},{signalPeriod},{movingAverageType})", resolution); var indicator = new KnowSureThing(name, roc1Period, roc1MaPeriod, roc2Period, roc2MaPeriod, roc3Period, roc3MaPeriod, roc4Period, roc4MaPeriod, signalPeriod, movingAverageType); InitializeIndicator(indicator, resolution, selector, symbol); return indicator; } /// /// Creates a new Klinger Volume Oscillator (KVO) indicator /// /// The symbol whose KVO we want /// The period of the fast EMA used to calculate KVO /// The period of the slow EMA used to calculate KVO, default to 13 /// The period of the signal EMA of the raw KVO value /// The resolution. /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Klinger Volume Oscillator indicator for the requested symbol. [DocumentationAttribute(Indicators)] public KlingerVolumeOscillator KVO(Symbol symbol, int fastPeriod, int slowPeriod, int signalPeriod = 13, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"KVO({fastPeriod},{slowPeriod},{signalPeriod})", resolution); var klingerVolumeOscillator = new KlingerVolumeOscillator(name, fastPeriod, slowPeriod, signalPeriod); InitializeIndicator(klingerVolumeOscillator, resolution, selector, symbol); return klingerVolumeOscillator; } /// /// Creates a new LogReturn indicator. /// /// The symbol whose log return we seek /// The period of the log return. /// The resolution. /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar. /// log return indicator for the requested symbol. [DocumentationAttribute(Indicators)] public LogReturn LOGR(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"LOGR({period})", resolution); var logReturn = new LogReturn(name, period); InitializeIndicator(logReturn, resolution, selector, symbol); return logReturn; } /// /// Creates and registers a new Least Squares Moving Average instance. /// /// The symbol whose LSMA we seek. /// The LSMA period. Normally 14. /// The resolution. /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar. /// A LeastSquaredMovingAverage configured with the specified period [DocumentationAttribute(Indicators)] public LeastSquaresMovingAverage LSMA(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"LSMA({period})", resolution); var leastSquaresMovingAverage = new LeastSquaresMovingAverage(name, period); InitializeIndicator(leastSquaresMovingAverage, resolution, selector, symbol); return leastSquaresMovingAverage; } /// /// Creates a new LinearWeightedMovingAverage indicator. This indicator will linearly distribute /// the weights across the periods. /// /// The symbol whose LWMA we want /// The period over which to compute the LWMA /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// [DocumentationAttribute(Indicators)] public LinearWeightedMovingAverage LWMA(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"LWMA({period})", resolution); var linearWeightedMovingAverage = new LinearWeightedMovingAverage(name, period); InitializeIndicator(linearWeightedMovingAverage, resolution, selector, symbol); return linearWeightedMovingAverage; } /// /// Creates a MACD indicator for the symbol. The indicator will be automatically updated on the given resolution. /// /// The symbol whose MACD we want /// The period for the fast moving average /// The period for the slow moving average /// The period for the signal moving average /// The type of moving average to use for the MACD /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The moving average convergence divergence between the fast and slow averages [DocumentationAttribute(Indicators)] public MovingAverageConvergenceDivergence MACD(Symbol symbol, int fastPeriod, int slowPeriod, int signalPeriod, MovingAverageType type = MovingAverageType.Exponential, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"MACD({fastPeriod},{slowPeriod},{signalPeriod})", resolution); var movingAverageConvergenceDivergence = new MovingAverageConvergenceDivergence(name, fastPeriod, slowPeriod, signalPeriod, type); InitializeIndicator(movingAverageConvergenceDivergence, resolution, selector, symbol); return movingAverageConvergenceDivergence; } /// /// Creates a new MeanAbsoluteDeviation indicator. /// /// The symbol whose MeanAbsoluteDeviation we want /// The period over which to compute the MeanAbsoluteDeviation /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The MeanAbsoluteDeviation indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public MeanAbsoluteDeviation MAD(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"MAD({period})", resolution); var meanAbsoluteDeviation = new MeanAbsoluteDeviation(name, period); InitializeIndicator(meanAbsoluteDeviation, resolution, selector, symbol); return meanAbsoluteDeviation; } /// /// Creates a new Mesa Adaptive Moving Average (MAMA) indicator. /// The MAMA adjusts its smoothing factor based on the market's volatility, making it more adaptive than a simple moving average. /// /// The symbol for which the MAMA indicator is being created. /// The fast limit for the adaptive moving average. /// The slow limit for the adaptive moving average. /// The resolution /// Optional function to select a value from the BaseData. Defaults to casting the input to a TradeBar. /// The Mesa Adaptive Moving Average (MAMA) indicator for the requested symbol with the specified limits. [DocumentationAttribute(Indicators)] public MesaAdaptiveMovingAverage MAMA(Symbol symbol, decimal fastLimit = 0.5m, decimal slowLimit = 0.05m, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"MAMA({fastLimit},{slowLimit})", resolution); var mesaAdaptiveMovingAverage = new MesaAdaptiveMovingAverage(name, fastLimit, slowLimit); InitializeIndicator(mesaAdaptiveMovingAverage, resolution, selector, symbol); return mesaAdaptiveMovingAverage; } /// /// Creates an Market Profile indicator for the symbol with Volume Profile (VOL) mode. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose VP we want /// The period of the VP /// The percentage of volume contained in the value area /// How many digits you want to round and the precision. i.e 0.01 round to two digits exactly. /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Volume Profile indicator for the given parameters [DocumentationAttribute(Indicators)] public VolumeProfile VP(Symbol symbol, int period = 2, decimal valueAreaVolumePercentage = 0.70m, decimal priceRangeRoundOff = 0.05m, Resolution resolution = Resolution.Daily, Func selector = null) { var name = CreateIndicatorName(symbol, $"VP({period})", resolution); var marketProfile = new VolumeProfile(name, period, valueAreaVolumePercentage, priceRangeRoundOff); InitializeIndicator(marketProfile, resolution, selector, symbol); return marketProfile; } /// /// Creates an Market Profile indicator for the symbol with Time Price Opportunity (TPO) mode. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose TP we want /// The period of the TP /// The percentage of volume contained in the value area /// How many digits you want to round and the precision. i.e 0.01 round to two digits exactly. /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Time Profile indicator for the given parameters [DocumentationAttribute(Indicators)] public TimeProfile TP(Symbol symbol, int period = 2, decimal valueAreaVolumePercentage = 0.70m, decimal priceRangeRoundOff = 0.05m, Resolution resolution = Resolution.Daily, Func selector = null) { var name = CreateIndicatorName(symbol, $"TP({period})", resolution); var marketProfile = new TimeProfile(name, period, valueAreaVolumePercentage, priceRangeRoundOff); InitializeIndicator(marketProfile, resolution, selector, symbol); return marketProfile; } /// /// Creates a new Time Series Forecast indicator /// /// The symbol whose TSF we want /// The period of the TSF /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to Value property of BaseData (x => x.Value) /// The TimeSeriesForecast indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public TimeSeriesForecast TSF(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"TSF({period})", resolution); var timeSeriesForecast = new TimeSeriesForecast(name, period); InitializeIndicator(timeSeriesForecast, resolution, selector, symbol); return timeSeriesForecast; } /// /// Creates a new Maximum indicator to compute the maximum value /// /// The symbol whose max we want /// The look back period over which to compute the max value /// The resolution /// 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, /// otherwise it defaults to Value property of BaseData (x => x.Value) /// A Maximum indicator that compute the max value and the periods since the max value [DocumentationAttribute(Indicators)] public Maximum MAX(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"MAX({period})", resolution); var maximum = new Maximum(name, period); // assign a default value for the selector function if (selector == null) { var subscription = GetSubscription(symbol); if (typeof(TradeBar).IsAssignableFrom(subscription.Type)) { // if we have trade bar data we'll use the High property, if not x => x.Value will be set in RegisterIndicator selector = x => ((TradeBar)x).High; } } InitializeIndicator(maximum, resolution, selector, symbol); return maximum; } /// /// Creates a new MoneyFlowIndex indicator. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose MFI we want /// The period over which to compute the MFI /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The MoneyFlowIndex indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public MoneyFlowIndex MFI(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"MFI({period})", resolution); var moneyFlowIndex = new MoneyFlowIndex(name, period); InitializeIndicator(moneyFlowIndex, resolution, selector, symbol); return moneyFlowIndex; } /// /// Creates a new Mass Index indicator. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose Mass Index we want. /// The period used by both EMA. /// The sum period. /// The resolution. /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Mass Index indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public MassIndex MASS(Symbol symbol, int emaPeriod = 9, int sumPeriod = 25, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"MASS({emaPeriod},{sumPeriod})", resolution); var massIndex = new MassIndex(name, emaPeriod, sumPeriod); InitializeIndicator(massIndex, resolution, selector, symbol); return massIndex; } /// /// Creates a new MidPoint indicator. /// /// The symbol whose MIDPOINT we want /// The period over which to compute the MIDPOINT /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The MidPoint indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public MidPoint MIDPOINT(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"MIDPOINT({period})", resolution); var midPoint = new MidPoint(name, period); InitializeIndicator(midPoint, resolution, selector, symbol); return midPoint; } /// /// Creates a new MidPrice indicator. /// /// The symbol whose MIDPRICE we want /// The period over which to compute the MIDPRICE /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The MidPrice indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public MidPrice MIDPRICE(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"MIDPRICE({period})", resolution); var midPrice = new MidPrice(name, period); InitializeIndicator(midPrice, resolution, selector, symbol); return midPrice; } /// /// Creates a new Minimum indicator to compute the minimum value /// /// The symbol whose min we want /// The look back period over which to compute the min value /// The resolution /// 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, /// otherwise it defaults to Value property of BaseData (x => x.Value) /// A Minimum indicator that compute the in value and the periods since the min value [DocumentationAttribute(Indicators)] public Minimum MIN(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"MIN({period})", resolution); var minimum = new Minimum(name, period); // assign a default value for the selector function if (selector == null) { var subscription = GetSubscription(symbol); if (typeof(TradeBar).IsAssignableFrom(subscription.Type)) { // if we have trade bar data we'll use the Low property, if not x => x.Value will be set in RegisterIndicator selector = x => ((TradeBar)x).Low; } } InitializeIndicator(minimum, resolution, selector, symbol); return minimum; } /// /// Creates a new Momentum indicator. This will compute the absolute n-period change in the security. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose momentum we want /// The period over which to compute the momentum /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The momentum indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public Momentum MOM(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"MOM({period})", resolution); var momentum = new Momentum(name, period); InitializeIndicator(momentum, resolution, selector, symbol); return momentum; } /// /// Creates a new Momersion indicator. /// /// The symbol whose Momersion we want /// The minimum period over which to compute the Momersion. Must be greater than 3. If null, only full period will be used in computations. /// The full period over which to compute the Momersion /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The Momersion indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public Momersion MOMERSION(Symbol symbol, int? minPeriod, int fullPeriod, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"MOMERSION({minPeriod},{fullPeriod})", resolution); var momersion = new Momersion(name, minPeriod, fullPeriod); InitializeIndicator(momersion, resolution, selector, symbol); return momersion; } /// /// Creates a new MomentumPercent indicator. This will compute the n-period percent change in the security. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose momentum we want /// The period over which to compute the momentum /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The momentum indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public MomentumPercent MOMP(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"MOMP({period})", resolution); var momentumPercent = new MomentumPercent(name, period); InitializeIndicator(momentumPercent, resolution, selector, symbol); return momentumPercent; } /// /// Creates a new NormalizedAverageTrueRange indicator. /// /// The symbol whose NATR we want /// The period over which to compute the NATR /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The NormalizedAverageTrueRange indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public NormalizedAverageTrueRange NATR(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"NATR({period})", resolution); var normalizedAverageTrueRange = new NormalizedAverageTrueRange(name, period); InitializeIndicator(normalizedAverageTrueRange, resolution, selector, symbol); return normalizedAverageTrueRange; } /// /// Creates a new On Balance Volume indicator. This will compute the cumulative total volume /// based on whether the close price being higher or lower than the previous period. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose On Balance Volume we seek /// The resolution. /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The On Balance Volume indicator for the requested symbol. [DocumentationAttribute(Indicators)] public OnBalanceVolume OBV(Symbol symbol, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, "OBV", resolution); var onBalanceVolume = new OnBalanceVolume(name); InitializeIndicator(onBalanceVolume, resolution, selector, symbol); return onBalanceVolume; } /// /// Creates a new PivotPointsHighLow indicator /// /// The symbol whose PPHL we seek /// 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 /// 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 /// The number of last stored indicator values /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The PivotPointsHighLow indicator for the requested symbol. [DocumentationAttribute(Indicators)] public PivotPointsHighLow PPHL(Symbol symbol, int lengthHigh, int lengthLow, int lastStoredValues = 100, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"PPHL({lengthHigh},{lengthLow})", resolution); var pivotPointsHighLow = new PivotPointsHighLow(name, lengthHigh, lengthLow, lastStoredValues); InitializeIndicator(pivotPointsHighLow, resolution, selector, symbol); return pivotPointsHighLow; } /// /// Creates a new PercentagePriceOscillator indicator. /// /// The symbol whose PPO we want /// The fast moving average period /// The slow moving average period /// The type of moving average to use /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The PercentagePriceOscillator indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public PercentagePriceOscillator PPO(Symbol symbol, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"PPO({fastPeriod},{slowPeriod})", resolution); var percentagePriceOscillator = new PercentagePriceOscillator(name, fastPeriod, slowPeriod, movingAverageType); InitializeIndicator(percentagePriceOscillator, resolution, selector, symbol); return percentagePriceOscillator; } /// /// Creates a new Parabolic SAR indicator /// /// The symbol whose PSAR we seek /// Acceleration factor start value. Normally 0.02 /// Acceleration factor increment value. Normally 0.02 /// Acceleration factor max value. Normally 0.2 /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// A ParabolicStopAndReverse configured with the specified periods [DocumentationAttribute(Indicators)] public ParabolicStopAndReverse PSAR(Symbol symbol, decimal afStart = 0.02m, decimal afIncrement = 0.02m, decimal afMax = 0.2m, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"PSAR({afStart},{afIncrement},{afMax})", resolution); var parabolicStopAndReverse = new ParabolicStopAndReverse(name, afStart, afIncrement, afMax); InitializeIndicator(parabolicStopAndReverse, resolution, selector, symbol); return parabolicStopAndReverse; } /// /// Creates a new RegressionChannel indicator which will compute the LinearRegression, UpperChannel and LowerChannel lines, the intercept and slope /// /// The symbol whose RegressionChannel we seek /// The period of the standard deviation and least square moving average (linear regression line) /// The number of standard deviations specifying the distance between the linear regression and upper or lower channel lines /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// A Regression Channel configured with the specified period and number of standard deviation [DocumentationAttribute(Indicators)] public RegressionChannel RC(Symbol symbol, int period, decimal k, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"RC({period},{k})", resolution); var regressionChannel = new RegressionChannel(name, period, k); InitializeIndicator(regressionChannel, resolution, selector, symbol); return regressionChannel; } /// /// Creates a new Relative Moving Average indicator for the symbol. The indicator will be automatically updated on the given resolution. /// /// The symbol whose relative moving average we seek /// The period of the relative moving average /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// A relative moving average configured with the specified period and number of standard deviation [DocumentationAttribute(Indicators)] public RelativeMovingAverage RMA(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"RMA({period})", resolution); var relativeMovingAverage = new RelativeMovingAverage(name, period); InitializeIndicator(relativeMovingAverage, resolution, selector, symbol); return relativeMovingAverage; } /// /// Creates a new RateOfChange indicator. This will compute the n-period rate of change in the security. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose RateOfChange we want /// The period over which to compute the RateOfChange /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The RateOfChange indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public RateOfChange ROC(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"ROC({period})", resolution); var rateOfChange = new RateOfChange(name, period); InitializeIndicator(rateOfChange, resolution, selector, symbol); return rateOfChange; } /// /// Creates a new RateOfChangePercent indicator. This will compute the n-period percentage rate of change in the security. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose RateOfChangePercent we want /// The period over which to compute the RateOfChangePercent /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The RateOfChangePercent indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public RateOfChangePercent ROCP(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"ROCP({period})", resolution); var rateOfChangePercent = new RateOfChangePercent(name, period); InitializeIndicator(rateOfChangePercent, resolution, selector, symbol); return rateOfChangePercent; } /// /// Creates a new RateOfChangeRatio indicator. /// /// The symbol whose ROCR we want /// The period over which to compute the ROCR /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The RateOfChangeRatio indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public RateOfChangeRatio ROCR(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"ROCR({period})", resolution); var rateOfChangeRatio = new RateOfChangeRatio(name, period); InitializeIndicator(rateOfChangeRatio, resolution, selector, symbol); return rateOfChangeRatio; } /// /// Creates a new RelativeStrengthIndex indicator. This will produce an oscillator that ranges from 0 to 100 based /// on the ratio of average gains to average losses over the specified period. /// /// The symbol whose RSI we want /// The period over which to compute the RSI /// The type of moving average to use in computing the average gain/loss values /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The RelativeStrengthIndex indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public RelativeStrengthIndex RSI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Wilders, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"RSI({period},{movingAverageType})", resolution); var relativeStrengthIndex = new RelativeStrengthIndex(name, period, movingAverageType); InitializeIndicator(relativeStrengthIndex, resolution, selector, symbol); return relativeStrengthIndex; } /// /// Creates a new RelativeVigorIndex indicator. /// /// The symbol whose RVI we want /// The period over which to compute the RVI /// The type of moving average to use /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The RelativeVigorIndex indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public RelativeVigorIndex RVI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"RVI({period},{movingAverageType})", resolution); var relativeVigorIndex = new RelativeVigorIndex(name, period, movingAverageType); InitializeIndicator(relativeVigorIndex, resolution, selector, symbol); return relativeVigorIndex; } /// /// Creates an RelativeDailyVolume indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose RDV we want /// The period of the RDV /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Relative Volume indicator for the given parameters [DocumentationAttribute(Indicators)] public RelativeDailyVolume RDV(Symbol symbol, int period = 2, Resolution resolution = Resolution.Daily, Func selector = null) { var name = CreateIndicatorName(symbol, $"RDV({period})", resolution); var relativeDailyVolume = new RelativeDailyVolume(name, period); RegisterIndicator(symbol, relativeDailyVolume, resolution, selector); return relativeDailyVolume; } /// /// Creates a new Rho indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The option symbol whose values we want as an indicator /// The mirror option for parity calculation /// The risk free rate /// The dividend yield /// The option pricing model used to estimate Rho /// The option pricing model used to estimate IV /// The desired resolution of the data /// A new Rho indicator for the specified symbol [DocumentationAttribute(Indicators)] public Rho R(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null, Resolution? resolution = null) { var name = InitializeOptionIndicator(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution); var rho = new Rho(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel); InitializeOptionIndicator(rho, resolution, symbol, mirrorOption); return rho; } /// /// Creates a new Rho indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The option symbol whose values we want as an indicator /// The mirror option for parity calculation /// The risk free rate /// The dividend yield /// The option pricing model used to estimate Rho /// The option pricing model used to estimate IV /// The desired resolution of the data /// A new Rho indicator for the specified symbol [DocumentationAttribute(Indicators)] public Rho ρ(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes, OptionPricingModelType? ivModel = null, Resolution? resolution = null) { return R(symbol, mirrorOption, riskFreeRate, dividendYield, optionModel, ivModel, resolution); } /// /// Creates a new Stochastic RSI indicator which will compute the %K and %D /// /// The symbol whose Stochastic RSI we seek /// The period of the relative strength index /// The period of the stochastic indicator /// The smoothing period of K output /// The smoothing period of D output /// The type of moving average to be used /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// A StochasticRelativeStrengthIndex configured with the specified periods and moving average type [DocumentationAttribute(Indicators)] public StochasticRelativeStrengthIndex SRSI(Symbol symbol, int rsiPeriod, int stochPeriod, int kSmoothingPeriod, int dSmoothingPeriod, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"SRSI({rsiPeriod},{stochPeriod},{kSmoothingPeriod},{dSmoothingPeriod})", resolution); var indicator = new StochasticRelativeStrengthIndex(name, rsiPeriod, stochPeriod, kSmoothingPeriod, dSmoothingPeriod, movingAverageType); InitializeIndicator(indicator, resolution, selector, symbol); return indicator; } /// /// Creates a new SuperTrend indicator. /// /// The symbol whose SuperTrend indicator we want. /// The smoothing period for average true range. /// Multiplier to calculate basic upper and lower bands width. /// Smoother type for average true range, defaults to Wilders. /// The resolution. /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar [DocumentationAttribute(Indicators)] public SuperTrend STR(Symbol symbol, int period, decimal multiplier, MovingAverageType movingAverageType = MovingAverageType.Wilders, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"STR({period},{multiplier})", resolution); var strend = new SuperTrend(name, period, multiplier, movingAverageType); InitializeIndicator(strend, resolution, selector, symbol); return strend; } /// /// Creates a new SharpeRatio indicator. /// /// The symbol whose RSR we want /// Period of historical observation for sharpe ratio calculation /// /// Risk-free rate for sharpe ratio calculation. If not specified, it will use the algorithms' /// /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The SharpeRatio indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public SharpeRatio SR(Symbol symbol, int sharpePeriod, decimal? riskFreeRate = null, Resolution? resolution = null, Func selector = null) { var baseBame = riskFreeRate.HasValue ? $"SR({sharpePeriod},{riskFreeRate})" : $"SR({sharpePeriod})"; var name = CreateIndicatorName(symbol, baseBame, resolution); IRiskFreeInterestRateModel riskFreeRateModel = riskFreeRate.HasValue ? new ConstantRiskFreeRateInterestRateModel(riskFreeRate.Value) // Make it a function so it's lazily evaluated: SetRiskFreeInterestRateModel can be called after this method : new FuncRiskFreeRateInterestRateModel((datetime) => RiskFreeInterestRateModel.GetInterestRate(datetime)); var sharpeRatio = new SharpeRatio(name, sharpePeriod, riskFreeRateModel); InitializeIndicator(sharpeRatio, resolution, selector, symbol); return sharpeRatio; } /// /// Creates a new Sortino indicator. /// /// The symbol whose Sortino we want /// Period of historical observation for Sortino ratio calculation /// Minimum acceptable return (eg risk-free rate) for the Sortino ratio calculation /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The SortinoRatio indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public SortinoRatio SORTINO(Symbol symbol, int sortinoPeriod, double minimumAcceptableReturn = 0.0, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"SORTINO({sortinoPeriod},{minimumAcceptableReturn})", resolution); var sortinoRatio = new SortinoRatio(name, sortinoPeriod, minimumAcceptableReturn); InitializeIndicator(sortinoRatio, resolution, selector, symbol); return sortinoRatio; } /// /// Creates a new Parabolic SAR Extended indicator /// /// The symbol whose SAREXT we seek /// The starting value for the Stop and Reverse indicator /// The offset value to be applied on reverse /// The starting acceleration factor for short positions /// The increment value for the acceleration factor for short positions /// The maximum value for the acceleration factor for short positions /// The starting acceleration factor for long positions /// The increment value for the acceleration factor for long positions /// The maximum value for the acceleration factor for long positions /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// A ParabolicStopAndReverseExtended configured with the specified periods [DocumentationAttribute(Indicators)] public ParabolicStopAndReverseExtended SAREXT(Symbol symbol, decimal sarStart = 0.0m, decimal offsetOnReverse = 0.0m, decimal afStartShort = 0.02m, decimal afIncrementShort = 0.02m, decimal afMaxShort = 0.2m, decimal afStartLong = 0.02m, decimal afIncrementLong = 0.02m, decimal afMaxLong = 0.2m, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"SAREXT({sarStart},{offsetOnReverse},{afStartShort},{afIncrementShort},{afMaxShort},{afStartLong},{afIncrementLong},{afMaxLong})", resolution); var parabolicStopAndReverseExtended = new ParabolicStopAndReverseExtended(name, sarStart, offsetOnReverse, afStartShort, afIncrementShort, afMaxShort, afStartLong, afIncrementLong, afMaxLong); InitializeIndicator(parabolicStopAndReverseExtended, resolution, selector, symbol); return parabolicStopAndReverseExtended; } /// /// Creates a Squeeze Momentum indicator to identify market squeezes and potential breakouts. /// Compares Bollinger Bands and Keltner Channels to signal low or high volatility periods. /// /// The symbol for which the indicator is calculated. /// The period for Bollinger Bands. /// The multiplier for the Bollinger Bands' standard deviation. /// The period for Keltner Channels. /// The multiplier for the Average True Range in Keltner Channels. /// The resolution of the data. /// Selects a value from the BaseData to send into the indicator. If null, defaults to the Value property of BaseData (x => x.Value). /// The configured Squeeze Momentum indicator. [DocumentationAttribute(Indicators)] public SqueezeMomentum SM(Symbol symbol, int bollingerPeriod = 20, decimal bollingerMultiplier = 2m, int keltnerPeriod = 20, decimal keltnerMultiplier = 1.5m, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"SM({bollingerPeriod}, {bollingerMultiplier}, {keltnerPeriod}, {keltnerMultiplier})", resolution); var squeezeMomentum = new SqueezeMomentum(name, bollingerPeriod, bollingerMultiplier, keltnerPeriod, keltnerMultiplier); InitializeIndicator(squeezeMomentum, resolution, selector, symbol); return squeezeMomentum; } /// /// Creates an SimpleMovingAverage indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose SMA we want /// The period of the SMA /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The SimpleMovingAverage for the given parameters [DocumentationAttribute(Indicators)] public SimpleMovingAverage SMA(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"SMA({period})", resolution); var simpleMovingAverage = new SimpleMovingAverage(name, period); InitializeIndicator(simpleMovingAverage, resolution, selector, symbol); return simpleMovingAverage; } /// /// Creates a new Schaff Trend Cycle indicator /// /// The symbol for the indicator to track /// The fast moving average period /// The slow moving average period /// The signal period /// The type of moving average to use /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The SchaffTrendCycle indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public SchaffTrendCycle STC(Symbol symbol, int cyclePeriod, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType = MovingAverageType.Exponential, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"STC({cyclePeriod},{fastPeriod},{slowPeriod})", resolution); var schaffTrendCycle = new SchaffTrendCycle(name, cyclePeriod, fastPeriod, slowPeriod, movingAverageType); InitializeIndicator(schaffTrendCycle, resolution, selector, symbol); return schaffTrendCycle; } /// /// Creates a new SmoothedOnBalanceVolume indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose SmoothedOnBalanceVolume we want /// The smoothing period used to smooth the computed OnBalanceVolume values /// The type of smoothing to use /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// A new SmoothedOnBalanceVolume indicator with the specified smoothing type and period [DocumentationAttribute(Indicators)] public SmoothedOnBalanceVolume SOBV(Symbol symbol, int period, MovingAverageType type = MovingAverageType.Simple, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"SOBV({period})", resolution); var indicator = new SmoothedOnBalanceVolume(name, period, type); InitializeIndicator(indicator, resolution, selector, symbol); return indicator; } /// /// Creates a new StandardDeviation indicator. This will return the population standard deviation of samples over the specified period. /// /// The symbol whose STD we want /// The period over which to compute the STD /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The StandardDeviation indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public StandardDeviation STD(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"STD({period})", resolution); var standardDeviation = new StandardDeviation(name, period); InitializeIndicator(standardDeviation, resolution, selector, symbol); return standardDeviation; } /// /// Creates a new TargetDownsideDeviation indicator. The target downside deviation is defined as the root-mean-square, or RMS, of the deviations of the /// realized return’s underperformance from the target return where all returns above the target return are treated as underperformance of 0. /// /// The symbol whose TDD we want /// The period over which to compute the TDD /// The resolution /// Minimum acceptable return (MAR) for the target downside deviation calculation /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The TargetDownsideDeviation indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public TargetDownsideDeviation TDD(Symbol symbol, int period, double minimumAcceptableReturn = 0, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"TDD({period},{minimumAcceptableReturn})", resolution); var targetDownsideDeviation = new TargetDownsideDeviation(name, period, minimumAcceptableReturn); InitializeIndicator(targetDownsideDeviation, resolution, selector, symbol); return targetDownsideDeviation; } /// /// Creates a new TomDemark Sequential candlestick indicator for the symbol. The indicator will be automatically /// updated on the symbol's subscription resolution. /// /// The symbol whose TomDemark Sequential we want /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a IBaseDataBar /// The TomDemark Sequential indicator for the requested symbol over the specified period public TomDemarkSequential TDS(Symbol symbol, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, "TDS", resolution); var tdSequential = new TomDemarkSequential(name); InitializeIndicator(tdSequential, resolution, selector, symbol); return tdSequential; } /// /// Creates a new Stochastic indicator. /// /// The symbol whose stochastic we seek /// The period of the stochastic. Normally 14 /// The sum period of the stochastic. Normally 14 /// The sum period of the stochastic. Normally 3 /// The resolution. /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// Stochastic indicator for the requested symbol. [DocumentationAttribute(Indicators)] public Stochastic STO(Symbol symbol, int period, int kPeriod, int dPeriod, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"STO({period},{kPeriod},{dPeriod})", resolution); var stochastic = new Stochastic(name, period, kPeriod, dPeriod); InitializeIndicator(stochastic, resolution, selector, symbol); return stochastic; } /// /// Overload short hand to create a new Stochastic indicator; defaulting to the 3 period for dStoch /// /// The symbol whose stochastic we seek /// The resolution. /// The period of the stochastic. Normally 14 /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// Stochastic indicator for the requested symbol. [DocumentationAttribute(Indicators)] public Stochastic STO(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { return STO(symbol, period, period, 3, resolution, selector); } /// /// Creates a new instance of the Premier Stochastic Oscillator for the specified symbol. /// /// The symbol for which the stochastic indicator is being calculated. /// The period for calculating the Stochastic K value. /// The period for the Exponential Moving Average (EMA) used to smooth the Stochastic K. /// The data resolution (e.g., daily, hourly) for the indicator /// Optional function to select a value from the BaseData. Defaults to casting the input to a TradeBar. /// A PremierStochasticOscillator instance for the specified symbol. [DocumentationAttribute(Indicators)] public PremierStochasticOscillator PSO(Symbol symbol, int period, int emaPeriod, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"PSO({period},{emaPeriod})", resolution); var premierStochasticOscillator = new PremierStochasticOscillator(name, period, emaPeriod); InitializeIndicator(premierStochasticOscillator, resolution, selector, symbol); return premierStochasticOscillator; } /// /// Creates a new Sum indicator. /// /// The symbol whose Sum we want /// The period over which to compute the Sum /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The Sum indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public Sum SUM(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"SUM({period})", resolution); var sum = new Sum(name, period); InitializeIndicator(sum, resolution, selector, symbol); return sum; } /// /// Creates Swiss Army Knife transformation for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol to use for calculations /// The period of the calculation /// The delta scale of the BandStop or BandPass /// The tool os the Swiss Army Knife /// The resolution /// elects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The calculation using the given tool [DocumentationAttribute(Indicators)] public SwissArmyKnife SWISS(Symbol symbol, int period, double delta, SwissArmyKnifeTool tool, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"SWISS({period},{delta},{tool})", resolution); var swissArmyKnife = new SwissArmyKnife(name, period, delta, tool); InitializeIndicator(swissArmyKnife, resolution, selector, symbol); return swissArmyKnife; } /// /// Creates a new Theta indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The option symbol whose values we want as an indicator /// The mirror option for parity calculation /// The risk free rate /// The dividend yield /// The option pricing model used to estimate Theta /// The option pricing model used to estimate IV /// The desired resolution of the data /// A new Theta indicator for the specified symbol [DocumentationAttribute(Indicators)] public Theta T(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null, Resolution? resolution = null) { var name = InitializeOptionIndicator(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution); var theta = new Theta(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel); InitializeOptionIndicator(theta, resolution, symbol, mirrorOption); return theta; } /// /// Creates a new Theta indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The option symbol whose values we want as an indicator /// The mirror option for parity calculation /// The risk free rate /// The dividend yield /// The option pricing model used to estimate Theta /// The option pricing model used to estimate IV /// The desired resolution of the data /// A new Theta indicator for the specified symbol [DocumentationAttribute(Indicators)] public Theta Θ(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType optionModel = OptionPricingModelType.BlackScholes, OptionPricingModelType? ivModel = null, Resolution? resolution = null) { return T(symbol, mirrorOption, riskFreeRate, dividendYield, optionModel, ivModel, resolution); } /// /// Creates a new T3MovingAverage indicator. /// /// The symbol whose T3 we want /// The period over which to compute the T3 /// The volume factor to be used for the T3 (value must be in the [0,1] range, defaults to 0.7) /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The T3MovingAverage indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public T3MovingAverage T3(Symbol symbol, int period, decimal volumeFactor = 0.7m, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"T3({period},{volumeFactor})", resolution); var t3MovingAverage = new T3MovingAverage(name, period, volumeFactor); InitializeIndicator(t3MovingAverage, resolution, selector, symbol); return t3MovingAverage; } /// /// Creates a new TripleExponentialMovingAverage indicator. /// /// The symbol whose TEMA we want /// The period over which to compute the TEMA /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The TripleExponentialMovingAverage indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public TripleExponentialMovingAverage TEMA(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"TEMA({period})", resolution); var tripleExponentialMovingAverage = new TripleExponentialMovingAverage(name, period); InitializeIndicator(tripleExponentialMovingAverage, resolution, selector, symbol); return tripleExponentialMovingAverage; } /// /// Creates a TrueStrengthIndex indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose TSI we want /// Period used for the first price change smoothing /// Period used for the second (double) price change smoothing /// The signal period /// The type of moving average to use for the signal /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The TrueStrengthIndex indicator for the given parameters [DocumentationAttribute(Indicators)] public TrueStrengthIndex TSI(Symbol symbol, int longTermPeriod = 25, int shortTermPeriod = 13, int signalPeriod = 7, MovingAverageType signalType = MovingAverageType.Exponential, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"TSI({longTermPeriod},{shortTermPeriod},{signalPeriod})", resolution); var trueStrengthIndex = new TrueStrengthIndex(name, longTermPeriod, shortTermPeriod, signalPeriod, signalType); InitializeIndicator(trueStrengthIndex, resolution, selector, symbol); return trueStrengthIndex; } /// /// Creates a new TrueRange indicator. /// /// The symbol whose TR we want /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The TrueRange indicator for the requested symbol. [DocumentationAttribute(Indicators)] public TrueRange TR(Symbol symbol, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, "TR", resolution); var trueRange = new TrueRange(name); InitializeIndicator(trueRange, resolution, selector, symbol); return trueRange; } /// /// Creates a new TriangularMovingAverage indicator. /// /// The symbol whose TRIMA we want /// The period over which to compute the TRIMA /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The TriangularMovingAverage indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public TriangularMovingAverage TRIMA(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"TRIMA({period})", resolution); var triangularMovingAverage = new TriangularMovingAverage(name, period); InitializeIndicator(triangularMovingAverage, resolution, selector, symbol); return triangularMovingAverage; } /// /// Creates a new Trix indicator. /// /// The symbol whose TRIX we want /// The period over which to compute the TRIX /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The Trix indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public Trix TRIX(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"TRIX({period})", resolution); var trix = new Trix(name, period); InitializeIndicator(trix, resolution, selector, symbol); return trix; } /// /// Creates a new UltimateOscillator indicator. /// /// The symbol whose ULTOSC we want /// The first period over which to compute the ULTOSC /// The second period over which to compute the ULTOSC /// The third period over which to compute the ULTOSC /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The UltimateOscillator indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public UltimateOscillator ULTOSC(Symbol symbol, int period1, int period2, int period3, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"ULTOSC({period1},{period2},{period3})", resolution); var ultimateOscillator = new UltimateOscillator(name, period1, period2, period3); InitializeIndicator(ultimateOscillator, resolution, selector, symbol); return ultimateOscillator; } /// /// Creates a new Vega indicator for the symbol The indicator will be automatically /// updated on the symbol's subscription resolution /// /// The option symbol whose values we want as an indicator /// The mirror option for parity calculation /// The risk free rate /// The dividend yield /// The option pricing model used to estimate Vega /// The option pricing model used to estimate IV /// The desired resolution of the data /// A new Vega indicator for the specified symbol [DocumentationAttribute(Indicators)] public Vega V(Symbol symbol, Symbol mirrorOption = null, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType? optionModel = null, OptionPricingModelType? ivModel = null, Resolution? resolution = null) { var name = InitializeOptionIndicator(symbol, out var riskFreeRateModel, out var dividendYieldModel, riskFreeRate, dividendYield, optionModel, resolution); var vega = new Vega(name, symbol, riskFreeRateModel, dividendYieldModel, mirrorOption, optionModel, ivModel); InitializeOptionIndicator(vega, resolution, symbol, mirrorOption); return vega; } /// /// Creates a new Chande's Variable Index Dynamic Average indicator. /// /// The symbol whose VIDYA we want /// The period over which to compute the VIDYA /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The VariableIndexDynamicAverage indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public VariableIndexDynamicAverage VIDYA(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"VIDYA({period})", resolution); var variableIndexDynamicAverage = new VariableIndexDynamicAverage(name, period); InitializeIndicator(variableIndexDynamicAverage, resolution, selector, symbol); return variableIndexDynamicAverage; } /// /// Creates a new Variance indicator. This will return the population variance of samples over the specified period. /// /// The symbol whose VAR we want /// The period over which to compute the VAR /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The Variance indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] [Obsolete("'VAR' is obsolete please use 'V' instead")] public Variance VAR(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { return V(symbol, period, resolution, selector); } /// /// Creates a new Variance indicator. This will return the population variance of samples over the specified period. /// /// The symbol whose variance we want /// The period over which to compute the variance /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The Variance indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public Variance V(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"V({period})", resolution); var variance = new Variance(name, period); InitializeIndicator(variance, resolution, selector, symbol); return variance; } /// /// Creates a new ValueAtRisk indicator. /// /// The symbol whose VAR we want /// The period over which to compute the VAR /// The confidence level for Value at risk calculation /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The ValueAtRisk indicator for the requested Symbol, lookback period, and confidence level public ValueAtRisk VAR(Symbol symbol, int period, double confidenceLevel, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"VAR({period},{confidenceLevel})", resolution); var valueAtRisk = new ValueAtRisk(name, period, confidenceLevel); InitializeIndicator(valueAtRisk, resolution, selector, symbol); return valueAtRisk; } /// /// Creates an VolumeWeightedAveragePrice (VWAP) indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose VWAP we want /// The period of the VWAP /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The VolumeWeightedAveragePrice for the given parameters [DocumentationAttribute(Indicators)] public VolumeWeightedAveragePriceIndicator VWAP(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"VWAP({period})", resolution); var volumeWeightedAveragePriceIndicator = new VolumeWeightedAveragePriceIndicator(name, period); InitializeIndicator(volumeWeightedAveragePriceIndicator, resolution, selector, symbol); return volumeWeightedAveragePriceIndicator; } /// /// Creates the canonical VWAP indicator that resets each day. The indicator will be automatically /// updated on the security's configured resolution. /// /// The symbol whose VWAP we want /// The IntradayVWAP for the specified symbol [DocumentationAttribute(Indicators)] public IntradayVwap VWAP(Symbol symbol) { var name = CreateIndicatorName(symbol, "VWAP", null); var intradayVwap = new IntradayVwap(name); RegisterIndicator(symbol, intradayVwap); return intradayVwap; } /// /// Creates a new VolumeWeightedMovingAverage indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose VWMA we want /// The smoothing period used to smooth the computed VWMA values /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// A new VolumeWeightedMovingAverage indicator with the specified smoothing period [DocumentationAttribute(Indicators)] public VolumeWeightedMovingAverage VWMA(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"VWMA({period})", resolution); var indicator = new VolumeWeightedMovingAverage(name, period); InitializeIndicator(indicator, resolution, selector, symbol); return indicator; } /// /// Creates a new Vortex indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose VWMA we want /// The smoothing period used to smooth the computed VWMA values /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// A new Vortex indicator with the specified smoothing period [DocumentationAttribute(Indicators)] public Vortex VTX(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"VTX({period})", resolution); var indicator = new Vortex(name, period); InitializeIndicator(indicator, resolution, selector, symbol); return indicator; } /// /// Creates a new Williams %R indicator. This will compute the percentage change of /// the current closing price in relation to the high and low of the past N periods. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose Williams %R we want /// The period over which to compute the Williams %R /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Williams %R indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public WilliamsPercentR WILR(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"WILR({period})", resolution); var williamsPercentR = new WilliamsPercentR(name, period); InitializeIndicator(williamsPercentR, resolution, selector, symbol); return williamsPercentR; } /// /// Creates a WilderMovingAverage indicator for the symbol. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose WMA we want /// The period of the WMA /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The WilderMovingAverage for the given parameters /// WWMA for Welles Wilder Moving Average [DocumentationAttribute(Indicators)] public WilderMovingAverage WWMA(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"WWMA({period})", resolution); var wilderMovingAverage = new WilderMovingAverage(name, period); InitializeIndicator(wilderMovingAverage, resolution, selector, symbol); return wilderMovingAverage; } /// /// Creates a Wilder Swing Index (SI) indicator for the symbol. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose SI we want /// The maximum daily change in price for the SI /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The WilderSwingIndex for the given parameters /// SI for Wilder Swing Index [DocumentationAttribute(Indicators)] public WilderSwingIndex SI(Symbol symbol, decimal limitMove, Resolution? resolution = Resolution.Daily, Func selector = null) { var name = CreateIndicatorName(symbol, "SI", resolution); var si = new WilderSwingIndex(name, limitMove); InitializeIndicator(si, resolution, selector, symbol); return si; } /// /// Creates a Wilder Accumulative Swing Index (ASI) indicator for the symbol. /// The indicator will be automatically updated on the given resolution. /// /// The symbol whose ASI we want /// The maximum daily change in price for the ASI /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The WilderAccumulativeSwingIndex for the given parameters /// ASI for Wilder Accumulative Swing Index [DocumentationAttribute(Indicators)] public WilderAccumulativeSwingIndex ASI(Symbol symbol, decimal limitMove, Resolution? resolution = Resolution.Daily, Func selector = null) { var name = CreateIndicatorName(symbol, "ASI", resolution); var asi = new WilderAccumulativeSwingIndex(name, limitMove); InitializeIndicator(asi, resolution, selector, symbol); return asi; } /// /// Creates a new Arms Index indicator /// /// The symbols whose Arms Index we want /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Arms Index indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public ArmsIndex TRIN(IEnumerable symbols, Resolution? resolution = null, Func selector = null) { return TRIN(symbols.ToArray(), resolution, selector); } /// /// Creates a new Arms Index indicator /// /// The symbols whose Arms Index we want /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Arms Index indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public ArmsIndex TRIN(Symbol[] symbols, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(QuantConnect.Symbol.None, "TRIN", resolution ?? GetSubscription(symbols.First()).Resolution); var trin = new ArmsIndex(name); foreach (var symbol in symbols) { trin.Add(symbol); } InitializeIndicator(trin, resolution, selector, symbols); return trin; } /// /// Creates a new Advance/Decline Ratio indicator /// /// The symbols whose A/D Ratio we want /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Advance/Decline Ratio indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public AdvanceDeclineRatio ADR(IEnumerable symbols, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(QuantConnect.Symbol.None, "A/D Ratio", resolution ?? GetSubscription(symbols.First()).Resolution); var adr = new AdvanceDeclineRatio(name); foreach (var symbol in symbols) { adr.Add(symbol); } InitializeIndicator(adr, resolution, selector, symbols.ToArray()); return adr; } /// /// Creates a new Advance/Decline Volume Ratio indicator /// /// The symbol whose A/D Volume Rate we want /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Advance/Decline Volume Ratio indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public AdvanceDeclineVolumeRatio ADVR(IEnumerable symbols, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(QuantConnect.Symbol.None, "A/D Volume Rate", resolution ?? GetSubscription(symbols.First()).Resolution); var advr = new AdvanceDeclineVolumeRatio(name); foreach (var symbol in symbols) { advr.Add(symbol); } InitializeIndicator(advr, resolution, selector, symbols.ToArray()); return advr; } /// /// Creates a new Advance/Decline Difference indicator /// /// The symbols whose A/D Difference we want /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The Advance/Decline Difference indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public AdvanceDeclineDifference ADDIFF(IEnumerable symbols, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(QuantConnect.Symbol.None, "A/D Difference", resolution ?? GetSubscription(symbols.First()).Resolution); var adDiff = new AdvanceDeclineDifference(name); foreach (var symbol in symbols) { adDiff.Add(symbol); } InitializeIndicator(adDiff, resolution, selector, symbols.ToArray()); return adDiff; } /// /// Creates a new McGinley Dynamic indicator /// /// The symbol whose McGinley Dynamic indicator value we want /// The period of the McGinley Dynamic indicator /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The McGinley Dynamic indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public McGinleyDynamic MGD(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"MGD({period})", resolution); var indicator = new McGinleyDynamic(name, period); InitializeIndicator(indicator, resolution, selector, symbol); return indicator; } /// /// Creates a new McClellan Oscillator indicator /// /// The symbols whose McClellan Oscillator we want /// Fast period EMA of advance decline difference /// Slow period EMA of advance decline difference /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The McClellan Oscillator indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public McClellanOscillator MOSC(IEnumerable symbols, int fastPeriod = 19, int slowPeriod = 39, Resolution? resolution = null, Func selector = null) { return MOSC(symbols.ToArray(), fastPeriod, slowPeriod, resolution, selector); } /// /// Creates a new McClellan Oscillator indicator /// /// The symbols whose McClellan Oscillator we want /// Fast period EMA of advance decline difference /// Slow period EMA of advance decline difference /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The McClellan Oscillator indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public McClellanOscillator MOSC(Symbol[] symbols, int fastPeriod = 19, int slowPeriod = 39, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(QuantConnect.Symbol.None, $"MO({fastPeriod},{slowPeriod})", resolution ?? GetSubscription(symbols.First()).Resolution); var mosc = new McClellanOscillator(name, fastPeriod, slowPeriod); foreach (var symbol in symbols) { mosc.Add(symbol); } InitializeIndicator(mosc, resolution, selector, symbols); return mosc; } /// /// Creates a new McClellan Summation Index indicator /// /// The symbols whose McClellan Summation Index we want /// Fast period EMA of advance decline difference /// Slow period EMA of advance decline difference /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The McClellan Summation Index indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public McClellanSummationIndex MSI(IEnumerable symbols, int fastPeriod = 19, int slowPeriod = 39, Resolution? resolution = null, Func selector = null) { return MSI(symbols.ToArray(), fastPeriod, slowPeriod, resolution, selector); } /// /// Creates a new McClellan Summation Index indicator /// /// The symbols whose McClellan Summation Index we want /// Fast period EMA of advance decline difference /// Slow period EMA of advance decline difference /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// The McClellan Summation Index indicator for the requested symbol over the specified period [DocumentationAttribute(Indicators)] public McClellanSummationIndex MSI(Symbol[] symbols, int fastPeriod = 19, int slowPeriod = 39, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(QuantConnect.Symbol.None, $"MSI({fastPeriod},{slowPeriod})", resolution ?? GetSubscription(symbols.First()).Resolution); var msi = new McClellanSummationIndex(name, fastPeriod, slowPeriod); foreach (var symbol in symbols) { msi.Add(symbol); } InitializeIndicator(msi, resolution, selector, symbols); return msi; } /// /// Creates a new RogersSatchellVolatility indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose RogersSatchellVolatility we want /// The period of the rolling window used to compute volatility /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar /// A new RogersSatchellVolatility indicator with the specified smoothing type and period [DocumentationAttribute(Indicators)] public RogersSatchellVolatility RSV(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"RSV({period})", resolution); var indicator = new RogersSatchellVolatility(name, period); InitializeIndicator(indicator, resolution, selector, symbol); return indicator; } /// /// Creates a ZeroLagExponentialMovingAverage indicator for the symbol. The indicator will be automatically /// updated on the given resolution. /// /// The symbol whose ZLEMA we want /// The period of the ZLEMA /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The ZeroLagExponentialMovingAverage for the given parameters [DocumentationAttribute(Indicators)] public ZeroLagExponentialMovingAverage ZLEMA(Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"ZLEMA({period})", resolution); var zeroLagExponentialMovingAverage = new ZeroLagExponentialMovingAverage(name, period); InitializeIndicator(zeroLagExponentialMovingAverage, resolution, selector, symbol); return zeroLagExponentialMovingAverage; } /// /// Creates a ZigZag indicator for the specified symbol, with adjustable sensitivity and minimum trend length. /// /// The symbol for which to create the ZigZag indicator. /// The sensitivity for detecting pivots. /// The minimum number of bars required for a trend before a pivot is confirmed. /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// The configured ZigZag indicator. [DocumentationAttribute(Indicators)] public ZigZag ZZ(Symbol symbol, decimal sensitivity = 0.05m, int minTrendLength = 1, Resolution? resolution = null, Func selector = null) { var name = CreateIndicatorName(symbol, $"ZZ({sensitivity},{minTrendLength})", resolution); var zigZag = new ZigZag(name, sensitivity, minTrendLength); InitializeIndicator(zigZag, resolution, selector, symbol); return zigZag; } /// /// Creates a new name for an indicator created with the convenience functions (SMA, EMA, ect...) /// /// The symbol this indicator is registered to /// The indicator type, for example, 'SMA(5)' /// The resolution requested /// A unique for the given parameters [DocumentationAttribute(Indicators)] public string CreateIndicatorName(Symbol symbol, FormattableString type, Resolution? resolution) { return CreateIndicatorName(symbol, Invariant(type), resolution); } /// /// Creates a new name for an indicator created with the convenience functions (SMA, EMA, ect...) /// /// The symbol this indicator is registered to /// The indicator type, for example, 'SMA(5)' /// The resolution requested /// A unique for the given parameters [DocumentationAttribute(Indicators)] public string CreateIndicatorName(Symbol symbol, string type, Resolution? resolution) { var symbolIsNotEmpty = symbol != QuantConnect.Symbol.None && symbol != QuantConnect.Symbol.Empty; if (!resolution.HasValue && symbolIsNotEmpty) { resolution = GetSubscription(symbol).Resolution; } var res = string.Empty; switch (resolution) { case Resolution.Tick: res = "tick"; break; case Resolution.Second: res = "sec"; break; case Resolution.Minute: res = "min"; break; case Resolution.Hour: res = "hr"; break; case Resolution.Daily: res = "day"; break; case null: break; default: throw new ArgumentOutOfRangeException(nameof(resolution), resolution, "resolution parameter is out of range."); } var parts = new List(); if (symbolIsNotEmpty) { parts.Add(symbol.ToString()); } parts.Add(res); return Invariant($"{type}({string.Join("_", parts)})").Replace(")(", ","); } /// /// Gets the SubscriptionDataConfig for the specified symbol and tick type /// /// Thrown if no configuration is found for the requested symbol /// The symbol to retrieve configuration for /// The tick type of the subscription to get. If null, will use the first ordered by TickType /// The SubscriptionDataConfig for the specified symbol private SubscriptionDataConfig GetSubscription(Symbol symbol, TickType? tickType = null) { SubscriptionDataConfig subscription; try { // deterministic ordering is required here var subscriptions = SubscriptionManager.SubscriptionDataConfigService .GetSubscriptionDataConfigs(symbol) // make sure common lean data types are at the bottom .OrderByDescending(x => LeanData.IsCommonLeanDataType(x.Type)) .ThenBy(x => x.TickType) .ToList(); // find our subscription subscription = subscriptions.FirstOrDefault(x => tickType == null || tickType == x.TickType); if (subscription == null) { // if we can't locate the exact subscription by tick type just grab the first one we find subscription = subscriptions.First(); } } catch (InvalidOperationException) { // this will happen if we did not find the subscription, let's give the user a decent error message throw new Exception($"Please register to receive data for symbol \'{symbol}\' using the AddSecurity() function."); } return subscription; } /// /// Creates and registers a new consolidator to receive automatic updates at the specified resolution as well as configures /// the indicator to receive updates from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The resolution at which to send data to the indicator, null to use the same resolution as the subscription /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) [DocumentationAttribute(ConsolidatingData)] [DocumentationAttribute(Indicators)] public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, Resolution? resolution = null, Func selector = null) { RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution), selector ?? (x => x.Value)); } /// /// Creates and registers a new consolidator to receive automatic updates at the specified resolution as well as configures /// the indicator to receive updates from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The resolution at which to send data to the indicator, null to use the same resolution as the subscription /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) [DocumentationAttribute(ConsolidatingData)] [DocumentationAttribute(Indicators)] public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, TimeSpan? resolution = null, Func selector = null) { RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution), selector ?? (x => x.Value)); } /// /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates /// from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The consolidator to receive raw subscription data /// Selects a value from the BaseData send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) [DocumentationAttribute(ConsolidatingData)] [DocumentationAttribute(Indicators)] public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, IDataConsolidator consolidator, Func selector = null) { // default our selector to the Value property on BaseData selector = selector ?? (x => x.Value); RegisterConsolidator(symbol, consolidator, null, indicator); // attach to the DataConsolidated event so it updates our indicator consolidator.DataConsolidated += (sender, consolidated) => { var value = selector(consolidated); indicator.Update(new IndicatorDataPoint(consolidated.Symbol, consolidated.EndTime, value)); }; } /// /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates /// from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The resolution at which to send data to the indicator, null to use the same resolution as the subscription [DocumentationAttribute(ConsolidatingData)] [DocumentationAttribute(Indicators)] public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, Resolution? resolution = null) where T : IBaseData { RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution, typeof(T))); } /// /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates /// from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The resolution at which to send data to the indicator, null to use the same resolution as the subscription /// Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x) [DocumentationAttribute(ConsolidatingData)] [DocumentationAttribute(Indicators)] public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, Resolution? resolution, Func selector) where T : IBaseData { RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution, typeof(T)), selector); } /// /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates /// from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The resolution at which to send data to the indicator, null to use the same resolution as the subscription /// Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x) [DocumentationAttribute(ConsolidatingData)] [DocumentationAttribute(Indicators)] public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, TimeSpan? resolution, Func selector = null) where T : IBaseData { RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution, typeof(T)), selector); } /// /// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates /// from the consolidator. /// /// The symbol to register against /// The indicator to receive data from the consolidator /// The consolidator to receive raw subscription data /// Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x) [DocumentationAttribute(ConsolidatingData)] [DocumentationAttribute(Indicators)] public void RegisterIndicator(Symbol symbol, IndicatorBase indicator, IDataConsolidator consolidator, Func selector = null) where T : IBaseData { // assign default using cast var selectorToUse = selector ?? (x => (T)x); RegisterConsolidator(symbol, consolidator, null, indicator); // check the output type of the consolidator and verify we can assign it to T var type = typeof(T); if (!type.IsAssignableFrom(consolidator.OutputType)) { if (type == typeof(IndicatorDataPoint) && selector == null) { // if no selector was provided and the indicator input is of 'IndicatorDataPoint', common case, a selector with a direct cast will fail // so we use a smarter selector as in other API methods selectorToUse = consolidated => (T)(object)new IndicatorDataPoint(consolidated.Symbol, consolidated.EndTime, consolidated.Value); } else { throw new ArgumentException($"Type mismatch found between consolidator and indicator for symbol: {symbol}." + $"Consolidator outputs type {consolidator.OutputType.Name} but indicator expects input type {type.Name}" ); } } // attach to the DataConsolidated event so it updates our indicator consolidator.DataConsolidated += (sender, consolidated) => { var value = selectorToUse(consolidated); indicator.Update(value); }; } /// /// Will unregister an indicator and it's associated consolidator instance so they stop receiving data updates /// /// The indicator instance to unregister [DocumentationAttribute(ConsolidatingData)] [DocumentationAttribute(Indicators)] public void UnregisterIndicator(IndicatorBase indicator) { DeregisterIndicator(indicator); } /// /// Will deregister an indicator and it's associated consolidator instance so they stop receiving data updates /// /// The indicator instance to deregister [DocumentationAttribute(ConsolidatingData)] [DocumentationAttribute(Indicators)] public void DeregisterIndicator(IndicatorBase indicator) { foreach (var consolidator in indicator.Consolidators) { SubscriptionManager.RemoveConsolidator(null, consolidator); } indicator.Consolidators.Clear(); } /// /// Warms up a given indicator with historical data /// /// The symbol whose indicator we want /// The indicator we want to warm up /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) [DocumentationAttribute(HistoricalData)] [DocumentationAttribute(Indicators)] public void WarmUpIndicator(Symbol symbol, IndicatorBase indicator, Resolution? resolution = null, Func selector = null) { WarmUpIndicator(new[] { symbol }, indicator, resolution, selector); } /// /// Warms up a given indicator with historical data /// /// The symbols whose indicator we want /// The indicator we want to warm up /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) [DocumentationAttribute(HistoricalData)] [DocumentationAttribute(Indicators)] public void WarmUpIndicator(IEnumerable symbols, IndicatorBase indicator, Resolution? resolution = null, Func selector = null) { if (AssertIndicatorHasWarmupPeriod(indicator)) { IndicatorHistory(indicator, symbols, 0, resolution, selector); } } /// /// Warms up a given indicator with historical data /// /// The symbol whose indicator we want /// The indicator we want to warm up /// The necessary period to warm up the indicator /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) [DocumentationAttribute(HistoricalData)] [DocumentationAttribute(Indicators)] public void WarmUpIndicator(Symbol symbol, IndicatorBase indicator, TimeSpan period, Func selector = null) { WarmUpIndicator([symbol], indicator, period, selector); } /// /// Warms up a given indicator with historical data /// /// The symbols whose indicator we want /// The indicator we want to warm up /// The necessary period to warm up the indicator /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) [DocumentationAttribute(HistoricalData)] [DocumentationAttribute(Indicators)] public void WarmUpIndicator(IEnumerable symbols, IndicatorBase indicator, TimeSpan period, Func selector = null) { var history = GetIndicatorWarmUpHistory(symbols, indicator, period, out var identityConsolidator); if (history == Enumerable.Empty()) return; // assign default using cast selector ??= (x => x.Value); Action onDataConsolidated = bar => { var input = new IndicatorDataPoint(bar.Symbol, bar.EndTime, selector(bar)); indicator.Update(input); }; WarmUpIndicatorImpl(symbols, period, onDataConsolidated, history, identityConsolidator); } /// /// Warms up a given indicator with historical data /// /// The symbol whose indicator we want /// The indicator we want to warm up /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) [DocumentationAttribute(HistoricalData)] [DocumentationAttribute(Indicators)] public void WarmUpIndicator(Symbol symbol, IndicatorBase indicator, Resolution? resolution = null, Func selector = null) where T : class, IBaseData { WarmUpIndicator(new[] { symbol }, indicator, resolution, selector); } /// /// Warms up a given indicator with historical data /// /// The symbols whose indicator we want /// The indicator we want to warm up /// The resolution /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) [DocumentationAttribute(HistoricalData)] [DocumentationAttribute(Indicators)] public void WarmUpIndicator(IEnumerable symbols, IndicatorBase indicator, Resolution? resolution = null, Func selector = null) where T : class, IBaseData { if (AssertIndicatorHasWarmupPeriod(indicator)) { IndicatorHistory(indicator, symbols, 0, resolution, selector); } } /// /// Warms up a given indicator with historical data /// /// The symbols whose indicator we want /// The indicator we want to warm up /// The necessary period to warm up the indicator /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) [DocumentationAttribute(HistoricalData)] [DocumentationAttribute(Indicators)] public void WarmUpIndicator(IEnumerable symbols, IndicatorBase indicator, TimeSpan period, Func selector = null) where T : class, IBaseData { var history = GetIndicatorWarmUpHistory(symbols, indicator, period, out var identityConsolidator); if (history == Enumerable.Empty()) return; // assign default selector selector ??= GetDefaultSelector(); // we expect T type as input Action onDataConsolidated = bar => { indicator.Update(selector(bar)); }; WarmUpIndicatorImpl(symbols, period, onDataConsolidated, history, identityConsolidator); } /// /// Warms up a given indicator with historical data /// /// The symbol whose indicator we want /// The indicator we want to warm up /// The necessary period to warm up the indicator /// Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x) [DocumentationAttribute(HistoricalData)] [DocumentationAttribute(Indicators)] public void WarmUpIndicator(Symbol symbol, IndicatorBase indicator, TimeSpan period, Func selector = null) where T : class, IBaseData { WarmUpIndicator([symbol], indicator, period, selector); } private Func GetDefaultSelector() where T : IBaseData { if (typeof(T) == typeof(IndicatorDataPoint)) { return x => { if (!(x is IndicatorDataPoint)) { return (T)(object)new IndicatorDataPoint(x.Symbol, x.EndTime, x.Price); } return (T)x; }; } return x => (T)x; } private IEnumerable GetIndicatorWarmUpHistory(IEnumerable symbols, IIndicator indicator, TimeSpan timeSpan, out bool identityConsolidator) { identityConsolidator = false; if (!AssertIndicatorHasWarmupPeriod(indicator)) { return Enumerable.Empty(); } var periods = ((IIndicatorWarmUpPeriodProvider)indicator).WarmUpPeriod; if (periods != 0) { var resolution = timeSpan.ToHigherResolutionEquivalent(false); // if they are the same, means we can use an identity consolidator identityConsolidator = resolution.ToTimeSpan() == timeSpan; var resolutionTicks = resolution.ToTimeSpan().Ticks; if (resolutionTicks != 0) { periods *= (int)(timeSpan.Ticks / resolutionTicks); } try { return History(symbols, periods, resolution, dataNormalizationMode: GetIndicatorHistoryDataNormalizationMode(indicator)); } catch (ArgumentException e) { Debug($"{indicator.Name} could not be warmed up. Reason: {e.Message}"); } } return Enumerable.Empty(); } private bool AssertIndicatorHasWarmupPeriod(IIndicator indicator) { if (indicator is not IIndicatorWarmUpPeriodProvider) { if (!_isEmitWarmupInsightWarningSent) { Debug($"Warning: the 'WarmUpIndicator' feature only works with indicators which inherit from '{nameof(IIndicatorWarmUpPeriodProvider)}'" + $" and define a warm up period, setting property 'WarmUpPeriod' with a value > 0." + $" The provided indicator of type '{indicator.GetType().Name}' will not be warmed up."); _isEmitWarmupInsightWarningSent = true; } return false; } return true; } private void WarmUpIndicatorImpl(IEnumerable symbols, TimeSpan period, Action handler, IEnumerable history, bool identityConsolidator) where T : class, IBaseData { var consolidators = symbols.ToDictionary(symbol => symbol, symbol => { IDataConsolidator consolidator; if (SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(symbol).Count > 0) { consolidator = Consolidate(symbol, period, handler); } else { if (identityConsolidator) { period = TimeSpan.Zero; } var providedType = typeof(T); if (providedType.IsAbstract) { var dataType = SubscriptionManager.LookupSubscriptionConfigDataTypes( symbol.SecurityType, Resolution.Daily, // order by tick type so that behavior is consistent with 'GetSubscription()' symbol.IsCanonical()) // make sure common lean data types are at the bottom .OrderByDescending(tuple => LeanData.IsCommonLeanDataType(tuple.Item1)) .ThenBy(tuple => tuple.Item2).First(); consolidator = CreateConsolidator(period, dataType.Item1, dataType.Item2); } else { // if the 'providedType' is not abstract we use it instead to determine which consolidator to use var tickType = LeanData.GetCommonTickTypeForCommonDataTypes(providedType, symbol.SecurityType); consolidator = CreateConsolidator(period, providedType, tickType); } consolidator.DataConsolidated += (s, bar) => handler((T)bar); } return consolidator; }); foreach (var slice in history) { foreach (var (symbol, consolidator) in consolidators) { var consolidatorInputType = consolidator.InputType; if (slice.TryGet(consolidatorInputType, symbol, out var data)) { consolidator.Update(data); } } } // Scan for time after we've pumped all the data through for this consolidator foreach (var (symbol, consolidator) in consolidators) { if (consolidator.WorkingData != null) { DateTime currentTime; if (Securities.TryGetValue(symbol, out var security)) { currentTime = security.LocalTime; } else { var exchangeHours = MarketHoursDatabase.GetExchangeHours(symbol.ID.Market, symbol, symbol.SecurityType); currentTime = UtcTime.ConvertFromUtc(exchangeHours.TimeZone); } consolidator.Scan(currentTime); } SubscriptionManager.RemoveConsolidator(symbol, consolidator); } } /// /// Gets the default consolidator for the specified symbol and resolution /// /// The symbol whose data is to be consolidated /// The resolution for the consolidator, if null, uses the resolution from subscription /// The data type for this consolidator, if null, uses TradeBar over QuoteBar if present /// The new default consolidator [DocumentationAttribute(ConsolidatingData)] [DocumentationAttribute(Indicators)] public IDataConsolidator ResolveConsolidator(Symbol symbol, Resolution? resolution, Type dataType = null) { var tickType = dataType != null ? LeanData.GetCommonTickTypeForCommonDataTypes(dataType, symbol.SecurityType) : (TickType?)null; return CreateConsolidator(symbol, null, tickType, null, resolution, null); } /// /// Gets the default consolidator for the specified symbol and resolution /// /// The symbol whose data is to be consolidated /// The requested time span for the consolidator, if null, uses the resolution from subscription /// The data type for this consolidator, if null, uses TradeBar over QuoteBar if present /// The new default consolidator [DocumentationAttribute(ConsolidatingData)] [DocumentationAttribute(Indicators)] public IDataConsolidator ResolveConsolidator(Symbol symbol, TimeSpan? timeSpan, Type dataType = null) { var tickType = dataType != null ? LeanData.GetCommonTickTypeForCommonDataTypes(dataType, symbol.SecurityType) : (TickType?)null; return CreateConsolidator(symbol, null, tickType, timeSpan, null, null); } /// /// Creates a new consolidator for the specified period, generating the requested output type. /// /// The consolidation period /// The desired input type of the consolidator, such as TradeBar or QuoteBar /// Trade or Quote. Optional, defaults to trade /// A new consolidator matching the requested parameters [DocumentationAttribute(ConsolidatingData)] public static IDataConsolidator CreateConsolidator(TimeSpan period, Type consolidatorInputType, TickType? tickType = null) { if (period.Ticks == 0) { return CreateIdentityConsolidator(consolidatorInputType); } // if our type can be used as a trade bar, then let's just make one of those // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to TradeBar if (typeof(TradeBar).IsAssignableFrom(consolidatorInputType)) { return new TradeBarConsolidator(period); } // if our type can be used as a quote bar, then let's just make one of those // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to QuoteBar if (typeof(QuoteBar).IsAssignableFrom(consolidatorInputType)) { return new QuoteBarConsolidator(period); } // if our type can be used as a tick then we'll use a consolidator that keeps the TickType // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to Tick if (typeof(Tick).IsAssignableFrom(consolidatorInputType)) { switch (tickType) { case TickType.OpenInterest: return new OpenInterestConsolidator(period); case TickType.Quote: return new TickQuoteBarConsolidator(period); default: return new TickConsolidator(period); } } // if our type can be used as a DynamicData then we'll use the DynamicDataConsolidator if (typeof(DynamicData).IsAssignableFrom(consolidatorInputType)) { return new DynamicDataConsolidator(period); } // no matter what we can always consolidate based on the time-value pair of BaseData return new BaseDataConsolidator(period); } /// /// Registers the to receive consolidated data for the specified symbol /// /// The symbol who's data is to be consolidated /// The consolidation period /// Data handler receives new consolidated data when generated /// A new consolidator matching the requested parameters with the handler already registered [DocumentationAttribute(ConsolidatingData)] public IDataConsolidator Consolidate(Symbol symbol, Resolution period, Action handler) { return Consolidate(symbol, period, TickType.Trade, handler); } /// /// Registers the to receive consolidated data for the specified symbol /// /// The symbol who's data is to be consolidated /// The consolidation period /// Data handler receives new consolidated data when generated /// A new consolidator matching the requested parameters with the handler already registered [DocumentationAttribute(ConsolidatingData)] public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, Action handler) { return Consolidate(symbol, period, TickType.Trade, handler); } /// /// Registers the to receive consolidated data for the specified symbol /// /// The symbol who's data is to be consolidated /// The consolidation period /// Data handler receives new consolidated data when generated /// A new consolidator matching the requested parameters with the handler already registered [DocumentationAttribute(ConsolidatingData)] public IDataConsolidator Consolidate(Symbol symbol, Resolution period, Action handler) { return Consolidate(symbol, period.ToTimeSpan(), TickType.Quote, handler); } /// /// Registers the to receive consolidated data for the specified symbol /// /// The symbol who's data is to be consolidated /// The consolidation period /// Data handler receives new consolidated data when generated /// A new consolidator matching the requested parameters with the handler already registered [DocumentationAttribute(ConsolidatingData)] public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, Action handler) { return Consolidate(symbol, period, TickType.Quote, handler); } /// /// Registers the to receive consolidated data for the specified symbol and tick type. /// The handler and tick type must match. /// /// The symbol who's data is to be consolidated /// The consolidation period /// Data handler receives new consolidated data when generated /// A new consolidator matching the requested parameters with the handler already registered [DocumentationAttribute(ConsolidatingData)] public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, Action handler) where T : class, IBaseData { // 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 // decision here (default type), it will be taken later by 'GetSubscription' so we keep it centralized // This could happen when a user passes in a generic 'Action' handler var tickType = typeof(T).IsAbstract ? (TickType?)null : LeanData.GetCommonTickTypeForCommonDataTypes(typeof(T), symbol.SecurityType); return Consolidate(symbol, period, tickType, handler); } /// /// Registers the to receive consolidated data for the specified symbol and tick type. /// The handler and tick type must match. /// /// The symbol who's data is to be consolidated /// The consolidation period /// The tick type of subscription used as data source for consolidator. Specify null to use first subscription found. /// Data handler receives new consolidated data when generated /// A new consolidator matching the requested parameters with the handler already registered [DocumentationAttribute(ConsolidatingData)] public IDataConsolidator Consolidate(Symbol symbol, Resolution period, TickType? tickType, Action handler) where T : class, IBaseData { return Consolidate(symbol, null, tickType, handler, null, period); } /// /// Registers the to receive consolidated data for the specified symbol and tick type. /// The handler and tick type must match. /// /// The symbol who's data is to be consolidated /// The consolidation period /// The tick type of subscription used as data source for consolidator. Specify null to use first subscription found. /// Data handler receives new consolidated data when generated /// A new consolidator matching the requested parameters with the handler already registered [DocumentationAttribute(ConsolidatingData)] public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, TickType? tickType, Action handler) where T : class, IBaseData { return Consolidate(symbol, null, tickType, handler, period, null); } /// /// Registers the to receive consolidated data for the specified symbol /// /// The symbol who's data is to be consolidated /// The consolidation calendar /// Data handler receives new consolidated data when generated /// A new consolidator matching the requested parameters with the handler already registered [DocumentationAttribute(ConsolidatingData)] public IDataConsolidator Consolidate(Symbol symbol, Func calendar, Action handler) { return Consolidate(symbol, calendar, TickType.Quote, handler); } /// /// Registers the to receive consolidated data for the specified symbol /// /// The symbol who's data is to be consolidated /// The consolidation calendar /// Data handler receives new consolidated data when generated /// A new consolidator matching the requested parameters with the handler already registered [DocumentationAttribute(ConsolidatingData)] public IDataConsolidator Consolidate(Symbol symbol, Func calendar, Action handler) { return Consolidate(symbol, calendar, TickType.Trade, handler); } /// /// Registers the to receive consolidated data for the specified symbol and tick type. /// The handler and tick type must match. /// /// The symbol who's data is to be consolidated /// The consolidation calendar /// Data handler receives new consolidated data when generated /// A new consolidator matching the requested parameters with the handler already registered [DocumentationAttribute(ConsolidatingData)] public IDataConsolidator Consolidate(Symbol symbol, Func calendar, Action handler) where T : class, IBaseData { // 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 // decision here (default type), it will be taken later by 'GetSubscription' so we keep it centralized // This could happen when a user passes in a generic 'Action' handler var tickType = typeof(T).IsAbstract ? (TickType?)null : LeanData.GetCommonTickTypeForCommonDataTypes(typeof(T), symbol.SecurityType); return Consolidate(symbol, calendar, tickType, handler); } /// /// Registers the to receive consolidated data for the specified symbol and tick type. /// The handler and tick type must match. /// /// The symbol who's data is to be consolidated /// The consolidation calendar /// The tick type of subscription used as data source for consolidator. Specify null to use first subscription found. /// Data handler receives new consolidated data when generated /// A new consolidator matching the requested parameters with the handler already registered [DocumentationAttribute(ConsolidatingData)] public IDataConsolidator Consolidate(Symbol symbol, Func calendar, TickType? tickType, Action handler) where T : class, IBaseData { return Consolidate(symbol, calendar, tickType, handler, null, null); } /// /// Gets the historical data of an indicator for the specified symbol. The exact number of bars will be returned. /// The symbol must exist in the Securities collection. /// /// The target indicator /// The symbol to retrieve historical data for /// The number of bars to request /// The resolution to request /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// pandas.DataFrame of historical data of an indicator public IndicatorHistory IndicatorHistory(IndicatorBase indicator, Symbol symbol, int period, Resolution? resolution = null, Func selector = null) { return IndicatorHistory(indicator, new[] { symbol }, period, resolution, selector); } /// /// Gets the historical data of an indicator for the specified symbols. The exact number of bars will be returned. /// The symbol must exist in the Securities collection. /// /// The target indicator /// The symbols to retrieve historical data for /// The number of bars to request /// The resolution to request /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// pandas.DataFrame of historical data of an indicator public IndicatorHistory IndicatorHistory(IndicatorBase indicator, IEnumerable symbols, int period, Resolution? resolution = null, Func selector = null) { var warmupPeriod = (indicator as IIndicatorWarmUpPeriodProvider)?.WarmUpPeriod ?? 0; if (warmupPeriod > 0 && period > 0) { warmupPeriod -= 1; } var history = History(symbols, period + warmupPeriod, resolution, dataNormalizationMode: GetIndicatorHistoryDataNormalizationMode(indicator)); return IndicatorHistory(indicator, history, selector); } /// /// Gets the historical data of a bar indicator for the specified symbol. The exact number of bars will be returned. /// The symbol must exist in the Securities collection. /// /// The target indicator /// The symbol to retrieve historical data for /// The number of bars to request /// The resolution to request /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// pandas.DataFrame of historical data of a bar indicator public IndicatorHistory IndicatorHistory(IndicatorBase indicator, Symbol symbol, int period, Resolution? resolution = null, Func selector = null) where T : IBaseData { return IndicatorHistory(indicator, new[] { symbol }, period, resolution, selector); } /// /// Gets the historical data of a bar indicator for the specified symbols. The exact number of bars will be returned. /// The symbol must exist in the Securities collection. /// /// The target indicator /// The symbols to retrieve historical data for /// The number of bars to request /// The resolution to request /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// pandas.DataFrame of historical data of a bar indicator public IndicatorHistory IndicatorHistory(IndicatorBase indicator, IEnumerable symbols, int period, Resolution? resolution = null, Func selector = null) where T : IBaseData { var warmupPeriod = (indicator as IIndicatorWarmUpPeriodProvider)?.WarmUpPeriod ?? 0; if (warmupPeriod > 0 && period > 0) { warmupPeriod -= 1; } var history = History(symbols, period + warmupPeriod, resolution, dataNormalizationMode: GetIndicatorHistoryDataNormalizationMode(indicator)); return IndicatorHistory(indicator, history, selector); } /// /// Gets the historical data of an indicator for the specified symbol. The exact number of bars will be returned. /// The symbol must exist in the Securities collection. /// /// The target indicator /// The symbol to retrieve historical data for /// The span over which to retrieve recent historical data /// The resolution to request /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// pandas.DataFrame of historical data of an indicator public IndicatorHistory IndicatorHistory(IndicatorBase indicator, Symbol symbol, TimeSpan span, Resolution? resolution = null, Func selector = null) { return IndicatorHistory(indicator, new[] { symbol }, span, resolution, selector); } /// /// Gets the historical data of an indicator for the specified symbol. The exact number of bars will be returned. /// The symbol must exist in the Securities collection. /// /// The target indicator /// The symbols to retrieve historical data for /// The span over which to retrieve recent historical data /// The resolution to request /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// pandas.DataFrame of historical data of an indicator public IndicatorHistory IndicatorHistory(IndicatorBase indicator, IEnumerable symbols, TimeSpan span, Resolution? resolution = null, Func selector = null) { return IndicatorHistory(indicator, symbols, Time - span, Time, resolution, selector); } /// /// Gets the historical data of a bar indicator for the specified symbol. The exact number of bars will be returned. /// The symbol must exist in the Securities collection. /// /// The target indicator /// The symbols to retrieve historical data for /// The span over which to retrieve recent historical data /// The resolution to request /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// pandas.DataFrame of historical data of a bar indicator public IndicatorHistory IndicatorHistory(IndicatorBase indicator, IEnumerable symbols, TimeSpan span, Resolution? resolution = null, Func selector = null) where T : IBaseData { return IndicatorHistory(indicator, symbols, Time - span, Time, resolution, selector); } /// /// Gets the historical data of a bar indicator for the specified symbol. The exact number of bars will be returned. /// The symbol must exist in the Securities collection. /// /// The target indicator /// The symbol to retrieve historical data for /// The span over which to retrieve recent historical data /// The resolution to request /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// pandas.DataFrame of historical data of a bar indicator public IndicatorHistory IndicatorHistory(IndicatorBase indicator, Symbol symbol, TimeSpan span, Resolution? resolution = null, Func selector = null) where T : IBaseData { return IndicatorHistory(indicator, new[] { symbol }, span, resolution, selector); } /// /// Gets the historical data of an indicator for the specified symbols. The exact number of bars will be returned. /// The symbol must exist in the Securities collection. /// /// The target indicator /// The symbols to retrieve historical data for /// The start time in the algorithm's time zone /// The end time in the algorithm's time zone /// The resolution to request /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// pandas.DataFrame of historical data of an indicator public IndicatorHistory IndicatorHistory(IndicatorBase indicator, IEnumerable symbols, DateTime start, DateTime end, Resolution? resolution = null, Func selector = null) { var history = History(symbols, GetIndicatorAdjustedHistoryStart(indicator, symbols, start, end, resolution), end, resolution, dataNormalizationMode: GetIndicatorHistoryDataNormalizationMode(indicator)); return IndicatorHistory(indicator, history, selector); } /// /// Gets the historical data of an indicator for the specified symbol. The exact number of bars will be returned. /// The symbol must exist in the Securities collection. /// /// The target indicator /// The symbol to retrieve historical data for /// The start time in the algorithm's time zone /// The end time in the algorithm's time zone /// The resolution to request /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// pandas.DataFrame of historical data of an indicator public IndicatorHistory IndicatorHistory(IndicatorBase indicator, Symbol symbol, DateTime start, DateTime end, Resolution? resolution = null, Func selector = null) { return IndicatorHistory(indicator, new[] { symbol }, start, end, resolution, selector); } /// /// Gets the historical data of a bar indicator for the specified symbol. The exact number of bars will be returned. /// The symbol must exist in the Securities collection. /// /// The target indicator /// The symbol to retrieve historical data for /// The start time in the algorithm's time zone /// The end time in the algorithm's time zone /// The resolution to request /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// pandas.DataFrame of historical data of a bar indicator public IndicatorHistory IndicatorHistory(IndicatorBase indicator, Symbol symbol, DateTime start, DateTime end, Resolution? resolution = null, Func selector = null) where T : IBaseData { return IndicatorHistory(indicator, new[] { symbol }, start, end, resolution, selector); } /// /// Gets the historical data of a bar indicator for the specified symbols. The exact number of bars will be returned. /// The symbol must exist in the Securities collection. /// /// The target indicator /// The symbols to retrieve historical data for /// The start time in the algorithm's time zone /// The end time in the algorithm's time zone /// The resolution to request /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// pandas.DataFrame of historical data of a bar indicator public IndicatorHistory IndicatorHistory(IndicatorBase indicator, IEnumerable symbols, DateTime start, DateTime end, Resolution? resolution = null, Func selector = null) where T : IBaseData { var history = History(symbols, GetIndicatorAdjustedHistoryStart(indicator, symbols, start, end, resolution), end, resolution, dataNormalizationMode: GetIndicatorHistoryDataNormalizationMode(indicator)); return IndicatorHistory(indicator, history, selector); } /// /// Gets the historical data of an indicator and convert it into pandas.DataFrame /// /// The target indicator /// Historical data used to calculate the indicator /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// pandas.DataFrame containing the historical data of public IndicatorHistory IndicatorHistory(IndicatorBase indicator, IEnumerable history, Func selector = null) { selector ??= (x => x.Value); return IndicatorHistory(indicator, history, (bar) => indicator.Update(new IndicatorDataPoint(bar.Symbol, bar.EndTime, selector(bar))), GetDataTypeFromSelector(selector)); } /// /// Gets the historical data of an bar indicator and convert it into pandas.DataFrame /// /// Bar indicator /// Historical data used to calculate the indicator /// Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value) /// pandas.DataFrame containing the historical data of public IndicatorHistory IndicatorHistory(IndicatorBase indicator, IEnumerable history, Func selector = null) where T : IBaseData { selector ??= GetDefaultSelector(); return IndicatorHistory(indicator, history, (bar) => indicator.Update(selector(bar))); } /// /// Adds the provided consolidator and asserts the handler T type is assignable from the consolidator output, /// if not will throw /// private IDataConsolidator Consolidate(Symbol symbol, Func calendar, TickType? tickType, Action handler, TimeSpan? period, Resolution? resolution) where T : class, IBaseData { var consolidator = CreateConsolidator(symbol, calendar, tickType, period, resolution, typeof(T)); if (handler != null) { // register user-defined handler to receive consolidated data events consolidator.DataConsolidated += (sender, consolidated) => handler((T)consolidated); // register the consolidator for automatic updates via SubscriptionManager RegisterConsolidator(symbol, consolidator, tickType, indicatorBase: null); } return consolidator; } /// /// Registers a Renko or VolumeRenko consolidator for the specified symbol and bar size, /// and subscribes the to receive consolidated data. /// /// The symbol whose data is to be consolidated /// The bar size used for consolidation /// The tick type of the data to be consolidated /// Handler to receive consolidated data /// A new Renko-based consolidator with the handler registered public IDataConsolidator Consolidate(Symbol symbol, decimal size, TickType? tickType, Action handler) where T : class, IBaseData { var consolidator = CreateConsolidator(symbol, size, typeof(T), tickType); if (handler != null) { // register user-defined handler to receive consolidated data events consolidator.DataConsolidated += (sender, consolidated) => handler((T)consolidated); // register the consolidator for automatic updates via SubscriptionManager RegisterConsolidator(symbol, consolidator, tickType, indicatorBase: null); } return consolidator; } private IDataConsolidator CreateConsolidator(Symbol symbol, decimal size, Type consolidatorType, TickType? tickType) { var subscription = GetSubscription(symbol); // Select consolidator based on the consolidator type // size attribute will be used as barSize or range if (consolidatorType == typeof(VolumeRenkoBar)) { return new VolumeRenkoConsolidator(size); } if (consolidatorType == typeof(RenkoBar)) { return new RenkoConsolidator(size); } if (consolidatorType == typeof(RangeBar)) { return new RangeConsolidator((int)size); } // size attribute will be used as maxCount // If the subscription uses Tick resolution, choose the consolidator based on TickType if (subscription.Resolution == Resolution.Tick) { switch (tickType) { case TickType.OpenInterest: return new OpenInterestConsolidator((int)size); case TickType.Quote: return new TickQuoteBarConsolidator((int)size); default: return new TickConsolidator((int)size); } } if (consolidatorType == typeof(TradeBar)) { return new TradeBarConsolidator((int)size); } if (consolidatorType == typeof(QuoteBar)) { return new QuoteBarConsolidator((int)size); } // no matter what, we can always consolidate using BaseData with a maxCount return new BaseDataConsolidator((int)size); } private IDataConsolidator CreateConsolidator(Symbol symbol, Func calendar, TickType? tickType, TimeSpan? period, Resolution? resolution, Type consolidatorType) { // resolve consolidator input subscription var subscription = GetSubscription(symbol, tickType); // verify this consolidator will give reasonable results, if someone asks for second consolidation but we have minute // data we won't be able to do anything good, we'll call it second, but it would really just be minute! if (period.HasValue && period.Value < subscription.Increment || resolution.HasValue && resolution.Value < subscription.Resolution) { throw new ArgumentException($"Unable to create {symbol} consolidator because {symbol} is registered for " + Invariant($"{subscription.Resolution.ToStringInvariant()} data. Consolidators require higher resolution data to produce lower resolution data.") ); } IDataConsolidator consolidator = null; if (calendar != null) { // create requested consolidator consolidator = CreateConsolidator(calendar, subscription.Type, subscription.TickType); } else { // if not specified, default to the subscription resolution if (!period.HasValue && !resolution.HasValue) { period = subscription.Increment; } if (period.HasValue && period.Value == subscription.Increment || resolution.HasValue && resolution.Value == subscription.Resolution) { consolidator = CreateIdentityConsolidator(subscription.Type); } else { if (resolution.HasValue) { if (resolution.Value == Resolution.Daily) { consolidator = new MarketHourAwareConsolidator(Settings.DailyPreciseEndTime, resolution.Value, subscription.Type, subscription.TickType, Settings.DailyConsolidationUseExtendedMarketHours && subscription.ExtendedMarketHours); } period = resolution.Value.ToTimeSpan(); } consolidator ??= CreateConsolidator(period.Value, subscription.Type, subscription.TickType); } } if (consolidatorType != null && !consolidatorType.IsAssignableFrom(consolidator.OutputType)) { throw new ArgumentException( $"Unable to consolidate with the specified handler because the consolidator's output type " + $"is {consolidator.OutputType.Name} but the handler's input type is {subscription.Type.Name}."); } return consolidator; } private IDataConsolidator CreateConsolidator(Func calendar, Type consolidatorInputType, TickType tickType) { // if our type can be used as a trade bar, then let's just make one of those // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to TradeBar if (typeof(TradeBar).IsAssignableFrom(consolidatorInputType)) { return new TradeBarConsolidator(calendar); } // if our type can be used as a quote bar, then let's just make one of those // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to QuoteBar if (typeof(QuoteBar).IsAssignableFrom(consolidatorInputType)) { return new QuoteBarConsolidator(calendar); } // if our type can be used as a tick then we'll use a consolidator that keeps the TickType // we use IsAssignableFrom instead of IsSubclassOf so that we can account for types that are able to be cast to Tick if (typeof(Tick).IsAssignableFrom(consolidatorInputType)) { if (tickType == TickType.Quote) { return new TickQuoteBarConsolidator(calendar); } return new TickConsolidator(calendar); } // if our type can be used as a DynamicData then we'll use the DynamicDataConsolidator if (typeof(DynamicData).IsAssignableFrom(consolidatorInputType)) { return new DynamicDataConsolidator(calendar); } // no matter what we can always consolidate based on the time-value pair of BaseData return new BaseDataConsolidator(calendar); } /// /// Creates a new consolidator identity consolidator for the requested output type. /// private static IDataConsolidator CreateIdentityConsolidator(Type consolidatorInputType) { if (typeof(TradeBar).IsAssignableFrom(consolidatorInputType)) { return new IdentityDataConsolidator(); } else if (typeof(QuoteBar).IsAssignableFrom(consolidatorInputType)) { return new IdentityDataConsolidator(); } else if (typeof(Tick).IsAssignableFrom(consolidatorInputType)) { return new IdentityDataConsolidator(); } else if (typeof(DynamicData).IsAssignableFrom(consolidatorInputType)) { return new DynamicDataConsolidator(1); } return new IdentityDataConsolidator(); } /// /// Registers and warms up (if EnableAutomaticIndicatorWarmUp is set) the indicator /// private void InitializeIndicator(IndicatorBase indicator, Resolution? resolution = null, Func selector = null, params Symbol[] symbols) { var dataType = GetDataTypeFromSelector(selector); foreach (var symbol in symbols) { RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution, dataType), selector); } if (Settings.AutomaticIndicatorWarmUp) { WarmUpIndicator(symbols, indicator, resolution, selector); } } private void InitializeIndicator(IndicatorBase indicator, Resolution? resolution = null, Func selector = null, params Symbol[] symbols) where T : class, IBaseData { foreach (var symbol in symbols) { RegisterIndicator(symbol, indicator, resolution, selector); } if (Settings.AutomaticIndicatorWarmUp) { WarmUpIndicator(symbols, indicator, resolution, selector); } } private void InitializeOptionIndicator(IndicatorBase indicator, Resolution? resolution, Symbol symbol, Symbol mirrorOption) { RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution, typeof(QuoteBar))); RegisterIndicator(symbol.Underlying, indicator, ResolveConsolidator(symbol.Underlying, resolution)); var symbols = new List { symbol, symbol.Underlying }; if (mirrorOption != null) { RegisterIndicator(mirrorOption, indicator, ResolveConsolidator(mirrorOption, resolution, typeof(QuoteBar))); symbols.Add(mirrorOption); } if (Settings.AutomaticIndicatorWarmUp) { WarmUpIndicator(symbols, indicator, resolution); } } private string InitializeOptionIndicator(Symbol symbol, out IRiskFreeInterestRateModel riskFreeRateModel, out IDividendYieldModel dividendYieldModel, decimal? riskFreeRate = null, decimal? dividendYield = null, OptionPricingModelType? optionModel = null, Resolution? resolution = null) where T : OptionIndicatorBase { var name = CreateIndicatorName(symbol, $"{typeof(T).Name}({riskFreeRate},{dividendYield},{OptionIndicatorBase.GetOptionModel(optionModel, symbol.ID.OptionStyle)})", resolution); riskFreeRateModel = riskFreeRate.HasValue ? new ConstantRiskFreeRateInterestRateModel(riskFreeRate.Value) // Make it a function so it's lazily evaluated: SetRiskFreeInterestRateModel can be called after this method : new FuncRiskFreeRateInterestRateModel((datetime) => RiskFreeInterestRateModel.GetInterestRate(datetime)); if (dividendYield.HasValue) { dividendYieldModel = new ConstantDividendYieldModel(dividendYield.Value); } else { dividendYieldModel = DividendYieldProvider.CreateForOption(symbol); } return name; } private void RegisterConsolidator(Symbol symbol, IDataConsolidator consolidator, TickType? tickType, IndicatorBase indicatorBase) { // keep a reference of the consolidator so we can unregister it later using only a reference to the indicator indicatorBase?.Consolidators.Add(consolidator); // register the consolidator for automatic updates via SubscriptionManager SubscriptionManager.AddConsolidator(symbol, consolidator, tickType); } private DateTime GetIndicatorAdjustedHistoryStart(IndicatorBase indicator, IEnumerable symbols, DateTime start, DateTime end, Resolution? resolution = null) { var warmupPeriod = (indicator as IIndicatorWarmUpPeriodProvider)?.WarmUpPeriod ?? 0; if (warmupPeriod != 0) { warmupPeriod -= 1; if (warmupPeriod > 0) { foreach (var request in CreateDateRangeHistoryRequests(symbols, start, end, resolution)) { var adjustedStart = _historyRequestFactory.GetStartTimeAlgoTz(request.StartTimeUtc, request.Symbol, warmupPeriod, request.Resolution, request.ExchangeHours, request.DataTimeZone, request.DataType, request.IncludeExtendedMarketHours); if (adjustedStart < start) { start = adjustedStart; } } } } return start; } private DataNormalizationMode? GetIndicatorHistoryDataNormalizationMode(IIndicator indicator) { DataNormalizationMode? dataNormalizationMode = null; if (indicator is OptionIndicatorBase optionIndicator && optionIndicator.OptionSymbol.Underlying.SecurityType == SecurityType.Equity) { // we use point in time raw data to warmup option indicators which use underlying prices and strikes dataNormalizationMode = DataNormalizationMode.ScaledRaw; } return dataNormalizationMode; } private IndicatorHistory IndicatorHistory(IndicatorBase indicator, IEnumerable history, Action updateIndicator, Type dataType = null) where T : IBaseData { // Reset the indicator indicator.Reset(); var properties = indicator.GetType() .GetProperties() .Where(p => !p.IsDefined(typeof(PandasIgnoreAttribute), true) && !_ignoredProperties.Contains(p.Name)) .ToLookup(p => typeof(IIndicator).IsAssignableFrom(p.PropertyType)); var indicatorProperties = properties[true]; var nonIndicatorProperties = properties[false]; var indicatorsDataPointPerProperty = indicatorProperties .Select(p => InternalIndicatorValues.Create(indicator, p)) .Append(InternalIndicatorValues.Create(indicator, "Current")) .ToList(); var nonIndicatorValues = new Dictionary>(); var indicatorsDataPointsByTime = new List(); var lastConsumedTime = DateTime.MinValue; IndicatorDataPoint lastPoint = null; void consumeLastPoint(IndicatorDataPoint newInputPoint) { if (newInputPoint == null || lastConsumedTime == newInputPoint.EndTime) { return; } lastConsumedTime = newInputPoint.EndTime; var IndicatorDataPoints = new IndicatorDataPoints { Time = newInputPoint.Time, EndTime = newInputPoint.EndTime }; indicatorsDataPointsByTime.Add(IndicatorDataPoints); for (var i = 0; i < indicatorsDataPointPerProperty.Count; i++) { var newPoint = indicatorsDataPointPerProperty[i].UpdateValue(); IndicatorDataPoints.SetProperty(indicatorsDataPointPerProperty[i].Name, newPoint); } foreach (var property in nonIndicatorProperties) { var propertyName = property.Name; var propertyValue = property.GetValue(indicator); if (!nonIndicatorValues.TryGetValue(propertyName, out var propertyHistory)) { propertyHistory = new List<(DateTime, object)>(); nonIndicatorValues[propertyName] = propertyHistory; } propertyHistory.Add((newInputPoint.EndTime, propertyValue)); } } IndicatorUpdatedHandler callback = (object _, IndicatorDataPoint newInputPoint) => { if (!indicator.IsReady) { return; } if (lastPoint == null || lastPoint.Time != newInputPoint.Time) { // if null, it's the first point, we transitions from not ready to ready // else when the time changes we fetch the indicators values, some indicators which consume data from multiple symbols might trigger the Updated event // even if their value has not changed yet consumeLastPoint(newInputPoint); } lastPoint = newInputPoint; }; // register the callback, update the indicator and unregister finally indicator.Updated += callback; if (typeof(T) == typeof(IndicatorDataPoint) || typeof(T).IsAbstract) { history.PushThrough(bar => updateIndicator(bar), dataType); } else { // if the indicator requires a specific type, like a QuoteBar for an equity symbol, we need to fetch it directly foreach (var dataDictionary in history.Get()) { foreach (var dataPoint in dataDictionary.Values) { updateIndicator(dataPoint); } } } // flush the last point, this will be useful for indicator consuming time from multiple symbols consumeLastPoint(lastPoint); indicator.Updated -= callback; return new IndicatorHistory(indicatorsDataPointsByTime, indicatorsDataPointPerProperty, new Lazy( () => PandasConverter.GetIndicatorDataFrame(indicatorsDataPointPerProperty.Select(x => new KeyValuePair>(x.Name, x.Values)), nonIndicatorValues), isThreadSafe: false)); } private Type GetDataTypeFromSelector(Func selector) { Type dataType = null; if (_quoteRequiredFields.Any(x => ReferenceEquals(selector, x))) { dataType = typeof(QuoteBar); } else if (ReferenceEquals(selector, Field.Volume)) { dataType = typeof(TradeBar); } return dataType; } } }