第四章:数据获取——用tushare和akshare搭建LOF数据管道
做LOF套利,数据就是你的眼睛。没有准确、及时的数据,再好的策略也是空中楼阁。
我个人习惯把数据获取分成两条线:一条是行情数据,一条是申赎数据。行情数据告诉你价格在动,申赎数据告诉你套利空间在哪。两条线缺一不可。
4.1 为什么需要两套数据源?
你想想看,LOF这个品种特殊在哪?它既能像股票一样在二级市场买卖,又能像基金一样在一级市场申赎。两个市场的价格经常不一致,这就是套利机会的来源。
但问题来了——行情数据和申赎数据,通常不在同一个地方。tushare擅长提供二级市场的行情快照,而akshare则能拿到一级市场的申赎清单。我刚开始做的时候,也想过只用一套数据源搞定,后来发现根本行不通。
核心逻辑:行情数据 + 申赎数据 = 套利机会识别
行情数据:实时价格、成交量、涨跌幅
申赎数据:基金净值、申购费率、赎回费率、申赎状态
说白了,你要算套利空间,就得同时知道「二级市场卖多少钱」和「一级市场值多少钱」。这两个价格一对比,溢价还是折价,一目了然。
4.2 使用tushare获取LOF行情数据
tushare是我用得比较多的数据源之一。它的行情数据接口稳定,字段也全。不过要注意,tushare需要注册获取token,免费版有调用频率限制。
4.2.1 安装与初始化
# 安装tushare
pip install tushare
# 初始化
import tushare as ts
# 设置token(记得替换成你自己的)
ts.set_token('你的token')
pro = ts.pro_api()
小提示:token可以在tushare官网的个人中心获取。免费版每分钟最多调用200次,做回测够用了,但实盘的话建议升级付费版。
4.2.2 获取LOF日线行情
我最常用的接口是fund_daily,它能拿到LOF基金的日线数据。包括开盘价、收盘价、最高价、最低价、成交量这些基础字段。
# 获取某只LOF的日线行情
df = pro.fund_daily(
ts_code='501018.SH', # 南方原油LOF
start_date='20240101',
end_date='20240301',
fields='ts_code,trade_date,open,high,low,close,vol,amount'
)
print(df.head())
输出结果大概长这样:
| ts_code | trade_date | open | high | low | close | vol |
|---|---|---|---|---|---|---|
| 501018.SH | 20240301 | 1.234 | 1.245 | 1.228 | 1.240 | 1234567 |
| 501018.SH | 20240229 | 1.220 | 1.238 | 1.215 | 1.232 | 987654 |
注意:tushare的基金行情数据,默认只返回上市交易的LOF和ETF。如果你查不到某只基金,先确认它是不是在交易所挂牌了。
4.2.3 获取实时行情
做套利需要盯盘,日线数据显然不够。我一般用fund_realtime接口拿实时快照。
# 获取实时行情
df_realtime = pro.fund_realtime(
ts_code='501018.SH',
fields='ts_code,name,price,high,low,volume,amount,pre_close'
)
print(df_realtime)
这个接口返回的是当前交易日的实时数据。嗯,这里要注意——tushare的实时数据有5秒左右的延迟,做高频套利的话可能不够用,但做日频套利完全没问题。
4.3 使用akshare获取LOF申赎数据
akshare是我后来才接触的库,说实话,一开始我对它有点偏见——觉得免费的东西质量不行。但用了一段时间后发现,它在基金申赎数据这块确实有两把刷子。
4.3.1 安装与基础用法
# 安装akshare
pip install akshare
# 基础导入
import akshare as ak
akshare不需要注册,直接就能用。这一点比tushare方便不少。
4.3.2 获取LOF申赎清单
我最常用的接口是fund_etf_fund_info_em,它能拿到LOF基金的申赎相关信息,包括净值、申购费率、赎回费率、申赎状态等。
# 获取LOF申赎数据
df_lof = ak.fund_etf_fund_info_em(
fund='501018', # 基金代码(不需要后缀)
start_date='20240101',
end_date='20240301'
)
print(df_lof.head())
返回的字段包括:
- 净值日期:基金净值的公布日期
- 单位净值:基金的实际净值
- 累计净值:考虑分红的净值
- 申购状态:开放/暂停
- 赎回状态:开放/暂停
- 申购费率:申购时需要支付的费率
- 赎回费率:赎回时需要支付的费率
关键点:申赎状态直接影响套利能否执行。如果基金暂停申购,那溢价套利就做不了。我曾在2022年原油LOF溢价的时候,因为没检查申赎状态,白白错过了机会。
4.3.3 获取实时净值估算
做套利时,净值是实时变化的。akshare提供了净值估算接口,可以拿到盘中估算净值。
# 获取实时净值估算
df_estimate = ak.fund_etf_spot_em()
# 筛选LOF基金
df_lof_estimate = df_estimate[df_estimate['基金类型'].str.contains('LOF')]
print(df_lof_estimate.head())
这个接口返回的是全市场所有ETF和LOF的实时估算数据。数据量比较大,我建议只筛选你关注的几只基金,别全量拉取。
4.4 数据整合:构建套利数据管道
数据拿到手了,下一步就是把它们整合起来。我个人习惯写一个数据管道类,把tushare和akshare的数据统一管理。
class LOFDataPipeline:
"""LOF套利数据管道"""
def __init__(self, tushare_token):
import tushare as ts
ts.set_token(tushare_token)
self.pro = ts.pro_api()
def get_market_data(self, ts_code, start_date, end_date):
"""获取行情数据(tushare)"""
df = self.pro.fund_daily(
ts_code=ts_code,
start_date=start_date,
end_date=end_date
)
return df
def get_redemption_data(self, fund_code, start_date, end_date):
"""获取申赎数据(akshare)"""
import akshare as ak
df = ak.fund_etf_fund_info_em(
fund=fund_code,
start_date=start_date,
end_date=end_date
)
return df
def merge_data(self, ts_code, fund_code, start_date, end_date):
"""合并行情和申赎数据"""
market_df = self.get_market_data(ts_code, start_date, end_date)
redeem_df = self.get_redemption_data(fund_code, start_date, end_date)
# 按日期合并
merged = pd.merge(
market_df,
redeem_df,
left_on='trade_date',
right_on='净值日期',
how='inner'
)
return merged
避坑指南:我曾经在合并数据时踩过一个坑——tushare的日期格式是'YYYYMMDD',而akshare的日期格式是'YYYY-MM-DD'。合并前一定要统一格式,否则会匹配不上。
4.5 数据质量检查
数据拿到手,别急着用。先做一轮质量检查。我一般检查这几个方面:
- 缺失值检查:净值、价格这些关键字段不能为空
- 日期连续性:交易日数据不能有跳空
- 异常值检查:价格不能为负,净值不能为0
- 申赎状态检查:确认基金是否正常开放申赎
def check_data_quality(df):
"""数据质量检查"""
issues = []
# 检查缺失值
if df['close'].isnull().any():
issues.append('收盘价存在缺失值')
# 检查异常值
if (df['close'] <= 0).any():
issues.append('收盘价存在非正值')
# 检查申赎状态
if '申购状态' in df.columns:
if (df['申购状态'] == '暂停').any():
issues.append('存在暂停申购的交易日')
return issues
4.6 本章核心知识图谱
下面这张图,是我做数据获取时的核心思路。你可以把它当成一个路线图。
这张图的核心逻辑很简单:tushare提供行情数据,akshare提供申赎数据,两者在数据整合层合并,最终输出套利信号。我建议你在实际项目中,也按照这个架构来搭建数据管道。
重要提醒:数据获取只是第一步。下一章我们会讲如何计算溢价率、识别套利机会。但如果你连数据都拿不准,后面的分析全是白搭。所以,花点时间把数据管道搭稳了,后面会省很多事。
好了,数据获取这块就讲到这里。代码我都贴出来了,你直接复制就能用。如果遇到问题,欢迎在课程群里交流。
公众号:蓝海资料掘金营,微信deep3321