Files
Miha Kralj 33d20f2a18 feat(dynamics): add PlusDI, MinusDI, PlusDM, MinusDM indicators
Complete thin Dx-composition wrapper indicators with full test coverage:

- PlusDi/MinusDi: Directional Indicator wrappers (DiPlus/DiMinus from Dx)
- PlusDm/MinusDm: Directional Movement wrappers (DmPlus/DmMinus from Dx)
- Individual validation tests per indicator directory (TALib, Skender, bounds)
- Combined unit tests (DiDm.Tests.cs) and validation tests (DiDm.Validation.Tests.cs)
- Quantower wrappers + tests for all 4 indicators
- PineScript v6 implementations with compensated RMA
- Normalized .md documentation for all indicators and categories
- 182 tests passing, 0 failures
2026-03-11 20:21:52 -07:00

9.8 KiB

STOCHF: Stochastic Fast Oscillator

Speed kills in traffic. In markets, it merely whipsaws.

Property Value
Category Oscillator
Inputs Bar series (High, Low, Close)
Parameters kLength (default 5), dPeriod (default 3)
Outputs Dual series (%K line, %D signal line)
Output range 0 to 100
Warmup kLength bars
PineScript stochf.pine

Key takeaways

  • The unsmoothed (raw) variant of the Stochastic Oscillator. %K has no additional SMA smoothing applied.
  • Default kLength is 5 (shorter than Stoch's 14), making it more responsive and noisier.
  • Uses MonotonicDeque pairs for O(1) amortized min/max tracking, identical architecture to Stoch.
  • Zero range (all bars identical) returns 0 for %K.
  • Matches TA-Lib's dedicated STOCHF function, which separates Fast from Slow Stochastic explicitly.

Historical Context

George C. Lane's Stochastic Oscillator (late 1950s) was originally this: the raw, unsmoothed position-in-range calculation with a simple SMA signal line. The "Fast" label was applied retroactively when traders began smoothing %K with an additional SMA to create the "Slow" variant. What Lane invented is what we now call Fast Stochastic.

TA-Lib codified the distinction by providing separate functions: STOCH (slow, with configurable smoothing on %K) and STOCHF (fast, raw %K). QuanTAlib follows this convention. The Stoch class defaults to kLength=14; the Stochf class defaults to kLength=5 for faster response. Both produce raw %K internally; the difference is the default parameterization and the explicit naming that signals intent.

The shorter default period makes Stochf more reactive to short-term price action. That reactivity is simultaneously its strength (early signals) and its weakness (more false signals in choppy markets). Traders who want the responsiveness of a 5-period lookback but less noise typically apply additional smoothing externally rather than switching to the Slow variant.

What It Measures and Why It Matters

Stochf measures where the current close sits within the highest-high to lowest-low range over the past kLength bars, expressed as a percentage from 0 to 100. The %D line is the SMA of %K over dPeriod bars.

The indicator prioritizes speed over smoothness. Because %K is unsmoothed and the default lookback is only 5 bars, Stochf reacts to price changes faster than its Slow Stochastic counterpart. This makes it useful for short-term trading where early detection of momentum shifts matters more than filtering noise.

The trade-off is straightforward: faster response means more false signals. In trending markets, Stochf whipsaws through overbought/oversold zones rapidly. In range-bound markets, the quick response helps identify turning points before slower indicators confirm. Knowing which regime you are trading determines whether Stochf helps or hurts.

Mathematical Foundation

Core Formula


HH_n = \max(H_i) \quad \text{for } i \in [t - n + 1, \, t]

LL_n = \min(L_i) \quad \text{for } i \in [t - n + 1, \, t]

\%K_t = 100 \times \frac{C_t - LL_n}{HH_n - LL_n}

\%D_t = \text{SMA}(\%K, d)

where n is kLength and d is dPeriod.

Parameter Mapping

Parameter Code Default Constraints
K Length kLength 5 > 0
D Period dPeriod 3 > 0

Warmup Period


W = n

The indicator requires n bars to fill the sliding window. The %D SMA pre-fills its buffer with the first %K value (PineScript convention), producing output from bar 0.

Architecture & Physics

1. MonotonicDeque Streaming

Identical architecture to Stoch: two MonotonicDeque instances (max for highs, min for lows) provide O(1) amortized sliding min/max. Circular buffers (_hBuf, _lBuf) store raw H/L values for deque rebuild on bar correction.

2. %D Signal Line

A circular buffer (_dBuf) with running sum computes the SMA of %K in O(1). First bar pre-fills the entire buffer with the initial %K value; subsequent bars replace the oldest entry.

3. Batch Path

Batch(ReadOnlySpan, ..., Span, Span, int, int) delegates to Highest.Batch() and Lowest.Batch(). Intermediate buffers use stackalloc for \leq 256 elements and ArrayPool<double> beyond that threshold.

4. Edge Cases

Condition Behavior
kLength <= 0 or dPeriod <= 0 ArgumentException with nameof()
NaN / Infinity input Substitutes last valid value per channel (H/L/C)
All NaN (no valid data yet) Returns NaN for both %K and %D
Zero range (HH = LL) %K returns 0
isNew = false Restores _ps, rebuilds both deques from circular buffer

Interpretation and Signals

Signal Zones

Zone Condition Interpretation
Overbought %K > 80 Close near period high; potential reversal down
Neutral 20 ≤ %K ≤ 80 Normal trading range
Oversold %K < 20 Close near period low; potential reversal up

Signal Patterns

  • %K/%D crossover: Bullish when %K crosses above %D; bearish when %K crosses below %D.
  • Divergence: Price makes new highs while %K fails to confirm (bearish) or price makes new lows while %K holds (bullish).
  • Hook reversal: %K reverses sharply at an extreme without completing a full crossover. Common with the fast variant's responsiveness.

Practical Notes

  • Stochf generates more crossover signals than Stoch due to the shorter default period and lack of %K smoothing. Filter with trend context.
  • In strong trends, %K oscillates rapidly near 100 (uptrend) or 0 (downtrend). These are not reversal signals; they confirm trend strength.
  • Consider using Stochf for entry timing within a trend identified by a slower indicator (ADX, SMA slope).
  • Stoch: Same formula with default kLength=14; often used with additional %K smoothing for the "Slow" variant.
  • Willr: Identical math with inverted [-100, 0] scale.
  • KDJ: Extended stochastic with J-line divergence amplification.
  • StochRSI: Applies the stochastic formula to RSI output instead of price.

Validation

Library Status Notes
Skender GetStoch(kLength, dPeriod, smoothPeriods=1) matches within 1e-6
TA-Lib StochF(high, low, close, kLength, dPeriod) matches within 1e-6
Tulip -- Not directly validated
Ooples -- Not validated

Performance Profile

Key Optimizations

  • O(1) amortized streaming: MonotonicDeque avoids full-window scans for min/max.
  • O(1) %D SMA: Circular buffer with running sum.
  • Zero allocation: Update uses pre-allocated circular buffers and record struct State.
  • Stackalloc/ArrayPool batch: Intermediate buffers use stackalloc for \leq 256 elements, ArrayPool beyond.

Operation Count (Streaming Mode)

Operation Count per bar
Comparisons 2-3 (deque push amortized)
Divisions 2 (range normalization + %D SMA)
Multiplications 1 (100 *)
Additions/Subtractions 2 (%D running sum update)
NaN checks 3 (high, low, close)
Total ~10 ops

SIMD Analysis (Batch Mode)

Property Value
Vectorizable Partially (via Highest.Batch / Lowest.Batch)
%K final loop Scalar: 100 * (close[i] - LL[i]) / (HH[i] - LL[i])
%D computation Scalar circular buffer with running sum

Common Pitfalls

  1. Fast vs Slow confusion: StochF is the unsmoothed variant. TA-Lib's STOCH applies %K smoothing; STOCHF does not. Comparing outputs without matching smoothing parameters produces mismatches.
  2. Default period difference: StochF defaults to kLength=5, not 14. Comparing directly to Stoch(14, 3) produces different results even though the formula is identical.
  3. More whipsaws: The shorter lookback and lack of smoothing generate more %K/%D crossovers. Most are noise in trending markets.
  4. Zero range returns 0: When all bars in the window have identical H/L, %K returns 0. Williams %R returns -50 for the same condition.
  5. %D warmup convention: First %D value pre-fills the SMA buffer with the initial %K, matching PineScript behavior. Other implementations may emit NaN until dPeriod bars of %K are available.
  6. Overbought persistence: In strong trends, %K stays near extremes. The fast response makes this more pronounced than with Slow Stochastic.

FAQ

Q: What is the difference between Stochf and Stoch? A: Identical formula, different defaults. Stochf defaults to kLength=5 for faster response. Stoch defaults to kLength=14. Neither applies additional smoothing to %K in this implementation. The "Slow Stochastic" convention requires smoothing %K with an SMA, which is a separate operation.

Q: Why does TA-Lib separate STOCH and STOCHF? A: TA-Lib's STOCH function includes a smoothK parameter that applies SMA smoothing to %K before computing %D (Slow Stochastic). STOCHF omits that smoothing step entirely. QuanTAlib's Stoch and Stochf both output raw %K; the distinction is in default parameters and naming convention.

Q: When should I prefer Stochf over Stoch? A: When you need faster signal detection and can tolerate more false positives. Typical use cases: scalping, intraday mean reversion, or as a timing tool within a larger trend-following system.

References

  • Lane, G. C. "Lane's Stochastics." Technical Analysis of Stocks & Commodities, 1984.
  • Murphy, J. J. Technical Analysis of the Financial Markets. New York Institute of Finance, 1999.
  • Achelis, S. B. Technical Analysis from A to Z. McGraw-Hill, 2000.