mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-01 19:27:44 +00:00
58 lines
2.1 KiB
Plaintext
58 lines
2.1 KiB
Plaintext
// Licensed under the Apache License, Version 2.0
|
|
// © mihakralj
|
|
//@version=6
|
|
indicator("Ehlers Moving Average Difference with Hann (MADH)", "MADH", overlay = false)
|
|
|
|
//@function Ehlers Moving Average Difference with Hann — dual Hann FIR filter
|
|
// difference expressed as a percentage. Zero-crossing oscillator.
|
|
//@param source Series to analyze (typically Close)
|
|
//@param shortLength Short Hann FIR window length (>= 1)
|
|
//@param dominantCycle Dominant cycle period (>= 2)
|
|
//@returns MADH oscillator value (percentage, zero-centered, unbounded)
|
|
//@reference Ehlers, J.F. (2021). "The MAD Indicator, Enhanced."
|
|
// Technical Analysis of Stocks & Commodities, Nov 2021.
|
|
//@optimized O(LongLength) per bar — FIR scan over two Hann-weighted windows
|
|
madh(series float source, simple int shortLength, simple int dominantCycle) =>
|
|
if shortLength < 1
|
|
runtime.error("ShortLength must be at least 1")
|
|
if dominantCycle < 2
|
|
runtime.error("DominantCycle must be at least 2")
|
|
|
|
int longLength = int(shortLength + dominantCycle / 2)
|
|
|
|
// --- Short Hann FIR filter ---
|
|
float filt1 = 0.0
|
|
float coef1 = 0.0
|
|
for k = 1 to shortLength
|
|
float w = 1.0 - math.cos(2.0 * math.pi * k / (shortLength + 1))
|
|
filt1 += w * nz(source[k - 1])
|
|
coef1 += w
|
|
if coef1 != 0.0
|
|
filt1 := filt1 / coef1
|
|
|
|
// --- Long Hann FIR filter ---
|
|
float filt2 = 0.0
|
|
float coef2 = 0.0
|
|
for k = 1 to longLength
|
|
float w = 1.0 - math.cos(2.0 * math.pi * k / (longLength + 1))
|
|
filt2 += w * nz(source[k - 1])
|
|
coef2 += w
|
|
if coef2 != 0.0
|
|
filt2 := filt2 / coef2
|
|
|
|
// --- MADH = percentage difference ---
|
|
float result = filt2 != 0.0 ? 100.0 * (filt1 / filt2 - 1.0) : 0.0
|
|
result
|
|
|
|
// ── Inputs ──
|
|
int p_short = input.int(8, "Short Length", minval = 1)
|
|
int p_cycle = input.int(27, "Dominant Cycle", minval = 2)
|
|
float p_src = input.source(close, "Source")
|
|
|
|
// ── Calculation ──
|
|
float out = madh(p_src, p_short, p_cycle)
|
|
|
|
// ── Plot ──
|
|
plot(out, "MADH", color.yellow, 2)
|
|
hline(0, "Zero", color.gray)
|