Local-first quantitative research toolkit for Hyperliquid.
Project description
hl-research
A Python toolkit for quantitative research on Hyperliquid. Pulls historical data from the HL info API on demand, caches it locally as Parquet, and ships research primitives for backtesting, wallet behavior analysis, vault inspection, and funding research. Runs from a laptop. No infrastructure.
pip install hl-research
The headline feature
Paste a wallet, get a self-contained HTML report:
hlr data pull-fills 0xabc... --since 2024-01-01
hlr wallet wrapped 0xabc... --out wrapped.html
open wrapped.html
PnL by asset, hour-of-day pattern, hold-time distribution, funding ledger, behavior cluster, counterfactual vs holding spot, top wins and losses. One file. Shareable.
Contents
Quickstart
Requires Python 3.12 or newer.
pip install hl-research
# Pull cache for one asset
hlr data pull BTC --since 2024-01-01
hlr data pull-funding BTC --since 2024-01-01
# See what's cached
hlr data ls
# Inspect a wallet (live)
hlr wallet inspect 0xabc...
# Build the wrapped report
hlr data pull-fills 0xabc... --since 2024-01-01
hlr wallet wrapped 0xabc... --out wrapped.html
# Browse interactively
hlr tui
Every command supports --json for piping into scripts. Report commands accept --out PATH for standalone HTML artifacts.
What you get
| Command group | What it does |
|---|---|
hlr data |
Incremental Parquet cache (DuckDB metadata) over the HL info API |
hlr wallet |
Inspect any wallet, build wrapped reports, list fills and funding |
hlr funding |
Funding-rate history, cross-asset heatmap, perp-perp basis, naive prediction |
hlr vault |
List, rank, and inspect HLP and user vaults |
hlr backtest |
Run strategy files written in plain Python, grid + random optimization, walk-forward |
hlr tui |
Six-screen Textual app over the same data layer |
Tour by command group
hlr data — local cache
The cache is the foundation. Everything else reads from it.
$ hlr data ls
KIND ENTITY INTERVAL ROWS SIZE SINCE UNTIL UPDATED
────────────────────────────────────────────────────────────────────────────────────────────────
candles BTC 1h 720 34.68 KB 2024-04-01 2024-04-30 2026-05-19 15:44
candles ETH 1h 720 34.95 KB 2024-04-01 2024-04-30 2026-05-19 15:44
candles SOL 1h 720 35.12 KB 2024-04-01 2024-04-30 2026-05-19 15:44
fills 0xa1b2…0000 — 18 6.27 KB 2024-04-01 2024-04-12 2026-05-19 15:44
funding BTC — 720 14.16 KB 2024-04-01 2024-04-30 2026-05-19 15:44
funding ETH — 720 14.27 KB 2024-04-01 2024-04-30 2026-05-19 15:44
$ hlr data info
╭─ cache ──────────────────────────────────────────────────────────────────────╮
│ │
│ CACHE DIRECTORY ~/.cache/hl-research │
│ TOTAL SIZE 203.08 KB │
│ FILES 9 │
│ DATASETS 9 │
│ LAST SYNC 2026-05-19 15:44 │
│ │
╰──────────────────────────────────────────────────────────────────────────────╯
Incremental by default — re-running pull resumes from the last cached candle.
hlr wallet — paste an address
Live account state:
hlr wallet inspect 0xabc...
Behavioral wrapped report (see screenshot above) — the headline artifact:
hlr wallet wrapped 0xabc... --out wrapped.html
Without --out you get a terminal summary:
╭─ wallet wrapped ─────────────────────────────────────────────────────────────╮
│ │
│ WALLET 0xa1b2…0000 │
│ PERIOD 2024-04-01 → 2024-04-12 │
│ REALIZED PNL +$4,240.00 │
│ FUNDING NET $0.00 │
│ WIN RATE 88.9% │
│ TRADES 9 │
│ CLUSTER chad │
│ Win rate was at least 65% and total PnL exceeded 1k. │
│ │
│ HOLD vs ACTUAL -$17,908.51 (pass --out to write the full HTML report) │
│ │
╰──────────────────────────────────────────────────────────────────────────────╯
Behavior clusters are rules-based — revenge_trader, funding_farmer, scalper, swing_trader, chad, leverage_addict, hold_and_pray, balanced. The output includes the reason that triggered the classification.
hlr funding — rates, basis, prediction
Cross-asset funding snapshot, sorted by absolute rate, annualized APR on the right:
$ hlr funding heatmap
ASSET RATE
──────────────────────────────────────────────────────────────────────────────────────────────
BTC +0.0147% │████████████████████████████ +16.1% APR
SOL +0.0134% │█████████████████████████ +14.7% APR
HYPE -0.0059% ███████████│ -6.4% APR
ETH +0.0014% │███ +1.5% APR
History + sparkline:
$ hlr funding history BTC
╭─ funding history ────────────────────────────────────────────────────────────╮
│ │
│ ASSET BTC │
│ OBSERVATIONS 720 │
│ RANGE 2024-04-01 → 2024-04-30 │
│ LATEST +0.0147% / period │
│ MEAN +0.0126% / period │
│ │
│ ▄▂▁▁▄▄▅▇▅▂▇█▄▂▆▇▄▆▂▁▂▇▅▃▅▆▅▆▃▂▂▃▃▃▇▂▃▅▁▁▇▆▇▇▃▂▆▇▃▁ │
│ │
╰──────────────────────────────────────────────────────────────────────────────╯
Perp-vs-perp basis leaderboard:
$ hlr funding arb BTC
PAIR LATEST BASIS ANNUALIZED MEAN BASIS N
────────────────────────────────────────────────────────────
BTC / HYPE +0.0206% +22.52% +0.0168% 720
BTC / ETH +0.0133% +14.60% +0.0035% 720
BTC / SOL +0.0013% +1.45% -0.0036% 720
Naive EWMA prediction with disclaimer:
$ hlr funding predict BTC
╭─ funding prediction ─────────────────────────────────────────────────────────╮
│ │
│ PREDICTED RATE +0.0111% │
│ LOWER (95%) +0.0013% │
│ UPPER (95%) +0.0209% │
│ │
│ Naive EWMA baseline. Do not trade on this without a real model. │
│ │
╰──────────────────────────────────────────────────────────────────────────────╯
hlr backtest — strategies in plain Python
# my_strategy.py
from hl_research.backtest.strategy import Order, Strategy
class MeanReversion(Strategy):
def __init__(self):
super().__init__()
self._lookback = []
def on_candle(self, candle, ctx):
self._lookback.append(candle.close)
if len(self._lookback) > 20:
self._lookback.pop(0)
mean = sum(self._lookback) / len(self._lookback)
position = ctx.positions.get(candle.asset)
held = position.size if position else 0.0
if candle.close < mean * 0.99 and held <= 0:
return [Order(asset=candle.asset, side="buy", size=0.05, kind="market")]
if candle.close > mean * 1.01 and held > 0:
return [Order(asset=candle.asset, side="sell", size=abs(held),
kind="market", reduce_only=True)]
return []
$ hlr backtest run my_strategy.py --asset BTC
╭─ backtest ───────────────────────────────────────────────────────────────────╮
│ │
│ STRATEGY MeanReversion │
│ ASSET BTC │
│ PERIOD 2024-04-01 → 2024-04-30 │
│ │
│ TOTAL RETURN -2.43% │
│ SHARPE -1.18 │
│ MAX DRAWDOWN -2.43% │
│ HIT RATE +0.00% │
│ PROFIT FACTOR 0.00 │
│ TRADES 4 │
│ NET FUNDING -$149.27 │
│ │
╰──────────────────────────────────────────────────────────────────────────────╯
╭─ equity ─────────────────────────────────────────────────────────────────────╮
│ │
│ ████████▇▇▆▆▆▆▆▆▆▆▆▆▆▆▅▅▄▄▄▄▄▄▄▄▄▄▄▃▃▃▃▃▃▃▃▃▃▃▂▂▁▁▁▁▁▁▁▁▁▁▁▁ │
│ │
│ START $100,000.00 END $97,571.67 │
│ PEAK $100,000.00 TROUGH $97,571.67 │
│ CHANGE -$2,428.33 (-2.43%) │
│ │
╰──────────────────────────────────────────────────────────────────────────────╯
The example loses money on this short window — backtesting on a month of one asset is a sanity check, not an alpha signal.
Optimization and walk-forward:
hlr backtest optimize my_strategy.py --param "lookback:10..30:5"
hlr backtest walk-forward my_strategy.py --window 90d --step 30d
hlr backtest run my_strategy.py --asset BTC --out report.html
hlr tui — interactive Textual app
hlr tui
Two-pane layout with six sections. 1–6 to switch, / for the asset picker, r to reload, q to quit. All views reuse the same cache and analytics the CLI uses.
Architecture
HL info endpoint
│
▼
api/ typed httpx client, retries, rate limit
│
▼
cache/ Parquet on disk, DuckDB metadata, incremental sync
│
▼
data/ Polars LazyFrames, pure transforms
│
├──▶ analytics/ wrapped, behavior, counterfactual, funding, vault
├──▶ backtest/ event loop, fill simulation, metrics, optimizer
└──▶ presentation/ Rich tables, Plotly charts, Jinja2 reports
│
└──▶ cli/, tui/
The data layer never calls presentation. Presentation never calls the API. The CLI binds the two. Pure functions in analytics/, frozen dataclasses everywhere, mypy strict across 79 source files.
Cache layout on disk:
~/.cache/hl-research/
├── meta.duckdb # sync state, asset and vault tables
└── data/
├── candles/asset=BTC/interval=1h/2024-04.parquet
├── funding/asset=BTC/2024.parquet
├── fills/wallet=0xabc.../2024-Q2.parquet
└── vaults/address=0xvault.../trades.parquet
Partitioned for Polars and DuckDB. Re-pulling resumes from the last cached row.
FAQ
Does this need a Hyperliquid account? No. Every endpoint hl-research uses is public.
Does it trade? No. hl-research is read-only by design. It never holds keys, places orders, or signs anything.
What data is missing? L2 microstructure history. Tick-level book data isn't available from the public API and we can't reconstruct it without a continuous ingestor. Candles, funding, fills, and vault state are all here.
How big does the cache get? ~50MB for two years of top-20 assets at 1h candles + funding. Active trader wallet fills add 1-10MB per wallet.
Can I use this in a notebook?
Yes — see examples/basic_backtest.ipynb and examples/wallet_analysis.ipynb. Every CLI command has a programmatic equivalent under hl_research.*.
What about live mode? On the v0.2 roadmap. Today everything is on-demand from the REST endpoint.
How do I contribute? See CONTRIBUTING.md. Issues and PRs welcome.
Install
pip install hl-research
Or with uv:
uv pip install hl-research
Optional extras:
pip install "hl-research[plot]" # matplotlib + plotly for charts
pip install "hl-research[tui]" # Textual interactive app
pip install "hl-research[all]" # everything
Docs
Full reference at ramenxbt.github.io/hl-research.
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hl_research-0.1.0.tar.gz.
File metadata
- Download URL: hl_research-0.1.0.tar.gz
- Upload date:
- Size: 91.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
39384672f5808a44888cb4ab02d2e58d25cb57a1740115ccbf9a28582993353b
|
|
| MD5 |
5e3763aba001c84b307359b3940f2e36
|
|
| BLAKE2b-256 |
b67860748c136c545d1dc873bdade90d6611fea0f01970c2b4b19329f081e5f6
|
Provenance
The following attestation bundles were made for hl_research-0.1.0.tar.gz:
Publisher:
release.yml on ramenxbt/hl-research
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hl_research-0.1.0.tar.gz -
Subject digest:
39384672f5808a44888cb4ab02d2e58d25cb57a1740115ccbf9a28582993353b - Sigstore transparency entry: 1575170098
- Sigstore integration time:
-
Permalink:
ramenxbt/hl-research@4d705f851a84958b0e37f05a86aa20a84b498bbf -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ramenxbt
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4d705f851a84958b0e37f05a86aa20a84b498bbf -
Trigger Event:
push
-
Statement type:
File details
Details for the file hl_research-0.1.0-py3-none-any.whl.
File metadata
- Download URL: hl_research-0.1.0-py3-none-any.whl
- Upload date:
- Size: 109.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d981e1fb394186b9dded5a52baa445700e7e5e982afdc5c4e177643a0adb566c
|
|
| MD5 |
f5b42aa8a7b7776ff88a0ef7b038981b
|
|
| BLAKE2b-256 |
095ec3ca8453b89f58527a64d5b4821966d2e7b5412577c5d1ac75620b1ccb73
|
Provenance
The following attestation bundles were made for hl_research-0.1.0-py3-none-any.whl:
Publisher:
release.yml on ramenxbt/hl-research
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hl_research-0.1.0-py3-none-any.whl -
Subject digest:
d981e1fb394186b9dded5a52baa445700e7e5e982afdc5c4e177643a0adb566c - Sigstore transparency entry: 1575170112
- Sigstore integration time:
-
Permalink:
ramenxbt/hl-research@4d705f851a84958b0e37f05a86aa20a84b498bbf -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ramenxbt
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4d705f851a84958b0e37f05a86aa20a84b498bbf -
Trigger Event:
push
-
Statement type: