feat(rl): fractal-zigzag entry plug-in on 3-minute Parquet - #12
Merged
Conversation
…entries First concrete RLStrategy entry side: detect_fractal_zigzag_pivots with live_edge=True so entries are identical on any prefix (no drift at the data edge). Seam 1 of the TDD plan: the lookahead proof runs both the generic check_causal harness and an exact prefix==full comparison. Refs #7
Seam 2: every candidate carries sl_distance = stop_atr * Wilder ATR(atr_period) at the signal bar plus the absolute stop_price one stop against the trade from the detection-time entry reference. Refs #7
Seam 3: compute_obs_features reuses the causal pivot-structure block from futures_foundation.pivots (htf_dir excluded — its ATR floor is a full-series median, not truncation-invariant). Proven byte-identical under truncation in the new test. Refs #7
Seam 4: load_3min_parquet + SYMBOLS; the data-gated test proves all six instruments load, span 2021-04..2026-06, and produce a plausible entry rate (skips on CI where the Parquet data is absent). Refs #7
lgbarn
marked this pull request as ready for review
July 12, 2026 01:41
4 tasks
… tp_rr pin, hoisted imports)
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
futures_foundation/rl/fractal_zigzag.py:detect_entriesdriven bydetect_fractal_zigzag_pivots(the trigger-scan causal winner) withlive_edge=Truenewest-bar confirms, so entries are truncation-invariant at the data edge.sl_distance= 1x Wilder ATR(20) at the signal bar, and the absolutestop_price.compute_obs_featuresreuses the causal pivot-structure block fromfutures_foundation.pivots(htf_direxcluded — its ATR floor is a full-series median, not truncation-invariant, so not obs-safe).load_3min_parquet+SYMBOLSfor the six-instrument 3-min Parquet data; registered in the RL registry as"fractal_zigzag".Closes
Closes #7
Acceptance criteria
test_entries_truncation_invariant(genericcheck_causalharness + exact prefix==full frame equality)test_every_entry_has_1x_atr_stoptest_six_symbols_load_and_produce_plausible_counts(data-gated); counts reported belowtest_obs_features_truncation_invariant(byte-identical rows under truncation)Entry counts (full span, k=2, min_leg_atr=1.25, ATR(20))
The near-exact long/short split follows from the detector's strict pivot alternation; the ~1-entry-per-8-10-bars density is the intended mechanical-candidate stream (the PPO chop-veto is the filter, per the RLStrategy design).
Test plan
uv run pytest tests/test_fractal_zigzag_strategy.py -q— 4 pass (parquet test skips without data)FFM_DATA_DIR=<path-to>/data uv run pytest tests/test_fractal_zigzag_strategy.py -q— 4 pass including the six-symbol span/count checkuv run pytest tests/test_fractal_pivots.py tests/test_rl_pipeline.py -q— adjacent suites unchanged, greenNotes for reviewer
tddlabel): each acceptance criterion was one red→green cycle, in commit order — truncation invariance → 1x ATR stop → causal obs features → Parquet loader/counts.live_edge=Trueis hardwired indetect_entries: it is both the issue's requirement (newest-bar confirms for bar-by-bar consumers) and what makes the prefix==full equality exact at the boundary (a training-modecf+1 < nguard would drop the newest pivot on the prefix side).- [x]items are author claims verified by local test runs; the parquet-gated test skips on CI (data is local-only/gitignored), so the counts table is the CI-visible evidence for AC 3.futures_foundation/rl/fractal_zigzag.py,tests/test_fractal_zigzag_strategy.py);rl/env.py,rl/__init__.py,tests/test_rl_pipeline.py, andtopstep.pyuntouched (sibling-owned this wave).ModuleNotFoundErrorfor optional deps (sklearn/torch/optuna/onnxruntime) absent from the local env; CI installs requirements.txt and is the arbiter.Out of scope
causal_htf_dirfirst; noted, not changed.