The welcome now carries a personId; it lands in the instance_id setting and rides on every hello and HTTP report from then on. The master keys the person by that uuid, so changing instance_name moves our history to the new name instead of starting a stranger. Read-only in Settings on purpose — editing it by hand would detach this machine from its person. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
119 lines
3.9 KiB
TypeScript
119 lines
3.9 KiB
TypeScript
/**
|
|
* Wire protocol for the control link to the master dashboard.
|
|
*
|
|
* Mirror of the block at the bottom of `autotrader-master/types.ts`, which is
|
|
* the source of truth. The two repos deploy independently, so change both
|
|
* together — and only ever by adding, since an instance and a master can be
|
|
* running different versions of this file at the same time.
|
|
*/
|
|
|
|
export interface AccountTypeStats {
|
|
accountTypeId: string | null;
|
|
label: string;
|
|
accountSize: number;
|
|
totalAccounts: number;
|
|
accountsTraded: number;
|
|
inTrade: number;
|
|
}
|
|
|
|
export interface FirmStats {
|
|
firm: string;
|
|
totalAccounts: number;
|
|
accountsTraded: number;
|
|
inTrade: number;
|
|
/** Per account type, summing to the firm's own totals. Optional so a master
|
|
* on an older build simply ignores it. */
|
|
accountTypes?: AccountTypeStats[];
|
|
}
|
|
|
|
export interface SchedulerState {
|
|
running: boolean;
|
|
action: 'Buy' | 'Sell' | 'Auto';
|
|
symbol: string;
|
|
lastRun: string | null;
|
|
intervalSeconds: number;
|
|
stopAfterAll?: boolean;
|
|
}
|
|
|
|
export interface AutomationSummary {
|
|
key: string;
|
|
label: string;
|
|
firm: string;
|
|
inputs: { id: string; label: string; min: number; max: number; default: number }[];
|
|
}
|
|
|
|
export interface InstanceCapabilities {
|
|
symbols: string[];
|
|
automations: AutomationSummary[];
|
|
runnerOnline: boolean;
|
|
}
|
|
|
|
// ── Firm catalog ─────────────────────────────────────────────────────────────
|
|
// Served by the master's public GET /api/firms/catalog and cached locally by
|
|
// lib/firm-catalog.ts. Credentials are per-machine and absent from all of it.
|
|
|
|
/** One account type as published by the master.
|
|
*
|
|
* The field names match `AccountConfig` in types.ts on purpose — that is what
|
|
* lets the trading code consume a catalog account type wherever it used to
|
|
* read a local account_configs row. */
|
|
export interface CatalogAccountType {
|
|
id: string;
|
|
firmId: string;
|
|
label: string;
|
|
prefix: string;
|
|
accountSize: number;
|
|
profitTarget: number;
|
|
consistency: number;
|
|
minDayPnL: number;
|
|
minTradingDays: number;
|
|
maxLoss: number;
|
|
maxPositionSize: number;
|
|
targetSameEquity: boolean;
|
|
withdrawalStages: { profit: number; consistency: number; minTradingDays: number }[];
|
|
/** ISO. Ties between two matching account types are broken by this. */
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface CatalogFirm {
|
|
id: string;
|
|
name: string;
|
|
/** Which platform the firm's accounts trade on. Only 'tradovate' firms get
|
|
* a client here; anything else is synced but sits idle until its trading
|
|
* logic exists. Older masters omit the field — treated as 'tradovate'. */
|
|
platform: 'tradovate' | 'topstepx';
|
|
bannedSymbols: string[];
|
|
accountTypes: CatalogAccountType[];
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface FirmCatalogPayload {
|
|
version: number;
|
|
updatedAt: string;
|
|
firms: CatalogFirm[];
|
|
}
|
|
|
|
export interface FirmCatalogUnchanged {
|
|
version: number;
|
|
updatedAt: string;
|
|
unchanged: true;
|
|
}
|
|
|
|
export type Command =
|
|
| { kind: 'trade'; action: 'Buy' | 'Sell' | 'Auto'; symbol: string; stopAfterAll?: boolean }
|
|
| { kind: 'stop-trading' }
|
|
| { kind: 'autobuyer-run'; automationId: string; inputs?: Record<string, number> }
|
|
| { kind: 'report-now' };
|
|
|
|
export type MasterMessage =
|
|
/** personId is the person's stable uuid; the instance stores it and
|
|
* presents it on later hellos, which is what makes a rename follow the
|
|
* person. */
|
|
| { type: 'welcome'; personId?: string }
|
|
| { type: 'command'; id: string; command: Command };
|
|
|
|
export type InstanceMessage =
|
|
| { type: 'hello'; instance: string; id?: string; capabilities: InstanceCapabilities }
|
|
| { type: 'report'; firms: FirmStats[]; scheduler: SchedulerState; capabilities?: InstanceCapabilities }
|
|
| { type: 'ack'; id: string; ok: boolean; result?: unknown; error?: string };
|