Run this on a standard one-day stock or ETF chart with a point value of one. The plots expose the stress classification, position and marked equity change for bar-by-bar review. The script does not calculate a cross-asset portfolio or a statistical alpha estimate. Keep the event settings fixed when comparing trend lookbacks.
The orange window starts on the bar after detection. Syntax validation checks the source, not trading performance. Zero slippage is a transparent baseline assumption, not an execution estimate.pine
//@version=6
strategy("Crisis alpha: signal and event audit", overlay = true,
initial_capital = 100000, pyramiding = 0,
margin_long = 100, margin_short = 100,
commission_type = strategy.commission.percent, commission_value = 0.10,
slippage = 0, calc_on_every_tick = false,
calc_on_order_fills = false, process_orders_on_close = false)
int trendBars = input.int(50, "Trend lookback", minval = 1, maxval = 2000)
int stressBars = input.int(60, "Stress high lookback", minval = 2, maxval = 2000)
int windowBars = input.int(20, "Forward event bars", minval = 1, maxval = 252)
float triggerPct = input.float(10.0, "Trigger drawdown (%)", minval = 0.1, maxval = 99.0)
float resetPct = input.float(5.0, "Rearm drawdown (%)", minval = 0.1, maxval = 99.0)
int shares = input.int(100, "Shares per direction", minval = 1)
if not timeframe.isdaily or timeframe.multiplier != 1
runtime.error("Use a standard one-day candle chart.")
if syminfo.pointvalue != 1
runtime.error("This example requires a point value of one per share.")
if resetPct >= triggerPct
runtime.error("Rearm drawdown must be smaller than trigger drawdown.")
if na(close) or close <= 0
runtime.error("Positive closing prices are required.")
bool ready = bar_index + 1 >= math.max(stressBars, trendBars + 1)
float highClose = ta.highest(close, stressBars)
float drawdown = ready ? close / highClose - 1.0 : na
int direction = ready ? (close > close[trendBars] ? 1 : close < close[trendBars] ? -1 : 0) : 0
var int remaining = 0
var bool armed = true
bool inWindow = remaining > 0
bool trigger = false
if barstate.isconfirmed and ready
if inWindow
remaining -= 1
else
if close > highClose * (1.0 - resetPct / 100.0)
armed := true
if armed and close <= highClose * (1.0 - triggerPct / 100.0)
trigger := true
armed := false
remaining := windowBars
if direction == 1 and strategy.position_size <= 0
strategy.entry("Long", strategy.long, qty = shares)
else if direction == -1 and strategy.position_size >= 0
strategy.entry("Short", strategy.short, qty = shares)
else if direction == 0 and strategy.position_size != 0
strategy.close_all(comment = "Equal reference price")
bgcolor(inWindow ? color.new(color.orange, 85) : na, title = "Forward stress window")
plotshape(trigger, title = "Stress detected at close", style = shape.triangledown,
location = location.abovebar, color = color.orange, size = size.tiny)
plot(ready ? (inWindow ? 1 : 0) : na, "Stress interval: 1 or 0", display = display.data_window)
plot(drawdown * 100.0, "Rolling drawdown (%)", display = display.data_window)
plot(strategy.position_size, "Shares held at close", display = display.data_window)
plot(strategy.equity - strategy.equity[1], "Marked equity change", display = display.data_window)