搭建过程
每个交易者都应该形成一套自己的交易系统。
很多交易者也清楚知道,搭建自己交易系统的重要性。现实中,从0到1往往是最难跨越的一步。
授人鱼不如授人以渔,为了帮助大家跨出搭建量化系统的第一步,我们决定推出这个主题系列。
这个系列中,我们用Python从0开始一步步搭建出一套ETF量化交易系统(选择ETF标的是因为对于普通交易者来说,ETF相对于选强势股难度要小,而且没有退市风险)。大家可以跟随着我们的实现路径来一起学习,从过程中掌握方法。
掌握了方法之后,你可以换成期货系统、比特币系统、美股系统,然后在实战中不断去完善自己的系统了。
搭建一套ETF量化交易系统涉及多个模块和组件的协同工作,包括数据源模块、量化策略模块、可视化模块、数据库模块、回测评估模块、自动交易模块等等。
DAY1-DAY15链接如下:15天搭建ETF量化交易系统
近几年随着AI文本大模型的推出,搭建自己的量化交易系统变得容易很多。 我们对“15天搭建ETF量化交易系统”系列的学习进行升级!本期我们结合DeepSeek学习如何对获取到的数据进行处理。
数据处理 DAY1我们获取到了ETF指定日期范围内的分钟级历史数据。格式如下所示: 时间 开盘 收盘 最高 最低 涨跌幅 涨跌额 成交量 成交额 振幅 换手率0 2025-03-20 09:35:00 1.057 1.063 1.065 1.057 0.38 0.004 406697 43189768.0 0.76 6.021 2025-03-20 09:40:00 1.063 1.063 1.066 1.062 0.00 0.000 306233 32601928.0 0.38 4.542 2025-03-20 09:45:00 1.063 1.062 1.064 1.061 -0.09 -0.001 134322 14267103.0 0.28 1.993 2025-03-20 09:50:00 1.062 1.064 1.065 1.062 0.19 0.002 126123 13411748.0 0.28 1.874 2025-03-20 09:55:00 1.064 1.064 1.064 1.063 0.00 0.000 64821 6895902.0 0.09 0.96接下来,我们把这份数据格式告诉DeepSeek,然后告诉它:这是获取到的Dataframe格式的15分钟ETF数据,以这个格式为例,提供对数据进行清洗的python代码。
结合DeepSeek的反馈,我们在Python的IDE中实际调试后归纳的操作如下:
# 1. 格式化时间列 df['时间'] = pd.to_datetime(df['时间']) # 2. 检查缺失值 print("缺失值统计:") print(df.isnull().sum()) # 如果有缺失值,可以选择填充或删除 # 例如,用前一个值填充缺失值 df.fillna(method='ffill', inplace=True) # 3. 去除重复数据 df.drop_duplicates(inplace=True) # 4. 检查异常值(例如涨跌幅、成交量等是否在合理范围内) # 例如,检查涨跌幅是否在 -10% 到 10% 之间 df = df[(df['涨跌幅'] >= -10) & (df['涨跌幅'] <= 10)] # 5. 检查振幅是否在合理范围内(例如 0% 到 10%) df = df[(df['振幅'] >= 0) & (df['振幅'] <= 10)] # 6. 检查成交量是否为非负数 df = df[df['成交量'] >= 0] # 7. 检查成交额是否为非负数 df = df[df['成交额'] >= 0] # 8. 重置索引(可选) df.reset_index(drop=True, inplace=True) # 9. 检查数据清洗后的结果 print("清洗后的数据:") print(df.head())
接下来,我们要对数据进行规整化处理,我们要求DeepSeek:“请帮我对这个数据做规整化处理,涨跌幅、振幅、换手率列的列名用%单位,成交额列名用万为单位,成交量列名用手为单位,处理完成后存储为csv文件”。 结合DeepSeek的反馈,我们在Python的IDE中实际调试后归纳的操作如下:# 数据规整化处理 # 1. 修改列名 df.rename(columns={ '涨跌幅': '涨跌幅(%)', '振幅': '振幅(%)', '换手率': '换手率(%)', '成交额': '成交额(万)', '成交量': '成交量(手)' }, inplace=True)# 2. 转换数据单位 df['成交额(万)'] = df['成交额(万)'] / 10000 # 成交额转换为“万” df['成交量(手)'] = df['成交量(手)'] / 100 # 成交量转换为“手”# 3. 检查规整化后的数据 print("规整化后的数据:") print(df.head())# 4. 存储为CSV文件 output_file = '规整化后的数据.csv' df.to_csv(output_file, index=False, encoding='utf-8-sig') # 保存为UTF-8编码的CSV文件 print(f"规整化后的数据已保存为 {output_file}")规整化后的数据如下所示: 时间 开盘 收盘 最高 最低 涨跌幅(%) 涨跌额 成交量(手) 成交额(万) 振幅(%) 换手率(%)0 2025-03-20 09:35:00 1.057 1.063 1.065 1.057 0.38 0.004 4066.97 4318.9768 0.76 6.021 2025-03-20 09:40:00 1.063 1.063 1.066 1.062 0.00 0.000 3062.33 3260.1928 0.38 4.542 2025-03-20 09:45:00 1.063 1.062 1.064 1.061 -0.09 -0.001 1343.22 1426.7103 0.28 1.993 2025-03-20 09:50:00 1.062 1.064 1.065 1.062 0.19 0.002 1261.23 1341.1748 0.28 1.874 2025-03-20 09:55:00 1.064 1.064 1.064 1.063 0.00 0.000 648.21 689.5902 0.09 0.96接下来,我们要每天增量地去存储数据,作为以后回测分析的历史数据,我们可以问DeepSeek:每天都会获取当天的15分钟数据,做同样的数据处理,然后和历史的15分钟数据合并成一个数据文件,请提供Python代码。结合DeepSeek的反馈,我们在Python的IDE中实际调试后归纳的操作如下:def process_and_merge_data(new_data_df, history_file='历史数据.csv'): """ 处理新数据并与历史数据合并 :param new_data_df: 当天获取的新数据 :param history_file: 历史数据文件路径 """ df_new = new_data_df # 2. 数据规整化处理 # 修改列名 df_new.rename(columns={ '涨跌幅': '涨跌幅(%)', '振幅': '振幅(%)', '换手率': '换手率(%)', '成交额': '成交额(万)', '成交量': '成交量(手)' }, inplace=True) # 转换数据 df_new['成交额(万)'] = df_new['成交额(万)'] / 10000 # 成交额转换为“万”单位 df_new['成交量(手)'] = df_new['成交量(手)'] / 100 # 成交量转换为“手”单位 # 3. 读取历史数据 if os.path.exists(history_file): df_history = pd.read_csv(history_file) else: df_history = pd.DataFrame() # 如果历史数据文件不存在,创建一个空的DataFrame # 4. 合并新数据和历史数据 df_combined = pd.concat([df_history, df_new], ignore_index=True) # 5. 去重(根据时间列) df_combined.drop_duplicates(subset=['时间'], inplace=True) # 6. 按时间排序 df_combined['时间'] = pd.to_datetime(df_combined['时间']) df_combined.sort_values(by='时间', inplace=True) print(df_combined) # 7. 保存合并后的数据 df_combined.to_csv(history_file, index=False, encoding='utf-8-sig') print(f"新数据已处理并合并到 {history_file}")我们可以看到存储的数据文件中已经把20日和21日的ETF数据结合起来了!接下来,我们获取到了5分钟周期的ETF数据后,我们就可以通过短周期的数据重采样成为长周期的K线数据,我们把5分钟的数据格式告诉DeepSeek,然后问DeepSeek:我已经把历史数据存储在csv中,按我们要求的数据格式,把5分钟周期的数据重采样成为60分钟的K线数据,请提供Python代码。结合DeepSeek的反馈,我们在Python的IDE中实际调试后反馈的结果如下: 时间 开盘 收盘 最高 最低 涨跌幅 涨跌额 成交量 成交额 振幅 换手率0 2025-03-20 10:30:00 1.057 1.059 1.066 1.057 0.00 0.000 1468123 1.559777e+08 0.85 21.741 2025-03-20 11:30:00 1.059 1.059 1.060 1.058 0.00 0.000 291814 3.090811e+07 0.19 4.322 2025-03-20 14:00:00 1.060 1.064 1.065 1.059 0.47 0.005 1017167 1.080729e+08 0.57 15.063 2025-03-20 15:00:00 1.063 1.064 1.075 1.062 0.00 0.000 3830081 4.089030e+08 1.22 56.734 2025-03-21 10:30:00 1.072 1.087 1.093 1.071 2.16 0.023 13636908 1.478784e+09 2.07 201.975 2025-03-21 11:30:00 1.086 1.120 1.127 1.084 3.04 0.033 21588616 2.394617e+09 3.96 319.746 2025-03-21 14:00:00 1.121 1.147 1.159 1.113 2.41 0.027 19548030 2.220576e+09 4.11 289.527 2025-03-21 15:00:00 1.146 1.130 1.154 1.098 -1.48 -0.017 29056432 3.266451e+09 4.88 430.35这样的好处是我们只需要存储小周期的数据即可,无论是60分钟还是日线、周线都可以从5分钟的历史数据中转换而成。
总结
有了DeepSeek作为助手,我们可以将它的反馈直接复制到Python IDE中进行调试。如果发现结果与预期不符,可以再次反馈给DeepSeek进行修正,直到满意为止。为了更好地利用DeepSeek,我们还需要不断提升自己的背景知识储备。
初期如果难以判断DeepSeek的反馈是否符合需求,可以在答疑解惑群中与大家一起学习交流,共同进步。
说明
此系列为连载专栏,完整代码会上传知识星球《玩转股票量化交易》!作为会员们的学习资料。
想要加入知识星球《玩转股票量化交易》的小伙伴记得先微信call我获取福利!
非星球会员需要的话,需要单独联系我购买!
知识星球介绍点击:知识星球《玩转股票量化交易》精华内容概览