feat(shadow-account): add as-of price-context features (entry RSI, prior return)#302
Merged
warren618 merged 1 commit intoJun 25, 2026
Merged
Conversation
Extend Shadow Account feature engineering with two point-in-time-safe price-context features per profitable roundtrip, read as-of the buy date: - entry_rsi14: 14-period Wilder RSI at entry (causal; mirrors the shape of compute_rsi in skills/technical-basic, re-implemented since that hyphenated skills dir is not importable). - prior_5d_return: trailing 5-bar close-to-close return ending at buy_dt. Both read only bars dated <= buy_dt (never the (buy_dt, sell_dt] exit window), so look-ahead is structurally impossible — the fetch window ends at buy_dt. Prices come through the backtest loader registry (resolve_loader + fetch), the same path the runner uses. Any failure (unmapped market, no source, empty result, insufficient history) degrades to NaN and the pipeline still runs, honoring the v1 'price features optional' contract. A price feature joins the clustering numeric set only when present for >= min_support roundtrips; partial NaNs are median-imputed (imputation affects grouping only, never rule bounds). Tests are deterministic and network-free. Refs HKUDS#295 Signed-off-by: Robin1987China <41602358+Robin1987China@users.noreply.github.com>
Collaborator
|
Thanks @Robin1987China! Merged as |
Merged
9 tasks
warren618
pushed a commit
that referenced
this pull request
Jun 26, 2026
…es (#314) Promoted entry_rsi14 / prior_5d_return bounds now flow into extracted ShadowRules and the generated SignalEngine for real conditional entry. Follows #302. Thanks @Robin1987China.
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
Shadow Account's
_compute_features()only learned from journal columns(
holding_days,pnl_pct,entry_hour,entry_weekday,market), so theextracted rules were purely behavioral with no market context. This adds two
price-context features per profitable roundtrip, read as-of the buy date:
entry_rsi14— 14-period Wilder RSI at entryprior_5d_return— trailing 5-bar close-to-close return ending atbuy_dtThis is the first step you green-lit in #295. I followed the three scoping notes
from that thread:
compute_rsishape inagent/src/skills/technical-basic/example_signal_engine.py:13(re-implementedinline because that hyphenated skills dir isn't importable). Prices go through
the loader registry (
resolve_loader+fetch), the same pathbacktest/runner.pyuses.buy_dt, no look-ahead. Both features read only bars dated<= buy_dt. The fetch window ends atbuy_dt, so the(buy_dt, sell_dt]exitwindow is never touched — look-ahead is structurally impossible, not just
guarded after the fact.
no source, empty result, insufficient history) drops the feature to NaN and the
pipeline still runs. All tests use mocked loaders — no network.
A price feature only joins the KMeans feature set when it's present for
>= min_supportroundtrips; otherwise clustering stays journal-only, exactly asbefore. Partial NaNs are median-imputed (that affects grouping only — rule bounds
never read price features).
Why
Shadow Account extracts rules from journal columns alone, so extracted rules
are purely behavioral with no market context. Adding price-context features
lets clustering see whether profitable roundtrips share common entry conditions
(overbought RSI, recent momentum), making extracted rules actionable rather
than just descriptive.
Changes
agent/src/shadow_account/extractor.py:_compute_rsi,_fetch_price_history,_as_of_index,_price_features_as_of,_attach_price_features(batches onefetch per symbol);
_auto_clustertakes anumeric_featuresarg instead of themodule constant;
_promoted_numeric_featuresgates promotion.agent/tests/test_shadow_account.py: 15 new tests + an autouse offline fixtureso the suite stays network-free.
Test Plan
ruff check— cleanpytest agent/tests/test_shadow_account.py— 43 passedbuy_dtdon't change values),tz-aware
buy_dt, all three degradation branches, batch-once-per-symbol,median-impute / all-NaN-drop in clustering
Checklist
Refs #295