nautechsystems/nautilus_trader · error

historical BinanceBar requests require time aggregation

Error message

historical BinanceBar requests require time aggregation

What it means

Historical `BinanceBar` requests require a time-aggregated BarSpecification — a SECOND/MINUTE/HOUR/DAY step. Tick- or volume-aggregated specs (e.g. a 100-VOLUME bar) are rejected because Binance kline endpoints only bucket data by time.

Source

Thrown at crates/adapters/binance/src/futures/data.rs:2640

    /// Requests Binance futures custom data.
    ///
    /// Spawned fetch failures are logged and no response is emitted, matching
    /// the existing request-path behavior for other Binance adapter requests.
    fn request_data(&self, request: RequestCustomData) -> anyhow::Result<()> {
        let data_type = request.data_type.clone();
        let data_type_name = data_type.type_name().to_string();

        if data_type_name == "BinanceBar" {
            let bar_type = parse_binance_bar_type(&data_type)?;
            anyhow::ensure!(
                bar_type.aggregation_source() == AggregationSource::External,
                "historical BinanceBar requests require EXTERNAL aggregation"
            );
            anyhow::ensure!(
                bar_type.spec().price_type == PriceType::Last,
                "historical BinanceBar requests require LAST price type"
            );
            anyhow::ensure!(
                bar_type.spec().is_time_aggregated(),
                "historical BinanceBar requests require time aggregation"
            );
            let http = self.http_client.clone();
            let sender = self.data_sender.clone();
            let request_id = request.request_id;
            let client_id = request.client_id;
            let start = request.start;
            let end = request.end;
            let limit = request.limit.map(|value| value.get() as u32);
            let params = request.params;
            let clock = self.clock;
            let venue = self.venue();
            let start_nanos = datetime_to_unix_nanos(start);
            let end_nanos = datetime_to_unix_nanos(end);
            get_runtime().spawn(async move {
                match http.request_binance_bars(bar_type, start, end, limit).await {
                    Ok(bars) => {

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Request a time-aggregated bar type, e.g. `BTCUSDT-PERP.BINANCE-1-MINUTE-LAST-EXTERNAL`
  2. For volume/tick bars, backfill trades and aggregate locally — Binance cannot serve them as history

Example fix

# before
bar_type = BarType.from_str('BTCUSDT-PERP.BINANCE-100-VOLUME-LAST-EXTERNAL')

# after
bar_type = BarType.from_str('BTCUSDT-PERP.BINANCE-1-MINUTE-LAST-EXTERNAL')
Defensive patterns

Strategy: validation

Validate before calling

from nautilus_trader.model.data import BarAggregation

def is_time_aggregated(bar_spec) -> bool:
    return bar_spec.aggregation in (BarAggregation.SECOND, BarAggregation.MINUTE, BarAggregation.HOUR, BarAggregation.DAY)

if not is_time_aggregated(bar_type.spec):
    raise ValueError(f'{bar_type} is not time-aggregated; Binance kline history is time-bucketed only')

Type guard

def is_time_aggregated_bar(bar_type) -> bool:
    return bar_type.spec.aggregation in (BarAggregation.SECOND, BarAggregation.MINUTE, BarAggregation.HOUR, BarAggregation.DAY)

Try / catch

try:
    actor.request_custom_data(data_type, ...)
except Exception as e:
    if 'require time aggregation' in str(e):
        raise ValueError('Volume/tick bar history is not served by Binance; backfill trades and aggregate locally') from e
    raise

Prevention

When it happens

Trigger: `request_data` with data type name `BinanceBar` and a bar type whose aggregation is not time-based, e.g. `BTCUSDT-PERP.BINANCE-100-VOLUME-LAST-EXTERNAL` or `-1-TICK-LAST-EXTERNAL`.

Common situations: Volume-bar or tick-bar strategies trying to backfill history; generic bar request code forwarding whatever bar type the strategy registered; porting from venues that serve tick/volume candles.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/255c2faae3518dea. Report an issue: GitHub.