Trade only on loaded history; catch early TopstepX fills; fix SI/M2K point values

- Both clients track which accounts this process has loaded history for
  (historyReady). An account restarted, rebuilt, wiped or newly listed is
  ineligible until its fetch lands, instead of trading as a fresh stage-1
  first day; a failed fetch with no cache no longer reads as empty history.
  Waiting accounts get a targeted fetch on the next sync.
- Tradovate holds an account whose start-of-day balance moves without a fill
  (a payout between hourly Cash History runs) until a Cash History books it,
  so a payout-pending account isn't re-traded on its ended cycle.
- Wipe routes forget history through the client and count accounts whose
  history didn't come back as failures.
- TopstepX sendOrder picks up a fill that arrived before the place response,
  and its REST backstop uses the documented Trade/search and Order/search.
- POINT_VALUES: SI 5000 (was 50), M2K 5 (was 10).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-09-24 17:04:09 -05:00
co-authored by Claude Opus 5.5
parent 61384c9fa6
commit 77d8c2ecdb
7 changed files with 292 additions and 46 deletions
+8 -10
View File
@@ -19,20 +19,18 @@ export async function POST() {
let failedAccounts = 0;
await Promise.all(clients.map(async (client) => {
// Forgotten, the accounts read unloaded and stay out of trading
// until the refetch below (or, if it fails, a later one) lands.
const ids = client.accountList.map((account) => account.id);
for (const account of client.accountList) {
wipeAccountData(account.id);
delete client.dailyPnL[account.id];
delete client.fullDailyPnL[account.id];
delete client.daysTraded[account.id];
delete client.priorProfit[account.id];
delete client.lastFundDates[account.id];
delete client.fundTransactions[account.id];
delete client.lastFetchErrors[account.name];
delete client.lastFetchRaw[account.name];
client.forgetHistory(account.id, account.name);
wiped++;
}
const result = await client.fetchDaysTraded();
failedAccounts += result.failedAccounts;
await client.fetchDaysTraded();
// Counted from the result, not the fetch's own tally: a client with
// no session fetches nothing and reports no failures.
failedAccounts += ids.filter((id) => !client.historyReady(id)).length;
}));
return NextResponse.json({ ok: true, wiped, failedAccounts });