// This Pine Script® code is licensed under Apache-2.0
// SPDX-License-Identifier: Apache-2.0
// © PineForge contributors 2026
//
// PF probe 105 — volatility-expansion close break
// Clean-room: written from validation goal, not from source.
//
// Purpose: exercises the rolling `ta.stdev(close, 20)` pair with
// `ta.sma(close, 20)` as a Bollinger-style expansion band, then
// fires entries when the close itself breaks past the upper or
// lower band. Two engine surfaces are pinned:
// (1) `ta.stdev` denominator convention — sample (n-1) vs
// population (n) divergence shifts the band slightly and
// flips a few borderline-bar break events.
// (2) Strict close-vs-band comparison ordering relative to the
// band's own update on the same bar (the band is computed
// from the same close that's being compared to it).
//
// Validation goal: bit-exact trade list against TradingView's broker
// emulator on the reference 15m feed. Pass = every break-driven
// entry fires on the same bar TradingView places it.
//
// TV setup: 15m chart, ETH-USDT-USDT (Binance USDT-M Perpetual). Full
// window matching corpus/data/ohlcv_ETH-USDT-USDT_15m.csv. Strategy
// properties: leave defaults from script header. Export "List of
// trades" → tv_trades.csv.
//@version=6
strategy("PF probe 105 - volty expansion close", shorttitle="PF_p105_VEXP",
overlay=true, initial_capital=1000000,
commission_type=strategy.commission.percent, commission_value=0,
slippage=0, default_qty_type=strategy.fixed, default_qty_value=1,
pyramiding=1, process_orders_on_close=false)
// ---- inputs --------------------------------------------------------
int i_len = input.int(20, "Baseline / stdev length", minval=2, maxval=200)
float i_mult = input.float(2.0,"Expansion multiple", minval=0.5, maxval=10.0, step=0.1)
// ---- baseline + expansion bands -----------------------------------
float baseline = ta.sma(close, i_len)
float vol = ta.stdev(close,i_len)
float upper = baseline + vol * i_mult
float lower = baseline - vol * i_mult
// ---- close-vs-band breakout entries -------------------------------
bool bull_break = close > upper
bool bear_break = close < lower
if bull_break and strategy.position_size <= 0
if strategy.position_size < 0
strategy.close("S", comment="flip flat")
strategy.entry("L", strategy.long, comment="upper-band break")
if bear_break and strategy.position_size >= 0
if strategy.position_size > 0
strategy.close("L", comment="flip flat")
strategy.entry("S", strategy.short, comment="lower-band break")