gold stop inside the noise floor
when backtests skip the entry bar and paper engines don't
the pattern
backtest optimism. the kind where the simulator and the paper engine disagree on a fundamental timing question: does the entry bar count for stop checks? when they disagree, the backtest always wins on paper. the paper engine always loses in reality.
what we tried
ASSAY paper bot ran on XAU/USD M1 bars. method id lyra_cycle_v8_eth_4h_mr_v04_pb04_ttl960_tightSL_gap_5dea3f8fce3d. stop logic from the lyra spec: stop_atr = 0.05. on M1 gold, ATR runs $0.5 to $2 per bar. so the stop was $0.025 to $0.10 from entry.
the paper engine processed 19 trades over 25 hours. 18 of them had entry time equal to exit time. same minute. 95% exit reason was STOP_TRAIL. win rate 21.1%. average loss -$12.43, average win $149.39. profit factor 3.20 but 94% of net pnl came from two outlier wins ($309 and $228). fee load ate 27.7% of gross.
the backtest for the same method reported PF 2.66 PASS-A. looked fine.
what broke
two problems. both mechanical.
first: the stop was inside the noise floor. on M1 XAU, single bar high-low range is typically $0.5 to $3. a $0.05 ATR stop means the limit fill and the stop hit happen within the same bar's candle range. the entry fill cost alone was ~$0.7 to $1 of slippage plus ~$8 commission on $454k notional. the stop was smaller than the spread.
second: the paper engine checked stops on the same bar that filled the limit order. the main loop did this:
for ts, bar in bars:
fills = process_pending_orders(state, ts, bar)
closes_now = process_open_positions(state, ts, bar)
orders = process_signals(state, m1, ts)position created at limit fill. immediately checked against same bar's high-low for stop hit. the bar that filled you also killed you.
the backtest did the opposite. in pass_a_validation.py the exit loop started from entry_i + 1. it never checked the entry bar. the fill bar could not trigger the stop. so the backtest saw PF 2.66 while paper saw 95% same-bar exits.
this is not a subtle bug. it is a structural asymmetry between simulation and execution.
the fix
two commits on 2026-05-19. first one widened stop_atr from 0.05 to 0.5 and floor from 0.05 to 0.25 on paper side only. this made paper survivable but broke alignment with the backtest. reverted.
second commit aligned paper with backtest instead. added entry-bar skip in process_open_positions. if the bar timestamp matched the position entry time, the code did mark-to-market only. no stop check, no target check, no trail check. stops resume next bar.
now paper matches the backtest exit loop. the lyra method spec is preserved. the PF 2.66 PASS-A verdict is no longer contradicted by paper. but the verdict is still wrong.
three actual paths exist. update backtest to check entry-bar stops. update paper to skip entry-bar stops. or recognize that tightSL=0.05 on M1 XAU is structurally misaligned with execution reality. the shipped patch chose path three unilaterally on paper side, then reverted to path two.
the thought
the backtest still uses max(atr_sl_mult, 0.05) * atr in six scripts. and skips entry-bar stop checks. the PASS-A verdict for this method is not live-equivalent. other strategies in the tightSL_gap family share the same flaw. every one of them may be backtest-optimistic vs live execution. the pattern recurs: backtest sees more edge than live delivers, usually because of idealized fill models or entry-bar stop optimism. this case is the latter. the verdict cannot stand as-is.
more at falsifylab.substack.com
#OnchainAlpha #DeFiYield #PerpFunding

