Skip to content

Commit 012b175

Browse files
authored
Merge pull request #6 from HanSun103/agent/live-forward-readme
Integrate frozen-cohort dashboard monitoring
2 parents 892203f + e9146b0 commit 012b175

18 files changed

Lines changed: 791 additions & 75 deletions

.github/workflows/deploy-dashboard.yml

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ on:
88
- "site/**"
99
- "src/experiments/public_dashboard_validation.py"
1010
- ".github/workflows/deploy-dashboard.yml"
11+
pull_request:
12+
branches:
13+
- main
14+
paths:
15+
- "site/**"
16+
- "src/experiments/public_dashboard_validation.py"
17+
- ".github/workflows/deploy-dashboard.yml"
1118
workflow_dispatch:
1219

1320
permissions:
@@ -23,27 +30,28 @@ jobs:
2330
runs-on: ubuntu-latest
2431
steps:
2532
- name: Check out repository
26-
uses: actions/checkout@v4
33+
uses: actions/checkout@v7
2734

2835
- name: Set up Python
29-
uses: actions/setup-python@v5
36+
uses: actions/setup-python@v7
3037
with:
3138
python-version: "3.12"
3239

3340
- name: Validate sanitized public bundle
3441
run: python -m src.experiments.public_dashboard_validation --site-dir site
3542

3643
- name: Configure GitHub Pages
37-
uses: actions/configure-pages@v5
44+
uses: actions/configure-pages@v6
3845

3946
- name: Upload dashboard artifact
40-
uses: actions/upload-pages-artifact@v4
47+
uses: actions/upload-pages-artifact@v5
4148
with:
4249
path: site
4350

4451
deploy:
4552
name: Deploy dashboard
4653
needs: validate
54+
if: github.ref == 'refs/heads/main'
4755
runs-on: ubuntu-latest
4856
permissions:
4957
pages: write
@@ -54,4 +62,4 @@ jobs:
5462
steps:
5563
- name: Deploy to GitHub Pages
5664
id: deployment
57-
uses: actions/deploy-pages@v4
65+
uses: actions/deploy-pages@v5

README.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
![Python 3.11+](https://img.shields.io/badge/Python-3.11%2B-2563eb)
77
![Research status](https://img.shields.io/badge/status-paper--live_research-d97706)
8-
![Tests](https://img.shields.io/badge/tests-215_passing-0f766e)
8+
![Tests](https://img.shields.io/badge/tests-218_passing-0f766e)
99
![License](https://img.shields.io/badge/license-MIT-64748b)
1010

1111
The project asks a narrow investment question:
@@ -209,6 +209,31 @@ before forward use. The six observed sessions will not choose the threshold.
209209

210210
[Review the rebalance-buffer experiment draft →](docs/design/REBALANCE_BUFFER_EXPERIMENT.md)
211211

212+
### Frozen-cohort dashboard
213+
214+
The legacy one-session experiment is now a frozen-cohort monitoring track rather
215+
than a source of new daily portfolios. Its daily command refreshes prices,
216+
extends the existing July 20–27 Ridge/XGBoost cohorts, rebuilds the local
217+
dashboard, and regenerates the sanitized GitHub Pages bundle:
218+
219+
```bash
220+
python -m src.cli run-live-forward-daily --as-of YYYY-MM-DD
221+
```
222+
223+
The **Holding-period laboratory** can keep any dated list unchanged or compare
224+
custom 1–60-session replacement horizons, including 5/10/20-session presets.
225+
Ridge and XGBoost can be toggled independently while SPY remains permanently
226+
visible from the shared decision-close baseline. It reports net return,
227+
SPY-relative return, replacement-only turnover, and rebalance counts under
228+
identical execution assumptions.
229+
230+
[Open the deployed live-forward dashboard →](https://hansun103.github.io/AI-Driven-Portfolio-Optimization-Backtesting-System/)
231+
232+
This monitoring track does not replace the primary horizon-matched 5/10/20
233+
experiment described above. The former one-session fitting workflow remains
234+
available only through the explicit `--retrain` flag and is not part of the
235+
normal monitoring run.
236+
212237
## Architecture
213238

214239
The historical system contained many experimental sleeves. Its full architecture

docs/GITHUB_PAGES_DEPLOYMENT.md

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ Yahoo Finance and cached inputs
99
|
1010
v
1111
Daily live-forward pipeline
12-
- evaluate prior frozen portfolios
13-
- tune and refit Ridge and XGBoost
14-
- freeze tomorrow's top-40 lists
15-
- calculate stability diagnostics
12+
- refresh official closes for archived cohorts
13+
- extend frozen Ridge and XGBoost portfolios
14+
- replay 1-60-session replacement policies
15+
- calculate returns, costs, and turnover
1616
|
1717
+--> reports/live_forward/ private, ignored research evidence
1818
|
@@ -25,10 +25,13 @@ Daily live-forward pipeline
2525
GitHub Actions / Pages
2626
```
2727

28-
`reports/live_forward/` remains the full local evidence store. The publisher uses explicit field
29-
allowlists to create `site/data/dashboard.json`; it does not copy local paths, cached input names,
30-
raw feature rows, model files, credentials, or candidate-trial details. The public bundle is then
31-
validated for required files, duplicate holdings, forbidden private strings, and a SHA-256 digest.
28+
`reports/live_forward/` remains the full local evidence store. The publisher uses
29+
separate explicit field allowlists for model snapshots and frozen-cohort policy
30+
paths when it creates `site/data/dashboard.json`; it does not copy local paths,
31+
cached input names, raw price/feature rows, model files, credentials, or
32+
candidate-trial details. The public bundle is then validated for required files,
33+
snapshot and cohort schemas, duplicate identifiers or holdings, forbidden
34+
private strings, and a SHA-256 digest.
3235

3336
## Daily publication
3437

@@ -38,6 +41,16 @@ The standard daily command now refreshes both the local dashboard and the public
3841
python -m src.cli run-live-forward-daily --as-of YYYY-MM-DD
3942
```
4043

44+
This command is monitoring-only by default and reports
45+
`"new_model_lists": 0`. It rebuilds:
46+
47+
- `reports/live_forward/cohort_monitor.json`;
48+
- `reports/live_forward/dashboard.html`; and
49+
- the tracked `site/` deployment bundle.
50+
51+
The historical one-session retraining path requires the explicit `--retrain`
52+
flag. It should not be used during the frozen-cohort policy experiment.
53+
4154
To rebuild the public bundle without retraining:
4255

4356
```bash
@@ -52,9 +65,11 @@ Validate exactly what will be published:
5265
python -m src.cli validate-live-dashboard-site --site-dir site
5366
```
5467

55-
Commit `site/` after reviewing the generated changes. A push to `main` that changes the public
56-
bundle starts `.github/workflows/deploy-dashboard.yml`. The workflow validates the bundle again,
57-
uploads it as a Pages artifact, and deploys it to the `github-pages` environment.
68+
Commit `site/` after reviewing the generated changes. A pull request that
69+
changes the public bundle runs the validation and packaging job without
70+
deploying. After merge, the resulting push to `main` runs the same validation,
71+
uploads the Pages artifact, and deploys it to the `github-pages` environment.
72+
The deploy job is explicitly restricted to `refs/heads/main`.
5873

5974
## One-time repository setting
6075

docs/LIVE_FORWARD_MONITOR.md

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,53 +14,57 @@ yet a production trading recommendation. Ridge is the stable linear benchmark an
1414
ranker is the nonlinear challenger. Both select 40 equal-weight names and share SPY as the market
1515
benchmark.
1616

17-
## Daily after-close workflow
17+
## Daily after-close workflow: monitoring phase
1818

19-
Run the production-style workflow after Yahoo Finance publishes the final regular-session bar:
19+
This dashboard track preserves the legacy one-session selections for the
20+
rebalancing-policy study; it is separate from the primary horizon-matched
21+
5/10/20-session live-forward experiment. The July 20–27 Ridge and XGBoost
22+
selections are frozen as permanent cohorts. After Yahoo Finance publishes the
23+
official daily close, run:
2024

2125
```bash
2226
python -m src.cli run-live-forward-daily --as-of YYYY-MM-DD
2327
```
2428

25-
The command performs these steps in order:
26-
27-
1. Waits for the final 15:30 hourly bar and verifies the official daily close is available.
28-
2. Evaluates portfolios frozen before the current session, including one holding-level return
29-
record per selected stock.
30-
3. Immediately rebuilds the local dashboard and sanitized `site/` bundle before model tuning starts.
31-
4. Incrementally refreshes daily market data, split events, and trailing sector-ETF classifications
32-
through the decision date.
33-
5. Expands sector observations backward-as-of so each historical feature and label uses only the
34-
classification available on that date.
35-
6. Builds forward-return training labels only where the future outcome was already known before the
36-
decision date.
37-
7. Tunes Ridge and XGBoost independently on temporal validation data, refits the selected
38-
configurations, and freezes both top-40 lists for the next evaluation session.
39-
8. Freezes a separate shadow portfolio by blending the two full-universe percentile rankings
40-
with the historically selected 25% Ridge / 75% XGBoost weight and applying the same top-40
41-
sector cap.
42-
9. Writes model-agreement, day-over-day selection-stability diagnostics, and candidate split
43-
features that are not yet eligible for model fitting.
44-
10. Rebuilds both dashboard outputs again so they include the newly frozen pending portfolios.
45-
46-
If final market data is unavailable, the command retries and then fails closed. It must not create a
47-
snapshot from a partial trading day.
48-
49-
## Tuning profiles
50-
51-
Use a full focused retune after changing a feature definition, repairing historical inputs, or as
52-
a periodic model audit:
29+
Monitoring-only is the default. The command:
30+
31+
1. requests adjusted daily prices only for SPY and securities present in the archived cohorts;
32+
2. verifies the requested official close exists and fails closed if Yahoo still has partial data;
33+
3. extends every unchanged July 20–27 portfolio through the new close;
34+
4. replays archived rebalance policies for every interval from 1 through 60 sessions;
35+
5. recalculates net return, SPY-relative return, cumulative turnover, and trades; and
36+
6. rebuilds the local dashboard and sanitized GitHub Pages bundle.
37+
38+
It does **not** fit a model or create a new stock list. The output explicitly reports
39+
`"new_model_lists": 0`.
40+
41+
The dashboard's **Holding-period laboratory** supports selecting any July 20–27 list, displaying
42+
Ridge and XGBoost together with clickable model chips, or replaying a 1–60-session rebalance
43+
interval. Five-, 10-, and 20-session presets are provided, and the horizon comparison table reports
44+
every 1–20-session candidate side by side. SPY is permanent and begins from the same zero-return
45+
decision-close baseline as each portfolio.
46+
47+
The displayed **replacement turnover** excludes the unavoidable initial purchase. An unchanged
48+
cohort therefore correctly shows 0% replacement turnover. Scheduled policies use the same
49+
$1 million capital, 8 bps one-way cost, $10 fixed trade fee, and 0.25% minimum trade-weight rule.
50+
51+
## Explicit archived retraining workflow
52+
53+
The old production-style retraining path remains available for reproducibility, but now requires
54+
the explicit `--retrain` flag:
5355

5456
```bash
5557
python -m src.cli run-live-forward-daily \
5658
--as-of YYYY-MM-DD \
59+
--retrain \
5760
--tuning-folds 5 \
5861
--ridge-optuna-trials 60 \
5962
--xgb-optuna-trials 50 \
6063
--optuna-timeout-seconds 7200
6164
```
6265

63-
The focused parameter ranges come from earlier completed live runs. The current decision date and
66+
Do not use this flag during the frozen-cohort monitoring phase. The focused parameter ranges come
67+
from earlier completed live runs. The current decision date and
6468
its future return remain excluded, so narrowing the search does not introduce look-ahead leakage.
6569
Five purged temporal folds provide a more stable selection estimate, while the separate Ridge and
6670
XGBoost trial budgets reflect their very different fitting costs.

site/assets/dashboard.css

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)