mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-20 03:28:05 +00:00
- Implemented Stochastic Oscillator (%K and %D) in Stoch.cs with streaming and batch processing capabilities. - Added validation tests for the Stochastic Oscillator in Stoch.Validation.Tests.cs, ensuring consistency with Skender.Stock.Indicators. - Created documentation for the Stochastic Oscillator in Stoch.md, detailing its mathematical formula, architecture, parameters, and common pitfalls. - Updated project file to include necessary numeric libraries for highest and lowest calculations.
3.2 KiB
3.2 KiB
Detrended Price Oscillator (DPO)
Overview
The Detrended Price Oscillator (DPO) removes the trend component from price data by displacing a Simple Moving Average (SMA), isolating short-term price cycles. Unlike most oscillators, DPO is not aligned to the latest price—it references a past SMA value to filter out long-term trends.
Formula
displacement = floor(period / 2) + 1
DPO = price − SMA(period)[displacement bars ago]
Where:
- period — SMA lookback window (default: 20)
- displacement — number of bars the SMA is shifted backward
- SMA — Simple Moving Average of the source series
Architecture
Source ──→ RingBuffer(period) ──→ SMA ──→ RingBuffer(displacement+1) ──→ DPO
[running sum] [O(1)] [stores SMA history]
Streaming (O(1) per bar)
| Component | Role |
|---|---|
_smaBuffer |
RingBuffer(period) — maintains running sum for O(1) SMA via Sum / period |
_smaHistory |
RingBuffer(displacement + 1) — stores past SMA values; .Oldest gives the displaced SMA |
Bar Correction
Uses Snapshot() / Restore() on both RingBuffers for intra-bar updates (isNew = false).
Warmup
WarmupPeriod = period + displacement — need period bars to compute the first SMA, then displacement more bars before the displaced SMA is available.
Performance Profile
| Metric | Value |
|---|---|
| Time complexity | O(1) per bar (streaming) |
| Space complexity | O(period + displacement) |
| Allocations | Zero per update |
| NaN handling | Last valid value substitution |
| SIMD | Not applicable (displacement dependency) |
Usage
// Streaming
var dpo = new Dpo(period: 20);
TValue result = dpo.Update(new TValue(time, price));
// Event-based
var source = new TSeries();
var dpo = new Dpo(source, period: 20);
// Batch
TSeries results = Dpo.Batch(source, period: 20);
// Span
Dpo.Batch(sourceSpan, outputSpan, period: 20);
Interpretation
-
Zero Line Crossovers:
- DPO crosses above zero: Price is above the displaced moving average (short-term bullish)
- DPO crosses below zero: Price is below the displaced moving average (short-term bearish)
-
Cycle Identification:
- DPO peaks and troughs correspond to short-term price cycles
- Distance between peaks estimates the dominant cycle period
- Works best when the dominant cycle length approximates the DPO period
-
Overbought/Oversold:
- Extreme DPO values suggest price has deviated significantly from its trend
- No fixed bounds; context-dependent interpretation
-
Divergence:
- Bullish: Price makes lower lows while DPO makes higher lows
- Bearish: Price makes higher highs while DPO makes lower highs
Validation
Cross-validated against:
- Tulip Indicators (
dpo) — exact match within 1e-9 tolerance - Manual SMA computation — independent verification of displaced SMA algorithm
Parameters
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
period |
int | 20 | > 0 | SMA lookback period |
References
- William Blau, Momentum, Direction, and Divergence, 1995
- Thomas Dorsey, Point and Figure Charting, 2007
- PineScript reference:
dpo.pine