跨交易所套利:Python 实践全指南

·

关键词:跨交易所套利、Python、加密货币、价格差异、交易手续费、信号生成、量化策略

市场背景与策略动机

跨交易所套利(cross-exchange arbitrage)是一种非常经典的量化交易思路:找出同一种加密资产在不同交易所之间的实时价差,在价格偏低处买入、同时在价格偏高处卖出,锁定无风险利润。
本指南以 Bitcoin(BTC) 为例,调用 CoinGeckoYFinance 两大公共数据源,带你跑完“连接行情 → 计算价差 → 扣除费用 → 生成信号 → 回测盈利”的全流程示例。

必备环境与库

import pandas as pd
import requests, json, datetime, numpy as np
import yfinance as yf
import matplotlib.pyplot as plt

步骤一:获取数据源 A——CoinGecko API

  1. 统一时间区间
    以 2023-04-17 为例,全天 5 分钟级 k 线共 288 条。
  2. 构建请求

    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()
  3. 清洗与重采样

    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"])

只有 价差 > 双边交易费 才能触发信号,正可谓“每一笔利润都是被手续费咬过一口的苹果”。

👉 想要一键部署高并发套利脚本?点这里查看最佳实践。

步骤六:生成买卖信号并执行交易

  1. 方向判定

    • Coingecko_BTC < YFinance_BTC → 在 Coingecko 买入、YFinance 卖出。
    • 反之亦然。
    df["Side"] = np.where(df["Coingecko_BTC"] < df["YFinance_BTC"], "buy_cg_sell_yf", "buy_yf_sell_cg")
  2. 可盈利判定

    df["Execute"] = df["Spread"] > df["TradingCost"]
  3. 预计收益

    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% 机会。

步骤七:实战建议与踩坑总结

  1. 实时性窗口
    5 分钟 k 线只是演示,高频套利更多用 毫秒级 WebSocket 推送,否则套不到价差就被市场抹平。
  2. 资金转移延迟
    链上充值、提币、稳定币转换都会带来 时间敞口
  3. 对冲仓位
    热门衍生品可提前对冲 BTC/USDT 永续合约,减少现货搬运延迟。
  4. 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 + aiohttpmultiprocessing 池化;也可借助 CCXT Pro 统一接入多家交易所流。

Q5:对冲仓位出现穿仓怎么办?
A:必须设置 强平风控:提前存储备用保证金、实时监听 Mark Price对冲仓位 delta

Q6:如何监控流动性突然枯竭导致的“假价差”?
A:增设 订单簿深度 > X BTC 的条件过滤;也可利用 Mid-price vs Top-of-book 螺栓策略或 滑点预估模型


参考阅读