mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-04 12:07:44 +00:00
35a6702b06
Deep review of all indicator categories verified .md headers against .cs WarmupPeriod, parameters, inputs, and outputs. Fixes include warmup corrections, parameter documentation, output type accuracy, and Pine Script alignment.
88 lines
3.7 KiB
Plaintext
88 lines
3.7 KiB
Plaintext
// Licensed under the Apache License, Version 2.0
|
|
// © mihakralj
|
|
//@version=6
|
|
indicator("Volatility Adjusted Moving Average (VAMA)", "VAMA", overlay=true)
|
|
|
|
//@function Calculates VAMA by adjusting MA length based on volatility ratio using ATR
|
|
//@param source Series to calculate VAMA from
|
|
//@param base_length Base lookback period for the moving average
|
|
//@param short_atr_period Short-term ATR period for current volatility measurement
|
|
//@param long_atr_period Long-term ATR period for reference volatility measurement
|
|
//@param min_length Minimum allowed adjusted length
|
|
//@param max_length Maximum allowed adjusted length
|
|
//@returns VAMA value
|
|
//@optimized Uses RMA compensator for ATR and circular buffer for O(1) sum updates
|
|
vama(series float source, simple int base_length, simple int short_atr_period=10, simple int long_atr_period=50, simple int min_length=5, simple int max_length=100) =>
|
|
var float prevClose = na
|
|
float tr1 = high - low
|
|
float tr2 = math.abs(high - prevClose)
|
|
float tr3 = math.abs(low - prevClose)
|
|
float trueRange = math.max(tr1, tr2, tr3)
|
|
prevClose := close
|
|
float EPSILON = 1e-10
|
|
var float raw_rma_short = 0.0
|
|
var float e_short = 1.0
|
|
var float raw_rma_long = 0.0
|
|
var float e_long = 1.0
|
|
float short_atr = na
|
|
float long_atr = na
|
|
if not na(trueRange)
|
|
float alpha_short = 1.0 / float(short_atr_period)
|
|
float beta_short = 1.0 - alpha_short
|
|
raw_rma_short := (raw_rma_short * (short_atr_period - 1) + trueRange) / short_atr_period
|
|
e_short := beta_short * e_short
|
|
short_atr := e_short > EPSILON ? raw_rma_short / (1.0 - e_short) : raw_rma_short
|
|
float alpha_long = 1.0 / float(long_atr_period)
|
|
float beta_long = 1.0 - alpha_long
|
|
raw_rma_long := (raw_rma_long * (long_atr_period - 1) + trueRange) / long_atr_period
|
|
e_long := beta_long * e_long
|
|
long_atr := e_long > EPSILON ? raw_rma_long / (1.0 - e_long) : raw_rma_long
|
|
float volatility_ratio = not na(short_atr) and not na(long_atr) and short_atr != 0.0 ? long_atr / short_atr : 1.0
|
|
float calc_length = base_length * volatility_ratio
|
|
int adjusted_length = int(math.max(min_length, math.min(max_length, calc_length)))
|
|
var array<float> buffer = array.new_float(max_length, na)
|
|
var int head = 0
|
|
var float sum = 0.0
|
|
var int valid_count = 0
|
|
if array.size(buffer) != max_length
|
|
buffer := array.new_float(max_length, na)
|
|
head := 0
|
|
sum := 0.0
|
|
valid_count := 0
|
|
float oldest = array.get(buffer, head)
|
|
if not na(oldest)
|
|
sum -= oldest
|
|
valid_count -= 1
|
|
if not na(source)
|
|
sum += source
|
|
valid_count += 1
|
|
array.set(buffer, head, source)
|
|
head := (head + 1) % max_length
|
|
float avg = valid_count > 0 ? sum / valid_count : source
|
|
int actual_count = math.min(valid_count, adjusted_length)
|
|
float partial_sum = 0.0
|
|
int partial_count = 0
|
|
for i = 0 to actual_count - 1
|
|
int idx = (head - 1 - i + max_length) % max_length
|
|
float val = array.get(buffer, idx)
|
|
if not na(val)
|
|
partial_sum += val
|
|
partial_count += 1
|
|
partial_count > 0 ? partial_sum / partial_count : nz(avg, source)
|
|
|
|
// ---------- Main loop ----------
|
|
|
|
// Inputs
|
|
i_base_length = input.int(20, "Base Length", minval=1)
|
|
i_source = input.source(close, "Source")
|
|
i_short_atr = input.int(10, "Short ATR Period", minval=1)
|
|
i_long_atr = input.int(50, "Long ATR Period", minval=1)
|
|
i_min_length = input.int(5, "Minimum Length", minval=1)
|
|
i_max_length = input.int(100, "Maximum Length", minval=1)
|
|
|
|
// Calculation
|
|
vama_value = vama(i_source, i_base_length, i_short_atr, i_long_atr, i_min_length, i_max_length)
|
|
|
|
// Plot
|
|
plot(vama_value, "VAMA", color=color.yellow, linewidth=2)
|