Add day-plan double-count diagnostics
The daily target sometimes inflates to base + consistency×todayPnL (e.g. 1200 + 0.4×1218.48 = 1687.39), which happens when a session's cached daily-P&L row is dated something other than the current tradeDate: it then lands in BOTH the prior-day list and realizedPnL, so day-start equity reads too low while the prior-day sum stays high. Detect it with a book-balance invariant that is coincidence-proof (it does not care whether prior and today P&L happen to be equal): the reconstructed day-start equity (equityProfit − realizedPnL) must equal priorProfit + sum(prior days). The state route now logs the full account state whenever those disagree by more than $50, and GET /api/debug reports the same per-account breakdown on demand (?account=<substring>) so the exact inputs can be captured the moment a number looks wrong. Read-only; no behavior change. Remove once the trigger is fixed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
5a69ea2f64
commit
ef476ccbb7
@@ -93,6 +93,49 @@ export async function GET() {
|
||||
const consistencyReal = (effective.consistency > 0 && effective.consistency < 1 && maxDay > 0)
|
||||
? maxDay / effective.consistency : 0;
|
||||
effectiveProfitTarget = Math.max(effective.profitTarget, consistencyReal);
|
||||
|
||||
// ── Double-count diagnostic ───────────────────────────────
|
||||
// computeDayPlan reconstructs day-start equity as
|
||||
// equityProfit − realizedPnL, then treats every dailyPnL row
|
||||
// NOT dated today as a prior day. Those two views must agree:
|
||||
// day-start equity should equal priorProfit + sum(prior days).
|
||||
// When a session's cached row is dated something other than
|
||||
// today's tradeDate, that session lands in BOTH the prior-day
|
||||
// list and realizedPnL — day-start equity reads too low while
|
||||
// the prior sum stays high, and the daily target inflates to
|
||||
// base + consistency×todayPnL (the $1,687.39 symptom). Fires
|
||||
// only when the books disagree by > $50, logging the exact
|
||||
// state needed to diagnose the trigger. Remove once resolved.
|
||||
const priorDaysSum = dailyPnL
|
||||
.filter((d) => d.date !== combined.tradeDate)
|
||||
.reduce((s, d) => s + d.pnl, 0);
|
||||
const dayStartEquity = equityProfit - combined.realizedPnL;
|
||||
const expectedDayStart = priorProfit + priorDaysSum;
|
||||
const drift = Math.round((dayStartEquity - expectedDayStart) * 100) / 100;
|
||||
if (Math.abs(drift) > 50) {
|
||||
console.warn('[day-plan][equity-drift] ' + JSON.stringify({
|
||||
account: acc.name,
|
||||
id: acc.id,
|
||||
serverNow: new Date().toISOString(),
|
||||
tradeDate: combined.tradeDate,
|
||||
drift,
|
||||
dayStartEquity,
|
||||
expectedDayStart,
|
||||
equityProfit,
|
||||
realizedPnL: combined.realizedPnL,
|
||||
priorProfit,
|
||||
priorDaysSum,
|
||||
dayTarget: plan?.dayTarget ?? null,
|
||||
remainingToday: plan?.remainingToday ?? null,
|
||||
consistency: effective.consistency,
|
||||
effectiveProfitTarget,
|
||||
hasTodayRow: dailyPnL.some((d) => d.date === combined.tradeDate),
|
||||
combineCmeHolidays: cfg.combineCmeHolidays === true,
|
||||
combinedDailyPnL: dailyPnL,
|
||||
rawDailyPnL: client.dailyPnL[acc.id] ?? [],
|
||||
}));
|
||||
}
|
||||
|
||||
// Condition 1: profit target already exceeded (target=0), still need days → any activity counts
|
||||
// Condition 2: target > 0 → all legs done (day's remaining target used up)
|
||||
if (plan) {
|
||||
|
||||
Reference in New Issue
Block a user