Enable Synthetic step and reversal with the default length 9, warm-up 100 and tolerance 0.000001. Inspect the Data Window at relative bars k shown above. Both confirmed event fields are available in test mode, but alerts are disabled there. With test mode off, the selected chart source drives both filters. The script is an independent implementation of the stated formulas and policies.
Pineify syntax check passed for this final source. The numerical fixture independently checks the formulas; syntax success alone does not establish chart parity or profitability.pine
//@version=6
indicator("EHMA and WMA Hull: controlled comparison", overlay=true, max_bars_back=1000)
n = input.int(9, "Base length", minval=1, maxval=500)
source = input.source(close, "Source")
warmup = input.int(100, "Minimum consecutive observations", minval=3)
epsilon = input.float(0.000001, "Slope tolerance in price units", minval=0)
isTest = input.bool(false, "Synthetic step and reversal")
halfLength = math.max(1, int(math.floor(n / 2.0)))
rootLength = math.max(1, int(math.floor(math.sqrt(n))))
emaSeeded(float x, int length) =>
float a = 2.0 / (length + 1.0)
float value = na
value := na(x) ? na : na(value[1]) ? x : a * x + (1.0 - a) * value[1]
value
wmaStrict(float x, int length) =>
float total = 0.0
for i = 0 to length - 1
total += (length - i) * x[i]
total / (length * (length + 1.0) / 2.0)
float sample = bar_index < 100 ? 100.0 : bar_index < 112 ? 110.0 : 100.0
float x = isTest ? sample : source
fast = emaSeeded(x, halfLength)
slow = emaSeeded(x, n)
ehma = emaSeeded(2.0 * fast - slow, rootLength)
fastW = wmaStrict(x, halfLength)
slowW = wmaStrict(x, n)
hma = wmaStrict(2.0 * fastW - slowW, rootLength)
var int consecutive = 0
consecutive := na(x) ? 0 : consecutive + 1
int required = math.max(warmup, n + rootLength - 1)
bool ready = consecutive >= required and not na(hma)
bool comparable = ready and ready[1] and ready[2]
float de = ehma - ehma[1]
float dh = hma - hma[1]
bool eUp = comparable and barstate.isconfirmed and de > epsilon and de[1] <= epsilon
bool eDown = comparable and barstate.isconfirmed and de < -epsilon and de[1] >= -epsilon
bool hUp = comparable and barstate.isconfirmed and dh > epsilon and dh[1] <= epsilon
bool hDown = comparable and barstate.isconfirmed and dh < -epsilon and dh[1] >= -epsilon
plot(ehma, "EHMA", color=color.blue, linewidth=2, style=plot.style_linebr)
plot(hma, "WMA Hull", color=color.orange, linewidth=2, style=plot.style_linebr)
plot(x, "Input", display=display.data_window)
plot(isTest ? bar_index - 99 : na, "Relative test bar k", display=display.data_window)
plot(ready ? 1 : 0, "Warm-up ready", display=display.data_window)
plot(eUp ? 1 : eDown ? -1 : 0, "EHMA confirmed slope event", display=display.data_window)
plot(hUp ? 1 : hDown ? -1 : 0, "HMA confirmed slope event", display=display.data_window)
alertcondition(not isTest and eUp, "EHMA upward slope onset", "EHMA slope became positive on a confirmed chart bar.")
alertcondition(not isTest and eDown, "EHMA downward slope onset", "EHMA slope became negative on a confirmed chart bar.")
alertcondition(not isTest and hUp, "HMA upward slope onset", "WMA Hull slope became positive on a confirmed chart bar.")
alertcondition(not isTest and hDown, "HMA downward slope onset", "WMA Hull slope became negative on a confirmed chart bar.")