1. 获取比特币历史价格数据

任务目标

调用Binance公开API,获取比特币(BTCUSDT)自2024年1月1日以来的历史日线K线数据,并将结果保存为CSV文件,包含开盘、最高、最低、收盘、成交量等关键字段。

环境与依赖

仅需Python 3.8+标准库,无需安装第三方包。使用urllib.request发送HTTP请求,csv模块写入文件,datetime处理时间戳。

实现代码

import csv
import json
import time
import urllib.request
import urllib.parse
from datetime import datetime, timezone

# Binance API 配置
BASE_URL = "https://api.binance.com/api/v3/klines"
SYMBOL = "BTCUSDT"
INTERVAL = "1d"
START_STR = "2024-01-01"
END_STR = "2024-12-31"
OUTPUT_FILE = "btc_daily.csv"

def date_to_ms(date_str):
    """将 YYYY-MM-DD 转为毫秒时间戳"""
    dt = datetime.strptime(date_str, "%Y-%m-%d").replace(tzinfo=timezone.utc)
    return int(dt.timestamp() * 1000)

def fetch_klines(symbol, interval, start_ms, end_ms):
    """分页获取K线数据,每次最多1000根"""
    all_data = []
    current_start = start_ms
    while current_start < end_ms:
        params = {
            "symbol": symbol,
            "interval": interval,
            "startTime": current_start,
            "endTime": end_ms,
            "limit": 1000
        }
        url = f"{BASE_URL}?{urllib.parse.urlencode(params)}"
        req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
        with urllib.request.urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read().decode())
        if not data:
            break
        all_data.extend(data)
        # 下一批从最后一条K线的下一毫秒开始
        current_start = data[-1][0] + 1
        time.sleep(0.2)  # 避免触发限频
    return all_data

def save_to_csv(klines, filename):
    """将K线数据写入CSV"""
    with open(filename, "w", newline="", encoding="utf-8") as f:
        writer = csv.writer(f)
        writer.writerow(["open_time", "open", "high", "low", "close", "volume", "close_time"])
        for k in klines:
            writer.writerow([
                datetime.fromtimestamp(k[0]/1000, tz=timezone.utc).strftime("%Y-%m-%d"),
                k[1], k[2], k[3], k[4], k[5],
                datetime.fromtimestamp(k[6]/1000, tz=timezone.utc).strftime("%Y-%m-%d")
            ])

if __name__ == "__main__":
    start_ms = date_to_ms(START_STR)
    end_ms = date_to_ms(END_STR) + 86400000 - 1  # 包含结束日当天
    print("正在获取数据...")
    klines = fetch_klines(SYMBOL, INTERVAL, start_ms, end_ms)
    if not klines:
        print("未获取到数据,请检查网络或参数")
    else:
        save_to_csv(klines, OUTPUT_FILE)
        print(f"成功获取 {len(klines)} 条日线数据,已保存至 {OUTPUT_FILE}")

运行方式

  1. 将上述代码保存为 fetch_btc.py;
  2. 在终端执行 python fetch_btc.py;
  3. 等待程序运行结束,查看当前目录下生成的 btc_daily.csv 文件。

验证方法

程序运行后应输出“成功获取 N 条日线数据”。打开CSV文件检查:

  • 首行为列名:open_time, open, high, low, close, volume, close_time;
  • 数据行数约为365行(2024年为闰年,实际366行);
  • 第一行日期为 2024-01-01,最后一行日期为 2024-12-31;
  • 收盘价(close)数值在合理范围(如30000~80000之间),成交量(volume)为正数。

预期输出示例

open_time,open,high,low,close,volume,close_time
2024-01-01,42228.00,45489.00,41700.00,45100.00,15234.567,2024-01-02
2024-01-02,45100.00,45980.00,43500.00,44000.00,18900.123,2024-01-03
...

以上仅为格式示例,实际数值以Binance返回的真实行情为准。