Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions docs/adr/0001-kernel-adapter-boundary.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ kernel and own these quirks, each at its site:
- **Seams the adapter overrides.** The kernel is driven, not patched. `PineStrategyHost` overrides
`resolve_execution_terms` (`pine_strategy_host.cpp:1179`) for TV sizing and fill spelling;
`validate_execution_precommit` (`pine_strategy_host.cpp:1204`), whose
`validate_precommit` (`pine_adapter.cpp:16988`) returns `AdmitWithHostMargin`
(`pine_adapter.cpp:17223`) to own the opening margin decision; `on_native_tick`
`validate_precommit` (`pine_adapter.cpp:17004`) returns `AdmitWithHostMargin`
(`pine_adapter.cpp:17239`) to own the opening margin decision; `on_native_tick`
(`pine_strategy_host.cpp:898`) / `on_native_applied` (`pine_strategy_host.cpp:970`) for
`calc_on_order_fills` re-entry. It does not own lot excursions: since the adapter state consolidation it keeps
the kernel's `owns_lot_excursions()` default, so the kernel's sampler books every Pine lot's
Expand Down Expand Up @@ -260,8 +260,8 @@ kernel and own these quirks, each at its site:
(`select_reservation_growth_sources` src/compat/pine/reservation_expansion.cpp:9).
- **Margin.** The kernel owns the margin *mechanism* — the level solve, the check points, the
kernel request, its re-pricing, the receipt — and the adapter answers its three policy hooks
with TradingView's: `margin_check_allowed` (`pine_adapter.cpp:18449`) for the scheduling,
`resolve_margin_requirement` (`pine_adapter.cpp:18518`) for the ten-significant-digit money,
with TradingView's: `margin_check_allowed` (`pine_adapter.cpp:18465`) for the scheduling,
`resolve_margin_requirement` (`pine_adapter.cpp:18534`) for the ten-significant-digit money,
and `resolve_margin_call_units` for the lot-floored 4x restore. That hook answers every call
on purpose (the margin and cancellation comparison): TradingView floors the restore onto the lot grid before the multiple,
so on a gridded tape the kernel's own `ShortfallMultiple 4` books 5 lots where TradingView
Expand All @@ -272,7 +272,7 @@ kernel and own these quirks, each at its site:
margin since F7), while the roll point measures at the remaining path's adverse mark (MG-FX:
0.4116 @ 97 there against TradingView's 0.3996 @ 100). What has no kernel check point at all
stays adapter-side: the `process_orders_on_close` chronology exception
(`non_pooc_commissioned_short` `pine_adapter.cpp:24835`) and
(`non_pooc_commissioned_short` `pine_adapter.cpp:24851`) and
the 1x-long money call — plus the TV admission scopes
(`explicit_pair_scope` `src/compat/pine/market_admission.cpp:34-47`) and the review fold they feed
(`awaits_pair_review` `:68-73`, `fold_admission_history` `:83-140`).
Expand Down Expand Up @@ -715,8 +715,8 @@ Every line number in this section names its symbol on this tree, which
| `NativeRunSpec` field | ruling | what the adapter runs instead | measurement and ruling of record | executed native consumers |
|---|---|---|---|---|
| `price_grid`, `grid_rounding` | **native-only** | TradingView's per-order-kind tick rules on top of `None`: `source_trigger_threshold` (`pine_adapter.cpp:471`), `source_level_on_price_grid` (`:454`), `nearest_tick` (`:361`) / `source_bar_fill_tick` (`:382`) / `directional_tick` (`:414`), behind the terms seam | R5-3 and design risk E7 ruled `None` for the adapter before the lane ran; lanes R7 and N13 measured the alternative anyway (raw levels submitted, `QuantizeFillsAndTriggers` with `HalfUp` declared). L8b closed the first blocker (no run aborts). The second has no remedy on either side: TradingView quantizes per order kind (stop and limit legs and a trail's activation on the quantized bar; the trail stop, the running best, stop-limit entries and the `calc_on_order_fills` cursors raw), the grid is one rule for the run, and the old N13 trial moved 30 pinned checks in 4 units; this is historical evidence, not a current-head result; a per-kind mask would spell that inconsistency into the kernel. The corpus cannot arbitrate (every probe runs a 0.01 tick on an on-grid feed; 5 of 312 differ in an engine-only column). Permanent witness: `tests/test_adapter_grid_relower.cpp`, whose section 5 pins the trail stop the grid fires a bar early. Design row PG and §3.6 | `examples/native/native_price_grid_strategy.cpp`, `examples/native/native_price_grid_c.c`, the private test `test_native_price_grid` |
| `risk` | **native-only** | all of `strategy.risk.*` but the direction: `update_risk_state` (`pine_adapter.cpp:18102`), `SourceDayLedger`, `submit_intraday_loss_close` (`pine_adapter.cpp:21479`), `chart_day_key` (`pine_adapter.cpp:17999`), `compat::pine::IntradayCap` with `IntradayOrderBudget` (337 lines) | Structural first: Pine's risk calls are per-bar statements, so a limit reaches the adapter on script bar 0, after `project()` (`pine_strategy_host.cpp:678`) and the kernel's `configure` (`pine_strategy_host.cpp:694`) have fixed and digested the spec. In substance (the risk-lowering comparison, `tests/test_adapter_risk_relower.cpp`, 62 checks over nine paired scenarios): the drawdown latch samples at the close only and still admits a reversal; the loss-day streak counts trades, not days; the intraday loss closes at the path's adverse extreme, refuses every placement and withdraws the book; the fill cap charges slots, transfers quota and closes at the bar's better extreme on the chart timezone's day. With the kernel seeded on the corpus, 3 of 4 cap probes diverge (3840 of 3916, 312 of 604, 2370 of 2384 rows; re-derived by `scripts/check_seeded_risk_experiment.sh` since the kernel/adapter differential study). `strategy.risk.allow_entry_in` is the one rule that is the kernel's already (`allowed_open_directions`). Design §3.6 | `examples/native/native_risk_limits_strategy.cpp`, `examples/native/native_trail_risk_strategy.cpp`, `tests/test_native_risk_limits.cpp`, `tests/test_native_c_api.c` |
| `max_abs_units` | **adapter-policy** | `strategy.risk.max_position_size` as a gate on the LIVE book before the fill (`max_position_size` `pine_adapter.cpp:17108`): an entry is refused once the book already holds the limit | design row MG2 (R5-1): the resulting-book cap is the generic one. Measured by N12's scenario `PS` in `tests/test_adapter_risk_relower.cpp`: two-unit entries against a limit of 3 leave the adapter at 4 and the kernel cap at 2 | `tests/test_native_resting_matching_contract.cpp`, `tests/test_native_run_spec.cpp` |
| `risk` | **native-only** | all of `strategy.risk.*` but the direction: `update_risk_state` (`pine_adapter.cpp:18118`), `SourceDayLedger`, `submit_intraday_loss_close` (`pine_adapter.cpp:21495`), `chart_day_key` (`pine_adapter.cpp:18015`), `compat::pine::IntradayCap` with `IntradayOrderBudget` (337 lines) | Structural first: Pine's risk calls are per-bar statements, so a limit reaches the adapter on script bar 0, after `project()` (`pine_strategy_host.cpp:678`) and the kernel's `configure` (`pine_strategy_host.cpp:694`) have fixed and digested the spec. In substance (the risk-lowering comparison, `tests/test_adapter_risk_relower.cpp`, 62 checks over nine paired scenarios): the drawdown latch samples at the close only and still admits a reversal; the loss-day streak counts trades, not days; the intraday loss closes at the path's adverse extreme, refuses every placement and withdraws the book; the fill cap charges slots, transfers quota and closes at the bar's better extreme on the chart timezone's day. With the kernel seeded on the corpus, 3 of 4 cap probes diverge (3840 of 3916, 312 of 604, 2370 of 2384 rows; re-derived by `scripts/check_seeded_risk_experiment.sh` since the kernel/adapter differential study). `strategy.risk.allow_entry_in` is the one rule that is the kernel's already (`allowed_open_directions`). Design §3.6 | `examples/native/native_risk_limits_strategy.cpp`, `examples/native/native_trail_risk_strategy.cpp`, `tests/test_native_risk_limits.cpp`, `tests/test_native_c_api.c` |
| `max_abs_units` | **adapter-policy** | `strategy.risk.max_position_size` as a gate on the LIVE book before the fill (`max_position_size` `pine_adapter.cpp:17124`): an entry is refused once the book already holds the limit | design row MG2 (R5-1): the resulting-book cap is the generic one. Measured by N12's scenario `PS` in `tests/test_adapter_risk_relower.cpp`: two-unit entries against a limit of 3 leave the adapter at 4 and the kernel cap at 2 | `tests/test_native_resting_matching_contract.cpp`, `tests/test_native_run_spec.cpp` |
| `max_open_lots` | **adapter-policy** | Pine pyramiding is a per-cycle entry count in the adapter's command policy; a resting source entry must not consume a physical-lot cap before it fills, so `project()` leaves the cap unset (the `max_open_lots` setting spelling is at `pine_adapter.cpp:2835`) | design row MG3 (R5-1); the contract comment in `project()`. Measured against TradingView by the kernel/adapter differential study (the private test `test_pyramiding_count_differential`, 15 scenarios on three `lab tv` tapes): TradingView checks an entry once, at its first eligible point, against the trades then open, and does not check a resting entry again at its fill; the kernel's cap books 14 of the 15 as TradingView does, the adapter's per-cycle count 13 (it keeps a slot a close or another entry's exit drained; since the resting-entry signal-state correction a resting LIMIT entry no longer counts, and one the count admitted fills over the cap, and since the residual-margin correction's SB the later market entries of a flat bar are refused at the fill once the book holds the cap, as on TradingView's tapes). A recorded divergence: the retention stands until a re-lowering decision. The adapter state consolidation tried the lowering and kept the count: on the kernel's cap four corpus probes moved away from TradingView, for want of the first-eligible-point rule (the kernel/adapter differential study's P4b); it fixed the reservation divergence measured beside it (P10), so a default `strategy.exit(from_entry)` under FIFO now reserves its entry's own quantity, the oldest lots first, as TradingView does | `tests/test_native_resting_matching_contract.cpp`, `tests/test_native_margin_model.cpp` |
| `initial_margin_fraction` | **adapter-policy** | TradingView's ten-significant-digit money admission against the signal-time tuple, answered as `AdmitWithHostMargin`; the `margin` model the adapter does declare is maintenance-only (`NativeMarginModel` `pine_adapter.cpp:3074`, `margin.maintenance_long` `pine_adapter.cpp:3089`) | design row MG4 and the wave-4 ruling recorded in `project()`: a positive initial requirement would decline openings TradingView takes. Measured both ways by the kernel/adapter differential study (the private test `test_adapter_margin_schedule_differential`, M11): the kernel's gate declines a 1x long whose entry fee the adapter admits (`InitialMargin`), and admits a gap-up add the adapter refuses against its signal-time equity; `ab9714be` books the adapter's answer both times | `tests/test_native_precommit_view.cpp`, `tests/test_native_margin_model.cpp` |
| `report_open_position_at_end` | **adapter-policy** | The Pine host owns TradingView's range-end shape: batch re-marks the stored final point and re-folds extremes, while REALTIME retains ordinary marks and `PineStrategyHost::present_report` re-marks only the caller-owned copy before generic metric derivation; the stream hash excludes that terminal extreme fold (`scheduler_record_range_end` pine_strategy_host.cpp:2261): report shape, not a mark-to-market row (`KernelRecordedAtHostMarks` pine_adapter.cpp:3044) | design row RP5; the kernel reads the field under `KernelRecorded` only, which `scripts/check_adapter_spec_shadowing.py` gates | `examples/native/native_sized_report_strategy.cpp`, `tests/test_native_report_truth.cpp` |
Expand Down
4 changes: 2 additions & 2 deletions docs/design/arena-bound.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ indexPeak(k) = 24 * slots(k) # k > 32
| Entry-rank AVL | (60+L)*J + 1[J>0] | `exit_rank_keys_` at `src/source/pine_adapter.cpp:6773-6774`; `Links` at `include/pineforge/detail/disk_id_table.hpp:165-182`, `end_` at `:348` |
| Erased minima data | (40+L)*D + (40+2*L)*Q | `erased_minima_` at `include/pineforge/source/pine_adapter.hpp:960`; 40-byte header at `include/pineforge/detail/id_pair_store.hpp:69` |
| Erased minima index | indexPeak(D+Q) | 16-byte slot at `include/pineforge/detail/id_pair_store.hpp:69`; replacement at `:642` |
| Consumed partial-cycle data | (41+2*L)*Q | `include/pineforge/source/pine_adapter.hpp:2834`; joined key at `src/source/pine_adapter.cpp:25477` |
| Consumed partial-cycle data | (41+2*L)*Q | `include/pineforge/source/pine_adapter.hpp:2834`; joined key at `src/source/pine_adapter.cpp:25493` |
| Consumed partial-cycle index | indexPeak(Q) | `include/pineforge/detail/id_pair_store.hpp:642` |
| Ordered consumed-cycle fold | 136*leaves + 2088*branches + 2096*savedPath | `include/pineforge/detail/id_pair_ordered_fold.hpp:161`, `:165`, `:172`, size assertion for `Leaf`, `Branch` and `Snapshot` at `:183` |
| Successor-root rows | 16*R | `src/native_order.cpp:8220`, row assertion for `Row` at `:8141`, 64-row tail bound `kTailRows` at `:8146` |
Expand Down Expand Up @@ -381,7 +381,7 @@ root only when a newly issued definition has one. The 64-row RAM tail makes
charging every issued row conservative. Partial closes create one trade
row per affected lot: `src/engine_execution.cpp:1241`. Bracket definitions
have limit, stop and trailing families; per-entry expansion is visible at
`src/source/pine_adapter.cpp:23440`. A closed-trade count cannot bound
`src/source/pine_adapter.cpp:23456`. A closed-trade count cannot bound
unfilled placement history or the replacement-root history.

The ordered fold retains distinct-ever keys, including erased keys.
Expand Down
Loading
Loading