- DXtrade client (lib/dxtrade-class.ts): REST session login with lockout-safe
backoff, 60s sync of accounts/metrics/positions/orders/transfers, history and
fund transactions from cash transactions, day-start balance at the 22:00 UTC
reset, CLOSE-by-positionCode exits (native OCO group, else a stop-first
emulated pair), a cross-account hedge guard, stray-order reaper.
- Instrument selector: the firm's symbol map lists candidate symbols per CME
root; the cheapest tradable one per unit of recent hourly volatility wins
(spread + 2x commission [+ financing] / sigma).
- Fees: a firm's commission % of notional prices every fee off the fill; the
take-profit is solved in closed form so the leg nets its target.
- Hard daily loss limit per account type: every leg carries a stop keeping the
firm's day inside the limit less a 10% reserve and both fees (rounded in);
a green day never widens it; no room or a refused bracket flattens.
- Notional sizing where the platform prices positions: target-hold volatility
sizing or the symbol map's fixed notional, under a per-type notional cap.
- Every-day firms trade weekends/holidays; the scheduler runs lanes (futures,
one per DXtrade firm) with their own hours, flat gate, mutex and batches.
- The catalog sync skips platforms this build doesn't know instead of treating
them as Tradovate. One shared fireLeg replaces the duplicated batch/copy code.
- npm run check: fee/stop/sizing/hours/selector checks; scripts/dxtrade-smoke.mjs
confirms the API against a real login before trading.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sixth review round (8e66631):
- An entry of unknown outcome is judged against a good sync that STARTED
at least 90s after it was declared unknown (lastSyncStartedAt: TopstepX's
pass start, Tradovate's request time), not one that merely ended then —
a sequential pass can read the account before a late fill.
- Once the broker shows its fill (a position, or realized P&L moved), the
entry becomes an ordinary filled one instead of holding the account for
the rest of the day.
- It never settles while the broker still shows a working order on the
account: Tradovate now reads working orders from the sync snapshot, and
its fill-timeout cancel checks Tradovate's answer instead of assuming it.
- A second wipe (after a restart) keeps the pending wipe's pre-wipe fund
signature instead of overwriting it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
- 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>
Why the autotrader sometimes broke after a weekend until `pm2 restart`:
`next start` only logs uncaught errors, so nothing ever crashed, and a few
paths could leave a client dead for the life of the process.
Tradovate: a closed socket scheduled exactly one re-login, with no catch —
one failure during weekend maintenance (or a rate-limit penalty returned as
a 200 without a token) and the client never came back. connectAndAuth is now
a single-flight loop that never throws: jittered backoff capped at 5 min,
penalty tickets waited out, captcha demands backed off. A 15s watchdog
abandons silent, never-authorized or stuck-closing sockets and stale syncs;
renewal falls back to a fresh login; orders fail fast (OrderNotPlacedError)
on a dead socket and time out instead of hanging; a bad sync answer no
longer wipes accounts and positions.
TopstepX: hub start/stop/invoke and every REST call are bounded; a wedged
hub is discarded and rebuilt; a stuck sync is superseded after 3 min;
re-login no longer tears down the sync loop; a watchdog re-logs when syncs
go stale; a no-fill timeout cancels the order.
Scheduler: one unready client used to hold every firm forever. It now holds
the tick for a 10-minute grace, then trades the other firms without it.
Per-firm try/catch in batch collection, one batch at a time, accounts marked
in flight, legs un-counted only when the entry never reached the broker, and
the scheduler starts before the first batch fires.
Boot and supervision: instrumentation.ts boots the process at server start
(it used to wait for the first dashboard request); a supervisor rebuilds a
client that has been unhealthy for 20 min (not a TopstepX one holding a
position); broker HTTP calls default to a 60s timeout; GET /api/health shows
each client's liveness and the scheduler's last decision. Shared state the
eager boot would otherwise split across bundles lives on globalThis. Logs no
longer carry access tokens or whole AxiosErrors (which include the encoded
Tradovate password).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cycleCompletion() says whether today's P&L finished the current cycle
(profit target, consistency and minimum days all met) — projectPerfectPath's
completion probe run without and with today. The reporter counts those as
`completed` (a subset of targetHit) and sends their names, so the master
can keep an account a firm erases after it passes. Checked ahead of the
lockout branch: a firm locking a passed account is no DLL loss. The local
dashboard shows them with a purple Completed pill.
Because the master keeps a completion for good, doubtful reads stay
'none': weekends, a Monday with a weekend-dated row, the first minutes
after the 5 PM roll, and history that hasn't freshly loaded.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- TopstepXClient (ProjectX Gateway): API-key auth, SignalR user hub,
Trade/search daily P&L, emulated OCO exits, books-invariant
withdrawal detection for $0-start accounts
- Platform-aware client pool, credentials (api_key column), and
credential form; $0-size account types match by prefix alone
- Drain stages: min-day ($5-$15 randomized) MNQ legs for the
configured days, then wait for the 50% withdrawal; stage pills
show 'Stage N – Drain'
- Account calendar projects the perfect path: future days book their
planned targets, simulated 50% withdrawals, payout marker
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>