Reporter: name the accounts whose final day completed their cycle
cycleCompletion() says whether today's P&L finished the current cycle (profit target, consistency and minimum days all met) — projectPerfectPath's completion probe run without and with today. The reporter counts those as `completed` (a subset of targetHit) and sends their names, so the master can keep an account a firm erases after it passes. Checked ahead of the lockout branch: a firm locking a passed account is no DLL loss. The local dashboard shows them with a purple Completed pill. Because the master keeps a completion for good, doubtful reads stay 'none': weekends, a Monday with a weekend-dated row, the first minutes after the 5 PM roll, and history that hasn't freshly loaded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
a47a86a59c
commit
acb8879575
+21
-1
@@ -3,8 +3,9 @@ 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 { historyFresh } from '@/lib/platform-client';
|
||||
import {
|
||||
combineCmeSessions, computeDayPlan, resolveEffectiveConfig, currentTradeDateCT,
|
||||
combineCmeSessions, computeDayPlan, cycleCompletion, resolveEffectiveConfig, currentTradeDateCT,
|
||||
BIG_DAY_THRESHOLD, FIRST_DAY_STOP, LEG_COMPLETION_EPSILON, MIN_DAY_STOP_MULT,
|
||||
} from '@/lib/trading-logic';
|
||||
|
||||
@@ -174,6 +175,24 @@ export async function GET() {
|
||||
}
|
||||
}
|
||||
|
||||
// Today finished the cycle — the reporter's check and guards,
|
||||
// so this pill and the master's purple count agree.
|
||||
let completed = false;
|
||||
const historyLoaded = client.dailyPnL[acc.id] !== undefined
|
||||
&& client.fundTransactions?.[acc.id] !== undefined;
|
||||
if (cfg && effective && historyLoaded && historyFresh(client, acc) && !client.positions[acc.id]) {
|
||||
completed = cycleCompletion({
|
||||
accountId: acc.id,
|
||||
rawTradeDate: tradeDate,
|
||||
cycleDailyPnL: client.dailyPnL[acc.id],
|
||||
rawRealizedPnL: cash.realizedPnL,
|
||||
combineCmeHolidays: cfg.combineCmeHolidays,
|
||||
effective,
|
||||
equityProfit: cash.amount - cfg.accountSize,
|
||||
splitEnabled: cfg.splitEnabled,
|
||||
}) === 'today';
|
||||
}
|
||||
|
||||
return {
|
||||
id: acc.id,
|
||||
name: acc.name,
|
||||
@@ -195,6 +214,7 @@ export async function GET() {
|
||||
autoLiqThreshold,
|
||||
totalProfit,
|
||||
targetHit,
|
||||
completed,
|
||||
stage,
|
||||
// Current stage is a drain stage — dashboards label it "Stage N – Drain".
|
||||
stageDrain: effective?.drain ?? false,
|
||||
|
||||
+13
-10
@@ -10,9 +10,10 @@ type SortDir = 'asc' | 'desc';
|
||||
|
||||
function statusRank(account: AccountState): number {
|
||||
if (isAccountDead(account)) return 0;
|
||||
if (account.completed) return 5; // Completed — finished its cycle today
|
||||
if (!account.active) return 1;
|
||||
if (!account.positionDirection) {
|
||||
if (account.targetHit) return 4; // Target Hit — most accomplished
|
||||
if (account.targetHit) return 4; // Target Hit — next to Completed
|
||||
return 2; // Flat
|
||||
}
|
||||
return 3; // In Trade
|
||||
@@ -384,15 +385,17 @@ function AccountRow({ account, firm, hideDead, privacy, onAssigned }: {
|
||||
<div className="flex items-center justify-between">
|
||||
{dead
|
||||
? <span className="inline-block px-2.5 py-0.5 rounded-full text-xs font-semibold bg-slate-800 text-white">Dead</span>
|
||||
: !account.active
|
||||
? <span className="inline-block px-2.5 py-0.5 rounded-full text-xs font-semibold bg-red-100 text-red-700">Hit DLL</span>
|
||||
: account.positionDirection
|
||||
? <span className={`inline-block px-2.5 py-0.5 rounded-full text-xs font-semibold ${account.positionDirection === 'long' ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'}`}>{account.positionDirection === 'long' ? 'Long' : 'Short'}</span>
|
||||
: account.personalDll
|
||||
? <span className="inline-block px-2.5 py-0.5 rounded-full text-xs font-semibold bg-amber-100 text-amber-700" title="Booked the day red via its own stop — make-back rides next session">Personal DLL</span>
|
||||
: account.targetHit
|
||||
? <span className="inline-block px-2.5 py-0.5 rounded-full text-xs font-semibold bg-green-100 text-green-700">Target Hit</span>
|
||||
: <span className="inline-block px-2.5 py-0.5 rounded-full text-xs font-semibold bg-slate-100 text-slate-500">Flat</span>}
|
||||
: account.completed
|
||||
? <span className="inline-block px-2.5 py-0.5 rounded-full text-xs font-semibold bg-purple-100 text-purple-700" title="Finished its cycle today — target, consistency and min days met">Completed</span>
|
||||
: !account.active
|
||||
? <span className="inline-block px-2.5 py-0.5 rounded-full text-xs font-semibold bg-red-100 text-red-700">Hit DLL</span>
|
||||
: account.positionDirection
|
||||
? <span className={`inline-block px-2.5 py-0.5 rounded-full text-xs font-semibold ${account.positionDirection === 'long' ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'}`}>{account.positionDirection === 'long' ? 'Long' : 'Short'}</span>
|
||||
: account.personalDll
|
||||
? <span className="inline-block px-2.5 py-0.5 rounded-full text-xs font-semibold bg-amber-100 text-amber-700" title="Booked the day red via its own stop — make-back rides next session">Personal DLL</span>
|
||||
: account.targetHit
|
||||
? <span className="inline-block px-2.5 py-0.5 rounded-full text-xs font-semibold bg-green-100 text-green-700">Target Hit</span>
|
||||
: <span className="inline-block px-2.5 py-0.5 rounded-full text-xs font-semibold bg-slate-100 text-slate-500">Flat</span>}
|
||||
<Link
|
||||
href={`/accounts/${account.id}`}
|
||||
className="text-slate-400 hover:text-slate-600 hover:bg-slate-200 p-1 rounded-md transition-colors inline-flex"
|
||||
|
||||
Reference in New Issue
Block a user