Hide the next stop on a booked day; label min day P&L as such

On 2026-10-08 a Tradeify min day ($150) stopped out at −$306 on its 2×
stop of $300. The dashboard then read "stop $912": the next-stop label is
recomputed from the remaining target, which the loss grew to $456, for a
leg that never fires — the day is booked and the make-back rides tomorrow,
stopless.

- obfuscationDayBooked() holds the scheduler's booked-day check; the state
  route asks it too and shows no next stop, last stand or hold on a
  booked day.
- The account page's "Daily Loss Limit" showed minDayPnL. It now shows the
  type's real daily loss limit, with Min Day P&L on its own row; the
  objective that passed on total profit ≥ minDayPnL is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-10-08 16:06:35 -05:00
co-authored by Claude Opus 5.5
parent c3b58c8d8b
commit c0261f42ae
3 changed files with 40 additions and 26 deletions
+24 -13
View File
@@ -144,6 +144,28 @@ function legSumToday(accountId: number, tradeDate: string): number {
return entry && entry.date === tradeDate ? entry.sum : 0;
}
/**
* Why an obfuscation stop has booked the day, or null when it hasn't. A
* stop-out shows as realized P&L falling short of the legs fired today — the
* day is booked; the make-back ride is tomorrow. The plain negative-realized
* check is what survives a restart, when the in-memory leg counter has
* forgotten the morning's stop-out. The dashboard asks too: a booked day has
* no next leg, so no next stop to show.
*/
export function obfuscationDayBooked(
cfg: { firstDayStop: boolean; minDayStop: boolean },
accountId: number,
tradeDate: string,
realizedPnL: number,
): string | null {
if (!cfg.firstDayStop && !cfg.minDayStop) return null;
if (realizedPnL <= -25) return 'red day booked — make-back rides tomorrow';
if (legsToday(accountId, tradeDate) > 0 && realizedPnL < legSumToday(accountId, tradeDate) - 25) {
return 'stopped out — day booked';
}
return null;
}
interface EntryOutcome {
tradeDate: string;
state: 'filled' | 'unknown';
@@ -685,19 +707,8 @@ function evaluateAccountForTrade(client: any, acc: { id: number; name: string; a
return { ...base, eligible: false, reason: 'exit refused — flattened, benched for the day' };
}
// Obfuscation stops: a stop-out shows as realized P&L falling short of the
// legs fired today — the day is booked; the make-back ride is tomorrow.
// The plain negative-realized check is what survives a restart, when the
// in-memory leg counter has forgotten the morning's stop-out.
if (cfg.firstDayStop || cfg.minDayStop) {
if (combined.realizedPnL <= -25) {
return { ...base, eligible: false, reason: 'red day booked — make-back rides tomorrow' };
}
if (legsToday(acc.id, tradeDate) > 0
&& combined.realizedPnL < legSumToday(acc.id, tradeDate) - 25) {
return { ...base, eligible: false, reason: 'stopped out — day booked' };
}
}
const booked = obfuscationDayBooked(cfg, acc.id, tradeDate, combined.realizedPnL);
if (booked) return { ...base, eligible: false, reason: booked };
const priorProfit = client.priorProfit?.[acc.id] ?? 0;
const allFundTxns = client.fundTransactions?.[acc.id] ?? [];