Files
QuanTAlib/lib/trends_IIR/frama/frama.pine
T
Miha Kralj 24e86d762a Add documentation links for various volatility indicators and channels
- Updated BBWN, BBWP, CCV, CV, CVI, EWMA, GKV, HLV, HV, Jvolty, JVOLTYN, MASSI, NATR, RSV, RV, RVI, TR, UI, VOV, VR, YZV indicators with documentation links.
- Added documentation links for Aberration, Acceleration Bands, Andrews' Pitchfork, Adaptive Price Zone, ATR Bands, Bollinger Bands, Center of Gravity, Donchian Channels, Decay Min-Max Channel, Detrended Synthetic Price, EACP, EBSW, HOMOD, Jurik Volatility Bands, Keltner Channel, MA Envelope, Min-Max Channel, Price Channel, Regression Channels, Standard Deviation Channel, Stoller Average Range Channel, Super Trend Bands, Ultimate Bands, Ultimate Channel, VWAP Bands, and VWAP with Standard Deviation Bands.
2026-02-18 11:55:48 -08:00

58 lines
2.0 KiB
Plaintext

// The MIT License (MIT)
// © mihakralj
//@version=6
indicator("Ehlers Fractal Adaptive Moving Average (FRAMA)", "FRAMA", overlay=true)
//@function Calculates Ehlers Fractal Adaptive Moving Average
//@param period Lookback period (forced to even, >= 2)
//@returns FRAMA value with fractal-adaptive smoothing
//@optimized Uses fractal dimension for adaptive alpha with O(n) complexity per bar
frama_strict(simple int period) =>
int p = math.max(2, period)
int pe = (p % 2 == 0) ? p : (p + 1)
int h = int(pe / 2)
// Price series per Ehlers FRAMA (commonly HL2)
float price = hl2
// Require enough history and non-NA ranges over the needed windows
bool ready =
bar_index >= pe - 1 and
not na(price) and
not na(ta.highest(high, pe)) and not na(ta.lowest(low, pe)) and
not na(ta.highest(high, h)) and not na(ta.lowest(low, h)) and
not na(ta.highest(high[h], h)) and not na(ta.lowest(low[h], h))
var float fr = na
if ready
// Ranges per Ehlers:
// N1: first half range / half
// N2: second half range / half (shifted by half)
// N3: full range / full
float n1 = (ta.highest(high, h) - ta.lowest(low, h)) / h
float n2 = (ta.highest(high[h], h) - ta.lowest(low[h], h)) / h
float n3 = (ta.highest(high, pe) - ta.lowest(low, pe)) / pe
float alpha = 1.0
if n1 > 0 and n2 > 0 and n3 > 0
float dimen = (math.log(n1 + n2) - math.log(n3)) / math.log(2.0)
alpha := math.exp(-4.6 * (dimen - 1.0))
alpha := math.max(0.01, math.min(1.0, alpha))
// Warm-start: first computed value seeds to price
float prev = nz(fr[1], price)
fr := alpha * price + (1.0 - alpha) * prev
else
fr := na
fr
// -------- Main --------
i_period = input.int(16, "Period (even enforced)", minval=2)
frama_value = frama_strict(i_period)
plot(frama_value, "FRAMA (strict)", color=color.yellow, linewidth=2)