请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  数理科学 帖子:3364716 新帖:3

自定义指数系列2 - 技术择时

有事您说话发表于:6 月 21 日 20:37回复(1)

1 引言¶

研究目的:
在上文《自定义指数系列1 - 构建价值100指数(10年10倍)》中,我们构造了自定义价值100指数,并且取得了还不错的效果。

但是,自定义价值100指数本身还是随着市场有较大的波动,那么我们能否通过技术择时,来达到更高的收益、更低的回撤呢?

研究内容:
上文中我们构造了月度调仓的自定义价值100指数,计算出了日频的open close high low。分别尝试均线择时、RSRS择时,观察技术择时在自定义指数上的效果。

研究结论:

RSRS择时在自定义指数上,也可以取得不错的效果。在自定义指数上,N=18 M=1100 阈值=0.7也是一个较好的参数。

2 RSRS指标计算¶

首先我们来回顾一下RSRS的计算方式:

在每个交易日,取最近N个时间序列的high low价格进行ols回归,得到beta斜率和R2(rsquared);

在每个交易日,取最近M个beta斜率,进行标准化,得到标准分zscore;

对标准分zscore,乘以rsquared,得到修正标准分;

对修正标准分,再乘以斜率beta,得到右偏修正标准分。

在上文中,我们构造了自定义价值100指数。下面,我们对自定义价值100指数,进行RSRS的计算。

import pickle
# 读取自定义指数数据文件
pkl_file = open('zs_df.pkl', 'rb')
zs_df = pickle.load(pkl_file)
pkl_file.close()
# OLS线性回归
def calc_OLS_list(x, y):  
    X = sm.add_constant(x)
    model = sm.OLS(y, X)
    results = model.fit()
    beta = results.params[1]
    r2 = results.rsquared
    return beta, r2
import statsmodels.api as sm
import pandas as pd

# 计算RSRS
N = 18
M = 1100
factor_index = []
factor_list = []
for day_index in range(N, len(zs_df)):
    df = zs_df[day_index - N: day_index]

    high_list = df['high'].tolist()
    low_list = df['low'].tolist()

    # print(len(high_list), len(low_list))
    beta, r2 = calc_OLS_list(low_list, high_list)

    date = zs_df.index[day_index]
    # print(date, beta, r2)
    factor_index.append(date)
    factor_list.append([beta, r2])

# 生成dataframe,行索引为日期,列名为'beta', 'r2'
factor_df = pd.DataFrame(data=factor_list, index=factor_index, columns=['beta', 'r2'])


factor_df = factor_df.reindex(columns=['beta', 'r2', 'score', 'revise_score', 'rightdev_score'])
for day_index in range(M, len(factor_df)):
    date = factor_df.index[day_index]
#     print(date)

    beta_list = factor_df['beta'][day_index - M: day_index]
    r2_list = factor_df['r2'][day_index - M: day_index]
    # score
    mean = beta_list.mean()
    std = beta_list.std()
    score = (beta_list[-1] - mean) / std

    revise_score = score * r2_list[-1]
    rightdev_score = score * r2_list[-1] * beta_list[-1]

    # 标准分
    factor_df.loc[date]['score'] = score
    #修正标准分
    factor_df.loc[date]['revise_score'] = revise_score
    #右偏标准分
    factor_df.loc[date]['rightdev_score'] = rightdev_score

print(factor_df)
                beta        r2       ...        revise_score  rightdev_score
2005-02-01  0.721068  0.796776       ...                 NaN             NaN
2005-02-02  0.712813  0.796776       ...                 NaN             NaN
2005-02-03  0.723315  0.614239       ...                 NaN             NaN
2005-02-04  0.806353  0.684180       ...                 NaN             NaN
2005-02-16  0.909182  0.737740       ...                 NaN             NaN
2005-02-17  0.939005  0.827477       ...                 NaN             NaN
2005-02-18  0.923678  0.859396       ...                 NaN             NaN
2005-02-21  0.915748  0.875366       ...                 NaN             NaN
2005-02-22  0.914922  0.883110       ...                 NaN             NaN
2005-02-23  0.925498  0.898250       ...                 NaN             NaN
2005-02-24  0.919584  0.918033       ...                 NaN             NaN
2005-02-25  0.899269  0.921517       ...                 NaN             NaN
2005-02-28  0.967134  0.942492       ...                 NaN             NaN
2005-03-01  0.966841  0.948925       ...                 NaN             NaN
2005-03-02  0.965966  0.951675       ...                 NaN             NaN
2005-03-03  0.969137  0.953157       ...                 NaN             NaN
2005-03-04  0.953566  0.950340       ...                 NaN             NaN
2005-03-07  0.920248  0.945716       ...                 NaN             NaN
2005-03-08  0.873502  0.930443       ...                 NaN             NaN
2005-03-09  0.810561  0.908395       ...                 NaN             NaN
2005-03-10  0.936448  0.943958       ...                 NaN             NaN
2005-03-11  0.975239  0.915703       ...                 NaN             NaN
2005-03-14  1.092860  0.932706       ...                 NaN             NaN
2005-03-15  1.102901  0.881529       ...                 NaN             NaN
2005-03-16  1.065494  0.861151       ...                 NaN             NaN
2005-03-17  0.985226  0.814816       ...                 NaN             NaN
2005-03-18  0.925480  0.784785       ...                 NaN             NaN
2005-03-21  0.912233  0.858611       ...                 NaN             NaN
2005-03-22  0.950629  0.907123       ...                 NaN             NaN
2005-03-23  0.907662  0.925752       ...                 NaN             NaN
...              ...       ...       ...                 ...             ...
2019-04-24  1.032696  0.961064       ...            0.571160        0.589831
2019-04-25  1.012395  0.938994       ...            0.563454        0.581877
2019-04-26  1.086277  0.917585       ...            0.434201        0.439583
2019-04-29  1.121149  0.944821       ...            0.834293        0.906273
2019-04-30  1.067524  0.957335       ...            1.056917        1.184961
2019-05-06  1.064483  0.968816       ...            0.758259        0.809459
2019-05-07  0.976013  0.968607       ...            0.748148        0.796391
2019-05-08  0.961438  0.978698       ...            0.227659        0.222198
2019-05-09  0.962896  0.982678       ...            0.142977        0.137463
2019-05-10  0.972397  0.984691       ...            0.152259        0.146610
2019-05-13  0.948904  0.987986       ...            0.209443        0.203661
2019-05-14  0.961378  0.987683       ...            0.069786        0.066221
2019-05-15  0.963548  0.987122       ...            0.144936        0.139339
2019-05-16  0.962013  0.986692       ...            0.158230        0.152462
2019-05-17  0.967529  0.984934       ...            0.149444        0.143767
2019-05-20  0.975740  0.982703       ...            0.182881        0.176942
2019-05-21  0.971554  0.979539       ...            0.232748        0.227102
2019-05-22  0.949886  0.975775       ...            0.208441        0.202512
2019-05-23  0.959606  0.963275       ...            0.080278        0.076255
2019-05-24  0.980501  0.948110       ...            0.137394        0.131844
2019-05-27  0.975072  0.916422       ...            0.257264        0.252248
2019-05-28  0.999516  0.886433       ...            0.219605        0.214130
2019-05-29  0.963649  0.813485       ...            0.345561        0.345393
2019-05-30  0.940352  0.658666       ...            0.139911        0.134825
2019-05-31  0.946206  0.744973       ...            0.020308        0.019097
2019-06-03  0.933361  0.729153       ...            0.050708        0.047980
2019-06-04  0.947285  0.756437       ...           -0.007189       -0.006710
2019-06-05  0.989779  0.791843       ...            0.057725        0.054682
2019-06-06  1.091828  0.885225       ...            0.267119        0.264388
2019-06-10  1.114550  0.910277       ...            0.852680        0.930980

[3486 rows x 5 columns]

3 特征展示¶

import matplotlib.pyplot as plt

# 设置字体 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']

# 用来正常显示负号
plt.rcParams['axes.unicode_minus'] = False

"""
绘制直方图
data:必选参数,绘图数据
bins:直方图的长条形数目,可选项,默认为10
normed:是否将得到的直方图向量归一化,可选项,默认为0,代表不归一化,显示频数。normed=1,表示归一化,显示频率。
facecolor:长条形的颜色
edgecolor:长条形边框的颜色
alpha:透明度
"""
plt.hist(factor_df['beta'], bins=50, density=0, facecolor="#1F77B4", edgecolor=None, alpha=1)
# 显示横轴标签
plt.xlabel("区间")
# 显示纵轴标签
plt.ylabel("频数/频率")
# 显示图标题
plt.title("beta分布直方图")
plt.show()

plt.hist(factor_df['score'], bins=50, density=0, facecolor="#1F77B4", edgecolor=None, alpha=1)
# 显示横轴标签
plt.xlabel("区间")
# 显示纵轴标签
plt.ylabel("频数/频率")
# 显示图标题
plt.title("标准分-分布直方图")
plt.show()

plt.hist(factor_df['revise_score'], bins=50, density=0, facecolor="#1F77B4", edgecolor=None, alpha=1)
# 显示横轴标签
plt.xlabel("区间")
# 显示纵轴标签
plt.ylabel("频数/频率")
# 显示图标题
plt.title("修正标准分-分布直方图")
plt.show()

plt.hist(factor_df['rightdev_score'], bins=50, density=0, facecolor="#1F77B4", edgecolor=None, alpha=1)
# 显示横轴标签
plt.xlabel("区间")
# 显示纵轴标签
plt.ylabel("频数/频率")
# 显示图标题
plt.title("右偏修正标准分-分布直方图")
plt.show()

从以上的分布图看,标准分的分布有尖峰厚尾的现象,且均值基本为0;经过标准分乘以R2之后,修正标准分的分布更符合正态分布;而右偏修正标准分,呈现出右偏态。

可以看出,对自定义指数的RSRS计算,计算出的数值分布与在沪深300指数上的分布一致。

下面,我们把beta、标准分、修正标准分、右偏标准分、自定义价值100指数收盘价以及上下阈值$^+_-0.7$的时间序列绘制成折线图。

# 展示折线图
def show_factor_value_line(factor_df):
    # 颜色 蓝 橙 绿 红 紫
    color_list = ['#5698c6', '#ff9e4a', '#60b760', '#e05c5d', '#ae8ccd', 'black', 'black']

    label_list = ['beta', 'score', 'revise_score', 'rightdev_score', 'close', 'up', 'low']

    # 这里需要用每天的因子数据分档,计算出5个折线
    y_list = [[], [], [], [], [], [], []]

    for i in range(0, len(factor_df)):
        date = factor_df.index[i]
        factor_data = factor_df.iloc[i]

        for l in range(0, 4):
            y_list[l].append(factor_data[label_list[l]])

        close = zs_df.loc[date]['close']
        y_list[4].append(close)
        y_list[5].append(0.7)
        y_list[6].append(-0.7)

    fig = plt.figure(figsize=(12, 8))
    ax = fig.add_subplot(1, 1, 1)
    ax.set_title("")

    for i in range(0, len(y_list)):
        yi = y_list[i]
        ax.plot(yi, color_list[i], label=label_list[i])

    x = np.arange(0, len(factor_df), 300)
    x_label = []
    for i in range(0, len(factor_df)):
        if i in x:
            date = factor_df.index[i]
            x_label.append(date)

    plt.xticks(x, x_label, rotation='vertical')


    plt.xticks(rotation=360)  # 旋转45度显示
    legend = ax.legend(loc='upper left', shadow=False)

    plt.show()
# 展示折线图
show_factor_value_line(factor_df)

可以看出,beta在时间序列上有波动,稳定大于0;beta的标准分、修正标准分、右偏标准分,在均值0左右上下波动,标准分的最低值较低,右偏标准分的峰度较高。但是右偏标准分的正值高峰,似乎和自定义价值100指数的最佳买点不匹配。

在沪深300指数上,我本人更倾向于使用修正标准分,在光大的择时周报中,沪深300指数的RSRS指标也是用修正标准分计算的。

那么,RSRS修正标准分在自定义价值100指数上择时,能否取得良好的效果呢?标准分、修正标准分、右偏标准分在自定义价值100指数上择时,到底谁更厉害?RSRS能否跑赢双均线?

接下来,我会对比3个标准分、MA60均线以及无择时的效果,我们拭目以待。

4 技术择时收益对比¶

通过上文中的代码,已经获取到了样本内的RSRS指标数据。

以下分别对比MA择时收益、RSRS择时收益,最后对最好的MA均线择时和最好的RSRS标准分择时做一个对比。

1. MA均线择时¶

# 求每天的收益率
ret_df_index = []
ret_df_data = []
for i in range(0, len(zs_df)):
    date = zs_df.index[i]
    ret_df_index.append(date)
    factor_data = zs_df.loc[date]
    ret_df_data.append(factor_data['close'])
ret_df = pd.DataFrame(data=ret_df_data, index=ret_df_index, columns=['close'])

# 收盘价的变化率为收益率
ret_df['rt'] = ret_df.pct_change()

ret_df = ret_df.reindex(columns=['close', 'rt', 'ma120', 'ma60', 'ma30', 'ma20', 'ma10','ma5'])
for i in range(120, len(ret_df)):
    date = ret_df.index[i]
    ret_df.loc[date]['ma120'] = ret_df['close'][i - 120:i].mean()

for i in range(60, len(ret_df)):
    date = ret_df.index[i]
    ret_df.loc[date]['ma60'] = ret_df['close'][i - 60:i].mean()

for i in range(30, len(ret_df)):
    date = ret_df.index[i]
    ret_df.loc[date]['ma30'] = ret_df['close'][i - 30:i].mean()

for i in range(20, len(ret_df)):
    date = ret_df.index[i]
    ret_df.loc[date]['ma20'] = ret_df['close'][i - 20:i].mean()

for i in range(10, len(ret_df)):
    date = ret_df.index[i]
    ret_df.loc[date]['ma10'] = ret_df['close'][i - 10:i].mean()

for i in range(5, len(ret_df)):
    date = ret_df.index[i]
    ret_df.loc[date]['ma5'] = ret_df['close'][i - 5:i].mean()


# 上移,转为当期收益率
ret_df['rt'] = ret_df['rt'].shift(-1)
ret_df['rt'] = ret_df['rt'].fillna(0)
print("ret_df")
print(ret_df)
ret_df
                close        rt    ...           ma10        ma5
2005-01-06   0.984399 -0.004273    ...            NaN        NaN
2005-01-07   0.980193  0.007802    ...            NaN        NaN
2005-01-10   0.987840  0.001123    ...            NaN        NaN
2005-01-11   0.988949  0.005529    ...            NaN        NaN
2005-01-12   0.994417  0.001192    ...            NaN        NaN
2005-01-13   0.995603 -0.009026    ...            NaN   0.987160
2005-01-14   0.986617 -0.023293    ...            NaN   0.989400
2005-01-17   0.963636  0.006111    ...            NaN   0.990685
2005-01-18   0.969524 -0.008519    ...            NaN   0.985844
2005-01-19   0.961265 -0.017065    ...            NaN   0.981959
2005-01-20   0.944861  0.030554    ...       0.981244   0.975329
2005-01-21   0.973730  0.019164    ...       0.977290   0.965180
2005-01-24   0.992391  0.007783    ...       0.976644   0.962603
2005-01-25   1.000115 -0.005659    ...       0.977099   0.968354
2005-01-26   0.994455 -0.014611    ...       0.978216   0.974472
2005-01-27   0.979925 -0.005268    ...       0.978220   0.981110
2005-01-28   0.974763 -0.007963    ...       0.976652   0.988123
2005-01-31   0.967001  0.000989    ...       0.975467   0.988330
2005-02-01   0.967957  0.054081    ...       0.975803   0.983252
2005-02-02   1.020304 -0.013117    ...       0.975646   0.976820
2005-02-03   1.006921  0.022975    ...       0.981550   0.981990
2005-02-04   1.030055  0.009578    ...       0.987756   0.987389
2005-02-16   1.039920 -0.006288    ...       0.993389   0.998448
2005-02-17   1.033382 -0.011582    ...       0.998142   1.013032
2005-02-18   1.021413  0.017595    ...       1.001468   1.026117
2005-02-21   1.039385  0.022405    ...       1.004164   1.026338
2005-02-22   1.062672  0.003274    ...       1.010110   1.032831
2005-02-23   1.066152  0.005165    ...       1.018901   1.039355
2005-02-24   1.071658  0.005566    ...       1.028816   1.044601
2005-02-25   1.077623  0.000103    ...       1.039186   1.052256
...               ...       ...    ...            ...        ...
2019-04-24  12.016030 -0.028016    ...      12.258106  12.219701
2019-04-25  11.679392 -0.021139    ...      12.197510  12.156202
2019-04-26  11.432507 -0.007791    ...      12.140640  12.035861
2019-04-29  11.343441  0.000871    ...      12.066889  11.841165
2019-04-30  11.353322 -0.062390    ...      11.991801  11.691963
2019-05-06  10.644983  0.014747    ...      11.892320  11.564938
2019-05-07  10.801965 -0.017862    ...      11.723466  11.290729
2019-05-08  10.609015 -0.017850    ...      11.575552  11.115244
2019-05-09  10.419648  0.035000    ...      11.395855  10.950545
2019-05-10  10.784340 -0.007813    ...      11.228875  10.765787
2019-05-13  10.700081 -0.002176    ...      11.108464  10.651990
2019-05-14  10.676795  0.022112    ...      10.976869  10.663010
2019-05-15  10.912877  0.016998    ...      10.876610  10.637976
2019-05-16  11.098376 -0.031375    ...      10.824647  10.698748
2019-05-17  10.750163 -0.013776    ...      10.800140  10.834494
2019-05-20  10.602065  0.017821    ...      10.739824  10.827658
2019-05-21  10.791003 -0.013027    ...      10.735533  10.808055
2019-05-22  10.650428 -0.016051    ...      10.734436  10.830897
2019-05-23  10.479475 -0.005572    ...      10.738578  10.778407
2019-05-24  10.421081  0.017422    ...      10.744560  10.654627
2019-05-27  10.602639  0.004183    ...      10.708234  10.588810
2019-05-28  10.646989  0.001608    ...      10.698490  10.588925
2019-05-29  10.664113 -0.004381    ...      10.695510  10.560122
2019-05-30  10.617398 -0.005729    ...      10.670633  10.562859
2019-05-31  10.556569 -0.015678    ...      10.622535  10.590444
2019-06-03  10.391060 -0.012315    ...      10.603176  10.617542
2019-06-04  10.263096 -0.002946    ...      10.582075  10.575226
2019-06-05  10.232860 -0.009529    ...      10.529285  10.498447
2019-06-06  10.135346  0.011077    ...      10.487528  10.412197
2019-06-10  10.247620  0.000000    ...      10.453115  10.315786

[3504 rows x 8 columns]
# MA均线择时收益
def show_ma_factor_return_rate(ori_factor_df):
    factor_df = ori_factor_df.dropna()
    color_list = ['black','#5698c6', '#ff9e4a', '#60b760', '#e05c5d', '#ae8ccd','grey','gold']

    label_list = ['不择时','ma120', 'ma60', 'ma30','ma20','ma10','ma5','ma5-ma60']

    # 这里需要用每天的因子数据分档,计算出5个折线
    y_list = []
    for i in range(0, len(label_list)):
        y_list.append([])

    # 收益率折线图从0开始
    for i in range(0, len(label_list)):
        yi = y_list[i]
        yi.append(0)

    pre_date = None

    flag_list = [0, 0, 0, 0]
    for date in factor_df.index:
        if type(pre_date) == type(None):
            pre_date = date
            continue

        # pre_date为date的上一个调仓日,这里获取上一个调仓日的因子值
        pre_factor_data = factor_df.loc[pre_date]

        # 获取上一个调仓日到本调仓日的收益率
        ret = ret_df.loc[pre_date]['rt']

        # 累计
        for i in range(1, 7):
            yi = y_list[i]
            score_name = label_list[i]
            ma = ret_df.loc[pre_date][score_name]
            if ret_df.loc[pre_date]['close'] > ma:
                sum_ret = yi[-1] + ret
            else:
                sum_ret = yi[-1]
            yi.append(sum_ret)
        
        if ret_df.loc[pre_date]['ma5'] > ret_df.loc[pre_date]['ma60']:
            y_list[7].append(y_list[7][-1] + ret)
        else:
            y_list[7].append(y_list[7][-1])

        # 不择时
        y_list[0].append(y_list[0][-1] + ret)

        pre_date = date

    fig = plt.figure(figsize=(12, 8))
    ax = fig.add_subplot(1, 1, 1)
    ax.set_title("")

    for i in range(0, len(y_list)):
        yi = y_list[i]
        ax.plot(yi, color_list[i], label=label_list[i])

    x = np.arange(0, len(factor_df), 300)
    x_label = []
    for i in range(0, len(factor_df)):
        if i in x:
            date = factor_df.index[i]
            x_label.append(date)
    plt.xticks(x, x_label, rotation='vertical')

    plt.xticks(rotation=360)  # 旋转45度显示
    legend = ax.legend(loc='upper left', shadow=False)

    plt.show()
# ma均线择时收益率
show_ma_factor_return_rate(factor_df)

由上图可以看出,在自定义价值100指数上,20日均线择时效果最好,5日均线择时效果最差。只有20日均线择时跑赢了指数本身。

2. RSRS择时¶

# RSRS择时收益
def show_score_factor_return_rate(ori_factor_df):
    factor_df = ori_factor_df.dropna()
    color_list = ['black','#5698c6', '#ff9e4a', '#60b760', '#e05c5d', '#ae8ccd']

    label_list = ['不择时','score', 'revise_score', 'rightdev_score']

    # 这里需要用每天的因子数据分档,计算出5个折线
    y_list = [[], [], [], []]

    # 收益率折线图从0开始
    for i in range(0, len(label_list)):
        yi = y_list[i]
        yi.append(0)

    pre_date = None

    flag_list = [0, 0, 0, 0]
    for date in factor_df.index:
        if type(pre_date) == type(None):
            pre_date = date
            continue

        # pre_date为date的上一个调仓日,这里获取上一个调仓日的因子值
        pre_factor_data = factor_df.loc[pre_date]

        # 获取上一个调仓日到本调仓日的收益率
        ret = ret_df.loc[pre_date]['rt']

        # 累计
        for i in range(1, 4):
            yi = y_list[i]
            score_name = label_list[i]
            if pre_factor_data[score_name] > 0.7:
                flag_list[i] = 1
            elif pre_factor_data[score_name] < -0.7:
                flag_list[i] = 0

            # 累计收益率
            if flag_list[i] == 1:
                sum_ret = yi[len(yi) - 1] + ret
            else:
                sum_ret = yi[len(yi) - 1]

            yi.append(sum_ret)

        

        # 不择时
        y_list[0].append(y_list[0][-1] + ret)

        pre_date = date

    fig = plt.figure(figsize=(12, 8))
    ax = fig.add_subplot(1, 1, 1)
    ax.set_title("")

    for i in range(0, len(y_list)):
        yi = y_list[i]
        ax.plot(yi, color_list[i], label=label_list[i])

    x = np.arange(0, len(factor_df), 300)
    x_label = []
    for i in range(0, len(factor_df)):
        if i in x:
            date = factor_df.index[i]
            x_label.append(date)
    plt.xticks(x, x_label, rotation='vertical')

    plt.xticks(rotation=360)  # 旋转45度显示
    legend = ax.legend(loc='upper left', shadow=False)

    plt.show()
# 收益率
show_score_factor_return_rate(factor_df)

由上图看出,在自定义价值100指数上择时,RSRS标准分、修正标准分、右偏标准分择时效果分别由好到差,与在沪深300指数上表现出了完全相反的结果。但是三个指标都跑赢了指数本身。

3. MA20与RSRS标准分¶

# 20日均线与RSRS标准分
def show_ma_score_factor_return_rate(ori_factor_df):
    factor_df = ori_factor_df.dropna()
    color_list = ['black','#5698c6', '#e05c5d']

    label_list = ['不择时', 'score','ma20']

    # 这里需要用每天的因子数据分档,计算出5个折线
    y_list = []
    for i in range(0, len(label_list)):
        y_list.append([])

    # 收益率折线图从0开始
    for i in range(0, len(label_list)):
        yi = y_list[i]
        yi.append(0)

    pre_date = None

    flag_list = [0, 0, 0, 0]
    for date in factor_df.index:
        if type(pre_date) == type(None):
            pre_date = date
            continue

        # pre_date为date的上一个调仓日,这里获取上一个调仓日的因子值
        pre_factor_data = factor_df.loc[pre_date]

        # 获取上一个调仓日到本调仓日的收益率
        ret = ret_df.loc[pre_date]['rt']

        # 累计
        if pre_factor_data['score'] > 0.7:
            flag_list[1] = 1
        elif pre_factor_data['score'] < -0.7:
            flag_list[1] = 0

        # 累计收益率
        if flag_list[1] == 1:
            sum_ret = y_list[1][-1] + ret
        else:
            sum_ret = y_list[1][-1]

        y_list[1].append(sum_ret)

        ma = ret_df.loc[pre_date]['ma20']
        if ret_df.loc[pre_date]['close'] > ma:
            sum_ret = y_list[2][-1] + ret
        else:
            sum_ret = y_list[2][-1]
        y_list[2].append(sum_ret)



        # 不择时
        y_list[0].append(y_list[0][-1] + ret)

        pre_date = date

    fig = plt.figure(figsize=(12, 8))
    ax = fig.add_subplot(1, 1, 1)
    ax.set_title("")

    for i in range(0, len(y_list)):
        yi = y_list[i]
        ax.plot(yi, color_list[i], label=label_list[i])

    x = np.arange(0, len(factor_df), 300)
    x_label = []
    for i in range(0, len(factor_df)):
        if i in x:
            date = factor_df.index[i]
            x_label.append(date)
    plt.xticks(x, x_label, rotation='vertical')

    plt.xticks(rotation=360)  # 旋转45度显示
    legend = ax.legend(loc='upper left', shadow=False)

    plt.show()
show_ma_score_factor_return_rate(factor_df)

可以看出,rsrs标准分的择时效果胜过ma20择时。

另外我写回测使用多回测框架,发现在自定义价值100指数上,N=18 M=1100 阈值=0.7也是一个较好的参数,回撤较低,年化较高。还有比较好的几组参数是N=22 M=800 阈值=0.9;N=15 M=600 阈值=0.9;。

5 研究结论¶

在上文系列1,我们构造了一个自定义价值100指数;RSRS择时在自定义价值100指数上,也可以取得不错的择时效果。值得一提的是,N=18 M=1100 阈值=0.7在自定义价值100也是一个较好的参数。

有兴趣的朋友可以试试每次选市值最小的100个股票,构造下证100指数,看看效果。

 

全部回复

0/140

量化课程

    移动端课程