第三章 数据获取:用Python搞定可转债行情数据
做可转债套利,第一步就是搞定数据。
没有数据,什么策略都是空中楼阁。我见过太多人,策略想得天花乱坠,结果连行情都拉不下来,白忙一场。
今天我就把三个主流数据源——聚宽、Tushare、AkShare——掰开揉碎了讲清楚。每个我都实战用过,坑也踩过不少。
3.1 聚宽(JoinQuant):本地与在线双模式
聚宽是我最早用的平台。它有两种玩法:在线研究环境和本地数据服务。
3.1.1 在线研究环境
你打开聚宽官网,新建一个研究 notebook,直接就能跑代码。不用装任何东西,特别适合快速验证想法。
# 聚宽在线环境获取可转债行情
from jqdata import *
# 初始化
run_daily()
# 获取所有可转债列表
bonds = get_all_securities(['bond'])
# 获取特定转债的历史行情
df = get_price('123456.XSHE',
start_date='2024-01-01',
end_date='2024-12-31',
frequency='daily',
fields=['open', 'close', 'high', 'low', 'volume', 'money'])
print(df.head())
我的习惯:在线环境适合写策略原型。但别用它跑大规模回测,速度会让你崩溃。
3.1.2 本地数据服务
聚宽也提供本地数据API。你需要先安装jqdatasdk,然后认证登录。
# 本地环境使用聚宽数据
import jqdatasdk as jq
# 认证(需要账号)
jq.auth('你的账号', '你的密码')
# 获取可转债基础信息
bonds = jq.get_all_securities(['bond'])
print(f"可转债数量: {len(bonds)}")
# 获取行情
df = jq.get_price('123456.XSHE',
count=100,
end_date='2024-12-31',
frequency='daily',
fields=['open', 'close', 'high', 'low', 'volume', 'money'])
注意:聚宽本地API有调用次数限制。我曾在回测时一次性拉了500只转债,直接被封了半小时。建议分批获取,加个time.sleep(1)。
3.2 Tushare:老牌数据接口
Tushare在国内量化圈名气很大。它数据全,但门槛也高——需要积分。
3.2.1 安装与配置
# 安装
pip install tushare
# 初始化
import tushare as ts
# 设置token(在Tushare官网注册获取)
ts.set_token('你的token')
pro = ts.pro_api()
3.2.2 获取可转债列表
# 获取所有可转债基本信息
cb_list = pro.cb_basic()
print(cb_list.head())
# 获取可转债日线行情
df = pro.cb_daily(
ts_code='123456.SZ',
start_date='20240101',
end_date='20241231',
fields='ts_code,trade_date,open,high,low,close,vol,amount'
)
print(df.head())
关键点:Tushare的字段名和聚宽不一样。比如成交量是'vol'不是'volume'。我刚开始用的时候,经常搞混,后来干脆写了个字段映射表。
3.2.3 获取转股价值等衍生数据
# 获取可转债转股信息
conv_info = pro.cb_conv(
ts_code='123456.SZ',
start_date='20240101',
end_date='20241231'
)
# 包含转股价、转股价值、溢价率等关键字段
避坑指南:我曾经发现Tushare的某些转债数据有缺失。比如2023年8月有几只转债的转股价没更新。后来我养成了习惯——拉完数据先做完整性检查,用isnull().sum()扫一遍。
3.3 AkShare:免费且全面的选择
AkShare是我最近比较偏爱的数据源。完全免费,数据源来自东方财富、新浪财经等,覆盖面很广。
3.3.1 安装与基础用法
# 安装
pip install akshare
# 获取可转债实时行情
import akshare as ak
# 获取所有可转债实时数据
df = ak.bond_cb_jsl()
print(df.head())
3.3.2 获取历史行情
# 获取单只转债的历史日线
df = ak.bond_cb_daily(
symbol='sh123456',
start_date='20240101',
end_date='20241231'
)
print(df.head())
注意:AkShare的代码格式和前面两个不一样。沪市转债前面要加'sh',深市加'sz'。比如'123456'在深市就是'sz123456'。这个坑我踩过,拉出来全是空数据,查了半天才发现是前缀问题。
3.3.3 获取可转债溢价率等关键指标
# 获取可转债溢价率数据
df = ak.bond_cb_jsl()
# 这个接口直接返回溢价率、转股价值、到期收益率等
# 筛选低溢价率转债
low_premium = df[df['溢价率'] < 5].sort_values('溢价率')
print(low_premium[['转债代码', '转债名称', '溢价率', '转股价值']])
3.4 三个数据源对比
| 特性 | 聚宽 | Tushare | AkShare |
|---|---|---|---|
| 费用 | 部分免费,高级功能收费 | 基础免费,高级需积分 | 完全免费 |
| 数据完整性 | 高 | 高 | 中等 |
| 更新速度 | 实时 | 实时 | 准实时 |
| 学习成本 | 中等 | 中等 | 低 |
| 适合场景 | 策略回测 | 专业研究 | 快速原型 |
我的建议:如果你刚开始做可转债套利,先用AkShare。免费、上手快。等策略跑通了,再考虑用Tushare或聚宽做更精细的数据验证。
3.5 实战:搭建统一数据获取模块
我个人习惯是写一个统一的数据获取模块。这样切换数据源时,只需要改一行代码。
class CBDataFetcher:
"""可转债数据获取统一接口"""
def __init__(self, source='akshare'):
self.source = source
if source == 'jq':
import jqdatasdk as jq
jq.auth('user', 'pwd')
elif source == 'tushare':
import tushare as ts
ts.set_token('token')
self.pro = ts.pro_api()
def get_daily(self, code, start, end):
"""获取日线数据"""
if self.source == 'akshare':
import akshare as ak
return ak.bond_cb_daily(symbol=code,
start_date=start,
end_date=end)
elif self.source == 'tushare':
return self.pro.cb_daily(ts_code=code,
start_date=start,
end_date=end)
# 其他数据源类似
def get_premium(self, code):
"""获取溢价率"""
# 实现略
pass
经验之谈:我建议你把数据获取和策略逻辑分开。这样哪天数据源挂了,换个接口就行,不用改策略代码。我吃过这个亏——聚宽有一次维护,我的整个回测系统瘫痪了两天。
3.6 数据质量检查
数据拿到手,别急着用。先做三件事:
- 检查缺失值:用df.isnull().sum()看看哪些字段有空值
- 检查异常值:比如价格突然变成0,或者成交量异常大
- 检查时间序列:交易日是否连续,有没有跳空
def check_data_quality(df):
"""数据质量检查"""
print("=== 数据质量报告 ===")
print(f"数据量: {len(df)}")
print(f"缺失值:\n{df.isnull().sum()}")
print(f"价格范围: {df['close'].min():.2f} - {df['close'].max():.2f}")
print(f"日期范围: {df['trade_date'].min()} - {df['trade_date'].max()}")
# 检查是否有价格异常
abnormal = df[df['close'] <= 0]
if len(abnormal) > 0:
print(f"警告: 发现{len(abnormal)}条价格异常数据")
重要:数据质量直接决定策略成败。我见过有人用有缺失的数据跑回测,结果策略表现特别好——后来发现是因为缺失的数据恰好是亏损的交易。数据清洗这一步,省不了。
数据获取这块,说白了就是三个步骤:选数据源、拉数据、洗数据。别在这上面花太多时间纠结,选一个趁手的工具,先把数据跑起来再说。
我个人推荐顺序:AkShare入门 → Tushare进阶 → 聚宽做回测。当然,如果你公司有Wind或者Choice的接口,那更省事——不过那是另一个话题了。
嗯,数据到手了,下一步就是分析。但那是下一章的内容了。