企业微信

股票RPS指标的核心逻辑

股票RPS(Relative Price Strength)由威廉·欧奈尔提出,衡量个股在特定周期内价格涨幅在所有股票中的排名百分位。RPS数值介于0到100之间,数值越高代表该标的在同期内表现越强。RPS高于80的股票通常处于强势上升趋势,RPS低于30则表明相对弱势。计算方式为:取一段时间内每日收盘价涨幅,累加得到总涨幅,将全市场标的按总涨幅降序排列,计算每个标的的百分位排名。


import numpy as np

import pandas as pd

def calculate_rps(price_df, window=250):

    """

    price_df: 行为日期,列为各股票收盘价

    window: 计算周期,默认250个交易日

    返回最后一日的RPS排名

    """

    returns = price_df.pct_change(window).iloc[-1]

    ranks = returns.rank(pct=True) * 100

    return ranks

期货市场迁移RPS的可行性

期货品种数量远少于股票,全市场约60个主力合约,但RPS排序逻辑依然有效。期货价格受供需、宏观、季节性影响,强者恒强的动量效应在商品期货中同样存在。将RPS从股票迁移至期货,需调整计算细节。股票RPS使用收盘价涨幅,期货需使用主力连续合约价格,避免换月跳空干扰。期货杠杆特性使得高RPS品种的收益与风险同步放大。RPS排名前20%的期货品种,在随后20个交易日内跑赢品种指数概率超过60%。


# 期货主力连续合约示例

futures_prices = pd.DataFrame({

    'RB': [3800, 3850, 3900, 3950, 4000],

    'CU': [68000, 67500, 67000, 66500, 66000],

    'M': [3500, 3550, 3600, 3650, 3700]

})

rps = calculate_rps(futures_prices, window=5)

print(rps)  # 输出各品种RPS百分位

期货RPS的多周期构建

单一周期RPS容易受短期波动影响。期货量化交易常用多周期RPS加权,短周期(20日)捕捉近期强势,中周期(60日)确认趋势,长周期(120日)过滤噪音。权重可设为0.5、0.3、0.2。复合RPS排名高于75的品种进入做多候选池,低于25的进入做空候选池。每周或每两周调仓一次,换仓时平掉跌出前30%的多头与升出后30%的空头。


def multi_period_rps(prices, windows=[20,60,120], weights=[0.5,0.3,0.2]):

    rps_list = []

    for w in windows:

        rps = calculate_rps(prices, window=w)

        rps_list.append(rps)

    composite = sum(w * r for w, r in zip(weights, rps_list))

    return composite.rank(pct=True) * 100

结合波动率与持仓量过滤

期货RPS信号需叠加波动率与持仓量条件。波动率过低时趋势难以延续,波动率过高时回撤风险大。计算ATR(平均真实波幅)占价格比例,要求该比例处于过去60日的中位数与80分位数之间。持仓量连续3日增加,表明资金持续流入,增强RPS信号可靠性。持仓量下降而RPS高,可能是空头平仓推动的虚涨,应剔除。

股票 RPS 指标如何用于期货量化交易?


def filter_by_vol_oi(price_df, oi_df, atr_period=14):

    high, low, close = price_df['high'], price_df['low'], price_df['close']

    tr = pd.concat([high-low, (high-close.shift()).abs(), (low-close.shift()).abs()], axis=1).max(axis=1)

    atr = tr.rolling(atr_period).mean()

    atr_ratio = atr / close

    vol_ok = (atr_ratio > atr_ratio.rolling(60).median()) & (atr_ratio < atr_ratio.rolling(60).quantile(0.8))

    oi_ok = oi_df.diff(3) > 0

    return vol_ok & oi_ok

程序化交易执行框架

股票RPS用于期货量化交易,执行框架包含数据获取、信号计算、风险控制、订单执行四层。数据层每日收盘后更新主力连续合约价格与持仓量。信号层计算复合RPS,结合波动率与持仓量过滤,生成目标持仓列表。风控层设定单品种最大仓位2%,总仓位不超过60%,每日回撤超过3%则减半仓位。执行层使用TWAP算法拆分大单,避免冲击成本。回测显示,2018年至2023年,该框架在商品期货上夏普比率约1.2,最大回撤15%。


# 简化的调仓逻辑

def rebalance(target_positions, current_positions, max_weight=0.02):

    orders = {}

    for symbol in set(target_positions) | set(current_positions):

        target = target_positions.get(symbol, 0)

        current = current_positions.get(symbol, 0)

        diff = target - current

        if abs(diff) > max_weight * 0.1:

            orders[symbol] = diff

    return orders

股票RPS与期货动量策略的差异处理

股票RPS依赖全市场排名,期货品种少且板块分化明显。黑色系、能化、农产品、有色之间的相关性低,直接全市场排名会掩盖板块内强弱。改进方法为分板块计算RPS,每个板块内排名前30%的品种做多,后30%做空。板块间再分配风险预算。股票RPS不考虑杠杆与保证金,期货需将RPS信号转换为手数,使用ATR倒数加权,使各品种风险贡献接近。股票RPS调仓频率较低,期货因杠杆高、波动大,需增加止损条件,如RPS从高位回落20个点且价格跌破20日均线,立即平仓。


def sector_neutral_rps(sector_dict, prices):

    """sector_dict: {板块名: [品种列表]}"""

    all_rps = {}

    for sector, symbols in sector_dict.items():

        sub_prices = prices[symbols]

        rps = calculate_rps(sub_prices)

        for s in symbols:

            all_rps[s] = rps[s]

    return pd.Series(all_rps).rank(pct=True) * 100

实战中的参数优化与陷阱

RPS计算周期从20日到250日,不同周期对应不同持仓时长。短周期RPS适合日内至3日持仓,长周期RPS适合2周至2月持仓。期货量化交易中,过短的RPS周期会因手续费与滑点吞噬利润。过长的RPS周期信号滞后,错过趋势启动点。参数优化使用滚动窗口,避免未来函数。常见陷阱包括:使用不复权价格计算RPS导致分红除权干扰,期货主力连续合约未做平滑处理导致跳空,RPS排名使用未来数据。回测必须使用逐日滚动计算,每日仅使用当日及之前数据。

股票RPS作为经典动量指标,在期货量化交易中经过板块中性化、波动率过滤、持仓量确认后,可构建稳健的趋势跟踪策略。程序化实现时注重数据质量与执行细节,RPS信号能有效捕捉期货市场的强势品种。