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.1.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.1-py3-none-any.whl (30.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: fractrade_hl_simple-0.2.1.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.1.tar.gz
Algorithm Hash digest
SHA256 3090b755e2fa65606afb22b651f7933407c7bb4a8ae4decb7a74a04b1cfa5fa4
MD5 06241739d1dc579417ea865a7210149a
BLAKE2b-256 5ab803da679fd277ed79b86422e9d1e3fa2c5b526c11dcc9a8e36b070dbe26c4

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fractrade_hl_simple-0.2.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9b8f0ae7669ade815390b780166c9335c19b98880cee800509be52175e14e331
MD5 724c6c75b0bf23affc1aeaae692730ae
BLAKE2b-256 7f75cbfe1800b787f1cbfdd710340add78f5aa86b2e2973950021c95b4a9b6f5

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