A Hyperliquid trading bot is software that connects to Hyperliquid's API to read market data and submit orders according to a predefined strategy. This article explains the core architecture, how to implement a minimal bot in Python, how to validate execution and risk controls, and how to troubleshoot common failure modes. It separates documented API behavior from design recommendations and from measurements you must run yourself. The goal is a bot you can test on testnet and operate with explicit, observable risk limits.
Scope and assumptions for a Hyperliquid trading bot
This guide covers the engineering of a bot that trades Hyperliquid perpetual futures and spot markets through the public API. It assumes you are comfortable with Python or JavaScript, understand perpetual futures mechanics (margin, funding, liquidation), and have a Hyperliquid account with API access. It does not recommend a specific strategy or promise profitability; automated execution does not remove market risk.
Hyperliquid is a decentralized exchange with an on-chain order book and a REST/WebSocket API. A bot typically needs three capabilities: authenticated order placement, real-time market data, and position/account state reconciliation. The exact endpoint URLs and authentication details are documented by Hyperliquid; this article uses placeholders such as RPC_URL and PRIVATE_KEY. For concrete endpoint and provider choices, use the RPC Assistant rather than hardcoding a public endpoint.
Before writing code, decide whether you will use an agent wallet (API wallet) or the main wallet private key. Agent wallets are the safer operational choice because they can trade but cannot withdraw. Keep keys in environment variables or a secrets manager, never in source control.
- Testnet first: Hyperliquid provides a testnet with faucet funds; validate the full loop there.
- Least privilege: use an agent wallet for order signing where supported.
- Observability: log every request, response, and state transition with timestamps.
- Kill switch: a single flag that cancels open orders and stops new submissions.
Mental model: data plane, decision plane, and execution plane
Separate your bot into three planes. The data plane ingests WebSocket feeds (order book, trades, fills) and maintains a local view of the market. The decision plane runs your strategy on a timer or on each market event and emits intents such as 'buy 0.1 BTC at limit price X'. The execution plane translates intents into signed API calls, tracks acknowledgements, and reconciles with exchange state.
This separation matters because most bot failures are not strategy failures; they are state divergence. If your local position says flat but the exchange says long, the next order may double your exposure. The execution plane should periodically fetch open orders and positions and compare them to local state, logging and correcting mismatches.
Latency budget: WebSocket delivery, strategy computation, signing, and HTTP round-trip all add up. For strategies sensitive to queue position or short-horizon price moves, measure each segment. For slower strategies (grid, DCA), a few hundred milliseconds is usually acceptable, but you should still measure rather than assume.
Prerequisites and environment setup
You need Python 3.10+ (or Node 18+), an HTTP client, a WebSocket client, and the Hyperliquid SDK or direct REST calls. The example below uses Python with the official hyperliquid-python-sdk, which handles signing and nonce management. Install it in a virtual environment and pin versions for reproducibility.
Create a .env file with your testnet key and a boolean flag. Never commit this file. For production, inject secrets through your orchestrator's secret store. If you run the bot on a server, restrict outbound network access to the endpoints you actually use and monitor for unexpected egress.
python -m venv .venv
source .venv/bin/activate
pip install hyperliquid-python-sdk python-dotenv websockets
# .env
HYPERLIQUID_PRIVATE_KEY=0xYOUR_AGENT_WALLET_PRIVATE_KEY
HYPERLIQUID_TESTNET=true
HYPERLIQUID_ACCOUNT_ADDRESS=0xYOUR_MAIN_WALLET_ADDRESSImplementing a minimal market-data and order loop
The following Python sketch connects to Hyperliquid, subscribes to the mid-price of a perp, and places a limit order when a simple threshold condition is met. It is deliberately small so you can verify each step. Replace the strategy block with your own logic. The code uses the SDK's Exchange and Info classes; check the SDK version's method signatures because they evolve.
Key implementation details: use an integer nonce that increases monotonically, set a time-in-force (e.g., Gtc or Ioc) explicitly, and include a client order ID so you can correlate fills with intents. After placing an order, poll or subscribe for the order status and update local state only on confirmed fills, not on submission.
import os, time
from dotenv import load_dotenv
from hyperliquid.exchange import Exchange
from hyperliquid.info import Info
from hyperliquid.utils import constants
load_dotenv()
base_url = constants.TESTNET_API_URL if os.getenv('HYPERLIQUID_TESTNET') == 'true' else constants.MAINNET_API_URL
account = os.environ['HYPERLIQUID_ACCOUNT_ADDRESS']
exchange = Exchange(os.environ['HYPERLIQUID_PRIVATE_KEY'], base_url, account_address=account)
info = Info(base_url, skip_ws=False)
coin = 'BTC'
last_mid = None
while True:
mids = info.all_mids()
mid = float(mids[coin])
if last_mid is not None and mid > last_mid * 1.001:
# Example intent: buy 0.001 BTC at mid with a small offset
px = round(mid * 0.999, 1)
order = exchange.order(coin, True, 0.001, px, {'limit': {'tif': 'Gtc'}}, reduce_only=False)
print('submitted', order)
last_mid = mid
time.sleep(1)Verifying execution: expected results and a measurement table
Before trusting the bot with size, run a verification pass on testnet. For each order, confirm that the exchange acknowledgement contains an order ID, that the order appears in open orders, and that a fill updates your position. Then run a controlled measurement of latency and error rates. Record the following table in your own runbook; do not fill it with invented numbers.
| Metric | How to measure | Target (your choice) | Observed |
|---|---|---|---|
| WebSocket message latency | Timestamp on receive minus exchange timestamp | < 250 ms p95 | |
| Order round-trip | Time from send to acknowledgement | < 500 ms p95 | |
| Reject rate | Rejected orders / total orders | < 1% | |
| State divergence | Reconciliation mismatches per hour | 0 | |
| Fill correlation | Fills matched to client order IDs | 100% |
Run the measurement for at least a few hours across different market conditions. If you use a hosted RPC or API provider, measure from the same region as your bot. For provider selection, see the RPC Assistant guidance on low-latency trading endpoints and the OnFinality network pages for supported chains.
Risk controls that belong in code, not in your head
Enforce limits in the execution plane so they cannot be bypassed by strategy bugs. At minimum: maximum position size per asset, maximum notional exposure, maximum daily loss, maximum order rate, and a mandatory reduce-only mode when drawdown exceeds a threshold. Each limit should be checked before signing an order and logged when triggered.
Use idempotent client order IDs and a deduplication window to avoid duplicate orders after a timeout. If an HTTP request times out, do not blindly retry a market order; query order status by client ID first. For limit orders, a retry with the same client ID is safer if the exchange supports idempotency; otherwise reconcile before resubmitting.
Funding and liquidation are part of risk. Track funding payments and margin ratio. A bot that ignores funding can bleed on a carry strategy. A bot that ignores margin can be liquidated during a fast move even if its entry logic was correct.
- Hard caps on position and notional, checked pre-trade.
- Daily loss circuit breaker that flips the bot to reduce-only.
- Order rate limiter with a token bucket.
- Alerting on reject spikes, reconciliation mismatches, and margin ratio thresholds.
Troubleshooting common Hyperliquid bot failures
Most failures fall into four buckets: authentication/signing, nonce and rate limits, state divergence, and connectivity. Start with the exchange response body; it usually names the error. Log the full request ID and timestamp so you can correlate with exchange status pages.
Signing errors often come from using the wrong wallet type or a mismatched account address. If you use an agent wallet, the signing key and the account address are different; pass both correctly. Nonce errors occur when multiple processes share a key or when the clock drifts. Use a single signer process and synchronize time via NTP.
Rate-limit errors require backoff with jitter, not tight retries. State divergence requires a reconciliation job that fetches open orders and positions and compares them to local state; run it on a schedule and after every reconnect. Connectivity issues are best handled with a supervisor that restarts the WebSocket and re-subscribes, plus a heartbeat that detects silent stalls.
import time, random
def with_backoff(fn, attempts=5):
for i in range(attempts):
try:
return fn()
except Exception as e:
if i == attempts - 1:
raise
sleep = min(2 ** i, 30) + random.random()
print(f'retry {i+1} after {sleep:.1f}s: {e}')
time.sleep(sleep)Limitations and tradeoffs of automated Hyperliquid trading
Automation improves consistency and speed but does not create edge. Backtests overfit, testnet liquidity differs from mainnet, and market impact grows with size. A grid bot that looks profitable in a range will accumulate inventory in a trend; a DCA bot that averages down can compound losses if the trend persists. Size and risk limits are the primary defense.
Operational complexity is real: key management, monitoring, upgrades, and incident response all require time. If you cannot staff those, a simpler bot with fewer moving parts is safer than a sophisticated one you cannot observe. Also consider regulatory and tax obligations in your jurisdiction; on-chain trading does not remove them.
Finally, API behavior can change. Pin SDK versions, read release notes, and keep a rollback path. Treat the bot as production software, not a script.
Next steps: from testnet to a monitored deployment
Once testnet verification passes, deploy with a small mainnet size and a strict loss cap. Add dashboards for latency, reject rate, position, and PnL. Set alerts for reconciliation mismatches and margin ratio. Run a weekly review of fills versus intents to catch silent failures.
For infrastructure, choose endpoints and nodes that match your latency and reliability requirements. Review the OnFinality API service, compare RPC pricing plans, and browse supported networks before committing. If you need dedicated throughput, evaluate dedicated nodes. For a concrete endpoint recommendation, consult the RPC Assistant rather than guessing.
Keep iterating: measure, tighten limits, and document incidents. A bot that is boring to operate is usually the one that survives.