Account types with the catalog's new combineCmeHolidays flag are read through a combined-day view: holiday-session P&L entries fold into the next full trading day (computed from the federal-holiday rules, so any year works), the day count matches how the firm records it (Apex: Sun/ Mon/Tue around a Monday holiday is ONE day), and on the later sessions of the stretch the earlier sessions' booked P&L carries into realized — so day targets, already-traded gates, target-hit status and the panel's day P&L all treat the stretch as a single day. Off by default; older masters that don't send the flag behave exactly as before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
52 lines
2.0 KiB
TypeScript
52 lines
2.0 KiB
TypeScript
import { NextResponse } from 'next/server';
|
|
import { getCachedCatalog } from '@/lib/firm-catalog';
|
|
import { getCredentials } from '@/lib/db';
|
|
import type { FirmConfig } from '@/types';
|
|
|
|
/**
|
|
* The firms this machine knows about — the master's catalog, annotated with
|
|
* whether credentials for each are stored here.
|
|
*
|
|
* Firms are created and edited on the master dashboard; there is no POST. The
|
|
* only writable thing per firm is its credentials, at
|
|
* PUT /api/firms/[id]/credentials.
|
|
*
|
|
* The stored password is deliberately not returned. It used to be, and nothing
|
|
* ever read it.
|
|
*/
|
|
export async function GET() {
|
|
try {
|
|
const result: FirmConfig[] = getCachedCatalog().map((firm) => {
|
|
const creds = getCredentials(firm.id);
|
|
return {
|
|
id: firm.id,
|
|
firm: firm.name,
|
|
username: creds?.username ?? '',
|
|
hasCredentials: !!creds,
|
|
bannedSymbols: firm.bannedSymbols,
|
|
accounts: firm.accountTypes.map((a) => ({
|
|
id: a.id,
|
|
label: a.label,
|
|
prefix: a.prefix,
|
|
profitTarget: a.profitTarget,
|
|
consistency: a.consistency,
|
|
minDayPnL: a.minDayPnL,
|
|
minTradingDays: a.minTradingDays,
|
|
accountSize: a.accountSize,
|
|
maxLoss: a.maxLoss,
|
|
maxPositionSize: a.maxPositionSize,
|
|
targetSameEquity: a.targetSameEquity,
|
|
splitEnabled: a.splitEnabled,
|
|
combineCmeHolidays: a.combineCmeHolidays,
|
|
withdrawalStages: a.withdrawalStages,
|
|
})),
|
|
catalogUpdatedAt: firm.updatedAt,
|
|
};
|
|
});
|
|
return NextResponse.json(result);
|
|
} catch (err) {
|
|
console.error('[GET /api/firms]', err);
|
|
return NextResponse.json({ error: 'Failed to fetch firms' }, { status: 500 });
|
|
}
|
|
}
|