Vest (next.vestmarkets.com) is a perps prop firm: index, metal and energy
perps on CME hours, plus stocks, FX and crypto. It joins as a fourth
platform, 'vest', on the DXtrade engine paths. Those are now keyed by
isNotionalPlatform() instead of === 'dxtrade': the firm's own symbols,
percent fees, notional sizing from volatility, and a scheduler lane of its
own.
- Login is relayed, not stored. Vest signs people in with Google through
Privy and renews the session with a device key the browser won't export.
Extension 0.17.0's vest-relay.js reads the token the Vest app renews for
itself (~15 min). It renews nothing, so the tab is never logged out. The
background script posts that token to POST /api/vest/session, which holds
it in memory only. With no Vest tab open on a machine that trades Vest,
the extension opens one.
- The firm's credential is the Vest login's wallet address. The dashboard's
form offers the relayed wallet with one click.
- VestClient (lib/vest-class.ts), mapped from the web app's traffic and code
since Vest publishes no API:
- Reads the capital accounts, balances (free amount plus position
collateral), positions and open orders with the user token.
- Mints per-account tokens for orders and transactions.
- Names accounts for their rules (V50K-E-D3-T10-34, V50K-F-D3-34,
V25K-I-7) so account-type prefixes can match.
- Takes Vest's own max-drawdown and daily-loss floors. dayStartBalance =
floor + the type's limit, so the engine's room is never more than
Vest's.
- Uses each symbol's taker fee and margin rate from exchangeInfo, and
hourly volatility over in-session hours only.
- Places take-profit and stop as position legs, which Vest cancels as an
OCO pair.
- Daily P&L and fund rows come from /v3/transactions by Vest's 20:00 ET
day. A books check holds an account, naming the transaction types, when
the balance and the transactions disagree.
- scripts/check-vest.mjs (in npm run check): Vest's day across DST, account
names, parsing, volatility gaps, market hours, the session store.
Not yet run against Vest with a live session: the order and exit bodies
come from the app's code, and the transaction classification from its enum.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Tradovate position opened before this build (so its entry wasn't recorded)
was named from the contract cache, whose entries expire after 30 minutes:
Majd's CL longs showed as #3273057. The resolver now also keeps a lasting
contract id → root index, which the mix reads after its recorded entries.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The master knew how many accounts were in a trade, not in what. Each firm's
report now carries its open positions by instrument (accounts long and
short, contracts held) and today's entries the same way.
A position's contract is named by its instrument: DXtrade's carries the
symbol; a futures one is looked up among the contracts this machine has
entered (recorded at the fill and kept), then the resolver's cache and
TopstepX's own. Entries are counted as they fill, per trade date, in a
setting, so a restart doesn't lose the day.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>