/// <summary> /// Creates a new Stochastics Indicator from the specified periods. /// </summary> /// <param name="name">The name of this indicator.</param> /// <param name="period">The period given to calculate the Fast %K</param> /// <param name="kPeriod">The K period given to calculated the Slow %K</param> /// <param name="dPeriod">The D period given to calculated the Slow %D</param> public Stochastic(string name, int period, int kPeriod, int dPeriod) : base(name) { _maximum = new Maximum(name + "_Max", period); _minimum = new Minimum(name + "_Min", period); _sumFastK = new Sum(name + "_SumFastK", kPeriod); _sumSlowK = new Sum(name + "_SumD", dPeriod); FastStoch = new FunctionalIndicator(name + "_FastStoch", (time, input) => ComputeFastStoch(period, time, input), fastStoch => _maximum.IsReady, () => { } ); StochK = new FunctionalIndicator(name + "_StochK", (time, input) => ComputeStochK(period, kPeriod, time, input), stochK => _maximum.IsReady, () => { } ); StochD = new FunctionalIndicator( name + "_StochD", (time, input) => ComputeStochD(period, kPeriod, dPeriod), stochD => _maximum.IsReady, () => { } ); WarmUpPeriod = period; }
/// <summary> /// Creates a new IchimokuKinkoHyo indicator from the specific periods /// </summary> /// <param name="name">The name of this indicator</param> /// <param name="tenkanPeriod">The Tenkan-sen period</param> /// <param name="kijunPeriod">The Kijun-sen period</param> /// <param name="senkouAPeriod">The Senkou A Span period</param> /// <param name="senkouBPeriod">The Senkou B Span period</param> /// <param name="senkouADelayPeriod">The Senkou A Span delay</param> /// <param name="senkouBDelayPeriod">The Senkou B Span delay</param> public IchimokuKinkoHyo(string name, int tenkanPeriod = 9, int kijunPeriod = 26, int senkouAPeriod = 26, int senkouBPeriod = 52, int senkouADelayPeriod = 26, int senkouBDelayPeriod = 26) : base(name) { WarmUpPeriod = Math.Max(tenkanPeriod + senkouADelayPeriod, kijunPeriod + senkouADelayPeriod); WarmUpPeriod = Math.Max(WarmUpPeriod, senkouBPeriod + senkouBDelayPeriod); TenkanMaximum = new Maximum(name + "_TenkanMax", tenkanPeriod); TenkanMinimum = new Minimum(name + "_TenkanMin", tenkanPeriod); KijunMaximum = new Maximum(name + "_KijunMax", kijunPeriod); KijunMinimum = new Minimum(name + "_KijunMin", kijunPeriod); SenkouBMaximum = new Maximum(name + "_SenkouBMaximum", senkouBPeriod); SenkouBMinimum = new Minimum(name + "_SenkouBMinimum", senkouBPeriod); DelayedTenkanSenkouA = new Delay(name + "DelayedTenkan", senkouADelayPeriod); DelayedKijunSenkouA = new Delay(name + "DelayedKijun", senkouADelayPeriod); DelayedMaximumSenkouB = new Delay(name + "DelayedMax", senkouBDelayPeriod); DelayedMinimumSenkouB = new Delay(name + "DelayedMin", senkouBDelayPeriod); Chikou = new Delay(name + "_Chikou", senkouADelayPeriod); SenkouA = new FunctionalIndicator( name + "_SenkouA", (time, input) => SenkouA.IsReady ? (DelayedTenkanSenkouA + DelayedKijunSenkouA) / 2 : Constants.Zero, senkouA => DelayedTenkanSenkouA.IsReady && DelayedKijunSenkouA.IsReady, () => { Tenkan.Reset(); Kijun.Reset(); }); SenkouB = new FunctionalIndicator( name + "_SenkouB", (time, input) => SenkouB.IsReady ? (DelayedMaximumSenkouB + DelayedMinimumSenkouB) / 2 : Constants.Zero, senkouA => DelayedMaximumSenkouB.IsReady && DelayedMinimumSenkouB.IsReady, () => { Tenkan.Reset(); Kijun.Reset(); }); Tenkan = new FunctionalIndicator( name + "_Tenkan", (time, input) => Tenkan.IsReady ? (TenkanMaximum + TenkanMinimum) / 2 : Constants.Zero, tenkan => TenkanMaximum.IsReady && TenkanMinimum.IsReady, () => { TenkanMaximum.Reset(); TenkanMinimum.Reset(); }); Kijun = new FunctionalIndicator( name + "_Kijun", (time, input) => Kijun.IsReady ? (KijunMaximum + KijunMinimum) / 2 : Constants.Zero, kijun => KijunMaximum.IsReady && KijunMinimum.IsReady, () => { KijunMaximum.Reset(); KijunMinimum.Reset(); }); }
/// <summary> /// Creates a new AverageTrueRange indicator using the specified period and moving average type /// </summary> /// <param name="name">The name of this indicator</param> /// <param name="period">The smoothing period used to smooth the true range values</param> /// <param name="movingAverageType">The type of smoothing used to smooth the true range values</param> public AverageTrueRange(string name, int period, MovingAverageType movingAverageType = MovingAverageType.Wilders) : base(name) { WarmUpPeriod = period; _smoother = movingAverageType.AsIndicator($"{name}_{movingAverageType}", period); TrueRange = new FunctionalIndicator(name + "_TrueRange", (time, currentBar) => { // in our Forward function we'll just call the ComputeTrueRange var nextValue = ComputeTrueRange(_previous, currentBar); _previous = currentBar; return(nextValue); } // in our IsReady function we just need at least one sample , trueRangeIndicator => trueRangeIndicator.Samples >= 1 ); }
/// <summary> /// Creates a new AroonOscillator from the specified up/down periods. /// </summary> /// <param name="name">The name of this indicator</param> /// <param name="upPeriod">The lookback period to determine the highest high for the AroonDown</param> /// <param name="downPeriod">The lookback period to determine the lowest low for the AroonUp</param> public AroonOscillator(string name, int upPeriod, int downPeriod) : base(name) { var max = new Maximum(name + "_Max", upPeriod + 1); AroonUp = new FunctionalIndicator(name + "_AroonUp", (time, input) => ComputeAroonUp(upPeriod, max, time, input), aroonUp => max.IsReady, () => max.Reset() ); var min = new Minimum(name + "_Min", downPeriod + 1); AroonDown = new FunctionalIndicator(name + "_AroonDown", (time, input) => ComputeAroonDown(downPeriod, min, time, input), aroonDown => min.IsReady, () => min.Reset() ); WarmUpPeriod = 1 + Math.Max(upPeriod, downPeriod); }
/// <summary> /// Initializes a new instance of the KeltnerChannels class /// </summary> /// <param name="name">The name of this indicator</param> /// <param name="period">The period of the average true range and moving average (middle band)</param> /// <param name="k">The number of multiples specifying the distance between the middle band and upper or lower bands</param> /// <param name="movingAverageType">The type of moving average to be used</param> public KeltnerChannels(string name, int period, double k, MovingAverageType movingAverageType = MovingAverageType.Simple) : base(name) { _k = k; WarmUpPeriod = period; //Initialise ATR and SMA AverageTrueRange = new AverageTrueRange(name + "_AverageTrueRange", period, MovingAverageType.Simple); MiddleBand = movingAverageType.AsIndicator(name + "_MiddleBand", period); //Compute Lower Band LowerBand = new FunctionalIndicator(name + "_LowerBand", (time, input) => MiddleBand.IsReady ? MiddleBand - AverageTrueRange * _k : Constants.Zero, lowerBand => MiddleBand.IsReady, () => MiddleBand.Reset() ); //Compute Upper Band UpperBand = new FunctionalIndicator(name + "_UpperBand", (time, input) => MiddleBand.IsReady ? MiddleBand + AverageTrueRange * _k : Constants.Zero, upperBand => MiddleBand.IsReady, () => MiddleBand.Reset() ); }
/// <summary> /// Initializes a new instance of the <see cref="AverageDirectionalIndex"/> class. /// </summary> /// <param name="name">The name.</param> /// <param name="period">The period.</param> public AverageDirectionalIndex(string name, int period) : base(name) { _period = period; _trueRange = new FunctionalIndicator(name + "_TrueRange", ComputeTrueRange, isReady => _previousInput != null ); _directionalMovementPlus = new FunctionalIndicator(name + "_PositiveDirectionalMovement", ComputePositiveDirectionalMovement, isReady => _previousInput != null ); _directionalMovementMinus = new FunctionalIndicator(name + "_NegativeDirectionalMovement", ComputeNegativeDirectionalMovement, isReady => _previousInput != null ); PositiveDirectionalIndex = new FunctionalIndicator(name + "_PositiveDirectionalIndex", (time, input) => { // Computes the Plus Directional Indicator(+DI period). if (_smoothedTrueRange != 0 && _smoothedDirectionalMovementPlus.IsReady) { return((DoubleArray)100d * _smoothedDirectionalMovementPlus / _smoothedTrueRange); } return(Constants.Zero); }, positiveDirectionalIndex => _smoothedDirectionalMovementPlus.IsReady, () => { _directionalMovementPlus.Reset(); _trueRange.Reset(); } ); NegativeDirectionalIndex = new FunctionalIndicator(name + "_NegativeDirectionalIndex", (time, input) => { // Computes the Minus Directional Indicator(-DI period). if (_smoothedTrueRange != 0 && _smoothedDirectionalMovementMinus.IsReady) { return(100d * _smoothedDirectionalMovementMinus / _smoothedTrueRange); } return(Constants.Zero); }, negativeDirectionalIndex => _smoothedDirectionalMovementMinus.IsReady, () => { _directionalMovementMinus.Reset(); _trueRange.Reset(); } ); _smoothedTrueRange = new FunctionalIndicator(name + "_SmoothedTrueRange", (time, input) => { // Computes the Smoothed True Range value. var value = Samples > _period + 1 ? _smoothedTrueRange / _period : Constants.Zero; return(_smoothedTrueRange + _trueRange - value); }, isReady => Samples > period ); _smoothedDirectionalMovementPlus = new FunctionalIndicator(name + "_SmoothedDirectionalMovementPlus", (time, input) => { // Computes the Smoothed Directional Movement Plus value. var value = Samples > _period + 1 ? _smoothedDirectionalMovementPlus / _period : Constants.Zero; return(_smoothedDirectionalMovementPlus + _directionalMovementPlus - value); }, isReady => Samples > period ); _smoothedDirectionalMovementMinus = new FunctionalIndicator(name + "_SmoothedDirectionalMovementMinus", (time, input) => { // Computes the Smoothed Directional Movement Minus value. var value = Samples > _period + 1 ? _smoothedDirectionalMovementMinus / _period : Constants.Zero; return(_smoothedDirectionalMovementMinus + _directionalMovementMinus - value); }, isReady => Samples > period ); _averageDirectionalIndex = new WilderMovingAverage(period); }