关键词:跨交易所套利、Python、加密货币、价格差异、交易手续费、信号生成、量化策略
市场背景与策略动机
跨交易所套利(cross-exchange arbitrage)是一种非常经典的量化交易思路:找出同一种加密资产在不同交易所之间的实时价差,在价格偏低处买入、同时在价格偏高处卖出,锁定无风险利润。
本指南以 Bitcoin(BTC) 为例,调用 CoinGecko 与 YFinance 两大公共数据源,带你跑完“连接行情 → 计算价差 → 扣除费用 → 生成信号 → 回测盈利”的全流程示例。
必备环境与库
import pandas as pd
import requests, json, datetime, numpy as np
import yfinance as yf
import matplotlib.pyplot as plt步骤一:获取数据源 A——CoinGecko API
- 统一时间区间
以 2023-04-17 为例,全天 5 分钟级 k 线共 288 条。 构建请求
url = "https://api.coingecko.com/api/v3/coins/bitcoin/market_chart/range" params = {"vs_currency":"usd","from":1681689600,"to":1681776000} data = requests.get(url,params=params).json()清洗与重采样
df_cg = pd.DataFrame(data["prices"], columns=["ts","price"]) df_cg["price"] = df_cg["price"].astype(float) df_cg["ts"] = pd.to_datetime(df_cg["ts"], unit="ms") # 重采样到 5 分钟对齐 idx = pd.date_range("2023-04-17 00:00:00","2023-04-17 23:55:00",freq="5min") df_cg = df_cg.set_index("ts").reindex(idx,method="ffill").reset_index() df_cg.rename(columns={"index":"Timestamp","price":"Coingecko_BTC"},inplace=True)
步骤二:获取数据源 B——YFinance
btc = yf.Ticker("BTC-USD")
hist = btc.history(start="2023-04-17",end="2023-04-18",interval="5m")
df_yf = hist[["Close"]].rename(columns={"Close":"YFinance_BTC"})
df_yf.index = hist.index.tz_localize(None)
df_yf = df_yf.reset_index().rename(columns={"index":"Timestamp"})步骤三:合并数据并画出价差
df = pd.merge(df_cg, df_yf, on="Timestamp", how="inner")
plt.figure(figsize=(9,4))
plt.plot(df["Timestamp"],df["Coingecko_BTC"],label="CoinGecko 价格")
plt.plot(df["Timestamp"],df["YFinance_BTC"],label="YFinance 价格")
plt.title("BTC 价格对比")
plt.legend()
plt.show()肉眼可见的两条线并未完全重合,价差(Spread) 便是潜在利润来源。
步骤四:量化价差并预估“理想利润”
df["Spread"] = abs(df["Coingecko_BTC"] - df["YFinance_BTC"])
plt.figure(figsize=(9,3))
plt.plot(df["Timestamp"],df["Spread"],color="red")
plt.title("CoinGecko vs YFinance 价差")
plt.show()若没有任何手续费,理论上可据此价差赚取 6,320 美元/天。但现实并非零和游戏,交易成本才是真正的“隐形屠夫”。
步骤五:引入交易费用模型
多数交易所采用 Maker / Taker 档位化费率。我们保守估计双边合计 0.2 %:
df["TradingCost"] = 0.002 * (df["Coingecko_BTC"] + df["YFinance_BTC"])只有 价差 > 双边交易费 才能触发信号,正可谓“每一笔利润都是被手续费咬过一口的苹果”。
步骤六:生成买卖信号并执行交易
方向判定
- 若
Coingecko_BTC<YFinance_BTC→ 在 Coingecko 买入、YFinance 卖出。 - 反之亦然。
df["Side"] = np.where(df["Coingecko_BTC"] < df["YFinance_BTC"], "buy_cg_sell_yf", "buy_yf_sell_cg")- 若
可盈利判定
df["Execute"] = df["Spread"] > df["TradingCost"]预计收益
profit = df.loc[df["Execute"], "Spread"] - df.loc[df["Execute"], "TradingCost"] print(f"全天可盈利笔数:{len(profit)},盈利率:{len(profit)/len(df):.1%},累积净收益:${profit.sum():.2f}")结果显示仅有 2 笔有机会净赚,收益约 303.69 美元——手续费抹平了 99% 机会。
步骤七:实战建议与踩坑总结
- 实时性窗口
5 分钟 k 线只是演示,高频套利更多用 毫秒级 WebSocket 推送,否则套不到价差就被市场抹平。 - 资金转移延迟
链上充值、提币、稳定币转换都会带来 时间敞口。 - 对冲仓位
热门衍生品可提前对冲 BTC/USDT 永续合约,减少现货搬运延迟。 - API 限速与风控
各大交易所 429 限速及 KYC 提款额度 可能提前扼杀策略。
常见问题 FAQ
Q1:出现价差就一定可以套利吗?
A:不一定。实际跑通需同时满足:a) 价差 > 全链路费用;b) 两边深度足够大额成交;c) 提币/期货抵扣能在价差消失前完成。
Q2:两个演示来源都不是真实交易所,能直接套用吗?
A:不能。本文旨在演示思路,真实生产需对接 Binance、OKX、Bybit、Coinbase Pro 等 live API。注意 REST/WebSocket 延迟差异。
Q3:手续费为何定在 0.2 %?
A:折中计算。主线中心化交易所现货平均双边费用 0.15 %-0.3 %;若使用 VIP 费率 或平台 Token 折扣,可进一步降低。
Q4:Python 库是否支持多线程加速?
A:可以使用 asyncio + aiohttp 或 multiprocessing 池化;也可借助 CCXT Pro 统一接入多家交易所流。
Q5:对冲仓位出现穿仓怎么办?
A:必须设置 强平风控:提前存储备用保证金、实时监听 Mark Price 与 对冲仓位 delta。
Q6:如何监控流动性突然枯竭导致的“假价差”?
A:增设 订单簿深度 > X BTC 的条件过滤;也可利用 Mid-price vs Top-of-book 螺栓策略或 滑点预估模型。
参考阅读
- CEX 官方费率文档
- Async 行情推送实战 – CCXT Wiki
- 高并发套利网络框架 – uvloop + redis-streams