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:
co-authored by
Claude Opus 5.5
parent
61384c9fa6
commit
77d8c2ecdb
@@ -355,6 +355,10 @@ async function legInstrument(
|
||||
|
||||
// ── per-account trade evaluation (shared by runTrade / copyTrade / hasRemaining…) ──
|
||||
|
||||
/** The ineligible reason for an account whose history isn't loaded yet — still
|
||||
* in play for stop-after-all, since it trades once the fetch lands. */
|
||||
const HISTORY_PENDING = 'history not loaded yet — waiting for the fetch';
|
||||
|
||||
interface AccountEvaluation {
|
||||
eligible: boolean;
|
||||
reason: string;
|
||||
@@ -400,6 +404,10 @@ function evaluateAccountForTrade(client: any, acc: { id: number; name: string; a
|
||||
// Another batch is placing this account's order right now; its position
|
||||
// won't show until the fill comes back, so the check above can't see it.
|
||||
if (runtime().accountsInFlight.has(acc.id)) return { ...base, eligible: false, reason: 'order in flight' };
|
||||
// History this client hasn't loaded (a restart, a rebuild, a wipe, a new
|
||||
// account) or that a payout has overtaken would plan the account as a
|
||||
// fresh stage-1 first day: an oversized leg, or a re-opened finished cycle.
|
||||
if (!client.historyReady(acc.id)) return { ...base, eligible: false, reason: HISTORY_PENDING };
|
||||
|
||||
// Obfuscation stops: a stop-out shows as realized P&L falling short of the
|
||||
// legs fired today — the day is booked; the make-back ride is tomorrow.
|
||||
@@ -1166,6 +1174,9 @@ function hasRemainingConfiguredAccounts(): boolean {
|
||||
|
||||
const ev = evaluateAccountForTrade(client, acc, tradeDate);
|
||||
if (ev?.eligible) return true;
|
||||
// Waiting on its history, not done: it may still owe today's trade.
|
||||
// Only while the session is open, like the unready firms above.
|
||||
if (ev?.reason === HISTORY_PENDING && !isInNoTradeWindow()) return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user