안녕하세요! 오늘은 **Binance Futures的历史数据批量下载**를 Python으로 자동화하는 방법에 대해 알아보겠습니다. Binance Futures는全球最大の暗号通貨先物取引所の1つであり、トレーダーや研究者にとって 풍부な歷史データへのアクセスが重要です。
目次
1. [Binance Futures APIとは?](#binance-futures-apiとは)
2. [事前準備](#事前準備)
3. [Python実装](#python実装)
4. [大量データダウンロードの最適化](#大量データダウンロードの最適化)
5. [エラー処理とベストプラクティス](#エラー処理とベストプラクティス)
6. [よくある問題と解決策](#よくある問題と解決策)
---
Binance Futures APIとは?
Binance Futuresは、世界最大級の暗号通貨先物取引所で、 풍부한歷史市場データを提供します。APIを活用することで、以下のようなデータが取得可能です:
- **K线数据**(ローソク足):1分足から1ヶ月足まで
- **取引データ**:約定履歴
- **注文簿データ**:板情報
- **ポジション情報**:保有ポジション
- **資金調達率**:Funding Rate
APIエンドポイント一覧
| エンドポイント | 説明 | 制限 |
|--------------|------|------|
|
/fapi/v1/klines | K线データ取得 | 1200 requests/min |
|
/fapi/v1/aggTrades | 集約取引取得 | 1200 requests/min |
|
/fapi/v1/fundingRate | 資金調達率 | 1200 requests/min |
|
/fapi/v1/openInterest | オープンインタレスト | 1200 requests/min |
---
事前準備
必要なライブラリのインストール
pip install requests pandas python-dotenv asyncio aiohttp
プロジェクト構造
binance_futures_data/
├── config.py # API設定
├── client.py # APIクライアント
├── downloader.py # データダウンロード
├── utils.py # ユーティリティ関数
├── requirements.txt # 依存関係
└── data/ # データ保存先
---
Python実装
1. 基本設定(config.py)
import os
from dotenv import load_dotenv
load_dotenv()
Binance Futures API設定
BINANCE_BASE_URL = "https://fapi.binance.com"
BINANCE_WS_URL = "wss://fstream.binance.com/ws"
APIキー(オプション:パブリックエンドポイントには不要)
API_KEY = os.getenv("BINANCE_API_KEY", "")
API_SECRET = os.getenv("BINANCE_API_SECRET", "")
レートリミット設定
REQUESTS_PER_MINUTE = 1100 # 安全マージンあり
REQUEST_DELAY = 60 / REQUESTS_PER_MINUTE
データ保存設定
DATA_DIR = "./data"
SAVE_FORMAT = "parquet" # parquet, csv, json
2. APIクライアント(client.py)
import requests
import time
from typing import Optional, List, Dict, Any
from datetime import datetime
import pandas as pd
class BinanceFuturesClient:
"""Binance Futures APIクライアント"""
def __init__(self, base_url: str = "https://fapi.binance.com"):
self.base_url = base_url
self.session = requests.Session()
self.last_request_time = 0
def _rate_limit(self):
"""レートリミット制御"""
elapsed = time.time() - self.last_request_time
if elapsed < REQUEST_DELAY:
time.sleep(REQUEST_DELAY - elapsed)
self.last_request_time = time.time()
def _request(self, method: str, endpoint: str, **kwargs) -> Dict[str, Any]:
"""HTTPリクエスト実行"""
url = f"{self.base_url}{endpoint}"
self._rate_limit()
response = self.session.request(method, url, **kwargs)
response.raise_for_status()
return response.json()
def get_klines(
self,
symbol: str,
interval: str,
start_time: Optional[int] = None,
end_time: Optional[int] = None,
limit: int = 1000
) -> pd.DataFrame:
"""
K线データ(ローソク足)を取得
Args:
symbol: 取引ペア(例:BTCUSDT)
interval: 間隔(1m, 5m, 1h, 1d, etc.)
start_time: 開始時間(ミリ秒)
end_time: 終了時間(ミリ秒)
limit: 取得件数(最大1000)
"""
params = {
"symbol": symbol.upper(),
"interval": interval,
"limit": limit
}
if start_time:
params["startTime"] = start_time
if end_time:
params["endTime"] = end_time
data = self._request("GET", "/fapi/v1/klines", params=params)
# DataFrameに変換
df = pd.DataFrame(data, columns=[
"open_time", "open", "high", "low", "close", "volume",
"close_time", "quote_volume", "trades", "taker_buy_volume",
"taker_buy_quote_volume", "ignore"
])
# 数値型に変換
for col in ["open", "high", "low", "close", "volume", "quote_volume"]:
df[col] = pd.to_numeric(df[col])
# 日時変換
df["open_time"] = pd.to_datetime(df["open_time"], unit="ms")
df["close_time"] = pd.to_datetime(df["close_time"], unit="ms")
return df
def get_funding_rate(
self,
symbol: str,
start_time: Optional[int] = None,
end_time: Optional[int] = None,
limit: int = 1000
) -> pd.DataFrame:
"""資金調達率を取得"""
params = {
"symbol": symbol.upper(),
"limit": limit
}
if start_time:
params["startTime"] = start_time
if end_time:
params["endTime"] = end_time
data = self._request("GET", "/fapi/v1/fundingRate", params=params)
df = pd.DataFrame(data)
df["fundingTime"] = pd.to_datetime(df["fundingTime"], unit="ms")
df["fundingRate"] = pd.to_numeric(df["fundingRate"])
return df
3. 的大量データダウンロード(downloader.py)
```python
import asyncio
import aiohttp
from datetime import datetime, timedelta
from typing import List, Tuple, Optional
import pandas as pd
from pathlib import Path
import json
class FuturesDataDownloader:
"""Binance Futures 大量データ一括ダウンロード"""
def __init__(
self,
base_url: str = "https://fapi.binance.com",
save_dir: str = "./data"
):
self.base_url = base_url
self.save_dir = Path(save_dir)
self.save_dir.mkdir(parents=True, exist_ok=True)
async def _fetch_klines_async(
self,
session: aiohttp.ClientSession,
symbol: str,
interval: str,
start_time: int,
end_time: int,
limit: int = 1000
) -> List:
"""非同期でK线データを取得"""
url = f"{self.base_url}/fapi/v1/klines"
params = {
"symbol": symbol.upper(),
"interval": interval,
"startTime": start_time,
"endTime": end_time,
"limit": limit
}
async with session.get(url, params=params) as response:
response.raise_for_status()
return await response.json()
async def download_historical_klines(
self,
symbol: str,
interval: str,
start_date: datetime,
end_date: datetime,
delay: float = 0.1
) -> pd.DataFrame:
"""
歴史的K线データを一括ダウンロード
Args:
symbol: 取引ペア
interval: 時間間隔
start_date: 開始日時
end_date