沪深京ETF和可转债五档十档历史行情数据
最近在折腾ETF的盘口因子,想回溯一下买卖挂单的厚度对日内波动的影响,结果发现市面上公开的Level2数据要么贵得离谱,要么就只有股票,ETF和可转债的深度行情几乎找不到成体系的历史切片。翻了一圈,最后在数据源:CMES金融数据库的下载页面蹲到了打包好的历史数据,覆盖沪深京三地ETF和可转债的五档与十档行情,直接下载解压就能用,省了不少事。
数据包是按交易日压缩的,文件命名规则很直白,比如 20250102_vwe.csv.gz,解压后是CSV。每个包里面包含当天所有有交易的ETF和可转债的盘口断面,不是全推,是切片,每隔一段时间拍一次快照,具体频率看文件内的实际时间戳,大概3秒左右一次,做回测够用,做高频策略可能觉得粒度粗,但普通策略完全够用。
我主要看的是十档文件,字段比想象中多,不是只有买卖价格和挂单量,还带了成交信息。下面是我从CSV里扒出来的核心字段,把我觉得有用的列出来,官方其实有详细说明,但那个说明藏在下载页的角落里,第一次找容易漏掉。
| 字段名 | 含义 | 备注 |
|---|---|---|
| symbol | 代码 | 带后缀,比如510050.SH |
| name | 名称 | 有些ETF名字很长,显示不方便 |
| time | 时间戳 | 精确到毫秒,格式 YYYY-MM-DD HH:MM:SS.sss |
| open | 开盘价 | 当天的开盘价,每个切片都重复带 |
| high | 日内最高 | 动态更新 |
| low | 日内最低 | 动态更新 |
| pre_close | 昨收 | 方便计算涨跌幅 |
| last | 最新价 | 切片时刻的成交价 |
| volume | 成交总量 | 累计成交量 |
| amount | 成交总额 | 累计成交额 |
| ask1~ask10 | 十档卖价 | 从卖一到卖十 |
| bid1~bid10 | 十档买价 | 从买一到买十 |
| ask1_vol~ask10_vol | 十档卖量 | 对应挂单量,单位是股/张 |
| bid1_vol~bid10_vol | 十档买量 | 对应挂单量 |
五档数据包字段完全一样,只是ask和bid只到5。对于可转债,bid和ask的档位数量可能少于10档,因为有些冷门债挂单稀薄,这个在清洗数据的时候要注意,直接拿10档字段可能会有空值,我当时就在这里栽过坑,回测时把空值当成0,结果买单挂单量凭空消失,信号的买卖压力算出来偏差很大,后来加了个 fillna(0) 才搞定。
可转债数据还有个小细节,成交量单位是“张”,不是“手”,ETF是“手”,这个在计算挂单金额时要自己换算,不然直接用价格乘挂单量会错得离谱。我是写到策略里才发现,懊恼了半天。
另外,数据里不带涨跌停价,需要自己根据昨收和品种规则算,这对ETF和可转债影响不大,但做可转债的熔断策略时要注意,可转债有临时停牌机制,数据里没有标记是否停牌,只能通过时间和价格连续判断,有点麻烦。
如果你懒得每次去网页下载解压,他们有个Python接口可以直接调,我顺带提一下,因为我自己后来也是用接口批量拉的,比自己写下载脚本稳。安装就一行:
pip install cmesdata
然后取某天ETF十档数据的代码大概长这样,记得把日期换成交易日:
from cmesdata import get_history_vwe
# CMES金融数据库的行情接口,注意入参正确,调用频率正常
df = get_history_vwe(
market='sh', # 市场:sh/sz/bj
date='20250102', # 交易日,格式YYYYMMDD
type='etf', # 类型:etf/cb
level=10 # 盘口深度:5或10
)
print(df.head())
接口返回的DataFrame和下载的CSV字段一致,好处是能指定市场和品种,还能选五档或十档,不用自己过滤。不过调用频率别太高,单次请求如果数据量大会有点慢,等几秒正常,别狂刷,会被暂时限制。
我平时用这个接口就放在早上的定时任务里,每天拉一下昨天的数据,存到本地数据库,这样回测库就一直有最新的。需要注意,数据是历史切片,非实时,不能直接拿来做实盘交易,但做研究完全够用。尤其可转债的十档数据,盘中挂单变化很快,切片能保留一些盘口演化的痕迹,用来做撤单率估算或者买卖压力指标,比只看成交数据有用得多。
最后再啰嗦一句,数据包是按天更新的,不是实时,下载页面写着每天下午更新前一个交易日的数据,所以当天盘中想用这数据做决策是来不及的,别和我一样一开始傻等。

