Funding Rate Specification
Funding Rate Specification
Overview
Kyan implements a continuous funding mechanism so perpetual contract prices converge to their underlying index prices. The premium is sampled every minute and funding is settled at every UTC hour boundary.
Funding Rate Calculation
Premium Index
Each sample measures the difference between the perpetual and index price:
Premium (p) = (Perpetual Price - Index Price) / Index Price
- Perpetual Price: orderbook midpoint (with fallbacks — see below)
- Index Price: spot price from the index feed
Funding Pipeline
The premium is averaged over the hour, then transformed into the per-hour funding rate through four steps:
1. Average p_avg = seconds-weighted running average of p over the current hour
2. Compress r = p_avg / PREMIUM_COMPRESSION_RATIO
3. Dampen |r| <= DAMPENER_THRESHOLD -> r = 0 (dead zone)
r > DAMPENER_THRESHOLD -> r = r - DAMPENER_THRESHOLD
r < -DAMPENER_THRESHOLD -> r = r + DAMPENER_THRESHOLD
4. Cap r = clamp(r, -MAX_FUNDING_RATE, +MAX_FUNDING_RATE)
5. Normalize rate_hourly = r / FUNDING_PERIOD_HOURS
Default configuration:
| Parameter | Env var | Default | Meaning |
|---|---|---|---|
| Compression ratio | PREMIUM_COMPRESSION_RATIO | 1 (≥1) | Divides the premium; 1 = no compression |
| Dampener threshold | DAMPENER_THRESHOLD | 0.0005 (0.05%) | Dead zone; premiums inside it produce zero funding |
| Max funding rate | MAX_FUNDING_RATE | 0.005 (0.5%) | Cap applied before normalization |
| Funding period | FUNDING_PERIOD_HOURS | 8 | Normalization divisor |
| Sampling interval | FUNDING_INTERVAL | 1 (minute) | Premium sampling cadence |
Because the cap is applied before dividing by the funding period, the effective per-hour cap is ±0.0625% (0.5% ÷ 8). The stored rate is the per-hour rate; the annualized rate is rate_hourly × 8760.
Price Discovery and Fallback Logic
Perpetual Price
The perpetual price is derived from the live orderbook, falling back to the index price whenever the book is unusable. All prices must be positive, finite numbers.
Primary: Orderbook Midpoint
- Best bid and best ask are read from the perp orderbook.
- Spread guard: if
(ask - bid) / index > MAX_SPREAD_PERCENTAGE(default0.01, 1%), fall back to the index price. - Otherwise
perp price = (bid + ask) / 2.
Single-Sided Book
- Bid only: use the bid if it is above the index price, otherwise use the index price.
- Ask only: use the ask if it is below the index price, otherwise use the index price.
No Valid Orders
- Fall back to the index price (logged at warn level).
Index Price
- Sourced from the index price feed, keyed per base asset.
- Must be a positive, finite number; an invalid index price is a hard error for that sample.
Settlement Mechanism
Funding Windows
- Settlement cadence: every UTC hour boundary (00:00, 01:00, …, 23:00).
- Rate: the hour's seconds-weighted average premium run through the funding pipeline above.
Payment Calculation
At each hour boundary every open perpetual position is settled:
Funding Payment = Position Size × rate_hourly
The payment adjusts the margin account's accrued_funding. The final rate for the hour is also stored as the "previous" rate, and the "current" accumulator resets to 0 for the next hour.
Settlement Triggers
- Scheduled: detected automatically when the current hour exceeds the last processed hour during minute processing.
- Manual:
POST /settle_funding_intervalwith an explicit settlement payload.
Payment Direction
- Positive funding rate (perpetual > index): long positions pay short positions.
- Negative funding rate (perpetual < index): short positions pay long positions.
Mechanically, the payment is size × rate and is decremented from the payer's accrued_funding; the sign of size (long positive, short negative) and of rate together produce the correct direction.
Reliability & Edge Cases
- Idempotent minute processing: each minute is processed at most once (dedupe guard); failed runs clear the guard so retries are not blocked.
- Initialization: on first run (or reset) the current and previous funding rates are set to
0and the last-processed hour is set to the current hour boundary (timestamp - timestamp % 3600). - Stale-data reset: if the last processed hour is more than 2 hours (7200s) old, funding state is reinitialized to
0. - Stored-rate guard: a stored hourly rate that is non-finite or has magnitude > 100% is rejected as invalid.
- Graceful degradation: any orderbook problem (wide spread, single side, missing/invalid orders) falls back to the index price; only an invalid index price is fatal for the sample.
API Integration
These endpoints are internal and triggered by Cloud Scheduler / operators (not part of the public trading API):
| Endpoint | Body | Success | Purpose |
|---|---|---|---|
POST /compute_minutely_funding | empty | 202 | Sample the premium for all instruments; run hour-boundary settlement when the hour rolls over |
POST /settle_funding_interval | settlement request (instrument, final_rate, timestamp, previous_hour, type) | 200 | Force settlement for one instrument |
GET /v1/funding/health | — | 200/503 | Health probe |
GET /v1/funding/metrics | — | 200 | Prometheus metrics |
GET /v1/funding/dashboard | — | 200 | Service dashboard summary |
Supported Instruments
Configurable via INSTRUMENTS; defaults:
- BTC_USDC-PERPETUAL
- ETH_USDC-PERPETUAL
Data Storage
- Redis: current and previous funding rates plus processing state (last processed hour, dedupe guard), keyed per base asset.
- PostgreSQL: perpetual positions and each margin account's
accrued_funding. - BigQuery: historical funding-rate samples and account-ledger settlement events.
