Warning: file_exists(): open_basedir restriction in effect. File(/www/wwwroot/com.xiximiao.oa/com.cmstop/public/www/wp-content/db.php) is not within the allowed path(s): (/www/wwwroot/com.xiximiao.oa/com.cmstop/public/www/:/tmp/:/proc/:/var/log/nginx/:/www/wwwroot/com.xiximiao.oa/com.cmstop/public/:/www/wwwroot/com.xiximiao.oa/com.cmstop/vendor/:/www/wwwroot/com.xiximiao.oa/com.cmstop/ppk/) in /www/wwwroot/com.xiximiao.oa/com.cmstop/public/www/wp-includes/load.php on line 707
2067 成交量加权RSRS择时策略(右偏标准分)-RSRS择时改进【成交量加权-钝化-右偏】.py » 轻知量化 QMT、PTrade、聚宽策略分享交流平台

2067 成交量加权RSRS择时策略(右偏标准分)-RSRS择时改进【成交量加权-钝化-右偏】.py

策略名称:成交量加权RSRS择时策略(右偏标准分)

策略说明:

本策略基于成交量加权的RSRS(阻力支撑相对强度)指标进行择时交易。RSRS指标通过回归分析计算市场的高点和低点之间的关系,结合成交量加权和右偏标准分的处理方式,生成交易信号。策略的核心思想是,当RSRS指标超过设定的买入阈值时,认为市场处于强势状态,选择开仓;当RSRS指标低于设定的卖出阈值时,认为市场处于弱势状态,选择平仓。

策略逻辑:

1. **数据获取与处理**:
- 获取标的指数(沪深300,代码:000300.XSHG)的历史高、低点和成交量数据。
- 使用加权最小二乘法(WLS)对高点和低点进行回归分析,计算斜率(beta)和决定系数(R²)。
- 计算标准化后的RSRS指标,并结合成交量加权和右偏标准分的处理方式生成最终的RSRS信号。

2. **信号生成**:
- 计算过去N天(默认18天)的RSRS斜率(beta)和决定系数(R²)。
- 对RSRS斜率进行标准化处理,得到Z-score。
- 结合成交量加权和右偏标准分的处理方式,生成最终的RSRS信号:`vol_rsrs_right = zscore * beta * r2`。
- 当RSRS信号大于买入阈值(0.85)时,认为市场处于强势状态,选择开仓;当RSRS信号小于卖出阈值(-0.85)时,认为市场处于弱势状态,选择平仓。

3. **交易执行**:
- 在每日的`market_open`函数中,根据生成的RSRS信号决定是否开仓或平仓。
- 开仓时,买入标的指数(沪深300);平仓时,卖出所有持仓。

策略参数:

- **标的指数**:沪深300(000300.XSHG)
- **N(计算RSRS的窗口期)**:18天
- **M(标准化窗口期)**:200天
- **买入阈值(buy)**:0.85
- **卖出阈值(sell)**:-0.85
- **运行时间(run_time)**:14:00

策略特点:

- **成交量加权**:通过成交量加权的方式,增强了RSRS指标对市场活跃度的敏感性。
- **右偏标准分**:通过右偏标准分的处理方式,增强了RSRS指标对市场强势状态的识别能力。
- **动态调整**:根据市场情况动态调整仓位,避免在市场弱势时持有过多仓位。

适用场景:

- **趋势明显的市场**:当市场处于明显的上升或下降趋势时,策略表现较好。
- **成交量活跃的市场**:在成交量活跃的市场环境下,策略的信号更为有效。

风险提示:

- **滞后性**:RSRS指标基于历史数据生成,可能存在一定的滞后性。
- **市场波动**:在市场波动较大时,策略可能会频繁开仓平仓,增加交易成本。
- **参数敏感性**:策略的表现对参数(如N、M、买入阈值、卖出阈值)较为敏感,需根据市场环境进行优化。

总结:

本策略通过成交量加权的RSRS指标进行择时交易,旨在捕捉市场的趋势变化,适合在趋势明显且成交量活跃的市场环境下使用。策略的核心在于通过成交量加权和右偏标准分的处理方式,动态调整仓位,以期在市场上升时获得收益,在市场下跌时减少损失。

策略python源码

# 标题:RSRS择时改进-【成交量加权-钝化-右偏】
# 作者:uuyue
# 回测金额要选择 100万

# 成交量加权的4种RSRS #
# 成交量加权-右偏标准分        vol_rsrs_right      = zscore*beta*r2   
# 成交量加权-钝化-右偏标准分   vol_rsrs_right_dun  = zscore*beta*(r2**(2*stdpercent)) 
# 成交量加权-无偏标准分        vol_rsrs            = zscore*r2 
# 成交量加权-钝化-无偏标准分   vol_rsrs_dun        = zscore*(r2**(2*stdpercent))  

import statsmodels.api as sm
import scipy.stats as stats

def initialize(context):
    g.security = '000300.XSHG'

    # 成交量加权-右偏标准分
    g.N = 18
    g.M = 200
    g.buy = 0.85
    g.sell = -g.buy
    g.run_time = '14:00'  #14:00
    
    '''
    #成交量加权-钝化-右偏标准分
    g.N = 18
    g.M = 200
    g.buy = 0.75
    g.sell = -g.buy
    g.run_time = '14:00'
    
    #成交量加权-无偏标准分   
    g.N = 17
    g.M = 1300
    g.buy = 0.9
    g.sell = -g.buy
    g.run_time = '9:30'  
    
    #成交量加权-钝化-无偏标准分    
    g.N = 16
    g.M = 1100
    g.buy = 0.7
    g.sell = -g.buy
    g.run_time = '9:30' 
    '''
    # 中间变量
    g.beta_weight = []
    g.r2_weight = []
    g.volatility = []
    g.pos = False
    g.days = 0
    g.rsrs = 0
  
    set_option("avoid_future_data", True)
    set_option('order_volume_ratio', 0.002)  # 成交量不得超过标的日成交量的千分之2
    set_option('use_real_price', True)    # 开启动态复权模式(真实价格)
    set_benchmark('000300.XSHG')    # 设定上证指数作为基准
    log.set_level('order', 'error')    # 过滤掉order系列API产生的比error级别低的log
    
    # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='fund')
    set_slippage(PriceRelatedSlippage(0.00246),type='fund')
   
    run_daily(before_market_open, time = 'before_open', reference_security='000300.XSHG') 
    run_daily(market_open, time = g.run_time, reference_security='000300.XSHG')
    run_daily(after_market_close, time = 'after_close', reference_security='000300.XSHG')

    # 计算2005年1月5日至回测开始日期的RSRS斜率指标    #context.previous_date + timedelta(days = -1)
    prices = get_price(g.security, '2005-05-01', context.previous_date, '1d', ['high', 'low', 'volume'])
    highs = prices.high
    lows = prices.low
    volumes = prices.volume
    weight_list = []
    
    for i in range(0, len(highs)-g.N+1):  #range(a,b)=[a,b)
        data_high = highs.iloc[i :i+g.N]  #dataframe 不包括[a:b]中的b,相当于[a:b)
        data_low  = lows.iloc[i :i+g.N]
        data_volume = volumes.iloc[i :i+g.N]
        X = sm.add_constant(data_low)  #为模型增加常数项,即回归线在y轴上的截距(括号里面写上自变量)
        # 处理报错:exog contains inf or nans
        #X[np.isnan(X)] = 0  #把X中的空值令为0
        #X[np.isinf(X)] = 0  #把无穷大的数据令为0
        
        # 成交量加权的权重列表
        for j in range(0, len(data_volume)):  #len(data_volume)=g.N=18,  j=0到17
            weight = data_volume[j]/data_volume.sum()
            weight_list.append(weight)

        model = sm.WLS(data_high, X, weight_list)  # 加权最小二乘法
        g.beta_weight.append(model.fit().params.low)
        g.r2_weight.append(model.fit().rsquared)
        weight_list = []
    
    #log.info('prices的长度=%s, g.beta_weight的长度=%s, g.r2_weight的长度=%s' % (len(prices),len(g.beta_weight),len(g.r2_weight)))
        
    #计算2005-01-01至开盘前一天的指数日收益率的波动率
    close = get_price(g.security,'2005-05-01', context.previous_date, '1d', 'close')['close']
    daily_return =  (close-close.shift(1))/close.shift(1)
    daily_return=list(daily_return.dropna())
    for i in range(len(daily_return))[g.N:]:
        std = np.std(daily_return[i-g.N:i])
        g.volatility.append(std)
    

def before_market_open(context):
    beta = 0
    r2 = 0
    weights = []
    
    if g.days == 0:
        g.days = 1
    elif g.days == 1:
        
        # 计算各种RSRS
        prices = attribute_history(g.security, g.N, '1d', ['high','low','volume'])
        highs = prices['high']
        lows = prices['low']
        volumes = prices['volume']
        X = sm.add_constant(lows)      # sm计算OLS时,左侧要补一列常数
        
        # 成交量加权的权重列表
        for i in range(0,len(prices)):
            weight = volumes[i]/volumes.sum()
            weights.append(weight)
        
        # 加权最小二乘法  #sm.WLS(y, X, weights)
        model = sm.WLS(highs, X, weights)
        beta = model.fit().params.low
        g.beta_weight.append(beta)
        r2 = model.fit().rsquared
        g.r2_weight.append(r2)        
        
        # 标准化/归一化
        section = g.beta_weight[-g.M:]
        mu = np.mean(section)
        sigma = np.std(section)
        zscore = (section[-1]-mu)/sigma
        
        # 计算N日收益率的标准差、M日收益率标准差的分位数(钝化RSRS所需)     
        # 用过去g.N天的数据,计算波动率,并获取它在过去g.M所处的百分位
        close = attribute_history(g.security, g.N+1, '1d', ['close'])['close']
        daily_return =  (close-close.shift(1))/close.shift(1)
        daily_return = list(daily_return.dropna())
        std = np.std(daily_return)                                           #计算N日收益率的标准差
        g.volatility.append(std)
        stdpercent = stats.percentileofscore(g.volatility[-g.M:], std)/100   #计算M日收益率标准差的分位数
        
        vol_rsrs_right = zscore*beta*r2                        #成交量加权-右偏标准分
        vol_rsrs = zscore*r2                                   #成交量加权-无偏标准分
        vol_rsrs_right_dun = zscore*beta*(r2**(2*stdpercent))  #钝化-成交量加权-右偏标准分
        vol_rsrs_dun = zscore*(r2**(2*stdpercent))             #钝化-成交量加权-无偏标准分
        
        log.info('zscore= %s, beta= %s, r2= %s, std= %s, stdpercent= %s'% (round(zscore,3),round(beta,3),round(r2,3),round(std,3),round(stdpercent,3)))
        log.info('成交量加权-右偏rsrs     = %s,成交量加权-无偏rsrs     = %s' % (round(vol_rsrs_right,3), round(vol_rsrs,3)))
        log.info('钝化-成交量加权-右偏rsrs= %s,钝化-成交量加权-无偏rsrs= %s' % (round(vol_rsrs_right_dun,3), round(vol_rsrs_dun,3)))
       
        # 成交量加权-右偏标准分        vol_rsrs_right      = zscore*beta*r2   
        # 成交量加权-钝化-右偏标准分   vol_rsrs_right_dun  = zscore*beta*(r2**(2*stdpercent)) 
        # 成交量加权-无偏标准分        vol_rsrs            = zscore*r2 
        # 成交量加权-钝化-无偏标准分   vol_rsrs_dun        = zscore*(r2**(2*stdpercent))  
        g.rsrs = vol_rsrs_right
        log.info('g.rsrs=%s' % round(g.rsrs,3))


def market_open(context):
    if g.rsrs > g.buy and g.pos==False:
        log.info('buy')
        order_value(g.security, context.portfolio.available_cash)
        g.pos = True
    elif g.rsrs < g.sell and g.pos==True:
        log.info('sell')
        order_target(g.security, 0)
        g.pos = False
 
def after_market_close(context):
    trades = get_trades()
    for _trade in trades.values():
        log.info('成交记录:'+str(_trade))
    log.info('##############################################################')
2025-02-20
⚠️
本站资源大多来自网络,仅供网友学习交流,未经作者或上传书面授权,请勿作他用。
站长 vx: xiangyin615 或者 留言反馈 ,我们将尽快处理。
Notice: When you of the legal rights be violate, please stir to vx: xiangyin615
个人中心
购物车
优惠劵
搜索