/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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; }
/// <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); }
/// <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); }
/// <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; }
/// <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; }
/// <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); }
/// <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); }
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); }
/// <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); }
/// <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; }
/// <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; }
protected override decimal ComputeNextValue(IBaseDataBar input) { _low.Update(input.EndTime, input.Low); _atr.Update(input); return((input.High - _low) / (_atr * _sqrtPeriod)); }
/// <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; }
/// <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; }
/// <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; }
private decimal AdjustedAverage( decimal currentAvg, int numPeriods, IBaseDataBar oldBar, IBaseDataBar newBar) { return(AdjustedAverage(currentAvg, numPeriods, Value(oldBar), Value(newBar))); }
/// <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); }
/// <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); }
/// <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); }
/// <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; }
/// <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; }
/// <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; }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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; }
/// <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; }
/// <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; }
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); }
/// <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); }
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); }
/// <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(); }
/// <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))); }
/// <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; }
/// <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; }
/// <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; }
/// <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; }
/// <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; }
/// <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; }
/// <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; }
/// <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; }
/// <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; }
/// <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; }
/// <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; }
/// <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; }
/// <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; }
/// <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; }
/// <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; }