Skip to content

fix(engine): make dead strategy.close semantically inert - #143

Merged
luisleo526 merged 1 commit into
mainfrom
codex/issue-141-dead-close-invariance
Aug 1, 2026
Merged

fix(engine): make dead strategy.close semantically inert#143
luisleo526 merged 1 commit into
mainfrom
codex/issue-141-dead-close-invariance

Conversation

@luisleo526

Copy link
Copy Markdown
Collaborator

Summary

  • make deferred-flip carry depend on runtime order state instead of the global script_has_strategy_close_ AST bit
  • retain the legacy bit as a no-op so existing generated classes remain source-compatible
  • add a metamorphic regression test proving an unreachable strategy.close cannot change bracket-exit fills
  • update existing characterization coverage and runtime documentation

Fixes #141.

Root cause

Codegen set script_has_strategy_close_ from textual AST presence, without reachability analysis. The runtime used that global bit to gate placement-time reversal carry, so adding an unreachable strategy.close changed later priced-entry quantities even though the executed broker commands were identical. A strategy.exit bracket can close the carry source on its own, so the runtime decision must use the order's captured state rather than unrelated source text.

Validation

  • full build succeeded
  • CTest: 123/123 passed
  • fresh locked Corpus A/B: 312/312 on both sides; 0 tier DOWN, 0 metric DOWN, 0 gate DOWN; the only changed probe remained Excellent and improved six metrics
  • full downstream strategy A/B: terminal classifications, grade rows, and trade tapes were identical; 0 tier DOWN, 0 countAbsDelta regressions, 0 Excellent-to-below-Strong regressions, 0 unresolved failures
  • downstream E+S remained neutral; owner explicitly approved the byte-identical no-regression result for this correctness fix

Copilot AI review requested due to automatic review settings August 1, 2026 08:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the deferred-flip carry behavior so that adding an unreachable strategy.close in Pine source cannot change runtime backtest fills. It removes the runtime dependency on the compile-time script_has_strategy_close_ AST bit, keeps that bit only for generated-code compatibility, and adds regression/characterization coverage plus runtime documentation updates.

Changes:

  • Remove script_has_strategy_close_ from the deferred-flip predicate in BacktestEngine::enter_market_from_flat.
  • Reframe script_has_strategy_close_ as a legacy, semantically inert compatibility member in engine headers and runtime docs.
  • Update/add tests to prove unreachable strategy.close is inert and adjust characterization expectations where carry behavior is now pinned correctly.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/engine_orders.cpp Drops the compile-time flag from the deferred-flip carry condition so behavior depends only on order-captured runtime state.
include/pineforge/engine.hpp Documents script_has_strategy_close_ as legacy compatibility only (no runtime semantic effect).
tests/test_strategy_pyramiding.cpp Removes direct flag forcing and adds a metamorphic regression test for issue #141.
tests/test_same_id_stop_replace.cpp Updates commentary to reflect the new deferred-flip predicate (no compile-time gate).
tests/test_close_all_coqueued_entry.cpp Updates characterization to match generated-script behavior and pins expected carry outcome.
docs/cheatsheet-runtime-and-execution.md Updates runtime cheat sheet to reflect that the flag no longer gates deferred-flip behavior and that brackets can arm carry behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +218 to +221
Bar bars[4] = {
{100, 101, 99, 100, 1000, 60'000},
{100, 101, 99, 100, 1000, 120'000}, // L fills; arm S + XL
{100, 101, 94, 95, 1000, 180'000}, // XL closes L; S untouched
@luisleo526
luisleo526 merged commit 8df08f2 into main Aug 1, 2026
8 checks passed
@luisleo526
luisleo526 deleted the codex/issue-141-dead-close-invariance branch August 1, 2026 08:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

An unreachable strategy.close changes backtest results (60 trades, PnL 182.00) via script_has_strategy_close_

2 participants