{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "c9127252", "metadata": {}, "outputs": [], "source": [ "# -*- coding: utf-8 -*-\n", "\"\"\"\n", "Binance Futures Klines Downloader (sliding window)\n", "\n", "This script downloads historical futures candlestick (kline) data from Binance.\n", "- Uses Binance Futures REST API endpoint: /fapi/v1/klines\n", "- Supports configurable interval and number of days\n", "- Handles Binance's max limit (1500 rows per request) by sliding window\n", "- Converts timestamps to datetime and numeric fields to float\n", "- Optionally saves the result to CSV\n", "\n", "Example:\n", " $ python download_futures_klines.py\n", "\"\"\"\n", "\n", "import requests\n", "import pandas as pd\n", "import time\n", "from datetime import datetime\n", "\n", "BASE_URL = \"https://fapi.binance.com/fapi/v1/klines\"\n", "\n", "\n", "def get_futures_klines(symbol, interval, start, end, limit=1500):\n", " \"\"\"\n", " Fetch a batch of Binance Futures klines between start and end timestamps.\n", "\n", " Parameters\n", " ----------\n", " symbol : str\n", " Trading pair symbol, e.g. \"BTCUSDT\".\n", " interval : str\n", " Kline interval, e.g. \"1m\", \"5m\", \"1h\".\n", " start : int\n", " Start time in milliseconds.\n", " end : int\n", " End time in milliseconds.\n", " limit : int, optional\n", " Max number of rows per request (default=1500).\n", "\n", " Returns\n", " -------\n", " pd.DataFrame\n", " DataFrame of klines with proper column names and dtypes.\n", " Empty DataFrame if no data returned.\n", " \"\"\"\n", " params = {\n", " \"symbol\": symbol,\n", " \"interval\": interval,\n", " \"limit\": limit,\n", " \"startTime\": start,\n", " \"endTime\": end,\n", " }\n", " resp = requests.get(BASE_URL, params=params)\n", " resp.raise_for_status()\n", " data = resp.json()\n", "\n", " columns = [\n", " \"open_time\", \"open\", \"high\", \"low\", \"close\", \"volume\",\n", " \"close_time\", \"quote_volume\", \"trades\",\n", " \"taker_base_volume\", \"taker_quote_volume\", \"ignore\"\n", " ]\n", " df = pd.DataFrame(data, columns=columns)\n", " if df.empty:\n", " return df\n", "\n", " # Convert datatypes\n", " df[\"open_time\"] = pd.to_datetime(df[\"open_time\"], unit=\"ms\")\n", " df[\"close_time\"] = pd.to_datetime(df[\"close_time\"], unit=\"ms\")\n", " numeric_cols = [\n", " \"open\", \"high\", \"low\", \"close\", \"volume\",\n", " \"quote_volume\", \"taker_base_volume\", \"taker_quote_volume\"\n", " ]\n", " df[numeric_cols] = df[numeric_cols].astype(float)\n", " return df\n", "\n", "\n", "def download_all_klines(symbol, interval=\"1m\", days=30, save_csv=True):\n", " \"\"\"\n", " Download all Binance Futures klines for a given symbol and time range.\n", "\n", " Parameters\n", " ----------\n", " symbol : str\n", " Trading pair symbol, e.g. \"BTCUSDT\".\n", " interval : str, optional\n", " Kline interval (default \"1m\").\n", " days : int, optional\n", " Number of days to download (default 30).\n", " save_csv : bool, optional\n", " Whether to save the result to CSV (default True).\n", "\n", " Returns\n", " -------\n", " pd.DataFrame\n", " Concatenated DataFrame of all klines.\n", " Empty DataFrame if nothing retrieved.\n", " \"\"\"\n", " end_time = int(time.time() * 1000) # current time (ms)\n", " start_time = end_time - days * 24 * 60 * 60 * 1000\n", "\n", " all_dfs = []\n", " # Calculate step size (ms) per API call\n", " minutes = int(interval.replace(\"m\", \"\")) if \"m\" in interval else 1\n", " step = 1500 * 60 * minutes * 1000\n", " current = start_time\n", "\n", " while current < end_time:\n", " next_end = min(current + step, end_time)\n", " df = get_futures_klines(symbol, interval, current, next_end)\n", " if not df.empty:\n", " all_dfs.append(df)\n", " print(f\"✅ Got {len(df)} rows from {df.iloc[0]['open_time']} to {df.iloc[-1]['close_time']}\")\n", " else:\n", " print(\"⚠️ Empty response, stopping...\")\n", " break\n", " current = next_end + 1\n", " time.sleep(0.3) # to avoid hitting API rate limits\n", "\n", " if all_dfs:\n", " final_df = pd.concat(all_dfs, ignore_index=True)\n", " if save_csv:\n", " filename = f\"{symbol}_{interval}_{days}d.csv\"\n", " final_df.to_csv(filename, index=False)\n", " print(f\"💾 Saved to {filename} ({len(final_df)} rows)\")\n", " return final_df\n", " else:\n", " return pd.DataFrame()\n", "\n", "\n", "# ===============================\n", "# Run example\n", "# ===============================\n", "if __name__ == \"__main__\":\n", " coin_ls = ['BTC', 'ETH']\n", " for coin in coin_ls:\n", " df = download_all_klines(f\"{coin}USDT\", interval=\"1m\", days=1)\n" ] }, { "cell_type": "code", "execution_count": null, "id": "7ff80947", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "base", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.7" } }, "nbformat": 4, "nbformat_minor": 5 }