Recipe 62 of 65
Build 1-second candles for a Hyperliquid coin
The API's time bars start at 1 minute; build 1-second bars from the archive's daily fills file by keeping the taker row of each trade, ordering by fill_ts and trade_id, and bucketing by second.
GET /v1/hyperliquid/archive/url answers it with one download, because GET /v1/hyperliquid/ohlcv serves time bars
from 1m up only. Build 1-second bars from the archive's daily fills file, which has every fill with a millisecond
fill_ts. Keep one row per trade (the taker side, is_maker = false),
order by fill_ts then trade_id, and bucket by second. Built this way, the bars add up exactly to the API's
1-minute bars. The full parameter lists are on Archive download link and
Candles.
Quick answer
Download one day, then bucket the taker rows by second in Polars.
# download one UTC day of every fill: redirect=1 answers with the link and -L follows it
curl -s -L -H "X-API-Key: $VIKE_API_KEY" -o fills-2026-10-23.parquet \
"https://data.vike.io/v1/hyperliquid/archive/url?dataset=fills&date=2026-10-23&redirect=1"import polars as pl
fills = pl.read_parquet("fills-2026-10-23.parquet") # or the free fills-sample.parquet
bars = (
fills.filter((pl.col("asset") == "BTC") & ~pl.col("is_maker")) # the taker row: one row per trade
.sort("fill_ts", "trade_id")
.group_by_dynamic("fill_ts", every="1s")
.agg(
open=pl.col("price").first(),
high=pl.col("price").max(),
low=pl.col("price").min(),
close=pl.col("price").last(),
volume=pl.col("size_token").sum(),
volume_usd=pl.col("size_usd").sum(),
n_trades=pl.len(),
)
)
print(bars.head())Example response
Computed with the Polars code on the free fills sample, captured from the live API on 2026-10-24 at 17:16 UTC (every BTC fill of 2026-10-21 00:00 to 01:00 UTC), shown as JSON, the first 4 of 2,346 one-second bars.
fill_ts is the start of the second, UTC. volume is BTC, volume_usd USD, n_trades trades in that second. There is
no bar for 00:00:01 or 00:00:03: nothing traded. Rolled up to minutes, these bars match the API's 1-minute bars for
the same minutes exactly (00:00: open 82,991, high 82,991, low 82,918, close 82,932, 11.14182 BTC, 235 trades).
[
{"fill_ts": "2026-10-21T00:00:00.000Z", "open": 82991.0, "high": 82991.0, "low": 82991.0, "close": 82991.0, "volume": 0.001, "volume_usd": 82.991, "n_trades": 1},
{"fill_ts": "2026-10-21T00:00:02.000Z", "open": 82991.0, "high": 82991.0, "low": 82988.0, "close": 82989.0, "volume": 0.16127, "volume_usd": 13383.94634, "n_trades": 6},
{"fill_ts": "2026-10-21T00:00:04.000Z", "open": 82976.0, "high": 82977.0, "low": 82976.0, "close": 82977.0, "volume": 0.00727, "volume_usd": 603.24264, "n_trades": 2},
{"fill_ts": "2026-10-21T00:00:05.000Z", "open": 82975.0, "high": 82975.0, "low": 82975.0, "close": 82975.0, "volume": 0.00148, "volume_usd": 122.803, "n_trades": 1}
]Variations
Check against the API. The same minutes from the API, to confirm your build.
# the API's first three BTC minutes of 2026-10-21
curl -H "X-API-Key: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/ohlcv?symbol=BTC&interval=1m&start=2026-10-21T00:00:00Z&limit=3"Trade-count bars from the API. If what you want is finer than a minute rather than exactly a second, the API serves bars of N trades from the same fills, up to the present.
# 100-trade BTC bars over ten minutes
curl -H "X-API-Key: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/ohlcv?symbol=BTC&interval=100t&start=2026-10-23T12:00:00Z&end=2026-10-23T12:10:00Z&limit=500"Fill the empty seconds. A backtest that expects one bar per second needs the gaps filled: carry close forward with zero volume.
grid = pl.datetime_range(bars["fill_ts"].min(), bars["fill_ts"].max(), "1s", time_unit="ms", time_zone="UTC", eager=True).alias("fill_ts").to_frame()
full = grid.join(bars, on="fill_ts", how="left").with_columns(
pl.col("close").forward_fill(),
pl.col("volume", "volume_usd", "n_trades").fill_null(0),
).with_columns(pl.col("open", "high", "low").fill_null(pl.col("close")))On the sample hour this turns 2,346 bars into the full 3,600.
Before you rely on it
History only, from the daily files
The fills file of a UTC day is published in the early UTC morning after the day ends, from 2026-05-01, so 1-second bars
are history, not live. For finer-than-minute bars up to now, use the API's trade-count bars (interval=100t). Its
1-trade bars (interval=1t) carry whole-second timestamps and come back in no fixed order within a second, so they
give a second's high, low and volume but not its open and close.
Count each trade once; liquidations are not flagged
Both sides of every trade are in the file. Keeping is_maker = false counts each trade once, as the API does; summing
all rows doubles the volume. Order by fill_ts and trade_id together: many trades share a millisecond. Nothing in the
file marks a fill as a liquidation.
Ask your agent
No MCP tool returns sub-minute bars: hl_ohlcv starts at 1 minute, so use the file.