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 核心逻辑流程图

下面这张图,展示了从交易所到策略的完整数据流:

交易所 API ccxt 统一接口 OHLCV 数据清洗 & 存储 策略计算 交易信号 下单执行 图:从交易所API到交易信号的完整数据流

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%的时间写策略,这才是量化交易的正确姿势。

专注资料整理