Files
QuanTAlib/lib/cycles/homod/homod.md
T
Miha Kralj 3dd05f23e4 Refactor indicators to include "Ehlers" in names and descriptions for clarity
- 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.
2026-02-18 19:08:15 -08:00

4.4 KiB
Raw Blame History

HOMOD: Ehlers Homodyne Discriminator

"The homodyne discriminator reveals instantaneous frequency by multiplying a signal with its delayed self — the phase rotation between samples directly encodes the cycle period."

The Homodyne Discriminator (HOMOD) estimates the dominant cycle period of a market using homodyne mixing—multiplying the signal by a delayed version of itself. This technique exposes the angular phase change between bars, allowing calculation of the instantaneous period at every time step.

Historical Context

In Rocket Science for Traders and Cybernetic Analysis for Stocks and Futures, John Ehlers introduced signal processing concepts novel to technical analysis. The Homodyne Discriminator was presented as a superior alternative to the Hilbert Transform Discriminator for cycle measurement.

It offers better noise rejection and stability while maintaining reasonable responsiveness, making it practical for real-time trading applications.

Architecture & Physics

The algorithm is a complex pipeline of filters and transformations designed to isolate the analytic signal.

1. Pre-Processing (4-Bar WMA)


Smooth = \frac{4P_t + 3P_{t-1} + 2P_{t-2} + P_{t-3}}{10}

2. Analytic Signal Generation

In-Phase (I) and Quadrature (Q) components via Hilbert Transform:


I_2 = I_1 - JQ

Q_2 = Q_1 + JI

Smoothed with EMA (α = 0.2).

3. Homodyne Mixing

Multiplying complex signal z_t by its conjugate delayed by one bar:


Real = (I_2 \cdot I_{2,prev}) + (Q_2 \cdot Q_{2,prev})

Imag = (I_2 \cdot Q_{2,prev}) - (Q_2 \cdot I_{2,prev})

4. Period Extraction


\theta = \operatorname{atan2}(Imag, Real)

Period = \frac{2\pi}{\theta}

Clamped to [MinPeriod, MaxPeriod] and smoothed.

Performance Profile

Operation Count (Streaming Mode, per Bar)

Operation Count Cost (cycles) Subtotal
MUL (Hilbert taps) 14 3 42
MUL (homodyne mix) 4 3 12
ADD/SUB 20 1 20
ATAN2 1 25 25
DIV 2 15 30
Total 41 ~129 cycles

Complexity Analysis

  • Streaming: O(1) per bar—fixed filter depth
  • Memory: O(1)—state struct with history variables
  • Warmup: ~2 × MaxPeriod bars for convergence

Validation

Library Status Notes
TA-Lib N/A Not implemented
Skender N/A Not implemented
PineScript Matches Ehlers' reference code

Usage & Pitfalls

  • Output is period in bars—not an oscillator like RSI, but a measurement like ATR
  • Long settling time (~2 × MaxPeriod)—early values unreliable
  • Trending markets make "cycle" ill-defined—period drifts to MaxPeriod
  • Check for cycling (ADX or trend filter) before trusting period values
  • High noise causes jitter—pre-smooth extremely noisy data
  • Use for adaptive tuning: Stochastic(length: homod.DominantCycle)

API

classDiagram
    class Homod {
        +double MinPeriod
        +double MaxPeriod
        +double DominantCycle
        +bool IsHot
        +Homod(double minPeriod, double maxPeriod)
        +Homod(ITValuePublisher source, double minPeriod, double maxPeriod)
        +TValue Update(TValue input, bool isNew)
        +void Reset()
    }

Class: Homod

Parameter Type Default Range Description
minPeriod double 6.0 >0 Minimum period to detect
maxPeriod double 50.0 >minPeriod Maximum period to detect

Properties

  • DominantCycle (double): Current dominant cycle period in bars
  • IsHot (bool): Returns true when warmup is complete

Methods

  • Update(TValue input, bool isNew): Updates the indicator with a new data point

C# Example

using QuanTAlib;

// Configure for cycles between 6 and 50 bars
var homod = new Homod(minPeriod: 6, maxPeriod: 50);

// Update with streaming data
foreach (var bar in quotes)
{
    var result = homod.Update(new TValue(bar.Date, bar.Close));
    
    if (homod.IsHot)
    {
        double period = homod.DominantCycle;
        Console.WriteLine($"{bar.Date}: Dominant Cycle = {period:F1} bars");
        
        // Use cycle to tune Stochastic
        int adaptiveLength = (int)Math.Round(period);
        var adaptiveStoch = new Stochastic(adaptiveLength);
    }
}

// Batch calculation
var output = Homod.Calculate(sourceSeries, minPeriod: 6, maxPeriod: 50);