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:
Brandon Li
2026-09-24 18:45:45 -05:00
co-authored by Claude Opus 5.5
parent 9b2d677662
commit 088886ed73
4 changed files with 204 additions and 107 deletions
+4 -1
View File
@@ -23,7 +23,10 @@ export interface PlatformContract {
export interface PlatformClient {
accountList: PlatformAccount[];
accountCashBalances: { [accountId: number]: { amount: number; realizedPnL: number } };
/** realizedPnL is today's. pendingRoll (Tradovate): the broker still shows
* the ended day's record and today's share of it can't be told apart —
* the account waits for the broker to roll it. */
accountCashBalances: { [accountId: number]: { amount: number; realizedPnL: number; pendingRoll?: boolean } };
positions: {
[accountId: number]: {
contractId: number | string;