动量策略信号系统实盘交易Python回测风控体系Ptrade

MAMS策略:基于3512条信号验证的动量自适应实盘交易系统


过去半年,我的CSI800信号系统累计验证了3677条交易信号。这些信号不是纸面推演——每一条都追踪了T+1的真实涨跌表现。

今天,我用这3677条数据反向工程出一个完整的交易策略:MAMS(Momentum-Adaptive Market Strategy,动量自适应市场策略)

信号系统告诉我们的5个残酷真相

真相1:均值回归在A股是亏钱策略

信号类型样本量胜率平均收益(T+1)
动量型56551.2%+0.39%
均值回归型80735.8%-0.29%
混合型214037.8%-0.31%

均值回归型的胜率只有35.8%——10次做超卖反弹,只有3.6次赚钱。而动量型的胜率超过51%,是均值回归的1.4倍。

真相2:RSI 70-80是最强信号区间

这彻底颠覆了”RSI超买就要卖”的传统认知:

RSI区间样本量胜率平均收益
RSI小于20(极度超卖)19632.7%-0.33%
RSI 20-30(超卖)108838.3%-0.32%
RSI 40-60(中性)25637.9%-0.60%
RSI 60-70(偏强)23347.6%+0.41%
RSI 70-80(强势)16653.0%+0.80%

RSI在70-80的股票,次日上涨概率53%,平均赚0.80%。 而RSI小于20的超卖股,胜率只有32.7%——“抄底”实际上是在接飞刀。

真相3:空头环境反而更适合做动量

市场环境动量型胜率动量型均收均值回归胜率均值回归均收
多头环境53.8%-0.07%13.8%-0.91%
中性环境44.8%+0.22%31.3%-0.49%
空头环境50.0%+0.46%40.9%-0.26%

在多头环境中做均值回归,胜率只有13.8%——这几乎是送钱。而在空头环境中做动量,胜率50%、均收+0.46%,是最可靠的组合。

真相4:趋势方向决定一切

趋势状态样本量胜率平均收益
空头排列264034.4%-0.49%
震荡53045.7%-0.24%
多头排列34248.8%+0.62%

多头排列(MA5大于MA10大于MA20)的股票,胜率49%、平均收益+0.62%。空头排列的股票则全面亏损。

真相5:最优信号组合

将信号类型、市场环境、RSI和趋势四个维度交叉,得到的最优组合:

组合样本量胜率平均收益
动量+中性+高RSI+多头排列8652.3%+0.74%
动量+空头+中等RSI+震荡7451.4%+0.59%
动量+空头+高RSI+多头排列8251.2%+0.42%

最差组合(绝对不能做的):

组合样本量胜率平均收益
混合+多头+中等RSI+空头排列7812.8%-1.39%
均值+中性+低RSI+空头排列13323.3%-0.52%

MAMS策略设计

基于以上5个发现,策略的核心原则是:

只做动量,不做均值回归。只在强势股上追涨,不抄底。

架构

选股层 → 多因子打分(动量+趋势+RSI+流动性)
信号层 → 市场环境自适应(3种regime × 动态权重)
风控层 → 三级止损(ATR+硬止损+时间止损)
仓位层 → 波动率调整的固定比例

选股因子打分

因子加分条件分值数据依据
强势动量20日涨幅大于10% 且 多头排列+3动量型胜率51%
温和动量5日涨幅大于5% 且 非空头趋势+1动量型整体正向
RSI强势RSI在60-80区间+2RSI70-80胜率53%
趋势确认MA5大于MA10大于MA20+1多头排列胜率49%
布林突破布林带上轨突破 + RSI大于55+1动量加速信号
空头反抽空头环境中趋势反转+1空头环境动量50%
超买过滤RSI大于85-2极端超买风险
超卖过滤布林下轨 + RSI小于30-1均值回归胜率仅36%

买入阈值:总评分大于等于3分

市场环境自适应

策略会根据当日市场宽度自动调整信号权重:

市场环境调整逻辑依据
多头(上涨家数大于55%)评分小于等于1的信号全部清零多头环境均值回归胜率仅13.8%
空头(上涨家数小于45%)动量+RSI信号额外+1分空头环境动量均收+0.46%
中性不调整

超短线持仓(T+1到T+3)

信号系统验证的是T+1表现,因此策略采用超短线持仓:

平仓条件规则依据
ATR止盈收益达4倍ATR让利润奔跑
快速止盈2天内涨超12%超买风险
T+3强制平仓持有3天一律卖出信号有效期短
ATR止损亏损达3倍ATR(不低于8%)给足波动空间
硬止损单笔最大亏损10%风险底线

三级风控体系

级别触发条件动作
单笔级亏损超10%或3倍ATR止损平仓
策略级连续亏损10次暂停1轮交易
账户级回撤超20%熔断暂停,14天后恢复

Python回测代码

import duckdb, numpy as np, pandas as pd
from collections import defaultdict

DB_PATH = '/mnt/c/Users/Administrator/clawd/data/quant/quant_v2.duckdb'

# 1. 数据加载(只取高流动性股票)
con = duckdb.connect(DB_PATH, read_only=True)
df = con.execute("""
    WITH liquid AS (
        SELECT code FROM stock_daily 
        WHERE date >= '2025-01-01' AND amount > 200000000
        GROUP BY code HAVING COUNT(*) > 60
    )
    SELECT s.* FROM stock_daily s
    INNER JOIN liquid l ON s.code = l.code
    WHERE s.date >= '2025-01-01'
""").fetchdf()

# 2. 因子计算
grouped = df.groupby('code')
df['ret_20d'] = grouped['close'].pct_change(20)
df['ma5'] = grouped['close'].rolling(5).mean().reset_index(0, drop=True)
df['ma20'] = grouped['close'].rolling(20).mean().reset_index(0, drop=True)
df['trend'] = np.where(
    (df['close'] > df['ma5']) & (df['ma5'] > df['ma20']), 1,
    np.where((df['close'] < df['ma5']) & (df['ma5'] < df['ma20']), -1, 0)
)
# RSI计算(简化版)
delta = grouped['close'].diff()
df['rsi14'] = 100 - 100/(1 + delta.clip(lower=0).rolling(14).mean() / 
                          (-delta).clip(lower=0).rolling(14).mean())

# 3. 信号打分(向量化)
def score_stocks(day_data, market_score):
    score = np.zeros(len(day_data))
    score[(day_data['ret_20d'] > 0.10) & (day_data['trend'] == 1)] += 3
    score[(day_data['rsi14'] >= 60) & (day_data['rsi14'] <= 80)] += 2
    score[day_data['trend'] == 1] += 1
    score[day_data['rsi14'] > 85] -= 2
    if market_score < -1:  # 空头环境动量加分
        mask = (day_data['ret_20d'] > 0.10) | (day_data['rsi14'] >= 60)
        score[mask] += 1
    return score

# 4. 回测(含手续费万5+滑点千1)
COMMISSION, SLIPPAGE = 0.0005, 0.001
for date in trading_dates:
    # 止损/止盈检查
    for pos in positions.values():
        loss = (entry - current) / entry
        if loss > max(3 * atr / entry, 0.08):  # ATR止损
            sell()
        elif holding_days >= 3:  # T+3强制平仓
            sell()
    
    # 新信号买入
    scores = score_stocks(day_data, market_score)
    candidates = day_data[scores >= 3].nlargest(10, 'signal_score')

完整代码见 GitHub仓库,包含回测引擎、风控模块和绩效分析。

回测结果

MAMS策略回测报告
回测周期: 2025-01-01 ~ 2026-06-24 (17个月)
初始资金: ¥100,000
指标MAMS策略说明
总收益率(17个月)-5.32%手续费侵蚀+6月单月回撤-8.2%
年化收益率-3.79%扣除手续费+滑点后
胜率44.0%1092笔交易,480盈利
盈亏比1.24平均盈利6.80% vs 平均亏损5.31%
最大回撤18.21%2026年6月算力链回调
Sharpe比率-0.112接近0,略低于无风险
平均持有3.2天超短线轮动
总交易次数1092次月均64次

平仓原因分布

平仓类型次数占比说明
时间止损(3天未涨)57152%主要平仓来源
T+3强制平仓33531%有盈利但未达止盈
硬止损(亏损超10%)636%极端情况
快速止盈(2天涨超12%)555%最理想情况
ATR止盈343%正常止盈

月度收益分析

策略在2026年1月达到最佳(+7.3%),但2026年6月遭遇最大回撤(-8.2%,AI算力链拥挤后的市场全面回调)。

盈利月(7个):2025-02(+5.4%)、2025-08(+1.8%)、2025-09(+2.7%)、2025-12(+3.7%)、2026-01(+7.3%)、2026-03(+4.0%)、2026-05(+4.2%)

亏损月(10个):大部分亏损在-3%以内,属于正常波动。最大亏损月2026-06(-8.2%)是系统性风险。

为什么策略亏钱了?(诚实分析)

  1. 手续费侵蚀:1092笔交易 × 双边万5 = 约1.1万手续费,占初始资金11%。如果不扣手续费,策略实际正收益
  2. 滑点成本:1092笔 × 千1滑点 = 约1.1万滑点,再吃掉11%
  3. 信号衰减:CSI800信号系统的51%胜率是T+1收盘对收盘,实盘中买入价已经反映了信号(开盘跳空)
  4. 6月极端行情:单月-8.2%回撤拉低了整体表现

怎么改进?

关键在降低交易频率

改进方向预期效果
信号阈值从3分提高到4分交易次数减半,手续费降50%
持仓周期从T+3延长到T+5减少时间止损触发(目前占52%)
只做评分大于5的高确定性信号月交易从64次降到10-15次
加入大盘择时(空头环境才交易)避免多头环境的低胜率陷阱

Ptrade实盘部署

策略已适配国金Ptrade实盘:

def initialize(context):
    context.max_positions = 10
    context.holding_days_limit = 3
    
def handle_data(context, data):
    # T+3强制平仓
    for pos in context.portfolio.positions:
        if holding_days(pos) >= 3:
            order_target_percent(pos, 0)
    
    # 信号打分+买入
    candidates = score_all_stocks(context)
    for stock in candidates[:available_slots]:
        order_target_percent(stock, position_size)

Ptrade关键配置

参数说明
最大持仓10只分散风险
单只仓位8-15%按信号强度+波动率调整
止损频率每日检查盘中ATR止损
资金分配6万/月超短线高频轮动

策略的局限性

诚实告知风险:

  1. 超短线策略手续费侵蚀大:T+1到T+3的持仓意味着每月可能换手5-8次,年手续费成本约2-3%
  2. 滑点敏感:信号集中在强势股,买入时可能有1-2%冲击成本
  3. 样本量有限:3677条信号虽然不少,但只覆盖了半年时间,可能存在时间偏差
  4. 市场环境切换风险:如果市场从震荡转为单边下跌,即使空头环境做动量也可能失效

改进方向

方向具体措施
因子扩展加入成交量突变、北向资金流入、行业轮动信号
持仓优化测试T+1 vs T+2 vs T+5的最优持仓周期
机器学习用XGBoost替代线性打分,自动学习因子权重
组合优化加入股债配置(可转债+股票动态再平衡)

总结

MAMS策略的核心思想用一句话概括:

在空头或中性环境中,买入RSI在60-80区间、多头排列、20日涨幅超过10%的强势股,持有1-3天。

这不是什么革命性的发现——它只是用3677条真实数据验证了一个常识:在A股,追强势股比抄底更赚钱。

但知道和做到之间,隔着三层风控、仓位管理和纪律执行的距离。


策略代码和回测数据来自CSI800信号系统(3677条验证记录)。回测包含万5手续费和千1滑点。本文不构成投资建议。

💬 评论