Cap consistency branch at maxDay; restore consistency cap in min-day

When consistency is between 0 and 1 (exclusive) and profitTarget not met,
the daily target should cap at maxDay (can't exceed the current max without
breaking the consistency ratio). The previous 'needed' calc could return
less than maxDay, stalling progress toward profitTarget.

Also restored Math.min(baseAmount, cappedByFuture) in the min-day
reservation so consistency is enforced when both mandates are active.

Traces:
- 0 days, $11111 target, 50%: first_day $5555.50, cappedByFuture $10511
  -> consistencyCap = min($5555.50, $10511) = $5555.50 ✓
- 3 days, $5946.44 equity, maxDay $2415.20, 50%: baseAmount $2415.20,
  cappedByFuture $5014.56 -> min = $2415.20 ✓

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-04-20 20:22:33 -05:00
co-authored by Claude Opus 4.6
parent c0d60dfe8d
commit 91a448750c
+10 -13
View File
@@ -109,16 +109,10 @@ export function computeDailyTarget(
path = 'reduced_day';
} else {
const maxDay = Math.max(...qualifyingDays.map((d) => d.pnl));
const realTarget = maxDay / consistency;
const needed = realTarget - totalProfit; // consistency calc stays on dailyPnL totalProfit
if (needed > maxDay) {
baseAmount = maxDay;
path = 'normal_day';
} else {
baseAmount = Math.max(0, needed);
path = 'reduced_day';
}
// Consistency-cap the daily target at maxDay (can't exceed maxDay without breaking consistency ratio).
// Let min-day block handle the lower bound and cappedByFuture logic.
baseAmount = maxDay;
path = 'normal_day';
}
// --- Min-day reservation (only when minDayPnL is a positive value) ---
@@ -139,9 +133,12 @@ export function computeDailyTarget(
// Cap: don't take more than what's available after reserving future days
const cappedByFuture = remaining - futureReserve;
// Target what's needed to stay on track for profitTarget (cappedByFuture), floored at minDayPnL unconditionally.
// If minDay × remainingDays >= remaining, we can coast on min-day (cappedByFuture < minDay → floor wins).
const amount = Math.max(effectiveMinDay, cappedByFuture);
// Target what's needed to stay on track for profitTarget (cappedByFuture), floored at minDayPnL.
// Cap at baseAmount when the consistency calc produced a positive value — ensures we don't
// exceed maxDay / (maxDay/consistency) constraint. When baseAmount is 0 (0/100% consistency
// or target already met), cappedByFuture drives the target directly.
const consistencyCap = baseAmount > 0 ? Math.min(baseAmount, cappedByFuture) : cappedByFuture;
const amount = Math.max(effectiveMinDay, consistencyCap);
return { amount: Math.round(amount * 100) / 100, path };
}