Repository navigation
Pine adapter: TradingView's margin, sizing and admission rules for one-position books - #330
Merged
Merged
Conversation
…e-position books
TradingView sizes, admits and margin-calls a strategy's orders on its own
ten-significant-digit money. This change teaches the Pine adapter the rules
that synthetic TradingView tapes pin. Each rule sits behind its own switch in
MarginRuleSwitches (include/pineforge/source/pine_adapter.hpp), so a
regression can be bisected rule by rule. The switches are process-wide and are
not installed API; only tests change them. No kernel file changes.
Rules, and the switches that ship on:
- decimal_sizing: a default percent-of-equity quantity is the floor of the
shortest decimal of sig10(E) / price, not of its binary quotient
(6.279 rather than 6.2789).
- pooc_fee_sizing: under process_orders_on_close, a default percent market
order is sized on its slipped execution price, grossed up by a percentage
commission on the ten-digit grid. The grossed unit is computed in one
function, tv_pooc_fee_grossed_unit.
- slipped_signal_admission: an explicit quantity opening from flat at full
margin is judged at its signal close, on the money scale unslipped and on
the price scale slipped.
- gain_loss_money: realized money is kept as two sums, gains and losses,
folded into the broker-state hash. It stands in for the engine's equity
only inside the regime the tapes pin: no fee anywhere (configured, in the
run's fee model, or recorded at an opening), point value 1, no FX series,
a power-of-ten lot step and at most one open lot. One predicate,
gain_loss_regime, holds that regime. Elsewhere the engine's equity stands.
- dust_unit_call: a dust restore calls one unit.
- long_open_close_checks and negative_free_cash_call: a long's one-unit
residual call at the open, the low and the close, compared exactly.
- coof_next_point_close: under calc_on_order_fills, a close placed after a
call fills at the bar's next point.
- close_point_reversal: a close_all sized before the close point's call.
Shipped off: fill_price_recheck. It gates both the unified placement half for
default orders and reversals and the fill re-check. With it off, those orders
keep the earlier admission. The scraped population showed reversals and
openings that TradingView fills at a gap of several ticks and then
margin-calls, a regime no tape pins. The tapes that need the fill re-check
are listed in their tests and asserted with every rule on. Splitting the
switch is a precondition for ever turning it on.
Evidence and tests:
- tests/fixtures/margin_call_rules holds 266 single-position tapes: 199
asserted, plus 67 recorded tapes of a short's call cut-off and slippage
gate, whose rule is not pinned. It also holds 10 order controls replayed
through handwritten hosts. tests/fixtures/margin_ledger_rules holds 381
event-ledger tapes. TradingView's exports and the Pine sources are
committed byte for byte.
- test_margin_call_rules_tapes and test_margin_ledger_rules_tapes replay
every tape:
- with the shipped switches: 170 of 199 and 269 of 381 match, and every
unmatched tape is listed with its reason;
- with every rule on: 172 and 373 match;
- with each rule off alone: every switch costs at least one tape;
- with every rule off: 133 match, the tapes the engine matched before.
- test_margin_rules_forward_replay replays a sample as a backtest and as a
bar-by-bar stream, with every rule on, every rule off and the shipped
switches. It requires byte-identical trades between the two modes on every
split.
- test_publication_witness adds two checks:
- nine fuzz run-passes where the G + L money once parted from the engine's
equity are regression tests: their closed trades must equal, in every
Trade field, those with gain_loss_money off;
- no closed trade of the battery leaves its lot grid.
Re-pinned tests:
- tests/oracle/test_oracle_frozen_size.cpp and
tests/test_default_qty_signal_freeze.cpp: 6.2789 -> 6.279. TradingView's
own tape of the same quotient,
tests/fixtures/margin_call_rules/sizing/sizing-decimal-floor-oracle-control,
buys 6.279 in two byte-identical exports. tests/oracle.sha256 is re-pinned.
- tests/test_explicit_qty_fill_admission_l4b.cpp: the GREEN-G no-op moves to
a funded capital of 10001, and a new assertion pins TradingView's drop at
the original operands, citing boundary/long-admit-m1u and
admit/admit-eth-s3-m07u.
- Four witness tables, re-harvested with each TU's own switch. Only hash
fields move: quiet_bar 110 of 276 rows, publication 43 of 156,
host_view_memo 13 of 13, and lookup_index's kFlip rows, reads and final.
Every closed trade of every battery is unchanged in every Trade field.
- tests/test_adapter_sizing_relower.cpp guard (e) keeps the kernel's
generic fee-divisor and sizing restatements forbidden in the adapter, with
one explicit exception: the TradingView fee-grossed unit inside
tv_pooc_fee_grossed_unit, which must exist once and cite its tapes.
Docs: docs/pine-adapter-kernel-notes.md section 1 states the rules, their
implemented scope, the switch table, the evidence and the known gaps. The
documentation anchors that the adapter's line shifts move are re-anchored.
Known gaps, listed in the tests:
- a carried short's call schedule, a short's call quantum at margin 50, and
a multi-lot short's call at the high;
- a multi-lot long at margin 50 with a per-contract fee;
- the slipped long's call at the low;
- the residual call after a trade history on the G + L money;
- the money basis of a long's one-unit call after a history.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
luisleo526
marked this pull request as ready for review
October 4, 2026 09:49
This was referenced Oct 4, 2026
luisleo526
added a commit
that referenced
this pull request
Oct 5, 2026
* docs: release notes and version scoping for v1.2.0 CHANGELOG: the Unreleased section becomes 1.2.0 (2026-10-05), a minor release that adds the compiled execution-capabilities extension to the C ABI (PF_CAPABILITIES_API_VERSION, strategy_capabilities_api_version, strategy_capabilities_receipt). One bullet per change since v1.1.0 with its PR (#328, #330, #331, #332, #333, #334, #335, #336, #337, #338 and the session-clock change, written #VCP until its PR number exists), the recipe additions under State hashes (#328, #330, #335; domain tags and epoch unchanged), Report keys (docker/run_json.py is byte-identical to v1.1.0's, so no key changes) and Migration. Version scoping: README, install and public-contract pages name v1.2.0 and codegen 1.2.0; "since the next release" and "fixed on main" in the capabilities guide and the runner guide become 1.2.0 and 1.1.0 (#325). Lines that state what an earlier release shipped stay. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * docs: 1.2.0's grades from the facts tokens, #339, and codegen's license - CHANGELOG: the session-clock change is #339 (merged as 52292db), in place of the #VCP token of 3082fbd; the "What a script author sees" bullet of 3082fbd now states release 1.2.0's grades (registry baseline pineforge-parity-baseline-20261005-engine-52292db9: 7,970 excellent / 19 strong of 7,989, none below strong) instead of the main scoreboard at 6b77f06. - README: the release sentence names 1.2.0 and renders releases[1.2.0], and the main scoreboard renders the same baseline, from pineforge-release facts/facts.json at 0c2f6838 (the facts export for the 1.2.0 release). - README, LEGAL.md, docs/pages/index.md: pineforge-codegen is under the PineForge Source License 1.1 from its release 1.2.0; releases up to 1.1.0 keep the PolyForm Noncommercial terms they shipped with. 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.
TradingView sizes, admits and margin-calls a strategy's orders on its own
ten-significant-digit money. This change teaches the Pine adapter the rules
that synthetic TradingView tapes pin. Each rule sits behind its own switch in
MarginRuleSwitches (include/pineforge/source/pine_adapter.hpp), so a
regression can be bisected rule by rule. The switches are process-wide and are
not installed API; only tests change them. No kernel file changes.
Rules, and the switches that ship on:
shortest decimal of sig10(E) / price, not of its binary quotient
(6.279 rather than 6.2789).
order is sized on its slipped execution price, grossed up by a percentage
commission on the ten-digit grid. The grossed unit is computed in one
function, tv_pooc_fee_grossed_unit.
margin is judged at its signal close, on the money scale unslipped and on
the price scale slipped.
folded into the broker-state hash. It stands in for the engine's equity
only inside the regime the tapes pin: no fee anywhere (configured, in the
run's fee model, or recorded at an opening), point value 1, no FX series,
a power-of-ten lot step and at most one open lot. One predicate,
gain_loss_regime, holds that regime. Elsewhere the engine's equity stands.
residual call at the open, the low and the close, compared exactly.
call fills at the bar's next point.
Shipped off: fill_price_recheck. It gates both the unified placement half for
default orders and reversals and the fill re-check. With it off, those orders
keep the earlier admission. The scraped population showed reversals and
openings that TradingView fills at a gap of several ticks and then
margin-calls, a regime no tape pins. The tapes that need the fill re-check
are listed in their tests and asserted with every rule on. Splitting the
switch is a precondition for ever turning it on.
Evidence and tests:
asserted, plus 67 recorded tapes of a short's call cut-off and slippage
gate, whose rule is not pinned. It also holds 10 order controls replayed
through handwritten hosts. tests/fixtures/margin_ledger_rules holds 381
event-ledger tapes. TradingView's exports and the Pine sources are
committed byte for byte.
every tape:
unmatched tape is listed with its reason;
bar-by-bar stream, with every rule on, every rule off and the shipped
switches. It requires byte-identical trades between the two modes on every
split.
equity are regression tests: their closed trades must equal, in every
Trade field, those with gain_loss_money off;
Re-pinned tests:
tests/test_default_qty_signal_freeze.cpp: 6.2789 -> 6.279. TradingView's
own tape of the same quotient,
tests/fixtures/margin_call_rules/sizing/sizing-decimal-floor-oracle-control,
buys 6.279 in two byte-identical exports. tests/oracle.sha256 is re-pinned.
a funded capital of 10001, and a new assertion pins TradingView's drop at
the original operands, citing boundary/long-admit-m1u and
admit/admit-eth-s3-m07u.
fields move: quiet_bar 110 of 276 rows, publication 43 of 156,
host_view_memo 13 of 13, and lookup_index's kFlip rows, reads and final.
Every closed trade of every battery is unchanged in every Trade field.
generic fee-divisor and sizing restatements forbidden in the adapter, with
one explicit exception: the TradingView fee-grossed unit inside
tv_pooc_fee_grossed_unit, which must exist once and cite its tapes.
Docs: docs/pine-adapter-kernel-notes.md section 1 states the rules, their
implemented scope, the switch table, the evidence and the known gaps. The
documentation anchors that the adapter's line shifts move are re-anchored.
Known gaps, listed in the tests:
a multi-lot short's call at the high;
Co-Authored-By: Claude Opus 5.5 (1M context) [email protected]
Measurement
Full population against the active baseline, after the exit-child-order merge: 7,989 probes, all measured, 7 up, 0 down, all strong → excellent:
One-rule-off measurements attribute every move to its rule. One NYSE:F probe stays within its tier, with a worse ladder rung. Replayed at the reference's rung, its trades are byte-identical: the move is a rung switch, not a regression. CI profiles are posted as
pineforge/verify; the sweep is posted aspineforge/parity.🤖 Generated with Claude Code