{chartTitle || 'EQUITY CURVE'}
{chartSub &&
{chartSub}
}
{/* Chart */}
{!chartTitle && !loading && !optLoading && !slLoading && !skipLoading && !overallLoading && (
Configure and run a backtest
)}
{(loading || optLoading || slLoading || skipLoading || overallLoading) && (
)}
{/* Optimize result */}
{optimizeResult && (() => {
const { data, mode: optMode, metric, activeIdx } = optimizeResult;
const b = data.best;
const mLabel = METRIC_LABELS[metric] || 'Score';
let bestCells;
if (optMode === 'crossover') bestCells = [{ label:'Fast MA', value: b.fastPeriod }, { label:'Slow MA', value: b.slowPeriod }, { label:'Long Lev', value: b.leverageLong+'x' }, { label:'Short Lev', value: b.leverageShort+'x' }, { label:'Return', value: fmtPct(b.totalReturn), color: retColorStr(b.totalReturn) }, { label:'CAGR', value: fmtPct(b.cagr), color: retColorStr(b.cagr) }, { label:'Max DD', value: b.maxDrawdown?.toFixed(1)+'%', color: TH.red }, { label: mLabel, value: scoreDisplayStr(b, metric) }];
else if (optMode === 'sweep') bestCells = [{ label:'MA Period', value: `${b.maType} ${b.period}` }, { label:'Long Lev', value: b.leverageLong+'x' }, { label:'Short Lev', value: b.leverageShort+'x' }, { label:'Return', value: fmtPct(b.totalReturn), color: retColorStr(b.totalReturn) }, { label:'CAGR', value: fmtPct(b.cagr), color: retColorStr(b.cagr) }, { label:'Max DD', value: b.maxDrawdown?.toFixed(1)+'%', color: TH.red }, { label: mLabel, value: scoreDisplayStr(b, metric) }];
else if (optMode === 'overall-sweep') bestCells = [{ label:'Asset', value: aLabel(b.asset) }, { label:'MA Period', value: `${b.maType} ${b.period}` }, { label:'Long Lev', value: b.leverageLong+'x' }, { label:'Short Lev', value: b.leverageShort+'x' }, { label:'Return', value: fmtPct(b.totalReturn), color: retColorStr(b.totalReturn) }, { label:'CAGR', value: fmtPct(b.cagr), color: retColorStr(b.cagr) }, { label:'Max DD', value: b.maxDrawdown?.toFixed(1)+'%', color: TH.red }, { label: mLabel, value: scoreDisplayStr(b, metric) }];
else if (optMode === 'dual') bestCells = [{ label:'MA 1', value: b.maPeriod1 }, { label:'MA 2', value: b.maPeriod2 }, { label:'Long Lev', value: b.leverageLong+'x' }, { label:'Short Lev', value: b.leverageShort+'x' }, { label:'Return', value: fmtPct(b.totalReturn), color: retColorStr(b.totalReturn) }, { label:'CAGR', value: fmtPct(b.cagr), color: retColorStr(b.cagr) }, { label:'Max DD', value: b.maxDrawdown?.toFixed(1)+'%', color: TH.red }, { label: mLabel, value: scoreDisplayStr(b, metric) }];
else bestCells = [{ label:'Cond 1', value: `${aLabel(b.asset1)} ${b.maPeriod1}` }, { label:'Cond 2', value: `${aLabel(b.asset2)} ${b.maPeriod2}` }, { label:'Trade', value: aLabel(b.tradeAsset) }, { label:'Long Lev', value: b.leverageLong+'x' }, { label:'Return', value: fmtPct(b.totalReturn), color: retColorStr(b.totalReturn) }, { label:'CAGR', value: fmtPct(b.cagr), color: retColorStr(b.cagr) }, { label:'Max DD', value: b.maxDrawdown?.toFixed(1)+'%', color: TH.red }, { label: mLabel, value: scoreDisplayStr(b, metric) }];
const tableHead = optMode === 'crossover' ? ['Fast / Slow','Leverage','Return','CAGR','Max DD',mLabel,'Trades'] :
optMode === 'overall-sweep' ? ['Asset · MA','Leverage','Return','CAGR','Max DD',mLabel,'Trades'] :
optMode === 'overall-dual' ? ['Cond1+Cond2→Trade','Leverage','Return','CAGR','Max DD',mLabel,'Trades'] :
optMode === 'dual' ? ['MA1 / MA2','Leverage','Return','CAGR','Max DD',mLabel,'Trades'] :
['MA Period','Leverage','Return','CAGR','Max DD',mLabel,'Trades'];
return (
}
tableHead={tableHead}
tableRows={buildOptRows(data.results, optMode, metric)}
activeIdx={activeIdx}
onRowClick={(i, r) => handleOptRowClick(i, r._raw)}
/>
);
})()}
{/* SL result */}
{slResult && (() => {
const { data, metric, activeIdx } = slResult;
const b = data.best;
const mLabel = METRIC_LABELS[metric] || 'Score';
const bestCells = [
{ label:'SL Type', value: b.slLabel },
{ label:'Return', value: fmtPct(b.totalReturn), color: retColorStr(b.totalReturn) },
{ label:'CAGR', value: fmtPct(b.cagr), color: retColorStr(b.cagr) },
{ label:'Max DD', value: b.maxDrawdown?.toFixed(1)+'%', color: TH.red },
{ label: mLabel, value: scoreDisplayStr(b, metric) },
{ label:'Trades', value: b.tradeCount },
];
return (
}
tableHead={['Stop Loss','Return','CAGR','Max DD',mLabel,'Trades']}
tableRows={buildSLRows(data.results, metric)}
activeIdx={activeIdx}
onRowClick={(i, r) => handleSLRowClick(i, r._raw)}
/>
);
})()}
{/* Skip result */}
{skipResult && (() => {
const { data, metric, activeIdx } = skipResult;
const b = data.best;
const mLabel = METRIC_LABELS[metric] || 'Score';
const bestCells = [
{ label:'Skip Setting', value: b.label },
{ label:'Return', value: fmtPct(b.totalReturn), color: retColorStr(b.totalReturn) },
{ label:'CAGR', value: fmtPct(b.cagr), color: retColorStr(b.cagr) },
{ label:'Max DD', value: b.maxDrawdown?.toFixed(1)+'%', color: TH.red },
{ label: mLabel, value: scoreDisplayStr(b, metric) },
{ label:'Trades', value: b.tradeCount },
];
return (
}
tableHead={['Skip Setting','Return','CAGR','Max DD',mLabel,'Trades']}
tableRows={buildSkipRows(data.results, metric)}
activeIdx={activeIdx}
onRowClick={(i, r) => handleSkipRowClick(i, r._raw)}
/>
);
})()}
{sweepTable}