3、数据获取基础:认识交易所API、使用ccxt获取行情数据、K线数据(OHLCV)的结构与含义
做量化交易,第一步不是写策略,而是拿到数据。
数据拿不到,或者拿错了,后面全是白搭。我见过太多新手,策略写得花里胡哨,结果一跑回测,发现K线数据的时间戳是错的,或者成交量单位搞反了。嗯,这种坑我自己也踩过。
3.1 交易所API是什么?
说白了,API就是交易所给你开的一个“后门”。
你通过这个后门,可以问交易所:“现在比特币多少钱?”或者“帮我下一个买单”。交易所收到你的请求,就会返回数据或者执行操作。
常见的交易所API类型:
- REST API:你发一个HTTP请求,它返回一个JSON。适合获取历史数据、下单。
- WebSocket API:建立长连接,交易所主动推数据给你。适合实时行情。
核心要点:做回测用REST API就够了。做实盘,必须上WebSocket。
我个人习惯,刚开始接触一个新交易所时,先用REST API把历史数据拉下来,跑一遍回测。等策略稳定了,再上WebSocket做实盘。
3.2 为什么选ccxt?
你想想看,全球上百家交易所,每家API的格式都不一样。如果每家都单独写一套代码,那得累死。
ccxt就是来解决这个问题的。它是一个统一接口的加密货币交易库,支持100+交易所。
它的好处很明显:
- 一套代码,切换交易所只需改一个参数
- 自动处理签名、频率限制、代理等脏活
- 社区活跃,更新快
我的建议:新手别自己手写API请求。直接用ccxt,省下的时间够你多写三个策略了。
3.3 使用ccxt获取行情数据
先安装:
pip install ccxt
然后,我们来获取币安的BTC/USDT实时行情:
import ccxt
# 初始化交易所
exchange = ccxt.binance()
# 获取Ticker(当前行情)
ticker = exchange.fetch_ticker('BTC/USDT')
print(ticker)
# 输出示例:
# {
# 'symbol': 'BTC/USDT',
# 'bid': 50000.0, # 买一价
# 'ask': 50001.0, # 卖一价
# 'last': 50000.5, # 最新成交价
# 'baseVolume': 12345, # 24小时成交量(BTC)
# 'quoteVolume': 6.17e8, # 24小时成交额(USDT)
# 'timestamp': 1700000000000
# }
这里要注意,fetch_ticker返回的是当前快照数据。如果你需要历史数据,得用fetch_ohlcv。
我曾经踩过的坑:有些交易所的ticker里,volume单位是基础货币(比如BTC),有些是计价货币(比如USDT)。一定要先看文档确认,否则回测结果会差很多。
3.4 K线数据(OHLCV)的结构与含义
OHLCV是量化交易最基础的数据结构。它代表一根K线。
每个字母的含义:
| 字段 | 含义 | 说明 |
|---|---|---|
| O | Open(开盘价) | 这根K线开始时的第一笔成交价 |
| H | High(最高价) | 这根K线期间的最高成交价 |
| L | Low(最低价) | 这根K线期间的最低成交价 |
| C | Close(收盘价) | 这根K线结束时的最后一笔成交价 |
| V | Volume(成交量) | 这根K线期间的总成交量 |
ccxt返回的OHLCV数据是一个二维数组:
[
[timestamp, open, high, low, close, volume],
[timestamp, open, high, low, close, volume],
...
]
举个例子:
# 获取最近10根1小时K线
ohlcv = exchange.fetch_ohlcv('BTC/USDT', timeframe='1h', limit=10)
for candle in ohlcv:
ts = candle[0] # 毫秒时间戳
open_price = candle[1]
high_price = candle[2]
low_price = candle[3]
close_price = candle[4]
volume = candle[5]
print(f"时间: {ts}, 开: {open_price}, 高: {high_price}, 低: {low_price}, 收: {close_price}, 量: {volume}")
重要提醒:时间戳单位是毫秒!很多新手直接当秒用,结果数据全乱了。记得除以1000转成秒,或者用pd.to_datetime(ts, unit='ms')。
3.5 核心逻辑流程图
下面这张图,展示了从交易所到策略的完整数据流:
3.6 实战:获取并保存K线数据
下面是一个完整的示例,把数据存到CSV文件里:
import ccxt
import pandas as pd
from datetime import datetime
def fetch_and_save_ohlcv(symbol='BTC/USDT', timeframe='1h', limit=500):
exchange = ccxt.binance()
# 获取数据
ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
# 转成DataFrame
df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
# 时间戳转成可读格式
df['datetime'] = pd.to_datetime(df['timestamp'], unit='ms')
# 保存到CSV
filename = f"{symbol.replace('/', '_')}_{timeframe}.csv"
df.to_csv(filename, index=False)
print(f"已保存 {len(df)} 根K线到 {filename}")
return df
# 运行
df = fetch_and_save_ohlcv()
我的习惯:每次拉数据时,我都会先检查一下最后一条数据的时间戳,确认数据是最新的。有时候交易所会有延迟,别拿旧数据当实时数据用。
3.7 常见问题与避坑
- 频率限制:交易所对API调用次数有限制。ccxt默认会处理,但如果你并发太高,还是会被封。我一般控制在每秒1-2次请求。
- 数据对齐:不同交易所的K线时间可能差几秒。做套利策略时,一定要对齐时间戳。
- 缺失数据:有些币种交易量小,K线可能不完整。回测前先检查数据连续性。
我曾经犯过的错:有一次我直接用默认参数拉数据,没检查时间范围。结果回测时发现,策略在2018年表现特别好,但实际那段时间交易所根本没上线这个币种。数据全是空的!从那以后,我每次拉数据都会先打印头尾时间戳确认一下。
好了,数据获取这块就讲到这里。记住一句话:数据质量决定策略上限。花80%的时间在数据上,20%的时间写策略,这才是量化交易的正确姿势。