Repository navigation
Pine adapter: TradingView's exit-child order at one point and the callback lifecycle (trail tolerance, revived exits, tick-built limit reach) - #328
Merged
Conversation
| sys.path.insert(0, str(scripts)) | ||
| from run_strategy import Strategy, _check_abi, inputs_run_kwargs # noqa: E402 | ||
|
|
||
| class TapeStrategy(Strategy): |
…id order, and the newborn stop When one path point triggers the children of a strategy.exit that names no entry, TradingView fills them one at a time in the order of its entry-id table (a java.util.HashMap over the entry ids: String.hashCode spread over 16 buckets, 32 once the keys pass 13, the newest key first in a bucket; keys are entry ids from their first fill plus one per waiting close order). Each child is a transaction of its entry's quantity, settled against its own entry under close_entries_rule ANY and against the oldest lots first otherwise, one row per settled slice with its share of the ten-significant-digit fees. The kernel fills such a leg once for the whole position. The host now re-cuts that one fill's rows, while they are still the last rows and not final, into the children's rows. Every shape the TradingView tapes do not reach keeps the kernel's rows: a fill that is not the tail or leaves part of the position open, a trailing leg, fewer than two ids, calc_on_order_fills, process_orders_on_close or an intrabar feed, a non-unit account rate, a cash-per-order or negative fee, a live leg of any other exit the price also reaches, a table past 32 buckets or with a tie in a grown table, a waiting strategy.order market order that would size the table differently, and a lot quantity off ten significant digits. A re-cut that adds rows re-counts strategy.wintrades / losstrades / eventrades and the gross sums; each kernel member it writes has an ADR-0001 row. A named stop whose limit entry fills at a point where the stop is already through now fills at once at the entry's fill with the stop's slippage, not at the level the bar crossed before the entry (no calc_on_order_fills, no intrabar feed). The entry-id table is hashed adapter state once it holds two ids or its peak passes 13 keys, and is cleared per run. Nine source-layer witnesses are re-pinned: seven hash-only, and two fuzz runs each move one trade by the newborn-stop rule (quiet-bar Random28 with the magnifier off, publication Config16). tests/test_global_exit_children_tapes.cpp replays all 127 TradingView tapes of the synthetic scripts: 93 asserted row for row, 34 recorded known divergences with the rule each needs and the first departure, and six unreached shapes pinned at the previous engine's own rows. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
…sue, and tick-built callback limit reach Three TradingView rules, taped on synthetic scripts (4 identical exports each), each behind its own switch in src/source/pine_n6_rules.hpp (`PineN6Rule`, `set_pine_n6_rule` / `pine_n6_rule`, atomic flags, all on; no public API, C ABI or strategy input, and no new durable state): - trail_points become ceil(trail_points - 8e-3 * mintick) ticks: the tolerance scales with mintick (ETH 0.01, XAUUSD 0.001, EURUSD 1e-5) instead of the constant 5e-5 ticks, which stays as the no-mintick fallback. Applied at every trail conversion site. - A declined reversal kills the held position's stop and limit exits; a later re-issue is a new live order. The replacement path already started fresh legs for a changed re-issue; the unchanged-reissue shortcuts kept the killed row. The revive applies to every side, sizing and stop or limit exit, and only to the kill: a row held behind the entry/close pair barrier keeps it. An exit issued once stays dead, as the declined-reversal trail-leg tests pin. calc_on_order_fills keeps its own decline path. - A limit exit born in a mid-leg calc_on_order_fills recalculation reaches its leg's end only on that waypoint's tick-built print; the level stays raw. tests/fixtures/n6_callback_lifecycle commits all 82 tapes with their generated strategies, plus five TradingView controls predicted before export (the short mirror, a partial stop, fixed and cash sizing, and the entry/close pair hold). test_n6_callback_lifecycle_tapes builds them into one module, replays them row for row (66 equal, 21 known divergences with their reason and first departure in known_divergences.json), clears each switch in turn and requires exactly the departures rule_off_departures.json records, and reads the pair-hold control's book to require that the stop re-issued in the pair's calculation stays behind the barrier. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
A pure rename and comment rewording; no behaviour changes. - The rule switches become PineCallbackLifecycleRule, kPineCallbackLifecycleRuleCount, set_pine_callback_lifecycle_rule and pine_callback_lifecycle_rule, with their storage callback_lifecycle_rules. Their header moves to the private src/compat/pine/callback_lifecycle_rules.hpp, so the compat unit that reads one no longer includes a src/source header; the adapter includes it from there. - The tape module, its generated include, entry-point prefixes, exported test hooks, CMake variables, the ctest row and the fixture directory become callback_lifecycle_tapes, callback_lifecycle_<tape>__, callback_lifecycle_tapes_set_rule / _rule_count, _pf_clt_*, test_callback_lifecycle_tapes and tests/fixtures/callback_lifecycle. - Comments, fixture READMEs, generated fixture headers and the free-text provenance fields name the TradingView tapes instead of internal campaign labels. Every edited line keeps its place, so no documentation anchor moves. The bytes TradingView ran (each tape's strategy.pine, its exports and the metrics that pin their hashes) are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
luisleo526
force-pushed
the
px/wave3-integration
branch
from
October 4, 2026 07:38
6c53633 to
0f7c529
Compare
luisleo526
marked this pull request as ready for review
October 4, 2026 08:31
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.
Summary
Two Pine adapter changes, each pinned against TradingView exports of synthetic scripts that are committed as fixtures with provenance. Each rule sits behind an internal test-only switch (on by default). There is no public API or input change, no kernel mechanics change and no new stream-mode gate.
25ed895b):tests/fixtures/global_exit_children(127 tapes), ctesttest_global_exit_children_tapes.cad267f2,6c536337):tests/fixtures/callback_lifecycle(87 tapes), ctesttest_callback_lifecycle_tapes. The switches are insrc/compat/pine/callback_lifecycle_rules.hpp.Verification
On the head (rebased onto v1.1.0):
test_ci_verify.pineforge/verify): release 847, sanitizers 827, debug 828, kernel 305 with 0 boundary findings, preflight 44 stages, docs, corpus parity 312/312 with 0 moved, and the subset.pineforge/parity), against the active baseline: 7,989 probes, all measured, 2 up, 0 down. One hard-lane probe, ETH 15m ORB, goes strong → excellent, and NYSE:F Nirav goes strong → excellent. No coverage is lost, there are no hard regressions and no leavers. 28 probes change trades. A one-rule-off bisect attributes 20 to the exit-child order and 8 to the callback lifecycle.🤖 Generated with Claude Code