Hyperliquid Market

Spot and perpetuals. tribulnation-hyperliquid, venue name hyperliquid.

See the generic market interface for the shared method surface. This page covers only what is Hyperliquid-specific.

Account

venue selects the network: hyperliquid is mainnet, hyperliquid_testnet is testnet. An address without a private_key is read-only. The built-in hyperliquid account is accounts.Hyperliquid(public=True), read-only.

Exchanges & ID conventions

Hyperliquid exposes several exchanges under one venue. exchanges() reports:

exchange_id Type What it is
spot spot The spot exchange.
'' (empty) perp The default perpetuals DEX.
<dex-name> perp A named builder-deployed perp DEX.

For perps, exchange_id is the DEX name; the empty string means the default/no-DEX universe. Under the hood perp_exchange(dex) treats '' and None equivalently.

Market IDs by exchange:

  • Perp — the asset name, e.g. BTC. Full ID: hyperliquid::BTC (empty exchange segment = default DEX) or hyperliquid:<dex>:BTC.
  • Spot — canonical form BASE/QUOTE:ASSET_IDX, e.g. BTC/USDC:0. Full ID: hyperliquid:spot:BTC/USDC:0. The ASSET_IDX is Hyperliquid's spotMeta.universe[].index; market() cross-checks that the BASE/QUOTE names match that index and raises on mismatch. Exchange.markets() returns fully-formed BASE/QUOTE:IDX strings you can pass straight back in.

Settings

place_order and index accept settings={'hyperliquid': {...}}, typed by the Settings TypedDict (core/settings.py). All keys are optional:

Key Type Applies to Meaning
reduce_only bool place_order Place as reduce-only.
limit_tif TimeInForce place_order Time-in-force for limit orders.
index_price 'oracle' | 'mark' index (perp) Which price index() returns; defaults to 'oracle'.

index_price='mark' returns the market's mark price, falling back to the oracle price when mark is unavailable; the default 'oracle' always returns the oracle price.

Venue-specific semantics

  • Spot and perp markets are separate objects (SpotMarket / PerpMarket) with their own rules and position logic. Only PerpMarket exposes funding and index().
  • candles raises NotImplementedError on both, and CANDLE_INTERVALS is empty: info.candle_snapshot answers at most 5000 candles per call and the typed client declares no paged walk for it yet, so the series cannot be swept through the client.
  • Perp available_notional/leverage and spot balances are computed against Hyperliquid-native metadata (asset/collateral tokens, user fees), cached venue-wide and refreshed lazily.
  • perp_collateral at the exchange level returns the account cross pool in unified account mode. The implementation asserts user_abstraction == "unifiedAccount" and raises on other modes. In unified mode, the real equity backing perps is the spot collateral token balance (determined by perp_meta['collateralToken'], USDC for the default DEX), not crossMarginSummary.accountValue (which only reflects USDC deposited into the perps engine). Fields: equity=spot_collateral_balance, free_collateral=tokenToAvailableAfterMaintenance for the collateral token, initial_margin=equity-free_collateral, maintenance_margin=crossMaintenanceMarginUsed, leverage=totalNtlPos/equity, margin_mode='cross'. Market.perp_collateral() is mode-aware: it finds the asset in assetPositions and branches on the position's leverage type — a cross position reports the same cross pool, while an isolated position gets its own bucket from that position's rawUsd + unrealizedPnl (equity), marginUsed (= initial_margin), and margin_mode='isolated'. HL gives no isolated maintenance figure directly, so it is approximated as positionValue / (2 · maxLeverage) (half the initial-margin fraction at max leverage).
  • collateral (spot) returns the quote-token balance (equity=total, free_collateral=total-hold).
  • Builder-DEX perps use a DEX-scoped asset-id formula (100000 + dex_idx*10000 + asset_idx); default-DEX perps use the plain asset index. This only matters internally — you address markets by name.

Example

from dotenv import load_dotenv
from tribulnation.sdk import MarketSDK, accounts

load_dotenv()

sdk = MarketSDK({'hl': accounts.Hyperliquid()})

# default-DEX perp
await sdk.index('hl::BTC')

# spot
book = await sdk.depth('hl:spot:BTC/USDC:0')

await sdk.place_order(
  'hl::ETH',
  {
    'type': 'LIMIT',
    'qty': 0.01,
    'price': 1000,
  },
  settings={'hyperliquid': {'limit_tif': 'Alo', 'reduce_only': False}},
)