Files
QuanTAlib/lib/trends_IIR/ltma/ltma.pine
T

61 lines
2.0 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// The MIT License (MIT)
// © mihakralj
//@version=6
indicator("Linear Trend Moving Average (LTMA)", "LTMA", overlay=true)
//@function Calculates Linear Trend MA using dual EMA with linear extrapolation
//@param source Series to smooth
//@param period Lookback period (determines alpha = 2/(period+1))
//@returns LTMA value: EMA-based linear trend projection from first bar
//@description LTMA tracks both level and slope using two cascaded EMAs,
// then extrapolates the linear trend forward. Unlike DEMA (which cancels
// first-order lag via 2×EMA1 EMA2), LTMA estimates the instantaneous
// slope from the EMA difference and projects it forward by the full period:
// slope = (EMA1 EMA2) / (decay 1)
// LTMA = EMA1 + slope × period
// where decay = (1 alpha). This produces a predictive moving average
// that follows linear trends with zero steady-state error.
// Uses §2 exponential warmup compensator on both EMAs (e*=beta,
// c=1/(1-e)) for valid output from bar 1.
ltma(series float source, simple int period) =>
if period <= 0
runtime.error("Period must be greater than 0")
float alpha = 2.0 / (period + 1)
float beta = 1.0 - alpha
var bool warmup = true
var float e = 1.0
var float ema1 = 0.0
var float ema2 = 0.0
var float result = source
float src = nz(source)
ema1 := alpha * (src - ema1) + ema1
ema2 := alpha * (ema1 - ema2) + ema2
if warmup
e *= beta
float c = 1.0 / (1.0 - e)
float comp1 = c * ema1
float comp2 = c * ema2
float slope = comp1 - comp2
result := comp1 + slope * period
warmup := e > 1e-10
else
float slope = ema1 - ema2
result := ema1 + slope * period
result
// ---------- Main loop ----------
// Inputs
i_period = input.int(14, "Period", minval=1)
i_source = input.source(close, "Source")
// Calculation
ltma_value = ltma(i_source, period=i_period)
// Plot
plot(ltma_value, "LTMA", color=color.yellow, linewidth=2)