vike

Recipe 61 of 65

Who traded against whom? Pair both counterparties of every Hyperliquid trade

In the archive's daily fills file both sides of a trade share trade_id; join the buy rows to the sell rows on asset, fill_ts and trade_id to get one row per trade with its buyer and seller.

GET /v1/hyperliquid/archive/url answers it with one download per day. The daily fills file holds one row per wallet and fill, so every trade appears twice: once for the buyer, once for the seller, with the same trade_id, fill_ts, price and size. Join the buy rows to the sell rows on asset, fill_ts and trade_id and you have one row per trade with both wallets, and is_maker says which side was resting on the book. The full parameter list is on Archive download link.

Quick answer

Download one day, then join the two sides in Polars.

cURL
# 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"
Polars
import polars as pl

fills = pl.read_parquet("fills-2026-10-23.parquet")  # or the free fills-sample.parquet
key = ["asset", "fill_ts", "trade_id"]
buys = fills.filter(pl.col("side") == "buy").select(*key, "price", "size_token", buyer="wallet", buyer_maker="is_maker")
sells = fills.filter(pl.col("side") == "sell").select(*key, seller="wallet")
trades = buys.join(sells, on=key)
print(trades.height, "trades from", fills.height, "fills")

pairs = (
    trades.group_by("buyer", "seller")
    .agg(usd=(pl.col("price") * pl.col("size_token")).sum(), trades=pl.len())
    .sort("usd", descending=True)
)
print(pairs.head(10))  # the wallet pairs that traded the most notional with each other

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 3 paired trades and the top 3 wallet pairs.

The 16,830 fills paired into exactly 8,415 trades: every trade_id had one buy row and one sell row, none was left over, and no wallet was on both sides. buyer_maker: false means the buyer crossed the book and the seller, here the same wallet three times, was resting. usd is the pair's traded notional over the hour.

Example response
{
  "trades": [
    {"fill_ts": "2026-10-21T00:00:00.503Z", "trade_id": 644315352389798, "price": 82991.0, "size_token": 0.001, "buyer": "0xd49eaf821d8fe887e043ef1510b77f461ae7e1fa", "seller": "0xa62b923a112d50d03e1e096bbd53422490dac104", "buyer_maker": false},
    {"fill_ts": "2026-10-21T00:00:02.073Z", "trade_id": 127035752616954, "price": 82991.0, "size_token": 0.00018, "buyer": "0xb8d7bbfa7c135239f7f850f916b0e51ca9e2a700", "seller": "0xa62b923a112d50d03e1e096bbd53422490dac104", "buyer_maker": false},
    {"fill_ts": "2026-10-21T00:00:02.165Z", "trade_id": 582937235624021, "price": 82991.0, "size_token": 0.00257, "buyer": "0x4aa5f7febdd1996f00e2910593ae7190ae3f72ec", "seller": "0xa62b923a112d50d03e1e096bbd53422490dac104", "buyer_maker": false}
  ],
  "top_pairs": [
    {"buyer": "0x5986347c1d0133d02d307f08bb1efd44c2eb89d9", "seller": "0xcf3f419d08a5bdc2c6e5fbd9ad70904c5420f95f", "usd": 1546732.47, "trades": 5},
    {"buyer": "0xb90dfbd7fad293b11f30fbf6b53a90cf9c65870c", "seller": "0xf5d81a135f756ca16544e53c20fc20643ec3ad53", "usd": 1263798.56, "trades": 86},
    {"buyer": "0x5986347c1d0133d02d307f08bb1efd44c2eb89d9", "seller": "0xaf9f722a676230cc44045efe26fe9a85801ca4fa", "usd": 1016680.86, "trades": 1}
  ]
}

Variations

Self-trades and tight loops. For a wash-trading check, look for a wallet on both sides, and for two wallets that trade both ways with each other.

Polars — wash check
print(trades.filter(pl.col("buyer") == pl.col("seller")).height)  # 0 on the sample
both_ways = pairs.join(pairs, left_on=["buyer", "seller"], right_on=["seller", "buyer"], suffix="_back")
print(both_ways.sort("usd", descending=True).head(10))

Each two-way pair shows twice, once from each end. On the sample, 0xf517…c032 bought $934,935 from 0xf5d8…ad53 in 46 trades and sold it $335,943 in 10: market making looks like this too, so a loop is a lead, not a verdict.

Who a wallet traded against. Filter the trades to one wallet on either side and count its counterparties.

Polars — one wallet
w = "0xa62b923a112d50d03e1e096bbd53422490dac104"
mine = trades.filter((pl.col("buyer") == w) | (pl.col("seller") == w))
other = pl.when(pl.col("buyer") == w).then(pl.col("seller")).otherwise(pl.col("buyer"))
print(mine.group_by(other.alias("counterparty")).agg(pl.len().alias("trades")).sort("trades", descending=True).head(10))

Try it with no key. The free sample has the same columns as a daily file.

cURL — free sample
# one BTC hour of fills, no API key
curl -o fills-sample.parquet "https://data.vike.io/archive/hl-samples/fills-sample.parquet"

Before you rely on it

Join on all three keys, not trade_id alone

A fill is identified by wallet, fill_ts and trade_id, so pair on asset, fill_ts and trade_id together. The file is sorted by asset, fill_ts, trade_id, wallet, so the two sides of a trade sit next to each other. Rarely, a trade can have only one recorded side; an anti-join of the fills against the paired keys finds those.

Daily files, from 2026-05-01

One file is one UTC day, published in the early UTC morning after it ends, so this is history, not a live tape. Each day needs its own temporary link, and links count against an allowance of 20 GB per user per rolling 24 hours.

Ask your agent

No MCP tool reads the archive: use the file.

Example response
{  "trades": [    {"fill_ts": "2026-10-21T00:00:00.503Z", "trade_id": 644315352389798, "price": 82991.0, "size_token": 0.001, "buyer": "0xd49eaf821d8fe887e043ef1510b77f461ae7e1fa", "seller": "0xa62b923a112d50d03e1e096bbd53422490dac104", "buyer_maker": false},    {"fill_ts": "2026-10-21T00:00:02.073Z", "trade_id": 127035752616954, "price": 82991.0, "size_token": 0.00018, "buyer": "0xb8d7bbfa7c135239f7f850f916b0e51ca9e2a700", "seller": "0xa62b923a112d50d03e1e096bbd53422490dac104", "buyer_maker": false},    {"fill_ts": "2026-10-21T00:00:02.165Z", "trade_id": 582937235624021, "price": 82991.0, "size_token": 0.00257, "buyer": "0x4aa5f7febdd1996f00e2910593ae7190ae3f72ec", "seller": "0xa62b923a112d50d03e1e096bbd53422490dac104", "buyer_maker": false}  ],  "top_pairs": [    {"buyer": "0x5986347c1d0133d02d307f08bb1efd44c2eb89d9", "seller": "0xcf3f419d08a5bdc2c6e5fbd9ad70904c5420f95f", "usd": 1546732.47, "trades": 5},    {"buyer": "0xb90dfbd7fad293b11f30fbf6b53a90cf9c65870c", "seller": "0xf5d81a135f756ca16544e53c20fc20643ec3ad53", "usd": 1263798.56, "trades": 86},    {"buyer": "0x5986347c1d0133d02d307f08bb1efd44c2eb89d9", "seller": "0xaf9f722a676230cc44045efe26fe9a85801ca4fa", "usd": 1016680.86, "trades": 1}  ]}