fix(backtest): flag a lookback the recommendation was not computed on
Selecting a different window or a comparison strategy silently made the tiles stop matching the recommendation below, which is baked into the report and cannot follow a dropdown. On load they now agree by construction; moving off that basis says so. Also: an absent production row produced no headline and no benchmark, but any passing gate finding still rendered a green "no warnings" chip — a success badge for missing data, directly beside "this report predates the portfolio monitor". Missing baseline now reads "baseline unavailable". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -42,8 +42,19 @@ export function BacktestPanel() {
|
||||
const monitor = report?.portfolio_monitor ?? null;
|
||||
const activeStrategy =
|
||||
selectedStrategy || monitor?.production_strategy || monitor?.strategies[0]?.strategy || '';
|
||||
// Default to the window the recommendation was computed on, so the tiles and
|
||||
// the recommendation never open showing different numbers. They used to: the
|
||||
// backend preferred "all" while this defaulted to "3y". The 3y fallback is
|
||||
// only for reports predating basis_lookback.
|
||||
const basisLookback = report?.recommendation?.basis_lookback ?? null;
|
||||
const activeLookback =
|
||||
selectedLookback || (monitor?.lookbacks.some((l) => l.lookback === '3y') ? '3y' : monitor?.lookbacks[0]?.lookback) || '';
|
||||
selectedLookback ||
|
||||
(basisLookback && monitor?.lookbacks.some((l) => l.lookback === basisLookback)
|
||||
? basisLookback
|
||||
: monitor?.lookbacks.some((l) => l.lookback === '3y')
|
||||
? '3y'
|
||||
: monitor?.lookbacks[0]?.lookback) ||
|
||||
'';
|
||||
const monitorRun = useMemo(
|
||||
() =>
|
||||
monitor?.runs.find((row) => row.strategy === activeStrategy && row.lookback === activeLookback) ??
|
||||
@@ -175,6 +186,9 @@ export function BacktestPanel() {
|
||||
activeLookback={activeLookback}
|
||||
onStrategyChange={setSelectedStrategy}
|
||||
onLookbackChange={setSelectedLookback}
|
||||
basisLookback={basisLookback}
|
||||
basisLookbackLabel={report.recommendation?.basis_lookback_label ?? null}
|
||||
productionStrategy={monitor?.production_strategy ?? null}
|
||||
/>
|
||||
|
||||
{report.recommendation && (
|
||||
|
||||
@@ -81,7 +81,16 @@ export function BacktestRecommendationCard({
|
||||
<div className="glass border border-blue-400/20 p-4">
|
||||
<div className="flex flex-wrap items-center justify-between gap-2">
|
||||
<p className="section-index">What this backtest recommends</p>
|
||||
{warningCount > 0 ? (
|
||||
{/* No headline means the backend found no production monitor row, so
|
||||
nothing here describes the production book. Zero keyword warnings
|
||||
is then absence of data, not a clean bill of health — a green chip
|
||||
beside "this report predates the portfolio monitor" would be a
|
||||
success badge for missing data. */}
|
||||
{!recommendation.headline ? (
|
||||
<span className="rounded-full border border-white/15 bg-white/[0.05] px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wider text-gray-400">
|
||||
baseline unavailable
|
||||
</span>
|
||||
) : warningCount > 0 ? (
|
||||
<span className="rounded-full border border-amber-400/40 bg-amber-400/10 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wider text-amber-300">
|
||||
⚠ {warningCount} warning{warningCount > 1 ? 's' : ''}
|
||||
</span>
|
||||
|
||||
@@ -30,6 +30,9 @@ export function PortfolioMonitorPanel({
|
||||
activeLookback,
|
||||
onStrategyChange,
|
||||
onLookbackChange,
|
||||
basisLookback = null,
|
||||
basisLookbackLabel = null,
|
||||
productionStrategy = null,
|
||||
}: {
|
||||
monitor: BacktestPortfolioMonitor | null | undefined;
|
||||
monitorRun: BacktestPortfolioMonitorRun | null | undefined;
|
||||
@@ -37,6 +40,10 @@ export function PortfolioMonitorPanel({
|
||||
activeLookback: string;
|
||||
onStrategyChange: (v: string) => void;
|
||||
onLookbackChange: (v: string) => void;
|
||||
/** The window the recommendation below was computed on. */
|
||||
basisLookback?: string | null;
|
||||
basisLookbackLabel?: string | null;
|
||||
productionStrategy?: string | null;
|
||||
}) {
|
||||
if (!monitor || !monitorRun) {
|
||||
return (
|
||||
@@ -90,6 +97,21 @@ export function PortfolioMonitorPanel({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* The recommendation below is baked into the report and cannot follow a
|
||||
dropdown. On load the two agree by construction; say so plainly the
|
||||
moment a selection moves off that basis. */}
|
||||
{((basisLookback && activeLookback !== basisLookback) ||
|
||||
(productionStrategy && activeStrategy !== productionStrategy)) && (
|
||||
<p className="text-[11px] text-amber-300/80">
|
||||
Showing{' '}
|
||||
{productionStrategy && activeStrategy !== productionStrategy
|
||||
? 'a comparison strategy'
|
||||
: 'a different window'}
|
||||
. The recommendation below is computed on the production strategy over{' '}
|
||||
{basisLookbackLabel ?? basisLookback} — these tiles will not match it.
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Tier 1 — what the book returned. */}
|
||||
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-5">
|
||||
<StatTile
|
||||
|
||||
@@ -336,6 +336,13 @@ export interface BacktestCurvePoint {
|
||||
export interface BacktestRecommendation {
|
||||
headline: string | null;
|
||||
items: { topic: string; text: string }[];
|
||||
/**
|
||||
* The monitor lookback every production/benchmark figure was read from. The
|
||||
* page defaults its selector to this so the tiles and the recommendation
|
||||
* cannot open on different windows. Absent on reports predating the field.
|
||||
*/
|
||||
basis_lookback?: string | null;
|
||||
basis_lookback_label?: string | null;
|
||||
note?: string;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user