6. 指数增强选股策略

本策略以0.8为初始权重跟踪指数标的沪深300中权重大于0.35%的成份股. 个股所占的百分比为(0.8*成份股权重)*100%.然后根据个股是否: 1.连续上涨5天 2.连续下跌5天 来判定个股是否为强势股/弱势股,并对其把权重由0.8调至1.0或0.6

策略运行频率:每日运行 策略运行时间:每日收盘前

回测时间为:2021-01-01到2022-12-31

6.1. 1. 策略代码

创建自定义交易策略:

import qteasy as qt
import numpy as np

class IndexEnhancement(qt.GeneralStg):
    
    def __init__(self, pars: tuple = (0.35, 0.8, 5)):
        super().__init__(
                pars=pars,
                par_count=2,
                par_types=['float', 'float', 'int'],  # 参数1:沪深300指数权重阈值,低于它的股票不被选中,参数2: 初始权重,参数3: 连续涨跌天数,作为强弱势判断阈值
                par_range=[(0.01, 0.99), (0.51, 0.99), (2, 20)],
                name='IndexEnhancement',
                description='跟踪HS300指数选股,并根据连续上涨/下跌趋势判断强弱势以增强权重',
                strategy_run_timing='close',  # 在周期结束(收盘)时运行
                strategy_run_freq='d',  # 每天执行一次选股
                strategy_data_types='wt-000300.SH, close',  # 利用HS300权重设定选股权重, 根据收盘价判断强弱势
                data_freq='d',  # 数据频率(包括股票数据和参考数据)
                window_length=20,
                use_latest_data_cycle=True,
                reference_data_types='',  # 不需要使用参考数据
        )
    
    def realize(self, h, r=None, t=None, pars=None):

        weight_threshold, init_weight, price_days = self.pars
        # 读取投资组合的权重wt和最近price_days天的收盘价
        wt = h[:, -1, 0]  # 当前所有股票的权重值
        pre_close = h[:, -price_days - 1:-1, 1]
        close = h[:, -price_days:, 1]  # 当前所有股票的最新连续收盘价

        # 计算连续price_days天的收益
        stock_returns = pre_close - close  # 连续p天的收益
        
        # 设置初始选股权重为0.8
        weights = init_weight * np.ones_like(wt)
        
        # 剔除掉权重小于weight_threshold的股票
        weights[wt < weight_threshold] = 0
        
        # 找出强势股,将其权重设为1, 找出弱势股,将其权重设置为 init_weight - (1 - init_weight)
        up_trends = np.all(stock_returns > 0, axis=1)
        weights[up_trends] = 1.0
        down_trend_weight = init_weight - (1 - init_weight)
        down_trends = np.all(stock_returns < 0, axis=1)
        weights[down_trends] = down_trend_weight
        
        # 实际选股权重为weights * HS300权重
        weights *= wt

        return weights

6.2. 2. 策略回测

回测参数:

  • 回测时间:2021-01-01到2022-12-31

  • 资产类型:股票

  • 资产池:沪深300成份股

  • 初始资金:100万

  • 买入批量:100股

  • 卖出批量:1股

shares = qt.filter_stock_codes(index='000300.SH', date='20210101')
print(len(shares), shares[:10])
alpha = IndexEnhancement()
op = qt.Operator(alpha, signal_type='PT')
op.op_type = 'stepwise'
op.set_blender('1.0*s0', "close")
op.run(mode=1,
       invest_start='20210101',
       invest_end='20221231',
       invest_cash_amounts=[1000000],
       asset_type='E',
       asset_pool=shares,
       trade_batch_size=100,
       sell_batch_size=1,
       trade_log=True,
      )

print()

6.3. 回测结果

419 ['000001.SZ', '000002.SZ', '000063.SZ', '000066.SZ', '000069.SZ', '000100.SZ', '000157.SZ', '000166.SZ', '000333.SZ', '000338.SZ']
No match found! To get better result, you can
- pass "match_full_name=True" to match full names of stocks and funds

     ====================================
     |                                  |
     |       BACK TESTING RESULT        |
     |                                  |
     ====================================

qteasy running mode: 1 - History back testing
time consumption for operate signal creation: 0.0 ms
time consumption for operation back looping:  13 sec 461.8 ms

investment starts on      2021-01-04 00:00:00
ends on                   2022-12-30 00:00:00
Total looped periods:     2.0 years.

-------------operation summary:------------
Only non-empty shares are displayed, call 
"loop_result["oper_count"]" for complete operation summary

          Sell Cnt Buy Cnt Total Long pct Short pct Empty pct
000001.SZ    0         3      3   100.0%     0.0%      0.0%  
000002.SZ    0         2      2   100.0%     0.0%      0.0%  
000063.SZ    0         0      0   100.0%     0.0%      0.0%  
000100.SZ    1         5      6    66.9%     0.0%     33.1%  
000333.SZ    0         1      1   100.0%     0.0%      0.0%  
000338.SZ    1         1      2    62.3%     0.0%     37.7%  
000651.SZ    0         1      1   100.0%     0.0%      0.0%  
000725.SZ    0        95     95   100.0%     0.0%      0.0%  
000858.SZ    0         0      0   100.0%     0.0%      0.0%  
002027.SZ    1         3      4    62.3%     0.0%     37.7%  
...            ...     ...   ...      ...       ...       ...
601229.SH    1         3      4    50.2%     0.0%     49.8%  
601288.SH    0        76     76   100.0%     0.0%      0.0%  
601318.SH    0         3      3   100.0%     0.0%      0.0%  
601328.SH    0        30     30   100.0%     0.0%      0.0%  
601398.SH    0       106    106   100.0%     0.0%      0.0%  
601601.SH    1         0      1    78.8%     0.0%     21.2%  
601668.SH    0        15     15   100.0%     0.0%      0.0%  
601688.SH    0         1      1   100.0%     0.0%      0.0%  
601899.SH    0         4      4   100.0%     0.0%      0.0%  
603259.SH    0         0      0   100.0%     0.0%      0.0%   

Total operation fee:     ¥    2,388.29
total investment amount: ¥1,000,000.00
final value:              ¥  703,480.41
Total return:                   -29.65% 
Avg Yearly return:              -16.23%
Skewness:                         -0.02
Kurtosis:                          1.63
Benchmark return:               -26.50% 
Benchmark Yearly return:        -14.36%

------strategy loop_results indicators------ 
alpha:                           -0.026
Beta:                             0.941
Sharp ratio:                     -1.237
Info ratio:                      -0.139
250 day volatility:               0.168
Max drawdown:                    43.41% 
    peak / valley:        2021-02-19 / 2022-10-31
    recovered on:         Not recovered!

===========END OF REPORT=============

png