Skip to content

R5 wave 1: native report truth, sizing bases, price grid, HTF subscriptions, order ergonomics + toolkit, top-level examples (L2/L3/L8/L6/L7/L10) - #260

Merged
luisleo526 merged 7 commits into
mainfrom
r5/int-20260920
Sep 20, 2026
Merged

luisleo526 merged 7 commits into
mainfrom
r5/int-20260920

Conversation

@luisleo526

Copy link
Copy Markdown
Collaborator

What

Six lanes of the native feature-parity roadmap (#256), each its own commit, all opt-in for native hosts and byte-neutral for the Pine adapter (never edited):

Lane Commit Native capability
L2 Report truth NativeReportPolicy::KernelRecorded — equity curve per script bar, finite drawdown/run-up, mark-to-market range-end rows, closed_trade_* accessors
L8 Price grid NativePriceGrid (quantized fills, optional quantized triggers), NativeGridRounding — TV's half-tick rule stays in the adapter
L3 Sizing bases Sized intent (cash / percent-of-equity, at-match or at-acceptance, fee-net, grid policy); ScopeFraction reduces (gross / net-of-siblings)
L6 HTF subscriptions NativeRunSpec::subscriptions + on_native_timeframe_bar / native_series_bar over the existing feed machinery (batch-only for now; stream mode is a follow-up)
L10 Examples examples/native/ under PINEFORGE_BUILD_EXAMPLES, PINEFORGE_EXPORT_NATIVE_STRATEGY, docs/pages/pine-to-native.md (Pine concept → native API map + migration)
L7 Order ergonomics working-book snapshot, cancel_all / cancel_where, FromOwnerFill anchors, TrailTicks, retain-trail replace, zero trail offset, header-only native_toolkit.hpp (submit_bracket, OrderBook)

Epochs: native_run_spec_v3, native_order_v6, engine_script_run_v18 — each bumped once. New spec fields fold into the continuation hash only when set (pinned in tests against clean main).

Evidence

  • Per lane: fresh ci_verify release PASS by the supervisor (495–499 tests each); lane tests 555 / 198 / 491 / 113 / 3 examples / 262+57 checks incl. twins against the adapter-driven path.
  • Integrated tree: ctest 513/513, ci_verify release (29 stages) + kernel (24 stages) PASS.
  • Campaign sweep exp-r5-int1b-six-lanes-20260920 on this exact tree (00373da7) vs the active baseline: 4190 graded, coverage-lost 0, hard regressions 0, band leavers 0, score 0 — no regression, net 0 (accepted per the standing ruling; the gate's target.not-positive is the neutral outcome; candidate snapshot 9da31061).

Merge with rebase (linear history, one commit per lane).

🤖 Generated with Claude Code

https://claude.ai/code/session_01CSmYixVAp4NqWpBZxkrLPT

current_fx_curve = compile_object("v18_native_fx_curve_surface_compile",
NATIVE_FX_CURVE_CALLER, include)
current_tick = compile_object("v17_native_tick_surface_compile",
current_tick = compile_object("v18_native_tick_surface_compile",
luisleo526 and others added 7 commits September 20, 2026 11:39
…-end rows (R5 lane L2)

A bare NativeStrategyHost gets a truthful report, opt-in through
NativeRunSpec (native_run_spec_v3):

- NativeReportPolicy { HostRecorded (default, today's behaviour),
  KernelRecorded }: under KernelRecorded the native consumer marks one
  equity point per script calculation — update_equity_extremes() then
  record_equity_point(script_open) right after each host callback, in the
  order the Pine host uses — so the curve has one point per script bar and
  the drawdown / run-up walk is no longer degenerate.
- report_open_position_at_end: a position still open at run end is reported
  as mark-to-market closed rows at the last close, one per physical lot,
  through the existing non-mutating row builder into range_end_trades_.
  Reporting only: no cash booked, no order placed, no hash moved.
- closed_trade_count() / closed_trade(i): public read accessors on
  BacktestEngine for the closed rows.

The new spec fields fold into the continuation hash only when the policy is
not HostRecorded, so every existing continuation hash is unchanged; the
adapter never sets them and is not touched.

Tests: tests/test_native_report_truth.cpp (default pin, curve length and
hand-walked drawdown, open-position row with identical broker hash, twin vs
the adapter-driven path, hash neutrality pinned against clean main).
ci_verify release PASS (495 tests). Design: docs/design/native-feature-parity.md A.1.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSmYixVAp4NqWpBZxkrLPT
(cherry picked from commit 377efad)
…5 lane L8)

native_run_spec_v3: NativePriceGrid { None (default), QuantizeFills,
QuantizeFillsAndTriggers } and NativeGridRounding { HalfUp, Directional }.
QuantizeFills rounds the resolved price onto price_tick before slippage
(half-up, or in the direction favouring the resting order);
QuantizeFillsAndTriggers additionally tests triggers against the
tick-quantized bar path. None is the identity: the matcher helpers take a
grid parameter and book exactly today's prices when it is off. Folded into
the continuation hash only when set. TradingView's half-tick rule stays in
the adapter, which is untouched.

Tests: tests/test_native_price_grid.cpp (grid None == clean main, half-up,
directional, quantized triggers, tick required, hash folds only when set,
adapter twin untouched). Design: docs/design/native-feature-parity.md A.7.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSmYixVAp4NqWpBZxkrLPT
(cherry picked from commit 1a9809a914e20dfeb4b7ced1162e2b48bb1282e8)
native_order_v6: a sixth OrderIntent `Sized` (CashValue / EquityFraction
basis, SizeTime AtMatch|AtAcceptance, ExecutionGridPolicy, fee-net option)
resolved by the kernel where HostSized terms resolve today, so a bare host
sizes by cash or percent-of-equity without overriding
resolve_execution_terms (which keeps the last word); and a third
ReductionSize `ScopeFraction` (fraction of the bound scope, Gross or
NetOfSiblings) for Pine's qty_percent-style exits. Non-representable ->
TermsUnresolved; invalid basis -> InvalidQuantityBasis. The adapter never
emits either and is untouched.

Tests: tests/test_native_sizing_bases.cpp (491 checks: differential Sized
vs hand-resolved HostSized with fee and grid, sizing points, rejections,
gross/net-of-siblings, pending bracket parent, adapter neutrality);
fail-before against the v5 closure. ci_verify release PASS (495).
Design: docs/design/native-feature-parity.md A.2.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSmYixVAp4NqWpBZxkrLPT
(cherry picked from commit 9048b8f2ef14566272dae6b36f85a6e3ff49b3d0)
native_run_spec_v3: `subscriptions` (NativeTimeframeSubscription { tf,
authoritative_bars, lookahead }) hashed only when non-empty;
engine_script_run_v18: `on_native_timeframe_bar(const Bar&, const
NativeTimeframeBarContext&)` and `native_series_bar(subscription)`. At
Ready->begin, only when subscriptions are declared, the native consumer
registers one evaluator per subscription through the existing
request.security feed machinery (register_security_eval,
set_native_security_feed, prepare_native_security_feeds — reached through
its existing friendship, no member moved), pumps feed_security_eval_state
from the accepted-input path and delivers each completed bucket immediately
before that input's calculation (lookahead=false) or at the bucket's first
input (lookahead=true). engine_security.cpp and the Pine scheduler are
untouched; the TV-calibrated W/M partition and holiday fold are documented
as the inherited contract. Subscriptions are batch-only for now: a stream
begin with subscriptions is refused by contract (follow-up).

Tests: tests/test_native_htf_subscriptions.cpp (113 checks: hourly over
15m with callback ordering, lookahead, authoritative bars, finer-than-input
refusal, weekly twin vs source::PineStrategyHost, hash neutrality pinned
against clean main); ci_verify release PASS (495). Design:
docs/design/native-feature-parity.md §2.iv, A.5.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSmYixVAp4NqWpBZxkrLPT
(cherry picked from commit 525a3081bb5b38d275c48cf52a4662c7de29c947)
…Pine-to-native guide (R5 lane L10)

The two Pine-free NativeStrategyHost examples move to examples/native/,
built as standalone executables under PINEFORGE_BUILD_EXAMPLES (with a
~90-line "hello, kernel" host) and still as the MODULE targets the live
runner loads. include/pineforge/native_module.hpp provides
PINEFORGE_EXPORT_NATIVE_STRATEGY(Class), replacing the hand-written
extern "C" shims. docs/pages/pine-to-native.md maps every Pine strategy
concept to its native counterpart (present today, cited, or the lane that
delivers it) with a worked migration and the twin-verification recipe.

Design: docs/design/native-feature-parity.md §2.v.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSmYixVAp4NqWpBZxkrLPT
(cherry picked from commit 044198cee5fea4082b9ab6fa946a69115ec8e818)
…ess, and the Pine-free toolkit (R5 lane L7)

native_order_v6 additions: TriggerAnchor { Absolute, FromOwnerFill{offset,
ticks} } on a request (a leg with owner WaitForApplied / BindOpening and a
relative anchor receives its level when the owner's fill arms it),
TrailTicks (trail offset spelled in ticks), ReplaceOptions
{ retain_trigger_state } keeping TrailTrack::best across a replace, and a
zero trail offset made legal (exit on the first adverse move past the best;
negative offsets still rejected). NativeStrategyHost gains non-virtual
native_working_requests(), cancel_all() and cancel_where(comment).
include/pineforge/native_toolkit.hpp is header-only and Pine-free:
submit_bracket(host, BracketSpec) emits the owner / group shapes of a
strategy.exit bracket, and OrderBook<Key> maps user ids to handles
(submit_or_replace / cancel). The adapter is untouched.

Tests: tests/test_native_order_ergonomics.cpp and
tests/test_native_toolkit_bracket.cpp (working snapshot, bulk cancels,
relative stop arming, ticks vs price offsets, zero-offset trail, retained
trail state, submit_bracket twin vs hand-submitted legs, OrderBook,
include independence of the toolkit). ci_verify release PASS. Design:
docs/design/native-feature-parity.md A.6.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSmYixVAp4NqWpBZxkrLPT
(cherry picked from commit 2b6e0b73235c736eaba3b024ce9a9c6f72a3cf52)
…-independent test pins

The continuation identity folds the host's timezone resources (zoneinfo
root and resolved zone files), so a raw native_continuation_hash() constant
pinned on one machine cannot pass on another; three lane tests did that and
failed on CI while their report and trade digests passed.

native_run_spec_digest(const NativeRunSpec&) (native_run_spec_v3) is the
machine-independent digest of exactly the fields hash_spec folds. The three
tests now pin that digest for a default spec, assert it is unchanged when
each lane's fields are restated at their defaults and moves when a field is
set, and keep every report / trade / fill digest; the two remaining
continuation-hash comparisons are between in-process runs. Proven under
TZDIR=/nonexistent and TZ=Asia/Kolkata. continuation_hash, hash_spec's
field order and every lane's semantics are untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSmYixVAp4NqWpBZxkrLPT
@luisleo526
luisleo526 merged commit 06ef483 into main Sep 20, 2026
11 checks passed
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