from decimal import Decimal
from pathlib import Path
import pandas as pd
from nautilus_trader.model.currencies import BTC, USDC
from nautilus_trader.model.data import Bar, BarType
from nautilus_trader.model.identifiers import InstrumentId, Symbol
from nautilus_trader.model.instruments import CryptoPerpetual
from nautilus_trader.model.objects import Price, Quantity
from nautilus_trader.persistence.catalog import ParquetDataCatalog
MONTHS = pd.period_range("2025-06", "2026-10", freq="M").strftime("%Y-%m")
URL = "https://huggingface.co/datasets/ironflow/hyperliquid-candles-1h/resolve/main/data/{}.parquet"
COLS = ["timestamp", "coin", "open", "high", "low", "close", "volume"]
raw = pd.concat(pd.read_parquet(URL.format(m), columns=COLS) for m in MONTHS)
btc = raw[raw.coin == "BTC"].sort_values("timestamp").set_index("timestamp")
# BTC settings. For another coin use szDecimals from Hyperliquid's meta as size_precision.
instrument = CryptoPerpetual(
instrument_id=InstrumentId.from_str("BTC-USD-PERP.HYPERLIQUID"), raw_symbol=Symbol("BTC"),
base_currency=BTC, quote_currency=USDC, settlement_currency=USDC, is_inverse=False,
price_precision=1, size_precision=5, price_increment=Price.from_str("0.1"),
size_increment=Quantity.from_str("0.00001"), ts_event=0, ts_init=0,
maker_fee=Decimal("0.00015"), taker_fee=Decimal("0.00045"),
margin_init=Decimal("0.05"), margin_maint=Decimal("0.025"),
)
bar_type = BarType.from_str("BTC-USD-PERP.HYPERLIQUID-1-HOUR-LAST-EXTERNAL")
# Nautilus stamps a bar at its close, Ironflow candles at their open.
bars = [
Bar(
bar_type,
instrument.make_price(row.open),
instrument.make_price(row.high),
instrument.make_price(row.low),
instrument.make_price(row.close),
instrument.make_qty(row.volume),
(int(row.Index.timestamp()) + 3600) * 1_000_000_000,
(int(row.Index.timestamp()) + 3600) * 1_000_000_000,
)
for row in btc.itertuples()
]
Path("catalog").mkdir(exist_ok=True)
catalog = ParquetDataCatalog("catalog")
catalog.write_data([instrument])
catalog.write_data(bars)
print(len(bars), "bars")