3. 数据获取:使用CCXT库统一获取多个交易所的订单簿与Ticker数据

做跨市场套利,第一步就是搞定数据。

你想想看,如果连价格都拿不准,那还套什么利?我见过不少新手,策略写得挺漂亮,结果数据源一换,全崩了。说白了,数据获取是整个套利系统的地基。

3.1 为什么选CCXT?

CCXT是一个开源的加密货币交易库。它支持上百家交易所,API接口统一。我个人习惯用它,原因很简单:

  • 统一接口:不管你是连币安还是OKX,代码写法几乎一样
  • 活跃维护:社区更新快,新交易所支持及时
  • Python原生:pip install ccxt 就能用,省心

核心优势:你只需要学会一套API,就能操作上百个交易所。这在跨市场套利场景下,简直是神器。

3.2 安装与初始化

先装包,这个不用多说:

pip install ccxt

然后初始化交易所连接。我一般会这样写:

import ccxt

# 初始化交易所
exchange_binance = ccxt.binance({
    'apiKey': '你的API_KEY',
    'secret': '你的SECRET_KEY',
    'enableRateLimit': True,  # 自动限速,防止被封
})

exchange_okx = ccxt.okx({
    'apiKey': '你的API_KEY',
    'secret': '你的SECRET_KEY',
    'password': '你的API密码',  # OKX需要这个
    'enableRateLimit': True,
})

小技巧:enableRateLimit 一定要设为 True。我曾经因为没开这个,被币安封了半小时IP,那叫一个惨。

3.3 获取Ticker数据

Ticker就是当前市场快照。包含最新价、24小时涨跌、成交量等。做套利时,我主要看最新价和买卖盘口。

# 获取BTC/USDT的Ticker
ticker_binance = exchange_binance.fetch_ticker('BTC/USDT')
ticker_okx = exchange_okx.fetch_ticker('BTC/USDT')

print(f"币安 BTC价格: {ticker_binance['last']}")
print(f"OKX BTC价格: {ticker_okx['last']}")

# 计算价差
spread = ticker_binance['last'] - ticker_okx['last']
print(f"价差: {spread}")

嗯,这里要注意:不同交易所的Ticker字段名可能略有差异。但CCXT帮你统一了,都用 lastbidask 这些标准字段。

3.4 获取订单簿数据

订单簿才是套利的核心。它告诉你当前市场上所有的买单和卖单。我一般会获取深度为10或20的订单簿,够用就行,太深了反而影响速度。

# 获取订单簿,深度10
orderbook_binance = exchange_binance.fetch_order_book('BTC/USDT', limit=10)
orderbook_okx = exchange_okx.fetch_order_book('BTC/USDT', limit=10)

# 查看卖一价和买一价
print(f"币安 卖一: {orderbook_binance['asks'][0]}")
print(f"币安 买一: {orderbook_binance['bids'][0]}")
print(f"OKX 卖一: {orderbook_okx['asks'][0]}")
print(f"OKX 买一: {orderbook_okx['bids'][0]}")

避坑指南:我曾经在实盘时,只看了Ticker的最新价就开仓,结果订单簿深度不够,一单下去滑了0.3%。记住:套利一定要看订单簿,别只看Ticker。

3.5 统一数据格式

不同交易所返回的数据结构虽然被CCXT统一了,但为了后续策略处理方便,我习惯再封装一层:

def normalize_ticker(ticker, exchange_name):
    return {
        'exchange': exchange_name,
        'symbol': ticker['symbol'],
        'last': ticker['last'],
        'bid': ticker['bid'],
        'ask': ticker['ask'],
        'volume': ticker['baseVolume'],
        'timestamp': ticker['timestamp'],
    }

def normalize_orderbook(orderbook, exchange_name):
    return {
        'exchange': exchange_name,
        'bids': orderbook['bids'][:10],  # 取前10档
        'asks': orderbook['asks'][:10],
        'timestamp': orderbook['timestamp'],
    }

这样做的好处是:后面策略模块不用关心数据是从哪个交易所来的,统一处理就行。

3.6 多交易所并发获取

套利讲究时效性。如果串行获取数据,等拿到第二个交易所的价格时,第一个已经变了。所以必须并发。

我一般用Python的 asyncio 配合 aiohttp 来做。但CCXT本身也支持异步:

import asyncio
import ccxt.async_support as ccxt_async

async def fetch_ticker_async(exchange, symbol):
    ticker = await exchange.fetch_ticker(symbol)
    await exchange.close()
    return ticker

async def main():
    binance = ccxt_async.binance()
    okx = ccxt_async.okx()
    
    results = await asyncio.gather(
        fetch_ticker_async(binance, 'BTC/USDT'),
        fetch_ticker_async(okx, 'BTC/USDT'),
    )
    
    print(f"币安: {results[0]['last']}")
    print(f"OKX: {results[1]['last']}")

asyncio.run(main())

为什么用异步? 串行获取两个交易所数据,网络延迟加起来可能200ms。异步并发,基本就是最慢那个交易所的延迟,通常50ms以内。做高频套利,这150ms的差距就是钱。

3.7 数据缓存与更新频率

别每次策略循环都去拉数据。我建议用本地缓存,定时更新:

import time
from functools import lru_cache

class DataCache:
    def __init__(self, ttl=1.0):  # 缓存1秒
        self.cache = {}
        self.ttl = ttl
    
    def get(self, key, fetch_func):
        now = time.time()
        if key in self.cache:
            data, timestamp = self.cache[key]
            if now - timestamp < self.ttl:
                return data
        
        # 缓存过期,重新获取
        data = fetch_func()
        self.cache[key] = (data, now)
        return data

这样做的好处是:策略循环可以跑得很快,数据更新频率可控。我一般设0.5秒到1秒的TTL,具体看策略对时效性的要求。

3.8 核心逻辑流程图

下面这张图,是我做跨市场套利数据获取的标准流程:

跨市场套利数据获取流程 启动数据获取 初始化多个交易所连接(CCXT) 异步并发获取Ticker和订单簿 数据标准化与缓存 计算价差,判断套利机会 循环等待下一轮

3.9 实战中的坑

最后分享几个我踩过的坑:

  • 限频问题:每个交易所都有API调用限制。CCXT的enableRateLimit能帮你控制,但不同交易所的限频策略不一样。我建议在代码里再加一层本地限频。
  • 网络超时:跨市场套利经常要连海外交易所。网络波动是家常便饭。一定要加超时重试机制。
  • 数据延迟:你拿到的订单簿,可能已经滞后了几百毫秒。做高频套利时,要考虑这个延迟对策略的影响。

我的经验:刚开始做套利时,我直接用Ticker数据开仓,结果被订单簿深度坑了好几次。后来改成只看订单簿前5档,配合滑点预估,才稳定下来。

数据获取这块,说白了就是三个字:快、准、稳。快靠异步并发,准靠CCXT统一接口,稳靠缓存和重试机制。把这三点做好,你的套利系统就成功了一半。

专注资料整理