Files
Miha Kralj 35a6702b06 fix(docs): correct .md documentation across errors, dynamics, filters, forecasts, momentum, numerics, oscillators, reversals, statistics, trends, volatility, volume
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.
2026-03-10 18:38:23 -07:00

44 lines
1.7 KiB
Plaintext

// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Ahrens Moving Average (AHRENS)", "AHRENS", overlay=true)
//@function Calculates Ahrens Moving Average using midpoint correction between current and lagged MA values
//@param source Series to smooth
//@param period Lookback length for the lag component and smoothing divisor
//@returns Ahrens MA value — a recursive IIR filter that adjusts toward source minus the midpoint of its current and lagged states
//@algorithm ahma = ahma[1] + (source - (ahma[1] + ahma[period]) / 2) / period
//@reference Richard D. Ahrens, "Build A Better Moving Average" (Stocks & Commodities V.31:11, October 2013)
//@optimized O(1) per bar via circular buffer for lagged MA state; O(period) memory for the ring buffer
ahrens(series float source, simple int period) =>
// Circular buffer to store past ahma values for period-bar lookback
var array<float> buffer = array.new_float(period, na)
var int head = 0
var float result = na
if not na(source)
float prev = nz(result, source)
float lagged = nz(array.get(buffer, head), source)
// Ahrens formula: ahma = prev + (source - midpoint(prev, lagged)) / period
float midpoint = (prev + lagged) * 0.5
result := prev + (source - midpoint) / float(period)
// Store current result in circular buffer and advance head
array.set(buffer, head, result)
head := (head + 1) % period
result
// ---------- Main loop ----------
// Inputs
i_period = input.int(9, "Period", minval=1)
i_source = input.source(close, "Source")
// Calculation
ahrens_value = ahrens(i_source, i_period)
// Plot
plot(ahrens_value, "AHRENS", color=color.yellow, linewidth=2)