예제 #1
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(IBaseDataBar input)
        {
            var deMax = 0m;
            var deMin = 0m;

            if (Samples > 1)
            {
                // By default, DeMin and DeMax must be 0m initially
                deMax = Math.Max(input.High - _lastHigh, 0);
                deMin = Math.Max(_lastLow - input.Low, 0);
            }

            _maxMA.Update(input.Time, deMax);
            _minMA.Update(input.Time, deMin);
            _lastHigh = input.High;
            _lastLow  = input.Low;

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

            var currentValue = _maxMA + _minMA;

            return(currentValue > 0m ? _maxMA / currentValue : 0m);
        }
예제 #2
0
 /// <summary>
 /// Resets this indicator to its initial state
 /// </summary>
 public override void Reset()
 {
     _previous = null;
     _smoother.Reset();
     TrueRange.Reset();
     base.Reset();
 }
        /// <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(IBaseDataBar input)
        {
            AroonUp.Update(input.Time, input.High);
            AroonDown.Update(input.Time, input.Low);

            return(AroonUp - AroonDown);
        }
예제 #4
0
파일: HeikinAshi.cs 프로젝트: KwFung7/Lean
        /// <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(IBaseDataBar input)
        {
            if (!IsReady)
            {
                Open.Update(input.Time, (input.Open + input.Close) / 2);
                Close.Update(input.Time, (input.Open + input.High + input.Low + input.Close) / 4);
                High.Update(input.Time, input.High);
                Low.Update(input.Time, input.Low);
            }
            else
            {
                Open.Update(input.Time, (Open + Close) / 2);
                Close.Update(input.Time, (input.Open + input.High + input.Low + input.Close) / 4);
                High.Update(input.Time, Math.Max(input.High, Math.Max(Open, Close)));
                Low.Update(input.Time, Math.Min(input.Low, Math.Min(Open, Close)));
            }

            var volume = 0.0m;

            if (input is TradeBar)
            {
                volume = ((TradeBar)input).Volume;
            }
            else if (input is RenkoBar)
            {
                volume = ((RenkoBar)input).Volume;
            }
            Volume.Update(input.Time, volume);

            return(Close);
        }
예제 #5
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, IBaseDataBar input)
        {
            var stochK = _maximum.Samples >= (period + constantK - 1) ? _sumFastK / constantK : new decimal(0.0);

            _sumSlowK.Update(input.Time, stochK);
            return(stochK * 100);
        }
예제 #6
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(IBaseDataBar input)
        {
            _maximum.Update(new IndicatorDataPoint { Value = input.High });
            _minimum.Update(new IndicatorDataPoint { Value = input.Low });

            return (_maximum + _minimum) / 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(IBaseDataBar input)
        {
            _trueRange.Update(input);
            _directionalMovementPlus.Update(input);
            _directionalMovementMinus.Update(input);
            _smoothedTrueRange.Update(Current);
            _smoothedDirectionalMovementPlus.Update(Current);
            _smoothedDirectionalMovementMinus.Update(Current);
            _previousInput = input;

            PositiveDirectionalIndex.Update(Current);
            NegativeDirectionalIndex.Update(Current);

            var diff = Math.Abs(PositiveDirectionalIndex.Current.Value - NegativeDirectionalIndex.Current.Value);
            var sum  = PositiveDirectionalIndex.Current.Value + NegativeDirectionalIndex.Current.Value;

            if (sum == 0)
            {
                return(50m);
            }

            _averageDirectionalIndex.Update(input.EndTime, 100m * diff / sum);

            return(_averageDirectionalIndex.Current.Value);
        }
예제 #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(IBaseDataBar input)
        {
            _adx.Update(input);
            _adxHistory.Add(_adx);

            return((_adx + _adxHistory[Math.Min(_adxHistory.Count - 1, _period - 1)]) / 2);
        }
예제 #9
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _equalAveragePeriod)
                {
                    _equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
                }

                return 0m;
            }

            decimal value;
            if (
                // first black
                GetCandleColor(window[1]) == CandleColor.Black &&
                // second black
                GetCandleColor(input) == CandleColor.Black &&
                // 1st and 2nd same close
                input.Close <= window[1].Close + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
                input.Close >= window[1].Close - GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, 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)

            _equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]) -
                                 GetCandleRange(CandleSettingType.Equal, window[_equalAveragePeriod + 1]);

            return value;
        }
예제 #10
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(IBaseDataBar input)
        {
            _trueRange.Update(input);

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

            var buyingPressure = new IndicatorDataPoint { Value = 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.Current.Value / _sumTrueRange1.Current.Value;
            var average2 = _sumBuyingPressure2.Current.Value / _sumTrueRange2.Current.Value;
            var average3 = _sumBuyingPressure3.Current.Value / _sumTrueRange3.Current.Value;

            return 100m * (4 * average1 + 2 * average2 + average3) / 7;
        }
예제 #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</returns>
        protected override decimal ComputeNextValue(IBaseDataBar input)
        {
            if (_previousInputs.IsReady)
            {
                var a = input.Close - input.Open;
                var b = _previousInputs[0].Close - _previousInputs[0].Open;
                var c = _previousInputs[1].Close - _previousInputs[1].Open;
                var d = _previousInputs[2].Close - _previousInputs[2].Open;
                var e = input.High - input.Low;
                var f = _previousInputs[0].High - _previousInputs[0].Low;
                var g = _previousInputs[1].High - _previousInputs[1].Low;
                var h = _previousInputs[2].High - _previousInputs[2].Low;
                CloseBand.Update(input.Time, (a + 2 * (b + c) + d) / 6);
                RangeBand.Update(input.Time, (e + 2 * (f + g) + h) / 6);

                if (CloseBand.IsReady && RangeBand.IsReady && RangeBand != 0m)
                {
                    _previousInputs.Add(input);
                    var rvi = CloseBand / RangeBand;
                    Signal?.Update(input.Time, rvi); // Checks for null before updating.
                    return(rvi);
                }
            }

            _previousInputs.Add(input);
            return(0m);
        }
예제 #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(IBaseDataBar 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);
        }
예제 #13
0
        protected override decimal ComputeNextValue(IBaseDataBar input)
        {
            _bars.Add(input);

            if (!_bars.IsReady)
            {
                return(0m);
            }

            double beta  = Math.Cos(2 * Math.PI / _period);
            double gamma = (1 / Math.Cos(4 * Math.PI * (double)_delta / _period));
            double alpha = gamma - Math.Sqrt(Math.Pow(gamma, 2) - 1);
            double p0    = (double)(_bars[0].High + _bars[0].Low) / 2;
            double p2    = (double)(_bars[2].High + _bars[2].Low) / 2;
            double bp    = _bps.IsReady ? 0.5 * (1 - alpha) * (p0 - p2) + beta * (1 + alpha) * _bps[0] - alpha * _bps[1] : 0.5 * (1 - alpha) * (p0 - p2);

            _bps.Add(bp);
            _bpMA.Update(input.Time, (decimal)bp);

            if (!_bps.IsReady)
            {
                return(0m);
            }

            double peak   = _bps[1] > _bps[0] && _bps[1] > _bps[2] ? _bps[1] : (double)_peak.Current.Value;
            double valley = _bps[1] < _bps[0] && _bps[1] < _bps[2] ? _bps[1] : (double)_valley.Current.Value;

            _peak.Update(input.Time, (decimal)peak);
            _valley.Update(input.Time, (decimal)valley);
            _peakMA.Update(input.Time, (decimal)peak);
            _valleyMA.Update(input.Time, (decimal)valley);

            return(_bpMA.IsReady ? _bpMA : 0m);
        }
예제 #14
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(IBaseDataBar 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 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 wil 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(IBaseDataBar input)
        {
            var x     = 0.0;
            var y     = 0.0;
            var price = (input.Low + input.High) / 2m;

            _medianMin.Update(input.Time, price);
            _medianMax.Update(input.Time, price);

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

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

            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.Value);
        }
예제 #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(IBaseDataBar input)
        {
            _trueRange.Update(input);

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

            var buyingPressure = new IndicatorDataPoint { Value = 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;
        }
예제 #17
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(IBaseDataBar 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;
        }
예제 #18
0
        protected override decimal ComputeNextValue(IBaseDataBar input)
        {
            _low.Update(input.EndTime, input.Low);
            _atr.Update(input);

            return((input.High - _low) / (_atr * _sqrtPeriod));
        }
예제 #19
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _bodyShortAveragePeriod)
                {
                    _bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
                }

                return 0m;
            }

            decimal value;
            if (GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
                GetUpperShadow(input) > GetRealBody(input) &&
                GetLowerShadow(input) > GetRealBody(input)
              )
                value = (int)GetCandleColor(input);
            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]);

            return value;
        }
예제 #20
0
파일: Hammer.cs 프로젝트: AlexCatarino/Lean
        /// <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<IBaseDataBar> window, IBaseDataBar 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);
                }

                if (Samples >= Period - _nearAveragePeriod - 1 && Samples < Period - 1)
                {
                    _nearPeriodTotal += GetCandleRange(CandleSettingType.Near, input);
                }

                return 0m;
            }

            decimal value;
            if (
                // small rb
                GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
                // long lower shadow
                GetLowerShadow(input) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal, input) &&
                // very short upper shadow
                GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input) &&
                // rb near the prior candle's lows
                Math.Min(input.Close, input.Open) <= window[1].Low + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, 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]);

            _nearPeriodTotal += GetCandleRange(CandleSettingType.Near, window[1]) -
                                GetCandleRange(CandleSettingType.Near, window[_nearAveragePeriod + 1]);

            return value;
        }
예제 #21
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _nearAveragePeriod)
                {
                    _nearPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
                }

                return 0m;
            }

            decimal value;
            if (
                (
                    // upside gap    
                    GetRealBodyGapUp(window[1], window[2]) &&
                    // 1st: white
                    GetCandleColor(window[1]) == CandleColor.White &&
                    // 2nd: black
                    GetCandleColor(input) == CandleColor.Black &&
                    //      that opens within the white rb
                    input.Open < window[1].Close && input.Open > window[1].Open &&
                    //      and closes under the white rb
                    input.Close < window[1].Open &&
                    //      inside the gap
                    input.Close > Math.Max(window[2].Close, window[2].Open) &&
                    // size of 2 rb near the same
                    Math.Abs(GetRealBody(window[1]) - GetRealBody(input)) < GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[1])
                ) ||
                (
                    // downside gap
                    GetRealBodyGapDown(window[1], window[2]) &&
                    // 1st: black
                    GetCandleColor(window[1]) == CandleColor.Black &&
                    // 2nd: white
                    GetCandleColor(input) == CandleColor.White &&
                    //      that opens within the black rb
                    input.Open < window[1].Open && input.Open > window[1].Close &&
                    //      and closes above the black rb
                    input.Close > window[1].Open &&
                    //      inside the gap
                    input.Close < Math.Min(window[2].Close, window[2].Open) &&
                    // size of 2 rb near the same
                    Math.Abs(GetRealBody(window[1]) - GetRealBody(input)) < GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[1])
                )
              )
                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)

            _nearPeriodTotal += GetCandleRange(CandleSettingType.Near, window[1]) -
                                GetCandleRange(CandleSettingType.Near, window[_nearAveragePeriod + 1]);

            return value;
        }
예제 #22
0
 private decimal AdjustedAverage(
     decimal currentAvg,
     int numPeriods,
     IBaseDataBar oldBar,
     IBaseDataBar newBar)
 {
     return(AdjustedAverage(currentAvg, numPeriods, Value(oldBar), Value(newBar)));
 }
예제 #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>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(IBaseDataBar input)
        {
            // compute the true range and then send it to our smoother
            TrueRange.Update(input);
            _smoother.Update(input.Time, TrueRange);

            return(_smoother.Current.Value);
        }
예제 #24
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(IBaseDataBar input)
        {
            var presentValue = (input.High + input.Low) / 2;

            SlowAo.Update(input.Time, presentValue);
            FastAo.Update(input.Time, presentValue);

            return(IsReady ? FastAo - SlowAo : 0m);
        }
예제 #25
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(IBaseDataBar input)
 {
     _maximum.Update(input.Time, input.High);
     _mininum.Update(input.Time, input.Low);
     FastStoch.Update(input);
     StochK.Update(input);
     StochD.Update(input);
     return(FastStoch);
 }
예제 #26
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _bodyDojiAveragePeriod)
                {
                    _bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
                }

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

                if (Samples >= Period - _nearAveragePeriod)
                {
                    _nearPeriodTotal += GetCandleRange(CandleSettingType.Near, input);
                }

                return 0m;
            }

            decimal value;
            if (
                // doji
                GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, input) &&
                // long shadow
                GetLowerShadow(input) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal, input) &&
                // long shadow
                GetUpperShadow(input) > GetCandleAverage(CandleSettingType.ShadowLong, _shadowLongPeriodTotal, input) &&
                // body near midpoint
                (
                    Math.Min(input.Open, input.Close)
                        <= input.Low + GetHighLowRange(input) / 2 + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, input)
                    &&
                    Math.Max(input.Open, input.Close)
                        >= input.Low + GetHighLowRange(input) / 2 - GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, input)
                )
              )
                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)

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

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

            _nearPeriodTotal += GetCandleRange(CandleSettingType.Near, input) -
                                GetCandleRange(CandleSettingType.Near, window[_nearAveragePeriod]);

            return value;
        }
예제 #27
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _shadowVeryShortAveragePeriod)
                {
                    _shadowVeryShortPeriodTotal[2] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[2]);
                    _shadowVeryShortPeriodTotal[1] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]);
                    _shadowVeryShortPeriodTotal[0] += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
                }

                return 0m;
            }

            decimal value;
            if (
                // white
                GetCandleColor(window[3]) == CandleColor.White &&
                // 1st black
                GetCandleColor(window[2]) == CandleColor.Black &&
                // very short lower shadow
                GetLowerShadow(window[2]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[2], window[2]) &&
                // 2nd black
                GetCandleColor(window[1]) == CandleColor.Black &&
                // very short lower shadow
                GetLowerShadow(window[1]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[1], window[1]) &&
                // 3rd black
                GetCandleColor(input) == CandleColor.Black &&
                // very short lower shadow
                GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[0], input) &&
                // 2nd black opens within 1st black's rb
                window[1].Open < window[2].Open && window[1].Open > window[2].Close &&
                // 3rd black opens within 2nd black's rb
                input.Open < window[1].Open && input.Open > window[1].Close &&
                // 1st black closes under prior candle's high
                window[3].High > window[2].Close &&
                // three declining
                window[2].Close > window[1].Close &&
                // three declining
                window[1].Close > input.Close
              )
                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)

            for (var i = 2; i >= 0; i--)
            {
                _shadowVeryShortPeriodTotal[i] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[i]) -
                                                  GetCandleRange(CandleSettingType.ShadowVeryShort, window[i + _shadowVeryShortAveragePeriod]);
            }

            return value;
        }
예제 #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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _shadowVeryShortAveragePeriod)
                {
                    _shadowVeryShortPeriodTotal[1] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]);
                    _shadowVeryShortPeriodTotal[0] += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
                }

                if (Samples >= Period - _bodyLongAveragePeriod)
                {
                    _bodyLongPeriodTotal[1] += GetCandleRange(CandleSettingType.BodyLong, window[1]);
                    _bodyLongPeriodTotal[0] += GetCandleRange(CandleSettingType.BodyLong, input);
                }

                return 0m;
            }

            decimal value;
            if (
                // opposite candles
                (int)GetCandleColor(window[1]) == -(int)GetCandleColor(input) &&
                // 1st marubozu
                GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal[1], window[1]) &&
                GetUpperShadow(window[1]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[1], window[1]) &&
                GetLowerShadow(window[1]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[1], window[1]) &&
                // 2nd marubozu
                GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal[0], input) &&
                GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[0], input) &&
                GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[0], input) &&
                // gap
                (
                  (GetCandleColor(window[1]) == CandleColor.Black && GetCandleGapUp(input, window[1]))
                  ||
                  (GetCandleColor(window[1]) == CandleColor.White && GetCandleGapDown(input, window[1]))
                )
              )
                value = (int)GetCandleColor(input);
            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)

            for (var i = 1; i >= 0; i--)
            {
                _shadowVeryShortPeriodTotal[i] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[i]) -
                                                  GetCandleRange(CandleSettingType.ShadowVeryShort, window[i + _shadowVeryShortAveragePeriod]);

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

            return value;
        }
예제 #29
0
 /// <summary>
 /// Computes the positive directional movement.
 /// </summary>
 /// <param name="input">The input.</param>
 /// <returns></returns>
 private decimal ComputePositiveDirectionalMovement(IBaseDataBar input)
 {
     if (_previousInput != null &&
         input.High > _previousInput.High &&
         input.High - _previousInput.High >= _previousInput.Low - input.Low)
     {
         return(input.High - _previousInput.High);
     }
     return(0m);
 }
예제 #30
0
 /// <summary>
 /// Computes the negative directional movement.
 /// </summary>
 /// <param name="input">The input.</param>
 /// <returns></returns>
 private decimal ComputeNegativeDirectionalMovement(IBaseDataBar input)
 {
     if (_previousInput != null &&
         _previousInput.Low > input.Low &&
         _previousInput.Low - input.Low > input.High - _previousInput.High)
     {
         return(_previousInput.Low - input.Low);
     }
     return(0m);
 }
예제 #31
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(IBaseDataBar 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);
        }
예제 #32
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(IBaseDataBar input)
        {
            ADX.Update(input);

            if (ADX.IsReady)
            {
                _adxHistory.Add(ADX.Current.Value);
            }

            return(IsReady ? (ADX.Current.Value + _adxHistory[_period - 1]) / 2 : 50m);
        }
예제 #33
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(IBaseDataBar input)
        {
            _maximum.Update(new IndicatorDataPoint {
                Value = input.High
            });
            _minimum.Update(new IndicatorDataPoint {
                Value = input.Low
            });

            return((_maximum + _minimum) / 2);
        }
예제 #34
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(IBaseDataBar input)
        {
            _adx.Update(input);

            if (_adx.IsReady)
            {
                _adxHistory.Add(_adx);
            }

            return(IsReady ? (_adx + _adxHistory[_period - 1]) / 2 : 50m);
        }
예제 #35
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(IBaseDataBar input)
        {
            if (_previousInput != null)
            {
                UpperBand.Update(new IndicatorDataPoint(_previousInput.Time, _previousInput.High));
                LowerBand.Update(new IndicatorDataPoint(_previousInput.Time, _previousInput.Low));
            }

            _previousInput = input;
            return (UpperBand.Current.Value + LowerBand.Current.Value) / 2;
        }
예제 #36
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _shadowVeryShortAveragePeriod)
                {
                    _shadowVeryShortPeriodTotal[3] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[3]);
                    _shadowVeryShortPeriodTotal[2] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[2]);
                    _shadowVeryShortPeriodTotal[1] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]);
                }

                return 0m;
            }

            decimal value;
            if (
                // 1st black
                GetCandleColor(window[3]) == CandleColor.Black &&
                // 2nd black
                GetCandleColor(window[2]) == CandleColor.Black &&
                // 3rd black
                GetCandleColor(window[1]) == CandleColor.Black &&
                // 4th black
                GetCandleColor(input) == CandleColor.Black &&
                // 1st: marubozu
                GetLowerShadow(window[3]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[3], window[3]) &&
                GetUpperShadow(window[3]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[3], window[3]) &&
                // 2nd: marubozu
                GetLowerShadow(window[2]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[2], window[2]) &&
                GetUpperShadow(window[2]) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[2], window[2]) &&
                // 3rd: opens gapping down
                GetRealBodyGapDown(window[1], window[2]) &&
                //      and has an upper shadow
                GetUpperShadow(window[1]) > GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal[1], window[1]) &&
                //      that extends into the prior body
                window[1].High > window[2].Close &&
                // 4th: engulfs the 3rd including the shadows
                input.High > window[1].High && input.Low < window[1].Low
              )
                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)

            for (var i = 3; i >= 1; i--)
            {
                _shadowVeryShortPeriodTotal[i] += GetCandleRange(CandleSettingType.ShadowVeryShort, window[i]) -
                                                  GetCandleRange(CandleSettingType.ShadowVeryShort, window[i + _shadowVeryShortAveragePeriod]);
            }

            return value;
        }
예제 #37
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(IBaseDataBar input)
        {
            Minimum.Update(input.Time, input.Low);
            Maximum.Update(input.Time, input.High);

            if (!this.IsReady) return 0;
           
            var range = (Maximum.Current.Value - Minimum.Current.Value);

            return range == 0 ? 0 : -100m*(Maximum.Current.Value - input.Close)/range;
        }
예제 #38
0
        protected override decimal ComputeNextValue(IBaseDataBar input)
        {
            _ema.Update(input.EndTime, input.Close);
            _delayedEMA.Update(_ema.Current);

            var zlema = (_k * ((2 * _ema) - _delayedEMA)) + ((1 - _k) * _delayedZLEMA);

            _delayedZLEMA.Update(input.EndTime, zlema);

            return(zlema);
        }
        /// <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(IBaseDataBar input)
        {
            if (_previousInput != null)
            {
                UpperBand.Update(new IndicatorDataPoint(_previousInput.Time, _previousInput.High));
                LowerBand.Update(new IndicatorDataPoint(_previousInput.Time, _previousInput.Low));
            }

            _previousInput = input;
            return((UpperBand.Current.Value + LowerBand.Current.Value) / 2);
        }
예제 #40
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(IBaseDataBar input)
        {
            if (_previousInput != null)
            {
                UpperBand.Update(_previousInput.Time, _previousInput.High);
                LowerBand.Update(_previousInput.Time, _previousInput.Low);
            }

            _previousInput = input;
            return((UpperBand + LowerBand) / 2);
        }
예제 #41
0
        protected override decimal ComputeNextValue(IBaseDataBar input)
        {
            _macd.Update(input.EndTime, input.Close);

            if (!_macd.IsReady)
            {
                return(0m);
            }

            var macdBar = new TradeBar
            {
                Time    = input.Time,
                EndTime = input.EndTime,
                Open    = _macd,
                High    = _macd,
                Low     = _macd,
                Close   = _macd
            };

            _frac1.Update(macdBar);

            if (!_frac1.IsReady)
            {
                return(0m);
            }

            var pf = _pf.IsReady ? _pf + (_factor * (_frac1.FastStoch - _pf)) : _frac1.FastStoch;

            _pf.Update(input.Time, pf);

            var pfBar = new TradeBar
            {
                Time    = input.Time,
                EndTime = input.EndTime,
                Open    = pf,
                High    = pf,
                Low     = pf,
                Close   = pf
            };

            _frac2.Update(pfBar);

            if (!_frac2.IsReady)
            {
                return(0m);
            }

            var pff = _pff.IsReady ? _pff + (_factor * (_frac2.FastStoch - _pff)) : _frac2.FastStoch;

            _pff.Update(input.Time, pff);

            return(pff);
        }
예제 #42
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();
 }
예제 #43
0
        /// <summary>
        /// Computes the True Range value.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns></returns>
        private decimal ComputeTrueRange(IBaseDataBar input)
        {
            if (_previousInput == null)
            {
                return(0m);
            }

            var range1 = input.High - input.Low;
            var range2 = Math.Abs(input.High - _previousInput.Close);
            var range3 = Math.Abs(input.Low - _previousInput.Close);

            return(Math.Max(range1, Math.Max(range2, range3)));
        }
예제 #44
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _bodyLongAveragePeriod - 2 && Samples < Period - 2)
                {
                    _bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
                }

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

                return 0m;
            }

            decimal value;
            if (
                // 1st: long
                GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
                //      black
                GetCandleColor(window[2]) == CandleColor.Black &&
                // 2nd: black
                GetCandleColor(window[1]) == CandleColor.Black &&
                //      harami
                window[1].Close > window[2].Close && window[1].Open <= window[2].Open &&
                //      lower low
                window[1].Low < window[2].Low &&
                // 3rd: short
                GetRealBody(input) < GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
                //      white
                GetCandleColor(input) == CandleColor.White &&
                //      open not lower
                input.Open > window[1].Low
              )
                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)

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

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

            return value;
        }
예제 #45
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _bodyLongAveragePeriod - 2 && Samples < Period - 2)
                {
                    _bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
                }

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

                return 0m;
            }

            decimal value;
            if (
                // 1st: white
                GetCandleColor(window[2]) == CandleColor.White &&
                //      long
                GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
                // 2nd: black
                GetCandleColor(window[1]) == CandleColor.Black &&
                //      short
                GetRealBody(window[1]) <= GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, window[1]) &&
                //      gapping up
                GetRealBodyGapUp(window[1], window[2]) &&
                // 3rd: black
                GetCandleColor(input) == CandleColor.Black &&
                // 3rd: engulfing prior rb
                input.Open > window[1].Open && input.Close < window[1].Close &&
                //      closing above 1st
                input.Close > window[2].Close
              )
                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)

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

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

            return value;
        }
예제 #46
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _nearAveragePeriod)
                {
                    _nearPeriodTotal += GetCandleRange(CandleSettingType.Near, window[1]);
                }

                if (Samples >= Period - _equalAveragePeriod)
                {
                    _equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
                }

                return 0m;
            }

            decimal value;
            if (
                ( // upside or downside gap between the 1st candle and both the next 2 candles
                  (GetRealBodyGapUp(window[1], window[2]) && GetRealBodyGapUp(input, window[2]))
                  ||
                  (GetRealBodyGapDown(window[1], window[2]) && GetRealBodyGapDown(input, window[2]))
                ) &&
                // 2nd: white
                GetCandleColor(window[1]) == CandleColor.White &&
                // 3rd: white
                GetCandleColor(input) == CandleColor.White &&
                // same size 2 and 3
                GetRealBody(input) >= GetRealBody(window[1]) - GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[1]) &&
                GetRealBody(input) <= GetRealBody(window[1]) + GetCandleAverage(CandleSettingType.Near, _nearPeriodTotal, window[1]) &&
                // same open 2 and 3
                input.Open >= window[1].Open - GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
                input.Open <= window[1].Open + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1])
              )
                value = GetRealBodyGapUp(window[1], window[2]) ? 1m : -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)

            _nearPeriodTotal += GetCandleRange(CandleSettingType.Near, window[1]) -
                                GetCandleRange(CandleSettingType.Near, window[1 + _nearAveragePeriod]);

            _equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]) -
                                 GetCandleRange(CandleSettingType.Equal, window[1 + _equalAveragePeriod]);

            return value;
        }
예제 #47
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _equalAveragePeriod)
                {
                    _equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
                }

                if (Samples >= Period - _bodyLongAveragePeriod)
                {
                    _bodyLongPeriodTotal[1] += GetCandleRange(CandleSettingType.BodyLong, window[1]);
                    _bodyLongPeriodTotal[0] += GetCandleRange(CandleSettingType.BodyLong, input);
                }

                return 0m;
            }

            decimal value;
            if (
                // opposite candles
                (int)GetCandleColor(window[1]) == -(int)GetCandleColor(input) &&
                // 1st long
                GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal[1], window[1]) &&
                // 2nd long
                GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal[0], input) &&
                // equal closes
                input.Close <= window[1].Close + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
                input.Close >= window[1].Close - GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1])
              )
                value = (int)GetCandleColor(input);
            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)

            _equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, input) -
                                 GetCandleRange(CandleSettingType.Equal, window[_equalAveragePeriod + 1]);

            for (var i = 1; i >= 0; i--)
            {
                _bodyLongPeriodTotal[i] += GetCandleRange(CandleSettingType.BodyLong, window[i]) -
                                           GetCandleRange(CandleSettingType.BodyLong, window[i + _bodyLongAveragePeriod]);
            }

            return value;
        }
        /// <summary>
        /// Computes the average value
        /// </summary>
        /// <param name="input">The data for the calculation</param>
        /// <returns>The average value</returns>
        protected override decimal ComputeNextValue(IBaseDataBar 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.IsReady)
            {
                _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;

        }
예제 #49
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _bodyDojiAveragePeriod - 2 && Samples < Period - 2)
                {
                    _bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
                }

                return 0m;
            }

            decimal value;
            if (
                // 1st: doji
                GetRealBody(window[2]) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, window[2]) &&
                // 2nd: doji
                GetRealBody(window[1]) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, window[2]) &&
                // 3rd: doji
                GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, window[2]))
            {     
                value = 0;
                if (
                    // 2nd gaps up
                    GetRealBodyGapUp(window[1], window[2]) &&
                    // 3rd is not higher than 2nd
                    Math.Max(input.Open, input.Close) < Math.Max(window[1].Open, window[1].Close)
                   )
                    value = -1m;
                if (
                    // 2nd gaps down
                    GetRealBodyGapDown(window[1], window[2]) &&
                    // 3rd is not lower than 2nd 
                    Math.Min(input.Open, input.Close) > Math.Min(window[1].Open, window[1].Close)
                   )
                    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)

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

            return value;
        }
예제 #50
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _bodyLongAveragePeriod - 2 && Samples < Period - 2)
                {
                    _bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
                }

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

                return 0m;
            }

            decimal value;
            if (
                // 1st: long
                GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
                // 2nd: short
                GetRealBody(window[1]) <= GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, window[1]) &&
                //      engulfed by 1st
                Math.Max(window[1].Close, window[1].Open) < Math.Max(window[2].Close, window[2].Open) &&
                Math.Min(window[1].Close, window[1].Open) > Math.Min(window[2].Close, window[2].Open) &&
                // 3rd: opposite to 1st
                ((GetCandleColor(window[2]) == CandleColor.White && GetCandleColor(input) == CandleColor.Black && input.Close < window[2].Open) ||
                  //      and closing out
                  (GetCandleColor(window[2]) == CandleColor.Black && GetCandleColor(input) == CandleColor.White && input.Close > window[2].Open)
                )
              )
                value = -(int)GetCandleColor(window[2]);
            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[2]) -
                                    GetCandleRange(CandleSettingType.BodyLong, window[2 + _bodyLongAveragePeriod]);

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

            return value;
        }
예제 #51
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _equalAveragePeriod)
                {
                    _equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
                }

                if (Samples >= Period - _bodyLongAveragePeriod)
                {
                    _bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[1]);
                }

                return 0m;
            }

            decimal value;
            if (
                // 1st: black
                GetCandleColor(window[1]) == CandleColor.Black &&
                //      long
                GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[1]) &&
                // 2nd: white
                GetCandleColor(input) == CandleColor.White &&
                //      open below prior low
                input.Open < window[1].Low &&
                //      close into prior body
                input.Close > window[1].Close + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
                //      under the midpoint
                input.Close <= window[1].Close + GetRealBody(window[1]) * 0.5m
              )
                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)

            _equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]) -
                                 GetCandleRange(CandleSettingType.Equal, window[_equalAveragePeriod + 1]);

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

            return value;
        }
예제 #52
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _shadowVeryShortAveragePeriod)
                {
                    _shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, window[1]);
                }

                return 0m;
            }

            decimal value;
            if (
                // 3 black candlesticks
                GetCandleColor(window[4]) == CandleColor.Black && 
                GetCandleColor(window[3]) == CandleColor.Black && 
                GetCandleColor(window[2]) == CandleColor.Black &&
                // with consecutively lower opens
                window[4].Open > window[3].Open && window[3].Open > window[2].Open &&
                // and closes
                window[4].Close > window[3].Close && window[3].Close > window[2].Close &&
                // 4th: black with an upper shadow
                GetCandleColor(window[1]) == CandleColor.Black &&
                GetUpperShadow(window[1]) > GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, window[1]) &&
                // 5th: white
                GetCandleColor(input) == CandleColor.White &&
                // that opens above prior candle's body
                input.Open > window[1].Open &&
                // and closes above prior candle's high
                input.Close > window[1].High
              )
                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)

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

            return value;
        }
예제 #53
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _bodyLongAveragePeriod - 1 && Samples < Period - 1)
                {
                    _bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
                }

                if (Samples >= Period - _bodyDojiAveragePeriod)
                {
                    _bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
                }

                return 0m;
            }

            decimal value;
            if (
                // 1st: long real body
                GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[1]) &&
                // 2nd: doji
                GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, input) &&
                //      that gaps up if 1st is white
                ((GetCandleColor(window[1]) == CandleColor.White && GetRealBodyGapUp(input, window[1]))
                    ||
                    //      or down if 1st is black
                    (GetCandleColor(window[1]) == CandleColor.Black && GetRealBodyGapDown(input, window[1]))
                ))
                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]);

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

            return value;
        }
예제 #54
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _bodyLongAveragePeriod - 1 && Samples < Period - 1)
                {
                    _bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
                }

                if (Samples >= Period - _bodyDojiAveragePeriod)
                {
                    _bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, input);
                }

                return 0m;
            }

            decimal value;
            if (
                // 1st: long
                GetRealBody(window[1]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[1]) &&
                // 2nd: doji
                GetRealBody(input) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, 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]);

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

            return value;
        }
예제 #55
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(IBaseDataBar 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;
        }
예제 #56
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                return 0m;
            }

            decimal value;
            if (
                // 1st and 2nd of same color
                GetCandleColor(window[2]) == GetCandleColor(window[1]) &&
                // 3rd opposite color
                (int)GetCandleColor(window[1]) == -(int)GetCandleColor(input) &&
                // 3rd opens within 2nd rb
                input.Open < Math.Max(window[1].Close, window[1].Open) &&
                input.Open > Math.Min(window[1].Close, window[1].Open) &&
                // 3rd closes within 1st rb
                input.Close < Math.Max(window[2].Close, window[2].Open) &&
                input.Close > Math.Min(window[2].Close, window[2].Open) &&
                ((
                    // when 1st is white
                    GetCandleColor(window[2]) == CandleColor.White &&
                    // upside gap
                    GetRealBodyGapUp(window[1], window[2])
                  ) ||
                  (
                    // when 1st is black
                    GetCandleColor(window[2]) == CandleColor.Black &&
                    // downside gap
                    GetRealBodyGapDown(window[1], window[2])
                  )
                )
            )
                value = (int)GetCandleColor(window[2]);
            else
                value = 0;

            return value;
        }
예제 #57
0
파일: Doji.cs 프로젝트: AlexCatarino/Lean
        /// <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<IBaseDataBar> window, IBaseDataBar 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;
        }
        /// <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(IBaseDataBar 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;
        }
예제 #59
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples >= Period - _shadowVeryShortAveragePeriod)
                {
                    _shadowVeryShortPeriodTotal += GetCandleRange(CandleSettingType.ShadowVeryShort, input);
                }

                if (Samples >= Period - _bodyLongAveragePeriod)
                {
                    _bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, input);
                }

                if (Samples >= Period - _equalAveragePeriod)
                {
                    _equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]);
                }

                return 0m;
            }

            decimal value;
            if (
                // opposite candles
                (int)GetCandleColor(window[1]) == -(int)GetCandleColor(input) &&
                // same open
                input.Open <= window[1].Open + GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
                input.Open >= window[1].Open - GetCandleAverage(CandleSettingType.Equal, _equalPeriodTotal, window[1]) &&
                // belt hold: long body
                GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, input) &&
                (
                  // with no lower shadow if bullish
                  (GetCandleColor(input) == CandleColor.White &&
                    GetLowerShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input)
                  )
                  ||
                  // with no upper shadow if bearish
                  (GetCandleColor(input) == CandleColor.Black &&
                    GetUpperShadow(input) < GetCandleAverage(CandleSettingType.ShadowVeryShort, _shadowVeryShortPeriodTotal, input)
                  )
                )
              )
                value = (int)GetCandleColor(input);
            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)

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

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

            _equalPeriodTotal += GetCandleRange(CandleSettingType.Equal, window[1]) -
                                 GetCandleRange(CandleSettingType.Equal, window[_equalAveragePeriod + 1]);

            return value;
        }
예제 #60
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<IBaseDataBar> window, IBaseDataBar input)
        {
            if (!IsReady)
            {
                if (Samples > Period - _bodyLongAveragePeriod)
                {
                    _bodyLongPeriodTotal += GetCandleRange(CandleSettingType.BodyLong, window[2]);
                }
                if (Samples > Period - _bodyDojiAveragePeriod)
                {
                    _bodyDojiPeriodTotal += GetCandleRange(CandleSettingType.BodyDoji, window[1]);
                }
                if (Samples > Period - _bodyShortAveragePeriod)
                {
                    _bodyShortPeriodTotal += GetCandleRange(CandleSettingType.BodyShort, input);
                }

                return 0m;
            }

            decimal value;
            if (
                // 1st: long
                GetRealBody(window[2]) > GetCandleAverage(CandleSettingType.BodyLong, _bodyLongPeriodTotal, window[2]) &&
                // 2nd: doji
                GetRealBody(window[1]) <= GetCandleAverage(CandleSettingType.BodyDoji, _bodyDojiPeriodTotal, window[1]) &&
                // 3rd: longer than short
                GetRealBody(input) > GetCandleAverage(CandleSettingType.BodyShort, _bodyShortPeriodTotal, input) &&
                ((
                    // 1st white
                    GetCandleColor(window[2]) == CandleColor.White &&
                    // 3rd black
                    GetCandleColor(input) == CandleColor.Black &&
                    // 3rd closes well within 1st rb
                    input.Close < window[2].Close - GetRealBody(window[2]) * _penetration &&
                    // upside gap between 1st and 2nd
                    GetCandleGapUp(window[1], window[2]) &&
                    // downside gap between 2nd and 3rd
                    GetCandleGapDown(input, window[1])
                  )
                  ||
                  (
                    // 1st black
                    GetCandleColor(window[2]) == CandleColor.Black &&
                    // 3rd white
                    GetCandleColor(input) == CandleColor.White &&
                    // 3rd closes well within 1st rb
                    input.Close > window[2].Close + GetRealBody(window[2]) * _penetration &&
                    // downside gap between 1st and 2nd
                    GetCandleGapDown(window[1], window[2]) &&
                    // upside gap between 2nd and 3rd
                    GetCandleGapUp(input, window[1])
                  )
                )
              )
                value = (int)GetCandleColor(input);
            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[2]) -
                                    GetCandleRange(CandleSettingType.BodyLong, window[_bodyLongAveragePeriod - 1]);

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

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

            return value;
        }