Repository navigation
round 7e: trail fills snap directionally at sub-tick opens, trail_points/offset tick rounding, trail activation on the quantized bar, Pine tolerant compare inside ta.dmi - #184
Merged
Conversation
…ck grid; tolerant trail_points ceil
Three trailing-exit rules pinned from TradingView tapes in round 7
(family G, stevenygabbyperez-fast-scalper-with-stops: strategy.exit(
stop=close*0.99|1.01, trail_points=close*0.02/syminfo.mintick, no
trail_offset); `lab tv` tapes scratchpad/r7/pins/scalper-trail-* and
trail-eq-*, campaign notes log-20260905t083... "PINNED (trail_points
without trail_offset...)" and log-20260905t090209z-57b186b9 "PINNED
(trail fill snap + activation grid...)", record scalper-PINS.md). TV is
ground truth.
(1) A one-shot (omitted / zero-offset) trail whose activation the bar's
OPEN already sits past arms at the open and fills at open -/+ 0 as a
LEVEL: directional snap (sell floor, buy ceil), not the nearest-tick
rounding of a raw print the order gapped through.
NASDAQ:AAPL 15m long 2025-04-21 19:45Z @191.91 (383.82 -> 384 ticks,
activation 195.75); 04-22 13:30Z opens 196.135: TV 196.13 with the
offset omitted and with trail_offset=0, 196.12 with trail_offset=1.
The engine booked bar_fill_price(196.135) = 196.14 -- the FIRST
divergence on the AAPL@15 lane (long 5455 -> $54.55 equity), the
rest of its 40/42 unmatched entries the all-in reversal cascade.
NASDAQ:AAPL 15m short 05-22 17:30Z @201.9; 05-23 13:30Z opens
193.665: TV 193.67 (ceil == nearest there).
Fix: try_exit_open_gap_fill flags the exits_at_activation open fill as
open_is_trail_level (new ExitPathFill field); evaluate_fill_price books
it as a level (apply_slippage's directional snap) instead of
bar_fill_price. A trail the open gaps through in the ADVERSE direction
(armed level) keeps the raw-print booking.
(2) trail_points is a tick count with a TOLERANT ceil; trail_offset an
EXACT floor. NYSE:F 15m short from the 04-02 19:00Z signal (entry
10.11), zero-offset trails filling at the activation:
14.00001 -> 14 ticks (@9.97); 14.0001 / 14.001 -> 15 (@9.96);
0.14 / syminfo.mintick (= 14.000000000000002) -> 14; 14.0000001 -> 14;
18.2 -> 19 (@9.92); trail_offset 0.3 / (syminfo.mintick * 10)
(= 2.9999999999999996) -> 2 ticks (04-03 14:15Z @9.85, not 9.86).
BINANCE:BTCUSDT 15m short 2025-08-17 23:30Z @117559.99 with
trail_points = 117560 * 0.02 / 0.01 = 235120.00000000003: TV exits
08-18 03:30Z @115208.79 (235120 ticks); std::ceil gave 235121 ->
.78 (the probe's BTC@15 first divergence).
Fix: trail_points_to_ticks = ceil(trail_points - 5e-5) (the tolerance
lies in [1e-5, 1e-4)); trail_offset_to_ticks = floor (unchanged
semantics, shared helper also used by the excursion peak fold).
(3) The activation level (entry -/+ N ticks) and the trailing level
(best -/+ K ticks) are ON the tick grid: a bar extreme landing exactly
on the level touches it. 10.11 - 21 * 0.01 is 9.899999999999999 in
doubles, one ulp UNDER the 9.9 low of NYSE:F 2025-04-03 13:45Z (O 10.165
H 10.18 L 9.9 C 9.9): TV fills the probe's trail there @9.90
(trail-eq-S-off0-tp21); the engine read the H->L leg as "not reached"
and gap-filled the next open @9.89. The "stop == trough == close
equality" reading of that row is REFUTED: trail_points 18 fills the
same bar at its activation 9.93 (trail-eq-S-off0 / -omit), the long
twin (@9.88, trail_points 8) fills 04-02 13:30Z @9.96 on a close == high
bar (trail-eq-L-off0). Whole-tick offsets trail durably with an
inclusive touch: trail_offset=1 fills 04-03 14:00Z @9.90 (trough 9.89 at
the open + 1t == the high; trail-eq-S-off1), the long 04-02 13:45Z @9.97
(9.985 - 1t = 9.975 floored; trail-eq-L-off1).
Fix: snap_trail_level_to_tick_grid materializes a level within 1e-6
tick of the grid as the grid point (tick_grid_price's k / (1/mintick)
spelling, bit-identical to a feed print); sub-tick levels such as
196.125 stay raw and take the directional fill snap. Applied to the
activation in compute_exit_trail_state and to active_exit_trail_level.
Untouched: stop / limit legs (round-6 quantized-bar trigger, fills as
before), the round-5 trail rules (open arming, sub-tick offset = 0,
no retro-arm, omitted-offset carried arming), the trail's raw-bar
trigger compares.
Tests: tests/test_trail_fill_snap.cpp (228 checks) pins every tape at
the resolver and end to end through BacktestEngine over the registry
bars (`lab bars` NASDAQ:AAPL / NYSE:F / BINANCE:BTCUSDT 15m): AAPL
196.13 / 196.12 / 193.67, F 9.90 / 9.93 / 9.92 / 9.97 / 9.96 / 9.85 /
9.90(off1) / 9.96(L) / 9.97(L off1), BTC 115208.79, the ceil / floor /
grid arithmetic, and controls (on-tick open unchanged, a resting stop
gapped at 196.135 still 196.14, adverse gap through an armed trail
level still a raw print). Against the pre-fix source the tape cells
fail. ctest 171/171 (was 170/170), scripts unittest 127/127,
check_c_abi_runtime ok.
Expected movers: fast-scalper AAPL@15 (weak 89.2 -> the 04-22 cascade
removed), BTC@15 (.79 row), F@15 (04-03 13:45Z row; entries already
99.3); any trail lane with FP-noisy trail_points or a sub-tick open.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CDd4qRxehN8VJ5o4wHDCw2
…own / down>up / up>0
TradingView's Pine float relationals treat two finite values as EQUAL when
|a - b| <= 1e-10 — an absolute, magnitude-independent band, inclusive at
exactly 1e-10 — and its builtins decide on the same predicate. Inside
ta.dmi the `up > down and up > 0` selection therefore books NEITHER
directional movement on an exact-decimal tie, where the engine's strict
IEEE compare handed the move to one side.
Pin (round 7 family K, boztilkiserhan serhan-1 wma-adx-trailing NYSE:F@15,
campaign notes log-20260905t084532z-25b09a71 and log-20260905t085626z-aff373d2):
* scratchpad/r7/pins/f15-plusdm-perbar-0714 (one qty-encoded lot per bar
over 2025-07-14..18) locates the single differing bar: 07-15 19:30Z,
up = 11.58 - 11.565, down = 11.54 - 11.525, both 0.015 in decimal and
1.78e-15 apart as doubles; TV's plusDM is 0.
* f15-dmi-internals-0718 / f15-wma-adx-sense-0718 (+ two history starts):
TV rma(plusDM,18) 0.006907 vs strict 0.006939, +DI 16.92562 vs
17.00417, ADX 24.22236 vs 23.571 at the 07-18 14:15Z signal — the bar
whose ADX > 24 short fires on TV only. Replaying the registry 15m bars
with the tolerant compare gives 0.006907 / 16.9256 / 24.2223.
* f15-eps-{abs,rel} (20 decisions, this session) pin the band itself:
equal for d = 1e-11..1e-14 at 11.5, 1e-10 vs 0 EQUAL (inclusive),
1.1e-10 vs 0 greater, a relative 1e-11 diff greater at m >= 100 —
bit-for-bit the codegen's KI-73 predicate (visit_expr.py
_emit_float_relational).
include/pineforge/pine_float_compare.hpp carries the predicate (pine_float_
eq/ne/gt/lt/ge/le, na -> false); ta.percentrank's src[i] <= src, which
already used a private copy of the band, reads the shared constant.
Surveyed and left alone (unpinned): ta.supertrend's close vs band and band
carry compares, ta.sar's high/low vs sar/ep, ta.mfi's src vs src[1] — the
same shape on derived doubles but no tape yet; ta.crossover/crossunder/
cross stay strict (round 7 family D pin: the cross decides on the exact
sign of the residual); obv/wad/pivot compare raw prints where the band
cannot matter.
tests/test_dmi_parity.cpp: the 07-15 19:30Z tie -> +DI = -DI = 0, clear
differences unchanged, the up > 0 band, and the 20 sensor decisions.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01FhcjTNYXowGbf116WBsgLF
…best kept)
TradingView tests a trailing stop's ACTIVATION (trail_points / trail_price)
against the bar's OHLC quantized to the tick — the round-6 stop / limit
trigger rule (design-stop-tick-rounding) extended to the trail's arming —
while the trail's running best stays the raw print (round 5). The engine
tested the raw bar, so a sub-tick extreme that TradingView reads as
touching the level left the trail dormant and slid the exit 1-4 bars.
Pin (round 7 family K, boztilkiserhan serhan-1 wma-adx-trailing NYSE:F@15,
campaign note log-20260905t084531z-57cedc55): three `lab tv` tapes on
NYSE:F 15m 2025-04-10..18, fixed 100 shares, scratchpad/r7/pins/
f15-trail-0415-{reissue,fixed760,fixed754} — a short entered 04-15 14:45Z
@9.49 with strategy.exit(trail_points = close * 0.008 / syminfo.mintick,
trail_offset = 0) re-issued every bar, or fixed 7.60 / 7.54 ticks (all
ceil to 8 -> activation 9.41) — ALL exit on the 15:45Z bar @9.41. That
bar's raw low is 9.415 (> 9.41: the engine's no-activate, exit slid to
16:45Z) and its quantized low is 9.41 (9.415 is 9.41499.. in binary),
which reaches the activation; offset 0 exits one-shot at the level. The
same slide shows on 06-20 (15:30Z vs 19:45Z) and 2026-01-21 (15:30Z vs
16:15Z) and on the serhan1 wma-rsi sibling (exitP90 0.0064 residual).
engine_path_resolve.cpp:
* a dormant exit-at-activation trail's activation reach is found on the
tick-quantized path segment (select_exit_segment_levels reports it
apart from an ACTIVE trail's level, which stays on the raw path;
collect_cross_events_split gains the trail_activation_level leg);
* update_exit_trail_state arms on the quantized segment end while the
running best takes the raw end;
* compute_exit_trail_state reads the carried raw best tick-quantized for
the arming test (the broker read the bars that produced it).
The open-gap test (try_exit_open_gap_fill) is untouched — unpinned, and
owned by round7/trail-fill-snap. The round-6 stopround-xt-L-trail pin
(raw best: a quantized 14.04 would have printed 14.01 where TradingView
exits at the next open) still holds — test_stop_tick_rounding passes.
tests/test_trail_activation_tick_bar.cpp: the three tapes replayed on the
registry 15m bars (exit 15:45Z @9.41 — was 16:45Z), a 9-tick control that
must NOT fire, and resolver-level pins (activation on the tick leg with
its chronology, an offset trail arming on the quantized extreme and
trailing the raw best, the carried best read quantized, a raw reach
unchanged).
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01FhcjTNYXowGbf116WBsgLF
…egistry NYSE:F bars)
Round 7 family K mechanism 3 (mukhlisilahi universal-backtest-pro NYSE:F@15,
campaign note log-20260905t084530z-66c3f27e) diagnosed the probe's chart
EMAs as running on the 15m AGGREGATE close of
[o, h, l, c, v] = request.security(syminfo.tickerid, tf_input,
[open, high, low, close, volume])
instead of TradingView's native 1D close (77/77 TV entries reproduce with
the native close, 76/77 engine entries with the aggregate), and named the
engine's tuple path as the suspect.
The engine's tuple path is NOT the defect. The codegen lowers the tuple body
to one evaluator assigning every element from the completed bucket
(`_req_sec_0_3 = bar.close`), and feed_security_input substitutes the native
row (substitute_native_security_bar) before any evaluator is dispatched, so
the scalar and tuple forms read the same bar. This test pins it on the
registry's own prints — NYSE:F 15m 2025-04-22 / 04-23 (feed 80f404ae85ef)
against the exchange's 1D rows (feed e3dd3a88e85b): with the feed installed
the tuple is the native row verbatim under both "D" and "1D" (04-22 close
9.65 where the last 15m print is 9.655; 04-23 9.835 / 10.0054 / 9.71 /
9.78 / 158,691,527 against the aggregate 9.83 / 10.0 / 9.715 / 9.765),
without it the aggregate — the values the probe's runs actually carried.
Why the runs carried the aggregate: the harness routes the native-daily
ladder candidate only when the source names the daily timeframe by LITERAL
("D" / "1D") — pineforge-lab scripts/verify_routing.py
executable_uses_daily_security, whose docstring excludes a variable
timeframe on purpose — and this script's timeframe is
input.timeframe("D") bound to `tf_input`, so the candidate never ran
(verify report db81fe845ec4: no securityFeed field, inputs null -> the
default "D"). The fix is the harness's routing (route an input.timeframe
whose default is daily, or route whenever the lane declares a 1D feed and
the argument is not a non-daily literal); no engine change.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01FhcjTNYXowGbf116WBsgLF
luisleo526
added a commit
that referenced
this pull request
Oct 12, 2026
Move CODEGEN_COMMIT in scripts/regen_corpus_cpp.sh and the matching literal and message in scripts/test_regen_corpus_cpp_pin.py from codegen a4259656 to the codegen v1.5.0 commit 52101f9b7b540fece4493ddc7495451b6d85fc07. The runtime image pin is unchanged. Measured on one AWS spot box (c5.4xlarge, engine b802cee, corpus b40aa8ec, docker transpile path, the exact edit of this commit applied by the round): - the old-pin control regeneration is clean (314 sources, 0 drifted); - all 314 regenerated generated.cpp change (312 validation probes and the 2 draft probes), 0 transpile failures; - fresh sweep of the old pin versus fresh sweep of the new pin on the same box: the engine trade lists of 312 of 312 validation probes are byte-identical; both headlines read excellent=311 anomaly=1; - the pin test and the VERIFY=1 idempotence check after regeneration pass. The regenerated files are in the paired pineforge-corpus change. Every file gains the same 321 lines, which were introduced by the codegen between the two pins: the coded run stops (codegen #184), the checked strategy settings and C ABI exception containment (#159), and the compiled-execution, confirmed-bar and order-shapes receipts (#167, #173, #178). 6 to 116 further lines per file are probe-specific. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
luisleo526
added a commit
that referenced
this pull request
Oct 12, 2026
Move the corpus gitlink from 9245f28a to e99bbd9db257740d9c77db37a8567616627130bf and record it on the `# corpus` line of scripts/corpus_parity_baseline.txt. The 312 baseline digests do not change: the engine trade lists are byte-identical (measured, below). Follows the pin commit of the same pull request. The corpus change (the two commits on top of the removal/headers change) re-emits all 312 validation generated.cpp with codegen 52101f9b7b540fece4493ddc7495451b6d85fc07 and re-derives the 60 generated_cpp_sha256 values of owned_strategies.json; validation_run there still records the 2026-09-26 sweep. Measured on AWS spot boxes: - trades, in the pin round of the previous commit (engine b802cee, corpus b40aa8ec; b802cee..2dbd72f changes only tests and CI scripts, and the 312 generated.cpp compiled there at the new pin are byte-identical to those in e99bbd9d): a fresh full sweep at the old pin and one at the new pin (same box, runtime, harness and feed) give byte-identical engine trade lists for 312 of 312 validation probes; both verifier headlines read excellent=311 anomaly=1; - with this engine (2dbd72f): the bytes in the corpus equal the new-pin regeneration of the final tree on a second box for 312 of 312 files, and VERIFY=1 scripts/regen_corpus_cpp.sh over the final tree reports 312 strategies, 0 drifted, 0 failed to transpile. Every generated.cpp gains the same 321 lines, which were introduced by the codegen between the two pins: the coded run stops (codegen #184), the checked strategy settings and C ABI exception containment (#159), and the compiled-execution, confirmed-bar and order-shapes receipts (#167, #173, #178); 6 to 116 further lines per file are probe-specific. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
luisleo526
added a commit
that referenced
this pull request
Oct 13, 2026
…ve the corpus gitlink to e99bbd9 (#377) build: pin the corpus regeneration to codegen 1.5.0 (52101f9b) Move CODEGEN_COMMIT in scripts/regen_corpus_cpp.sh and the matching literal and message in scripts/test_regen_corpus_cpp_pin.py from codegen a4259656 to the codegen v1.5.0 commit 52101f9b7b540fece4493ddc7495451b6d85fc07. The runtime image pin is unchanged. Measured on one AWS spot box (c5.4xlarge, engine b802cee, corpus b40aa8ec, docker transpile path, the exact edit of this commit applied by the round): - the old-pin control regeneration is clean (314 sources, 0 drifted); - all 314 regenerated generated.cpp change (312 validation probes and the 2 draft probes), 0 transpile failures; - fresh sweep of the old pin versus fresh sweep of the new pin on the same box: the engine trade lists of 312 of 312 validation probes are byte-identical; both headlines read excellent=311 anomaly=1; - the pin test and the VERIFY=1 idempotence check after regeneration pass. The regenerated files are in the paired pineforge-corpus change. Every file gains the same 321 lines, which were introduced by the codegen between the two pins: the coded run stops (codegen #184), the checked strategy settings and C ABI exception containment (#159), and the compiled-execution, confirmed-bar and order-shapes receipts (#167, #173, #178). 6 to 116 further lines per file are probe-specific. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> corpus: move the gitlink to e99bbd9d (generated.cpp from codegen 1.5.0) Move the corpus gitlink from 9245f28a to e99bbd9db257740d9c77db37a8567616627130bf and record it on the `# corpus` line of scripts/corpus_parity_baseline.txt. The 312 baseline digests do not change: the engine trade lists are byte-identical (measured, below). Follows the pin commit of the same pull request. The corpus change (the two commits on top of the removal/headers change) re-emits all 312 validation generated.cpp with codegen 52101f9b7b540fece4493ddc7495451b6d85fc07 and re-derives the 60 generated_cpp_sha256 values of owned_strategies.json; validation_run there still records the 2026-09-26 sweep. Measured on AWS spot boxes: - trades, in the pin round of the previous commit (engine b802cee, corpus b40aa8ec; b802cee..2dbd72f changes only tests and CI scripts, and the 312 generated.cpp compiled there at the new pin are byte-identical to those in e99bbd9d): a fresh full sweep at the old pin and one at the new pin (same box, runtime, harness and feed) give byte-identical engine trade lists for 312 of 312 validation probes; both verifier headlines read excellent=311 anomaly=1; - with this engine (2dbd72f): the bytes in the corpus equal the new-pin regeneration of the final tree on a second box for 312 of 312 files, and VERIFY=1 scripts/regen_corpus_cpp.sh over the final tree reports 312 strategies, 0 drifted, 0 failed to transpile. Every generated.cpp gains the same 321 lines, which were introduced by the codegen between the two pins: the coded run stops (codegen #184), the checked strategy settings and C ABI exception containment (#159), and the compiled-execution, confirmed-bar and order-shapes receipts (#167, #173, #178); 6 to 116 further lines per file are probe-specific. Co-Authored-By: Claude Sonnet 5.5 <[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.
Round-7e engine candidate (on the round-7c head d9e15ab; codegen unchanged at 65e7fd0), gated PASS against baseline
pineforge-parity-baseline-20260905-engine-d9e15abd(fast pr-gate, hard 0 regressions): 4161 → 4162 excellent+strong, +9 tiers, 0 down.Pinned on TradingView (
lab tvtapes; rules in the campaign ledger):trail_pointsceils with an FP tolerance (14.00001 → 14 ticks) andtrail_offsetfloors exactly; activation and trailing levels within 1e-6 tick of the grid sit on the grid, so a touch counts.ta.dmi(up > down), shared viapine_float_compare.hpp.request.securitypath is pinned by test (already correct).Tests: ctest 174/174.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Pyos7rr4EChCzh3H6S3Vob