Ehlers Laguerre Filter with Hanning window afl and indipendent gamma's

Taking inspiration from a recent article by John Ehlers on Laguerre TASC filters in July 2025, he mentioned the possibility of using a Hanning window to increase the performance of the filter itself.
The Laguerre filter is already an excellent “fast smoother.” I tried to implement the Hanning window by recreating the function in Amibroker with the help of AI (kimi.com).
The Hanning removes high-frequency micro-oscillations that the Laguerre filter does not.
I also added the option of having two separate ranges in the parameters so that the two filters can be tested with different parameters and together. The ribbon filter at the bottom makes it easier to read the indicators with possible trading signals.
I also added part of the code for backtesting to the formula, but it is not complete. The goal here was to display the two filters together to check their plotting on the chart and possibly reap some benefits. The figure shows Italian mini futures with the two filters with these parameters:

Hanning length: 20 periods
Laguerre filter: 10 periods
Laguerre gamma: 0.8
Laguerre gamma + Hanning: 0.2

// =========================================================
//  Laguerre Filter – With vs Without Hanning window comparison
//  Ribbon at the end to trading signals
//  Some code for backtesting (not complete)
//  INDEPENDENT Gamma's
//  A Chisari Marco's idea inspired by John Ehlers TASC article - July 2025
//  Using IA Using AI via https://www.kimi.com
// =========================================================

SetPositionSize( 1, spsShares ); // for future
//SetPositionSize( 3000, spsShares ); // for stocks

_SECTION_BEGIN("Laguerre Dual-Gamma");

/* ------------ Parameters ------------ */
src      = ParamField("Source", 3);          // Close (default)
HanN     = Param("Hanning Length", 0, 0, 50, 1);
Per      = Param("Laguerre Period", 30, 3, 100, 1);
GammaRaw = Param("Gamma – Laguerre RAW",  0.5, 0.0, 0.999, 0.01);
GammaHan = Param("Gamma – Laguerre+HAN",  0.5, 0.0, 0.999, 0.01);

/* ------------ SMOOTHING HANNING WINDOW------------ */
function HanningSmooth(p, n)
{
    local i, j, w, sumW, sumV, out;
    out = p;
    if (n > 1)
    {
        for (i = n - 1; i < BarCount; i++)
        {
            sumV = 0;  sumW = 0;
            for (j = 0; j < n; j++)
            {
                w = 0.5 * (1 - cos(2 * 3.1415926 * j / (n - 1)));
                sumV += p[i - j] * w;
                sumW += w;
            }
            out[i] = sumV / sumW;
        }
    }
    return out;
}

/* ------------ ULTIMATE SMOOTHER ------------ */
function UltimateSmoother(a, period)
{
    local a1, c2, c3, c1, out, i;
    a1 = exp(-1.414 * 3.14159 / period);
    c2 = 2 * a1 * cos(1.414 * 3.14159 / period);
    c3 = -a1 * a1;
    c1 = (1 + c2 - c3) / 4;
    out = a;
    for (i = 4; i < BarCount; i++)
        out[i] = (1 - c1) * a[i] +
                 (2 * c1 - c2) * a[i-1] -
                 (c1 + c3) * a[i-2] +
                 c2 * out[i-1] + c3 * out[i-2];
    return out;
}

/* ------------ LAGUERRE FILTER------------ */
function LaguerreFilter(data, gamma)
{
    local l0, l1, l2, l3, l4, l5, i;
    l0 = data;
    l1 = l2 = l3 = l4 = l5 = data;
    for (i = 1; i < BarCount; i++)
    {
        l1[i] = (1 - gamma) * l0[i-1] + gamma * l1[i-1];
        l2[i] = (1 - gamma) * l1[i-1] + gamma * l2[i-1];
        l3[i] = (1 - gamma) * l2[i-1] + gamma * l3[i-1];
        l4[i] = (1 - gamma) * l3[i-1] + gamma * l4[i-1];
        l5[i] = (1 - gamma) * l4[i-1] + gamma * l5[i-1];
    }
    return (l0 + 4 * l1 + 6 * l2 + 4 * l3 + l5) / 16;
}

/* ------------ FILTER CALCULATIONS ------------ */
usHan  = UltimateSmoother(HanningSmooth(src, HanN), Per);
usRaw  = UltimateSmoother(src, Per);

LagHan = LaguerreFilter(usHan, GammaHan);   // <-- GammaHan
LagRaw = LaguerreFilter(usRaw, GammaRaw);   // <-- GammaRaw

/* ------------ PLOTS ------------ */
Plot(src,   "Price", colorBlack, styleCandle);
Plot(LagHan, "Laguerre+Hann (?="+NumToStr(GammaHan,2)+")", colorYellow, styleLine | styleThick);
Plot(LagRaw, "Laguerre RAW   (?="+NumToStr(GammaRaw,2)+")", colorRed,    styleLine | styleThick);

_SECTION_END();

/* ------------ TRADING LOGIC ------------ */
pos   = LagHan < src AND LagRaw < src;
Sell  = LagHan > src AND LagRaw > src;
Short = Sell AND Ref(Sell, -1);
Cover = LagRaw < src;

Buy   = ExRem(pos, Short OR Sell);
Short = ExRem(Short, Buy OR Cover);

Ribbon_kol = IIf(pos, colorAqua, IIf(Sell, colorPink, colorWhite));
Plot(10, "Ribbon", Ribbon_kol, styleOwnScale | styleArea | styleNoLabel, -0.5, 100);
3 Likes

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.