Funding rates
Two collectors that look alike and write different things — the venue-wide market funding rate a strategy trades on, and one account's realized funding payments.
Two bins in crates/vike-backfill carry "funding" in their name, and
crates/vike-backfill/src/funding_rate.rs's header draws the line between them before anything
else. funding_rate_backfill writes the market rate: the venue-wide, position-independent
funding schedule for a symbol — keyless, available for every perpetual whether or not you hold it,
and the signal a funding-capture strategy trades on. hyperliquid_funding_backfill writes an
account's realized funding: a wallet's userFunding payments, which is a different series with a
different store kind. Both sit behind the venue-backfill feature, and the second reason is not
obvious: crates/vike-backfill/Cargo.toml notes that funding_rate_backfill looks bridge-free but
routes through crate::funding_rate, which calls vike-hyperliquid.
The market rate: funding_rate_backfill
The collector fetches a venue's public funding-rate schedule and ingests it as kind=bar, the rate
riding on vike_model::Bar::funding with OHLCV and volume left 0.0 — so a backtest's
funding_source seam can replay the real per-interval rate off the stored column
(funding_rate.rs header). Two venues ship, each as an impl of the FundingRateSource trait — a
pure, fixture-tested parser over the venue's JSON plus a paged fetch:
- Binance —
GET https://fapi.binance.com/fapi/v1/fundingRatewithsymbol,startTime,endTimeandlimit=1000; 8-hour cadence; a keyless GET over the crate's shared HTTP client. - Hyperliquid —
POST /infowith{"type":"fundingHistory", ...}; 1-hour cadence; a keyless mainnet read over the bridge's ownHyperliquidTransport.
Both venues cap responses at roughly 500–1000 rows, so fetch pages startTime forward until a
page comes back short or the cursor passes the end (page_forward, shared by both impls). The run
is idempotent per (venue, symbol, [start, end]) window through funding_rate_commit_key.
From crates/vike-backfill/src/bin/funding_rate_backfill.rs's usage: --venue selects the source
and names the store partition (binance | hyperliquid); --symbols is a comma list of
vikeSymbol=sourceSymbol pairs, bare SYM meaning the two coincide (Binance BTCUSDT, Hyperliquid
BTC); --start/--end are each an epoch-ms integer or a YYYY-MM-DD UTC date, --end
defaulting to now; --interval is the series interval label and defaults, for both venues, to the
cadence-agnostic namespace funding — FundingRateSource::default_interval is deliberately not a
cadence (8h/1h), because funding spacing varies by venue and by symbol, so the true cadence
lives in the data, in the spacing of the stored Bar.ts, and one stable label keeps this series in
its own keyspace where an OHLCV kline series can never interleave with it. An operator who wants a
cadence-tagged series passes --interval, as the second example below does. --store resolves
through the store's ladder: $VIKE_HIST_STORE, then a project
declared by $VIKE_SETTINGS_DIR, then <repo>/market_data/hist.
funding_rate_backfill --venue binance --symbols BTCUSDT,ETHUSDT --start 2024-01-01
funding_rate_backfill --venue hyperliquid --symbols BTC=BTC,ETH=ETH --start 1704067200000 --interval 1hHyperliquid's response carries a second number, and it is kept
The funding_rate.rs header records that premium was parsed and discarded for as long as the
file existed. It is the venue's funding premium for the same interval, not derivable from
fundingRate (the venue folds an interest-rate term in and then clamps), and it is the input the
cohort study's premium_z_24h feature needs. It is stored as its own kind — kind=perp_metrics,
one PerpMetricRow per interval that had one — rather than on the funding Bar, which has no field
for it. Binance sends no premium and therefore writes none. Open interest is deliberately not
beside it: Hyperliquid serves OI only as a current snapshot, never as history, so no backfill can
reconstruct a past value. The one producer that does fill open_interest is the vike.io hourly
panel, on the Data API page.
The account's payments: hyperliquid_funding_backfill
crates/vike-backfill/src/bin/hyperliquid_funding_backfill.rs fetches a master account's keyless
userFunding /info history on mainnet — no credentials, just the address — over
[--start, --end] and ingests it as kind=funding/venue=hyperliquid/symbol=<coin>, split by
coin and idempotent per (account, coin, window). It is the funding analog of
hyperliquid_backfill, and crates/vike-backfill/src/hyperliquid.rs owns both: the candle backfill
and backfill_hyperliquid_funding with its pure funding_rows_by_coin, persisting through
vike_data::HistStore::append_funding.
--account is the master account address funding is read against. The bin header is explicit about
the agent-wallet pitfall the bridge guards against elsewhere: it does not apply here, because funding
reads are keyless — pass the master address. --start/--end take the same epoch-ms-or-date
forms as the market-rate bin, and --store resolves the same way.
hyperliquid_funding_backfill --account 0x8f0a3e01d916486735a8f6a2ffc0685a3fa57bf5 --start 2024-01-01Which one you want
A funding-carry strategy backtest wants the market rate, on Bar.funding, from
funding_rate_backfill — that is the number the position would have paid or received per interval
regardless of who held it. A reconstruction of what one wallet actually received wants
kind=funding from hyperliquid_funding_backfill. crates/vike-backfill/src/caps.rs tracks the
first as bars and does not track the second at all, with the reason on the Hyperliquid row: realized
funding payments are not market data, and no coverage report asks for them. The kinds themselves
are documented under concepts/data; the tutorial that consumes the market
rate is funding carry across two venues.
Two producers of one series double its hours
vikedata_backfill --panel-funding also writes funding-rate hours, and its usage text states that
the panel's rate and fundingHistory's settled rate are different series — a snapshot aggregate
versus a settled interval rate, measured roughly 4× apart. The store's idempotency is batch-level on
the commit key, two producers are two keys, and the hours they share land twice. One store takes one
producer for a window.
Venue-direct
The seven collectors that page a venue's own keyless history endpoint into the store — five klines bins sharing one CLI body, plus Dukascopy ticks and Hyperliquid candles.
Databento
The paid equities-and-futures vendor — one schema, symbol and window from the historical HTTP API, decoded by pure fixture-tested parsers into bars, trades, quotes or the L2 book.