Files

41 lines
1.4 KiB
Plaintext
Raw Permalink Normal View History

// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Linear Trend Moving Average (LTMA)", "LTMA", overlay=true)
2026-02-23 17:27:35 -08:00
//@function Calculates LTMA using dual cascaded EMAs with linear trend extrapolation
//@param source Series to smooth
//@param period Lookback period (determines alpha = 2/(period+1))
2026-02-23 17:27:35 -08:00
//@returns LTMA value: lag-corrected EMA (equivalent to DEMA = 2·EMA1 EMA2)
//@description Removes the EMA lag by estimating the per-bar slope from the spread
// between two cascaded EMAs and projecting forward by exactly one lag interval.
// EMA1 lags by τ = (1−α)/α bars; EMA1EMA2 ≈ slope·τ; result = EMA1 + (EMA1EMA2).
// Initializing both EMAs to source on bar 1 gives zero warmup bias with no compensator needed.
ltma(series float source, simple int period) =>
float alpha = 2.0 / (period + 1)
float beta = 1.0 - alpha
2026-02-23 17:27:35 -08:00
var float ema1 = na
var float ema2 = na
float src = nz(source)
2026-02-23 17:27:35 -08:00
if na(ema1)
ema1 := src
ema2 := src
else
2026-02-23 17:27:35 -08:00
ema1 := alpha * src + beta * ema1
ema2 := alpha * ema1 + beta * ema2
// slope = EMA1 EMA2 ≈ slope_per_bar × lag
// result = EMA1 + slope × 1.0 → 2·EMA1 EMA2
ema1 + (ema1 - ema2)
// ---------- Main loop ----------
i_period = input.int(14, "Period", minval=1)
i_source = input.source(close, "Source")
ltma_value = ltma(i_source, period=i_period)
2026-02-23 17:27:35 -08:00
plot(ltma_value, "LTMA", color=color.yellow, linewidth=2)