Pre-roll fills stay visible; holds survive restarts and judge fund amounts
Second review round (e496404,9b2d677): - Tradovate: past the 5 PM roll an old-dated cash record counts only what it gained since the roll (its realizedPnL as last seen while current is kept as the roll base), so tonight's fills booked onto it before Tradovate rolls the account stay visible — no re-trading a one-and-done account. A record this process never saw before the roll leaves the account waiting for the broker's roll (ROLL_PENDING, counted in play for stop-after-all). The 60s snapshot carries the roll base and can't undo a newer record the socket delivered. - A wipe's hold is kept in account_meta, so a restart onto a failing Cash History still holds the account. - A Cash History whose pre-request balance the last vouched-for baseline can't explain, and which booked nothing, holds the account instead of rebasing onto an unbooked payout. - Holds compare fund transactions by date and amount (a second payout on a date that already has one), and an in-flight hold is judged against the rows from before its report. - The saved baseline tracks the day's realized P&L and folds, so a restart judges against current figures; held refetches back off to an hour, and a balance hold no Cash History can check is released after an hour. - TopstepX: a fetched account is promoted only by a sync whose reconcileFunds actually checked the books (not one skipped for an open position), and a direct fetch awaits that sync, so wipe routes report the real outcome. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
9b2d677662
commit
088886ed73
+5
-1
@@ -381,6 +381,9 @@ function entryCommissionFrom(before: number, after: number, contracts: number):
|
||||
/** 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';
|
||||
/** Likewise for an account whose broker hasn't rolled its cash record to the
|
||||
* new trade date, when this process didn't see the old day end. */
|
||||
const ROLL_PENDING = "waiting for the broker to roll the account's day";
|
||||
|
||||
interface AccountEvaluation {
|
||||
eligible: boolean;
|
||||
@@ -431,6 +434,7 @@ function evaluateAccountForTrade(client: any, acc: { id: number; name: string; a
|
||||
// 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 };
|
||||
if (cash.pendingRoll) return { ...base, eligible: false, reason: ROLL_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.
|
||||
@@ -1214,7 +1218,7 @@ function hasRemainingConfiguredAccounts(): boolean {
|
||||
// during the session and before it opens alike (a restart between
|
||||
// the 5 PM roll and the open loads histories right then). Only
|
||||
// once the session has closed is a still-loading account let go.
|
||||
if (ev?.reason === HISTORY_PENDING && !isAfterSessionClose()) return true;
|
||||
if ((ev?.reason === HISTORY_PENDING || ev?.reason === ROLL_PENDING) && !isAfterSessionClose()) return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user