diff --git a/app/api/state/route.ts b/app/api/state/route.ts
index 2065fac..970782b 100644
--- a/app/api/state/route.ts
+++ b/app/api/state/route.ts
@@ -3,7 +3,10 @@ import { loadDailyPnL } from '@/lib/db';
import { getClients } from '@/lib/clients';
import { getCachedCatalog } from '@/lib/firm-catalog';
import { getAccountConfig, getInferredSize, matchAccountType } from '@/lib/account-type-resolver';
-import { combineCmeSessions, computeDayPlan, resolveEffectiveConfig, currentTradeDateCT, LEG_COMPLETION_EPSILON } from '@/lib/trading-logic';
+import {
+ combineCmeSessions, computeDayPlan, resolveEffectiveConfig, currentTradeDateCT,
+ BIG_DAY_THRESHOLD, FIRST_DAY_STOP, LEG_COMPLETION_EPSILON, MIN_DAY_STOP_MULT,
+} from '@/lib/trading-logic';
export async function GET() {
try {
@@ -66,6 +69,7 @@ export async function GET() {
let dailyTarget: { amount: number; path: 'first_day' | 'normal_day' | 'reduced_day' } | null = null;
let remainingToday: number | null = null;
let effectiveProfitTarget: number | null = null;
+ let nextStop: number | null = null;
if (cfg && !isDead) {
const effective = resolveEffectiveConfig(
cfg.profitTarget,
@@ -85,6 +89,27 @@ export async function GET() {
dailyTarget = plan ? { amount: plan.dayTarget, path: plan.path } : null;
remainingToday = plan?.remainingToday ?? null;
+ // The stop the next trade would carry under the obfuscation
+ // options, mirroring obfuscationStopDollars in auto-trade:
+ // day 1 keeps the day's net floor at −$1,000, min days stop
+ // at 2× the target, and the day after a loss rides stopless.
+ if (plan && (cfg.firstDayStop || cfg.minDayStop)) {
+ const prior = dailyPnL
+ .filter((d) => d.date < combined.tradeDate && d.pnl !== 0)
+ .sort((a, b) => a.date.localeCompare(b.date));
+ const recoveryDay = prior.length > 0 && prior[prior.length - 1].pnl < 0;
+ if (!recoveryDay) {
+ let stop = Infinity;
+ if (cfg.firstDayStop && prior.length === 0) {
+ stop = Math.max(0, Math.round((FIRST_DAY_STOP + combined.realizedPnL) * 100) / 100);
+ }
+ if (cfg.minDayStop && plan.dayTarget <= BIG_DAY_THRESHOLD) {
+ stop = Math.min(stop, MIN_DAY_STOP_MULT * plan.dayTarget);
+ }
+ if (Number.isFinite(stop) && stop > 0) nextStop = Math.round(stop * 100) / 100;
+ }
+ }
+
// 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.
@@ -168,6 +193,7 @@ export async function GET() {
targetHit,
stage,
dailyTarget,
+ nextStop,
remainingToday,
effectiveProfitTarget,
dailyPnL,
diff --git a/app/page.tsx b/app/page.tsx
index c0c2059..3499b30 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -350,7 +350,12 @@ function AccountRow({ account, firm, hideDead, privacy, onAssigned }: {
{account.dailyTarget && (
- ${fmt(account.dailyTarget.amount)} today
+
+ ${fmt(account.dailyTarget.amount)} today
+ {account.nextStop !== null && (
+ · stop ${fmt(account.nextStop)}
+ )}
+
)}
diff --git a/types.ts b/types.ts
index 156ea55..0049e6a 100644
--- a/types.ts
+++ b/types.ts
@@ -56,6 +56,10 @@ export interface AccountState {
stage: number;
/** 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;
+ /** Dollars the next trade may lose before its obfuscation stop fires.
+ * null = the next trade rides stopless (options off, big non-first day,
+ * or a make-back day after a loss). */
+ nextStop: number | 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. */