量化策略—RSRS择时(下):用Python实现RSRS择时策略

量化投资学
90906-03 13:27

作者:量化投资学

题图:量化投资学微信公众号


在《RSRS择时(上):预测市场阻力与支撑的全新方法》和《RSRS择时(中):用加权回归和标准分改进RSRS指标》中,我们介绍了RSRS择时的思路,本文将以一个具体的例子说明如何用Python实现RSRS择时。

一、RSRS 择时的步骤

我们先简单回顾一下如何用RSRS指标进行:

1. 使用过去N日的最高价和最低价数据,通过线性回归模型计算出斜率(beta值)。这个斜率表示了最高价相对于最低价的变动强度。

2. 将计算得到的斜率转换为标准分(z-score),以标准化斜率值。为了提高择时的有效性,还可以用修正标准分或右偏标准分来改进RSRS指标。

3. 设定阈值S,当标准分的RSRS指标的值超过阈值S时,可以视为买入信号;当RSRS指标的值低于-S时,可以视为卖出信号。

4. 根据生成的交易信号执行交易,进行市场择时。

5. 通过历史数据回测,找到最优的参数N、M和S,这些参数决定了RSRS指标的择时效果。

6. 定期评估RSRS择时策略的表现,包括收益率、夏普比率、最大回撤等指标,动态调整RSRS指标的参数,以保持策略的适应性和有效性。

下面以沪深300指数为例,介绍如何用RSRS指标对沪深300指数进行择时交易。

二、获取基础数据

1. 导入需要的库

# 导入需要使用的库
import akshare as ak
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
# 在matplotlib绘图中显示中文和负号
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['font.family'] = 'STKAITI' # 中文字体'STKAITI'
plt.rcParams['axes.unicode_minus'] = False   # 解决坐标轴负数的负号显示问题
# 关闭警告信息
import warnings
warnings.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年的行情数据。数据格式如下:

图片

三、计算RSRS指标

1. 基础版的RSRS指标

基础版的RSRS是用一定时间窗口(N)内的最高价和最低价建立线性回归模型,然后求解模型的斜率beta作为RSRS指标。

# 基础版的RSRS
# 最高价和最低价的窗口长度
window_N = 16

# 初始化斜率和决定系数R-squared序列
beta = np.full(price_df.shape[0], np.nan)
r_squared = np.full(price_df.shape[0], np.nan)

# 逐个滚动窗口计算
for i in range(window_N-1, len(price_df)):
    # 获取窗口数据
    y = price_df['high'].iloc[i-window_N+1:i+1].values
    X = np.c_[np.ones(window_N), price_df['low'].iloc[i-window_N+1:i+1].values]

    # 线性回归模型
    model = LinearRegression()
    model.fit(X, y)

    # 保存斜率和R-squared
    beta[i] = model.coef_[1]
    r_squared[i] = model.score(X, y)

price_df['rsrs_beta'] = beta
price_df['r_squared'] = r_squared

2. 计算标准分版的RSRS

标准分RSRS指标是指计算回归斜率的标准分(z-score)作为RSRS指标值,公式为:

标准分RSRS = (当日斜率值 − 斜率均值) / 斜率标准差

其中,斜率均值和标准差是基于过去M日的斜率时间序列计算得到的。

# 标准分版的RSRS
# 计算标准分的窗口长度
window_M = 300
# 计算滚动窗口的平均值和标准差
rolling_mean = price_df['rsrs_beta'].rolling(window=window_M).mean()
rolling_std = price_df['rsrs_beta'].rolling(window=window_M).std()
# 计算斜率的Z-score值 = (当日斜率值 − 斜率均值) / 斜率标准差
price_df['rsrs_zscore'] = (price_df['rsrs_beta'] - rolling_mean) / rolling_std

3. 计算修正标准分版的RSRS

修正标准分通过将标准分与决定系数相乘来构建,以减少拟合效果差的标准分对策略的影响。决定系数(R-squared)可以反映模型对数据拟合程度的好坏。一个高的R-squared值意味着模型对数据的解释程度高,而一个低的值则意味着模型拟合效果差。

# 修正标准分版的RSRS = 标准分RSRS * 决定系数
price_df['rsrs_zscore_r2'] = price_df['rsrs_zscore'] * price_df['r_squared']

4. 计算右偏标准分版的RSRS

将修正标准分乘以回归斜率使得标准分分布右偏,使得指标可能更好地捕捉市场的上涨动能,增强了指标对未来收益率的预测能力。

# 右偏标准分版的RSRS = 修正标准分RSRS * 斜率
price_df['rsrs_zscore_positive'] = price_df['rsrs_zscore_r2'] * price_df['rsrs_beta']

四、用RSRS指标构建择时策略

我们分别用标准分RSRS、修正标准分RSRS和右偏标准分RSRS构建择时信号,比较这几种RSRS择时的效果。

1. 计算RSRS择时信号

设定择时阈值 s,当RSRS值高于s时开仓,RSRS值低于-s时清仓,RSRS值在-s和s之间时维持先前的仓位。

# 根据RSRS择时
rsrs_list = ['rsrs_zscore', 'rsrs_zscore_r2', 'rsrs_zscore_positive']
rsrs_name = ['标准分RSRS', '修正标准分RSRS', '右偏标准分RSRS']
s = 0.7  # RSRS的阈值
# 计算择时信号:RSRS值高于s时开仓,RSRS值低于-s时清仓,RSRS值在-s和s之间时维持先前的仓位
timing_df = pd.DataFrame()
for i in range(len(rsrs_list)):
    rsrs = rsrs_list[i]
    timing_df[f'{rsrs_name[i]}择时'] = (price_df[rsrs]>=s) * 1. + (price_df[rsrs]<=-s) * -1.
timing_df = timing_df.replace(0, np.nan)  # 先将0替换为NA
timing_df = timing_df.fillna(method='ffill')  # 使用前值填充NA
timing_df[timing_df<0] = 0
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='RSRS择时')

结果如下:

图片

从上图可以看到,标准分RSRS、修正标准分RSRS和右偏标准分RSRS都取得了明显的择时收益。

在三种RSRS择时中,右偏标准分RSRS的择时效果最好,修正标准分RSRS的择时效果次之,说明对RSRS指标的优化取得了良好的结果。

上述例子中的择时参数(数据窗口长度N、标准分计算周期M、择时阈值S)未必是最优参数,大家可以观察其他参数的择时效果,寻找最优的参数。

另外,对于不同的指数其最优参数也不同,大家可以在不同的指数下测试RSRS择时策略的有效性。


版权声明:文章版权归原作者所有,部分文章由作者授权本平台发布,若有其他不妥之处的可与小编联系。

免责声明:
您在阅读本内容或附件时,即表明您已事先接受以下“免责声明”之所载条款:
1、本文内容源于作者对于所获取数据的研究分析,本网站对这些信息的准确性和完整性不作任何保证,对由于该等问题产生的一切责任,本网站概不承担;阅读与私募基金相关内容前,请确认您符合私募基金合格投资者条件。
2、文件中所提供的信息尽可能保证可靠、准确和完整,但并不保证报告所述信息的准确性和完整性;亦不能作为投资决策的依据,不能作为道义的、责任的和法律的依据或者凭证。
3、对于本文以及文件中所提供信息所导致的任何直接的或者间接的投资盈亏后果不承担任何责任;本文以及文件发送对象仅限持有相关产品的客户使用,未经授权,请勿对该材料复制或传播。侵删!
4、所有阅读并从本文相关链接中下载文件的行为,均视为当事人无异议接受上述免责条款,并主动放弃所有与本文和文件中所有相关人员的一切追诉权。

本篇来自以下专栏
0
好投汇
第一时间获取行业新鲜资讯和深度商业分析,请在微信公众账号中搜索「好投汇」,或用手机扫描左方二维码,即可获得好投汇每日精华内容推送和最优搜索体验,并参与编辑活动。

推荐阅读

0
0

评论

你来谈谈?
发表

联系我们

邮箱 :help@haotouxt.com
电话 :0592-5588692
地址 :福建省厦门市湖里区航空商务广场7号楼10F
好投汇微信订阅号
扫一扫
关注好投汇微信订阅号
Copyright © 2017-2024, All Rights Reserved 闽ICP备19018471号-6