3、数据获取与准备:用akshare搞定可转债行情数据
做量化策略,数据就是你的弹药库。弹药不行,枪法再好也白搭。
我个人习惯,在开始任何回测之前,先把数据流程跑通。这一步看似枯燥,但能帮你省下后面80%的调试时间。今天我们就来聊聊,怎么用akshare拿到干净的可转债数据。
3.1 为什么选akshare?
市面上能拿数据的库不少,但akshare有个好处——它直接对接国内主流数据源,而且免费。我刚开始做可转债策略时,试过手动从网站爬,结果网站改个版,我的代码就废了。后来换成akshare,省心多了。
你想想看,一个库能覆盖股票、基金、期货、债券,还持续更新,这本身就是个巨大的时间红利。
核心要点:akshare的数据接口基本是傻瓜式调用,一行代码就能拿到DataFrame。但要注意,它依赖网络请求,如果数据量太大,建议加个延时。
3.2 安装与基础调用
先装库,这个不用多说:
pip install akshare --upgrade
然后试试能不能跑通:
import akshare as ak
# 获取可转债实时行情
df = ak.bond_zh_cov()
print(df.head())
嗯,这里要注意。第一次调用时,akshare会下载一些依赖数据,可能会慢一点。别急,等它跑完就行。
3.3 数据清洗与预处理
拿到原始数据后,你会发现一个问题——字段名是中文的,而且有些列是字符串格式。比如“现价”这一列,里面可能带“元”字,或者有空值。
我曾经在回测时,因为没处理空值,结果策略信号全乱了。从那以后,我养成了一个习惯:拿到数据先做三件事。
- 类型转换:把价格、成交量等数值列转成float或int
- 缺失值处理:要么填充,要么删除,不能留空
- 日期标准化:统一成YYYY-MM-DD格式
看个例子:
import pandas as pd
# 假设df是原始数据
df['现价'] = pd.to_numeric(df['现价'], errors='coerce')
df['转股价值'] = pd.to_numeric(df['转股价值'], errors='coerce')
# 删除缺失值严重的行
df = df.dropna(subset=['现价', '转股价值'])
# 计算双低值
df['双低值'] = df['现价'] + df['转股溢价率'] * 100
说白了,这一步就是给数据“洗澡”。洗得越干净,后面的分析越靠谱。
小技巧:如果你发现某只可转债的转股溢价率是负数,别急着删。这通常意味着存在套利机会,但也要注意流动性风险。
3.4 数据存储与读取
每次回测都去实时拉数据,既不现实也不高效。我建议把清洗后的数据存到本地,用的时候直接读。
我个人偏爱Parquet格式,压缩率高,读写快。当然,CSV也行,就是慢一点。
# 存储为Parquet
df.to_parquet('cb_data.parquet', index=False)
# 读取
df = pd.read_parquet('cb_data.parquet')
如果你用的是CSV,记得指定编码:
df.to_csv('cb_data.csv', index=False, encoding='utf-8-sig')
df = pd.read_csv('cb_data.csv', encoding='utf-8-sig')
避坑指南:我曾经因为没加encoding参数,结果在Windows上读CSV时全是乱码。后来统一用utf-8-sig,再也没出过问题。
3.5 本章知识体系
下面这张图,帮你理清数据获取与准备的完整流程:
3.6 实战中的几个坑
数据这块,我踩过的坑不少。挑几个典型的说说:
- 数据延迟:akshare的数据不是实时的,有几分钟延迟。做日内策略要注意。
- 停牌数据:可转债停牌时,价格不变,但成交量是0。回测时如果不处理,会高估流动性。
- 复权问题:可转债有下修、回售等事件,会影响价格。我一般用前复权数据做回测。
我的建议:第一次跑通流程后,把数据存一份快照。这样即使网络断了,你也能继续调试策略。数据是死的,策略是活的,别让数据问题卡住你的思路。
好了,数据准备这块就聊到这儿。记住,干净的数据是策略成功的一半。下一章我们开始真正进入回测环节,到时候你会感谢今天认真洗数据的自己。