Files
autofirmer-expanded/types.ts
T
Brandon LiandClaude Fable 5 ae0f93a44f Honor the catalog's min-legs setting and carve $500 pieces
Big days (> the $1,700 split threshold) must carve at least the account
type's minLegs from the catalog — pickLegAmount reserves the minimum
piece for each leg still owed, forcing a carve even once the residual
dips below the threshold, clamped to what the pieces allow. Days at or
below the threshold still trade as one leg. The smallest split piece
drops from $800 to $500. An older master without the field means no
minimum.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-11 15:32:40 -05:00

82 lines
3.8 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)
combineCmeHolidays: boolean; // true = CME holiday sessions count with the next full trading day (Apex-style)
withdrawalStages: { profit: number; consistency: number; minTradingDays: number }[]; // per-stage fresh profit + consistency (empty = use base values)
}
export interface FirmConfig {
/** Master's firm id (uuid). */
id: string;
firm: string;
/** Blank when this machine has no credentials for the firm. */
username: string;
/** True once a Tradovate username and password are stored locally. 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;
/** Current stage = 1 + number of withdrawals (negative fund transactions). Stage 1 = fresh account. */
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;
/** 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[];
}