One-and-done counts confirmed fills; holds need a persistent refusal; wipes keep their yardstick
Fourth review round (52ed9c7):
- The one-and-done guard counts only entries the broker confirmed filled,
so an entry that timed out or was rejected unfilled no longer benches the
account for the day.
- TopstepX: an account is promoted only by a sync that actually checked its
funds; one with no account type stays out (not traded) without costing a
sync per pass, and once typed waits for that check. Wipe routes don't
count untyped accounts as failures.
- Tradovate: an unchecked balance-hold release needs Cash History refused
for a full hour straight (a 4xx other than 401/403/408/429, or an answer
without data); any other outcome resets it, so one stray reply during a
5xx outage can't release a payout.
- A wipe keeps the pre-wipe baseline and fund rows as its yardstick: the
rebuild must explain today's balance against them, so a payout the
rebuilt report hasn't booked yet stays held.
- The roll base of an unrolled record is kept per trade date in
account_meta, so a restart later the same trade date counts from the same
point instead of from a value that already includes the day's fills.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
52ed9c75e4
commit
1eb0736fbe
@@ -894,10 +894,11 @@ export class TopstepXClient implements PlatformClient {
|
||||
console.error(`[topstepx] fund reconcile failed for ${acc.name}: ${errorMessage(err)}`);
|
||||
}
|
||||
// A freshly fetched history is tradable once a fresh pass has
|
||||
// actually checked the funds behind the balance (a skipped
|
||||
// check — a position still open — waits for a later pass).
|
||||
const ours = Boolean(getAccountConfig(acc.id).accountType);
|
||||
if ((reconciled || !ours) && this.reconcilePendingIds.delete(acc.id)) this.historyLoadedIds.add(acc.id);
|
||||
// actually checked the funds behind the balance. A skipped
|
||||
// check waits for a later pass — a position still open, or no
|
||||
// account type yet (not traded until one is assigned, and then
|
||||
// only after a check).
|
||||
if (reconciled && this.reconcilePendingIds.delete(acc.id)) this.historyLoadedIds.add(acc.id);
|
||||
|
||||
try {
|
||||
this.updateMllFloor(acc);
|
||||
@@ -1290,8 +1291,11 @@ export class TopstepXClient implements PlatformClient {
|
||||
// rather than leave them out for up to a minute, and before returning,
|
||||
// so a wipe route reads the result. (The firm's first pass syncs from
|
||||
// maybeFetchDaysTraded once readiness allows.)
|
||||
// Only ours: an account with no type stays pending without costing
|
||||
// a sync on every pass.
|
||||
const waiting = () => this.accountList.some((a) => this.reconcilePendingIds.has(a.id)
|
||||
&& (!onlyAccountIds || onlyAccountIds.includes(a.id)));
|
||||
&& (!onlyAccountIds || onlyAccountIds.includes(a.id))
|
||||
&& Boolean(getAccountConfig(a.id).accountType));
|
||||
if (waiting() && this.historyLoaded && !this.intentionalDisconnect) {
|
||||
await this.requestSync(); // a pass already running may have gone past them
|
||||
if (waiting()) await this.requestSync();
|
||||
|
||||
Reference in New Issue
Block a user