Compare commits

..
15 changed files with 788 additions and 624 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
# TradeAC custom-qlib-code snapshot (auto-generated) # TradeAC custom-qlib-code snapshot (auto-generated)
# parent repo HEAD : bba17bd401cd9cca714c329f7eb3ab71c36a490b # parent repo HEAD : 507846cee16eeee11daf33c4176e8aec79b985b2
# tac-qlib/tac_qlib/contrib # tac-qlib/tac_qlib/contrib
# tac-qlib/tac_qlib/data # tac-qlib/tac_qlib/data
# per-file hashes (git hash-object): # per-file hashes (git hash-object):
+35
View File
@@ -0,0 +1,35 @@
# Q08 — Risk-limit A/B re-validation (trace 40)
**Status:** DONE (verdict: REFUTED as an IR edge; safety-net value retained)
## Input
- Reference signal: exp-26 pred, run `21afc6afdb674a399b59dd76c97628ce` (mlflow exp 25)
- Window: 2026-01-04 → 2026-08-10, Topk10 n_drop1, SPY benchmark, $1M, 5/15bp/$5
- Tool: `rd_risk_calibrate` (A/B + sensitivity grid). Full JSON: `risk_calibration.json`
## Candidate spec (round-3 live spec)
`{"liquidity_floor_adv": 5000000, "size_cap_pct": 0.12, "concentration_cap_pct": 0.95, "drawdown_pause_pct": 0.10}`
## Results (net, with cost)
| Config | IR | Ann. return | Max DD |
|---|---|---|---|
| baseline (no limits) | 1.5804 | +27.50% | −6.91% |
| **candidate (5M floor + caps)** | **1.5121** | +2.20% | **−0.65%** |
| liquidity $10M | 1.5457 | +2.25% | −0.64% |
## Findings
- **Floor binds, not a no-op**: $5M liquidity floor dropped 8 symbols —
`DBA, DBC, ESPO, FDN, REM, TAN, UNG, XAR`.
- **No IR edge from the gate**: candidate IR (1.512) is BELOW baseline (1.580).
The exp-18 direction (floor IR 0.81→0.98) does NOT reproduce on the clean-lake
reference signal.
- **Drawdown cut is pure defunding**: size_cap 0.12 × concentration 0.95 fold
the effective risk_degree to ~0.0095 → ~$9.5k deployed of $1M (~100x less).
Sensitivity grid shows both caps are no-ops (conc 20–50% identical,
size_cap 5–20% identical); only the liquidity floor moves returns, marginally.
- **Conclusion**: keep the live spec as a safety net; there is no risk-limit
gate IR edge to harvest when the signal is the bottleneck (exp-20 pattern).
## Artifacts on this branch
- `evidence/q08-risklimit/risk_calibration.json` — full calibration dump
- `queue/designs/q08_risk_limit_ab.md` — the pre-registered design doc
@@ -0,0 +1,401 @@
{
"rows": [
{
"label": "baseline (no limits)",
"mean": 0.001155,
"std": 0.011279,
"annualized_return": 0.274989,
"information_ratio": 1.580427,
"max_drawdown": -0.069145
},
{
"label": "liquidity $10,000,000",
"mean": 9.4e-05,
"std": 0.000942,
"annualized_return": 0.022464,
"information_ratio": 1.545736,
"max_drawdown": -0.006389
},
{
"label": "conc 20%",
"mean": 0.000115,
"std": 0.001168,
"annualized_return": 0.027285,
"information_ratio": 1.513718,
"max_drawdown": -0.008104
},
{
"label": "conc 30%",
"mean": 0.000115,
"std": 0.001168,
"annualized_return": 0.027285,
"information_ratio": 1.513718,
"max_drawdown": -0.008104
},
{
"label": "conc 40%",
"mean": 0.000115,
"std": 0.001168,
"annualized_return": 0.027285,
"information_ratio": 1.513718,
"max_drawdown": -0.008104
},
{
"label": "conc 50%",
"mean": 0.000115,
"std": 0.001168,
"annualized_return": 0.027285,
"information_ratio": 1.513718,
"max_drawdown": -0.008104
},
{
"label": "candidate {\"liquidity_floor_adv\": 5000000.0, \"size_cap_pct\": 0.12, \"concentration_cap_pct\": 0.95, \"drawdown_pause_pct\": 0.1}",
"mean": 9.2e-05,
"std": 0.000943,
"annualized_return": 0.021991,
"information_ratio": 1.512051,
"max_drawdown": -0.00653
},
{
"label": "size_cap 5%",
"mean": 9.2e-05,
"std": 0.000943,
"annualized_return": 0.021991,
"information_ratio": 1.512051,
"max_drawdown": -0.00653
},
{
"label": "size_cap 10%",
"mean": 9.2e-05,
"std": 0.000943,
"annualized_return": 0.021991,
"information_ratio": 1.512051,
"max_drawdown": -0.00653
},
{
"label": "size_cap 15%",
"mean": 9.2e-05,
"std": 0.000943,
"annualized_return": 0.021991,
"information_ratio": 1.512051,
"max_drawdown": -0.00653
},
{
"label": "size_cap 20%",
"mean": 9.2e-05,
"std": 0.000943,
"annualized_return": 0.021991,
"information_ratio": 1.512051,
"max_drawdown": -0.00653
},
{
"label": "liquidity $5,000,000",
"mean": 9.2e-05,
"std": 0.000943,
"annualized_return": 0.021991,
"information_ratio": 1.512051,
"max_drawdown": -0.00653
},
{
"label": "liquidity $1,000,000",
"mean": 9.1e-05,
"std": 0.000929,
"annualized_return": 0.021625,
"information_ratio": 1.508748,
"max_drawdown": -0.006376
},
{
"label": "liquidity $2,500,000",
"mean": 7.1e-05,
"std": 0.000918,
"annualized_return": 0.017,
"information_ratio": 1.199721,
"max_drawdown": -0.007158
}
],
"runs": {
"baseline": {
"risk": {
"mean": 0.0011554172081987572,
"std": 0.01127853762493476,
"annualized_return": 0.27498929555130425,
"information_ratio": 1.5804272791471323,
"max_drawdown": -0.06914515336341577
},
"applied": {}
},
"candidate": {
"risk": {
"mean": 9.239707947451976e-05,
"std": 0.0009427144352738658,
"annualized_return": 0.0219905049149357,
"information_ratio": 1.5120514373488407,
"max_drawdown": -0.006530482262119444
},
"applied": {
"dropped_liquidity": [
"DBA",
"DBC",
"ESPO",
"FDN",
"REM",
"TAN",
"UNG",
"XAR"
]
}
},
"size_cap 5%": {
"risk": {
"mean": 9.239707947451976e-05,
"std": 0.0009427144352738658,
"annualized_return": 0.0219905049149357,
"information_ratio": 1.5120514373488407,
"max_drawdown": -0.006530482262119444
},
"applied": {
"dropped_liquidity": [
"DBA",
"DBC",
"ESPO",
"FDN",
"REM",
"TAN",
"UNG",
"XAR"
]
}
},
"size_cap 10%": {
"risk": {
"mean": 9.239707947451976e-05,
"std": 0.0009427144352738658,
"annualized_return": 0.0219905049149357,
"information_ratio": 1.5120514373488407,
"max_drawdown": -0.006530482262119444
},
"applied": {
"dropped_liquidity": [
"DBA",
"DBC",
"ESPO",
"FDN",
"REM",
"TAN",
"UNG",
"XAR"
]
}
},
"size_cap 15%": {
"risk": {
"mean": 9.239707947451976e-05,
"std": 0.0009427144352738658,
"annualized_return": 0.0219905049149357,
"information_ratio": 1.5120514373488407,
"max_drawdown": -0.006530482262119444
},
"applied": {
"dropped_liquidity": [
"DBA",
"DBC",
"ESPO",
"FDN",
"REM",
"TAN",
"UNG",
"XAR"
]
}
},
"size_cap 20%": {
"risk": {
"mean": 9.239707947451976e-05,
"std": 0.0009427144352738658,
"annualized_return": 0.0219905049149357,
"information_ratio": 1.5120514373488407,
"max_drawdown": -0.006530482262119444
},
"applied": {
"dropped_liquidity": [
"DBA",
"DBC",
"ESPO",
"FDN",
"REM",
"TAN",
"UNG",
"XAR"
]
}
},
"conc 20%": {
"risk": {
"mean": 0.00011464156491316718,
"std": 0.0011683839517000441,
"annualized_return": 0.027284692449333788,
"information_ratio": 1.5137180903503433,
"max_drawdown": -0.008103887185240407
},
"applied": {
"dropped_liquidity": [
"DBA",
"DBC",
"ESPO",
"FDN",
"REM",
"TAN",
"UNG",
"XAR"
]
}
},
"conc 30%": {
"risk": {
"mean": 0.00011464156491316718,
"std": 0.0011683839517000441,
"annualized_return": 0.027284692449333788,
"information_ratio": 1.5137180903503433,
"max_drawdown": -0.008103887185240407
},
"applied": {
"dropped_liquidity": [
"DBA",
"DBC",
"ESPO",
"FDN",
"REM",
"TAN",
"UNG",
"XAR"
]
}
},
"conc 40%": {
"risk": {
"mean": 0.00011464156491316718,
"std": 0.0011683839517000441,
"annualized_return": 0.027284692449333788,
"information_ratio": 1.5137180903503433,
"max_drawdown": -0.008103887185240407
},
"applied": {
"dropped_liquidity": [
"DBA",
"DBC",
"ESPO",
"FDN",
"REM",
"TAN",
"UNG",
"XAR"
]
}
},
"conc 50%": {
"risk": {
"mean": 0.00011464156491316718,
"std": 0.0011683839517000441,
"annualized_return": 0.027284692449333788,
"information_ratio": 1.5137180903503433,
"max_drawdown": -0.008103887185240407
},
"applied": {
"dropped_liquidity": [
"DBA",
"DBC",
"ESPO",
"FDN",
"REM",
"TAN",
"UNG",
"XAR"
]
}
},
"liquidity $1,000,000": {
"risk": {
"mean": 9.086210454881382e-05,
"std": 0.0009290831160004576,
"annualized_return": 0.021625180882617688,
"information_ratio": 1.508747982736451,
"max_drawdown": -0.006376134679664126
},
"applied": {
"dropped_liquidity": [
"ESPO"
]
}
},
"liquidity $2,500,000": {
"risk": {
"mean": 7.142665167642606e-05,
"std": 0.0009184775632266332,
"annualized_return": 0.016999543098989402,
"information_ratio": 1.1997208834083914,
"max_drawdown": -0.0071582979845040825
},
"applied": {
"dropped_liquidity": [
"DBA",
"DBC",
"ESPO",
"REM",
"XAR"
]
}
},
"liquidity $5,000,000": {
"risk": {
"mean": 9.239707947451976e-05,
"std": 0.0009427144352738658,
"annualized_return": 0.0219905049149357,
"information_ratio": 1.5120514373488407,
"max_drawdown": -0.006530482262119444
},
"applied": {
"dropped_liquidity": [
"DBA",
"DBC",
"ESPO",
"FDN",
"REM",
"TAN",
"UNG",
"XAR"
]
}
},
"liquidity $10,000,000": {
"risk": {
"mean": 9.438545151345752e-05,
"std": 0.0009420158170657147,
"annualized_return": 0.02246373746020289,
"information_ratio": 1.5457360696934006,
"max_drawdown": -0.006388809561209335
},
"applied": {
"dropped_liquidity": [
"DBA",
"DBC",
"ESPO",
"FDN",
"ICLN",
"ITA",
"MDY",
"REM",
"SHY",
"TAN",
"UNG",
"XAR"
]
}
}
},
"candidate": {
"liquidity_floor_adv": 5000000.0,
"size_cap_pct": 0.12,
"concentration_cap_pct": 0.95,
"drawdown_pause_pct": 0.1
}
}
-69
View File
@@ -1,69 +0,0 @@
# TradeAC Experiment Queue — Series 2 (Q12+)
**Purpose.** The next pre-registered batch of experiments, continuing Series 1
(Q01–Q11, exp 33–43, all executed and folded into `book/CLAIMS.md` /
`book/EVIDENCE.md`). Each entry targets a still-unproven `HYPOTHESIS` from the
book or an open question flagged in `CLAIMS.md`/`book/README.md`, and follows the
Series-1 discipline: one variable changed vs the exp-26 reference, acceptance
fixed BEFORE the run, sequential execution, trace-first, verify-then-close.
**Reference / control (MUST reproduce first).** exp 26 (`21afc6af…`, mlflow exp
25) is the campaign baseline; exp 39 (Q07, weekly rebalance) is the best
construction. Reference config is byte-reproduced in `workflows/exp26/` on the
`exp/26-…` branch and in this dir's `workflows/*.yaml`.
| Config element | exp-26 reference value |
|---|---|
| Universe | 50-ETF panel (`UNIVERSE` below) |
| Features | compact stochastic 25-field set (no ou/hmm/moments/garch) |
| Label | `Ref($close,-6)/Ref($close,-1)-1` (5d) |
| Model | `RankICEnsembleLGBModel`, seeds `42,7,2026,99,123`, lr 0.02, leaves 31, 3000 rounds, ES 200 |
| Segments | train 2016-01-04..2025-09-01 / valid 2025-09-03..2026-01-03 / test 2026-01-04..2026-08-10 |
| Strategy | TopkDropout, topk 10, n_drop 1, risk_degree 0.95 |
| Costs | open 0.0005 / close 0.0015 / min $5, deal $close, SPY benchmark, $1M |
**Reference metrics to beat (EVIDENCE#015):** net_ann +2.13%, net_IR 0.21, gross
+7.02%, maxDD −7.69%, RankIC 0.0663, RankICIR 0.2545, L/S Sharpe 4.54. Weekly
(Q07, EVIDENCE#028): net +12.51%, IR 1.24, maxDD −4.13%, ~1.1pp cost drag.
## The queue (ordered by value × feasibility)
| ID | Title / hypothesis | Change vs reference (ONE var) | Acceptance | Config | Ready? |
|----|--------------------|-------------------------------|------------|--------|--------|
| Q12 | **22d label + weekly recompute** — the untested combo: Q05's label edge (IC 0.097, RankIC 0.117) with Q07's cost relief | label → 22d AND strategy → weekly (two coupled, explicitly pre-registered) | net_IR > 0.5, net_ann > +5%, cost drag ≤ 2pp | `workflows/q12_label22d_weekly.yaml` | ✅ |
| Q13 | **Weekly rebalance reproduction on a 2nd window** — Q07 was a single OOS window; reproduce on test 2025-01-02..2025-12-31 before promoting to a live round | segments only (shifted) | net_IR > 0.21, net_ann > +2.13% on the new window | `workflows/q13_weekly_second_window.yaml` | ✅ |
| Q14 | **Out-of-universe validation** — compact stochastic set generalizes off the 50-ETF panel to a single-stock universe | universe → 30 liquid single names | RankIC > 0.03, ICIR > 0.15, net IR > 0 on stocks | `workflows/q14_out_of_universe.yaml` | ⚠️ needs stock-lake backfill (see design) |
| Q15 | **5-seed vs single-model clean A/B** — seed-count claim (exp 12 idea, re-validated exp 22–24, never a clean A/B) | seeds → 1 (`2026`) | single-model RankIC/IR < 5-seed ref; net_IR ≥ 0.21 acceptable if ≥ single | `workflows/q15_single_seed.yaml` | ✅ |
| Q16 | **HMM family added as features** — settles "dropping model-specific (ou,hmm) improves signal" (exp 25 tested OU; hmm-as-feature untested) | features += `sp_hmm_p_regime1,sp_hmm_state` | no improvement: RankIC ≤ 0.0663, net_IR ≤ 0.21 | `workflows/q16_hmm_features.yaml` | ✅ |
| Q17 | **Realized-moments family added** — settles "moment/volatility families regress" (exp 11 idea, never clean A/B) | features += `sp_rskew_5,sp_rskew_22,sp_rkurt_5,sp_rkurt_22,sp_dsv_5,sp_dsv_22` | no improvement: RankIC ≤ 0.0663, net_IR ≤ 0.21 | `workflows/q17_moments_features.yaml` | ✅ |
| Q18 | **OptimalStopControl clean re-test** — exp 13/14 claim (TopkDropout > stop-control) never re-tested post-reset | strategy → `OptimalStopControl` (exp-13 params) | TopkDropout net_IR ≥ stop-control net_IR; document cost drag | `workflows/q18_optstop.yaml` | ✅ (module verified in venv) |
| Q19 | **Martingale / variance-ratio study close-out** — exp 19 never closed; VR<1 at 5–20d on clean lake | ad-hoc script (no qrun) | VR stats + drift decomposition on 50-ETF panel | `designs/q19_martingale_vr.md` | ✅ script |
| Q20 | **Effective independent names (≈4)** — eigenvalue analysis on clean-lake covariance | ad-hoc script | eigenvalue spectrum + effective-rank count | `designs/q20_effective_names.md` | ✅ script |
### Deferred (methodology / infra, P3)
- Purged / walk-forward CV (was queue's old Q12) — methodology, not an alpha lever.
- PSI-based drift-aware retraining cadence — needs a drift-gate module + a retrain decision rule.
- No-trade buffer band / notional-vs-qty sizing — siblings of Q12/Q13; queue only if weekly reproduces.
- Macro/drift overlays (SPY>200d regime gate, momentum tilt) — needs new data pipeline.
## Execution protocol (per queued run)
1. **Validate the lake first** (`validate_lake_dataset` + `rd_status`) — clean-lake lesson: silent NaN-drops and hollow coverage invalidate a run. Q14 additionally requires backfilling the single-stock universe (bars + sp/ta features, full range, explicit `start`/`end`).
2. **Trace before running** (`rd_trace_start` with the hypothesis as `rational`, fresh `experiment_name`, `evolved_from=auto`).
3. **Run** `rd_run_workflow config_path=<abs path to the queue YAML> experiment_name=<fresh name>` — `wait=false`, poll `rd_exp_get_run` until `FINISHED`.
4. **Verify against acceptance** via `rd_exp_result` (headline + backtest risk).
5. **Finish the trace** (`rd_trace_finish` with `metrics` + `evaluation`), snapshot any changed contrib modules.
6. **Report to the book** — PROVE/REFUTE → update `book/CLAIMS.md` + `book/EVIDENCE.md`.
Sequential execution only (concurrent runs hang — chat-ideas.md ops lesson). Any
custom strategy/module changed here must be copied into the venv site-packages
snapshot before `rd_run_workflow` can import it (see `/app/AGENTS.md`). As of
2026-08-20 `WeeklyRebalanceDropoutStrategy` and `OptimalStopControl` are verified
in sync with the venv snapshot; the lake already persists the `sp_hmm_*` and
`sp_moments` families on the 50-ETF panel.
## Provenance
Mined 2026-08-20 from `book/CLAIMS.md`, `book/EVIDENCE.md`, `book/README.md`,
`book/references/chat-ideas.md`, and Series-1 `queue/` (Q01–Q11, executed exp
33–43). Reference numbers are post-clean-lake (exp 21+).
+34
View File
@@ -0,0 +1,34 @@
# QUEUE-08 — Risk-limit A/B re-validation: $5M liquidity floor on the exp-26 reference
**Status:** QUEUED · **Priority:** P1 · **Effort:** tool-only (no new code)
## Hypothesis (prove)
The $5M liquidity floor improves net IR and cuts drawdown on the **post-reset**
reference signal (pre-reset exp 18, EVIDENCE#008: net IR 0.81→0.98, cumDD
7.93%→5.44%), while size/concentration caps hurt by cutting deployed capital.
Needs re-validation on the exp-26 lineage because exp 18 is pre-clean-lake and
not comparable (EVIDENCE#009/010). Source: `book/CLAIMS.md` open question +
`book/README.md` `TODO(evidence-needed: reconciliation of exp 18 risk-limit spec
on the post-reset reference signal)`.
## Change vs exp-26 reference (ONE variable)
- Reference: the saved exp-26 prediction (run `21afc6af…`, mlflow exp 25).
- A/B via `rd_risk_calibrate` (runs limit-vs-no-limit A/B + sensitivity grid
over size_cap_pct, concentration_cap_pct, liquidity_floor_adv) and/or
`rd_backtest` with `risk_limits` on the SAME saved `pred.pkl`:
- baseline: no limits (this must reproduce the exp-26 net +2.13% / IR 0.21);
- candidate: `{"liquidity_floor_adv": 5000000, "size_cap_pct": 0.12,
"concentration_cap_pct": 0.95, "drawdown_pause_pct": 0.10}` (round-3 spec).
- Pick the spec (B2 calibration) that keeps live ≈ backtest.
## Acceptance
- Candidate spec: `net_IR > 0.21` AND `net_max_drawdown < 7.69%` vs no-limit on
the same pred. Size/concentration caps expected to REDUCE deployed capital
(record the direction as confirmation of exp 18).
- If the floor is a no-op (gates don't bind at this signal) → report that gates
are no-ops when the signal is the bottleneck (exp 20 pattern) as a PROVEN
clean-lake result.
## Execution prerequisites
- None (uses saved pred + `rd_risk_calibrate`/`rd_backtest`). Trace the A/B as
an experiment; record the spec chosen for the next live round.
-26
View File
@@ -1,26 +0,0 @@
# QUEUE-19 — Martingale / variance-ratio study close-out (no qrun)
**Status:** QUEUED · **Priority:** P2 · **Effort:** ad-hoc script under `book/data/`
## Hypothesis (settle)
Assets are submartingales long-horizon / mean-reverting short-horizon
(`VR < 1` at 5–20d). CLAIMS.md marks this HYPOTHESIS (chat-derived martingale
study; exp 19 was opened but never closed). It is a market-structure claim, not a
trading claim — settle it with a clean-lake script, then close exp 19 or open a
scripted EVIDENCE entry.
## Method (persist everything under `book/data/evidence/q19-vr/`)
1. Load the 50-ETF panel 1d bars from the lake for 2015-01-01..2026-08-19.
2. Compute the Lo–MacKinlay variance ratio at horizons 5 / 10 / 20d per symbol,
with heteroskedasticity-robust z-stats.
3. Report: per-horizon VR distribution, fraction of symbols with VR < 1 and the
z-significance, pooled drift vs daily variance (submartingale check).
4. Cross-check the pooled `sp_trend_slope_5` regression beta claim (β ≈ −0.53,
t ≈ −24) on the clean lake.
5. Write `VR_stats.csv` + a one-page summary into the evidence dir.
## Acceptance
- VR < 1 at 5–20d for a material fraction of the panel with |z| > 2 → supports
the mean-reversion HYPOTHESIS; else mark REFUTED or REFERENCED.
- The result updates CLAIMS.md's "Assets are submartingales…" row and closes the
exp-19 open thread.
-22
View File
@@ -1,22 +0,0 @@
# QUEUE-20 — Effective independent names in the 50-ETF book (no qrun)
**Status:** QUEUED · **Priority:** P2 · **Effort:** ad-hoc script under `book/data/`
## Hypothesis (settle)
The 50-ETF book has only ~4 effective independent names (CLAIMS.md HYPOTHESIS,
chat-derived eigenvalue analysis, pre-reset). This is a concentration/diversification
claim with direct sizing relevance; verify it on the clean lake.
## Method (persist everything under `book/data/evidence/q20-effective-names/`)
1. Load the 50-ETF panel 1d returns from the lake for the test window 2026-01-04..2026-08-10.
2. Standardize returns; compute the correlation matrix and its eigendecomposition.
3. Count eigenvalues above the Marchenko–Pastur bound (N=50, T≈150) and report the
cumulative-variance share of the top k components.
4. Effective-rank measures: participation ratio `(Σλ)² / Σλ²` and cumulative 80%
variance count.
5. Write `eigenanalysis.csv` + a one-page summary.
## Acceptance
- If effective rank ≈ 4 (top-4 explain ~80%+ variance), the concentration claim is
PROVEN and feeds chapter 08 sizing guidance (why topk 10→20 adds no breadth).
- If effective rank is much larger, mark the claim REFUTED.
-105
View File
@@ -1,105 +0,0 @@
# QUEUE-12 — Long-horizon label (22d) + weekly recompute construction.
# Untested combination from book/CLAIMS.md open questions: Q05 (exp 37) proved the
# 22d label has the strongest signal (IC 0.097, RankIC 0.117) but daily turnover
# killed the book (net -4.60%); Q07 (exp 39) proved weekly recompute is the cost
# lever (net +12.51%). Hypothesis: pairing them monetizes the label edge.
# Change vs exp-26 reference: label 5d -> 22d AND strategy -> WeeklyRebalanceDropoutStrategy.
# Acceptance: net_IR > 0.5, net_ann > +5%, cost drag <= 2pp.
# Run: rd_run_workflow config_path=<repo>/experiments/queue/workflows/q12_label22d_weekly.yaml \
# experiment_name=tac-rd-q12-label22d-weekly
{%- set LAKE = TAC_LAKE_DIR %}
{%- set UNIVERSE = "SPY,QQQ,DIA,IWM,MDY,VTI,VOO,VEA,VWO,VT,EFA,EEM,TLT,IEF,SHY,AGG,BND,LQD,HYG,JNK,EMB,GLD,SLV,USO,UNG,DBA,DBC,XLK,XLF,XLE,XLV,XLI,XLY,XLP,XLU,XLB,XLRE,ARKK,SMH,SOXX,IBB,XBI,ITA,XAR,ICLN,TAN,FDN,IGV,ESPO,REM" %}
{%- set FEATURES = "$open,$high,$low,$close,$vwap,$volume,sp_ret,sp_jump_ratio,sp_jump_flag,sp_jump_tail,sp_max_move,sp_rv1,sp_rv5,sp_rv22,sp_vol_ratio_5_22,sp_vol_ratio_1_22,sp_trend_slope_5,sp_trend_slope_20,sp_trend_slope_60,sp_logp,sp_hurst_exponent,sp_sig_level1_lead,sp_sig_level1_lag,sp_sig_level2_lead_lag,sp_sig_level2_lag_lead" %}
qlib_init:
provider_uri: "{{ LAKE }}"
region: us
expression_cache: null
dataset_cache: null
calendar_provider:
class: tac_qlib.data.providers.LakeCalendarProvider
kwargs: { lake_root: "{{ LAKE }}", market: US }
instrument_provider:
class: tac_qlib.data.providers.LakeInstrumentProvider
kwargs: { lake_root: "{{ LAKE }}", market: US, markets: {} }
feature_provider:
class: tac_qlib.data.providers.LakeFeatureProvider
kwargs: { lake_root: "{{ LAKE }}", market: US }
exp_manager:
class: MLflowExpManager
module_path: qlib.workflow.expm
kwargs: { uri: "sqlite:///mlruns.db", default_exp_name: "tac-rd-q12-label22d-weekly" }
task:
model:
class: RankICEnsembleLGBModel
module_path: tac_qlib.contrib.model.rank_ensemble
kwargs:
loss: mse
learning_rate: 0.02
num_leaves: 31
n_estimators: 3000
num_boost_round: 3000
early_stopping_rounds: 200
min_data_in_leaf: 20
lambda_l2: 0.5
colsample_bytree: 0.8
subsample: 0.8
subsample_freq: 1
reg_alpha: 0.1
reg_lambda: 1.0
seeds: "42,7,2026,99,123"
dataset:
class: DatasetH
module_path: qlib.data.dataset
kwargs:
handler:
class: TACHandler
module_path: tac_qlib.contrib.data.handler
kwargs:
instruments: "{{ UNIVERSE }}"
start_time: 2015-01-03
end_time: 2026-08-10
fit_start_time: 2016-01-04
fit_end_time: 2025-09-01
freq: day
lake_root: "{{ LAKE }}"
market: US
label: "Ref($close,-23)/Ref($close,-1)-1"
feature_fields: "{{ FEATURES }}"
infer_processors:
- { class: DropAllNaN, kwargs: { fit_start_time: "2016-01-04", fit_end_time: "2025-09-01" } }
- { class: ProcessInf, kwargs: {} }
- { class: CSRankNorm, kwargs: {} }
- { class: ZScoreNorm, kwargs: { fit_start_time: "2016-01-04", fit_end_time: "2025-09-01" } }
- { class: Fillna, kwargs: {} }
segments:
train: [2016-01-04, 2025-09-01]
valid: [2025-09-03, 2026-01-03]
test: [2026-01-04, 2026-08-10]
record:
- { class: SignalRecord, module_path: qlib.workflow.record_temp, kwargs: {} }
- { class: SigAnaRecord, module_path: qlib.workflow.record_temp, kwargs: { ana_long_short: true, ann_scaler: 252 } }
- class: PortAnaRecord
module_path: qlib.workflow.record_temp
kwargs:
config:
strategy:
class: WeeklyRebalanceDropoutStrategy
module_path: tac_qlib.contrib.strategy.weekly_rebalance
kwargs: { signal: "<PRED>", topk: 10, n_drop: 1, only_tradable: true, risk_degree: 0.95 }
backtest:
start_time: 2026-01-04
end_time: 2026-08-10
account: 1000000
benchmark: SPY
exchange_kwargs:
codes: "{{ UNIVERSE }}"
deal_price: $close
freq: day
open_cost: 0.0005
close_cost: 0.0015
min_cost: 5.0
risk_analysis_freq: 1d
@@ -1,106 +0,0 @@
# QUEUE-13 — Weekly rebalance reproduction on a second OOS window.
# Q07 (exp 39) proved weekly recompute on test 2026-01-04..2026-08-10 (net +12.51%,
# IR 1.24) but that is a single OOS window. Before promoting the weekly construction
# to a live round, reproduce it on a disjoint window: test 2025-01-02..2025-12-31
# with train/valid shifted to end 2024.
# Change vs exp-26 reference: segments shifted only (train ends 2024-08, test = 2025);
# strategy is the SAME weekly recompute as exp 39. Label stays 5d.
# Acceptance: net_IR > 0.21 AND net_ann > +2.13% on the 2025 window.
# Run: rd_run_workflow config_path=<repo>/experiments/queue/workflows/q13_weekly_second_window.yaml \
# experiment_name=tac-rd-q13-weekly-second-window
{%- set LAKE = TAC_LAKE_DIR %}
{%- set UNIVERSE = "SPY,QQQ,DIA,IWM,MDY,VTI,VOO,VEA,VWO,VT,EFA,EEM,TLT,IEF,SHY,AGG,BND,LQD,HYG,JNK,EMB,GLD,SLV,USO,UNG,DBA,DBC,XLK,XLF,XLE,XLV,XLI,XLY,XLP,XLU,XLB,XLRE,ARKK,SMH,SOXX,IBB,XBI,ITA,XAR,ICLN,TAN,FDN,IGV,ESPO,REM" %}
{%- set FEATURES = "$open,$high,$low,$close,$vwap,$volume,sp_ret,sp_jump_ratio,sp_jump_flag,sp_jump_tail,sp_max_move,sp_rv1,sp_rv5,sp_rv22,sp_vol_ratio_5_22,sp_vol_ratio_1_22,sp_trend_slope_5,sp_trend_slope_20,sp_trend_slope_60,sp_logp,sp_hurst_exponent,sp_sig_level1_lead,sp_sig_level1_lag,sp_sig_level2_lead_lag,sp_sig_level2_lag_lead" %}
qlib_init:
provider_uri: "{{ LAKE }}"
region: us
expression_cache: null
dataset_cache: null
calendar_provider:
class: tac_qlib.data.providers.LakeCalendarProvider
kwargs: { lake_root: "{{ LAKE }}", market: US }
instrument_provider:
class: tac_qlib.data.providers.LakeInstrumentProvider
kwargs: { lake_root: "{{ LAKE }}", market: US, markets: {} }
feature_provider:
class: tac_qlib.data.providers.LakeFeatureProvider
kwargs: { lake_root: "{{ LAKE }}", market: US }
exp_manager:
class: MLflowExpManager
module_path: qlib.workflow.expm
kwargs: { uri: "sqlite:///mlruns.db", default_exp_name: "tac-rd-q13-weekly-second-window" }
task:
model:
class: RankICEnsembleLGBModel
module_path: tac_qlib.contrib.model.rank_ensemble
kwargs:
loss: mse
learning_rate: 0.02
num_leaves: 31
n_estimators: 3000
num_boost_round: 3000
early_stopping_rounds: 200
min_data_in_leaf: 20
lambda_l2: 0.5
colsample_bytree: 0.8
subsample: 0.8
subsample_freq: 1
reg_alpha: 0.1
reg_lambda: 1.0
seeds: "42,7,2026,99,123"
dataset:
class: DatasetH
module_path: qlib.data.dataset
kwargs:
handler:
class: TACHandler
module_path: tac_qlib.contrib.data.handler
kwargs:
instruments: "{{ UNIVERSE }}"
start_time: 2015-01-03
end_time: 2025-12-31
fit_start_time: 2016-01-04
fit_end_time: 2024-08-30
freq: day
lake_root: "{{ LAKE }}"
market: US
label: "Ref($close,-6)/Ref($close,-1)-1"
feature_fields: "{{ FEATURES }}"
infer_processors:
- { class: DropAllNaN, kwargs: { fit_start_time: "2016-01-04", fit_end_time: "2024-08-30" } }
- { class: ProcessInf, kwargs: {} }
- { class: CSRankNorm, kwargs: {} }
- { class: ZScoreNorm, kwargs: { fit_start_time: "2016-01-04", fit_end_time: "2024-08-30" } }
- { class: Fillna, kwargs: {} }
segments:
train: [2016-01-04, 2024-08-30]
valid: [2024-09-03, 2024-12-31]
test: [2025-01-02, 2025-12-31]
record:
- { class: SignalRecord, module_path: qlib.workflow.record_temp, kwargs: {} }
- { class: SigAnaRecord, module_path: qlib.workflow.record_temp, kwargs: { ana_long_short: true, ann_scaler: 252 } }
- class: PortAnaRecord
module_path: qlib.workflow.record_temp
kwargs:
config:
strategy:
class: WeeklyRebalanceDropoutStrategy
module_path: tac_qlib.contrib.strategy.weekly_rebalance
kwargs: { signal: "<PRED>", topk: 10, n_drop: 1, only_tradable: true, risk_degree: 0.95 }
backtest:
start_time: 2025-01-02
end_time: 2025-12-31
account: 1000000
benchmark: SPY
exchange_kwargs:
codes: "{{ UNIVERSE }}"
deal_price: $close
freq: day
open_cost: 0.0005
close_cost: 0.0015
min_cost: 5.0
risk_analysis_freq: 1d
-107
View File
@@ -1,107 +0,0 @@
# QUEUE-14 — Out-of-universe validation: compact stochastic set on single-stock names.
# The 50-ETF panel results (compact feature set, RankIC 0.0663) are panel-specific;
# book/CLAIMS.md marks "generalizes to other universes" HYPOTHESIS - TODO(evidence-needed).
# Change vs exp-26 reference: universe -> 30 liquid US single-stock names.
# PREREQUISITE: backfill lake bars + sp/ta features for these symbols (full range,
# explicit start/end) — the stock panel currently has only ~180d of data (2025-12-01+).
# Backfill: get_lake_bars symbols=... start=2000-01-03 then
# get_lake_sp symbol=<s> start=2000-01-03 end=<today> fit_end=<train-end> persist=true
# Acceptance: RankIC > 0.03, ICIR > 0.15, net IR > 0 on the stock universe.
# Run: rd_run_workflow config_path=<repo>/experiments/queue/workflows/q14_out_of_universe.yaml \
# experiment_name=tac-rd-q14-out-of-universe
{%- set LAKE = TAC_LAKE_DIR %}
{%- set UNIVERSE = "AAPL,MSFT,NVDA,AMZN,GOOGL,META,TSLA,AVGO,AMD,JPM,UNH,PG,JNJ,MA,V,WMT,DIS,HD,KO,PEP,BAC,XOM,MCD,ABBV,COST,CRM,NFLX,ORCL,IBM,T" %}
{%- set FEATURES = "$open,$high,$low,$close,$vwap,$volume,sp_ret,sp_jump_ratio,sp_jump_flag,sp_jump_tail,sp_max_move,sp_rv1,sp_rv5,sp_rv22,sp_vol_ratio_5_22,sp_vol_ratio_1_22,sp_trend_slope_5,sp_trend_slope_20,sp_trend_slope_60,sp_logp,sp_hurst_exponent,sp_sig_level1_lead,sp_sig_level1_lag,sp_sig_level2_lead_lag,sp_sig_level2_lag_lead" %}
qlib_init:
provider_uri: "{{ LAKE }}"
region: us
expression_cache: null
dataset_cache: null
calendar_provider:
class: tac_qlib.data.providers.LakeCalendarProvider
kwargs: { lake_root: "{{ LAKE }}", market: US }
instrument_provider:
class: tac_qlib.data.providers.LakeInstrumentProvider
kwargs: { lake_root: "{{ LAKE }}", market: US, markets: {} }
feature_provider:
class: tac_qlib.data.providers.LakeFeatureProvider
kwargs: { lake_root: "{{ LAKE }}", market: US }
exp_manager:
class: MLflowExpManager
module_path: qlib.workflow.expm
kwargs: { uri: "sqlite:///mlruns.db", default_exp_name: "tac-rd-q14-out-of-universe" }
task:
model:
class: RankICEnsembleLGBModel
module_path: tac_qlib.contrib.model.rank_ensemble
kwargs:
loss: mse
learning_rate: 0.02
num_leaves: 31
n_estimators: 3000
num_boost_round: 3000
early_stopping_rounds: 200
min_data_in_leaf: 20
lambda_l2: 0.5
colsample_bytree: 0.8
subsample: 0.8
subsample_freq: 1
reg_alpha: 0.1
reg_lambda: 1.0
seeds: "42,7,2026,99,123"
dataset:
class: DatasetH
module_path: qlib.data.dataset
kwargs:
handler:
class: TACHandler
module_path: tac_qlib.contrib.data.handler
kwargs:
instruments: "{{ UNIVERSE }}"
start_time: 2015-01-03
end_time: 2026-08-10
fit_start_time: 2016-01-04
fit_end_time: 2025-09-01
freq: day
lake_root: "{{ LAKE }}"
market: US
label: "Ref($close,-6)/Ref($close,-1)-1"
feature_fields: "{{ FEATURES }}"
infer_processors:
- { class: DropAllNaN, kwargs: { fit_start_time: "2016-01-04", fit_end_time: "2025-09-01" } }
- { class: ProcessInf, kwargs: {} }
- { class: CSRankNorm, kwargs: {} }
- { class: ZScoreNorm, kwargs: { fit_start_time: "2016-01-04", fit_end_time: "2025-09-01" } }
- { class: Fillna, kwargs: {} }
segments:
train: [2016-01-04, 2025-09-01]
valid: [2025-09-03, 2026-01-03]
test: [2026-01-04, 2026-08-10]
record:
- { class: SignalRecord, module_path: qlib.workflow.record_temp, kwargs: {} }
- { class: SigAnaRecord, module_path: qlib.workflow.record_temp, kwargs: { ana_long_short: true, ann_scaler: 252 } }
- class: PortAnaRecord
module_path: qlib.workflow.record_temp
kwargs:
config:
strategy:
class: TopkDropoutStrategy
module_path: qlib.contrib.strategy
kwargs: { signal: "<PRED>", topk: 10, n_drop: 1, only_tradable: true, risk_degree: 0.95 }
backtest:
start_time: 2026-01-04
end_time: 2026-08-10
account: 1000000
benchmark: SPY
exchange_kwargs:
codes: "{{ UNIVERSE }}"
deal_price: $close
freq: day
open_cost: 0.0005
close_cost: 0.0015
min_cost: 5.0
risk_analysis_freq: 1d
-106
View File
@@ -1,106 +0,0 @@
# QUEUE-18 — OptimalStopControl clean re-test vs TopkDropout (exp 13/14 claim).
# CLAIMS.md HYPOTHESIS: "TopkDropout beats stochastic-control OptimalStopControl on
# the ensemble signal" — exp 13/14 were pre-clean-lake; never re-tested post-reset.
# Same compact signal as the exp-26 reference; ONLY the strategy changes to
# OptimalStopControl with exp-13 params (entry 0.85 / exit 0.7 / hold 10 / sl -0.08).
# PREREQUISITE: tac_qlib/contrib/strategy/optimal_stop.py must be synced to the venv
# site-packages snapshot before running (see /app/AGENTS.md).
# Acceptance: TopkDropout net_IR >= stop-control net_IR; document cost drag of both.
# Run: rd_run_workflow config_path=<repo>/experiments/queue/workflows/q18_optstop.yaml \
# experiment_name=tac-rd-q18-optstop
{%- set LAKE = TAC_LAKE_DIR %}
{%- set UNIVERSE = "SPY,QQQ,DIA,IWM,MDY,VTI,VOO,VEA,VWO,VT,EFA,EEM,TLT,IEF,SHY,AGG,BND,LQD,HYG,JNK,EMB,GLD,SLV,USO,UNG,DBA,DBC,XLK,XLF,XLE,XLV,XLI,XLY,XLP,XLU,XLB,XLRE,ARKK,SMH,SOXX,IBB,XBI,ITA,XAR,ICLN,TAN,FDN,IGV,ESPO,REM" %}
{%- set FEATURES = "$open,$high,$low,$close,$vwap,$volume,sp_ret,sp_jump_ratio,sp_jump_flag,sp_jump_tail,sp_max_move,sp_rv1,sp_rv5,sp_rv22,sp_vol_ratio_5_22,sp_vol_ratio_1_22,sp_trend_slope_5,sp_trend_slope_20,sp_trend_slope_60,sp_logp,sp_hurst_exponent,sp_sig_level1_lead,sp_sig_level1_lag,sp_sig_level2_lead_lag,sp_sig_level2_lag_lead" %}
qlib_init:
provider_uri: "{{ LAKE }}"
region: us
expression_cache: null
dataset_cache: null
calendar_provider:
class: tac_qlib.data.providers.LakeCalendarProvider
kwargs: { lake_root: "{{ LAKE }}", market: US }
instrument_provider:
class: tac_qlib.data.providers.LakeInstrumentProvider
kwargs: { lake_root: "{{ LAKE }}", market: US, markets: {} }
feature_provider:
class: tac_qlib.data.providers.LakeFeatureProvider
kwargs: { lake_root: "{{ LAKE }}", market: US }
exp_manager:
class: MLflowExpManager
module_path: qlib.workflow.expm
kwargs: { uri: "sqlite:///mlruns.db", default_exp_name: "tac-rd-q18-optstop" }
task:
model:
class: RankICEnsembleLGBModel
module_path: tac_qlib.contrib.model.rank_ensemble
kwargs:
loss: mse
learning_rate: 0.02
num_leaves: 31
n_estimators: 3000
num_boost_round: 3000
early_stopping_rounds: 200
min_data_in_leaf: 20
lambda_l2: 0.5
colsample_bytree: 0.8
subsample: 0.8
subsample_freq: 1
reg_alpha: 0.1
reg_lambda: 1.0
seeds: "42,7,2026,99,123"
dataset:
class: DatasetH
module_path: qlib.data.dataset
kwargs:
handler:
class: TACHandler
module_path: tac_qlib.contrib.data.handler
kwargs:
instruments: "{{ UNIVERSE }}"
start_time: 2015-01-03
end_time: 2026-08-10
fit_start_time: 2016-01-04
fit_end_time: 2025-09-01
freq: day
lake_root: "{{ LAKE }}"
market: US
label: "Ref($close,-6)/Ref($close,-1)-1"
feature_fields: "{{ FEATURES }}"
infer_processors:
- { class: DropAllNaN, kwargs: { fit_start_time: "2016-01-04", fit_end_time: "2025-09-01" } }
- { class: ProcessInf, kwargs: {} }
- { class: CSRankNorm, kwargs: {} }
- { class: ZScoreNorm, kwargs: { fit_start_time: "2016-01-04", fit_end_time: "2025-09-01" } }
- { class: Fillna, kwargs: {} }
segments:
train: [2016-01-04, 2025-09-01]
valid: [2025-09-03, 2026-01-03]
test: [2026-01-04, 2026-08-10]
record:
- { class: SignalRecord, module_path: qlib.workflow.record_temp, kwargs: {} }
- { class: SigAnaRecord, module_path: qlib.workflow.record_temp, kwargs: { ana_long_short: true, ann_scaler: 252 } }
- class: PortAnaRecord
module_path: qlib.workflow.record_temp
kwargs:
config:
strategy:
class: OptimalStopControl
module_path: tac_qlib.contrib.strategy.optimal_stop
kwargs: { signal: "<PRED>", topk: 10, entry_pct: 0.85, exit_pct: 0.7, max_hold_days: 10, min_hold_days: 2, sl: -0.08 }
backtest:
start_time: 2026-01-04
end_time: 2026-08-10
account: 1000000
benchmark: SPY
exchange_kwargs:
codes: "{{ UNIVERSE }}"
deal_price: $close
freq: day
open_cost: 0.0005
close_cost: 0.0015
min_cost: 5.0
risk_analysis_freq: 1d
@@ -1,39 +1,51 @@
# QUEUE-16 — HMM family added as model features to the compact set. # -----------------------------------------------------------------------------
# CLAIMS.md HYPOTHESIS: "Dropping model-specific feature families (ou, hmm) # ABLATION A (baseline): LightGBM with RankIC early-stopping on the 50-ETF SP-5d
# improves the rank signal" — exp 25 cleanly tested OU (adding it hurts: IC 0.0511->0.0343); # panel, using ALL 24 sp_* feature columns (ou,hmm,jump,har,trend,hurst,
# hmm-as-features has NOT been clean A/B'd post-reset (exp 42 tested hmm as an entry # signature). Copy of the canonical workflow_lgb_sp5d_rankic.yaml with a
# GATE overlay, refuted). This run adds the hmm family columns to the compact set. # distinct experiment name so the ablation runs are isolated.
# Change vs exp-26 reference: features += sp_hmm_p_regime1, sp_hmm_state. #
# Acceptance (prune-hypothesis): no improvement — RankIC <= 0.0663, net_IR <= 0.21. # Run:
# Run: rd_run_workflow config_path=<repo>/experiments/queue/workflows/q16_hmm_features.yaml \ # rd_run_workflow config_path=tac-qlib/workflows/ablate_baseline_all_sp_fields.yaml \
# experiment_name=tac-rd-q16-hmm-features # experiment_name=tac-rd-rank-ablate
# -----------------------------------------------------------------------------
{%- set LAKE = TAC_LAKE_DIR %} {%- set LAKE = TAC_LAKE_DIR %}
{%- set UNIVERSE = "SPY,QQQ,DIA,IWM,MDY,VTI,VOO,VEA,VWO,VT,EFA,EEM,TLT,IEF,SHY,AGG,BND,LQD,HYG,JNK,EMB,GLD,SLV,USO,UNG,DBA,DBC,XLK,XLF,XLE,XLV,XLI,XLY,XLP,XLU,XLB,XLRE,ARKK,SMH,SOXX,IBB,XBI,ITA,XAR,ICLN,TAN,FDN,IGV,ESPO,REM" %} {%- set UNIVERSE = "SPY,QQQ,DIA,IWM,MDY,VTI,VOO,VEA,VWO,VT,EFA,EEM,TLT,IEF,SHY,AGG,BND,LQD,HYG,JNK,EMB,GLD,SLV,USO,UNG,DBA,DBC,XLK,XLF,XLE,XLV,XLI,XLY,XLP,XLU,XLB,XLRE,ARKK,SMH,SOXX,IBB,XBI,ITA,XAR,ICLN,TAN,FDN,IGV,ESPO,REM" %}
{%- set FEATURES = "$open,$high,$low,$close,$vwap,$volume,sp_ret,sp_jump_ratio,sp_jump_flag,sp_jump_tail,sp_max_move,sp_rv1,sp_rv5,sp_rv22,sp_vol_ratio_5_22,sp_vol_ratio_1_22,sp_trend_slope_5,sp_trend_slope_20,sp_trend_slope_60,sp_logp,sp_hurst_exponent,sp_sig_level1_lead,sp_sig_level1_lag,sp_sig_level2_lead_lag,sp_sig_level2_lag_lead,sp_hmm_p_regime1,sp_hmm_state" %} {%- set SP_FIELDS = "sp_ret,sp_ou_zscore,sp_ou_half_life,sp_ou_revert,sp_hmm_p_regime1,sp_hmm_state,sp_jump_ratio,sp_jump_flag,sp_jump_tail,sp_max_move,sp_rv1,sp_rv5,sp_rv22,sp_vol_ratio_5_22,sp_vol_ratio_1_22,sp_trend_slope_5,sp_trend_slope_20,sp_trend_slope_60,sp_logp,sp_hurst_exponent,sp_sig_level1_lead,sp_sig_level1_lag,sp_sig_level2_lead_lag,sp_sig_level2_lag_lead" %}
qlib_init: qlib_init:
provider_uri: "{{ LAKE }}" provider_uri: "{{ LAKE }}"
region: us region: us
expression_cache: null expression_cache: null
dataset_cache: null dataset_cache: null
calendar_provider: calendar_provider:
class: tac_qlib.data.providers.LakeCalendarProvider class: tac_qlib.data.providers.LakeCalendarProvider
kwargs: { lake_root: "{{ LAKE }}", market: US } kwargs:
lake_root: "{{ LAKE }}"
market: US
instrument_provider: instrument_provider:
class: tac_qlib.data.providers.LakeInstrumentProvider class: tac_qlib.data.providers.LakeInstrumentProvider
kwargs: { lake_root: "{{ LAKE }}", market: US, markets: {} } kwargs:
lake_root: "{{ LAKE }}"
market: US
markets: {}
feature_provider: feature_provider:
class: tac_qlib.data.providers.LakeFeatureProvider class: tac_qlib.data.providers.LakeFeatureProvider
kwargs: { lake_root: "{{ LAKE }}", market: US } kwargs:
lake_root: "{{ LAKE }}"
market: US
exp_manager: exp_manager:
class: MLflowExpManager class: MLflowExpManager
module_path: qlib.workflow.expm module_path: qlib.workflow.expm
kwargs: { uri: "sqlite:///mlruns.db", default_exp_name: "tac-rd-q16-hmm-features" } kwargs:
uri: "sqlite:///{{ LAKE }}/mlruns.db"
default_exp_name: "tac-rd-rank-ablate"
task: task:
model: model:
class: RankICEnsembleLGBModel class: RankICLGBModel
module_path: tac_qlib.contrib.model.rank_ensemble module_path: tac_qlib.contrib.model.rank_gbdt
kwargs: kwargs:
loss: mse loss: mse
learning_rate: 0.02 learning_rate: 0.02
@@ -48,7 +60,7 @@ task:
subsample_freq: 1 subsample_freq: 1
reg_alpha: 0.1 reg_alpha: 0.1
reg_lambda: 1.0 reg_lambda: 1.0
seeds: "42,7,2026,99,123" seed: 42
dataset: dataset:
class: DatasetH class: DatasetH
@@ -61,27 +73,38 @@ task:
instruments: "{{ UNIVERSE }}" instruments: "{{ UNIVERSE }}"
start_time: 2015-01-03 start_time: 2015-01-03
end_time: 2026-08-10 end_time: 2026-08-10
fit_start_time: 2016-01-04 fit_start_time: 2015-01-03
fit_end_time: 2025-09-01 fit_end_time: 2025-09-01
freq: day freq: day
lake_root: "{{ LAKE }}" lake_root: "{{ LAKE }}"
market: US market: US
label: "Ref($close,-6)/Ref($close,-1)-1" label: "Ref($close,-6)/Ref($close,-1)-1"
feature_fields: "{{ FEATURES }}" feature_fields: "$open,$high,$low,$close,$vwap,$volume,{{ SP_FIELDS }}"
infer_processors: infer_processors:
- { class: DropAllNaN, kwargs: { fit_start_time: "2016-01-04", fit_end_time: "2025-09-01" } } - class: DropAllNaN
- { class: ProcessInf, kwargs: {} } kwargs: {}
- { class: CSRankNorm, kwargs: {} } - class: ProcessInf
- { class: ZScoreNorm, kwargs: { fit_start_time: "2016-01-04", fit_end_time: "2025-09-01" } } kwargs: {}
- { class: Fillna, kwargs: {} } - class: CSRankNorm
kwargs: {}
- class: ZScoreNorm
kwargs: {}
- class: Fillna
kwargs: {}
segments: segments:
train: [2016-01-04, 2025-09-01] train: [2015-01-03, 2025-09-01]
valid: [2025-09-03, 2026-01-03] valid: [2025-09-03, 2026-01-03]
test: [2026-01-04, 2026-08-10] test: [2026-01-04, 2026-08-10]
record: record:
- { class: SignalRecord, module_path: qlib.workflow.record_temp, kwargs: {} } - class: SignalRecord
- { class: SigAnaRecord, module_path: qlib.workflow.record_temp, kwargs: { ana_long_short: true, ann_scaler: 252 } } module_path: qlib.workflow.record_temp
kwargs: {}
- class: SigAnaRecord
module_path: qlib.workflow.record_temp
kwargs:
ana_long_short: true
ann_scaler: 252
- class: PortAnaRecord - class: PortAnaRecord
module_path: qlib.workflow.record_temp module_path: qlib.workflow.record_temp
kwargs: kwargs:
@@ -89,7 +112,12 @@ task:
strategy: strategy:
class: TopkDropoutStrategy class: TopkDropoutStrategy
module_path: qlib.contrib.strategy module_path: qlib.contrib.strategy
kwargs: { signal: "<PRED>", topk: 10, n_drop: 1, only_tradable: true, risk_degree: 0.95 } kwargs:
signal: "<PRED>"
topk: 10
n_drop: 2
only_tradable: true
risk_degree: 0.95
backtest: backtest:
start_time: 2026-01-04 start_time: 2026-01-04
end_time: 2026-08-10 end_time: 2026-08-10
@@ -102,4 +130,4 @@ task:
open_cost: 0.0005 open_cost: 0.0005
close_cost: 0.0015 close_cost: 0.0015
min_cost: 5.0 min_cost: 5.0
risk_analysis_freq: 1d risk_analysis_freq: 1d
@@ -1,38 +1,52 @@
# QUEUE-15 — 5-seed vs single-model clean A/B on the compact stochastic set. # -----------------------------------------------------------------------------
# CLAIMS.md HYPOTHESIS: "5-seed RankIC ensemble raises performance vs single model # ABLATION B (generic-only): same panel/model as the baseline, but feature
# on ablated set" — pre-clean-lake exp 12 idea, re-validated directionally by exp # fields restricted to the model-free / generic stochastic-process families
# 22–24, never a clean A/B post-reset. Seed count is load-bearing (exp 28: 2<5). # (jump,har,trend,hurst,signature). Drops the model-specific ou (OU/AR-1
# Change vs exp-26 reference: seeds "42,7,2026,99,123" -> single seed "2026". # half-life) and hmm (2-state regime) families to test whether the generic
# Acceptance: single-model RankIC < 0.0663, net_IR < 0.21 (ensemble beats single). # families alone dominate the rank dimension.
# Run: rd_run_workflow config_path=<repo>/experiments/queue/workflows/q15_single_seed.yaml \ #
# experiment_name=tac-rd-q15-single-seed # Run:
# rd_run_workflow config_path=tac-qlib/workflows/ablate_generic_only_sp_fields.yaml \
# experiment_name=tac-rd-rank-ablate
# -----------------------------------------------------------------------------
{%- set LAKE = TAC_LAKE_DIR %} {%- set LAKE = TAC_LAKE_DIR %}
{%- set UNIVERSE = "SPY,QQQ,DIA,IWM,MDY,VTI,VOO,VEA,VWO,VT,EFA,EEM,TLT,IEF,SHY,AGG,BND,LQD,HYG,JNK,EMB,GLD,SLV,USO,UNG,DBA,DBC,XLK,XLF,XLE,XLV,XLI,XLY,XLP,XLU,XLB,XLRE,ARKK,SMH,SOXX,IBB,XBI,ITA,XAR,ICLN,TAN,FDN,IGV,ESPO,REM" %} {%- set UNIVERSE = "SPY,QQQ,DIA,IWM,MDY,VTI,VOO,VEA,VWO,VT,EFA,EEM,TLT,IEF,SHY,AGG,BND,LQD,HYG,JNK,EMB,GLD,SLV,USO,UNG,DBA,DBC,XLK,XLF,XLE,XLV,XLI,XLY,XLP,XLU,XLB,XLRE,ARKK,SMH,SOXX,IBB,XBI,ITA,XAR,ICLN,TAN,FDN,IGV,ESPO,REM" %}
{%- set FEATURES = "$open,$high,$low,$close,$vwap,$volume,sp_ret,sp_jump_ratio,sp_jump_flag,sp_jump_tail,sp_max_move,sp_rv1,sp_rv5,sp_rv22,sp_vol_ratio_5_22,sp_vol_ratio_1_22,sp_trend_slope_5,sp_trend_slope_20,sp_trend_slope_60,sp_logp,sp_hurst_exponent,sp_sig_level1_lead,sp_sig_level1_lag,sp_sig_level2_lead_lag,sp_sig_level2_lag_lead" %} {%- set SP_FIELDS = "sp_ret,sp_jump_ratio,sp_jump_flag,sp_jump_tail,sp_max_move,sp_rv1,sp_rv5,sp_rv22,sp_vol_ratio_5_22,sp_vol_ratio_1_22,sp_trend_slope_5,sp_trend_slope_20,sp_trend_slope_60,sp_logp,sp_hurst_exponent,sp_sig_level1_lead,sp_sig_level1_lag,sp_sig_level2_lead_lag,sp_sig_level2_lag_lead" %}
qlib_init: qlib_init:
provider_uri: "{{ LAKE }}" provider_uri: "{{ LAKE }}"
region: us region: us
expression_cache: null expression_cache: null
dataset_cache: null dataset_cache: null
calendar_provider: calendar_provider:
class: tac_qlib.data.providers.LakeCalendarProvider class: tac_qlib.data.providers.LakeCalendarProvider
kwargs: { lake_root: "{{ LAKE }}", market: US } kwargs:
lake_root: "{{ LAKE }}"
market: US
instrument_provider: instrument_provider:
class: tac_qlib.data.providers.LakeInstrumentProvider class: tac_qlib.data.providers.LakeInstrumentProvider
kwargs: { lake_root: "{{ LAKE }}", market: US, markets: {} } kwargs:
lake_root: "{{ LAKE }}"
market: US
markets: {}
feature_provider: feature_provider:
class: tac_qlib.data.providers.LakeFeatureProvider class: tac_qlib.data.providers.LakeFeatureProvider
kwargs: { lake_root: "{{ LAKE }}", market: US } kwargs:
lake_root: "{{ LAKE }}"
market: US
exp_manager: exp_manager:
class: MLflowExpManager class: MLflowExpManager
module_path: qlib.workflow.expm module_path: qlib.workflow.expm
kwargs: { uri: "sqlite:///mlruns.db", default_exp_name: "tac-rd-q15-single-seed" } kwargs:
uri: "sqlite:///{{ LAKE }}/mlruns.db"
default_exp_name: "tac-rd-rank-ablate"
task: task:
model: model:
class: RankICEnsembleLGBModel class: RankICLGBModel
module_path: tac_qlib.contrib.model.rank_ensemble module_path: tac_qlib.contrib.model.rank_gbdt
kwargs: kwargs:
loss: mse loss: mse
learning_rate: 0.02 learning_rate: 0.02
@@ -47,7 +61,7 @@ task:
subsample_freq: 1 subsample_freq: 1
reg_alpha: 0.1 reg_alpha: 0.1
reg_lambda: 1.0 reg_lambda: 1.0
seeds: "2026" seed: 42
dataset: dataset:
class: DatasetH class: DatasetH
@@ -60,27 +74,38 @@ task:
instruments: "{{ UNIVERSE }}" instruments: "{{ UNIVERSE }}"
start_time: 2015-01-03 start_time: 2015-01-03
end_time: 2026-08-10 end_time: 2026-08-10
fit_start_time: 2016-01-04 fit_start_time: 2015-01-03
fit_end_time: 2025-09-01 fit_end_time: 2025-09-01
freq: day freq: day
lake_root: "{{ LAKE }}" lake_root: "{{ LAKE }}"
market: US market: US
label: "Ref($close,-6)/Ref($close,-1)-1" label: "Ref($close,-6)/Ref($close,-1)-1"
feature_fields: "{{ FEATURES }}" feature_fields: "$open,$high,$low,$close,$vwap,$volume,{{ SP_FIELDS }}"
infer_processors: infer_processors:
- { class: DropAllNaN, kwargs: { fit_start_time: "2016-01-04", fit_end_time: "2025-09-01" } } - class: DropAllNaN
- { class: ProcessInf, kwargs: {} } kwargs: {}
- { class: CSRankNorm, kwargs: {} } - class: ProcessInf
- { class: ZScoreNorm, kwargs: { fit_start_time: "2016-01-04", fit_end_time: "2025-09-01" } } kwargs: {}
- { class: Fillna, kwargs: {} } - class: CSRankNorm
kwargs: {}
- class: ZScoreNorm
kwargs: {}
- class: Fillna
kwargs: {}
segments: segments:
train: [2016-01-04, 2025-09-01] train: [2015-01-03, 2025-09-01]
valid: [2025-09-03, 2026-01-03] valid: [2025-09-03, 2026-01-03]
test: [2026-01-04, 2026-08-10] test: [2026-01-04, 2026-08-10]
record: record:
- { class: SignalRecord, module_path: qlib.workflow.record_temp, kwargs: {} } - class: SignalRecord
- { class: SigAnaRecord, module_path: qlib.workflow.record_temp, kwargs: { ana_long_short: true, ann_scaler: 252 } } module_path: qlib.workflow.record_temp
kwargs: {}
- class: SigAnaRecord
module_path: qlib.workflow.record_temp
kwargs:
ana_long_short: true
ann_scaler: 252
- class: PortAnaRecord - class: PortAnaRecord
module_path: qlib.workflow.record_temp module_path: qlib.workflow.record_temp
kwargs: kwargs:
@@ -88,7 +113,12 @@ task:
strategy: strategy:
class: TopkDropoutStrategy class: TopkDropoutStrategy
module_path: qlib.contrib.strategy module_path: qlib.contrib.strategy
kwargs: { signal: "<PRED>", topk: 10, n_drop: 1, only_tradable: true, risk_degree: 0.95 } kwargs:
signal: "<PRED>"
topk: 10
n_drop: 2
only_tradable: true
risk_degree: 0.95
backtest: backtest:
start_time: 2026-01-04 start_time: 2026-01-04
end_time: 2026-08-10 end_time: 2026-08-10
@@ -101,4 +131,4 @@ task:
open_cost: 0.0005 open_cost: 0.0005
close_cost: 0.0015 close_cost: 0.0015
min_cost: 5.0 min_cost: 5.0
risk_analysis_freq: 1d risk_analysis_freq: 1d
+141
View File
@@ -0,0 +1,141 @@
# -----------------------------------------------------------------------------
# ISOLATION: multi-seed RankIC ensemble, ablate-B generic-only feature set.
#
# Isolates the ensemble effect on the SP-5d rank signal. Same panel, segments,
# history (full backfilled 2016+) and feature set as the exp-9 ablate-B winner
# (generic-only sp_* families: jump,har,trend,hurst,signature), but replaces the
# single RankICLGBModel with a 5-seed RankICEnsembleLGBModel (42,7,2026,99,123)
# that averages per-day predictions.
#
# Differs from exp-15 (tac-rd-rank-ensemble, mlflow exp 15) ONLY by dropping the
# TA subset (rsi_14,roc_10,macd_hist,willr_14,atr_14) and the inter-asset xr_*
# features, so any change vs exp-15 is attributable to the feature set alone,
# and any change vs exp-9 is attributable to the ensemble + full history alone.
#
# Run:
# rd_run_workflow config_path=experiments/workflows/exp12_isolation_ensemble.yaml \
# experiment_name=tac-rd-rank-ensemble-isolated
# -----------------------------------------------------------------------------
{%- set LAKE = TAC_LAKE_DIR %}
{%- set UNIVERSE = "SPY,QQQ,DIA,IWM,MDY,VTI,VOO,VEA,VWO,VT,EFA,EEM,TLT,IEF,SHY,AGG,BND,LQD,HYG,JNK,EMB,GLD,SLV,USO,UNG,DBA,DBC,XLK,XLF,XLE,XLV,XLI,XLY,XLP,XLU,XLB,XLRE,ARKK,SMH,SOXX,IBB,XBI,ITA,XAR,ICLN,TAN,FDN,IGV,ESPO,REM" %}
{%- set SP_FIELDS = "sp_ret,sp_jump_ratio,sp_jump_flag,sp_jump_tail,sp_max_move,sp_rv1,sp_rv5,sp_rv22,sp_vol_ratio_5_22,sp_vol_ratio_1_22,sp_trend_slope_5,sp_trend_slope_20,sp_trend_slope_60,sp_logp,sp_hurst_exponent,sp_sig_level1_lead,sp_sig_level1_lag,sp_sig_level2_lead_lag,sp_sig_level2_lag_lead" %}
qlib_init:
provider_uri: "{{ LAKE }}"
region: us
expression_cache: null
dataset_cache: null
calendar_provider:
class: tac_qlib.data.providers.LakeCalendarProvider
kwargs:
lake_root: "{{ LAKE }}"
market: US
instrument_provider:
class: tac_qlib.data.providers.LakeInstrumentProvider
kwargs:
lake_root: "{{ LAKE }}"
market: US
markets: {}
feature_provider:
class: tac_qlib.data.providers.LakeFeatureProvider
kwargs:
lake_root: "{{ LAKE }}"
market: US
exp_manager:
class: MLflowExpManager
module_path: qlib.workflow.expm
kwargs:
uri: "sqlite:///mlruns.db"
default_exp_name: "tac-rd-rank-ensemble-isolated"
task:
model:
class: RankICEnsembleLGBModel
module_path: tac_qlib.contrib.model.rank_ensemble
kwargs:
loss: mse
learning_rate: 0.02
num_leaves: 31
n_estimators: 3000
num_boost_round: 3000
early_stopping_rounds: 200
min_data_in_leaf: 20
lambda_l2: 0.5
colsample_bytree: 0.8
subsample: 0.8
subsample_freq: 1
reg_alpha: 0.1
reg_lambda: 1.0
seeds: "42,7,2026,99,123"
dataset:
class: DatasetH
module_path: qlib.data.dataset
kwargs:
handler:
class: TACHandler
module_path: tac_qlib.contrib.data.handler
kwargs:
instruments: "{{ UNIVERSE }}"
start_time: 2015-01-03
end_time: 2026-08-14
fit_start_time: 2016-01-04
fit_end_time: 2025-09-01
freq: day
lake_root: "{{ LAKE }}"
market: US
label: "Ref($close,-6)/Ref($close,-1)-1"
feature_fields: "$open,$high,$low,$close,$vwap,$volume,{{ SP_FIELDS }}"
infer_processors:
- class: DropAllNaN
kwargs: {}
- class: ProcessInf
kwargs: {}
- class: CSRankNorm
kwargs: {}
- class: ZScoreNorm
kwargs: {}
- class: Fillna
kwargs: {}
segments:
train: [2016-01-04, 2025-09-01]
valid: [2025-09-03, 2026-01-03]
test: [2026-01-04, 2026-08-10]
record:
- class: SignalRecord
module_path: qlib.workflow.record_temp
kwargs: {}
- class: SigAnaRecord
module_path: qlib.workflow.record_temp
kwargs:
ana_long_short: true
ann_scaler: 252
- class: PortAnaRecord
module_path: qlib.workflow.record_temp
kwargs:
config:
strategy:
class: TopkDropoutStrategy
module_path: qlib.contrib.strategy
kwargs:
signal: "<PRED>"
topk: 10
n_drop: 2
only_tradable: true
risk_degree: 0.95
backtest:
start_time: 2026-01-04
end_time: 2026-08-10
account: 1000000
benchmark: SPY
exchange_kwargs:
codes: "{{ UNIVERSE }}"
deal_price: $close
freq: day
open_cost: 0.0005
close_cost: 0.0015
min_cost: 5.0
risk_analysis_freq: 1d
@@ -1,34 +1,53 @@
# QUEUE-17 — Realized-moments family added to the compact set. # -----------------------------------------------------------------------------
# CLAIMS.md HYPOTHESIS: "Adding moment/volatility families regresses the signal" # EXP 18 - Risk-limit control: reference model + TopkDropout baseline (A).
# (idea: pre-clean-lake exp 11). M1 momentum bundle (exp 29) and M3 GARCH (exp 31) #
# were refuted post-reset; the realized-moments family (sp_rskew/sp_rkurt/sp_dsv) # Signal/model identical to the reference (tac-rd-rank-ensemble-isolated,
# has NOT been clean A/B'd. This run adds the moments columns to the compact set. # run 0cea66d9...): RankICEnsembleLGBModel (parallel, 5 seeds) on the 50-ETF
# Change vs exp-26 reference: features += sp_rskew_5,sp_rskew_22,sp_rkurt_5,sp_rkurt_22,sp_dsv_5,sp_dsv_22. # SP-5d panel, test 2026-01-04..2026-08-10. This workflow reproduces the
# Acceptance (prune-hypothesis): no improvement — RankIC <= 0.0663, net_IR <= 0.21. # unconstrained TopkDropout baseline net-of-cost so the risk-limited variant
# Run: rd_run_workflow config_path=<repo>/experiments/queue/workflows/q17_moments_features.yaml \ # (same pred, liquidity/size/concentration caps) can be compared 1:1.
# experiment_name=tac-rd-q17-moments-features #
# The risk_limits spec itself is applied via rd_backtest / rd_strategy_targets
# (tool-level param, not a YAML key); this run records the unconstrained
# baseline that the limit A/B is measured against.
#
# Run:
# rd_run_workflow config_path=experiments/workflows/exp18-risk-limit/a_baseline.yaml \
# experiment_name=tac-rd-risk-limit
# -----------------------------------------------------------------------------
{%- set LAKE = TAC_LAKE_DIR %} {%- set LAKE = TAC_LAKE_DIR %}
{%- set UNIVERSE = "SPY,QQQ,DIA,IWM,MDY,VTI,VOO,VEA,VWO,VT,EFA,EEM,TLT,IEF,SHY,AGG,BND,LQD,HYG,JNK,EMB,GLD,SLV,USO,UNG,DBA,DBC,XLK,XLF,XLE,XLV,XLI,XLY,XLP,XLU,XLB,XLRE,ARKK,SMH,SOXX,IBB,XBI,ITA,XAR,ICLN,TAN,FDN,IGV,ESPO,REM" %} {%- set UNIVERSE = "SPY,QQQ,DIA,IWM,MDY,VTI,VOO,VEA,VWO,VT,EFA,EEM,TLT,IEF,SHY,AGG,BND,LQD,HYG,JNK,EMB,GLD,SLV,USO,UNG,DBA,DBC,XLK,XLF,XLE,XLV,XLI,XLY,XLP,XLU,XLB,XLRE,ARKK,SMH,SOXX,IBB,XBI,ITA,XAR,ICLN,TAN,FDN,IGV,ESPO,REM" %}
{%- set FEATURES = "$open,$high,$low,$close,$vwap,$volume,sp_ret,sp_jump_ratio,sp_jump_flag,sp_jump_tail,sp_max_move,sp_rv1,sp_rv5,sp_rv22,sp_vol_ratio_5_22,sp_vol_ratio_1_22,sp_trend_slope_5,sp_trend_slope_20,sp_trend_slope_60,sp_logp,sp_hurst_exponent,sp_sig_level1_lead,sp_sig_level1_lag,sp_sig_level2_lead_lag,sp_sig_level2_lag_lead,sp_rskew_5,sp_rskew_22,sp_rkurt_5,sp_rkurt_22,sp_dsv_5,sp_dsv_22" %} {%- set SP_FIELDS = "sp_ret,sp_jump_ratio,sp_jump_flag,sp_jump_tail,sp_max_move,sp_rv1,sp_rv5,sp_rv22,sp_vol_ratio_5_22,sp_vol_ratio_1_22,sp_trend_slope_5,sp_trend_slope_20,sp_trend_slope_60,sp_logp,sp_hurst_exponent,sp_sig_level1_lead,sp_sig_level1_lag,sp_sig_level2_lead_lag,sp_sig_level2_lag_lead" %}
qlib_init: qlib_init:
provider_uri: "{{ LAKE }}" provider_uri: "{{ LAKE }}"
region: us region: us
expression_cache: null expression_cache: null
dataset_cache: null dataset_cache: null
calendar_provider: calendar_provider:
class: tac_qlib.data.providers.LakeCalendarProvider class: tac_qlib.data.providers.LakeCalendarProvider
kwargs: { lake_root: "{{ LAKE }}", market: US } kwargs:
lake_root: "{{ LAKE }}"
market: US
instrument_provider: instrument_provider:
class: tac_qlib.data.providers.LakeInstrumentProvider class: tac_qlib.data.providers.LakeInstrumentProvider
kwargs: { lake_root: "{{ LAKE }}", market: US, markets: {} } kwargs:
lake_root: "{{ LAKE }}"
market: US
markets: {}
feature_provider: feature_provider:
class: tac_qlib.data.providers.LakeFeatureProvider class: tac_qlib.data.providers.LakeFeatureProvider
kwargs: { lake_root: "{{ LAKE }}", market: US } kwargs:
lake_root: "{{ LAKE }}"
market: US
exp_manager: exp_manager:
class: MLflowExpManager class: MLflowExpManager
module_path: qlib.workflow.expm module_path: qlib.workflow.expm
kwargs: { uri: "sqlite:///mlruns.db", default_exp_name: "tac-rd-q17-moments-features" } kwargs:
uri: "sqlite:///{{ LAKE }}/mlruns.db"
default_exp_name: "tac-rd-risk-limit"
task: task:
model: model:
@@ -49,6 +68,7 @@ task:
reg_alpha: 0.1 reg_alpha: 0.1
reg_lambda: 1.0 reg_lambda: 1.0
seeds: "42,7,2026,99,123" seeds: "42,7,2026,99,123"
parallel: 5
dataset: dataset:
class: DatasetH class: DatasetH
@@ -60,28 +80,39 @@ task:
kwargs: kwargs:
instruments: "{{ UNIVERSE }}" instruments: "{{ UNIVERSE }}"
start_time: 2015-01-03 start_time: 2015-01-03
end_time: 2026-08-10 end_time: 2026-08-14
fit_start_time: 2016-01-04 fit_start_time: 2016-01-04
fit_end_time: 2025-09-01 fit_end_time: 2025-09-01
freq: day freq: day
lake_root: "{{ LAKE }}" lake_root: "{{ LAKE }}"
market: US market: US
label: "Ref($close,-6)/Ref($close,-1)-1" label: "Ref($close,-6)/Ref($close,-1)-1"
feature_fields: "{{ FEATURES }}" feature_fields: "$open,$high,$low,$close,$vwap,$volume,{{ SP_FIELDS }}"
infer_processors: infer_processors:
- { class: DropAllNaN, kwargs: { fit_start_time: "2016-01-04", fit_end_time: "2025-09-01" } } - class: DropAllNaN
- { class: ProcessInf, kwargs: {} } kwargs: {}
- { class: CSRankNorm, kwargs: {} } - class: ProcessInf
- { class: ZScoreNorm, kwargs: { fit_start_time: "2016-01-04", fit_end_time: "2025-09-01" } } kwargs: {}
- { class: Fillna, kwargs: {} } - class: CSRankNorm
kwargs: {}
- class: ZScoreNorm
kwargs: {}
- class: Fillna
kwargs: {}
segments: segments:
train: [2016-01-04, 2025-09-01] train: [2016-01-04, 2025-09-01]
valid: [2025-09-03, 2026-01-03] valid: [2025-09-03, 2026-01-03]
test: [2026-01-04, 2026-08-10] test: [2026-01-04, 2026-08-10]
record: record:
- { class: SignalRecord, module_path: qlib.workflow.record_temp, kwargs: {} } - class: SignalRecord
- { class: SigAnaRecord, module_path: qlib.workflow.record_temp, kwargs: { ana_long_short: true, ann_scaler: 252 } } module_path: qlib.workflow.record_temp
kwargs: {}
- class: SigAnaRecord
module_path: qlib.workflow.record_temp
kwargs:
ana_long_short: true
ann_scaler: 252
- class: PortAnaRecord - class: PortAnaRecord
module_path: qlib.workflow.record_temp module_path: qlib.workflow.record_temp
kwargs: kwargs:
@@ -89,7 +120,12 @@ task:
strategy: strategy:
class: TopkDropoutStrategy class: TopkDropoutStrategy
module_path: qlib.contrib.strategy module_path: qlib.contrib.strategy
kwargs: { signal: "<PRED>", topk: 10, n_drop: 1, only_tradable: true, risk_degree: 0.95 } kwargs:
signal: "<PRED>"
topk: 10
n_drop: 2
only_tradable: true
risk_degree: 0.95
backtest: backtest:
start_time: 2026-01-04 start_time: 2026-01-04
end_time: 2026-08-10 end_time: 2026-08-10
@@ -102,4 +138,4 @@ task:
open_cost: 0.0005 open_cost: 0.0005
close_cost: 0.0015 close_cost: 0.0015
min_cost: 5.0 min_cost: 5.0
risk_analysis_freq: 1d risk_analysis_freq: 1d