Files
autofirmer-expanded/types.ts
T
Brandon LiandClaude Opus 5.5 acb8879575 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>
2026-09-23 12:28:41 -05:00

111 lines
5.6 KiB
TypeScript

export interface AccountConfig {
/** Master's account type id — what a manual assignment pins to. */
id: string;
label: string;
prefix: string;
profitTarget: number;
consistency: number;
minDayPnL: number;
minTradingDays: number;
accountSize: number;
maxLoss: number; // 0 = no limit; positive = account is "Dead" when loss exceeds this
maxPositionSize: number; // 0 = no limit; positive = max contracts per trade
targetSameEquity: boolean; // if true, reduce profitTarget by priorProfit after withdrawal
splitEnabled: boolean; // false = big days trade as one unsplit leg instead of random ≥$500 pieces
minLegs: number; // big days (> $1,700) must carve at least this many legs (0 = however the carve falls)
firstDayStop: boolean; // first cycle day carries a $1,000 account stop - books red and ends
minDayStop: boolean; // min-day trades carry a 2x-target stop; next day after a loss rides stopless
combineCmeHolidays: boolean; // true = CME holiday sessions count with the next full trading day (Apex-style)
withdrawalStages: { profit: number; consistency: number; minTradingDays: number; drain?: boolean; minDayPnL?: number; withdrawalPct?: number; payoutCap?: number }[]; // per-stage fresh profit + consistency (empty = use base values); drain = spam-withdraw stage
/** Payout model, from the master's payout settings (absent on old masters):
* withdraw withdrawalPct of balance (capped at payoutCap) per cycle,
* receive profitSplit of the gross; trailingDrawdown feeds the ruin
* probabilities. payoutable=false means completing the target just
* PASSES the account (an eval) rather than paying out. */
payoutable?: boolean;
withdrawalPct?: number;
payoutCap?: number;
profitSplit?: number;
trailingDrawdown?: number;
}
export interface FirmConfig {
/** Master's firm id (uuid). */
id: string;
firm: string;
/** Which platform the firm's accounts trade on — decides both which client
* drives it and which credential fields the dashboard asks for. */
platform: 'tradovate' | 'topstepx';
/** Blank when this machine has no credentials for the firm. */
username: string;
/** True once the platform's credentials are stored locally — Tradovate
* username + password, or a TopstepX API key. Firms without them are
* shown greyed out with an inline credential form. */
hasCredentials: boolean;
bannedSymbols: string[];
/** The firm's account types, straight from the catalog. Doubles as the
* option list for a manual account-type override. */
accounts: AccountConfig[];
catalogUpdatedAt: string;
}
export interface AccountState {
id: number;
name: string;
active: boolean;
amount: number;
realizedPnL: number;
daysTraded: number;
positionDirection: 'long' | 'short' | null;
/** Balance floor from Tradovate's auto-liquidation profile (0 = not set) */
autoLiqThreshold: number;
/** Sum of all historical daily P&L entries */
totalProfit: number;
/** True when today's realizedPnL has met or exceeded the computed daily target */
targetHit: boolean;
/** True when a stop-enabled account booked its day red via its own stop —
* the personal DLL. It stands down until the next session's make-back. */
personalDll: boolean;
/** True when today's trading finished the current cycle — profit target,
* consistency and minimum days all met (cycleCompletion 'today'). Only
* the final day; the firm may lock or remove the account afterwards. */
completed: boolean;
/** Current stage = 1 + number of withdrawals (negative fund transactions). Stage 1 = fresh account. */
stage: number;
/** True when the current stage is a drain stage (spam-withdraw mode). */
stageDrain: 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;
/** 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. */
dailyPnL: { date: string; pnl: number }[];
/** Full P&L history across all cycles — used for calendar and equity curve display. */
fullDailyPnL: { date: string; pnl: number }[];
/** Fund transactions (deposits/withdrawals) — used by the calendar and equity curve. */
fundTransactions: { date: string; amount: number }[];
/** Master account type this account resolved to. null = Unassigned. */
accountTypeId: string | null;
accountTypeLabel: string | null;
assignmentSource: 'manual' | 'auto' | 'unassigned';
/** The resolved config inlined, so client components need no second lookup. */
accountType: AccountConfig | null;
/** Size from the initial funding transaction; null until reports return. */
inferredAccountSize: number | null;
/** True when more than one account type matched and updatedAt decided it. */
accountTypeAmbiguous: boolean;
}
export interface FirmState {
/** Master's firm id — join state to config on this, not on the name, which
* changes the moment someone renames a firm on the master. */
firmId: string;
firm: string;
connected: boolean;
accounts: AccountState[];
}