Show the next trade's stop next to the daily target
Stop-enabled accounts show an amber "stop $X" beside the day target: the day-1 net floor (live against realized P&L) or 2x a min-day's target, mirroring exactly what the trade path will place — and nothing when the next trade rides stopless. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
6685a75864
commit
1bca441247
+27
-1
@@ -3,7 +3,10 @@ import { loadDailyPnL } from '@/lib/db';
|
|||||||
import { getClients } from '@/lib/clients';
|
import { getClients } from '@/lib/clients';
|
||||||
import { getCachedCatalog } from '@/lib/firm-catalog';
|
import { getCachedCatalog } from '@/lib/firm-catalog';
|
||||||
import { getAccountConfig, getInferredSize, matchAccountType } from '@/lib/account-type-resolver';
|
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() {
|
export async function GET() {
|
||||||
try {
|
try {
|
||||||
@@ -66,6 +69,7 @@ export async function GET() {
|
|||||||
let dailyTarget: { amount: number; path: 'first_day' | 'normal_day' | 'reduced_day' } | null = null;
|
let dailyTarget: { amount: number; path: 'first_day' | 'normal_day' | 'reduced_day' } | null = null;
|
||||||
let remainingToday: number | null = null;
|
let remainingToday: number | null = null;
|
||||||
let effectiveProfitTarget: number | null = null;
|
let effectiveProfitTarget: number | null = null;
|
||||||
|
let nextStop: number | null = null;
|
||||||
if (cfg && !isDead) {
|
if (cfg && !isDead) {
|
||||||
const effective = resolveEffectiveConfig(
|
const effective = resolveEffectiveConfig(
|
||||||
cfg.profitTarget,
|
cfg.profitTarget,
|
||||||
@@ -85,6 +89,27 @@ export async function GET() {
|
|||||||
dailyTarget = plan ? { amount: plan.dayTarget, path: plan.path } : null;
|
dailyTarget = plan ? { amount: plan.dayTarget, path: plan.path } : null;
|
||||||
remainingToday = plan?.remainingToday ?? 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).
|
// Effective profit target = max(stage target, consistency realTarget).
|
||||||
// If a big day forces the consistency rule, the account must reach maxDay/consistency
|
// If a big day forces the consistency rule, the account must reach maxDay/consistency
|
||||||
// in total trading profit for the stage, not just profitTarget.
|
// in total trading profit for the stage, not just profitTarget.
|
||||||
@@ -168,6 +193,7 @@ export async function GET() {
|
|||||||
targetHit,
|
targetHit,
|
||||||
stage,
|
stage,
|
||||||
dailyTarget,
|
dailyTarget,
|
||||||
|
nextStop,
|
||||||
remainingToday,
|
remainingToday,
|
||||||
effectiveProfitTarget,
|
effectiveProfitTarget,
|
||||||
dailyPnL,
|
dailyPnL,
|
||||||
|
|||||||
+6
-1
@@ -350,7 +350,12 @@ function AccountRow({ account, firm, hideDead, privacy, onAssigned }: {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{account.dailyTarget && (
|
{account.dailyTarget && (
|
||||||
<span className="text-xs text-slate-400">${fmt(account.dailyTarget.amount)} today</span>
|
<span className="text-xs text-slate-400">
|
||||||
|
${fmt(account.dailyTarget.amount)} today
|
||||||
|
{account.nextStop !== null && (
|
||||||
|
<span className="text-amber-600" title="The next trade's stop — dollars it may lose before booking the day"> · stop ${fmt(account.nextStop)}</span>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -56,6 +56,10 @@ export interface AccountState {
|
|||||||
stage: number;
|
stage: number;
|
||||||
/** Next trading day's target, computed server-side. null when account is dead or config is missing. */
|
/** 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;
|
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). */
|
/** Actual profit target to hit — max(stage profit target, consistency realTarget = maxDay/consistency). */
|
||||||
effectiveProfitTarget: number | null;
|
effectiveProfitTarget: number | null;
|
||||||
/** Current cycle daily P&L — used for target calculations. */
|
/** Current cycle daily P&L — used for target calculations. */
|
||||||
|
|||||||
Reference in New Issue
Block a user