{ try { return JSON.parse(cfg.withdrawal_stages ?? '[]'); } catch { return []; } })();
const effective = resolveEffectiveConfig(
@@ -52,6 +53,15 @@ export async function GET() {
const equityProfit = cash.amount - cfg.account_size;
const target = computeDailyTarget(effective.profitTarget, effective.consistency, dailyPnL, cfg.min_day_pnl, effective.minTradingDays, equityProfit);
dailyTarget = target;
+
+ // Effective profit target = max(stage target, consistency realTarget).
+ // If a big day forces the consistency rule, the account must reach maxDay/consistency
+ // in total trading profit for the stage, not just profitTarget.
+ const qualifying = cfg.min_day_pnl === 0 ? dailyPnL : dailyPnL.filter((d) => d.pnl >= cfg.min_day_pnl);
+ const maxDay = qualifying.length > 0 ? Math.max(...qualifying.map((d) => d.pnl)) : 0;
+ const consistencyReal = (effective.consistency > 0 && effective.consistency < 1 && maxDay > 0)
+ ? maxDay / effective.consistency : 0;
+ effectiveProfitTarget = Math.max(effective.profitTarget, consistencyReal);
// Condition 1: profit target already exceeded (target=0), still need days → any activity counts
// Condition 2: target > 0 → must have made at least the computed daily target
if (target) {
@@ -75,6 +85,7 @@ export async function GET() {
totalProfit,
targetHit,
dailyTarget,
+ effectiveProfitTarget,
dailyPnL,
fullDailyPnL: client.fullDailyPnL?.[acc.id] ?? loadDailyPnL(acc.id),
fundTransactions: displayFundTxns,
diff --git a/app/page.tsx b/app/page.tsx
index d0d1fd5..5728a76 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -135,7 +135,7 @@ function AccountRow({ account, firm, hideDead, privacy }: { account: AccountStat
|
- ${cfg?.profitTarget?.toLocaleString() ?? '—'}
+ ${(account.effectiveProfitTarget ?? cfg?.profitTarget ?? 0).toLocaleString(undefined, { maximumFractionDigits: 2 })}
{account.dailyTarget && (
${fmt(account.dailyTarget.amount)} today
)}
diff --git a/types.ts b/types.ts
index a44c5bd..ec98a82 100644
--- a/types.ts
+++ b/types.ts
@@ -36,6 +36,8 @@ export interface AccountState {
targetHit: boolean;
/** Next trading day's target, computed server-side. null when account is dead or config is missing. */
dailyTarget: { amount: number; path: 'first_day' | 'normal_day' | 'reduced_day' } | null;
+ /** Actual profit target to hit — max(stage profit target, consistency realTarget = maxDay/consistency). */
+ effectiveProfitTarget: number | null;
/** Current cycle daily P&L — used for target calculations. */
dailyPnL: { date: string; pnl: number }[];
/** Full P&L history across all cycles — used for calendar and equity curve display. */
|