Skip to content

Commit 7e1ba02

Browse files
committed
Unify live dashboard horizon monitoring
1 parent e9146b0 commit 7e1ba02

15 files changed

Lines changed: 944 additions & 108 deletions

README.md

Lines changed: 26 additions & 10 deletions
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-218_passing-0f766e)
8+
![Tests](https://img.shields.io/badge/tests-221_passing-0f766e)
99
![License](https://img.shields.io/badge/license-MIT-64748b)
1010

1111
The project asks a narrow investment question:
@@ -227,7 +227,14 @@ visible from the shared decision-close baseline. It reports net return,
227227
SPY-relative return, replacement-only turnover, and rebalance counts under
228228
identical execution assumptions.
229229

230-
[Open the deployed live-forward dashboard →](https://hansun103.github.io/AI-Driven-Portfolio-Optimization-Backtesting-System/)
230+
The deployed monitor now has two linked pages with one shared visual shell:
231+
232+
- [Live Forward Monitor — default view →](https://hansun103.github.io/AI-Driven-Portfolio-Optimization-Backtesting-System/)
233+
- [Horizon Comparison — 5/10/20-session research →](https://hansun103.github.io/AI-Driven-Portfolio-Optimization-Backtesting-System/horizons.html)
234+
235+
The original Stock-level view remains canonical rather than being duplicated
236+
on the horizon page. The two-page contract and evidence boundaries are recorded
237+
in the [dashboard merge design](docs/design/DASHBOARD_TWO_PAGE_MERGE.md).
231238

232239
This monitoring track does not replace the primary horizon-matched 5/10/20
233240
experiment described above. The former one-session fitting workflow remains
@@ -378,20 +385,29 @@ because they weaken the preferred narrative.
378385
## Known limitations
379386

380387
1. No redesigned 20-session paper-live forecast has matured yet.
381-
2. The strongest portfolio results remain development evidence, not a genuine
388+
2. The strongest repaired historical test covers roughly 2018–2023, not a
389+
full decade. It therefore spans too few independent market regimes for a
390+
durable claim. Extending point-in-time testing toward at least ten years is
391+
a research target, not a guarantee of adequacy: long-window backtests still
392+
require regime analysis, untouched confirmation, and correction for the
393+
number of strategies tried. See
394+
[CFA Institute’s backtesting guidance](https://www.cfainstitute.org/insights/professional-learning/refresher-readings/2026/backtesting-and-simulation)
395+
and the
396+
[deflated-Sharpe discussion of sample length and multiple testing](https://academic.oup.com/jrssig/article/18/6/22/7038278).
397+
3. The strongest portfolio results remain development evidence, not a genuine
382398
untouched confirmation.
383-
3. Public data does not fully solve delisted-security coverage or historical
399+
4. Public data does not fully solve delisted-security coverage or historical
384400
sector classification.
385-
4. The average ranking edge is small and varies materially by year and regime.
386-
5. Sentiment is promising, but coverage, timestamp quality, and causal
401+
5. The average ranking edge is small and varies materially by year and regime.
402+
6. Sentiment is promising, but coverage, timestamp quality, and causal
387403
attribution remain incomplete.
388-
6. The high-recall survival model has not passed its activation gates and
404+
7. The high-recall survival model has not passed its activation gates and
389405
remains a shadow watchlist.
390-
7. Same-close tactical execution is unvalidated without intraday quotes and
406+
8. Same-close tactical execution is unvalidated without intraday quotes and
391407
actual paper or broker fills.
392-
8. Scheduled full top-40 replacement remains under audit; the six-session
408+
9. Scheduled full top-40 replacement remains under audit; the six-session
393409
ablation is too short to activate a freeze or buffer.
394-
9. Static cost assumptions do not establish capacity, taxes, borrow
410+
10. Static cost assumptions do not establish capacity, taxes, borrow
395411
availability, market impact, or partial-fill behavior.
396412

397413
## Research disclaimer
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Two-page dashboard merge design
2+
3+
Status: local proposal awaiting approval. Do not merge or deploy yet.
4+
5+
## Decision
6+
7+
Publish one dashboard product with two real static pages:
8+
9+
| Page | Proposed URL | Responsibility |
10+
| --- | --- | --- |
11+
| Live Forward Monitor | `dashboard.html` | Daily operational evidence, benchmark comparison, stability, the canonical stock-level view, and experiment history |
12+
| Horizon Comparison | `horizons.html` | Horizon-matched 5/10/20-session progress, validation context, model specifications, SHAP explanations, and pipeline health |
13+
14+
Both headers use the same two-option page switcher. The selected page is visually
15+
active. Ordinary links are preferable to a hidden single-page application because
16+
browser back/forward works, each page can fail independently, and GitHub Pages can
17+
serve the files without a runtime.
18+
19+
## Shared stock-level view
20+
21+
The Horizon Comparison page does not implement another portfolio table.
22+
23+
The existing Stock-level view remains the canonical component. Its model selector
24+
will be extended to understand both:
25+
26+
- legacy daily live-forward snapshots; and
27+
- v2 Ridge/XGBoost arms for the 5-, 10-, and 20-session horizons.
28+
29+
An `Inspect stocks` action on a horizon model will link to a URL such as:
30+
31+
```text
32+
dashboard.html?decision=2026-07-29&family=xgb_ranker&horizon=20#stock-level
33+
```
34+
35+
The original page reads those parameters, selects the requested frozen portfolio,
36+
and scrolls to the shared Stock-level view. This avoids divergent filtering,
37+
sorting, return formatting, and holding-level evaluation logic.
38+
39+
## Partial and mature evidence
40+
41+
The horizon page reports three different evidence states without mixing them:
42+
43+
1. **Awaiting entry** — the portfolio is frozen but its next-open entry has not
44+
occurred.
45+
2. **Interim mark** — one or more open-to-open observations exist. The page shows
46+
session progress and the compounded partial return immediately.
47+
3. **Matured label** — the complete 5-, 10-, or 20-session evaluation is available
48+
and may enter the formal prospective comparison.
49+
50+
The page never displays validation return as live return. A zero-session portfolio
51+
is shown as `0 / horizon` and `Awaiting entry`, not as a zero realized return.
52+
53+
## Explainability
54+
55+
Every newly frozen v2 forecast writes `shap_summary.csv`.
56+
57+
- Ridge uses linear SHAP contributions around the current eligible cohort as the
58+
background.
59+
- XGBoost uses exact TreeSHAP contributions from the fitted booster.
60+
- The dashboard publishes mean absolute SHAP, signed mean SHAP, positive
61+
contribution share, method, and explanation-row count.
62+
63+
Each model card contains a collapsed `Show SHAP feature importance` control.
64+
Opening it displays a horizontal importance chart. Old immutable forecasts that
65+
predate this artifact state that SHAP was not captured; coefficients or XGBoost
66+
gain are not relabelled as SHAP.
67+
68+
## Daily refresh contract
69+
70+
The daily pipeline should:
71+
72+
1. refresh data and generate the current snapshots;
73+
2. evaluate all available interim open-to-open observations;
74+
3. evaluate newly matured forecasts;
75+
4. generate SHAP summaries for new horizon snapshots;
76+
5. rebuild `dashboard.html` and `horizons.html`;
77+
6. run public-payload and browser smoke checks; and
78+
7. publish both pages together through the existing GitHub Pages action.
79+
80+
Publishing must be atomic: a cycle should never expose one page with a newer data
81+
contract than the other.
82+
83+
## Approval boundary
84+
85+
The current local Horizon Comparison preview demonstrates the second page. After
86+
approval, the merge work will add the page switcher and v2 arm support to the
87+
original dashboard, generate the final `horizons.html`, update the refresh and
88+
deployment workflows, and then request approval before pushing.

site/assets/dashboard.css

Lines changed: 7 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

site/data/manifest.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
{
2-
"schema_version": 2,
3-
"generated_at_utc": "2026-07-29T16:55:17.967215+00:00",
2+
"schema_version": 3,
3+
"generated_at_utc": "2026-07-29T22:29:54.012984+00:00",
44
"latest_decision_date": "2026-07-28",
55
"snapshot_count": 17,
66
"evaluation_count": 14,
77
"dashboard_sha256": "9d15420d6e5370038763505be97432e381f7a0932cc1aeac953399c030b2185c",
88
"dashboard_bytes": 546502,
9+
"horizon_dashboard_sha256": "20d6bdaa4d619ecca77441801a4f2e63b93c665822979b278cb490999bd4695a",
10+
"horizon_dashboard_bytes": 66861,
11+
"horizon_forecast_arms": 6,
912
"source_policy": "sanitized_live_forward_outputs_only"
1013
}

0 commit comments

Comments
 (0)