/// <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 for the indicator /// /// /// </summary> /// <param name="window"></param> /// <param name="input"></param> /// <returns></returns> /// <remarks> /// From Ehlers page 15 equation 2.7 and Easy Language code on page 34 figure 4.2 /// His formula is changed slightly because he uses _cycle[1] in the second line of the high /// pass filter. Easy Language creates the newest reading in the indicator before the formula is evaluated, /// so that _cycle[1] refers to "yesterday" (in daily parlance) and _cycle is the newly created /// reading with an implicit index of [0]. /// On the other had, Lean's Add method adds the result of the formula to the underlying list /// after it has been evaluated, so that "yesterday's" value in the formula is _cycle[0] not _cycle[1] as Ehlers says. ///After the Add _cycle[0] is the latest value and yesterday's value is _cycle[1] /// /// _smooth, on the other hand, has already been added, so I can use _smooth[1] to refer to "yesterday's" value ///Following is the high pass filter used for the instanteous trend /// I create the intermediate hfp variable for clarity in the code. ///</remarks> protected override decimal ComputeNextValue(IReadOnlyWindow <IndicatorDataPoint> window, IndicatorDataPoint input) { // for convenience var time = input.Time; if (barcount > 2) { _smooth.Add(idp(time, (window[0].Value + 2 * window[1].Value + window[2].Value / 6))); if (barcount < _period) { _cycle.Add(idp(time, (window[0].Value - 2 * window[1].Value + window[2].Value) / 4)); } else { // Calc the high pass filter _cycle value var hfp = (1 - a / 2) * (1 - a / 2) * (_smooth[0].Value - 2 * _smooth[1].Value + _smooth[2].Value) + 2 * (1 - a) * _cycle[0].Value - (1 - a) * (1 - a) * _cycle[1].Value; _cycle.Add(idp(time, hfp)); } } else { _smooth.Add(idp(time, window[0].Value)); _cycle.Add(idp(time, 0)); } barcount++; return(_cycle[0].Value); }
/// <summary> /// A Fisher Transform of Prices /// </summary> /// <param name="name">string - the name of the indicator</param> /// <param name="period">The number of periods for the indicator</param> public FisherTransform(string name, int period) : base(name, period) { // Initialize the local variables _maxHigh = new Maximum("MaxHigh", period); _minLow = new Minimum("MinLow", period); value1 = new RollingWindow <IndicatorDataPoint>(period); // add two minimum values to the value1 to get things started value1.Add(new IndicatorDataPoint(DateTime.MinValue, .0001m)); value1.Add(new IndicatorDataPoint(DateTime.MinValue, .0001m)); }
/// <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(IndicatorDataPoint input) { _price.Add((double)input.Price); if (_price.Samples == 1) { _price.Add(_price[0]); _price.Add(_price[0]); } double signal = _a0 * _c0 * (_b0 * _price[0] + _b1 * _price[1] + _b2 * _price[2]) + _a0 * (_a1 * _filt[0] + _a2 * _filt[1]); _filt.Add(signal); return((decimal)signal); }
protected override decimal ComputeNextValue(IndicatorDataPoint input) { double realPart = 0; double imagPart = 0; _prices.Add(input); if (!_prices.IsReady) { return(LeadDirection); } for (int i = 0; i < _period; i++) { double temp = (double)_prices[i].Value; realPart = realPart + temp * Math.Cos(2 * Math.PI * i / _period); imagPart = imagPart + temp * Math.Sin(2 * Math.PI * i / _period); } double phase1 = Math.Abs(realPart) > 0.001 ? Math.Atan(imagPart / realPart) : Math.PI / 2 * Math.Sign(imagPart); double phase2 = realPart < 0 ? phase1 + Math.PI : phase1; double phase = phase2 < 0 ? phase2 + 2 * Math.PI : phase2 > 2 * Math.PI ? phase2 - 2 * Math.PI : phase2; _sine.Update(input.EndTime, (decimal)Math.Cos(phase)); _lead.Update(input.EndTime, (decimal)Math.Cos(phase + Math.PI / 4)); _direction = _lead > _sine ? Direction.Up : _lead < _sine ? Direction.Down : _direction; return(LeadDirection); }
protected override decimal ComputeNextValue(TradeBar input) { _previousBars.Add(input); if (_previousBars.IsReady) { if (_previousBars[2].High > _previousBars[0].High && _previousBars[2].High > _previousBars[1].High && _previousBars[2].High > _previousBars[3].High && _previousBars[2].High > _previousBars[4].High) { _barryUp = input.High; } if (_previousBars[2].Low > _previousBars[0].Low && _previousBars[2].Low > _previousBars[1].Low && _previousBars[2].Low > _previousBars[3].Low && _previousBars[2].Low > _previousBars[4].Low) { _barryDown = input.Low; } } return(MidPoint); }
/// <summary> /// Computes the next value for this indicator from the given state. /// /// As this indicator is receiving data points from two different symbols, /// it's going to compute the next value when the amount of data points /// of each of them is the same. Otherwise, it will return the last beta /// value computed /// </summary> /// <param name="input">The input value of this indicator on this time step. /// It can be either from the target or the reference symbol</param> /// <returns>The beta value of the target used in relation with the reference</returns> protected override decimal ComputeNextValue(TradeBar input) { var inputSymbol = input.Symbol; if (inputSymbol == _targetSymbol) { _targetDataPoints.Add(input.Close); } else if (inputSymbol == _referenceSymbol) { _referenceDataPoints.Add(input.Close); } else { throw new Exception("The given symbol was not target or reference symbol"); } if (_targetDataPoints.Samples == _referenceDataPoints.Samples && _referenceDataPoints.Count > 1) { _targetReturns.Add(GetNewReturn(_targetDataPoints)); _referenceReturns.Add(GetNewReturn(_referenceDataPoints)); ComputeBeta(); } return(_beta); }
/// <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); }
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 for this indicator from the given state. /// </summary> /// <param name="window">The window of data held in this indicator</param> /// <param name="input">The input value to this indicator on this time step</param> /// <returns></returns> /// <remarks> /// The Hull moving average is a series of nested weighted moving averages. /// Using the LWMA custom function for calculating weighted moving averages, /// the Hull moving average can be calculated following the steps. /// ///1.Calculate the n periodweighted moving average of a series "=WMA(price for n periods)" ///2.Calculate the n/2 period weighted moving average of a series"=WMA(price for n/2 periods)". Round n/2 to the nearest whole number ///3.Create a time series with 2*WMA from Step 2 - WMA from Step 1 ///4.The HMA is the WMA of the series in Step 3. "=WMA(Step 3 outputs fo k period)" /// </remarks> protected override decimal ComputeNextValue(IReadOnlyWindow <IndicatorDataPoint> window, IndicatorDataPoint input) { _longWma.Update(input); _shortWma.Update(input); _smooth.Add(new IndicatorDataPoint(input.Time, 2 * _shortWma.Current.Value - _longWma.Current.Value)); _result.Update(new IndicatorDataPoint(input.Time, _smooth[0].Value)); return(_result.Current.Value); }
/// <summary> /// Invokes NewPivotPointFormed event /// </summary> private void OnNewPivotPointFormed(PivotPoint pivotPoint) { if (pivotPoint != null) { _windowPivotPoints.Add(pivotPoint); NewPivotPointFormed?.Invoke(this, new PivotPointsEventArgs(pivotPoint)); } }
/// <summary> /// Calculates the next value for the decycle /// </summary> /// <param name="window">the window for this indicator</param> /// <param name="input">the latest price to input into the trend</param> /// <returns>the computed value</returns> protected override decimal ComputeNextValue(IReadOnlyWindow <IndicatorDataPoint> window, IndicatorDataPoint input) { // for convenience DateTime time = input.Time; _price.Add(input); if (!_price.IsReady) { _decycle.Add(input); } else { decimal decycle = alpha / 2 * (_price[0] + _price[1]) + (1 - alpha) * _decycle[1]; _decycle.Add(idp(time, decycle)); } return(_decycle[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(TradeBar 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="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</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="window"></param> /// <param name="input">The input given to the indicator</param> /// <returns> /// A new value for this indicator /// </returns> protected override decimal ComputeNextValue(IReadOnlyWindow <IndicatorDataPoint> window, IndicatorDataPoint input) { if (window.Count >= 3) { _multipliedDiffWindow.Add((window[0] - window[1]) * (window[1] - window[2])); } // Estimate the indicator if less than 50% of observation are zero. Avoid division by // zero and estimations with few real observations in case of forward filled data. if (IsReady && _multipliedDiffWindow.Count(obs => obs == 0) < 0.5 * _multipliedDiffWindow.Count) { var mc = _multipliedDiffWindow.Count(obs => obs > 0); var mRc = _multipliedDiffWindow.Count(obs => obs < 0); return(100m * mc / (mc + mRc)); } return(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(TradeBar input) { // Save the bar for summing Bars.Add(input); // check if it is not ready add a 0 to the RviWindow if (!Bars.IsReady) { RviWindow.Add(new IndicatorDataPoint(input.EndTime, 0.0m)); } else { // Bars have been added, so Bars[0] is the current value of the input // Filter the Close - Open with a four-bar symetical FIR filter before the terms are summed. var v1 = ((Bars[0].Close - Bars[0].Open) + 2 * (Bars[1].Close - Bars[1].Open) + 2 * (Bars[2].Close - Bars[3].Open) + (Bars[3].Close - Bars[3].Open) / 6); value1.Add(new IndicatorDataPoint(input.EndTime, v1)); // Filter the High - Low with a four-bar symetical FIR filter before the terms are summed. var v2 = ((Bars[0].High - Bars[0].Low) + 2 * (Bars[1].High - Bars[1].Low) + 2 * (Bars[2].High - Bars[3].Low) + (Bars[3].High - Bars[3].Low) / 6); value2.Add(new IndicatorDataPoint(input.EndTime, v2)); // The numerator and denominator are summed independently decimal num = value1.Sum(point => point.Value); decimal denom = value2.Sum(point => point.Value); try { // The RVI is the ratio of the numerator to the denominator. Since // they are lagged by the same amount, due to the filtering, // the lag is removed by taking the ratio. RviWindow.Add(new IndicatorDataPoint(input.EndTime, num / denom)); } catch (DivideByZeroException zex) { throw new Exception(zex.Message + zex.StackTrace); } } return(RviWindow[0].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 = (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) { return(price); } var hh = _high.Take(_n / 2).Max(); var ll = _low.Take(_n / 2).Min(); var n1 = (hh - ll) / (_n / 2); hh = _high.Skip(_n / 2).Take(_n / 2).Max(); ll = _low.Skip(_n / 2).Take(_n / 2).Min(); var n2 = (hh - ll) / (_n / 2); var n3 = (_high.Max() - _low.Min()) / _n; double dimen = 0; if (n1 + n2 > 0 && n3 > 0) { dimen = Math.Log((n1 + n2) / n3) / Math.Log(2); } var alpha = (decimal)Math.Exp(_w * (dimen - 1)); if (alpha < .01m) { alpha = .01m; } if (alpha > 1) { alpha = 1; } return(alpha * price + (1 - alpha) * Current.Value); }
protected override decimal ComputeNextValue(TradeBar input) { _fractal.Add(input); if (!_fractal.IsReady) { return(MidPoint); } if (_fractal.IndexOfMax((bar, index) => bar.High) == _fractalMidIndex) { _barryUp = input.High; } if (_fractal.IndexOfMin((bar, index) => bar.Low) == _fractalMidIndex) { _barryDown = input.Low; } return(MidPoint); }
protected override decimal ComputeNextValue(IReadOnlyWindow <IndicatorDataPoint> window, IndicatorDataPoint input) { var stop = 0; var src = input.Value; if (src == Src.FirstOrDefault()) { return(xEma); } Src.Add(src); if (Src.IsReady) { //PFE = sqrt(pow(close - close[Length], 2) + 100) var s1 = Src.Skip(1).FirstOrDefault(); var sL = Src.LastOrDefault(); var perfL = src - sL; PFE = Math.Sqrt((double)(perfL * perfL) + 100); //C2C = sum(sqrt(pow((close - close[1]), 2) + 1), Length) var perf1 = src - s1; var tosum = Math.Sqrt((double)(perf1 * perf1) + 1); C2C.Add(tosum); //xFracEff = iff(close - close[Length] > 0, round((PFE / C2C) * 100) , round(-(PFE / C2C) * 100)) double c2csum = 0; double xFracEff = 0; if (C2C.IsReady) { c2csum = C2C.Sum(); xFracEff = (perfL > 0) ? Math.Round(PFE / c2csum * 100) : Math.Round(-PFE / c2csum * 100); xEma.Update(input.Time, (decimal)xFracEff); } if (xEma.IsReady) { return(xEma); //Math.Min(Math.Max(xEma, -100), 100); } } return(0); }
/// <summary> /// Computes the next value for this indicator from the given state. /// </summary> /// <param name="input">The input value to this indicator on this time step</param> /// <returns>A a value for this indicator</returns> protected override decimal ComputeNextValue(IndicatorDataPoint input) { _rollingData.Add(input.Value); if (_rollingData.Count < 3) { return(0m); } var previousPoint = _rollingData[1]; var previousPoint2 = _rollingData[2]; var logPoint = 0.0; if (previousPoint2 != 0) { logPoint = Math.Log((double)(previousPoint / previousPoint2)); } _standardDeviation.Update(input.Time, (decimal)logPoint); if (!_rollingData.IsReady) { return(0m); } if (!_standardDeviation.IsReady) { return(0m); } var m = _standardDeviation.Current.Value * previousPoint; if (m == 0) { return(0); } var spikeValue = (input.Value - previousPoint) / m; return(spikeValue); }
/// <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) { _windowHighs.Add(input); _windowLows.Add(input); PivotPoint highPoint = null, lowPoint = null; if (_windowHighs.IsReady) { highPoint = FindNextHighPivotPoint(_windowHighs, _surroundingBarsCountForHighPoint); } if (_windowLows.IsReady) { lowPoint = FindNextLowPivotPoint(_windowLows, _surroundingBarsCountForLowPoint); } OnNewPivotPointFormed(highPoint); OnNewPivotPointFormed(lowPoint); return(ConvertToComputedValue(highPoint, lowPoint)); }
/// <summary> /// Computes the next value of this indicator from the given state /// </summary> /// <param name="window"></param> /// <param name="input">The input given to the indicator</param> /// <returns> /// A new value for this indicator /// </returns> protected override decimal ComputeNextValue(IReadOnlyWindow <IndicatorDataPoint> window, IndicatorDataPoint input) { int Mc = 0; int MRc = 0; decimal momersion = 50m; if (window.Count >= 3) { _multipliedDiffWindow.Add((window[0] - window[1]) * (window[1] - window[2])); } // Estimate the indicator if less than 50% of observation are zero. Avoid division by // zero and estimations with few real observations in case of forward filled data. if (this.IsReady && _multipliedDiffWindow.Count(obs => obs == 0) < 0.5 * _multipliedDiffWindow.Count) { Mc = _multipliedDiffWindow.Count(obs => obs > 0); MRc = _multipliedDiffWindow.Count(obs => obs < 0); momersion = 100m * Mc / (Mc + MRc); } return(momersion); }
/// <summary> /// Computes the next value for this indicator from the given state. /// </summary> /// <param name="window">The window of data held in this indicator</param> /// <param name="input">The input value to this indicator on this time step</param> /// <returns>A new value for this indicator</returns> protected override decimal ComputeNextValue(IReadOnlyWindow <IndicatorDataPoint> window, IndicatorDataPoint input) { decimal dominantCycle; List <double> Correlations; Vector <double> DTF; hpf.Update(input); sSmoother.Update(hpf.Current); sSmootherWindow.Add((double)sSmoother.Current.Value); if (!this.IsReady) { dominantCycle = 0m; } else { Correlations = EstimateAutocorrelations(); DTF = EstimateDFT(Correlations); dominantCycle = EstimateDominantCycle(DTF); } return(dominantCycle); }
/// <summary> /// Forecasts the series of the fitted model one point ahead. /// </summary> /// <param name="input">The input given to the indicator</param> /// <returns>A new value for this indicator</returns> protected override decimal ComputeNextValue(IndicatorDataPoint input) { _rollingData.Add((double)input.Value); if (_rollingData.IsReady) { var arrayData = _rollingData.ToArray(); arrayData = _diffOrder > 0 ? DifferenceSeries(_diffOrder, arrayData, out _diffHeads) : arrayData; TwoStepFit(arrayData); double summants = 0; if (_arOrder > 0) { for (var i = 0; i < _arOrder; i++) // AR Parameters { summants += ArParameters[i] * arrayData[i]; } } if (_maOrder > 0) { for (var i = 0; i < _maOrder; i++) // MA Parameters { summants += MaParameters[i] * _residuals[_maOrder + i + 1]; } } summants += Intercept; // By default equals 0 if (_diffOrder > 0) { var dataCast = arrayData.ToList(); dataCast.Insert(0, summants); // Prepends summants = InverseDifferencedSeries(dataCast.ToArray(), _diffHeads).First(); // Returns disintegrated series } return((decimal)summants); } return(0m); }
protected override decimal ComputeNextValue(IReadOnlyWindow <IndicatorDataPoint> window, IndicatorDataPoint input) { // AroonUp.Update(input.Time, input.High); // AroonDown.Update(input.Time, input.Low); var src = input.Value; Src.Add(src); if (Src.IsReady) { var it1 = (It.IsReady) ? It[0] : ((src + 2 * Src[1] + Src[2]) / 4); var it2 = (It.IsReady) ? It[1] : ((src + 2 * Src[1] + Src[2]) / 4); var it = (_alpha - ((_alpha * _alpha) / 4)) * src + 0.5m * _alpha * _alpha * Src[1] - (_alpha - 0.75m * _alpha * _alpha) * Src[2] + 2 * (1 - _alpha) * it1 - (1 - _alpha) * (1 - _alpha) * it2; Lag = 2 * it - it2; It.Add(it); InstantaneousTrend = it; } return(Lag - InstantaneousTrend); }
/// <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="window">The IReadOnlyWindow of Indicator Data Points for the history of this indicator</param> /// <param name="input">IndicatorDataPoint - the time and value of the next price</param> /// <returns></returns> protected override decimal ComputeNextValue(IReadOnlyWindow <IndicatorDataPoint> window, IndicatorDataPoint input) { _maxHigh.Update(input); _minLow.Update(input); decimal fishx = 0; if (IsReady) { // get some local variables var price = input.Value; var minL = _minLow.Current.Value; var maxH = _maxHigh.Current.Value; if (price == 0) { Current = new IndicatorDataPoint(input.EndTime, 0); } else { // get the value1 from the last time this function was called var v1 = value1[0].Value; try { // compute the EMA of the price and the last value1 value1.Add(new IndicatorDataPoint(input.Time, .33m * 2m * ((price - minL) / (maxH - minL) - .5m) + .67m * v1)); } catch (Exception ex) { throw new Exception(ex.Message + ex.StackTrace); } try { // limit the new value1 so that it falls within positive or negative unity if (value1[0].Value > .9999m) { value1[0].Value = .9999m; } if (value1[0].Value < -.9999m) { value1[0].Value = -.9999m; } var current = Current; // calcuate the Fisher transform according the the formula above and from Ehlers // Math.Log takes and produces doubles, so the result is converted back to Decimal // The calculation uses the Current.Value from the last time the function was called, // so an intermediate variable is introduced so that it can be used in the // calculation before the result is assigned to the Current.Value after the calculation is made. fishx = Convert.ToDecimal(.5 * Math.Log((1.0 + (double)value1[0].Value) / (1.0 - (double)value1[0].Value))); } catch (Exception ex) { throw new Exception(ex.Message + ex.StackTrace); } } } return(fishx); }
/// <summary> /// Invokes NewPivotPointFormed event /// </summary> protected virtual void OnNewPivotPointFormed(PivotPoint pivotPoint) { _windowPivotPoints.Add(pivotPoint); NewPivotPointFormed?.Invoke(this, new PivotPointsEventArgs(pivotPoint)); }
/// <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) { _windowHighs.Add(input); _windowLows.Add(input); PivotPoint high = null, low = null; if (_windowHighs.IsReady) { var isHigh = true; var middlePoint = _windowHighs[_lengthHigh]; for (var k = 0; k < _windowHighs.Size && isHigh; k++) { // Skip the middle point if (k == _lengthHigh) { continue; } // Check if current high is below middle point high isHigh = _windowHighs[k].High < middlePoint.High; } if (isHigh) { high = new PivotPoint(PivotPointType.High, middlePoint.High, middlePoint.EndTime); } } if (_windowLows.IsReady) { var isLow = true; var middlePoint = _windowLows[_lengthLow]; for (var k = 0; k < _windowLows.Size && isLow; k++) { if (k == _lengthLow) { continue; } isLow = _windowLows[k].Low > middlePoint.Low; } if (isLow) { low = new PivotPoint(PivotPointType.Low, middlePoint.Low, middlePoint.EndTime); } } if (high != null) { OnNewPivotPointFormed(high); if (low != null) { // Can be the bar forms both high and low pivot points at the same time OnNewPivotPointFormed(low); return((decimal)PivotPointType.Both); } return((decimal)PivotPointType.High); } if (low != null) { OnNewPivotPointFormed(low); return((decimal)PivotPointType.Low); } return((decimal)PivotPointType.None); }
/// <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(T input) { _window.Add(input); return(ComputeNextValue(_window, input)); }