> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ironflow.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Freqtrade Hyperliquid historical data

> Backtest Freqtrade on Hyperliquid perps past the 5,000-candle limit: free hourly candles and funding since June 2025 with no key, and 1m to 30m with a key.

Hyperliquid's API only returns about the last 5,000 candles per interval, so Freqtrade cannot download a long Hyperliquid backtest. Write Ironflow history straight into Freqtrade's data folder instead.

Tested with Freqtrade 2026.10.

## Hourly history, no key

Free hourly candles and funding, from June 2025 to the last full month. Run this from your Freqtrade directory:

```python ironflow_history.py theme={null}
"""Write Ironflow's free Hyperliquid history as Freqtrade futures data."""
from pathlib import Path

import pandas as pd
from freqtrade.data.history import get_datahandler
from freqtrade.enums import CandleType

COINS = ["BTC", "ETH"]
MONTHS = pd.period_range("2025-06", "2026-10", freq="M").strftime("%Y-%m")
URL = "https://huggingface.co/datasets/ironflow/hyperliquid-{}/resolve/main/data/{}.parquet"


def load(dataset):
    df = pd.concat(pd.read_parquet(URL.format(dataset, m)) for m in MONTHS)
    return df.rename(columns={"timestamp": "date"})


candles = load("candles-1h")
funding = load("funding")
funding["date"] = funding["date"].dt.floor("h")

datadir = Path("user_data/data/hyperliquid")
(datadir / "futures").mkdir(parents=True, exist_ok=True)
store = get_datahandler(datadir, "feather")
for coin in COINS:
    pair = f"{coin}/USDC:USDC"
    store.ohlcv_store(pair, "1h", candles[candles.coin == coin].sort_values("date"), CandleType.FUTURES)
    store.ohlcv_store(pair, "1h", funding[funding.coin == coin].sort_values("date"), CandleType.FUNDING_RATE)
    print(pair, len(candles[candles.coin == coin]), "candles")
```

Then backtest. Your config needs `"trading_mode": "futures"`, `"margin_mode": "isolated"`, `"stake_currency": "USDC"`, `"exchange": {"name": "hyperliquid", "pair_whitelist": ["BTC/USDC:USDC", "ETH/USDC:USDC"]}` and `"timeframe": "1h"`:

```bash theme={null}
python ironflow_history.py
freqtrade backtesting --config config.json --strategy SampleStrategy --timerange 20250601-20261031
```

That covers more than 12,000 hourly candles per pair. Extend `MONTHS` as new months are published.

## 1m to 30m, with a key

The free candle dataset is hourly. For shorter timeframes use `/v1/candles` with your key:

```python ironflow_recent.py theme={null}
"""Write recent Hyperliquid candles and funding as Freqtrade data, using your key."""
import os
import time
from pathlib import Path

import pandas as pd
import requests
from freqtrade.data.history import get_datahandler
from freqtrade.enums import CandleType

API = "https://api.ironflow.sh/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['IRONFLOW_KEY']}"}
COINS = ["BTC"]
TIMEFRAME = "5m"
DAYS = 13  # free key: 14 days, Explorer: 90, Builder: 365

end = pd.Timestamp.now("UTC").floor("h")
span = {"from": int((end - pd.Timedelta(days=DAYS)).floor("D").timestamp() * 1000), "to": int(end.timestamp() * 1000)}


def fetch(path, **params):
    rows = []
    params.update(span, limit=1000)
    while True:
        r = requests.get(f"{API}/{path}", params=params, headers=HEADERS, timeout=30)
        if r.status_code == 429:
            time.sleep(int(r.headers.get("Retry-After", 5)))
            continue
        r.raise_for_status()
        body = r.json()
        rows += body["data"]
        if not body["pagination"]["has_more"]:
            df = pd.DataFrame(rows)
            df["date"] = pd.to_datetime(df["timestamp"], unit="ms", utc=True)
            return df
        params["cursor"] = body["pagination"]["next_cursor"]


def candles(market, interval):
    df = fetch("candles", market=market, interval=interval)
    df[["open", "high", "low", "close", "volume"]] = df[["open", "high", "low", "close", "volume"]].astype(float)
    return df


datadir = Path("user_data/data/hyperliquid")
(datadir / "futures").mkdir(parents=True, exist_ok=True)
store = get_datahandler(datadir, "feather")
for coin in COINS:
    pair, market = f"{coin}/USDC:USDC", f"{coin}-PERP"
    store.ohlcv_store(pair, TIMEFRAME, candles(market, TIMEFRAME), CandleType.FUTURES)
    store.ohlcv_store(pair, "1h", candles(market, "1h"), CandleType.FUTURES)  # Freqtrade needs 1h for funding
    funding = fetch("funding", market=market)
    funding["date"] = funding["date"].dt.floor("h")
    funding = funding.drop_duplicates("date")  # first reading of each hour
    funding["funding_rate"] = funding["rate"].astype(float)
    store.ohlcv_store(pair, "1h", funding, CandleType.FUNDING_RATE)
    print(pair, "done")
```

```bash theme={null}
IRONFLOW_KEY=if_your_key python ironflow_recent.py
freqtrade backtesting --config config.json --strategy SampleStrategy --timeframe 5m
```

## Plan limits

| Access | History | Requests |
| - | - | - |
| [Free datasets](https://docs.ironflow.sh/guides/datasets.md), no key | Hourly candles from 25 May 2025, funding from May 2023, updated monthly | No limit |
| Free key | 14 days | 60 a minute |
| Explorer | 90 days | 100 a minute |
| Builder | 1 year | 1,000 a minute |
| Enterprise | Everything stored | 10,000 a minute |

A free key's 14 days is 20,160 `1m` candles. Hourly it is 336, so use the free dataset above for long hourly tests. [Get a free key](https://ironflow.sh/key) or see [all plans](https://docs.ironflow.sh/concepts/rate-limits.md).

Candles are built from every fill, so high, low and trade count can differ from Hyperliquid's own candles in heavy liquidation hours.

Next: [paper trade on Hyperliquid](https://ironflow.sh/guides/hyperliquid-paper-trading) with the official SDK, \$10,000 and live prices.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.