All articles
Strategies·March 22, 2026·4 min read

Paper Trading Hyperliquid Perps: A Pre-Live Checklist

How to wire a strategy against Hyperliquid's testnet WebSocket feed, track realistic funding and fee drag, and set clear go/no-go metrics before deploying real margin. Includes a Python checklist for validating order-management logic.

Shipping a perp strategy on Hyperliquid without a proper paper-trading phase is how you turn a promising backtest into an expensive lesson. The testnet is faithful enough to the production environment that most bugs surface there — if you're disciplined about what you measure. Here is the checklist we run before any strategy moves to live margin.

Connecting to the Testnet Feed

Hyperliquid's testnet WebSocket endpoint (wss://api.hyperliquid-testnet.xyz/ws) carries real-time L2 book updates, trade streams, and user-level fills — the same message schema as mainnet. Wire your bot against it directly; do not stub the feed with recorded data, because latency variance and mid-auction gaps will not be present in a replay.

Subscribe to the l2Book channel for each market you trade and the userFills channel keyed to your testnet address. The fills channel is the ground truth for your position tracker — do not derive position from order acknowledgements alone, because partial fills and rejection races will corrupt that count.

import asyncio, json, websockets

TESTNET_WS = "wss://api.hyperliquid-testnet.xyz/ws"

async def connect(address: str):
    async with websockets.connect(TESTNET_WS) as ws:
        await ws.send(json.dumps({
            "method": "subscribe",
            "subscription": {"type": "userFills", "user": address}
        }))
        async for msg in ws:
            yield json.loads(msg)

Run this continuously, not in a poll loop. Any reconnect logic must replay missed fills from the REST /userFills endpoint before resuming normal operation — otherwise your position state drifts silently.

Modelling Fee and Funding Drag Honestly

The single biggest gap between paper results and live results is fee and funding slippage. Hyperliquid charges maker/taker fees at the account tier level; on testnet your account starts at the base tier (0.02% maker, 0.05% taker). If your strategy targets maker rebates, test at that tier — but also stress-test it at taker rates, because queue position degrades under real order flow.

Funding accrues every hour. For a mean-reversion or trend-following strategy holding positions overnight, funding can easily exceed 20–40 bps per day on high-IV markets. Track it explicitly:

def apply_funding(position_usd: float, funding_rate: float) -> float:
    """funding_rate is the 1h rate from the /meta endpoint, signed."""
    return position_usd * funding_rate  # positive = long pays, negative = long receives

Pull the hourly funding rates from /info (fundingHistory action) and replay them against your paper positions. If your Sharpe drops by more than 30% once you layer in real funding costs, the strategy is not robust enough to go live.

Validating Order-Management Logic

Order management is where production bugs live. During paper trading, exercise every code path deliberately:

  • Partial fills: Place a limit order at a price the book will only partially fill. Verify your position tracker handles the residual correctly and does not re-submit the full quantity.
  • Cancel-replace races: Modify a resting order while a fill is in flight. The cancel acknowledgement and the fill notification can arrive out of order; your state machine must be idempotent.
  • Reject handling: Submit an order that exceeds your testnet margin. Confirm the rejection is caught, logged, and does not leave a phantom open-order entry in your internal ledger.
  • Reconnect mid-position: Kill the WebSocket connection while holding a position. On reconnect, reconcile internal state against the REST /clearinghouseState snapshot before resuming.

Run each scenario five times, not once. Intermittent failures in order management will not show up on a single pass.

Go/No-Go Metrics

Define thresholds before you start paper trading, not after. Changing them post-hoc to make results look better is the most common way teams fool themselves. The criteria we use:

Metric Minimum bar
Net Sharpe (after fees + funding) ≥ 1.2 over 20 trading days
Max drawdown (intraday, paper equity) ≤ 2× your live per-trade risk budget
Fill rate on maker orders ≥ 60% of intended quantity
Unhandled exception rate 0 — any exception is a blocker
Latency p99 (signal → order sent) ≤ 150 ms from colocated infra

The latency number matters more than most teams expect. Hyperliquid's order book moves fast on liquid perps like BTC and ETH; a strategy that looks profitable at 500 ms latency in paper mode will find that its edge disappears at go-live because it is consistently at the back of the queue.

Transition Protocol

When all go/no-go metrics pass, do not flip a binary switch to live. Start with position sizing at 10% of your intended live notional for the first two days. Compare fill patterns — queue position, partial fill rate, slippage versus mid — against your paper baseline. If they match within 15%, scale to 50%, then full size. If they diverge, you have a model assumption that testnet did not surface.

Document every deviation. Keeping a structured log of paper-vs-live discrepancies is what lets you diagnose the next strategy faster. The TierZero bots service runs this exact protocol for every strategy we operate, and the log has saved us from at least three live deployments that would have lost money.


If you want a second pair of eyes on your paper-trading results before committing margin, reach out — we review strategy logs and will tell you plainly whether the numbers support going live.

Need a bot like this built?

We design, build and run trading bots on Solana, Hyperliquid and Polymarket.

Start a project
#hyperliquid#perpetuals#paper-trading#strategy#python#risk-management#testing