/// <inheritdoc /> protected override decimal ComputeNextValue(IReadOnlyWindow <IndicatorDataPoint> window, IndicatorDataPoint input) { if (Samples == 1 || input.Value <= Current.Value) { // our first sample or if we're bigger than our previous indicator value // reset the periods since minimum (it's this period) and return the value PeriodsSinceMinimum = 0; return(input.Value); } if (PeriodsSinceMinimum >= Period - 1) { // at this point we need to find a new minimum // the window enumerates from most recent to oldest // so let's scour the window for the max and it's index // this could be done more efficiently if we were to intelligently keep track of the 'next' // minimum, so when one falls off, we have the other... but then we would also need the 'next, next' // minimum, so on and so forth, for now this works. var minimum = window.Select((v, i) => new { Value = v, Index = i }).OrderBy(x => x.Value.Value).First(); PeriodsSinceMinimum = minimum.Index; return(minimum.Value); } // if we made it here then we didn't see a new minimum and we haven't reached our period limit, // so just increment our periods since minimum and return the same value as we had before PeriodsSinceMinimum++; return(Current); }
/// <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> /// <exception cref="System.NotImplementedException"></exception> protected override decimal ComputeNextValue(IReadOnlyWindow <IndicatorDataPoint> window, IndicatorDataPoint input) { return(IsReady ? window.Select((t, i) => t.Price * _weightVector[i]).Sum() : input.Value); }
/// <summary> /// Computes the next value for this indicator from the given state. /// </summary> /// <param name="timeWindow"></param> /// <param name="window">The window of data held in this indicator</param> /// <param name="time"></param> /// <param name="input">The input value to this indicator on this time step</param> /// <returns> /// A new value for this indicator /// </returns> /// <exception cref="System.NotImplementedException"></exception> protected override DoubleArray Forward(IReadOnlyWindow <long> timeWindow, IReadOnlyWindow <DoubleArray> window, long time, DoubleArray input) { return(IsReady ? window.Select((t, i) => t.Value * _weightVector[i]).Sum() : input); }
/// <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(IReadOnlyWindow <IndicatorDataPoint> window, IndicatorDataPoint input) { if (Samples < 2) { return(0m); } IEnumerable <double> doubleValues = window.Select(i => Convert.ToDouble(i.Value)); double std = MathNetStatistics.PopulationStandardDeviation(doubleValues); return(Convert.ToDecimal(std)); }