搭建过程
每个交易者都应该形成一套自己的交易系统。
很多交易者也清楚知道,搭建自己交易系统的重要性。现实中,从0到1往往是最难跨越的一步。
授人鱼不如授人以渔,为了帮助大家跨出搭建量化系统的第一步,我们决定推出这个主题系列。
这个系列中,我们用Python从0开始一步步搭建出一套ETF量化交易系统(选择ETF标的是因为对于普通交易者来说,ETF相对于选强势股难度要小,而且没有退市风险)。大家可以跟随着我们的实现路径来一起学习,从过程中掌握方法。
掌握了方法之后,你可以换成期货系统、比特币系统、美股系统,然后在实战中不断去完善自己的系统了。
搭建一套ETF量化交易系统涉及多个模块和组件的协同工作,包括数据源模块、量化策略模块、可视化模块、数据库模块、回测评估模块、自动交易模块等等。
DAY1我们介绍下如何搭建自己的ETF数据源模块
ETF数据源
AkShare是基于Python的财经数据接口库,AkShare提供的API函数,可以直接获取ETF的实时行情、历史数据等。
我们使用AkShare作为ETF数据源。
我们使用命令安装下AkShare:
pip install akshare
我们需要三类数据:ETF代码和名称、实时行情数据以及历史行情数据。
使用fund_etf_category_sina 函数获取所有 ETF 基金的实时行情数据。
etf_data = ak.fund_etf_category_sina(symbol="ETF基金")
# 显示前10行
print(etf_data.head(5))
"""
代码 名称 最新价 涨跌额 涨跌幅 买入 卖出 昨收 今开 最高 最低 成交量 成交额
0 sz159998 计算机ETF 0.714 0.021 3.030 0.714 0.715 0.693 0.695 0.717 0.693 39176900 27750943
1 sz159997 电子ETF 0.843 0.025 3.056 0.843 0.844 0.818 0.821 0.846 0.819 42597200 35630600
2 sz159996 家电ETF 1.175 0.012 1.032 1.174 1.175 1.163 1.163 1.181 1.160 77680200 91177308
3 sz159995 芯片ETF 0.826 0.024 2.993 0.825 0.826 0.802 0.801 0.826 0.801 480305699 393002419
4 sz159994 5GETF 0.766 0.030 4.076 0.766 0.767 0.736 0.740 0.771 0.740 56534500 43087108
"""
# 显示最后3行
print(etf_data.tail(3))
"""
代码 名称 最新价 涨跌额 涨跌幅 买入 卖出 昨收 今开 最高 最低 成交量 成交额
934 sh510030 价值ETF 0.848 0.003 0.355 0.848 0.851 0.845 0.850 0.852 0.842 2808900 2381342
935 sh510020 超大盘ETF 2.753 0.040 1.474 2.751 2.753 2.713 2.724 2.756 2.724 653710 1789779
936 sh510010 180治理ETF 1.464 0.018 1.245 1.435 1.465 1.446 1.445 1.464 1.445 24900 36290
"""
fund_etf_category_sina 接口返回的是一个pandas DataFrame,包含了全部ETF基金的实时行情数据。每行数据代表一个ETF基金,通常包含以下列:
基金代码:ETF基金的代码,用于唯一标识一个ETF基金。
基金简称:ETF基金的简称或名称。
最新价:ETF基金当前的交易价格。
涨跌幅:ETF基金相对于前一日收盘价的涨跌幅百分比。
涨跌额:ETF基金相对于前一日收盘价的涨跌金额。
开盘价:ETF基金当日开盘时的价格。
昨收盘:ETF基金前一交易日的收盘价。
最高价:ETF基金当日交易的最高价格。
最低价:ETF基金当日交易的最低价格。
成交量:ETF基金当日的成交量。
成交额:ETF基金当日的成交额。
fund_etf_category_sina接口还可以返回ETF的代码和名称。
# 打印ETF代码和名称
for index, item in etf_data.iterrows():
print(f"ETF代码: {item['代码']}, ETF名称: {item['名称']}")
"""
ETF代码: sz159998, ETF名称: 计算机ETF
ETF代码: sz159997, ETF名称: 电子ETF
ETF代码: sz159996, ETF名称: 家电ETF
ETF代码: sz159995, ETF名称: 芯片ETF
ETF代码: sz159994, ETF名称: 5GETF
"""
fund_etf_hist_min_em 接口包含了指定ETF基金在指定日期范围内的分钟级历史数据。
# 使用 fund_etf_hist_min_em 获取 ETF 基金的分钟级历史数据。
etf_hist_data = ak.fund_etf_hist_min_em(symbol="510300", start_date="20240425", end_date="20240426")
print(etf_hist_data.head(5))
"""
时间 开盘 收盘 最高 最低 涨跌幅 涨跌额 成交量 成交额 振幅 换手率
0 2024-04-25 09:35:00 3.503 3.501 3.509 3.501 -0.34 -0.012 321378 112617010.0 0.23 0.06
1 2024-04-25 09:40:00 3.502 3.499 3.502 3.498 -0.06 -0.002 268571 93992920.0 0.11 0.05
2 2024-04-25 09:45:00 3.500 3.499 3.501 3.498 0.00 0.000 187412 65579490.0 0.09 0.03
3 2024-04-25 09:50:00 3.499 3.496 3.499 3.495 -0.09 -0.003 208152 72790535.0 0.11 0.04
4 2024-04-25 09:55:00 3.496 3.501 3.502 3.495 0.14 0.005 153200 53594439.0 0.20 0.03
"""
fund_etf_hist_min_em 接口返回的是一个DataFrame,包含以下列:
时间:分钟级别的时间戳。
最新价:ETF基金在对应时间点的最新交易价格。
涨跌幅:ETF基金在对应时间点的涨跌幅百分比。
成交量:ETF基金在对应时间点的成交量。
成交额:ETF基金在对应时间点的成交额。
开盘价:ETF基金在对应时间段的开盘价格(可能并非每分钟都有开盘价)。
最高价:ETF基金在对应时间段内的最高交易价格。
最低价:ETF基金在对应时间段内的最低交易价格。
封装成类
作为一套系统,我们需要创建一个ETF数据源模块,供其他模块调用。于是创建一个ETFDataSource类,这个类提供了三个方法:
get_etf_codes_and_names:查询ETF代码和名称,返回DataFrame。
get_etf_real_time_data:获取指定ETF基金的实时行情数据,返回Series。
get_etf_hist_data:获取指定ETF基金在指定日期范围内的历史走势数据,返回DataFrame。
关键例程代码如下所示,完整代码可以前往知识星球下载。
class ETFDataSource:
"""
ETF数据源模块,封装了akshare库的相关接口。
"""
def __init__(self):
"""
初始化ETF数据源模块。
"""
pass
def get_etf_codes_and_names(self):
"""
查询ETF代码和名称。
Returns:
pd.DataFrame: 包含ETF代码和名称的DataFrame。
"""
# 省略
return etf_data[['代码', '名称']]
def get_etf_real_time_data(self, symbol):
"""
获取ETF实时行情数据。
Args:
symbol (str): ETF基金的代码。
Returns:
pd.Series: 包含ETF实时行情数据的Series。
"""
# 使用akshare的fund_etf_category_sina接口获取ETF实时行情数据
return real_time_data[real_time_data["代码"] == code]
def get_etf_hist_data(self, symbol, start_date, end_date):
"""
获取ETF历史走势数据。
Args:
symbol (str): ETF基金的代码。
start_date (str): 开始日期,格式为'YYYYMMDD'。
end_date (str): 结束日期,格式为'YYYYMMDD'。
Returns:
pd.DataFrame: 包含ETF历史走势数据的DataFrame。
"""
# 省略
return hist_data
if __name__ == "__main__":
# 创建ETF数据源对象
etf_source = ETFDataSource()
# 查询ETF代码和名称
etf_codes_and_names = etf_source.get_etf_codes_and_names()
print("ETF代码和名称:")
print(etf_codes_and_names)
# 假设要查询代码为'510300'的ETF实时行情数据
symbol = '510300'
etf_real_time_data = etf_source.get_etf_real_time_data(symbol)
print(f"\nETF {symbol} 实时行情数据:")
print(etf_real_time_data)
# 假设要查询代码为'510300'的ETF在指定日期范围内的历史走势数据
start_date = '20240401'
end_date = '20240426'
etf_hist_data = etf_source.get_etf_hist_data(symbol, start_date, end_date)
print(f"\nETF {symbol} {start_date}至{end_date}历史走势数据:")
print(etf_hist_data)
说明
此系列为连载专栏,完整代码会上传知识星球《玩转股票量化交易》!作为会员们的学习资料。
想要加入知识星球《玩转股票量化交易》的小伙伴记得先微信call我获取福利!
非星球会员需要的话,需要单独联系我购买!
知识星球介绍点击:知识星球《玩转股票量化交易》精华内容概览