bots··3 min read

Building your first Hyperliquid perp bot

A technical walk-through of the stack I personally started with. Published as educational engineering content, not trading advice.

Educational engineering content only. This post describes how I personally built a piece of software. It is not a recommendation to trade cryptocurrency, nor is it financial product advice. Automated trading systems can lose money rapidly. Anyone considering deploying real capital should speak to a licensed Australian financial adviser first.

Why some traders ship their own bot

Every month a new telegram channel tells you they've got the signal. Every month the signal lasts two weeks then drifts into chop. The issue isn't that discretionary trading is bad — it's that retail runs it without the discipline, the screen time, or the ability to sleep through a news print.

Running a bot fixes all three. It doesn't make you money by itself — it just removes the variance you add as a human. The edge has to come from somewhere real: a basis, a rate, a cross-venue funding gap, a liquidation cluster.

That's what we'll ship today. Nothing exotic. Just the skeleton you can hang your own edge on.

The stack

Here's what I actually use in production:

  • VPS: Hetzner CCX11 in Frankfurt (under $10/mo, better than AWS for this size)
  • OS: Ubuntu 24.04 LTS
  • Language: Python 3.12 for bots, TypeScript for tooling
  • Exchange: Hyperliquid (perps) — their SDK is honestly the cleanest I've used
  • Monitoring: Grafana + Loki via Docker compose
  • Alerts: Telegram bot for anything that touches P&L

Don't get cute. If you're building your first bot, use the exact stack above. Once it's live and making money you can start swapping pieces.

Minimum viable bot

Here's the smallest thing that counts as a bot, not a script:

from hyperliquid.info import Info
from hyperliquid.exchange import Exchange

# connection setup skipped — see the repo

def on_tick(state):
    position = state.position("BTC")
    if abs(position.size) > MAX_SIZE:
        raise RiskBreach("position too large")
    edge = compute_edge(state)
    if edge > THRESHOLD:
        state.place_order("BTC", size=0.01, side="long")

Four parts that matter: connection to the venue, state you can reason about, an edge function, and a risk check that can halt everything. If any one of these is missing, you don't have a bot — you have a loaded gun pointing at your collateral.

Risk before edge

I've watched dozens of new bot builders skip the risk layer because it's the boring part. They ship the edge, it works for a week, then a fat-finger trade empties the account in one bar.

Write your risk checks first. Specifically:

  1. Per-trade loss cap (percentage of equity, not absolute)
  2. Daily drawdown kill-switch (auto-flat everything, auto-disable new orders)
  3. Position size cap that's independent of equity
  4. Heartbeat: if the bot doesn't log progress for N minutes, page yourself

The first one stops dumb trades. The second stops bad days. The third stops runaway leverage. The fourth stops silent failures, which are the worst kind.

Deploying

Deployment is just docker compose up -d with systemd watching the container. I'm not including the compose file here because it's boring — you'll write your own. The point is to run under a process supervisor so that if your bot crashes at 3am, it restarts within 30 seconds.

If you need to shell in and "fix something," you don't have a bot. You have a manual trader with extra steps.

What's next

In the next post I'll walk through the structure of one specific strategy — funding-rate basis capture — at a code-and-mechanics level. It's presented as an engineering case study, not a signal.

Educational content only. Not financial product advice. Not a recommendation to trade cryptocurrency or deploy automated trading systems. Run cat rules.md in /terminal for the list of rules I personally trade by.

Get the next one by email.

Weekly-ish. Unsubscribe any time.

One email a week. Unsubscribe any time.

§related

More like this.