Skip to main content

Module historical

Module historical 

Source
Expand description

Historical klines (OHLCV candles) via Binance’s public, unauthenticated REST endpoints — spot (/api/v3/klines) and futures continuous (/fapi/v1/continuousKlines). Historical klines (OHLCV candles) via Binance’s public, unauthenticated REST endpoints.

Gives consumers free historical candle data for research/backtest on both BinanceSpot and BinanceFuturesUsd — no API key, no paid data subscription. Construct a client for the surface you want and call fetch_candles:

use rustrade_data::exchange::binance::historical::BinanceHistoricalClient;
use rustrade_data::subscription::candle::CandleInterval;
use chrono::{Duration, Utc};
use futures::StreamExt;

let client = BinanceHistoricalClient::spot();
let end = Utc::now();
let start = end - Duration::days(1);

let mut stream = client.fetch_candles("BTCUSDT", CandleInterval::Min1, start, end);
while let Some(candle) = stream.next().await {
    println!("{:?}", candle?);
}

§Two surfaces, one mapping

Spot and futures return the same array-of-arrays row shape and share one row→Candle mapping. They differ only on host, page cap, and URL params:

SurfaceEndpointHostPage capMarket param
spot/api/v3/klinesapi.binance.com1000symbol
futures/fapi/v1/continuousKlinesfapi.binance.com1500pair + contractType=PERPETUAL

The futures path uses the continuous-contract surface (contractType=PERPETUAL) rather than /fapi/v1/klines. For a perpetual this is the same data as the symbol klines plus sub-minute resolutions: /fapi/v1/klines returns 400 Invalid interval for Sec1, whereas the continuous surface serves genuine 1-second candles.

§Rate limits & resumable backfill

On HTTP 429/418 the stream yields BinanceDataError::RateLimited and ends — it never waits, retries, or runs a process-global limiter (the consumer owns retry/backoff). The stream is resumable: on a RateLimited error, wait retry_after, then re-invoke fetch_candles with start advanced to 1ms past the last close_time already received (last_close_time + 1ms, i.e. the next candle’s open). The [start, end] range is close_time-inclusive, so resuming exactly at last_close_time would re-yield that final candle; the +1ms step skips it without leaving a gap. No progress is lost — pagination keys off open_time, and open ≡ close − interval.

A long unattended backfill (a 90-day 1s series is ≈ 7.8M candles over thousands of requests) will not “just work” without that resume loop on the consumer side, but the default pre-pacing keeps a single steady backfill within Binance’s weight budget so the common case rarely trips a 429 in the first place.

Structs§

BinanceHistoricalClient
REST client for Binance historical klines on a single surface (spot or futures-continuous). Construct with spot or futures; both bake in the surface’s host, page cap, and a conservative default pre-pace.