how it works
Two axes. One must prove the other.
The check doesn't just recompute your record — it proves the recomputation. Two mathematically independent views of the same account have to agree, or the disagreement is printed with a measured number.
Pull the complete record
Fills come from an independent chain indexer — the venue's own fill API only retains about 30 hours, so anything built on it alone silently truncates. Funding events, ledger updates and the sampled portfolio curves come from the venue API, which serves full history for those types.
Recompute the components
Realized PnL is summed fill by fill. Funding is summed event by event. Fees are summed with their sign — a positive fee is a rebate, not a cost. Builder-dex fills are included; spot fills are separated out.
Verify against the venue curve
Axis 1: the venue's official sampled ΔPnL minus our recomputed realized PnL, funding and fees. On a verified account this residual equals the drift in open-position unrealized PnL.
Close the independent identity
Axis 2: Δ account value − every flow crossing the perp boundary (deposits, withdrawals, sends, sub-account transfers) must equal the venue's PnL. This axis uses no fills at all — it is a fully independent check on axis 1.
the identity, formally
axis 1: official ΔPnL − (realized + funding + signed fees)
= residual ≈ Δ unrealized PnL
axis 2: Δ accountValue − boundary flows
= impliedPnL ≈ official ΔPnL
axis 2 uses zero fills — it verifies axis 1 independently.
semantics that silently corrupt naive parsers
Verified on live data, not read from docs.
Signed fees
Fill fees are signed: negative means paid, positive means rebate. Treating every fee as a cost inflates expenses on rebate-heavy accounts.
Send direction
A send row names a sender (user) and a receiver (destination), each with their own pool (sourceDex / destinationDex). Which side of the boundary the funds crossed depends on who you are — misreading this hid a $2.43M inbound transfer on one real account.
Perp universe, not main perp
The venue's perp* portfolio buckets span the main perp plus every builder dex. Spot-side movements (spotTransfer) never touch that boundary and must be excluded — including them produced false gaps of nine figures.
Unrealized PnL lives in positions
marginSummary carries no unrealized PnL field — it must be summed from assetPositions. Skipping it makes the identity look broken when it isn't.
Venue fill retention
userFillsByTime returns only the last ~30 hours, with no error and no flag. A 30-day recomputation built on it silently uses ~2 days of data.
measured, not claimed
known limits — printed, not hidden
- — Builder-dex accounts: the venue's PnL series excludes unrealized dex PnL while its account-value series includes it. The two official series contradict each other; we print the measured gap instead of picking one silently.
- — Full-history pulls for very active accounts take minutes today. Incremental caching is on the roadmap.
- — CEX-side cost basis, FIFO / weighted-average lot tracking and actual filing output are not in the free check.
- — One address is not one person. Other wallets, CEX accounts and pre-transfer basis are out of scope.
not tax advice · every claim on this page is re-derivable