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>
53 lines
2.0 KiB
TypeScript
53 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,
|
|
minLegs: a.minLegs,
|
|
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 });
|
|
}
|
|
}
|