Crypto Bots

How to Automate Hyperliquid Trading with Python in 2026

Hyperliquid is the fastest-growing perpetuals DEX, processing $5B+ daily volume fully on-chain. Learn how to build automated trading bots using Hyperliquid's Python SDK and WebSocket API.

A
AI Agents Hubยท2026-03-29ยท5 min readยท857 words

Builder of AI agents, crypto trading bots, and open-source automation tools. Sharing practical guides on how to build, deploy, and profit from AI and DeFi technology.

Why Hyperliquid Is Different

Hyperliquid is not just another DEX. It's a fully on-chain order book perpetuals exchange built on its own L1 blockchain (Hyperliquid L1). Everything that happens on a centralized exchange โ€” order placement, matching, liquidations โ€” happens on-chain with sub-second finality.

For bot builders, this means:

  • CEX-like UX with on-chain transparency
  • No KYC required for trading
  • Full on-chain order book โ€” you can read every order
  • Maker rebates of up to 0.02% (you get paid to provide liquidity)
  • No gas fees for trading (network fees covered by protocol)

Setting Up Hyperliquid Python SDK

pip install hyperliquid-python-sdk
import eth_account
from eth_account.signers.local import LocalAccount
from hyperliquid.info import Info
from hyperliquid.exchange import Exchange
from hyperliquid.utils import constants
import json

# Setup account (Arbitrum EVM address)
private_key = "YOUR_PRIVATE_KEY"
account: LocalAccount = eth_account.Account.from_key(private_key)
print(f"Trading address: {account.address}")

# Connect to Hyperliquid
info = Info(constants.MAINNET_API_URL, skip_ws=True)
exchange = Exchange(account, constants.MAINNET_API_URL)

# Check account state
user_state = info.user_state(account.address)
print(f"USDC Balance: ${float(user_state['marginSummary']['accountValue']):.2f}")

Getting Market Data

def get_market_info(coin: str = "BTC") -> dict:
    """Get current price and market data for a coin"""
    
    # Get all mid prices
    all_mids = info.all_mids()
    mid_price = float(all_mids.get(coin, 0))
    
    # Get order book
    l2_snapshot = info.l2_snapshot(coin)
    best_bid = float(l2_snapshot['levels'][0][0]['px'])
    best_ask = float(l2_snapshot['levels'][1][0]['px'])
    spread = best_ask - best_bid
    spread_bps = (spread / mid_price) * 10000
    
    # Get recent trades
    recent_trades = info.recent_trades(coin)
    
    return {
        'coin': coin,
        'mid': mid_price,
        'bid': best_bid,
        'ask': best_ask,
        'spread_bps': spread_bps,
        'last_trade_side': recent_trades[0]['side'] if recent_trades else None,
    }

# Example
btc_data = get_market_info("BTC")
print(f"BTC: ${btc_data['mid']:,.2f} | Spread: {btc_data['spread_bps']:.2f}bps")

Placing Orders

def place_limit_order(coin: str, is_buy: bool, sz: float, limit_px: float) -> dict:
    """Place a limit order on Hyperliquid"""
    
    order_result = exchange.order(
        coin,
        is_buy,
        sz,       # Size in coin units
        limit_px, # Limit price
        {"limit": {"tif": "Gtc"}}  # Good till cancelled
    )
    
    if order_result["status"] == "ok":
        statuses = order_result["response"]["data"]["statuses"]
        for status in statuses:
            if "resting" in status:
                oid = status["resting"]["oid"]
                print(f"โœ… Order placed: {'BUY' if is_buy else 'SELL'} {sz} {coin} @ ${limit_px:,.2f}")
                print(f"   Order ID: {oid}")
                return {'success': True, 'oid': oid}
    
    print(f"โŒ Order failed: {order_result}")
    return {'success': False}

def place_market_order(coin: str, is_buy: bool, sz: float) -> dict:
    """Place a market order (uses aggressive limit with slippage)"""
    mid = float(info.all_mids()[coin])
    
    # Market order = limit at 3% slippage tolerance
    slippage = 1.03 if is_buy else 0.97
    limit_px = round(mid * slippage, 2)
    
    order_result = exchange.order(
        coin,
        is_buy,
        sz,
        limit_px,
        {"limit": {"tif": "Ioc"}}  # Immediate or Cancel for market-like execution
    )
    
    return order_result

def close_position(coin: str) -> dict:
    """Close open position for a coin"""
    user_state = info.user_state(account.address)
    positions = user_state.get('assetPositions', [])
    
    for pos in positions:
        if pos['position']['coin'] == coin:
            size = float(pos['position']['szi'])
            if size != 0:
                is_buy = size < 0  # Short position needs a buy to close
                result = place_market_order(coin, is_buy, abs(size))
                print(f"Closed {coin} position: {size} units")
                return result
    
    print(f"No position found for {coin}")
    return {}

Building a Simple Trend-Following Bot

import time
import pandas as pd

def get_candles(coin: str, interval: str = "1h", lookback: int = 100) -> pd.DataFrame:
    """Fetch candlestick data from Hyperliquid"""
    import time
    
    end_time = int(time.time() * 1000)
    start_time = end_time - (lookback * 3600 * 1000)  # lookback hours ago
    
    candles = info.candles_snapshot(coin, interval, start_time, end_time)
    
    df = pd.DataFrame(candles, columns=['t', 'T', 'o', 'h', 'l', 'c', 'v', 'n'])
    df = df.rename(columns={'o': 'open', 'h': 'high', 'l': 'low', 'c': 'close', 'v': 'volume'})
    df[['open', 'high', 'low', 'close']] = df[['open', 'high', 'low', 'close']].astype(float)
    
    return df

class HyperliquidTrendBot:
    def __init__(self, coins: list[str], position_size_usd: float = 100):
        self.coins = coins
        self.position_size_usd = position_size_usd
        self.open_positions = {}
    
    def get_ema_signal(self, coin: str) -> str:
        df = get_candles(coin, '1h', 100)
        df['ema12'] = df['close'].ewm(span=12).mean()
        df['ema26'] = df['close'].ewm(span=26).mean()
        
        latest = df.iloc[-1]
        prev = df.iloc[-2]
        
        if prev['ema12'] <= prev['ema26'] and latest['ema12'] > latest['ema26']:
            return 'BUY'
        elif prev['ema12'] >= prev['ema26'] and latest['ema12'] < latest['ema26']:
            return 'SELL'
        elif latest['ema12'] > latest['ema26']:
            return 'HOLD_LONG'
        else:
            return 'HOLD_SHORT'
    
    def run_cycle(self):
        for coin in self.coins:
            signal = self.get_ema_signal(coin)
            mid = float(info.all_mids()[coin])
            size = self.position_size_usd / mid
            
            in_position = coin in self.open_positions
            
            if signal == 'BUY' and not in_position:
                result = place_market_order(coin, True, round(size, 4))
                if result.get('status') == 'ok':
                    self.open_positions[coin] = {'side': 'long', 'entry': mid}
                    print(f"๐Ÿ“ˆ OPENED LONG {coin} @ ${mid:,.2f}")
            
            elif signal == 'SELL' and in_position and self.open_positions[coin]['side'] == 'long':
                close_position(coin)
                del self.open_positions[coin]
                print(f"๐Ÿ“‰ CLOSED LONG {coin} @ ${mid:,.2f}")

# Run bot
bot = HyperliquidTrendBot(['BTC', 'ETH', 'SOL'])

while True:
    bot.run_cycle()
    time.sleep(3600)  # Check every hour

Real-Time WebSocket Feed

from hyperliquid.info import Info

def handle_price_update(data):
    """Handle real-time price updates"""
    print(f"Price update: {data}")

# Subscribe to live data
info_ws = Info(constants.MAINNET_API_URL)
info_ws.subscribe(
    {"type": "allMids"},
    handle_price_update
)

Why Hyperliquid for Bots in 2026

  • No gas fees: Execute thousands of orders without gas costs
  • Maker rebates: Earn -0.02% on limit orders (unusual for DEX)
  • On-chain transparency: All data publicly readable โ€” no proprietary APIs needed
  • $5B+ daily volume: Deep enough liquidity for meaningful position sizes
  • No withdrawal restrictions: It's your keys, your crypto

Hyperliquid represents the best of both worlds โ€” CEX performance on a decentralized protocol. For bot builders willing to learn the SDK, it's one of the most exciting trading environments available.

Related Articles