Refactor documentation links in numerics, oscillators, reversals, and statistics modules to use relative paths; update Bias class to handle division by zero more robustly; remove obsolete CUMMEAN Pine script; enhance trend indicators documentation; add Visual Studio Code workspace configuration.

This commit is contained in:
Miha Kralj
2026-02-04 11:43:59 -08:00
parent c034cbd5e5
commit 3e854eac3f
60 changed files with 9944 additions and 2641 deletions
+200 -102
View File
@@ -1,143 +1,241 @@
# DSP: Detrended Synthetic Price
## Overview and Purpose
> "Remove the trend, reveal the cycles."
The Detrended Synthetic Price (DSP) is a cycle analysis indicator developed by John Ehlers that isolates the cyclical component of price action by subtracting a slower-period EMA from a faster-period EMA. Introduced in his work on digital signal processing for traders, DSP creates a band-pass filter effect that removes both long-term trends and short-term noise, revealing the dominant market cycle.
The Detrended Synthetic Price (DSP) indicator, developed by John Ehlers, is a cycle analysis tool that removes trend components to expose underlying price cycles. By differencing two exponential moving averages (fast and slow), DSP creates a zero-centered oscillator that highlights momentum shifts.
Unlike traditional detrending methods that use high-pass filters, Ehlers' DSP uses the difference between a quarter-cycle EMA and a half-cycle EMA relative to the dominant cycle period. This creates an in-phase output that oscillates around zero, with the amplitude and frequency revealing information about cycle strength and timing. The quarter-cycle smoother responds quickly to price changes while the half-cycle smoother provides the baseline reference, and their difference creates the band-pass effect.
## Historical Context
DSP serves as both a standalone cycle indicator and a foundational component for more advanced Ehlers indicators. By isolating the dominant cycle component, it provides a clearer view of market rhythms without the contamination of longer-term trends or higher-frequency noise.
John Ehlers introduced the Detrended Synthetic Price as part of his cycle analysis toolkit. The indicator builds on the MACD concept but uses EMA periods derived from cycle theory: quarter-cycle (fast) and half-cycle (slow) lengths. This mathematical relationship helps isolate cycle components while suppressing trend noise.
## Core Concepts
The "synthetic" in the name refers to how DSP synthesizes a detrended view of price by subtracting the slower-reacting EMA from the faster one. When the fast EMA exceeds the slow EMA, price momentum is bullish; when below, momentum is bearish.
* **Dual-EMA Structure:** Uses two independent EMAs at quarter-cycle (P/4) and half-cycle (P/2) periods derived from the dominant cycle
* **Band-Pass Effect:** Quarter-cycle minus half-cycle creates a filter that passes the dominant cycle while attenuating trends and noise
* **In-Phase Output:** The resulting oscillator is in-phase with the dominant cycle, providing clear timing signals
* **Zero-Crossing Analysis:** Oscillations around zero line reveal cycle phase and potential reversal points
* **Cycle Isolation:** Mathematically isolates the periodic component that matches the specified dominant cycle period
Unlike traditional oscillators that bound between fixed levels, DSP oscillates around zero with amplitude proportional to price volatility and cycle strength.
## Common Settings and Parameters
## Architecture & Physics
| Parameter | Default | Function | When to Adjust |
| ------ | ------ | ------ | ------ |
| Source | source | Data source for calculation | Use `close` for end-of-bar analysis, `hlc3` for balanced price representation |
| Dominant Cycle Period | 40 | Period used to calculate quarter-cycle and half-cycle EMAs | Should match actual market cycle: 20-30 for faster cycles, 40-50 for standard, 60-80 for slower cycles |
DSP uses dual EMA smoothing with bias correction during warmup to produce accurate values from the first bar.
**Pro Tip:** The Dominant Cycle Period should ideally be obtained from HT_DCPERIOD or other cycle measurement tools for adaptive behavior. For fixed analysis, 40 bars works well for daily charts (approximates a 2-month cycle). The quarter-cycle EMA (P/4 = 10) responds to short-term moves while the half-cycle EMA (P/2 = 20) provides the baseline, creating the band-pass effect.
### Core Components
## Calculation and Mathematical Foundation
1. **Period Parameter**: Base cycle length (default 40)
2. **Fast EMA**: Smoothing with period = max(2, round(period/4)) - quarter cycle
3. **Slow EMA**: Smoothing with period = max(3, round(period/2)) - half cycle
4. **Bias Correction**: Warmup decay factors eliminate EMA initialization bias
5. **State Record**: Maintains EMA values and warmup factors for rollback support
**Simplified explanation:**
DSP calculates two EMAs at periods that are fractions of the dominant cycle (quarter and half), then subtracts the slower from the faster to create an oscillator that isolates the cyclical component.
### Period Derivation
**Technical formula:**
For period = 40:
- Fast period = max(2, round(40/4)) = 10
- Slow period = max(3, round(40/2)) = 20
1. Calculate quarter-cycle and half-cycle periods from dominant cycle:
```
Fast_Period = round(Period / 4)
Slow_Period = round(Period / 2)
```
For period = 4 (minimum):
- Fast period = max(2, round(4/4)) = max(2, 1) = 2
- Slow period = max(3, round(4/2)) = max(3, 2) = 3
2. Calculate alpha values for both EMAs:
```
Alpha_Fast = 2 / (Fast_Period + 1)
Alpha_Slow = 2 / (Slow_Period + 1)
```
### Calculation Flow
3. Apply exponential smoothing with warmup compensation:
```
EMA_Fast = EMA(Price, Fast_Period)
EMA_Slow = EMA(Price, Slow_Period)
```
For each update:
1. Calculate fast alpha: $\alpha_f = 2 / (p_f + 1)$
2. Calculate slow alpha: $\alpha_s = 2 / (p_s + 1)$
3. Update fast EMA with bias correction
4. Update slow EMA with bias correction
5. DSP = corrected_fast_ema - corrected_slow_ema
4. Calculate DSP as the difference:
```
DSP = EMA_Fast - EMA_Slow
```
## Mathematical Foundation
> 🔍 **Technical Note:** The implementation uses unified warmup compensation to ensure both EMAs produce valid outputs from bar 1. The quarter-cycle EMA provides rapid response to price changes while the half-cycle EMA establishes the reference baseline. Their difference creates a band-pass filter centered on the dominant cycle period, effectively removing both low-frequency trends (longer than the cycle) and high-frequency noise (shorter than the cycle).
### EMA Alpha Calculation
## Interpretation Details
$$
\alpha = \frac{2}{period + 1}
$$
DSP provides cycle-focused market analysis through the isolated cyclical component:
For fast period 10: $\alpha_f = \frac{2}{11} \approx 0.1818$
* **Zero-Line Crossovers:**
* Cross above zero: Cycle entering positive phase, potential bullish swing point
* Cross below zero: Cycle entering negative phase, potential bearish swing point
* Frequency of crossings indicates cycle period accuracy
For slow period 20: $\alpha_s = \frac{2}{21} \approx 0.0952$
* **Amplitude Analysis:**
* Larger oscillations: Stronger cycle component, more pronounced market rhythm
* Smaller oscillations: Weaker cycle, market transitioning or range-bound
* Amplitude expansion signals increasing cycle strength
* Amplitude contraction signals decreasing cycle strength
### EMA Update (with bias correction)
* **Cycle Phase Identification:**
* Peak values: Cycle approaching maximum (consider taking profits on longs)
* Trough values: Cycle approaching minimum (consider taking profits on shorts)
* Rate of change indicates cycle acceleration/deceleration
* Zero crossings mark quarter-cycle phase transitions
The raw EMA recursion:
* **Trend vs Cycle:**
* Regular oscillations with consistent amplitude: Strong cyclic behavior
* Irregular oscillations or bias to one side: Trend component present
* Dampening oscillations: Cycle weakening, possible trend emergence
* Amplifying oscillations: Cycle strengthening, rhythmic behavior dominant
$$
EMA^{raw}_t = \alpha \cdot P_t + (1 - \alpha) \cdot EMA^{raw}_{t-1}
$$
## Limitations and Considerations
The warmup decay factor tracks bias:
* **Period Dependency:** Effectiveness depends on correct Dominant Cycle Period setting relative to actual market cycles
* **Cycle Variability:** Market cycles are not perfectly periodic; DSP reveals approximate rhythms that can shift over time
* **Trend Sensitivity:** During strong trends, the oscillator may show persistent bias rather than symmetric oscillations
* **Lag Component:** EMAs introduce some lag, though the dual-EMA structure minimizes this compared to single moving averages
* **Requires Cycle Knowledge:** Best results when dominant cycle period is known (use HT_DCPERIOD for adaptive approach)
* **Not Predictive Alone:** Shows current cycle state; combine with other tools for timing and confirmation
$$
e_t = (1 - \alpha) \cdot e_{t-1}
$$
Starting with $e_0 = 1$, this converges to 0 as the EMA warms up.
The bias-corrected EMA:
$$
EMA_t = \frac{EMA^{raw}_t}{1 - e_t}
$$
### DSP Formula
$$
DSP_t = EMA^{fast}_t - EMA^{slow}_t
$$
where both EMAs are bias-corrected.
### Properties
- **Range**: Unbounded, oscillates around zero
- **Zero Crossing**: Indicates momentum shift
- **Positive Values**: Fast EMA > Slow EMA (bullish momentum)
- **Negative Values**: Fast EMA < Slow EMA (bearish momentum)
- **Warmup**: IsHot when $e_{slow} < 0.05$ (5% remaining bias)
### Example Calculation
For period = 40 with constant price 100:
After warmup, both EMAs converge to 100:
- Fast EMA = 100
- Slow EMA = 100
- DSP = 100 - 100 = 0
For uptrend (price rising steadily):
- Fast EMA responds quicker, stays closer to current price
- Slow EMA lags behind
- DSP > 0 (positive momentum)
## Performance Profile
### Operation Count (Streaming Mode, per Bar)
| Metric | Score | Notes |
| :--- | :--- | :--- |
| **Throughput** | ~8 ns/bar | O(1) constant time |
| **Allocations** | 0 | Zero-allocation in hot path |
| **Complexity** | O(1) | Fixed operations per update |
| **Accuracy** | 10 | Exact EMA with bias correction |
| Operation | Count | Cost (cycles) | Subtotal |
| :--- | :---: | :---: | :---: |
| ADD/SUB | 3 | 1 | 3 |
| MUL | 4 | 3 | 12 |
| **Total** | **7** | — | **~15 cycles** |
### Operation Count (per update)
**Breakdown:**
- Fast EMA (quarter-cycle): 2 MUL + 1 ADD = 7 cycles
- Slow EMA (half-cycle): 2 MUL + 1 ADD = 7 cycles
- DSP difference: 1 SUB = 1 cycle
### Complexity Analysis
| Mode | Complexity | Notes |
| Operation | Count | Notes |
| :--- | :---: | :--- |
| Streaming | O(1) | Two IIR filters, constant time |
| Batch | O(n) | Linear scan, no lookback iteration |
**Memory**: ~24 bytes (2 EMA states × 8 bytes + output)
### SIMD Analysis
| Optimization | Applicable | Notes |
| :--- | :---: | :--- |
| AVX2 vectorization | ❌ | IIR recursion prevents cross-bar parallelism |
| FMA | ✅ | EMA: `α × price + (1-α) × prev` |
| Batch parallelism | ❌ | Sequential dependency on previous EMA state |
**FMA Optimization:** Each EMA can use single FMA instruction: `fma(α, price, (1-α) × prev)`, reducing 2 MUL + 1 ADD to 1 FMA + 1 MUL (~11 cycles total).
| ADD/SUB | ~6 | EMA updates and DSP calculation |
| MUL | ~6 | Alpha multiplications |
| DIV | 2 | Bias correction divisions |
| FMA | 4 | Fused multiply-add for EMA |
### Quality Metrics
| Metric | Score | Notes |
| :--- | :---: | :--- |
| **Accuracy** | 9/10 | Band-pass effect isolates dominant cycle |
| **Timeliness** | 8/10 | Dual EMA minimizes lag vs single MA |
| **Accuracy** | 10/10 | Exact EMA with bias correction |
| **Timeliness** | 8/10 | Faster than traditional MACD |
| **Overshoot** | 7/10 | EMA smoothing reduces overshoot |
| **Smoothness** | 8/10 | Clean oscillations when cycle present |
| **Smoothness** | 8/10 | Dual EMA provides good smoothing |
## Validation
| Library | Status | Notes |
| :--- | :--- | :--- |
| **TA-Lib** | N/A | Not available in TA-Lib |
| **Skender** | N/A | Not available in Skender |
| **Tulip** | N/A | Not available in Tulip |
| **PineScript** | ✅ | Validated against original DSP implementation |
DSP is validated through mathematical properties:
- Constant price produces zero DSP
- Uptrend produces positive DSP
- Downtrend produces negative DSP
- Oscillates around zero for cyclic price patterns
## Common Pitfalls
1. **Period Selection**: The period parameter represents the dominant cycle length. Use half the detected cycle period for optimal results. Default 40 works for daily data.
2. **Comparison to MACD**: DSP differs from MACD in period derivation. MACD uses arbitrary 12/26 periods; DSP uses cycle-theory-based period/4 and period/2.
3. **Warmup Behavior**: DSP includes bias correction, so early values are usable. IsHot indicates when the slow EMA bias drops below 5%.
4. **Amplitude Interpretation**: DSP amplitude scales with price level. A $1 stock and $100 stock with identical percentage moves will have 100x different DSP amplitudes.
5. **Zero Crossings**: Not all zero crossings are tradeable. Use in conjunction with cycle analysis or additional confirmation.
6. **Trending Markets**: In strong trends, DSP stays positive or negative for extended periods. Cycle analysis is most effective in ranging markets.
## Usage
```csharp
using QuanTAlib;
// Create a 40-period DSP indicator
var dsp = new Dsp(period: 40);
// Update with new values
var result = dsp.Update(new TValue(DateTime.UtcNow, 100.0));
// Access the last calculated DSP value
Console.WriteLine($"DSP: {dsp.Last.Value}");
// Chained usage
var source = new TSeries();
var dspChained = new Dsp(source, period: 40);
// Static batch calculation
var output = Dsp.Calculate(source, period: 40);
// Span-based calculation
Span<double> outputSpan = stackalloc double[source.Count];
Dsp.Batch(source.Values, outputSpan, period: 40);
```
## Applications
### Cycle Detection
DSP zero crossings help identify cycle turning points:
- DSP crosses above zero: cycle trough (potential buy)
- DSP crosses below zero: cycle peak (potential sell)
### Trend Filtering
Use DSP sign to filter trades with trend direction:
- DSP > 0: Only take long trades
- DSP < 0: Only take short trades
### Momentum Confirmation
DSP slope confirms momentum strength:
- Rising DSP: Increasing bullish momentum
- Falling DSP: Increasing bearish momentum
### Divergence Analysis
Like other oscillators, DSP divergences signal potential reversals:
- Price higher high, DSP lower high: bearish divergence
- Price lower low, DSP higher low: bullish divergence
## Comparison to Related Indicators
### DSP vs MACD
| Feature | DSP | MACD |
| :--- | :--- | :--- |
| Period basis | Cycle theory (P/4, P/2) | Arbitrary (12, 26) |
| Signal line | None (optional) | 9-period EMA |
| Bias correction | Yes | No |
| Histogram | No | Yes (MACD - Signal) |
### DSP vs Detrended Price Oscillator (DPO)
| Feature | DSP | DPO |
| :--- | :--- | :--- |
| Calculation | Fast EMA - Slow EMA | Price - SMA shifted |
| Time alignment | Current | Shifted back period/2 + 1 |
| Leading/Lagging | Leading | Centered (neither) |
## References
* Ehlers, J. F. (2013). *Cycle Analytics for Traders: Advanced Technical Trading Concepts*. Wiley Trading.
* Ehlers, J. F. (2001). *Rocket Science for Traders: Digital Signal Processing Applications*. Wiley Trading.
* Ehlers, J. F. (2004). *Cybernetic Analysis for Stocks and Futures: Cutting-Edge DSP Technology to Improve Your Trading*. Wiley Trading.
- Ehlers, J.F. (2001). *Rocket Science for Traders*. Wiley.
- Ehlers, J.F. (2004). *Cybernetic Analysis for Stocks and Futures*. Wiley.
- TradingView PineScript: DSP implementation in cycle analysis scripts.