diff options
| author | Tyler <tyler@tylerhoang.xyz> | 2026-05-17 00:10:42 -0700 |
|---|---|---|
| committer | Tyler <tyler@tylerhoang.xyz> | 2026-05-17 00:10:42 -0700 |
| commit | 654b76c34d93f8d31b199afb84edb2742b26444a (patch) | |
| tree | d1641b9f5720e27a0066b8ad568d97afc5526f17 | |
| parent | 2b229cff5f99a00b6cc984f4c1c3c41de7f1e04c (diff) | |
Fix 5D x-axis labels and weekend/closed fallback for intraday default
- 5D period now uses '%a %H:%M' tick format so each day is labelled (Mon 09:30)
instead of bare times that repeat across five days
- default_period resolves to '1mo' when 1D series is empty (market closed,
weekend, holiday) so the chart isn't blank on first load
- JS activePeriod reads from OVERVIEW_META.default_period at boot instead of
hardcoded '1d', and bootOverview syncs the active button to match
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| -rw-r--r-- | components/overview.py | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/components/overview.py b/components/overview.py index c52cae2..9ea3f19 100644 --- a/components/overview.py +++ b/components/overview.py @@ -281,7 +281,7 @@ def render_overview(ticker: str): meta = { "updated_label": datetime.now().strftime("%Y-%m-%d %H:%M"), - "default_period": "1d", + "default_period": "1d" if series.get("1d") else "1mo", "default_mode": "price", "default_comparisons": ["^GSPC"], } @@ -482,7 +482,7 @@ def render_overview(ticker: str): "<script>" + payload_js + meta_js - + "var activePeriod='1d';var activeMode='price';var activeComparisons=['^GSPC'];" + + "var activePeriod=OVERVIEW_META.default_period||'1d';var activeMode='price';var activeComparisons=['^GSPC'];" + "function cssVar(n){return getComputedStyle(document.documentElement).getPropertyValue(n).trim();}" + "function withAlpha(hex,a){if(!hex||hex.charAt(0)!=='#'||hex.length!==7)return 'rgba(0,0,0,'+a+')';var r=parseInt(hex.substring(1,3),16),g=parseInt(hex.substring(3,5),16),b=parseInt(hex.substring(5,7),16);return 'rgba('+r+','+g+','+b+','+a+')';}" + "var C_FG1=cssVar('--fg-1');var C_FG2=cssVar('--fg-2');var C_FG3=cssVar('--fg-3');var C_LINE=cssVar('--line-1');var C_BRASS=cssVar('--brass');var C_BRASS_B=cssVar('--brass-bright');var C_POS=cssVar('--positive');var C_NEG=cssVar('--negative');var C_WARN=cssVar('--warning');var C_INFO=cssVar('--info');" @@ -505,10 +505,10 @@ def render_overview(ticker: str): + "function setPeriod(period,btn){activePeriod=period;document.querySelectorAll('[id^=btn-p-]').forEach(function(b){b.classList.remove('active');});if(btn)btn.classList.add('active');refreshAll();}" + "function setMode(mode,btn){activeMode=mode;document.querySelectorAll('[id^=btn-m-]').forEach(function(b){b.classList.remove('active');});if(btn)btn.classList.add('active');renderCompButtons();renderChart();renderReadout();}" + "function toggleComparison(sym,btn){var i=activeComparisons.indexOf(sym);if(i>=0){activeComparisons.splice(i,1);}else{activeComparisons.push(sym);}if(!activeComparisons.length){activeComparisons=['^GSPC'];}renderCompButtons();renderChart();renderReadout();}" - + "function renderChart(){if(typeof Plotly==='undefined'){return;}var tkr=OVERVIEW_DATA.ticker;var base=getSeries(tkr);var traces=[];if(activeMode==='price'){var p=toTraceData(base);traces.push({x:p.x,y:p.y,type:'scatter',mode:'lines',name:tkr,line:{color:C_BRASS,width:2.2},fill:'tozeroy',fillcolor:withAlpha(C_BRASS,0.10)});}else{var p2=rebased(base);traces.push({x:p2.x,y:p2.y,type:'scatter',mode:'lines',name:tkr,line:{color:C_BRASS,width:2.4}});var idx=1;activeComparisons.forEach(function(sym){if(sym===tkr)return;var rr=rebased(getSeries(sym));if(!rr.x.length)return;var label=sym;var comps=OVERVIEW_DATA.comparisons||[];for(var i=0;i<comps.length;i+=1){if(comps[i].symbol===sym){label=comps[i].label||sym;break;}}traces.push({x:rr.x,y:rr.y,type:'scatter',mode:'lines',name:label,line:{color:REL_COLORS[idx%REL_COLORS.length],width:1.8}});idx+=1;});}var isIntraday=(activePeriod==='1d'||activePeriod==='5d');var layout={height:320,margin:{l:52,r:14,t:14,b:34},paper_bgcolor:'rgba(0,0,0,0)',plot_bgcolor:'rgba(0,0,0,0)',hovermode:'x unified',font:{family:'IBM Plex Mono',color:C_FG3},xaxis:{showgrid:false,zeroline:false,tickfont:{family:'IBM Plex Mono'},tickformat:isIntraday?'%H:%M':'%b %d'},yaxis:{showgrid:true,gridcolor:C_LINE,zeroline:(activeMode==='relative'),zerolinecolor:C_LINE,tickprefix:(activeMode==='price'?'$':''),ticksuffix:(activeMode==='relative'?'%':''),tickformat:(activeMode==='relative'?'.1f':',.2f')},legend:{orientation:'h',x:0,y:1.12,bgcolor:'rgba(0,0,0,0)',font:{family:'IBM Plex Mono',color:C_FG2,size:11}}};Plotly.react('ov-chart',traces,layout,{displayModeBar:false,responsive:true});}" + + "function renderChart(){if(typeof Plotly==='undefined'){return;}var tkr=OVERVIEW_DATA.ticker;var base=getSeries(tkr);var traces=[];if(activeMode==='price'){var p=toTraceData(base);traces.push({x:p.x,y:p.y,type:'scatter',mode:'lines',name:tkr,line:{color:C_BRASS,width:2.2},fill:'tozeroy',fillcolor:withAlpha(C_BRASS,0.10)});}else{var p2=rebased(base);traces.push({x:p2.x,y:p2.y,type:'scatter',mode:'lines',name:tkr,line:{color:C_BRASS,width:2.4}});var idx=1;activeComparisons.forEach(function(sym){if(sym===tkr)return;var rr=rebased(getSeries(sym));if(!rr.x.length)return;var label=sym;var comps=OVERVIEW_DATA.comparisons||[];for(var i=0;i<comps.length;i+=1){if(comps[i].symbol===sym){label=comps[i].label||sym;break;}}traces.push({x:rr.x,y:rr.y,type:'scatter',mode:'lines',name:label,line:{color:REL_COLORS[idx%REL_COLORS.length],width:1.8}});idx+=1;});}var isIntraday=(activePeriod==='1d'||activePeriod==='5d');var layout={height:320,margin:{l:52,r:14,t:14,b:34},paper_bgcolor:'rgba(0,0,0,0)',plot_bgcolor:'rgba(0,0,0,0)',hovermode:'x unified',font:{family:'IBM Plex Mono',color:C_FG3},xaxis:{showgrid:false,zeroline:false,tickfont:{family:'IBM Plex Mono'},tickformat:(activePeriod==='5d'?'%a %H:%M':(isIntraday?'%H:%M':'%b %d'))},yaxis:{showgrid:true,gridcolor:C_LINE,zeroline:(activeMode==='relative'),zerolinecolor:C_LINE,tickprefix:(activeMode==='price'?'$':''),ticksuffix:(activeMode==='relative'?'%':''),tickformat:(activeMode==='relative'?'.1f':',.2f')},legend:{orientation:'h',x:0,y:1.12,bgcolor:'rgba(0,0,0,0)',font:{family:'IBM Plex Mono',color:C_FG2,size:11}}};Plotly.react('ov-chart',traces,layout,{displayModeBar:false,responsive:true});}" + "function renderReadout(){var rg=OVERVIEW_DATA.range_52w||{};var lo=asNum(rg.low),hi=asNum(rg.high),px=asNum(rg.price);var txt='';if(lo!==null&&hi!==null&&px!==null&&hi>lo&&px>0){var above=((px-lo)/lo)*100;var below=((hi-px)/px)*100;txt='Stock is '+above.toFixed(1)+'% above 52-week low and '+below.toFixed(1)+'% below 52-week high.';}if(activeMode==='relative'){var t=rebased(getSeries(OVERVIEW_DATA.ticker));var tLast=t.y.length?t.y[t.y.length-1]:null;var sp=rebased(getSeries('^GSPC'));var spLast=sp.y.length?sp.y[sp.y.length-1]:null;if(tLast!==null&&spLast!==null){txt='Relative over '+periodLabel(activePeriod)+': '+OVERVIEW_DATA.ticker+' '+(tLast>=0?'+':'')+tLast.toFixed(1)+'% vs S&P 500 '+(spLast>=0?'+':'')+spLast.toFixed(1)+'%.';}}if(!txt){txt='Data is limited for this ticker and selected period, but chart controls remain available.';}document.getElementById('ov-readout').textContent=txt;}" + "function refreshAll(){renderSignals();renderKpis();renderRangeCard();renderShortCard();renderCompButtons();renderChart();renderReadout();}" - + "function bootOverview(){refreshAll();if(typeof Plotly==='undefined'){setTimeout(refreshAll,350);setTimeout(refreshAll,900);}}" + + "function bootOverview(){document.querySelectorAll('[id^=btn-p-]').forEach(function(b){b.classList.remove('active');});var initBtn=document.getElementById('btn-p-'+activePeriod);if(initBtn)initBtn.classList.add('active');refreshAll();if(typeof Plotly==='undefined'){setTimeout(refreshAll,350);setTimeout(refreshAll,900);}}" + "if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',bootOverview);}else{bootOverview();}" + "</script>" ) |
