diff --git a/frontend/src/components/admin/PerformanceSettings.tsx b/frontend/src/components/admin/PerformanceSettings.tsx index 015c131..563e23f 100644 --- a/frontend/src/components/admin/PerformanceSettings.tsx +++ b/frontend/src/components/admin/PerformanceSettings.tsx @@ -49,6 +49,15 @@ export function PerformanceSettings() { if (window.isLoading || shadow.isLoading || !book) return ; + // Staged edits: nothing about the shadow book persists until Save, matching + // the other admin panels — and making the live-trade toggle deliberate. + const bookDirty = + !!shadow.data && + (book.enabled !== shadow.data.enabled || + book.capacity !== shadow.data.capacity || + book.risk_pct !== shadow.data.risk_pct || + book.start_equity !== shadow.data.start_equity); + return (
@@ -106,14 +115,15 @@ export function PerformanceSettings() { saveBook.mutate({ enabled: e.target.checked })} + onChange={(e) => setBook({ ...book, enabled: e.target.checked })} className="mt-0.5" /> Shadow book enabled - Starts opening real paper positions automatically on the next near-close scan. Verify its - first selections match a backtest of that day's cross-section before trusting the curve. + Starts opening real paper positions automatically on the next near-close scan — takes + effect when you Save. Verify its first selections match the top-ranked qualified setups + before trusting the curve. @@ -127,7 +137,6 @@ export function PerformanceSettings() { max={100} value={book.capacity} onChange={(e) => setBook({ ...book, capacity: Number(e.target.value) })} - onBlur={() => saveBook.mutate({ capacity: book.capacity })} className="input-glass w-full px-3 py-2 text-sm" /> @@ -140,7 +149,6 @@ export function PerformanceSettings() { max={10} value={book.risk_pct} onChange={(e) => setBook({ ...book, risk_pct: Number(e.target.value) })} - onBlur={() => saveBook.mutate({ risk_pct: book.risk_pct })} className="input-glass w-full px-3 py-2 text-sm" /> @@ -152,7 +160,6 @@ export function PerformanceSettings() { step={1000} value={book.start_equity} onChange={(e) => setBook({ ...book, start_equity: Number(e.target.value) })} - onBlur={() => saveBook.mutate({ start_equity: book.start_equity })} className="input-glass w-full px-3 py-2 text-sm" /> @@ -161,6 +168,20 @@ export function PerformanceSettings() { Defaults match the validated configuration: 10 positions, 1% fixed-fractional risk. Start equity is only a sizing base — the books are compared in R-multiples, not currency.

+ +
+ + {bookDirty && !saveBook.isPending && ( + Unsaved changes + )} +
);