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.2.tar.gz (31.5 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.2-py3-none-any.whl (30.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: fractrade_hl_simple-0.2.2.tar.gz
  • Upload date:
  • Size: 31.5 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.2.tar.gz
Algorithm Hash digest
SHA256 c4ab23370009ca50ec85d0c2d9cd9a309f05d5dd0ea0ebcef54dfbc425f0fdf7
MD5 50345d3ea83a16c7df98f72e9039f663
BLAKE2b-256 32a2ab870693c927fb959692a33779c06d74406a67d3e25719b178765917f4e5

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fractrade_hl_simple-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 30.3 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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7d846d6c494fcffd81eebf6db00a8b6d1bffe0dafb7552d35b93c970bf14fa59
MD5 e5ff9c39c720a1573ac33af64cd11648
BLAKE2b-256 d6d6dde44f08ce912ad115cc1ce8f0f12c4c049819bd33ef1858e2d2f5208832

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