Files
QuanTAlib/lib/channels/apchannel/apchannel.pine
T

55 lines
1.9 KiB
Plaintext

// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Adaptive Price Channel (APCHANNEL)", "APCHANNEL", overlay=true)
//@function Calculates the Adaptive Price Channel using dual EMA on highs and lows.
//@doc The channel applies exponential smoothing to price highs and lows independently,
// creating a dynamic envelope that "remembers" significant extremes while gradually
// fading their influence. Unlike fixed-window Donchian channels that drop extremes
// abruptly, APCHANNEL decays them smoothly (leaky integration).
//@param alpha Smoothing factor (0 < alpha <= 1). Higher = faster decay, shorter memory.
//@returns tuple of [middle, upper, lower] band values
//@optimized O(1) per bar via EMA recursion; uses FMA pattern: decay*prev + alpha*new
apchannel(simple float alpha) =>
if alpha <= 0.0 or alpha > 1.0
runtime.error("Alpha must be > 0 and <= 1")
[float(na), float(na), float(na)]
float decay = 1.0 - alpha
// EMA of highs (upper band)
var float high_ema = na
float valid_high = nz(high, nz(high_ema, 0.0))
if na(high_ema)
high_ema := valid_high
else
high_ema := decay * high_ema + alpha * valid_high
// EMA of lows (lower band)
var float low_ema = na
float valid_low = nz(low, nz(low_ema, 0.0))
if na(low_ema)
low_ema := valid_low
else
low_ema := decay * low_ema + alpha * valid_low
// Midpoint
float mid = (high_ema + low_ema) / 2.0
[mid, high_ema, low_ema]
// ---------- Main loop ----------
// Inputs
i_alpha = input.float(0.2, "Alpha (smoothing factor)", minval=0.01, maxval=1.0, step=0.01)
// Calculation
[middle, upper, lower] = apchannel(i_alpha)
// Plot
plot(middle, "Middle", color=color.yellow, linewidth=2)
p1 = plot(upper, "Upper", color=color.new(color.blue, 50), linewidth=1)
p2 = plot(lower, "Lower", color=color.new(color.blue, 50), linewidth=1)
fill(p1, p2, color=color.new(color.blue, 90))