// This Pine Script® code is licensed under Apache-2.0
// SPDX-License-Identifier: Apache-2.0
// © PineForge contributors 2026
//
// Barstate-magnifier probe 01a — barstate.isconfirmed, magnifier ON
//
// Purpose: barstate.isconfirmed must fire exactly once per chart bar
// regardless of magnifier sub-bar ticks. With magnifier ON the
// runtime risk is is_first_tick_/is_last_tick_ getting flipped on the
// last sample of the last sub-bar and the gated branch firing more
// than once or on the wrong bar (Pine #4). Pair with 01b (magnifier
// OFF) — the fill bar must be byte-identical between the two runs.
//
// Trade shape: long-only. EMA(9/21) crossover signal latches when
// detected; entry executes only on the bar whose close is confirmed
// (barstate.isconfirmed). Exit on opposite cross also confirmed.
//
// TV setup: 15m chart, ETH-USDT-USDT, magnifier ON. Export trades to
// trades.csv. Compare against 01b/trades.csv for bar-identical fills.
//@version=6
strategy("PF barstate-magnifier probe 01a - isconfirmed ON", shorttitle="BSM_01a_ON", overlay=true,
initial_capital=1000000, use_bar_magnifier=true,
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)
emaFast = ta.ema(close, 9)
emaSlow = ta.ema(close, 21)
var bool pendingLong = false
var bool pendingExit = false
if ta.crossover(emaFast, emaSlow)
pendingLong := true
if ta.crossunder(emaFast, emaSlow)
pendingExit := true
if barstate.isconfirmed and pendingLong and strategy.position_size == 0
strategy.entry("L", strategy.long, qty=1, comment="confirmed long")
pendingLong := false
if barstate.isconfirmed and pendingExit and strategy.position_size > 0
strategy.close("L", comment="confirmed exit")
pendingExit := false