AI助手多样化研究--(股票)最基础的择时与相对强度因子回测
  了不起的阿斗 15天前 231 1

AI助手多样化研究–(股票)最基础的择时与相对强度因子回测

情绪冰点下的相对强度选股策略:构建思路与因子设计

——了不起的阿斗

本文记录一套基于市场情绪极端悲观状态与个股相对强度的选股策略构建过程,使用平台AI助手实现整体构建。
之前尝试将传统主观交易的部分条件进行因子化和回测中留了一些钩子,在主观交易中还有一套市场情绪判断体系用来择时,这次使用最基础的择时因子加入策略之中。
https://www.pandaai.online/community/article/581


一、在恐慌中寻找韧性

1.1 出发点

大多数动量策略的逻辑是顺势而为——在市场情绪高涨时追入表现最强的个股。这套策略反其道而行之:专门在市场情绪跌入极度悲观的时刻,寻找相对强度最高的个股买入

核心假设是:

当全市场处于集体恐慌或持续阴跌状态时,绝大多数股票跟随市场下行。在这种环境下,若某些个股仍能维持相对强势——价格动量没有崩塌、成交额也没有明显萎缩——背后必然存在资金的主动支撑行为。这种"逆势不跌"或"跌幅显著小于市场"的特征,预示着一旦市场情绪从冰点回暖,这类股票会率先补涨乃至领涨。

1.2 与趋势策略的本质区别

维度 趋势跟随策略 本策略
情绪信号作用 过滤器(情绪好才进场) 触发器(情绪冰点才进场)
选股时机 市场上涨、情绪高涨时 市场恐慌、情绪极端时
买入逻辑 追强势(高买更高卖) 在废墟里找幸存者
拥挤度 高(多数人在追涨) 低(多数人在回避市场)
核心驱动 动量持续 困境反转 + 相对强度

二、第一层:市场情绪因子——确定买入时机

2.1 指标选择:涨跌家数差(Market Breadth)

择时信号来源于市场广度指标,即全市场当日上涨个股数量与下跌个股数量之差:

CleanShot 20260302 at 03.46.522x.jpg

其中:

  • Advancet\text{Advance}_t:第 tt 日全市场收盘价较前日上涨的个股数量
  • Declinet\text{Decline}_t:第 tt 日全市场收盘价较前日下跌的个股数量

这个指标的优势在于它反映的是市场内部结构,而非价格指数表面的涨跌。指数可能因少数权重股拉动而"虚涨",但涨跌家数差能真实揭示多空力量的全貌:

  • Breadtht0\text{Breadth}_t \gg 0:多数个股在上涨,市场情绪健康、扩散性强
  • Breadtht0\text{Breadth}_t \approx 0:多空均衡,方向不明
  • Breadtht0\text{Breadth}_t \ll 0:多数个股在下跌,市场处于恐慌或持续阴跌状态

2.2 平滑处理:滑动均值过滤噪声

单日的涨跌家数差波动较大,受到市场临时性因素(如消息面冲击、当日情绪过激)干扰明显。因此对原始序列取 NN 日滑动均值,形成平滑后的情绪指数:

CleanShot 20260302 at 03.47.052x.jpg

例如可以 N=5N = 5,平衡响应速度与平滑程度。

2.3 冰点判定:触发买入扫描

当平滑情绪指数持续低于阈值 θ\theta,且维持时间超过若干个交易日,判定市场进入"情绪冰点"区间,此时启动选股程序:

CleanShot 20260302 at 03.48.362x.jpg

阈值 θ\theta 的取法可基于历史分位数(如取历史序列的 10% 分位点),确保只在真正极端悲观的状态下触发,而非日常的小幅调整。

关键理解:这里情绪因子是反向触发器,而非正向确认信号。情绪越极端,抛压越接近枯竭,边际卖盘越少,反转的赔率结构越好。


三、第二层:相对强度因子——确定买入标的

3.1 设计动机:价格动量不足以区分主动买盘与滞后下跌

在情绪冰点的环境里,抗跌的原因可能有两种:

  1. 流动性差导致的滞后:股票成交极度萎缩,价格因为没有卖盘而"被动"维持,属于假强
  2. 主动买盘支撑:成交量有热度,资金在主动介入,属于真强

单纯用价格涨跌幅无法区分这两种情况。为此,在价格动量的基础上,叠加成交额的对数项作为资金热度修正,构造量价共振的相对强度因子。

3.2 因子公式

NN 日窗口为例,原始公式来源于通达信指标语言:

ROC_N_LN = (C / REF(C, N) * 100 - 100) + 10 * LN(MA(AMO, N) / 100000000)

转化为数学表达式:

CleanShot 20260302 at 03.48.482x.jpg

其中:

  • CtC_t:当日收盘价
  • CtNC_{t-N}NN 日前收盘价
  • AMON=1Ni=0N1AMOti\overline{\text{AMO}}_N = \frac{1}{N}\sum_{i=0}^{N-1} \text{AMO}_{t-i}:近 NN 日平均成交额(单位:元)
  • 10810^8:以1亿元为基准单位进行归一化
  • 系数 1010:对成交额项的权重缩放,使两项数量级大致匹配,后续可以进一步优化

3.3 成交额取对数的两层含义

① 压缩量级差异

不同个股的成交额差距可达数百倍甚至更多(小盘股日均几千万,龙头股可达百亿级)。直接使用原始成交额会让大市值股票天然占据优势,对数变换将这种量级差异压缩到合理范围,使因子在截面上具有可比性:

CleanShot 20260302 at 03.49.032x.jpg

② 边际效用递减

资金的边际参与意义是递减的:成交额从1亿增加到2亿,意味着买盘翻倍,信号意义显著;但从100亿增至101亿几乎不传递额外信息。对数函数的凹性天然体现了这一经济直觉。

3.4 多周期合成:3日、5日、7日

选取三个时间窗口,分别计算 F3F_3F5F_5F7F_7,进行截面标准化后等权合成(也可以主观增加权重):

CleanShot 20260302 at 03.49.162x.jpg

其中 F~N\tilde{F}_N 为各因子的截面 Z-score 标准化:

CleanShot 20260302 at 03.49.472x.jpg

多周期合成的意义在于多频率共识投票

  • F3F_3 捕捉短线爆发力,对近期强势反应灵敏
  • F5F_5 为中间过渡,兼顾响应速度与稳定性
  • F7F_7 平滑噪声,反映更持续的趋势性强势

只有在多个时间维度上综合得分靠前的个股,才真正符合"量价共振、持续强势"的特征,单一周期的偶发性拉升不容易获得高分。


四、整体框架:两层串联结构

市场情绪因子 (Breadth均值)
        │
        ▼
  情绪冰点判定?
  Breadth_ma < θ
        │
       YES ──────────────────────────────────────────┐
        │                                            │
        ▼                                            ▼
  启动截面选股                               否 → 空仓等待
        │
        ▼
  计算 F_composite (3/5/7日量价动量)
        │
        ▼
  截面排名,选取得分最高的前 N% 个股
        │
        ▼
  等权建仓,等待情绪从冰点回暖
        │
        ▼
  情绪修复 / 价格目标触发 → 离场

两层因子在信息来源上是相互独立的:

  • 情绪因子来自全市场整体行为(宏观层面)
  • 相对强度因子来自个股截面比较(微观层面)

两者低相关性叠加,在理论上比叠加高度相关的因子具有更强的稳健性。


五、策略的结构性优势

5.1 交易拥挤度低

情绪冰点时,绝大多数参与者选择回避市场,主动做多的资金极少。在这种环境下建仓,对手盘以被动抛售者为主,而非同向竞争的追涨者,买入成本结构天然更优。

5.2 赔率不对称

极端悲观情绪本身具有均值回归特性——持续低迷的涨跌家数差不会无限延续,市场广度最终会从极端值回归。这意味着入场时间点在统计上接近阶段性低点,向上的空间大于向下的风险,形成正偏的赔率结构。

5.3 选股的内在逻辑自洽

在全市场下跌背景下仍能维持量价共振的个股,其背后的逻辑只有一种合理解释:有真实的主力资金在该价格区域认为有价值,并持续介入。这种行为本身就是一种信息,比价格形态或财务指标更直接地反映了"钱在哪里"。

后续扩展:

方向 思路
情绪因子增强 引入 ADL 累积线(涨跌家数差的累加序列),在冰点判定中加入趋势斜率维度
相对强度细化 将综合因子拆分为"价格相对强度"与"资金相对强度"两个子维度,分别排名后再合成
IC 加权替代等权 根据历史各窗口因子的 IC 值动态调整 3/5/7 日的合成权重
离场机制 情绪从冰点回升超过一定幅度,或相对强度因子排名显著下滑时,触发减仓离场
与基本面结合 在量价因子筛选的基础上,叠加基本面质量过滤(如 ROE、现金流),剔除基本面恶化的"假强势"

六、记录ai助手实现构建的过程

创建空白工作流,搭建基础框架

CleanShot 20260302 at 01.26.022x.jpg
使用AI助手搭建基础框架

生成结果:
CleanShot 20260302 at 01.29.182x.jpg

然后,发现因子代码实现的其实和原有想法有区别,全局AI助手搭建框架差不多,但细节代码需要微调,使用代码内的ai助手重新调整
CleanShot 20260302 at 01.31.352x.jpg
CleanShot 20260302 at 01.32.462x.jpg
再看下回测部分的代码逻辑,直接问AI助手
CleanShot 20260302 at 01.36.182x.jpg
CleanShot 20260302 at 01.50.362x.jpg
策略逻辑看起来问题不大,先运行试试
CleanShot 20260302 at 01.38.162x.jpg
运气不错,一把跑通

如果遇到负载超负荷,那可能是因为回测的日期范围长导致内存不够……说实话这个内存经常不够对我来说,其实也不是多复杂的因子
有时候报错10001或者10005也有可能是内存不过或者超范围导致访问数据空之类的问题,先跑短期3个月6个月的。如果卡在某个环节超过3分钟基本上是数据爆了。

稍微修改了一下部分参数后再次运行,先看下因子分析结果
CleanShot 20260302 at 02.07.462x.jpg

看下因子分析结果里面AI助手的分析评价
CleanShot 20260302 at 02.08.182x.jpg
因子测试结果简要分析
核心问题:因子方向与构建逻辑存在矛盾
最值得注意的一个信号是 IC_mean 为负、Rank_IC 为负,而平台设置的因子方向是"正向(1)"。这意味着因子值越低的股票,后续表现反而越好——从分组收益也可以印证:组1(低因子值组)年化80%,组5(高因子值组)年化只有40%,排序完全反了。
这在逻辑上其实不奇怪。ROC_LN 因子值高,说明该股近期已经涨幅大、成交热度高——在情绪冰点的择时前提下,这类股票反而是"已经被拉高、追涨风险大"的标的;而因子值低(轻微下跌但成交尚有热度)的股票,才更符合"逆势抗跌、等待反转"的初衷。
建议:将因子方向改为负向(0),与策略逻辑对齐。

IC 稳定性问题:时变性强
IC 衰减图显示,IC 在各期正负交替、无明显持续方向,P(IC>0.02) 与 P(IC<-0.02) 各50%,IC_IR 仅 -0.30。这说明因子效果对市场环境高度敏感——在某些阶段非常有效,在另一些阶段完全失效甚至反向。
原因很可能是:当前回测期(2025年2月至8月)只有约半年,且没有加入情绪冰点的择时过滤,因子在非冰点期间被"稀释"了。单独测因子和真正策略场景是两回事,因子分析模块是全时段截面测试,而该因子本身设计是为冰点环境下的选股服务的,在普通市场环境里预测力自然不稳定。

分组结构的亮点
尽管如此,分组收益仍然呈现出单调性:组1 > 组2 > 组3 > 组4 > 组5(年化80% → 40%),说明因子的截面排序能力本身是存在的,只是方向设反了。修正方向后,多空组合的表现有望显著改观。

在普通市场环境里,近期涨幅大、成交热的股票往往已经透支,后续容易回调,这是正常的短期反转效应。
但你的策略从不在普通环境里用这个因子。你只在情绪冰点这个极端条件下启动选股。此时市场大面积下跌,高 ROC_LN 的股票不是"追高",而是"全市皆跌、它偏偏扛住"——完全是另一种信息含义。

看下策略的回测结果
CleanShot 20260302 at 02.30.422x.jpg
看下AI智能分析:
CleanShot 20260302 at 02.30.232x.jpg
亮点:夏普2.50 + 最大回撤-6.84% 这个组合是真正的硬指标,说明策略的"收益效率"非常高,不是靠扛回撤硬撑出来的收益。Beta仅0.07,意味着超额几乎全来自选股alpha,和市场涨跌基本脱钩,这正是"情绪冰点"设计的核心价值体现。
需要注意的问题
从净值曲线可以看到几个值得警惕的结构:
① 收益高度集中在5月初那一波。2月到4月基本是横盘甚至略亏,5月上旬出现一次大幅拉升,之后进入漫长的震荡巩固,8月末再起一波。这说明策略的收益来源非常集中——很可能只有2-3次"冰点触发"贡献了绝大多数收益,其余时间空仓或微亏。
② 4月初有一次明显回撤至-7%附近,结合你设置的止损-7%,这次很可能是止损触发出场,说明止损线设置是合理的,确实在保护回撤。
但这个策略很多参数可以继续修改调整……
CleanShot 20260302 at 03.45.402x.jpg

今晚先写到这……
其实很多因子参数都是可以继续用机器学习或者优化方法去回测出最优解的。


本文为策略研究备忘,记录初始构建思路,待后续回测验证与迭代完善。

最后一次编辑于 15天前 1

XPQuant

Mark,学习了,感谢~

2026-03-04 14:37:43      回复

推荐阅读
  18028306419   3天前   20   0   0 Python
  15012901756   2天前   15   0   0 Python