mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-19 02:58:05 +00:00
- Updated the name and description of the Hilbert Trendline (HTIT) to "Ehlers Hilbert Transform Instantaneous Trend (HTIT)". - Changed the name and description of the MESA Adaptive Moving Average (MAMA) to "Ehlers MESA Adaptive Moving Average". - Modified the Center of Gravity (CG) indicator to "Ehlers Center of Gravity (CG)". - Renamed the Detrended Synthetic Price (DSP) to "Ehlers Detrended Synthetic Price (DSP)". - Updated the Autocorrelation Periodogram (EACP) to "Ehlers Autocorrelation Periodogram (EACP)". - Changed the Homodyne Discriminator (HOMOD) to "Ehlers Homodyne Discriminator (HOMOD)". - Updated the Hilbert Transform Dominant Cycle Period and Phase indicators to include "Ehlers" in their names. - Renamed the Hilbert Transform Phasor Components to "Ehlers Hilbert Transform Phasor Components (HT_PHASOR)". - Updated the SineWave indicator to "Ehlers Hilbert Transform SineWave (HT_SINE)". - Changed the Phasor Analysis indicator to "Ehlers Hilbert Transform Phasor Components (HT_PHASOR)". - Updated the SSF-Based Detrended Synthetic Price to "Ehlers SSF Detrended Synthetic Price (SSFDSP)". - Renamed the Ultimate Channel to "Ehlers Ultimate Channel (UCHANNEL)". - Added new indicators: Moving Average Variable Period (MAVP), Ehlers Predictive Moving Average (PMA), Ehlers Reverse EMA (REVERSEEMA), and Ehlers Trendflex Indicator (TRENDFLEX). - Updated various SVG badges to reflect changes in classes, comments, source files, lines of code, methods, and public types.
146 lines
3.9 KiB
Markdown
146 lines
3.9 KiB
Markdown
# DSP: Ehlers Detrended Synthetic Price
|
||
|
||
> "Remove the trend, reveal the cycles."
|
||
|
||
The Detrended Synthetic Price (DSP) indicator creates a zero-centered oscillator by subtracting a half-cycle EMA from a quarter-cycle EMA. Developed by John Ehlers, this "synthetic" price highlights underlying cyclical movement, identifying momentum shifts when the faster EMA crosses the slower one.
|
||
|
||
## Historical Context
|
||
|
||
John Ehlers introduced the DSP as part of his research into cycle analytics for traders. While many indicators (like MACD) use arbitrary periods (12/26), DSP is grounded in cycle theory. Ehlers posits that to effectively isolate a cycle, one should filter data based on the dominant cycle period.
|
||
|
||
The use of period/4 and period/2 roughly corresponds to extracting the cycle's momentum while cancelling out longer-term trends. This makes DSP particularly effective for cycle-based trading strategies.
|
||
|
||
## Architecture & Physics
|
||
|
||
DSP utilizes a dual EMA architecture, calibrated to specific fractions of the cycle period.
|
||
|
||
### 1. Component Periods
|
||
|
||
$$
|
||
P_{fast} = \max(2, \text{round}(P / 4))
|
||
$$
|
||
|
||
$$
|
||
P_{slow} = \max(3, \text{round}(P / 2))
|
||
$$
|
||
|
||
### 2. Alpha Coefficients
|
||
|
||
$$
|
||
\alpha_{fast} = \frac{2}{P_{fast} + 1}
|
||
$$
|
||
|
||
$$
|
||
\alpha_{slow} = \frac{2}{P_{slow} + 1}
|
||
$$
|
||
|
||
### 3. EMA Updates (with Bias Correction)
|
||
|
||
$$
|
||
EMA_{raw} = \alpha \cdot Price + (1 - \alpha) \cdot EMA_{raw\_prev}
|
||
$$
|
||
|
||
$$
|
||
EMA_{corrected} = \frac{EMA_{raw}}{1 - (1-\alpha)^n}
|
||
$$
|
||
|
||
### 4. DSP Calculation
|
||
|
||
$$
|
||
DSP = EMA_{fast} - EMA_{slow}
|
||
$$
|
||
|
||
## Performance Profile
|
||
|
||
### Operation Count (Streaming Mode, per Bar)
|
||
|
||
| Operation | Count | Cost (cycles) | Subtotal |
|
||
| :--- | :---: | :---: | :---: |
|
||
| FMA (EMA updates) | 2 | 4 | 8 |
|
||
| MUL (decay factors) | 2 | 3 | 6 |
|
||
| DIV (bias correction) | 2 | 15 | 30 |
|
||
| SUB (DSP = fast - slow) | 1 | 1 | 1 |
|
||
| **Total** | **7** | — | **~45 cycles** |
|
||
|
||
### Complexity Analysis
|
||
|
||
- **Streaming:** O(1) per bar—fixed calculation depth
|
||
- **Memory:** O(1)—only EMA state variables
|
||
- **Warmup:** ~2 × slow period for convergence
|
||
|
||
## Validation
|
||
|
||
| Library | Status | Notes |
|
||
| :--- | :---: | :--- |
|
||
| TA-Lib | N/A | Not standard |
|
||
| Skender | N/A | Not standard |
|
||
| PineScript | ✅ | Matches Ehlers' reference logic |
|
||
|
||
## Usage & Pitfalls
|
||
|
||
- **Zero crossing** indicates cycle phase change—above zero is bullish, below zero is bearish
|
||
- **Period should match market cycle**—if market cycle is 20 bars, use period 20 not 40
|
||
- **Not normalized**—amplitude reflects absolute price difference, varies by asset
|
||
- **Whipsaws** occur in ranging markets with cycles shorter than the setting
|
||
- **Divergence** (higher price highs with lower DSP highs) suggests cycle energy loss
|
||
- **Use FusedMultiplyAdd** for optimal precision in EMA recursion
|
||
|
||
## API
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class Dsp {
|
||
+int Period
|
||
+double Value
|
||
+bool IsHot
|
||
+Dsp(int period)
|
||
+Dsp(ITValuePublisher source, int period)
|
||
+TValue Update(TValue input, bool isNew)
|
||
+void Reset()
|
||
}
|
||
```
|
||
|
||
### Class: `Dsp`
|
||
|
||
| Parameter | Type | Default | Range | Description |
|
||
| :--- | :--- | :--- | :--- | :--- |
|
||
| `period` | `int` | `40` | `≥4` | Dominant cycle period |
|
||
|
||
### Properties
|
||
|
||
- `Value` (`double`): The current DSP value (oscillates around 0)
|
||
- `IsHot` (`bool`): Returns `true` when warmup is complete
|
||
|
||
### Methods
|
||
|
||
- `Update(TValue input, bool isNew)`: Updates the indicator with a new data point
|
||
|
||
## C# Example
|
||
|
||
```csharp
|
||
using QuanTAlib;
|
||
|
||
// Create DSP for a 40-bar cycle
|
||
var dsp = new Dsp(period: 40);
|
||
|
||
// Update with streaming data
|
||
foreach (var bar in quotes)
|
||
{
|
||
var result = dsp.Update(new TValue(bar.Date, bar.Close));
|
||
|
||
if (dsp.IsHot)
|
||
{
|
||
Console.WriteLine($"{bar.Date}: DSP = {result.Value:F4}");
|
||
|
||
// Cycle phase detection
|
||
if (result.Value > 0)
|
||
Console.WriteLine(" → Bullish cycle phase");
|
||
else
|
||
Console.WriteLine(" → Bearish cycle phase");
|
||
}
|
||
}
|
||
|
||
// Batch calculation
|
||
var output = Dsp.Calculate(sourceSeries, period: 40);
|
||
```
|