{"record":{"id":"0c3a8ee1b319f899","repo":"nautechsystems/nautilus_trader","slug":"binance-futures-aggregate-trade-history-is-limited","errorCode":null,"errorMessage":"Binance Futures aggregate trade history is limited to the past 24 hours","messagePattern":"Binance Futures aggregate trade history is limited to the past 24 hours","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/futures/http/client.rs","lineNumber":2932,"sourceCode":"\n        Ok(result)\n    }\n\n    /// Requests bounded aggregate public trades for an instrument.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if a supplied time bound is invalid or parsing fails.\n    pub async fn request_agg_trades(\n        &self,\n        instrument_id: InstrumentId,\n        start: Option<Timestamp>,\n        end: Option<Timestamp>,\n        limit: Option<u32>,\n    ) -> anyhow::Result<Vec<TradeTick>> {\n        let cutoff =\n            self.clock.get_time_ns().to_datetime_utc() - jiff::SignedDuration::from_hours(24);\n        anyhow::ensure!(\n            start.as_ref().is_none_or(|value| value >= &cutoff)\n                && end.as_ref().is_none_or(|value| value >= &cutoff),\n            \"Binance Futures aggregate trade history is limited to the past 24 hours\"\n        );\n        let (symbol, price_precision, size_precision) =\n            self.cached_precisions_by_id(instrument_id)?;\n        let params = BinanceAggTradesParams {\n            symbol,\n            from_id: None,\n            start_time: start.map(|value| value.as_millisecond()),\n            end_time: end.map(|value| value.as_millisecond()),\n            limit,\n        };\n        let trades = self.inner.agg_trades(&params).await?;\n        trades\n            .iter()\n            .map(|trade| {\n                let ts_init = parse_millis(trade.time, \"Futures aggregate trade time\")?;","sourceCodeStart":2914,"sourceCodeEnd":2950,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/a4b06ed870971b5671d12754ea138a3ab99b1dec/crates/adapters/binance/src/futures/http/client.rs#L2914-L2950","documentation":"Thrown by BinanceFuturesHttpClient::request_agg_trades when the requested start or end timestamp is earlier than the client clock's current time minus 24 hours. Binance's futures aggTrades endpoint genuinely only serves the recent window (unlike spot), so the client validates both bounds up front against clock.get_time_ns() and rejects requests that would silently return partial or empty data. Either bound being older than the cutoff fails the whole call, even if the other bound is recent.","triggerScenarios":"Requesting aggTrades with a start_ts from days or weeks ago (e.g. for backfill or warm-up of short-horizon signals); passing an end timestamp that predates the cutoff because of unit or timezone confusion; running against a clock set later than real time (test clock) so the cutoff moves forward and a request valid yesterday now fails.","commonSituations":"Porting spot-market backfill code to futures; strategies requesting 'trades since session start' where the session began >24h ago; a backtest/test clock advanced beyond the data window; millisecond-vs-nanosecond timestamp mix-ups making bounds look ancient.","solutions":["Clamp both start and end to be >= now - 24h (or pass None) before calling","For history older than 24h, use request_binance_bars (klines), which serves deep history, and reconstruct aggregates from bars","Double-check timestamp units and timezone — NautilusTrader Timestamps are ns-since-epoch UTC; ensure no ms/s mix-up","In tests, align the injected clock with realistic present time before asserting on this API"],"exampleFix":"// before\nlet trades = client.request_agg_trades(inst, Some(start_3_days_ago), None, None).await?;\n\n// after\nlet cutoff = client.clock.get_time_ns().to_datetime_utc() - jiff::SignedDuration::from_hours(24);\nlet start = start.max(Timestamp::from_datetime_utc(cutoff));\nlet trades = client.request_agg_trades(inst, Some(start), None, None).await?;","handlingStrategy":"validation","validationCode":"let cutoff = clock.get_time_ns().to_datetime_utc() - jiff::SignedDuration::from_hours(24);\nlet start = start.filter(|t| *t >= Timestamp::from_datetime_utc(cutoff));\nlet end = end.filter(|t| *t >= Timestamp::from_datetime_utc(cutoff));\nlet trades = client.request_agg_trades(inst, start, end, limit).await?;","typeGuard":null,"tryCatchPattern":"Catch the message, clamp both bounds to the 24h cutoff (or None), and retry once; if older data is required, switch to request_binance_bars for klines.","preventionTips":["Clamp aggTrades windows to now-24h before requesting","Use klines for backfill older than 24 hours","Keep timestamp units consistent (ns UTC) across the codebase"],"tags":["binance","futures","agg-trades","market-data","timestamp","rust","nautilustrader"],"backgroundTag":"historical-data-window-limit","analyzedSha":"a4b06ed870971b5671d12754ea138a3ab99b1dec","analyzedAt":"2026-08-16T22:54:50.089Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}