예제 #1
0
        /// <summary>
        /// Computes the next value in the transform.
        /// value1 is a function used to normalize price withing the last _period day range.
        /// value1 is centered on its midpoint and then doubled so that value1 will swing between -1 and +1.
        /// value1 is also smoothed with an exponential moving average whose alpha is 0.33.
        ///
        /// Since the smoothing may allow value1 to exceed the _period day price range, limits are introduced to
        /// preclude the transform from blowing up by having an input larger than unity.
        /// </summary>
        /// <param name="input">IndicatorDataPoint - the time and value of the next price</param>
        /// <returns></returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            var x     = 0.0;
            var y     = 0.0;
            var price = (input.Low + input.High) / 2m;

            _medianMin.Update(input.Occured, input.TimeZone, price);
            _medianMax.Update(input.Occured, input.TimeZone, price);

            if (!IsReady)
            {
                return(0);
            }

            var minL = _medianMin.Current.Price;
            var maxH = _medianMax.Current.Price;

            if (minL != maxH)
            {
                x = _alpha * 2 * ((double)((price - minL) / (maxH - minL)) - .5) + (1 - _alpha) * _previous;
                y = FisherTransformFunction(x);
            }
            _previous = x;

            return(Convert.ToDecimal(y) + .5m * Current.Price);
        }
예제 #2
0
        /// <summary>
        /// Computes the Slow Stochastic %K.
        /// </summary>
        /// <param name="period">The period.</param>
        /// <param name="constantK">The constant k.</param>
        /// <param name="input">The input.</param>
        /// <returns>The Slow Stochastics %K value.</returns>
        private decimal ComputeStochK(int period, int constantK, DataPointBar input)
        {
            var stochK = _maximum.Samples >= (period + constantK - 1) ? _sumFastK / constantK : new decimal(0.0);

            _sumSlowK.Update(input.Occured, input.TimeZone, stochK);
            return(stochK * 100);
        }
예제 #3
0
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            AroonUp.Update(input.Occured, input.TimeZone, input.High);
            AroonDown.Update(input.Occured, input.TimeZone, input.Low);

            return(AroonUp - AroonDown);
        }
예제 #4
0
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            if (!IsReady)
            {
                _previousInput = input;
                return(0m);
            }

            var greatest = input.High - input.Low;

            var value2 = Math.Abs(_previousInput.Close - input.High);

            if (value2 > greatest)
            {
                greatest = value2;
            }

            var value3 = Math.Abs(_previousInput.Close - input.Low);

            if (value3 > greatest)
            {
                greatest = value3;
            }

            _previousInput = input;

            return(greatest);
        }
예제 #5
0
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The trade bar input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            // On first iteration we can’t produce an SAR value so we save the current bar and return zero
            if (Samples == 1)
            {
                _previousBar = input;

                // return a value that's close to where we will be, returning 0 doesn't make sense
                return(input.Close);
            }

            // On second iteration we initiate the position the extreme point and the SAR
            if (Samples == 2)
            {
                Init(input);
                _previousBar = input;
                return(_sar);
            }

            if (_isLong)
            {
                HandleLongPosition(input);
            }
            else
            {
                HandleShortPosition(input);
            }

            _previousBar = input;

            return(_outputSar);
        }
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            _adx.Update(input);
            _adxHistory.Add(_adx);

            return((_adx + _adxHistory[Math.Min(_adxHistory.Count - 1, _period - 1)]) / 2);
        }
예제 #7
0
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            _trueRange.Update(input);

            if (Samples == 1)
            {
                _previousInput = input;
                return(50m);
            }

            var buyingPressure = new IndicatorDataPoint {
                Price = input.Close - Math.Min(input.Low, _previousInput.Close)
            };

            _sumBuyingPressure1.Update(buyingPressure);
            _sumBuyingPressure2.Update(buyingPressure);
            _sumBuyingPressure3.Update(buyingPressure);

            _sumTrueRange1.Update(_trueRange.Current);
            _sumTrueRange2.Update(_trueRange.Current);
            _sumTrueRange3.Update(_trueRange.Current);

            _previousInput = input;

            if (!IsReady)
            {
                return(50m);
            }

            var average1 = _sumBuyingPressure1 / _sumTrueRange1;
            var average2 = _sumBuyingPressure2 / _sumTrueRange2;
            var average3 = _sumBuyingPressure3 / _sumTrueRange3;

            return(100m * (4 * average1 + 2 * average2 + average3) / 7);
        }
예제 #8
0
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            // compute the true range and then send it to our smoother
            TrueRange.Update(input);
            _smoother.Update(input.Occured, input.TimeZone, TrueRange);

            return(_smoother.Current.Price);
        }
예제 #9
0
 /// <summary>
 /// Computes the next value of this indicator from the given state
 /// </summary>
 /// <param name="input">The input given to the indicator</param>
 protected override decimal ComputeNextValue(DataPointBar input)
 {
     _maximum.Update(input.Occured, input.TimeZone, input.High);
     _mininum.Update(input.Occured, input.TimeZone, input.Low);
     FastStoch.Update(input);
     StochK.Update(input);
     StochD.Update(input);
     return(FastStoch);
 }
예제 #10
0
        /// <summary>
        /// Computes the average value
        /// </summary>
        /// <param name="input">The data for the calculation</param>
        /// <returns>The average value</returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            var price = (double)(input.High + input.Low) / 2;

            _high.Add((double)input.High);
            _low.Add((double)input.Low);

            // our first data point just return identity
            if (_high.Samples <= _high.Size)
            {
                _filt = price;
            }
            double n1;
            double n2;
            double n3;
            double hh;
            double ll;
            double dimen = 0;
            double alpha;

            n3 = (_high.Max() - _low.Min()) / _n;

            hh = _high.Take(_n / 2).Max();
            ll = _low.Take(_n / 2).Min();

            n1 = (hh - ll) / (_n / 2);

            if (_high.IsReady)
            {
                hh = _high.Skip(_n / 2).Take(_n / 2).Max();
                ll = _low.Skip(_n / 2).Take(_n / 2).Min();
            }

            n2 = (hh - ll) / (_n / 2);

            if (n1 > 0 && n2 > 0 && n3 > 0)
            {
                dimen = (Math.Log(n1 + n2) - Math.Log(n3)) / Math.Log(2);
            }
            ;

            alpha = Math.Exp(_w * (dimen - 1));
            if (alpha < .01)
            {
                alpha = .01;
            }
            if (alpha > 1)
            {
                alpha = 1;
            }

            _filt = alpha * price + (1 - alpha) * _filt;

            return((decimal)_filt);
        }
예제 #11
0
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator, which by convention is the mean value of the upper band and lower band.</returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            if (_previousInput != null)
            {
                UpperBand.Update(new IndicatorDataPoint(_previousInput.Occured, _previousInput.TimeZone, _previousInput.High));
                LowerBand.Update(new IndicatorDataPoint(_previousInput.Occured, _previousInput.TimeZone, _previousInput.Low));
            }

            _previousInput = input;
            return (UpperBand.Current.Price + LowerBand.Current.Price) / 2;
        }
예제 #12
0
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            _maximum.Update(new IndicatorDataPoint {
                Price = input.High
            });
            _minimum.Update(new IndicatorDataPoint {
                Price = input.Low
            });

            return((_maximum + _minimum) / 2);
        }
예제 #13
0
 /// <summary>
 /// Resets this indicator to its initial state
 /// </summary>
 public override void Reset()
 {
     _previousInput = null;
     _trueRange.Reset();
     _sumBuyingPressure1.Reset();
     _sumBuyingPressure2.Reset();
     _sumBuyingPressure3.Reset();
     _sumTrueRange1.Reset();
     _sumTrueRange2.Reset();
     _sumTrueRange3.Reset();
     base.Reset();
 }
예제 #14
0
        /// <summary>
        /// Computes the True Range value.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns></returns>
        private decimal ComputeTrueRange(DataPointBar input)
        {
            var trueRange = new decimal(0.0);

            if (_previousInput == null)
            {
                return(trueRange);
            }

            trueRange = (Math.Max(Math.Abs(input.Low - _previousInput.Close), Math.Max(TrueRange.Current, Math.Abs(input.High - _previousInput.Close))));

            return(trueRange);
        }
예제 #15
0
 /// <summary>
 /// Resets this indicator to its initial state
 /// </summary>
 public override void Reset()
 {
     base.Reset();
     _previousInput = null;
     TrueRange.Reset();
     DirectionalMovementPlus.Reset();
     DirectionalMovementMinus.Reset();
     SmoothedTrueRange.Reset();
     SmoothedDirectionalMovementMinus.Reset();
     SmoothedDirectionalMovementPlus.Reset();
     PositiveDirectionalIndex.Reset();
     NegativeDirectionalIndex.Reset();
 }
예제 #16
0
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            Minimum.Update(input.Occured, input.TimeZone, input.Low);
            Maximum.Update(input.Occured, input.TimeZone, input.High);

            if (!IsReady)
            {
                return(0);
            }

            var range = (Maximum.Current.Price - Minimum.Current.Price);

            return(range == 0 ? 0 : -100m * (Maximum.Current.Price - input.Close) / range);
        }
예제 #17
0
        /// <summary>
        /// Computes the TrueRange from the current and previous trade bars
        ///
        /// TrueRange is defined as the maximum of the following:
        ///   High - Low
        ///   ABS(High - PreviousClose)
        ///   ABS(Low  - PreviousClose)
        /// </summary>
        /// <param name="previous">The previous trade bar</param>
        /// <param name="current">The current trade bar</param>
        /// <returns>The true range</returns>
        public static decimal ComputeTrueRange(DataPointBar previous, DataPointBar current)
        {
            var range1 = current.High - current.Low;

            if (previous == null)
            {
                return(range1);
            }

            var range2 = Math.Abs(current.High - previous.Close);
            var range3 = Math.Abs(current.Low - previous.Close);

            return(Math.Max(range1, Math.Max(range2, range3)));
        }
예제 #18
0
        /// <summary>
        /// Computes the next value for this indicator from the given state.
        /// </summary>
        /// <param name="input">The TradeBar to this indicator on this time step</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            AverageTrueRange.Update(input);

            var typicalPrice = (input.High + input.Low + input.Close) / 3m;

            MiddleBand.Update(input.Occured, input.TimeZone, typicalPrice);

            // poke the upper/lower bands, they actually don't use the input, they compute
            // based on the ATR and the middle band
            LowerBand.Update(input);
            UpperBand.Update(input);
            return(MiddleBand);
        }
예제 #19
0
        /// <summary>
        /// Initialize the indicator values
        /// </summary>
        private void Init(DataPointBar currentBar)
        {
            // init position
            _isLong = currentBar.Close >= _previousBar.Close;

            // init sar and Extreme price
            if (_isLong)
            {
                _ep  = Math.Min(currentBar.High, _previousBar.High);
                _sar = _previousBar.Low;
            }
            else
            {
                _ep  = Math.Min(currentBar.Low, _previousBar.Low);
                _sar = _previousBar.High;
            }
        }
예제 #20
0
        /// <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)
        {
            _smoother = movingAverageType.AsIndicator(string.Format("{0}_{1}", name, movingAverageType), period);

            DataPointBar previous = null;

            TrueRange = new FunctionalIndicator <DataPointBar>(name + "_TrueRange", currentBar =>
            {
                // in our ComputeNextValue 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
                                                               );
        }
예제 #21
0
        /// <summary>
        /// Computes the Fast Stochastic %K.
        /// </summary>
        /// <param name="period">The period.</param>
        /// <param name="input">The input.</param>
        /// <returns>The Fast Stochastics %K value.</returns>
        private decimal ComputeFastStoch(int period, DataPointBar input)
        {
            var     denominator = (_maximum - _mininum);
            var     numerator   = (input.Close - _mininum);
            decimal fastStoch;

            if (denominator == 0m)
            {
                // if there's no range, just return constant zero
                fastStoch = 0m;
            }
            else
            {
                fastStoch = _maximum.Samples >= period ? numerator / denominator : new decimal(0.0);
            }
            _sumFastK.Update(input.Occured, input.TimeZone, fastStoch);
            return(fastStoch * 100);
        }
예제 #22
0
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            decimal typicalPrice = (input.High + input.Low + input.Close) / 3.0m;

            TypicalPriceAverage.Update(input.Occured, input.TimeZone, typicalPrice);
            TypicalPriceMeanDeviation.Update(input.Occured, input.TimeZone, typicalPrice);

            // compare this to zero, since if the mean deviation is very small we can get
            // precision errors due to non-floating point math
            var weightedMeanDeviation = _k * TypicalPriceMeanDeviation.Current;

            if (weightedMeanDeviation == 0.0m)
            {
                return(0.0m);
            }

            return((typicalPrice - TypicalPriceAverage.Current) / weightedMeanDeviation);
        }
예제 #23
0
 /// <summary>
 /// Computes the next value of this indicator from the given state
 /// </summary>
 /// <param name="input">The input given to the indicator</param>
 protected override decimal ComputeNextValue(DataPointBar input)
 {
     TenkanMaximum.Update(input.Occured, input.TimeZone, input.High);
     TenkanMinimum.Update(input.Occured, input.TimeZone, input.Low);
     Tenkan.Update(input);
     KijunMaximum.Update(input.Occured, input.TimeZone, input.High);
     KijunMinimum.Update(input.Occured, input.TimeZone, input.Low);
     Kijun.Update(input);
     DelayedTenkanSenkouA.Update(input.Occured, input.TimeZone, Tenkan.Current.Price);
     DelayedKijunSenkouA.Update(input.Occured, input.TimeZone, Kijun.Current.Price);
     SenkouA.Update(input);
     SenkouBMaximum.Update(input.Occured, input.TimeZone, input.High);
     SenkouBMinimum.Update(input.Occured, input.TimeZone, input.Low);
     DelayedMaximumSenkouB.Update(input.Occured, input.TimeZone, SenkouBMaximum.Current.Price);
     DelayedMinimumSenkouB.Update(input.Occured, input.TimeZone, SenkouBMinimum.Current.Price);
     SenkouB.Update(input);
     return(input.Close);
 }
예제 #24
0
        /// <summary>
        /// Computes the positive directional movement.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns></returns>
        private decimal ComputePositiveDirectionalMovement(DataPointBar input)
        {
            var postiveDirectionalMovement = new decimal(0.0);

            if (_previousInput == null)
            {
                return(postiveDirectionalMovement);
            }

            if ((input.High - _previousInput.High) >= (_previousInput.Low - input.Low))
            {
                if ((input.High - _previousInput.High) > 0)
                {
                    postiveDirectionalMovement = input.High - _previousInput.High;
                }
            }

            return(postiveDirectionalMovement);
        }
예제 #25
0
        /// <summary>
        /// Computes the negative directional movement.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns></returns>
        private decimal ComputeNegativeDirectionalMovement(DataPointBar input)
        {
            var negativeDirectionalMovement = new decimal(0.0);

            if (_previousInput == null)
            {
                return(negativeDirectionalMovement);
            }

            if ((_previousInput.Low - input.Low) > (input.High - _previousInput.High))
            {
                if ((_previousInput.Low - input.Low) > 0)
                {
                    negativeDirectionalMovement = _previousInput.Low - input.Low;
                }
            }

            return(negativeDirectionalMovement);
        }
예제 #26
0
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            TrueRange.Update(input);
            DirectionalMovementPlus.Update(input);
            DirectionalMovementMinus.Update(input);
            SmoothedTrueRange.Update(Current);
            SmoothedDirectionalMovementMinus.Update(Current);
            SmoothedDirectionalMovementPlus.Update(Current);
            if (_previousInput != null)
            {
                PositiveDirectionalIndex.Update(Current);
                NegativeDirectionalIndex.Update(Current);
            }
            var diff  = Math.Abs(PositiveDirectionalIndex - NegativeDirectionalIndex);
            var sum   = PositiveDirectionalIndex + NegativeDirectionalIndex;
            var value = sum == 0 ? 50 : ((_period - 1) * Current.Price + 100 * diff / sum) / _period;

            _previousInput = input;
            return(value);
        }
예제 #27
0
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(DataPointBar input)
        {
            _tr.Update(input);

            if (!IsReady)
            {
                _atr.Update(input);
                return(input.Close != 0 ? _atr / input.Close * 100 : 0m);
            }

            if (Samples == _period + 1)
            {
                // first output value is SMA of TrueRange
                _atr.Update(input);
                _lastAtrValue = _atr;
            }
            else
            {
                // next TrueRange values are smoothed using Wilder's approach
                _lastAtrValue = (_lastAtrValue * (_period - 1) + _tr) / _period;
            }

            return(input.Close != 0 ? _lastAtrValue / input.Close * 100 : 0m);
        }
예제 #28
0
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="window">The window of data held in this indicator</param>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(IReadOnlyWindow <DataPointBar> window, DataPointBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _bodyLongAveragePeriod - 1 && Samples < Period - 1)
                {
                    _bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
                }

                if (Samples >= Period - _bodyShortAveragePeriod)
                {
                    _bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
                }

                return(0m);
            }

            decimal value;

            if (
                // 1st: long
                GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[1]) &&
                // 2nd: short
                GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
                //      engulfed by 1st
                Math.Max(input.Close, input.Open) < Math.Max(window[1].Close, window[1].Open) &&
                Math.Min(input.Close, input.Open) > Math.Min(window[1].Close, window[1].Open)
                )
            {
                value = -(int)GetCandleColor(window[1]);
            }
            else
            {
                value = 0m;
            }

            // add the current range and subtract the first range: this is done after the pattern recognition
            // when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)

            _bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]) -
                                    GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod + 1]);

            _bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
                                     GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);

            return(value);
        }
예제 #29
0
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="window">The window of data held in this indicator</param>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(IReadOnlyWindow <DataPointBar> window, DataPointBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _bodyShortAveragePeriod)
                {
                    _bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
                }

                if (Samples >= Period - _shadowLongAveragePeriod)
                {
                    _shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input);
                }

                if (Samples >= Period - _shadowVeryShortAveragePeriod)
                {
                    _shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
                }

                return(0m);
            }

            decimal value;

            if (
                // small rb
                GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
                // long upper shadow
                GetUpperShadow(input) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal, input) &&
                // very short lower shadow
                GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input) &&
                // gap up
                GetRealBodyGapUp(input, window[1])
                )
            {
                value = -1m;
            }
            else
            {
                value = 0m;
            }

            // add the current range and subtract the first range: this is done after the pattern recognition
            // when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)

            _bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input) -
                                     GetCandleRange(CandleSettingType.BodyShort, window[_bodyShortAveragePeriod]);

            _shadowLongPeriodTotal += GetCandleRange(CandleSettingType.ShadowLong, input) -
                                      GetCandleRange(CandleSettingType.ShadowLong, window[_shadowLongAveragePeriod]);

            _shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input) -
                                           GetCandleRange(CandleSettingType.ShadowVeryShort, window[_shadowVeryShortAveragePeriod]);

            return(value);
        }
예제 #30
0
        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="window">The window of data held in this indicator</param>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(IReadOnlyWindow <DataPointBar> window, DataPointBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _bodyDojiAveragePeriod)
                {
                    _bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
                }

                return(0m);
            }

            var value = GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, input) ? 1m : 0m;

            // add the current range and subtract the first range: this is done after the pattern recognition
            // when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)

            _bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input) -
                                    GetCandleRange(CandleSettingType.BodyDoji, window[_bodyDojiAveragePeriod]);

            return(value);
        }