Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(fills): normalize qty_percent when freezing a deferred layered exit qty#77

Merged
luisleo526 merged 1 commit into
mainfrom
fix/qty-percent-reconcile-deferred-layered-exit
Jul 7, 2026
Merged

fix(fills): normalize qty_percent when freezing a deferred layered exit qty#77
luisleo526 merged 1 commit into
mainfrom
fix/qty-percent-reconcile-deferred-layered-exit

Conversation

@luisleo526

Copy link
Copy Markdown
Collaborator

Summary

A layered strategy.exit group (a partial qty_percent leg + a 100% sibling) armed while the position is FLAT goes through the deferred-reconcile path reconcile_deferred_layered_exits (src/engine_fills.cpp:922-939). That path froze each leg's o.qty to its reserved slice but left the 100% sibling's o.qty_percent at 100.

On a later per-bar re-arm of the partial sibling, the compute_exit_reserved_qty guard (src/engine_strategy_commands.cpp:1023-1033) read that stale qty_percent=100 as a still-pending full exit, dropped the re-issued partial, and the 100% leg re-expanded to flatten the whole position at its stop — over-closing a TP1(50%) + TP2(100%) bracket (100% single close instead of two 50% legs).

Fix

Set o.qty_percent consistent with the o.qty reconcile already froze (one line, mirrors the live-armed normalization at engine_strategy_commands.cpp:1020):

if (live_pos > kQtyEpsilon) o.qty_percent = (res / live_pos) * 100.0;

Gated by reconcile's existing leg_count >= 2 && has_partial condition. Live-armed layered exits (armed inside if position_size > 0) never enter reconcile — they normalize at arm time — so they are untouched, as are non-layered brackets.

Gate (fresh-context R7)

  • cmake --build build --target pineforge clean
  • ctest: 79/79 passing
  • run_corpus.sh: 239 excellent / 12 strong / 1 anomaly, fail=0 — corpus artifacts byte-identical (the deferred-layered path has no corpus coverage; golden bracket-partial-exit-qty-percent-01 is live-armed)
  • scraper data sweep across 8 qty_percent sentinels + 2 3commas DCA/grid: 0 up / 0 down, run_err=0

The originating strategy is coverage-capped by an unrelated HTF-warmup ceiling, so this is a correctness/fidelity fix rather than a scoreboard move; ~15 data/ layered-exit strategies exercise the construct.

🤖 Generated with Claude Code

…it qty

reconcile_deferred_layered_exits froze each leg's qty to its reserved
slice but left the 100% sibling's qty_percent at 100. On a later re-arm
of the partial sibling, the compute_exit_reserved_qty guard read that
stale 100 as a still-pending FULL exit, dropped the re-issued partial,
and the 100% leg re-expanded to flatten the whole position at its stop —
over-closing a layered TP1(50%)+TP2(100%) bracket that was armed while
flat (the deferred path; live-armed groups normalize at arm time).

Set qty_percent consistent with the qty reconcile already froze (mirrors
the live-armed normalization in compute_exit_reserved_qty). The change is
gated by reconcile's leg_count>=2 + has_partial condition, so live-armed
layered exits and non-layered brackets are untouched.

Gate (R7, fresh context): cmake pineforge clean; ctest 79/79; run_corpus
239 exc/12 strong/1 anomaly fail=0 (byte-identical corpus); data sweep
0 up/0 down across 8 qty_percent sentinels + 2 3commas DCA/grid, run_err=0.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@luisleo526 luisleo526 merged commit c8b4ac4 into main Jul 7, 2026
5 checks passed
@luisleo526 luisleo526 deleted the fix/qty-percent-reconcile-deferred-layered-exit branch July 7, 2026 19:54
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.

1 participant