- 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.
6.2 KiB
HT_TRENDMODE: Ehlers Hilbert Transform Trend vs Cycle Mode
Historical Context
The Hilbert Transform Trend Mode indicator was developed by John Ehlers as part of his cycle analysis toolkit. It uses the Hilbert Transform—a signal processing technique—to determine whether price action is dominated by trending behavior or cyclical/mean-reverting behavior.
This implementation follows TA-Lib's Ehlers-faithful algorithm from his February 2002 publication "The Instantaneous Trendline." The key insight: trend mode is detected via multiple criteria including SineWave crossings, phase rate analysis, and price-trendline deviation.
Architecture & Physics
The Trend/Cycle Duality
Markets alternate between two fundamental states:
| State | Characteristic | Strategy |
|---|---|---|
| Trend Mode (1) | Directional momentum | Trend-following |
| Cycle Mode (0) | Mean-reverting oscillation | Range-trading |
The TA-Lib algorithm uses four criteria to determine trend mode:
- SineWave Crossings: Reset trend counter when Sine crosses LeadSine
- Days in Trend: Must exceed half the smooth period
- Phase Rate Check: Normal phase change rate indicates cycle mode
- Price-Trendline Deviation: ≥1.5% deviation forces trend mode
Mathematical Foundation
1. Hilbert Transform Components
The indicator uses the same Hilbert Transform core as HT_DCPERIOD:
smooth_price = (4×P₀ + 3×P₁ + 2×P₂ + P₃) / 10
detrender = FIR(smooth_price) × bandwidth
Q1 = FIR(detrender) × bandwidth
I1 = detrender[3]
// Phasor rotation
I2 = I1 - jQ
Q2 = Q1 + jI
2. Period and DC Phase
Re = 0.2×(I2×I2[1] + Q2×Q2[1]) + 0.8×Re[1]
Im = 0.2×(I2×Q2[1] - Q2×I2[1]) + 0.8×Im[1]
period = 360 / (atan(Im/Re) × RAD2DEG)
smooth_period = 0.33×period + 0.67×smooth_period[1]
// DC Phase calculation
realPart = Σ sin(i × 360/dcPeriod) × smoothPrice[i]
imagPart = Σ cos(i × 360/dcPeriod) × smoothPrice[i]
dcPhase = atan(realPart/imagPart) × RAD2DEG + 90 + lag_compensation
3. SineWave Indicators
sine = sin(dcPhase × DEG2RAD)
leadSine = sin((dcPhase + 45) × DEG2RAD)
4. Trendline Calculation
// SMA over dominant cycle period
sma = average(price, dcPeriodInt)
// WMA smoothing
trendline = (4×sma₀ + 3×sma₁ + 2×sma₂ + sma₃) / 10
5. Trend Mode Decision (TA-Lib Algorithm)
trend = 1 // Assume trend by default
// Criterion 1: SineWave crossing resets counter
if (sine crosses leadSine):
daysInTrend = 0
trend = 0
daysInTrend++
// Criterion 2: Must be trending for half a cycle
if (daysInTrend < 0.5 × smoothPeriod):
trend = 0
// Criterion 3: Normal phase rate → cycle mode
phaseChange = dcPhase - prevDcPhase
expectedChange = 360 / smoothPeriod
if (phaseChange > 0.67×expectedChange AND phaseChange < 1.5×expectedChange):
trend = 0
// Criterion 4: Price deviation override
if (abs((smoothPrice - trendline) / trendline) >= 0.015):
trend = 1
Performance Profile
- Complexity: O(1) per update
- Memory: ~450 bytes state + circular buffers
- Lookback: 63 bars (TA-Lib compatible)
Zero-Allocation Design
[SkipLocalsInit]
public sealed class HtTrendmode : AbstractBase
{
// All state in value types
private State _state;
private State _p_state;
// Pre-allocated buffers for Hilbert Transform
private readonly double[] _circBuffer;
private readonly double[] _smoothPrice;
private readonly double[] _priceHistory;
}
Bar Correction Pattern
Supports streaming updates with correction:
// New bar
var result = indicator.Update(price, isNew: true);
// Same bar, corrected price
var corrected = indicator.Update(newPrice, isNew: false);
Usage
Streaming
var indicator = new HtTrendmode();
foreach (var bar in bars)
{
var result = indicator.Update(bar.Close, isNew: true);
if (indicator.TrendMode == 1)
{
// Use trend-following strategy
ApplyMomentumStrategy();
}
else
{
// Use mean-reversion strategy
ApplyRangeStrategy();
}
}
Batch
var result = HtTrendmode.Calculate(closePrices);
Properties
| Property | Type | Description |
|---|---|---|
TrendMode |
int | Current mode: 1=trend, 0=cycle |
SmoothPeriod |
double | Smoothed dominant cycle period [6-50] |
InstPeriod |
double | Instantaneous (unsmoothed) period |
DCPhase |
double | Dominant cycle phase in degrees |
Trendline |
double | WMA-smoothed SMA over cycle period |
DaysInTrend |
int | Days since last SineWave crossing |
Interpretation
Signal Interpretation
| Value | Mode | Interpretation |
|---|---|---|
| 1 | Trend | Price is trending; momentum strategies preferred |
| 0 | Cycle | Price is oscillating; mean-reversion preferred |
Common Patterns
- Trend Confirmation: When TrendMode flips from 0→1 after a breakout
- Cycle Entry: When TrendMode flips from 1→0 at potential reversal zones
- Mode Persistence: Long runs of 1s indicate strong trends
- Mode Oscillation: Rapid flipping indicates choppy markets
Using Auxiliary Properties
// Access the trendline for support/resistance
double trend = indicator.Trendline;
// Check how long in current trend
int duration = indicator.DaysInTrend;
// Use phase for timing entries
double phase = indicator.DCPhase;
Validation
Cross-Library Comparison
| Library | Function | Notes |
|---|---|---|
| TA-Lib | HT_TRENDMODE |
Reference implementation (matched) |
| TradingView | Built-in | PineScript version (differs) |
Common Pitfalls
- Lag: Hilbert Transform has inherent lag (~32-63 bars for reliable signal)
- Whipsaws: Mode can flip rapidly in transitional markets
- Warmup: Requires 63+ bars before valid output
- Division Safety: Use epsilon checks to avoid division by zero
References
- Ehlers, J.F. "The Instantaneous Trendline" (February 2002)
- Ehlers, J.F. "MESA and Trading Market Cycles" (2002)
- Ehlers, J.F. "Rocket Science for Traders" (2001)
- TA-Lib HT_TRENDMODE Source