量化策略02—均线择时策略全攻略(下)

本文是量化策略解析系列的第2篇。系列连载见:

量化策略解析—系列连载

在上一篇文章《均线择时策略全攻略(上)》中,我们介绍了均线择时策略的思路,本篇将用一个具体的例子来介绍如何用Python来实现均线择时策略。
一、获取基础数据
我们以上证指数为例,讲解如何用Python实现均线择时。
1. 导入需要用到的库
# 导入需要使用的库import akshare as akimport pandas as pdimport numpy as npimport pandas_ta as ta# 在matplotlib绘图中显示中文和负号import matplotlib.pyplot as pltimport matplotlib as mplmpl.rcParams['font.family'] = 'STKAITI' # 中文字体'STKAITI'plt.rcParams['axes.unicode_minus'] = False   # 解决坐标轴负数的负号显示问题# 关闭警告信息import warningswarnings.filterwarnings('ignore')
2. 从AKShare数据源获取上证指数的数据
关于AKShare的使用,可以参看后附的文章《如何用AKShare获取金融数据》。AKShare的接口有时会有变动,如果获取数据出错请参考AKShare的官网解决。
# 获取上证指数数据index_code = 'sh000001'start_date = pd.to_datetime('2014-01-01')end_date = pd.to_datetime('2023-12-31')price_df = ak.stock_zh_index_daily(symbol=index_code)price_df['date'] = pd.to_datetime(price_df['date']).dt.dateprice_df = price_df[(price_df['date']>=start_date) & (price_df['date']<=end_date)]price_df = price_df.sort_values('date').set_index('date')
上述代码从AKShare的stock_zh_index_daily接口获取上证指数的行情数据保存到一个名为”price_df”的DataFrame中,并选取’2014-01-01’至’2023-12-31’这10年的数据作为本例的样本数据。
3. 计算每日的收益率
# 计算每日的收益率price_df['returns'] = price_df['close'].pct_change().shift(-1).fillna(0)
上述代码用pct_change()函数计算每日的收益率。
price_df的格式如下:
图片
二、单均线择时策略
1. 计算移动平均线
移动平均线的种类很多,这里用简单移动平均线作为示例。我们使用pandas_ta库来计算移动平均线,关于pandas_ta库的使用可以参看后附的文章《量化宝藏工具箱:技术指标库 Pandas TA 教程》。
# 计算移动平均线值days = 20price_df[f'ma_{days}'] = ta.sma(price_df['close'], length=days)
上述代码的功能是调用pandas_ta库来计算20日简单移动平均线(SMA)。
2. 计算择时信号
开仓信号:当日的均线值大于昨日的均线值时开仓,值为1;
清仓信号:当日的均线值小于昨日的均线值时清仓,值为0。
# 择时信号:当日均线值大于昨日则开仓,否则清仓timing_df = (price_df[[f'ma_{days}']].diff()>0) * 1.timing_df['不择时'] = 1.
上述代码中,price_df[[f’ma_{days}’]].diff()计算20日均线值的变化量,即当天的均线值与前一天的均线值的差。若当天的均线值大于前一天的,则diff()>0的结果为True,乘以1.后变为1.0,表示发出买入信号;若不大于,则结果为False,乘以1.后变为0.0,表示发出卖出信号。在timing_df中还添加了一个名为不择时的列,其值均为1.0,代表不进行择时操作时的基准情况。
3. 计算择时的效果
# 计算每日收益率timing_ret = timing_df.mul(price_df['returns'], axis=0)timing_ret['超额收益'] = (1+timing_ret[f'ma_{days}']).div(1+timing_ret['不择时'], axis=0) - 1.# 计算累计收益率cumul_ret = (1 + timing_ret.fillna(0)).cumprod() - 1.
这段代码先计算每日收益率(包括择时后的每日收益和不择时的每日收益),用mul()函数将择时信号与前面计算的日收益率相乘,如果择时信号为1则保留当日收益率,如果择时信号为0则当日收益率为0;然后计算超额收益,即将择时的收益与不择时的收益比较;最后用cumprod()函数计算累计收益。
关于各种收益的计算,可以参看后附的文章《一文讲清7种收益率的python实现》和《计算超额收益,你用减法还是除法》。
4. 将择时的效果可视化输出
# 可视化输出cumul_ret.plot(figsize=(10, 6), title='单均线择时')
结果如下:
图片
三、双均线择时策略
双均线择时策略需要两条均线:长均线和短均线。
1. 计算长短周期的均线值
days_s = 5days_l = 60price_df['ma_s'] = ta.sma(price_df['close'], length=days_s)price_df['ma_l'] = ta.sma(price_df['close'], length=days_l)
上述代码中,days_s 为短周期(5天),days_l 为长周期(60天)。然后使用pandas_ta库来计算长短两个周期的移动平均线。
2. 计算择时信号
开仓信号:当短均线值大于长均线值时开仓,值为1;
清仓信号:当短均线值小于长均线值时清仓,值为0。
# 择时信号:当日短期均线值大于长期均线值则开仓,否则清仓timing_df = pd.DataFrame()timing_df['择时'] = (price_df['ma_s']>price_df['ma_l']) * 1.timing_df['不择时'] = 1.
3. 计算择时的效果
# 计算择时后的每日收益率timing_ret = timing_df.mul(price_df['returns'], axis=0)timing_ret['超额收益'] = (1+timing_ret['择时']).div(1+timing_ret['不择时'], axis=0) - 1.
# 计算累计收益率cumul_ret = (1 + timing_ret.fillna(0)).cumprod() - 1.
4. 将择时的效果可视化输出
# 可视化输出cumul_ret.plot(figsize=(10, 6), title='双均线择时')
结果如下:
图片
四、均线择时的分析
1. 均线择时的效果分析
1)从择时的收益曲线可以看到,在本例中,不管是单均线择时还是双均线择时,都比不择时的效果要好。
2)分析择时的超额曲线可以看到,择时的收益主要来源于指数大跌时的止损。而由于均线的滞后性,在指数由跌转涨时,由于未能及时开仓,此时的超额收益是负的(表现为超额收益曲线的下跌),尤其在震荡行情中,均线择时容易反复打脸。
2. 均线择时的参数优化
均线择时主要有两个参数:
1)均线的类型
均线的类型有多种,本例中使用了简单移动平均线,我们还可以使用其他的均线来观察择时效果。关于各种均线的介绍,可以参看后附的文章《均线解密:如何有效利用移动平均线》。利用pandas_ta库,很容易就能计算各种不同的均线。
2)均线的周期
在本例中,我们在单均线策略中使用了20日均线,在双均线策略中使用了5日均线和60日均线。我们还可以尝试其他的均线周期,观察不同周期的择时效果。但要注意的是,如果我们对所有的均线周期进行遍历,总能够找到一个最好的周期值,但这个周期值可能是过拟合的结果,即过度拟合了样本数据,但在样本外可能是失效的。为了防止这个问题,我们可以将数据分为样本内和样本外两份,在样本内寻找最佳参数,然后在样本外验证这个参数是否有效。
均线择时是一种简单但常用的择时策略。尽管存在一定的局限性和挑战,但通过合理的策略设计和优化,均线择时仍然是量化投资领域中一个有价值的工具。
相关文章:
均线择时策略全攻略(上)
均线解密:如何有效利用移动平均线
如何用AKShare获取金融数据
量化宝藏工具箱:技术指标库 Pandas TA 教程
一文讲清7种收益率的python实现
计算超额收益,你用减法还是除法

发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/106004
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!

(0)
股市刺客的头像股市刺客
上一篇 5天前
下一篇 5天前

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注