量化策略17—复现ICU均线及其择时策略

在上一篇文章《ICU均线(上):使用稳健回归方法,突破传统均线》中,我们参考中泰证券的研报《“ICU均线”下的择时策略:“均线”才是绝对收益利器?》,介绍了一种基于稳健回归算法的新型均线——ICU均线,它能够更好地处理异常值,提供更稳健的趋势信号,并且具有更快的反应速度和更高的稳健性。本文以沪深300指数为例,介绍如何用Python实现ICU均线,并观察用ICU均线来进行择时的效果。

一、获取基础数据
1. 导入需要的库
# 导入需要使用的库import akshare as akimport pandas as pdimport numpy as np
# 在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数据源获取沪深300指数的数据
关于AKShare的使用,可以参看后附的文章《如何用AKShare获取金融数据》。AKShare的接口有时会有变动,如果获取数据出错请参考AKShare的官网解决。
# 获取指数数据index_code = 'sh000300'start_date = pd.to_datetime('2005-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'])price_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()接口获取沪深300指数从2005年到2023年的行情数据。数据格式如下:
图片
二、计算ICU均线
1. 计算重复中位数回归的斜率和截距
在《ICU均线(上):使用稳健回归方法,突破传统均线》中,我们介绍了ICU均线的算法,ICU均线的计算采用了重复中位数回归方法。
重复中位数回归是一种稳健回归技术,它的计算方法是:先对每一对数据点计算斜率;再对所有数据点对的斜率取中位数,得到整体的回归斜率;然后根据回归斜率,对每一对数据点计算截距;最后对所有数据点的截距取中位数,得到整体的回归截距。重复中位数回归的函数如下:
def repeated_median_regression(x, y):
    n = len(x)    slopes = []
    # 计算所有点对的斜率    for i in range(n):        for j in range(i + 1, n):            if x[j] != x[i]:                slopes.append((y[j] - y[i]) / (x[j] - x[i]))
    # 计算所有斜率的中位数    median_slope = np.median(slopes)    
    # 计算所有截距的中位数    intercepts = y - median_slope * x    median_intercept = np.median(intercepts)
    return median_slope, median_intercept
上述函数中,参数x为回归的自变量(时间序列),参数y为回归的因变量(价格序列)。函数返回重复中位数回归方程的斜率和截距。
2. 用重复中位数回归计算ICU均线
得出回归方程的斜率和截距后,我们就可以构建回归直线方程,根据中位数回归计算出的回归系数 α 和 β,计算时间窗口 window 内的均线值。
def calculate_icu_ma(prices, window):
    icu_ma = []
    for i in range(len(prices)):        if i < window - 1:            icu_ma.append(np.nan)  # 前window-1个点无法计算均线        else:            x = np.arange(window)            y = prices[i - window + 1:i + 1].values            slope, intercept = repeated_median_regression(x, y)            icu_ma.append(intercept + slope * (window - 1))  # 计算窗口最后一个点的均线值
    return pd.Series(icu_ma, index=prices.index)
上述函数用于计算ICU均线,参数prices为价格序列(pandas Series);参数window为计算均线的滚动窗口大小。函数的返回值为ICU均线序列。
接下来我们可以用这个函数来计算ICU均线:
# 计算ICU均线window = 10price_df['icu_ma'] = calculate_icu_ma(price_df['close'], window)
上述代码以10日为滚动窗口来计算ICU均线。
三、根据ICU均线择时
1. 计算择时信号
择时规则为:当收盘价大于ICU均线值时开仓,反之则清仓。
# ICU均线择时信号:当日 close 值大于 icu_ma 值则开仓,否则清仓timing_df = pd.DataFrame()timing_df['icu择时'] = (price_df['close']>price_df['icu_ma']) * 1.timing_df['不择时'] = 1.
在上述代码中,当策略开仓时,择时信号为1;当策略清仓时,择时信号为0。
2. 计算择时收益
# 计算指数每日的收益率price_df['returns'] = price_df['close'].pct_change().shift(-1).fillna(0)# 计算择时后的每日收益率timing_ret = timing_df.mul(price_df['returns'], axis=0).dropna()
# 计算择时后的累计收益率cumul_ret = (1 + timing_ret.fillna(0)).cumprod() - 1.
上述代码先计算指数的每日收益率,然后将日收益率和择时信号相乘,如果择时信号为1,则保留该日收益率;如果择时信号为0,则该日收益率为0。然后计算累计收益。关于各种收益的计算,可以参看后附的文章《一文讲清7种收益率的python实现》。
3. 可视化择时效果
# 可视化输出cumul_ret.plot(figsize=(10, 6), title='ICU择时')
择时效果如下:
图片
可以看到,ICU择时达到了不错的择时效果。但复现的效果不及研报,原研报中择时收益曲线的回撤很小,有可能加入了其他的过滤条件。

相关文章:

ICU均线(上):使用稳健回归方法,突破传统均线

如何用AKShare获取金融数据

一文讲清7种收益率的python实现

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

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

相关推荐

发表回复

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