Skip to content

Commit ed8bac6

Browse files
committed
Reset horizon dashboard to latest dataset
1 parent f56f028 commit ed8bac6

3 files changed

Lines changed: 6 additions & 4 deletions

File tree

site/horizons.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@
4646
const data=JSON.parse(document.getElementById('dashboard-data').textContent),decisionSelect=document.getElementById('decisionSelect'),familyFilter=document.getElementById('familyFilter'),horizonFilter=document.getElementById('horizonFilter'),STATE_KEY='live-forward-horizon-dashboard-v1';
4747
const COLORS={ridge:'#3156d3',xgb_ranker:'#0f9f8f',ridge_h5:'#7290eb',ridge_h10:'#4f70dc',ridge_h20:'#3156d3',xgb_ranker_h5:'#70c8bd',xgb_ranker_h10:'#3eb2a4',xgb_ranker_h20:'#0f9f8f',spy:'#d89614'},names={ridge:'Ridge',xgb_ranker:'XGBoost'},fmtPct=v=>v==null||!Number.isFinite(Number(v))?'n/a':(Number(v)*100).toFixed(2)+'%',fmtNum=(v,d=3)=>v==null||!Number.isFinite(Number(v))?'n/a':Number(v).toFixed(d),human=v=>String(v??'').replaceAll('_',' ').replace(/\b\w/g,c=>c.toUpperCase()),tone=v=>Number(v)>=0?'pos':'neg',armColor=a=>COLORS[`${a.family}_h${a.horizon_sessions}`]||COLORS[a.family],armLabel=a=>`${names[a.family]||human(a.family)} · ${a.horizon_sessions} sessions`;
4848
let saved={};try{saved=JSON.parse(localStorage.getItem(STATE_KEY)||'{}')}catch{}let hiddenSeries=new Set(saved.hiddenSeries||[]);
49-
function save(){try{localStorage.setItem(STATE_KEY,JSON.stringify({decisionDate:decisionSelect.value,family:familyFilter.value,horizon:horizonFilter.value,hiddenSeries:[...hiddenSeries]}))}catch{}}
49+
function save(){try{localStorage.setItem(STATE_KEY,JSON.stringify({decisionDate:decisionSelect.value,dataLatestDate:dates[0]||null,family:familyFilter.value,horizon:horizonFilter.value,hiddenSeries:[...hiddenSeries]}))}catch{}}
5050
function option(value,label){const node=document.createElement('option');node.value=value;node.textContent=label;return node}
51-
const dates=[...new Set(data.arms.map(a=>a.decision_date))].sort().reverse();dates.forEach(d=>decisionSelect.appendChild(option(d,d)));decisionSelect.value=dates.includes(saved.decisionDate)?saved.decisionDate:dates[0]||'';familyFilter.value=['ridge','xgb_ranker'].includes(saved.family)?saved.family:'all';horizonFilter.value=['5','10','20'].includes(saved.horizon)?saved.horizon:'all';
51+
const dates=[...new Set(data.arms.map(a=>a.decision_date))].sort().reverse();dates.forEach(d=>decisionSelect.appendChild(option(d,d)));const savedDateMatchesCurrentDataset=saved.dataLatestDate===dates[0];decisionSelect.value=savedDateMatchesCurrentDataset&&dates.includes(saved.decisionDate)?saved.decisionDate:dates[0]||'';familyFilter.value=['ridge','xgb_ranker'].includes(saved.family)?saved.family:'all';horizonFilter.value=['5','10','20'].includes(saved.horizon)?saved.horizon:'all';
5252
function decisionArms(){return data.arms.filter(a=>a.decision_date===decisionSelect.value)}
5353
function visibleArms(){return decisionArms().filter(a=>(familyFilter.value==='all'||a.family===familyFilter.value)&&(horizonFilter.value==='all'||String(a.horizon_sessions)===horizonFilter.value))}
5454
function table(rows,columns,sortState){if(!rows.length)return'<div class="empty"><div><strong>No matching records</strong><span>Adjust the filters or wait for the required outcome window.</span></div></div>';const head=columns.map(([key,label])=>`<th><button class="sort" data-sort="${key}">${label}${sortState?.key===key?(sortState.direction==='asc'?' ↑':' ↓'):''}</button></th>`).join(''),body=rows.map(row=>`<tr>${columns.map(([key])=>{const value=row[key],shown=key.includes('return')||key==='weight'||key==='sentiment_coverage'?fmtPct(value):key==='score'?fmtNum(value,5):value??'—';return`<td class="${key.includes('return')&&value!=null?tone(value):''}">${shown}</td>`}).join('')}</tr>`).join('');return`<div class="table-wrap"><table><thead><tr>${head}</tr></thead><tbody>${body}</tbody></table></div>`}

src/experiments/live_forward_20d_dashboard.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,9 +313,9 @@ def horizon_dashboard_html(payload: dict[str, Any]) -> str:
313313
const data=JSON.parse(document.getElementById('dashboard-data').textContent),decisionSelect=document.getElementById('decisionSelect'),familyFilter=document.getElementById('familyFilter'),horizonFilter=document.getElementById('horizonFilter'),STATE_KEY='live-forward-horizon-dashboard-v1';
314314
const COLORS={ridge:'#3156d3',xgb_ranker:'#0f9f8f',ridge_h5:'#7290eb',ridge_h10:'#4f70dc',ridge_h20:'#3156d3',xgb_ranker_h5:'#70c8bd',xgb_ranker_h10:'#3eb2a4',xgb_ranker_h20:'#0f9f8f',spy:'#d89614'},names={ridge:'Ridge',xgb_ranker:'XGBoost'},fmtPct=v=>v==null||!Number.isFinite(Number(v))?'n/a':(Number(v)*100).toFixed(2)+'%',fmtNum=(v,d=3)=>v==null||!Number.isFinite(Number(v))?'n/a':Number(v).toFixed(d),human=v=>String(v??'').replaceAll('_',' ').replace(/\b\w/g,c=>c.toUpperCase()),tone=v=>Number(v)>=0?'pos':'neg',armColor=a=>COLORS[`${a.family}_h${a.horizon_sessions}`]||COLORS[a.family],armLabel=a=>`${names[a.family]||human(a.family)} · ${a.horizon_sessions} sessions`;
315315
let saved={};try{saved=JSON.parse(localStorage.getItem(STATE_KEY)||'{}')}catch{}let hiddenSeries=new Set(saved.hiddenSeries||[]);
316-
function save(){try{localStorage.setItem(STATE_KEY,JSON.stringify({decisionDate:decisionSelect.value,family:familyFilter.value,horizon:horizonFilter.value,hiddenSeries:[...hiddenSeries]}))}catch{}}
316+
function save(){try{localStorage.setItem(STATE_KEY,JSON.stringify({decisionDate:decisionSelect.value,dataLatestDate:dates[0]||null,family:familyFilter.value,horizon:horizonFilter.value,hiddenSeries:[...hiddenSeries]}))}catch{}}
317317
function option(value,label){const node=document.createElement('option');node.value=value;node.textContent=label;return node}
318-
const dates=[...new Set(data.arms.map(a=>a.decision_date))].sort().reverse();dates.forEach(d=>decisionSelect.appendChild(option(d,d)));decisionSelect.value=dates.includes(saved.decisionDate)?saved.decisionDate:dates[0]||'';familyFilter.value=['ridge','xgb_ranker'].includes(saved.family)?saved.family:'all';horizonFilter.value=['5','10','20'].includes(saved.horizon)?saved.horizon:'all';
318+
const dates=[...new Set(data.arms.map(a=>a.decision_date))].sort().reverse();dates.forEach(d=>decisionSelect.appendChild(option(d,d)));const savedDateMatchesCurrentDataset=saved.dataLatestDate===dates[0];decisionSelect.value=savedDateMatchesCurrentDataset&&dates.includes(saved.decisionDate)?saved.decisionDate:dates[0]||'';familyFilter.value=['ridge','xgb_ranker'].includes(saved.family)?saved.family:'all';horizonFilter.value=['5','10','20'].includes(saved.horizon)?saved.horizon:'all';
319319
function decisionArms(){return data.arms.filter(a=>a.decision_date===decisionSelect.value)}
320320
function visibleArms(){return decisionArms().filter(a=>(familyFilter.value==='all'||a.family===familyFilter.value)&&(horizonFilter.value==='all'||String(a.horizon_sessions)===horizonFilter.value))}
321321
function table(rows,columns,sortState){if(!rows.length)return'<div class="empty"><div><strong>No matching records</strong><span>Adjust the filters or wait for the required outcome window.</span></div></div>';const head=columns.map(([key,label])=>`<th><button class="sort" data-sort="${key}">${label}${sortState?.key===key?(sortState.direction==='asc'?' ↑':' ↓'):''}</button></th>`).join(''),body=rows.map(row=>`<tr>${columns.map(([key])=>{const value=row[key],shown=key.includes('return')||key==='weight'||key==='sentiment_coverage'?fmtPct(value):key==='score'?fmtNum(value,5):value??'—';return`<td class="${key.includes('return')&&value!=null?tone(value):''}">${shown}</td>`}).join('')}</tr>`).join('');return`<div class="table-wrap"><table><thead><tr>${head}</tr></thead><tbody>${body}</tbody></table></div>`}

tests/test_live_forward_20d_dashboard.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,5 +172,7 @@ def test_dashboard_html_exposes_v2_information_architecture() -> None:
172172
assert "never mixed with validation estimates" in html
173173
assert "Show SHAP feature importance" in html
174174
assert "live-forward-horizon-dashboard-v1" in html
175+
assert "saved.dataLatestDate===dates[0]" in html
176+
assert "dataLatestDate:dates[0]||null" in html
175177
assert "width=device-width,initial-scale=1" in html
176178
assert "__DASHBOARD_PAYLOAD__" not in html

0 commit comments

Comments
 (0)