Skip to content

Partial exits: exits share each trade's quantity in placement order - #432

Merged
alexgrover merged 2 commits into
devfrom
fix/partial-exit-allocation
Oct 14, 2026
Merged

alexgrover merged 2 commits into
devfrom
fix/partial-exit-allocation

Conversation

@alexgrover

@alexgrover alexgrover commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

Builds on #431 (merged): it uses its path helpers and per-trade trailing state.

Several strategy.exit orders on one entry, measured on TradingView (BINANCE:BTCUSDT 1h, CME ES, Pine v6) with 11 new partial-exit probes.

Changes

Exits share each trade's quantity in placement order (exitCapacity). Each exit used to close up to its own qty / qty_percent of the position, so a full-size stop placed after a 50% target closed everything. On TradingView, each exit takes its share out of what the exits placed before it, and still working, have not taken. The share is its qty_percent of the trade's entry quantity, its absolute qty (oldest trades first), or all the rest.

  • 50% target first, then a stop: the stop closes half (pe01);
  • the stop placed first takes everything, and the target never fills (pe02);
  • 30% / 30% / rest (pe03); 60% + 60% gives the second 40% (pe04); qty = 3 against 1 open takes all (pe05);
  • an exit that re-calls an id keeps its place, also after it filled on one of the trades (pe06, pe11);
  • on whole contracts, 50% of 1 contract takes the contract (x10 ES 1D);
  • under pyramiding, the reservation is per trade: an earlier 50% exit holds half of each trade (pe11).

Exit orders are taken in path order. When two exit orders trigger on one bar, the one whose first leg the path reaches first fills first (pe01/03/04).

strategy.close with qty / qty_percent keeps the exits working. Only a full close cancels the entry's pending exits. After a 50% close, the 50% target still fills on that bar (pe07).

A reversal takes its exits with it. Exits without from_entry that were placed while a position was open die when a reversal closes that position, as they already did when it went flat. The new position gets the exits placed for it (pe11).

Tests

tests/namespaces/strategy/partial-exits.test.ts (8 tests): the placement-order cases, over-allocation, qty over the position, whole contracts, a re-called exit after a fill on an older trade, a partial strategy.close, and the reversal. 7 fail on the base branch; "stop placed first takes all" guards existing behavior.

Results against TradingView (compared with dev, with #431 included)

  • Partial-exit probes: pe01–pe10 identical (all on dev diverged from trade 0–3); pe11 first divergence trade 0 → 43.
  • Controlled cases 10 and 10 @d, x10 BTC 1h and x10 ES 1D: identical. x10 AAPL 1D / 1h: trade 0 / 3 → 2 / 9 (AAPL off-tick prices).
  • Public strategies: quantumforex-sniperfusion becomes identical.
  • Premium backtesters: as Trailing stops and fills along the bar path #431.
  • No run gets worse.
  • Unit suite: all committed tests pass. Oracle suite: 0 regressions.

alexgrover and others added 2 commits October 14, 2026 20:22
Several strategy.exit orders on one entry each closed up to their own
qty / qty_percent of the position, so a full-size stop placed after a
50% target closed all of it. On TradingView exits share each trade's
quantity in the order they were first placed: each takes its
qty_percent of the trade's entry quantity, its absolute qty (oldest
trades first) or the rest, out of what the exits placed before it and
still working have not taken (a re-call keeps the exit's place). On
whole contracts 50% of 1 contract takes the contract.

Exit orders are also taken in the order the bar's path reaches their
first leg. strategy.close with qty / qty_percent no longer cancels the
exits of the entry (only a full close does), and a reversal takes the
exits without from_entry placed for the reversed position with it.

Co-authored-by: Cursor <cursoragent@cursor.com>
@cursor

cursor Bot commented Oct 14, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: daa806eb-38c9-4774-83ff-0ecc77197fbc)

@alexgrover
alexgrover changed the base branch from fix/trailing-stop-parity to dev October 14, 2026 19:24
@alexgrover
alexgrover merged commit b3efb25 into dev Oct 14, 2026
2 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant