Self-trade prevention
When an order would fill against the same address's resting order, HyperCore cancels the resting one: no fill, no fee, and the incoming order carries on.
Self-trade prevention stops you paying two fees to trade with yourself. A normal fill against your own quote would move no risk, yet charge both sides and print volume no one else traded.
Centralised exchanges often call this rule “expire maker”. It suits market making: the aggressor usually wants the liquidity behind your own quote.
Your resting order is cancelled, not filled
Section titled “Your resting order is cancelled, not filled”When an incoming order reaches a resting order from the same address in price-time matching (the order book), the resting order is cancelled: no fill, no fee, no printed trade. The incoming order matches on to its limit price, then follows its time in force (Gtc rests, Ioc is cancelled).
The rule is keyed on address
Section titled “The rule is keyed on address”An API wallet only signs; the order belongs to the master or the sub-account named in vaultAddress, so several API wallets on one account are one address (API wallets).
Sub-accounts and vaults have their own addresses and are independent accounts in the clearinghouse. So a master’s order can fill against its own sub-account’s as an ordinary trade, with fees on both sides; this follows from the docs and has not been measured here.
The numbers
Section titled “The numbers”| Item | Value |
|---|---|
| Mode | Expire maker: the resting order is cancelled |
| Scope | Same address; API wallets count as their master |
| Fee on the prevented match | 0 on both sides |
| Public trade feed | Nothing printed |
| Status of the cancelled order | selfTradeCanceled |
| Incoming order | Continues to its limit price, then follows its TIF |
What you’ll notice on one account
Section titled “What you’ll notice on one account”Mostly, you’ll see an order disappear. Say you rest a bid at 99 for a dip, then market-sell to close a long: if your bid is best, the sell cancels it and fills against the next bids. Place it again if you still want it.
A prevented match adds no volume toward your fee tier (fees).
Handling the cancel in code
Section titled “Handling the cancel in code”Treat selfTradeCanceled as a cancel you did not send. It arrives on the orderUpdates WebSocket channel, and orderStatus reports it:
{ "order": { "coin": "ETH", "side": "A", "limitPx": "2412.7", "sz": "0.5", "oid": 1, "timestamp": 1724361546645, "origSz": "0.5" }, "status": "selfTradeCanceled", "statusTimestamp": 1724361546645}- No inventory change, no fill row. A quoting loop that reprices on fills must handle this status or keep a quote it no longer has.
- To pull a quote rather than lose it to your own taker, cancel it: in a block, cancels run before
GtcandIocorders. - Sub-accounts remove the protection between strategies. Teams split anyway because nonces are tracked per signer, so processes sharing one wallet with millisecond nonces collide; separate API wallets on one account fix that and keep the protection.
Volume data and two unmeasured cases
Section titled “Volume data and two unmeasured cases”- External volume data never sees prevented matches.
- Undocumented and unmeasured: whether a post-only order crossing only your own resting order is rejected as a post-only violation or handled by self-trade prevention, and the same for an
Iocwhose only match is your own.
For separate addresses under one master, see Sub-accounts. For quoting both sides, see Market making.