What You Are Building
A Python bot that watches a target trader’s Hyperliquid wallet, detects when they open or close a perpetuals position, and mirrors the trade on your own account with position sizing and risk caps you control. Claude Code writes the polling and order logic while you pick the wallet to follow and set the limits. You run it on testnet first.
Why Copy Trading Works on Hyperliquid
Copy trading means mirroring another trader’s positions automatically. On most exchanges this is hard, because you cannot see what other accounts are doing. Hyperliquid is different: it runs a fully on-chain order book, so every wallet’s open positions and fills are public. You can read any address’s positions straight from the API without that trader sharing anything.
That public state is what makes a copy bot possible at all:
| What You Need | Centralized Exchange | Hyperliquid |
|---|---|---|
| See a target’s positions | Not possible (private) | Public via info API |
| See their fills in real time | Not possible | WebSocket userFills feed |
| Latency to react | N/A | Low, on-chain order book |
| Their permission | Required | Not needed (data is public) |
| Your custody | Exchange holds funds | Non-custodial, your wallet signs |
The catch is that public does not mean safe to copy blindly. You are still mirroring someone else’s risk decisions, and a trader who looks great for three months can blow up in a week. The risk-cap layer below is the part that matters most, so do not skip it.
If you have already built a Hyperliquid trading bot with Claude Code, this reuses the same SDK and wallet setup. The new piece is reading another wallet’s state and translating it into your own sized orders.
How a Copy Bot Actually Works
A copy bot has one job: notice when the target trades, then place a matching trade before the price moves too far. Broken into steps:
- Poll (or subscribe to) the target wallet’s current positions.
- Compare against the last snapshot you saw.
- When a position appears, grows, shrinks, or closes, work out the delta.
- Scale that delta to your account size and risk rules.
- Submit your own order through your agent wallet.
- Log everything so you can audit each mirrored trade later.
The naive version copies position sizes one to one. That breaks the moment the target has a bigger account than you, or uses 20x leverage you do not want. The useful version translates their intent (went long BTC, roughly 30% of their book) into your sizing (go long BTC, capped at your per-trade dollar limit).
Prerequisites
- Python 3.10+
- A funded Ethereum wallet for your own account (a fresh one for testnet)
- Claude Code installed and working
- Basic Python and async familiarity
- A target wallet address to follow (start with one you pick on testnet, or a known address)
Step 1: Set Up Your Own Testnet Wallet
Use a fresh wallet for bot work, never your main one.
- Generate a new wallet in MetaMask or your wallet of choice and save the private key.
- Visit app.hyperliquid-testnet.xyz and connect it.
- Click the faucet to receive test USDC.
- Approve trading permissions when prompted.
Hyperliquid uses an agent wallet pattern: your main wallet authorizes a separate hot wallet that signs trades, so the bot process never holds your primary key. Claude Code can scaffold this for you. The Hyperliquid bot tutorial covers the agent setup in detail if you want the full walkthrough.
Step 2: Install the SDK
Create a project folder and install the official SDK:
mkdir hl-copy-bot && cd hl-copy-bot
python -m venv venv && source venv/bin/activate
pip install hyperliquid-python-sdk
Then open Claude Code in that folder:
claude
Step 3: Read a Target Wallet’s Positions
This is the part that does not exist on centralized exchanges. The info endpoint returns any address’s current state, no authentication needed. Ask Claude Code:
Write a function using the hyperliquid SDK that takes a wallet
address and returns its current perpetual positions as a list of
{coin, size, side, entry_price}. Use the testnet info endpoint.
You will get something close to this:
from hyperliquid.info import Info
from hyperliquid.utils import constants
info = Info(constants.TESTNET_API_URL, skip_ws=True)
def get_positions(address: str):
state = info.user_state(address)
positions = []
for ap in state["assetPositions"]:
p = ap["position"]
size = float(p["szi"])
if size == 0:
continue
positions.append({
"coin": p["coin"],
"size": abs(size),
"side": "long" if size > 0 else "short",
"entry_price": float(p["entryPx"]),
})
return positions
Run it against your target address and confirm you see their open positions. This read costs nothing and needs no keys, since the data is already public on-chain.
Step 4: Detect Changes
The bot keeps a snapshot of what the target held last time it checked, then diffs against the new snapshot. Ask Claude Code:
Write a diff function that compares two position snapshots
(previous and current) and returns a list of actions: opened,
increased, decreased, or closed, with the coin, side, and the
size delta for each.
A simple version:
def diff_positions(prev, curr):
actions = []
prev_map = {p["coin"]: p for p in prev}
curr_map = {p["coin"]: p for p in curr}
for coin, c in curr_map.items():
p = prev_map.get(coin)
if p is None:
actions.append({"type": "opened", "coin": coin,
"side": c["side"], "delta": c["size"]})
elif c["size"] > p["size"]:
actions.append({"type": "increased", "coin": coin,
"side": c["side"], "delta": c["size"] - p["size"]})
elif c["size"] < p["size"]:
actions.append({"type": "decreased", "coin": coin,
"side": c["side"], "delta": p["size"] - c["size"]})
for coin, p in prev_map.items():
if coin not in curr_map:
actions.append({"type": "closed", "coin": coin,
"side": p["side"], "delta": p["size"]})
return actions
Step 5: Scale to Your Account, Not Theirs
This is where most copy bots go wrong. Copying raw sizes assumes your account matches the target’s. Instead, scale by the fraction of their equity the trade represents, then apply your dollar cap.
Tell Claude Code your rules in plain language:
When the target opens or increases a position, size my order as a
fixed fraction of my account equity, never more than $200 notional
per trade, and never more than 3 open positions at once. Skip the
trade if it would breach any cap. Mirror closes fully.
The sizing logic should look something like this:
MAX_NOTIONAL = 200 # dollars per trade
MAX_POSITIONS = 3
ACCOUNT_FRACTION = 0.10 # 10% of my equity per signal, then capped
def size_order(my_equity, mark_price, open_positions):
if open_positions >= MAX_POSITIONS:
return 0
target_notional = min(my_equity * ACCOUNT_FRACTION, MAX_NOTIONAL)
return round(target_notional / mark_price, 4)
Note what this ignores on purpose: the target’s leverage and their exact size. You are copying direction and rough conviction, not their risk appetite. If they go 20x, you do not. That gap is the whole point of a sane copy bot.
Step 6: Place the Mirrored Order
Now wire the actions to your own agent wallet. For an opened or increased long, place a buy; for a closed, reduce your matching position to zero. Ask Claude Code:
Using the hyperliquid Exchange class with my agent wallet, place
a market order for the sized quantity in the action's direction.
For closes, close my existing position in that coin. Print the
order result.
from hyperliquid.exchange import Exchange
import eth_account
wallet = eth_account.Account.from_key(AGENT_PRIVATE_KEY)
exchange = Exchange(wallet, constants.TESTNET_API_URL)
def execute(action, qty):
is_buy = action["side"] == "long"
if action["type"] == "closed":
exchange.market_close(action["coin"])
else:
exchange.market_open(action["coin"], is_buy, qty)
Always run this on testnet until you have watched it mirror 30+ trades correctly. Check that every mirrored order matches the direction you expected and that no order ever breaks your caps.
Step 7: The Polling Loop
Tie it together. Poll every few seconds, diff, size, execute, log:
import time
prev = get_positions(TARGET_ADDRESS)
while True:
curr = get_positions(TARGET_ADDRESS)
for action in diff_positions(prev, curr):
my_state = info.user_state(MY_ADDRESS)
equity = float(my_state["marginSummary"]["accountValue"])
open_count = len([a for a in my_state["assetPositions"]
if float(a["position"]["szi"]) != 0])
mark = float(info.all_mids()[action["coin"]])
qty = size_order(equity, mark, open_count)
if qty > 0 or action["type"] == "closed":
execute(action, qty)
print(f"mirrored {action['type']} {action['coin']} qty={qty}")
prev = curr
time.sleep(5)
For lower latency, ask Claude Code to swap the poll for the WebSocket userFills subscription so you react on the target’s fill instead of waiting for the next poll. Polling every five seconds is fine to learn with; the WebSocket version reacts in under a second.
Risk Controls You Should Not Skip
Copy trading hands your sizing decisions to a stranger. These limits keep one bad target from draining the account:
- Hard notional cap per trade. The
MAX_NOTIONALabove. A target’s $50k position becomes your $200 one, not a proportional monster. - Max open positions. Stops the bot from chasing a target who runs ten positions at once.
- A coin allowlist. Only mirror BTC and ETH if that is all you want exposure to. Skip the rest.
- A daily loss kill switch. If your equity drops past a threshold in a day, stop mirroring and alert yourself.
- Ignore leverage entirely. Set your own and never read theirs. This is the single biggest protection.
Ask Claude Code to add each of these as an explicit check before execute runs, and to log the reason whenever it skips a trade. You want a paper trail for every decision the bot makes.
When to Go Live
Run on testnet for at least two weeks. Watch how the bot handles the messy cases: a target who flips from long to short in one move, a coin you do not have margin for, a position that closes in pieces. Only move to mainnet with real but small funds once the testnet log shows clean, correctly sized mirrors with no cap breaches.
Even then, treat the target’s track record with suspicion. On-chain history shows what they did, not what they will do. Size as if any target can blow up next week, because some of them will.
What to Read Next
- New to Hyperliquid bots? Start with the Hyperliquid trading bot tutorial to learn the SDK and agent wallet setup
- Want indicator-based signals instead of copying? Pair mcp-trader with your bot using the MCP servers guide
- Prefer a centralized exchange? The Bybit MCP bot tutorial covers crypto futures with fund isolation
- Want to package this as a reusable workflow? See the Claude Code trading skills guide for turning a bot into a skill