Skip to main content

A simple API wrapper for automated trading on Hyperliquid DEX with Python

Project description

fractrade-hl-simple

A simple Python wrapper for the Hyperliquid DEX API, focused on perpetual futures trading. Built for reliability with automatic retries, configurable slippage, and proper error handling — because this is real money.

Installation & Updates

Using pip:

pip install fractrade-hl-simple

# Update to latest version
pip install --upgrade fractrade-hl-simple

Using poetry:

poetry add fractrade-hl-simple

# Update to latest version
poetry update fractrade-hl-simple

Setup

  1. Create a .env file in your project root:
HYPERLIQUID_ENV=mainnet  # or testnet
HYPERLIQUID_PUBLIC_ADDRESS=your_public_address
HYPERLIQUID_PRIVATE_KEY=your_private_key

We recommend creating a separate API wallet in the Hyperliquid UI for automated trading. API wallets cannot withdraw funds, limiting risk. When using an API wallet, set HYPERLIQUID_PUBLIC_ADDRESS to your main account address and HYPERLIQUID_PRIVATE_KEY to the API wallet's private key.

  1. Initialize the client:
from fractrade_hl_simple import HyperliquidClient

client = HyperliquidClient()

Client Configuration

The client accepts several optional parameters:

client = HyperliquidClient(
    env="mainnet",              # "mainnet" or "testnet"
    default_slippage=0.05,      # 5% default slippage for market orders (0.0-0.5)
    max_retries=3,              # Retry transient failures (0 to disable)
    retry_delay=1.0,            # Base delay between retries (exponential backoff)
    cache_market_specs=True,    # Cache market specs across instances (24h TTL)
)

Retry logic: All API calls automatically retry on network errors, timeouts, rate limits, and server errors. Auth errors and validation errors are never retried.

Authentication Modes

1. Environment Variables (Default)

client = HyperliquidClient()  # Loads from .env automatically

2. Explicit Account

from fractrade_hl_simple import HyperliquidClient, HyperliquidAccount

account = HyperliquidAccount(
    private_key="your_private_key",
    public_address="your_public_address"
)
client = HyperliquidClient(account=account)

3. Unauthenticated (Public Endpoints Only)

client = HyperliquidClient()  # Falls back if no credentials found

Basic Usage

Get Market Prices

btc_price = client.get_price("BTC")
all_prices = client.get_price()  # Returns dict of all symbols

Check Account Balance

balance = client.get_perp_balance()
print(f"Account balance: ${float(balance):,.2f}")

View Positions

positions = client.get_positions()
for pos in positions:
    direction = "LONG" if pos.is_long else "SHORT"
    print(f"{pos.symbol} {direction} {float(pos.size):+.3f} @ ${float(pos.entry_price):,.2f}")

Place Orders

# Market buy
order = client.buy("BTC", size=0.001)

# Market buy with custom slippage (overrides default_slippage)
order = client.buy("BTC", size=0.001, slippage=0.02)  # 2% slippage

# Limit buy
order = client.buy("BTC", size=0.001, limit_price=80000.0)

# Market sell
order = client.sell("BTC", size=0.001)

# Limit sell
order = client.sell("BTC", size=0.001, limit_price=90000.0)

Stop Loss and Take Profit

# For long positions (is_buy=False by default — sells when triggered)
client.stop_loss("BTC", size=0.001, trigger_price=80000.0)
client.take_profit("BTC", size=0.001, trigger_price=95000.0)

# For short positions (must set is_buy=True — buys when triggered)
client.stop_loss("BTC", size=0.001, trigger_price=90000.0, is_buy=True)
client.take_profit("BTC", size=0.001, trigger_price=75000.0, is_buy=True)

Open Position with TP/SL

# Long with stop loss and take profit
position = client.open_long_position(
    symbol="BTC",
    size=0.001,
    stop_loss_price=80000.0,
    take_profit_price=95000.0,
)
# Returns: {"entry": Order, "stop_loss": Order, "take_profit": Order}

# Short with TP/SL
position = client.open_short_position("BTC", 0.001, stop_loss_price=90000.0, take_profit_price=75000.0)

Close Position

close_order = client.close("BTC")

# close() warns if the IOC order doesn't fill (position may still be open)
if close_order.status != "filled":
    print("Warning: close order was not filled!")

Cancel Orders

client.cancel_order(order_id=12345, symbol="BTC")  # Accepts str or int
client.cancel_all_orders("BTC")   # Cancel all BTC orders
client.cancel_all_orders()        # Cancel all orders across all symbols

Leverage Management

# Set cross leverage
client.set_leverage("BTC", 10)

# Set isolated leverage
client.set_leverage("ETH", 5, is_cross=False)

# Add margin to an isolated position
client.add_isolated_margin("ETH", 100.0)  # Add $100

Order Tracking

# Get recent fills
fills = client.get_fills()                    # All symbols
fills = client.get_fills("BTC")               # BTC only

for fill in fills:
    print(f"{fill.symbol} {fill.direction} {fill.size} @ {fill.price} pnl={fill.closed_pnl}")

# Get fills in a time range (timestamps in milliseconds)
import time
start = int((time.time() - 86400) * 1000)  # 24 hours ago
fills = client.get_fills_by_time(start_time=start)

# Check order status
status = client.get_order_status(order_id=12345)

Bulk Orders

# Place multiple orders atomically
result = client.bulk_order([
    {"symbol": "BTC", "is_buy": True,  "size": 0.001, "limit_price": 80000.0},
    {"symbol": "ETH", "is_buy": True,  "size": 0.01,  "limit_price": 3000.0},
    {"symbol": "BTC", "is_buy": False, "size": 0.001, "limit_price": 90000.0, "reduce_only": True},
])

# Cancel multiple orders atomically
client.bulk_cancel([
    {"symbol": "BTC", "order_id": 12345},
    {"symbol": "ETH", "order_id": 67890},
])

Market Data

Order Book

order_book = client.get_order_book("BTC")
print(f"Best bid: ${order_book['best_bid']:,.2f}")
print(f"Best ask: ${order_book['best_ask']:,.2f}")
print(f"Spread: ${order_book['spread']:,.2f}")

Optimal Limit Pricing

# urgency_factor: 0.0 = patient (at best bid/ask), 1.0 = aggressive (crosses spread)
patient_price = client.get_optimal_limit_price("BTC", "buy", urgency_factor=0.1)
aggressive_price = client.get_optimal_limit_price("BTC", "buy", urgency_factor=0.9)

Funding Rates

# Current predicted funding rate
btc_rate = client.get_funding_rates("BTC")  # Returns float

# All rates sorted by value
all_rates = client.get_funding_rates()  # Returns List[{"symbol": str, "funding_rate": float}]

# Filter by threshold
high_rates = client.get_funding_rates(threshold=0.0001)  # Only |rate| >= threshold

# Historical funding rates
history = client.get_funding_history("BTC", start_time=1700000000000)
# Returns List[{"time": int, "funding_rate": float, "premium": float}]

Portfolio Performance

portfolio = client.get_portfolio()
# or for any address:
portfolio = client.get_portfolio("0x...")

Market Info

markets = client.get_market_info()       # All markets
btc_info = client.get_market_info("BTC") # Specific market

# Refresh market specs (cached for 24 hours, but can be forced)
client.refresh_market_specs()

Error Handling

The library provides specific exceptions for different failure modes:

from fractrade_hl_simple import (
    HyperliquidException,        # Base — catch all library errors
    PositionNotFoundException,   # No position found for symbol
    OrderNotFoundException,      # Order not found (cancel/query)
    InsufficientMarginException, # Not enough margin
    OrderException,              # Base for order-related errors
)

try:
    client.close("BTC")
except PositionNotFoundException:
    print("No BTC position to close")
except HyperliquidException as e:
    print(f"Hyperliquid error: {e}")

Key error behaviors:

  • get_open_orders() raises on API failure (never silently returns empty list)
  • cancel_all_orders() raises if any cancellation fails, reporting which orders failed
  • cancel_order() returns False if order not found, raises on real errors
  • close() logs a warning if the IOC order doesn't fill

Logging

import logging

# Show info-level logs
logging.basicConfig(level=logging.INFO)

# For detailed debugging (API calls, order details, retry attempts)
logging.basicConfig(level=logging.DEBUG)

All logs are under the fractrade_hl_simple logger.

Using the API Module

All client methods are also available as standalone functions:

from fractrade_hl_simple import buy, get_price, get_fills, set_leverage

price = get_price("BTC")
order = buy("BTC", 0.001)
fills = get_fills("BTC")
set_leverage("BTC", 10)

Complete Example

from fractrade_hl_simple import HyperliquidClient

client = HyperliquidClient(default_slippage=0.03, max_retries=3)

# Check balance
balance = client.get_perp_balance()
print(f"Balance: ${float(balance):,.2f}")

# Set leverage
client.set_leverage("BTC", 10)

# Open long with TP/SL
price = client.get_price("BTC")
position = client.open_long_position(
    "BTC", size=0.001,
    stop_loss_price=price * 0.95,
    take_profit_price=price * 1.10,
)
print(f"Entry: {position['entry'].order_id}")

# Monitor fills
fills = client.get_fills("BTC")
for fill in fills[:5]:
    print(f"  {fill.direction} {fill.size} @ {fill.price}")

# Close when done
client.close("BTC")

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT

Disclaimer

This software is provided as-is. Use at your own risk. The authors take no responsibility for any financial losses incurred while using this software. Always test thoroughly on testnet before trading with real funds.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fractrade_hl_simple-0.2.0.tar.gz (31.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fractrade_hl_simple-0.2.0-py3-none-any.whl (30.1 kB view details)

Uploaded Python 3

File details

Details for the file fractrade_hl_simple-0.2.0.tar.gz.

File metadata

  • Download URL: fractrade_hl_simple-0.2.0.tar.gz
  • Upload date:
  • Size: 31.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.6.1 CPython/3.11.5 Linux/6.12.63+deb13-amd64

File hashes

Hashes for fractrade_hl_simple-0.2.0.tar.gz
Algorithm Hash digest
SHA256 2a4832482032c6349ce05cb7af60ef0b3ee133517d5d52f9b6489f7417160c43
MD5 fb9833d7bfa16c3b9d1e7ddcdf9abea6
BLAKE2b-256 57aa596d7473b5b6cdedad25d77f211d625654a324ba9d98a0e39d27340b70cc

See more details on using hashes here.

File details

Details for the file fractrade_hl_simple-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: fractrade_hl_simple-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 30.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.6.1 CPython/3.11.5 Linux/6.12.63+deb13-amd64

File hashes

Hashes for fractrade_hl_simple-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 29f50333aad8801e97482098239bfd5112e1a8395e50d1b749ec4948b3ea76ff
MD5 27a04d230f5f5ca06f95aeee5c7a4e5b
BLAKE2b-256 1cc8927b55ae579f65546d25b38d383aed6e50b837b4ee23aa71d08c69da4687

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page