@@ -63,6 +63,92 @@ let selectedRunView = 'summary';
6363 } ) ;
6464} ) ( ) ;
6565
66+ // ===== LAZY STRATEGY PAGE RENDERING =====
67+ var _renderedStratPages = { } ;
68+
69+ function ensureStratPage ( stratIdx ) {
70+ if ( _renderedStratPages [ stratIdx ] ) return ;
71+ _renderedStratPages [ stratIdx ] = true ;
72+
73+ var s = STRATEGIES [ stratIdx ] ;
74+ if ( ! s ) return ;
75+ var sid = s . id ;
76+ var i = stratIdx ;
77+ var rl = s . runLabels || [ ] ;
78+
79+ var h = '<div class="page" id="page-' + sid + '" style="display:none">' ;
80+ h += '<h2 class="page-title">' ;
81+ h += '<span class="sb-dot" style="background:' + s . color + ';width:12px;height:12px"></span> ' ;
82+ h += escHtmlLazy ( s . name ) ;
83+ if ( s . tag ) h += ' <span class="tag-badge">' + escHtmlLazy ( s . tag ) + '</span>' ;
84+ if ( rl . length > 1 ) {
85+ h += ' <select class="view-select strat-window-select" data-strat="' + i + '" onchange="onStratWindowChange(' + i + ', this.value)">' ;
86+ h += '<option value="summary">Σ All Windows</option>' ;
87+ rl . forEach ( function ( pair ) {
88+ var rn = pair [ 0 ] , lab = pair [ 1 ] ;
89+ var mapped = s . runNameMap [ rn ] || '' ;
90+ h += '<option value="' + mapped + '">' + escHtmlLazy ( lab ) + '</option>' ;
91+ } ) ;
92+ h += '</select>' ;
93+ }
94+ h += '</h2>' ;
95+
96+ h += '<div id="' + sid + '-summary-content"></div>' ;
97+ h += '<div id="' + sid + '-parameters"></div>' ;
98+
99+ if ( rl . length > 1 ) {
100+ h += '<div class="chart-card collapsed"><div class="chart-title">Backtest Runs</div>' ;
101+ h += '<div class="table-wrap"><table class="comp-table" id="strat-runs-table-' + i + '">' ;
102+ h += '<thead><tr><th>Run</th><th>Return</th><th>Sharpe</th><th>Max DD</th><th>Trades</th></tr></thead><tbody>' ;
103+ rl . forEach ( function ( pair ) {
104+ var rn = pair [ 0 ] , lab = pair [ 1 ] ;
105+ var mapped = s . runNameMap [ rn ] || '' ;
106+ h += '<tr data-run="' + mapped + '"><td>' + escHtmlLazy ( lab ) + '</td><td></td><td></td><td></td><td></td></tr>' ;
107+ } ) ;
108+ h += '</tbody></table></div></div>' ;
109+ }
110+
111+ h += '<div class="nav-tabs strat-nav-tabs" id="' + sid + '-tabs">' ;
112+ h += '<div class="tab active" onclick="switchStratTab(\'' + sid + '\',\'performance\')">Performance</div>' ;
113+ h += '<div class="tab" onclick="switchStratTab(\'' + sid + '\',\'trading\')">Trading</div>' ;
114+ h += '</div>' ;
115+
116+ h += '<div class="tab-panel active" id="' + sid + '-performance">' ;
117+ h += '<div id="' + sid + '-portfolio-summary"></div>' ;
118+ h += '<div id="' + sid + '-trading-activity"></div>' ;
119+
120+ h += '<div class="chart-card"><div class="chart-title" id="eq-title-' + sid + '">Equity Curves (All Runs)</div>' ;
121+ h += '<div class="chart-wrap"><canvas id="c-' + sid + '-eq"></canvas><div class="tooltip" id="tt-' + sid + '-eq"></div></div></div>' ;
122+
123+ h += '<div class="chart-card"><div class="chart-title" id="rs-title-' + sid + '">Rolling Sharpe Ratio (All Runs)</div>' ;
124+ h += '<div class="chart-wrap"><canvas id="c-' + sid + '-rsharpe"></canvas><div class="tooltip" id="tt-' + sid + '-rsharpe"></div></div></div>' ;
125+
126+ h += '<div class="chart-card"><div class="chart-title" id="dd-title-' + sid + '">Drawdown (All Runs)</div>' ;
127+ h += '<div class="chart-wrap"><canvas id="c-' + sid + '-dd"></canvas><div class="tooltip" id="tt-' + sid + '-dd"></div></div></div>' ;
128+
129+ h += '<div id="' + sid + '-monthly-returns"></div>' ;
130+ h += '<div id="' + sid + '-yearly-returns"></div>' ;
131+ h += '<div id="' + sid + '-return-scenarios"></div>' ;
132+ h += '</div>' ;
133+
134+ h += '<div class="tab-panel" id="' + sid + '-trading">' ;
135+ h += '<div id="' + sid + '-timeline-scatter"></div>' ;
136+ h += '<div id="' + sid + '-trades-table"></div>' ;
137+ h += '<div id="' + sid + '-orders-table"></div>' ;
138+ h += '<div id="' + sid + '-positions-table"></div>' ;
139+ h += '</div>' ;
140+
141+ h += '</div>' ;
142+
143+ var container = document . getElementById ( 'strategy-pages-container' ) ;
144+ if ( container ) container . insertAdjacentHTML ( 'beforeend' , h ) ;
145+ }
146+
147+ function escHtmlLazy ( str ) {
148+ if ( ! str ) return '' ;
149+ return String ( str ) . replace ( / & / g, '&' ) . replace ( / < / g, '<' ) . replace ( / > / g, '>' ) . replace ( / " / g, '"' ) ;
150+ }
151+
66152function onOverviewWindowChange ( value ) {
67153 onRunViewChange ( value ) ;
68154}
@@ -448,6 +534,10 @@ function syncSbChallenger() {
448534}
449535
450536function showPage ( pageId ) {
537+ // Lazy-render strategy pages on first visit
538+ var stratMatch = pageId . match ( / ^ s t r a t - ( \d + ) $ / ) ;
539+ if ( stratMatch ) ensureStratPage ( parseInt ( stratMatch [ 1 ] ) ) ;
540+
451541 document . querySelectorAll ( '.page' ) . forEach ( p => p . style . display = 'none' ) ;
452542 const target = document . getElementById ( 'page-' + pageId ) ;
453543 if ( target ) target . style . display = 'block' ;
@@ -4494,8 +4584,9 @@ function drawPageCharts(pageId) {
44944584
44954585// ===== POPULATE RUNS TAB CELLS =====
44964586function populateRunsTabs ( ) {
4587+ // Only populate runs tables for already-rendered strategy pages
44974588 STRATEGIES . forEach ( ( s , idx ) => {
4498- populateStratRunsTable ( idx ) ;
4589+ if ( _renderedStratPages [ idx ] ) populateStratRunsTable ( idx ) ;
44994590 } ) ;
45004591}
45014592
@@ -6468,6 +6559,17 @@ function updateStratTables(stratIdx) {
64686559}
64696560
64706561// ===== INIT =====
6562+ // Auto-select top 10 by CAGR when there are more than 10 strategies
6563+ if ( ! IS_SINGLE && STRATEGIES . length > 10 ) {
6564+ var _initIndices = STRATEGIES . map ( function ( _ , i ) { return i ; } ) ;
6565+ _initIndices . sort ( function ( a , b ) {
6566+ var ca = STRATEGIES [ a ] . summary . cagr , cb = STRATEGIES [ b ] . summary . cagr ;
6567+ if ( ca == null ) ca = - Infinity ;
6568+ if ( cb == null ) cb = - Infinity ;
6569+ return cb - ca ;
6570+ } ) ;
6571+ _initIndices . slice ( 0 , 10 ) . forEach ( function ( i ) { selectedForCompare . add ( i ) ; } ) ;
6572+ }
64716573buildBenchmarkChips ( ) ;
64726574rebuildWindowCoverage ( ) ;
64736575rebuildOverviewKPIs ( ) ;
@@ -6476,6 +6578,7 @@ rebuildOverviewTradingActivity();
64766578rebuildReturnScenarios ( ) ;
64776579initCollapseButtons ( ) ;
64786580syncModalCount ( ) ;
6581+ syncMainTableCheckboxes ( ) ;
64796582populateRunsTabs ( ) ;
64806583drawPageCharts ( 'overview' ) ;
64816584renderNotesList ( ) ;
0 commit comments