Repository navigation
Pine adapter: margin calls at the open, the exact reversal tie, and global exits on a held position, pinned by TradingView controls - #345
Merged
Conversation
…open check after an add, fill-time admission at the open, the refined lagged follow-up A full-margin, one-lot process_orders_on_close position (percent commission, slippage, lot grid <= 1) is called at the open after its close fill on TradingView's schedule: the call is sized at the source close c' for longs as for shorts, and its one-unit band and short gate are priced at the open's print. The booked book is then re-checked at the open's mark at that print, gated like any other check: - not short there: the lagged follow-up of the close-sized call books at the print; - short, and the re-check books nothing (its units vetoed by the gate, or under one restore step): the sequence ends, with no follow-up at the print and nothing owed onward; - short, and the re-check books: a short's re-check owes its own lagged follow-up to the bar's first extreme, where the walk books it at that point's print or drops it when the point's own check is short (as the open's own call already owes its follow-up there). Outside the walk's scope the follow-up books at the open's print, as before. None of these calls is repeated at one price. The gated re-check, the end of the sequence and the owed follow-up are pinned by 14 synthetic TradingView controls and one population cohort's TradingView trades (OANDA:EURUSD 15, 2025-06-18: 5.52 at the open, the re-check vetoed, then 522.36 at the high). A long's booked re-check is never short at full margin, so those rules act on shorts only. A leveraged book's open check runs after a market add filling there, on the book holding it and its entry fee (slippage 0, percent commission, not process_orders_on_close). An explicit-quantity long from flat filling at the next open is dropped where sig10(sig10(E) / Q) is below the slipped open tick (full margin, with slippage, not process_orders_on_close). In the POOC path walk the lagged follow-up also runs on whole-share books with the one-unit fallback, chains, and is dropped at a point whose own check is short; inside the opening-call scope the open's own call owes it to the first extreme, while outside it a carried short's open call keeps its repeat at one price. Each rule part sits behind its own test-only switch in detail::MarginOpeningSwitches, default on. The controls are committed as tests/fixtures/margin_open_rules with test_margin_open_rules_tapes (43/43 tapes, 129 TradingView trades, forward == backtest 43/43, each switch costs a tape); margin_schedule_rules' add-fee tapes and fourteen margin_call_rules tapes (the short-s5 family, inherited/eth-slip-5, schedule-q9p1305-s4) now match and are asserted. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
TradingView keeps only the close leg of a default 100 % reversal whose binary64 equity E is under sig10(Q c') while its ten-digit money sig10(E) reaches that cost, whatever strategy.exit stop or trail legs rest in the book: the reversed position's stop, its stop with a trail, or the new entry's own exit. The engine judged rule 2 only on a clear book and opened the reversal beside a resting exit. unified_admission_terms now judges that exact tie, E < cost <= sig10(E), beside resting exit stop and trail legs on a whole-unit lot (switch tie_reversal_beside_exits, on). Off the tie, beside a limit leg and on a fractional lot such a book keeps the earlier rules: no tape decides rule 5, the fill re-check or those books there. Pinned by 36 lab tv controls on NYSE:F 15m (admission_rules/ reversal_tie, 3 byte-identical exports each, predictions written before export): long and short, with and without process_orders_on_close, beside no exit, a resting stop, or stop and trail exits; equity one ulp under the cost, equal to it, and a cent above and below. TradingView equals the prediction on all 36. The engine now books all 36; with the switch off the eight one-ulp ties beside exits open the reversal, as on the parent. The population case the rule fixes sits 13 ulps under its cost, so the rule does not hang on a one-ulp residue. Documentation anchors into the two edited files are carried by an exact line map from the parent. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
A strategy.exit with no from_entry, called while a position is held beside an entry order of the other side (resting at a level, or placed earlier in the same calculation), took that pending order as its parent (observe_staged_parent in exit()). With the order's side, the exit's limit and stop thresholds sat half a tick on the wrong side of the leg that closes the held position: the leg settled at its source level outside its immutable trigger, the kernel answered MatchRejected InvalidTerms, the request was withdrawn and re-issued, and the exit filled bars late or only on a gapped open; a stop fired a tick late. With the order's price basis, a relative profit or loss leg waited for that order's fill, which never came. Reachable on main with calc_on_order_fills off, at any margin setting. TradingView binds such an exit to the held position. In 21 pairs of synthetic `lab tv --no-note` controls on NYSE:F 15m (limit, stop and profit legs, long and short, calc_on_order_fills off and on, the default margin requirement and margins off; every prediction written before its export), each script with the resting opposite entry books exactly the trades of the same script without it, row for row: 0 counterexamples. The adapter now skips a pending opposite entry as the parent of a global exit while a position is held, so the thresholds rest on the held side and a relative leg resolves against the held position. Kernel untouched; no stream gate. The rule is ExitBindingRuleSwitches::global_exit_binds_held_position (on; tests clear it). It acts whatever the margin setting, as the controls bind the same with the default margin requirement and without one. Approved re-pin: the rule ships unscoped, and the three synthetic witnesses it moves are re-pinned. tests/test_adapter_quiet_bar_pinned.inc is re-harvested with that TU's own switch (12 of 276 rows, Random12, 27 and 31 under the four run modes). Random27 trade 18 (17 under the magnifier), Random31 trade 5 and Random12 trade 2 are the pinned mechanism: the exit's level touched exactly on the held side, the opposite entry not reached on that bar. Random31 trade 6 follows from trade 5: the opposite limit then fills from flat at its placement size, which TradingView does on the exit's own bar in the pin's controls; on that later bar it is an inference. Random12 trades 4-6 (magnifier off) are a known divergence, recorded by decision: the rule's skip at that call is caused by a short limit resting since two bars before, the short stop at the exit's own stop is placed after the exit, and no tape has this exit-first call order (tests/fixtures/cross_side_exit/README.md). Per-run-pass dumps of the whole suite, rule on against off: trades move only in those 12 quiet_bar run-passes (and their probe and ungated variants) and the new tapes; every other witness keeps its trades, and 15 transcript-mode run-passes of the quiet_bar battery change their recorded broker-state hashes with identical trades (unpinned). Tests: tests/fixtures/cross_side_exit holds 15 of the tapes with their frozen generated strategies (test_cross_side_exit_tapes), run at the default margin; TradingView's margin-0 exports of the same scripts are byte-identical to the default-margin ones (the pin's evidence): 11 equal TradingView row for row; 4 depart at one known row of another rule (math.round_to_mintick of a half-cent level), the same in each control and its opp twin. With the switch off exactly the 8 opp tapes move; streams equal backtests with it on and off; the calc_on_order_fills opp tape is refused by a stream. test_exit_binding_tapes registers the part (no exit_binding tape has the shape). Docs: the part's row and scope in pine-adapter-kernel-notes and the exit_binding README; documentation anchors moved by an exact line map. Population: the shape is reached by 9 probes of one source (a market reversal on the exit's bar, where the reversal cancels the exit anyway); a census found no other run reaching it, and the rule moved no population trade set. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
| sys.path.insert(0, str(scripts)) | ||
| from run_strategy import Strategy, _check_abi, _load_bars, inputs_run_kwargs # noqa: E402 | ||
|
|
||
| class TapeStrategy(Strategy): |
| _check_abi(self.lib) | ||
| self._setup_signatures() | ||
|
|
||
| class StreamStrategy(Strategy): |
luisleo526
marked this pull request as ready for review
October 5, 2026 18:41
luisleo526
added a commit
that referenced
this pull request
Oct 6, 2026
…se's owed follow-up, open-marketable exits first, and same-side global exits, pinned by TradingView controls (#347) * Pine adapter: a re-issued exit filled at its call keeps the pass's position view Under process_orders_on_close, exit() fills a re-issued strategy.exit of a one-lot short whose stop or limit is already through the bar's close at the call (its current-close path, execute_current). Unlike an ordinary close_all (KI-64), it did not freeze the script's position view, so the rest of the pass read strategy.position_size == 0 and a reset strategy.position_avg_price. A late observer, strategy.position_size[1] < 0 and strategy.position_size == 0, then fired one bar early, and an exit cooldown blocked the next bar's entry. The scraped job-2947 probe on BINANCE:ETHUSDT.P 15 lost its 2026-01-08 23:30 UTC short and every later trade this way. TradingView fills that exit at the close, after the pass: the pass keeps the pre-fill size and average. The adapter now freezes the script's position view before it executes the exit, as close_all does. Once the fill has left the book flat, the generated strategy.position_avg_price read (position_entry_price_ behind a non-zero signed_position_size()) keeps the pre-fill average until the pass ends. PineStrategyHost:: hold_script_average_price writes it, and release_script_average_price restores the flat book's 0 right after on_source_bar, before the orders the pass placed settle. No codegen change. Each part has its own switch, PoocCloseFillViewSwitches:: current_exit_keeps_position_view and current_exit_keeps_average_price (on; tests clear them). Both act only at that call site. close_all's own average read and the intraday-cap close at the call are unchanged. Pinned by 15 synthetic lab tv --no-note controls on BINANCE:ETHUSDT.P 15m, 2026-01-08..10. Each was exported twice, the two exports are byte-identical, rangeProof is covered on both, and every prediction was written before its export: 0 TradingView counterexamples. tests/fixtures/pooc_close_fill_view holds 11 of them with their frozen generated strategies (codegen c1df8a6): - Nine equal TradingView row for row, entry ids included. These are the re-issued stop exit's size read, its cooldown observer, its ATR-stop cooldown at 100 % of equity, its average read and its limit leg, plus the long mirror, strategy.close, close_all and a first-issue exit, which never moved. - Two are known divergences the rule leaves open. close_all's average read is AVGPRE on TradingView and AVGOTHER in the engine. After the re-issued exit, TradingView keeps the pre-fill strategy.opentrades, closedtrades, openprofit, netprofit and equity; the engine reads them after the fill. test_pooc_close_fill_view_tapes clears each part and requires the departures recorded in switch_off_departures.json. The average part moves 2 tapes; the view part moves the 5 re-issued short tapes. It also requires every tape's stream to equal its backtest with both parts on and off. Last, it records every tape's per-bar broker-state hash with the average part on and off: position_entry_price_ is hashed, so the hashes must be equal wherever the trades are, and otherwise first differ after the exit bar's fold. A hold that outlived its pass fails it: with the release_script_average_price() call removed, the trades stay the same and the hashes of the re-issued exit tapes differ from the exit bar's fold on. The four cooldown controls of tests/fixtures/margin_call_rules stay equal. Fail-before: the test module does not compile against the parent tree (pooc_close_fill_view_switches is not a member of detail). With both parts cleared, the five re-issued short tapes depart from TradingView, as on the parent. Whole-suite per-run trade dumps (%.17g, every field) against the parent: the dumps cover 670 processes and 56,558 runs. Every pre-existing run-pass keeps its trades with both parts on and with both off. The only differences are the new test, the repetition counts of timing-calibrated loops and the run order of a test that runs two hosts on two threads; their distinct runs are identical. No witness re-pin. The transient flag is waived in broker_state_hash_waivers.txt: it is false at every fold. Documentation anchors into the four edited files are carried by an exact line map from the parent (245 moved, 0 stuck). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * Pine adapter: a POOC close's owed follow-up booked after the script, frozen close sizes and their over-fill lot, and the open's lot-by-lot follow-up R-A (MarginScheduleSwitches::close_follow_up_after_script): a carried process_orders_on_close short's lagged follow-up owed to its bar's close is held through the close's own check (rule 7 still drops it where the close is short) and booked after the script, ahead of the close's fills, at the same print. A strategy.close(id) of the whole one-lot book (flush_pending_closes) or a close_all() placed there keeps the size the script saw: a transaction that crosses zero and opens the excess as a lot of its own, under the close order's label. That lot is credited to the close ledger and the pyramiding records ahead of the entry beside it, so the next open's nameless margin calls take it first in first out, as the kernel does from the book, and a later strategy.close of that entry closes all of the entry's units. A reversal entry's excess joins its own lot (apply_frozen_reversal_close). Partial closes, closes of several lots and the twin outside process_orders_on_close keep today's sizing (margin_schedule_rules frozen/close-id stays a known divergence). No tape runs pyramiding above 1, so the pyramiding-record credit is unexercised. Beside that lot only a market entry filling at the close it was placed at is exempt: from the pyramiding-0 refusal, and a default-sized one from the fill-time affordability check too (a scraped OANDA:EURUSD 15 probe, job-2550, 2026-04-09 01:45 UTC: TradingView fills a default-sized "LONG" of 18624.97 beside the 0.56 over-fill lot). Priced entries and later fills keep every gate; no tape decides those shapes. One of them changes against the parent tree, which opens no over-fill lot: an explicit stop entry placed at that close at pyramiding 0 fills on the next bar there, and is refused here as a same-side add beside the lot. R-B (MarginOpeningSwitches::lot_by_lot_open_follow_up): on a fractional lot grid, the close-sized call at the next open takes a book of several lots the close's fills opened, first in first out, and its follow-up is checked lot by lot (open_print_lot_follow_up_units). One-lot books keep open_print_follow_up_units, and whole-share books of several lots keep the previous rules. On a fractional book of several lots a short's booked re-check now runs as well (the parent tree never entered this schedule for several lots); nothing follows it, since no tape decides that follow-up. Tests: tests/fixtures/margin_open_rules lots/ holds 10 synthetic TradingView controls (62 trades), each exported twice with identical output and predicted before export. All 10 match row for row and stream to the backtest's trades; the parent tree matches none of the first 8. Two of them close the entry by id after the open's calls (strategy.close("L"), with an explicit and with a default-sized L). Off alone, close_follow_up_after_script loses 7 tapes and lot_by_lot_open_follow_up 9. margin_open_rules: 53 tapes, all match. The job-2550 probe's trades now equal TradingView's 3761 rows. Whole-suite per-run trade dumps (%.17g, every field) with both switches on and off: only the lots/ tapes move. Documentation: both switches' rows, the counts, and the anchor digits carried by an exact line map. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * Pine adapter: a market entry's opening check at its open fill follows the exit legs marketable there TradingView, pinned on 25 synthetic controls (each exported twice, byte-identical, every prediction written before its export): at a market entry that opens the book from flat at a bar's open, the exit legs it released that are already marketable at that open -- a short's stop at or below the open's tick or its limit at or above it, a long's mirror -- fill there first, and the opening margin check then runs on the book they leave (nothing after a whole exit). A leg the bar reaches only later on its path, one tick after the open included, never preempts: the check's call books at the fill first. Both sides. Four more controls make the strategy.exit global (no from_entry) and place it with the entry: TradingView books each exactly as its bound control. ab9714b's rule -- a 1x short skips the opening trim when an exit leg touches anywhere on the entry bar -- is refuted by TradingView on its own shape (test_margin_call_1x_long_entry_fill scenario E's settings and bar: 0.008 ETH called at the open, then the stop closes 3.492). For a market entry opening the book from flat at the open (one lot, no add, no book of several entries, neither process_orders_on_close nor calc_on_order_fills) the adapter asks the legs that fill released whether they are marketable at the open (priced_exit_precedes_opening). The released legs (opening_released_leg) are those bound to the entry's request, those bound to its id and materialized at the fill on the book's side, and a global leg placed while the book was flat whose request follows the entry's. Every other leg (a strategy.exit without from_entry placed before the entry or while a position was held, a leg carried from an earlier bar or lot) is still asked ab9714b's question, and every other fill (stop and limit entries, reversals, adds, books of several entries, process_orders_on_close, calc_on_order_fills) keeps that rule. The scope is narrower than the pin's wording because the wider form (every market fill at the open, every live leg) moved the state hashes of two synthetic witnesses, test_adapter_quiet_bar (18 runs) and test_publication_witness (10 runs): hash-only, every trade field equal in a whole-suite dump, through legs the kernel never fills at that open, whose owed check then lingered. Which exclusion each of the last 8 runs needed was not bisected. Known divergences of the kept rule: - Two are committed as tapes the test lists in kKnownDivergences: TradingView calls a short reversal (out of a 0.001 long) and a short stop entry gapped at the open (a sell stop above the close) before their stop on the path, as it does the market entry; the engine books the stop 3.5 with no call. - A global strategy.exit placed before the entry, while the book is flat, has no tape. TradingView voids an exit called while no position is held and no entry order is working (its exit-binding pins), so, by inference, it calls such a short at the open print. The engine keeps a leg there that never fills, at the open or later, and still asks ab9714b's question of it: the short's opening call is skipped whenever the bar touches the leg's stop, and the short is called at the path's extreme instead, the same with the switch off. The leg stays out of the released legs for an engine-only reason: counted, it defers the check to a fill that never comes, which drops the check, a long's too (in test_adapter_quiet_bar Random32 that moved only the state hash). - Adds, books of several entries, limit entries, process_orders_on_close and calc_on_order_fills stay on that rule without a tape. A partial exit at the open owes the check after its own fill (open_exit_first_bar_: 0.0032 called after a 0.0004 stop, as TradingView books it); the record is cleared at the next bar open if no released leg fills. The opening check's body moves unchanged into run_opening_checkpoint so both points run the same branch. Switch MarginOpeningSwitches::open_marketable_exit_first, default on; off restores the previous rule (every deterministic run-pass of the suite books the parent tree's trades, field for field). Tests: the 31 controls are tapes in tests/fixtures/margin_open_rules exit-order/ (53 trades). margin_open_rules now holds 84 tapes and 244 trades: 82 match, the 2 listed divergences still differ, forward == backtest on all 84, and the switch off loses 17 (15 of the 25 pinned controls, which the parent tree misses, and the two global controls that tell the rules apart). Scenario E of test_margin_call_1x_long_entry_fill (twin and base copy) books TradingView's shape, 0.1996 @100 "Margin call" then 99.7504 @105; its twin-parity rewrite entry is extended. Docs: the switch row and counts, and every anchor into the moved files re-anchored by an exact line map. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * Pine adapter: a global exit called while a position is held binds to it beside a same-side add too A strategy.exit with no from_entry, called while a position is held beside an entry order of the HELD side (an add resting at a limit or a stop, placed earlier in the same calculation, or queued by a fill recalculation), still took that pending add as its parent (observe_staged_parent in exit()): #345 skipped only an entry order of the other side. With the add's price basis, a profit or trail leg rested at the add's limit plus its ticks and filled at the next open, so a script booked thousands of one-bar trades; a loss leg, and any leg beside a stop add, waited for the add's fill, which never came, and the position ran to the end of the range. A market add at the pyramiding cap never became a pending parent. TradingView binds such an exit to the held position whatever the side of the order beside it. In 36 pairs of synthetic `lab tv --no-note` controls on NYSE:F 15m (a resting limit add, a resting stop add, or a market add at the cap; profit, loss, profit and loss, and trail legs; long and short; calc_on_order_fills off and on; every prediction written before its export), each add script's List of Trades is byte-identical to its control's: 0 counterexamples. The skip now drops its side term, so the exit keeps the held position's side and entry price. Under calc_on_order_fills one more path departed: the profit-and-loss bracket the exit stages in the entry's fill recalculation (the chart-tick scope) counted the resting add as a competing order of the source book, which took the bracket's chart-tick reach (its threshold moved half a tick beyond a level the on-grid test misreads by one ULP), so a limit the fill bar's high reaches exactly filled one bar late. flush_pending_bracket_legs now leaves the entry orders of the held side out of the census of a held global exit's leg. Two switches (ExitBindingRuleSwitches, on; tests clear them): global_exit_binds_held_position (extended, sizeof unchanged) and the new held_exit_bracket_ignores_same_side_entries (sizeof 5 -> 6). Kernel untouched; no stream gate. Not in scope: an add that fills while the exit works (TradingView gives each entry its own exit levels and books FIFO; the engine books one exit at the average price) is a separate rule. Tests: tests/fixtures/same_side_exit holds the 36 add tapes and their 20 controls (exact Pine bytes, TradingView's List of Trades, provenance, frozen generated C++ of codegen c1df8a69); test_same_side_exit_tapes requires 38 tapes equal to TradingView row for row and the other 18 to depart exactly at their recorded row (the same row in a control and its add tapes: the trailing leg and calc_on_order_fills re-entries, another rule's); with global_exit_binds_held_position off exactly the 32 resting-add tapes move, with held_exit_bracket_ignores_same_side_entries off exactly the 4 calc_on_order_fills profit-and-loss add tapes; no control and no cap tape moves. The calc_on_order_fills add tapes are refused by a forward stream; every other add tape streams (1 and 30 bars of history, every run of the feed between two nights) to the backtest's trades. test_exit_binding_tapes sets the new switch in every_part() and lists it. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
luisleo526
added a commit
that referenced
this pull request
Oct 6, 2026
* docs: release notes and version scoping for v1.3.0 CHANGELOG 1.3.0: confirmed-bar admission in pineforge-live (#342), the Pine adapter changes of #341, #345 and #347, tests and docs (#343, #344); no report key changes; the state-hash recipe additions of #341 and #347, domain tags and the v19 epoch unchanged; migration. Version scoping: README, install.md and public-contract.md name v1.3.0, its tarballs, the engine1.3.0-codegen1.3.0 image and the 1.3.0 pair. The confirmed-bar receipt and its admission, marked unreleased after 1.2.0 by #342, ship in 1.3.0 (README, strategy-capabilities.md, runner/README.md). Codegen license lines (README, LEGAL.md, docs/pages/index.md): the PineForge Source License 1.2 from codegen 1.3.0; 1.2.0 keeps 1.1, releases up to 1.1.0 the PolyForm Noncommercial terms. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * docs: release 1.3.0's grades in the README and the changelog, from the facts tokens The README's release sentence moves to the releases[1.3.0] tokens, and its main-scoreboard lines re-render the values defe41f (#343) rendered at pineforge-release 3e39d64, and the 1.3.0 changelog says which registry baseline grades the release and why that baseline is the release's code, all rendered from pineforge-release facts/facts.json at ff21de0 (#32). The changelog sentence extends the last line of the "What a script author sees" bullet that 0e1ced7 added. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pine adapter: three TradingView rules pinned by synthetic controls
Three adapter-only changes (
src/source/,include/pineforge/source/, tests and docs; no kernel,grader, metric, tolerance or codegen change). Each rule part sits behind its own test-only switch,
default on, so a regression bisects per rule. One commit per change.
1. Margin calls at the open after a process_orders_on_close fill (
detail::MarginOpeningSwitches)A full-margin, one-lot
process_orders_on_closeposition (percent commission, slippage, lot gridof at most 1) is called at the open after its close fill on TradingView's schedule:
the sequence ends, with no follow-up at the print and nothing owed onward;
extreme, booked at that point's print or dropped where that point's own check is short (as the
open's own call already owes its follow-up there).
Also:
and its entry fee (slippage 0, percent commission, not
process_orders_on_close);sig10(sig10(E) / Q)is below the slipped open tick (full margin, with slippage, notprocess_orders_on_close);process_orders_on_closepath walk the lagged follow-up also runs on whole-share books withthe one-unit fallback, chains, and is dropped at a point whose own check is short; inside the
opening-call scope the open's own call owes it to the first extreme, outside it a carried short's
open call keeps its repeat at one price.
Evidence:
lab tv --no-note, two byte-identical exports each,predictions written before export), committed as
tests/fixtures/margin_open_rules(129 TradingViewtrades): the engine books 43/43 row for row, and a forward stream books the backtest's trades on all
43. Turning any switch off costs tapes.
re-check vetoed or rounding to zero (a sequence that ends there, high- or low-first), the re-check
booking and owing its follow-up to a first extreme (low or high, booked there; dropped where that point
is short itself), a re-check with no follow-up, and an open where the booked book is not short. With
them, one population cohort's TradingView trades (OANDA:EURUSD 15, 2025-06-18: 5.52 at the open, the
re-check vetoed, then 522.36 at the high), also committed as a replica tape.
margin_call_rulestapes now match and are asserted (258 of 266, was 244) and the threeadd-feetapes ofmargin_schedule_rules(38 of 39, was 35).2. Rule 2's exact tie beside resting exit legs (
MarginRuleSwitches::tie_reversal_beside_exits)TradingView keeps only the close leg of a default 100 % reversal whose binary64 equity
Eis undersig10(Q c′)while its ten-digit moneysig10(E)reaches that cost (E < cost <= sig10(E)),whatever
strategy.exitstop or trail legs rest in the book. The engine judged that tie only on a clearbook. It now judges it beside resting stop and trail legs on a whole-unit lot; beside a limit leg, on a
fractional lot and for an explicit reversal quantity the earlier rules stand (no tape decides those).
Evidence: 36 synthetic controls on NYSE:F 15m (three byte-identical exports each, predictions
written before export): long and short, with and without
process_orders_on_close, beside no exit, aresting stop, or stop and trail exits; equity one ulp under the cost, equal to it, and a cent above and
below. TradingView equals the prediction on all 36; the previous engine opened the reversal on the 8
one-ulp ties beside an exit.
test_admission_rules_tapes: 111/111 tapes, 216 TradingView rows;forward == batch on 94 of the 97 NYSE:F tapes (the test names the three it leaves out). The population
case the rule fixes sits 13 ulps under its cost, so the rule does not hang on a one-ulp residue.
3. A global exit called while a position is held binds to it (
ExitBindingRuleSwitches::global_exit_binds_held_position)A
strategy.exitwith nofrom_entry, called while a position is held beside an entry order of theother side (resting at a level, or placed earlier in the same calculation), took that pending order as
its parent: its limit and stop sat on the wrong side of the leg that closes the held position, so the
exit filled bars late or only on a gapped open, a stop fired a tick late, and a relative
profit/lossleg was never placed. It now binds to the held position, at any margin setting.Evidence: 21 pairs of synthetic controls (limit, stop and profit legs, long and short,
calc_on_order_fillsoff and on, the default margin requirement and margins off; predictions writtenbefore export): every script with the resting opposite entry books exactly the trades of the same script
without it, 0 counterexamples.
tests/fixtures/cross_side_exitcommits 15 of the tapes, run at thedefault margin (TradingView's margin-0 exports of the same scripts are byte-identical to the default-margin
ones): 11 equal TradingView row for row, 4 depart at one known row of another rule
(
math.round_to_mintickof a half-cent level); with the switch off exactly the 8opptapes move; streamsequal backtests with the rule on and off.
Approved re-pin:
test_adapter_quiet_bar(12 of 276 rows)The exit-binding rule moves fills in three random witnesses. The table
(
tests/test_adapter_quiet_bar_pinned.inc) is re-harvested with the TU's own harvest switch; nothingelse in the suite moves. Run modes: magnifier off/on × recording on/off (the same 12 run-passes move in
the plain, transcript, probe and ungated builds).
SXB(reversal), P&L −1.354Y(its stop, touched exactly), P&L −6.349B, P&L 1.1485Y, P&L −3.8465B, P&L −2.4221Y(its limit, touched exactly), P&L −3.7118Every other witness keeps its trades. 15 transcript-mode run-passes of the quiet_bar battery change their
recorded broker-state hashes with identical trades (unpinned).
Known divergences
short limit resting since two bars before; the short stop at the exit's own stop is placed after the
exit; no tape has this exit-first call order.
through both): TradingView executes both orders, the entry first, and the exit's quantity then opens a
second position. Neither this engine nor the previous one books those rows.
math.round_to_mintickof a half-cent level (4cross_side_exittapes, another rule): TradingViewrounds 9.655 to 9.66, the engine to 9.65.
≠ 100, commission 0 or several lots; the explicit-quantity admission for shorts at a ten-digit tie; the
open check after an add when the open's own check already called. 8 of the 266
margin_call_rulestapes and one
margin_schedule_rulestape stay listed known divergences.reversal quantity the earlier admission rules stand until a control decides them.
Release note
Verification
test_margin_open_rules_tapes43/43tapes, forward == backtest 43/43, every switch costs tapes (
short_point_drops_owed9);test_admission_rules_tapes111/111, forward == batch 94/94;test_cross_side_exit_tapes11 exact + 4known;
test_margin_call_rules_tapes258/266 (all switches off: 140, the count before the rules);test_margin_schedule_rules_tapes38/39;test_margin_opposite_tapes63,504 checks;test_adapter_quiet_bar276/276 re-pinned runs.per-run dump of every trade field (
%.17g): every run that one change moves equals that change's run in thecombined engine (399 runs of the margin-call tape tests, 48 quiet_bar runs), every other run equals main's,
and no run is moved by two changes. Each change's own new tests give the same trades alone and combined.
margin-call change moves (same-input replays with and without it; it never decides there).
845/845, kernel 307/307 with 0 residual findings, Doxygen 0 warnings, corpus parity 312/312 probes
unchanged (subset 54/54).
Population gate
One whole-population sweep of this head's exact tree (
exp-px-wave-r2-gate-20261006, attempt 1; engine8eb97508, codegen mainc1df8a6, populationcf857209), graded against the active baselinepineforge-parity-baseline-20261005-codegen-609b3519:f-15 stevenygabbyperez-fast-scalper-with-stops: the exact reversal tie (change 2);f-15 axealgo-tp-sl-toolkit-axealgo: margin calls at the open (change 1);eurusd-15 job-2942-mjrodriguezorlich69-forex-apex-matrix-v5-hmm-stationarity-core: the open check after an add's fill (change 1);eth-scraped-15 officialjackofalltrades-caldera-meridian-strategy-joat(hard lane): margin calls at the open (change 1).eth-15 blitz-locked-macd-pullback-sniper-trend-adx-filtered-strategystays strong. Its first divergence fromTradingView moves from 2025-05-03 to 2025-06-23, its exact rows rise from 145 to 233 of 588, and its trade
count comes within two of TradingView's (597 → 579). Match % moves 97.2 → 95.8, from the equity cascade after
that later divergence: an opening trim that TradingView books at a slipped market short's fill before a
same-bar priced exit. That rule is not pinned yet.
616c35d250686fe4395e8ea9adfa1bdc3b91d342a958c0db3c200310ce3de5f1(7,989 graded).🤖 Generated with Claude Code
🤖 Generated with Claude Code