Files
PolyHermes/scripts/fetch_binance_btc_usdc_klines.py
WrBug b50e43c239 feat(crypto-tail): 策略最小价差(无/固定/自动) + 前端默认与文案
- 后端: 最小价差 DB/Entity/DTO、Binance K线 REST+WS、自动价差 IQR 预计算与执行时校验
- 前端: 最小价差(自动-固定-无),默认自动,label 旁 info 说明,选择自动不展示建议约
- i18n: minSpreadModeTip 说明不写死标的
- 文档: crypto-tail-strategy-min-spread-flow.md
- scripts: Binance K线拉取与 WS 示例

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-14 15:16:44 +08:00

106 lines
3.5 KiB
Python

#!/usr/bin/env python3
"""
从币安现货 API 获取 BTC/USDC 15 分钟 K 线数据。
API: https://api.binance.com/api/v3/klines
无需 API Key,公开行情接口。
使用方法:
python3 scripts/fetch_binance_btc_usdc_klines.py
python3 scripts/fetch_binance_btc_usdc_klines.py --limit 96
python3 scripts/fetch_binance_btc_usdc_klines.py --limit 10 --interval 15m
"""
import argparse
import json
import sys
import time
import urllib.error
import urllib.parse
import urllib.request
BINANCE_BASE = "https://api.binance.com"
def fetch_klines(
symbol: str = "BTCUSDC",
interval: str = "15m",
limit: int = 500,
start_time: int | None = None,
end_time: int | None = None,
) -> list[list] | None:
"""
获取 K 线数据。
返回每根 K 线: [ openTime, open, high, low, close, volume, closeTime, ... ]
"""
params = {"symbol": symbol, "interval": interval, "limit": limit}
if start_time is not None:
params["startTime"] = start_time
if end_time is not None:
params["endTime"] = end_time
qs = urllib.parse.urlencode(params)
url = f"{BINANCE_BASE}/api/v3/klines?{qs}"
req = urllib.request.Request(url, headers={"User-Agent": "PolymarketBot/1.0 (script)"})
try:
with urllib.request.urlopen(req, timeout=15) as resp:
return json.load(resp)
except urllib.error.HTTPError as e:
body = e.read().decode() if e.fp else ""
try:
err = json.loads(body)
except json.JSONDecodeError:
err = {"msg": body}
print(f"Request failed: {e.code} - {err}", file=sys.stderr)
return None
except Exception as e:
print(f"Request error: {e}", file=sys.stderr)
return None
def main():
parser = argparse.ArgumentParser(description="Fetch Binance BTC/USDC 15m klines")
parser.add_argument("--symbol", default="BTCUSDC", help="Trading pair (default: BTCUSDC)")
parser.add_argument("--interval", default="15m", help="Kline interval (default: 15m)")
parser.add_argument("--limit", type=int, default=20, help="Number of klines (default: 20, max 1000)")
parser.add_argument("--start", type=int, default=None, help="Start time (ms)")
parser.add_argument("--end", type=int, default=None, help="End time (ms)")
args = parser.parse_args()
limit = max(1, min(1000, args.limit))
print("=== Binance BTC/USDC K-line (15m) ===\n")
print(f"Symbol: {args.symbol} Interval: {args.interval} Limit: {limit}")
if args.start:
print(f"Start: {args.start} ({time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(args.start // 1000))})")
if args.end:
print(f"End: {args.end} ({time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(args.end // 1000))})")
print()
klines = fetch_klines(
symbol=args.symbol,
interval=args.interval,
limit=limit,
start_time=args.start,
end_time=args.end,
)
if not klines:
print("No kline data returned")
sys.exit(1)
print(f"Got {len(klines)} kline(s)\n")
print("Columns: openTime, open, high, low, close, volume, closeTime, ...")
print("-" * 72)
for k in klines:
open_ts_ms = k[0]
open_ts = open_ts_ms // 1000
ts_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(open_ts))
o, h, l, c, v = k[1], k[2], k[3], k[4], k[5]
print(f" {ts_str} O:{o} H:{h} L:{l} C:{c} V:{v}")
print("-" * 72)
last = klines[-1]
print(f"Latest: open={last[1]}, high={last[2]}, low={last[3]}, close={last[4]}, volume={last[5]}")
if __name__ == "__main__":
main()