// This Pine Script® code is licensed under Apache-2.0
// SPDX-License-Identifier: Apache-2.0
// © PineForge contributors 2026
//
// PF probe 100 — dual-SMA crossover entries
// Clean-room: written from validation goal, not from source.
//
// Purpose: exercises the canonical dual-MA crossover surface with
// `ta.sma(close, fast)` and `ta.sma(close, slow)` plus
// `ta.crossover` / `ta.crossunder` for entry triggers. SMA is the
// cleanest TA building block (no recursive seed), so any TV/engine
// drift here points at how the engine's `crossover` helper detects
// the strict inequality flip from one bar to the next — and at how
// the SMA-windowing handles its first `slow` bars of warmup
// (during which TradingView's chart, which has bars before the CSV
// start, may already report a non-na SMA where the engine reports
// `na`).
//
// Validation goal: bit-exact trade list against TradingView's broker
// emulator on the reference 15m feed. Pass = every long/short 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 100 - dual sma cross", shorttitle="PF_p100_DSMA",
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_fast = input.int(9, "Fast SMA length", minval=2, maxval=100)
int i_slow = input.int(21, "Slow SMA length", minval=3, maxval=200)
// ---- the two SMAs --------------------------------------------------
float fast_ma = ta.sma(close, i_fast)
float slow_ma = ta.sma(close, i_slow)
// ---- crossover-driven entries -------------------------------------
bool golden_cross = ta.crossover(fast_ma, slow_ma)
bool death_cross = ta.crossunder(fast_ma, slow_ma)
if golden_cross and strategy.position_size <= 0
if strategy.position_size < 0
strategy.close("S", comment="flip flat")
strategy.entry("L", strategy.long, comment="golden cross")
if death_cross and strategy.position_size >= 0
if strategy.position_size > 0
strategy.close("L", comment="flip flat")
strategy.entry("S", strategy.short, comment="death cross")