【2021股票量化精华帖_优化第3篇】基于选股策略结果的资金曲线择时

发布于: 雪球转发:0回复:0喜欢:0

【2021股票量化精华帖_优化第3篇】基于选股策略结果的资金曲线择时(以伽利略为例)

一、基本思路

在运行选股策略时把equity保存下来,其中有一列‘equity_curve‘也就是资金曲线一列,我们把他当作收盘价,然后套用择时策略框架进行择时。

二、具体构建

直接套用择时策略框架肯定是不行的,里面还有些细节需要处理。

1、文件读入

这个就不多说,路径、文件名、列名等等都需要修改,在进行股票择时的时候还需要进行复权,这里也省了。

2、周期转换

在进行股票择时的时候我们通常使用的都是日线数据,也就是说在交易日的每一天都有可能放出买卖信号,而我们目前的操作模式是仅在周末进行一次选股和判断,在持仓周期内无法获取实时的资金曲线。

解决办法就是要把择时策略的日频信号转换成周频信号。例如本周五收盘后择时策略仍处于持仓状态,那么我们下个周期继续执行该选股策略,反之则下个周期该选股策略空仓也就是不再买入。

这样每周进行一次择时来决定下周是否买入。具体实现方法就是在得到pos信息后进行一次周期转换。

下面是我的信号周期转换函数,由于自己做了写修改,可能跟邢大的不太一样。

# 将日线仓位信号转换为其他周期仓位信号

def transfer_pos_to_period_data(df, period_type='m'):

# 将交易日期设置为index

df['交易日期'] = pd.to_datetime(df['交易日期'])

df['周期第一个交易日'] = df['交易日期']

df['周期pos'] = df['pos']

df.set_index('交易日期', inplace=True)

period_df = df.resample(rule=period_type).agg(

{

'周期第一个交易日': 'first',

'周期pos': 'first',

}

)

df.drop(['周期第一个交易日', '周期pos'], axis=1, inplace=True)

period_df.dropna(subset=['周期pos'], inplace=True)

period_df.set_index('周期第一个交易日', inplace=True)

df['周期pos'] = period_df['周期pos']

# 重新设定index

df.reset_index(inplace=True)

# 将周期pos施加到每一天,替换pos

df['周期pos'] = df['周期pos'].fillna(method='ffill')

df['pos'] = df['周期pos']

del df['周期pos']

return df

3、资金曲线

在一般的择时策略中,我们是通过找出买卖点然后扣除手续费和印花税的方式来计算交易费用。但是我们的选股策略资金曲线在生成之前已经扣除了周一开盘买入、周五尾盘卖出的费用,而且还计算好了每天的资金曲线涨跌幅。所以在这里进行新的资金曲线计算反而简单了。选股资金曲线csv文件中的内容是这样的:

交易日期

指数涨跌幅

持有股票代码

涨跌幅

equity_curve

equity_curve_base

2010/12/27

-0.01896

sh600074 sh600165 sh600235

-0.02646

0.973538

0.981038

2010/12/28

-0.0174

sh600074 sh600165 sh600235

-0.00013

0.973414

0.963963

2010/12/29

0.006784

sh600074 sh600165 sh600235

0.035092

1.007573

0.970503

2010/12/30

0.002922

sh600074 sh600165 sh600235

-0.01068

0.996817

0.973338

2010/12/31

0.017579

sh600074 sh600165 sh600235

0.03371

1.030419

0.990449

2011/1/4

0.015872

sh600232 sh600566 sh600856

0.007376

1.038019

1.006169

2011/1/5

-0.00493

sh600232 sh600566 sh600856

0.010564

1.048985

1.00121

2011/1/6

-0.00507

sh600232 sh600566 sh600856

0.020946

1.070956

0.996134

2011/1/7

0.00517

sh600232 sh600566 sh600856

0.001045

1.072075

1.001284

核心思想就是,对于持仓日采用选股策略产生的涨跌幅,对于空仓日直接把涨跌幅赋值0,在此基础上计算择时后的资金曲线。代码如下:

vdef equity_curve_with_chg(df, c_rate=1.2/10000, t_rate=1.0/1000, slippage=0.01):

df['equity_change'] = df['涨跌幅']

df.loc[df['pos'] == 0, 'equity_change'] = 0

df['equity_change'].fillna(value=0, inplace=True)

df['equity_curve'] = (1 + df['equity_change']).cumprod()

df['equity_curve_base'] = df['close']

return df

三、回测结果

细节修改完后套用择时指标进行回测,以mtm指标为例,代码如下:

def MTM_signal(df, para):

n, p = para[0], para[1]

df['mtm'] = (df['close'] / df['close'].shift(n)) * 100

df.loc[df['mtm'] > p, 'signal'] = 1.0

df.loc[df['mtm'] < p, 'signal'] = 0.0

return df

选择参数【5,95】,回测时间2011年初至2020年7月3日,每周选3只股票。回测结果如下:

交易次数:84,胜率(%):44.047619047619044,买入胜率(%)50.0
买入次数:42,买入胜数:21
年华收益(%): 74.15
最大回撤(%): -38.99
最大回撤开始时间 2011-07-20
最大回撤结束时间 2012-12-13

下图中蓝色是择时后的资金曲线,黄色是原始的伽利略资金曲线。

虽然总体收益提升不大,但是最大回撤降低了不少。

四、小结

对于这种周频的择时,我尝试过很多基础的指标,结果都不是很理想,虽然能很大程度上降低但也会大幅降低收益。

还有一种优化思路就是,按照10%的比例选股生成资金曲线,对这个资金曲线进行择时。之前邢大也说过,每周选3只股票有很大的偶然性,按照10%的比例选股资金曲线可能更能代表因子的波动规律。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

以上非完整内容