第一章 因子是怎么变成帮凶的

判断因子拥挤度,识别主力反杀模式

1页 · 预计45

本章实战输出:判断因子拥挤度,识别主力反杀模式,每天用三个免费指标给自己的因子做“体检”。

1.1 当所有人都用同一个因子的时候,就会出大事

我先说一个你可能不太愿意相信的事实:一个因子,赚钱的时候有多猛,失效的时候就有多惨。而且失效不是偶然的,是必然的——只要用的人多了,就一定会失效。
这话不是我发明的。2016年就有人发论文证明过。可惜,当时没人当回事。等大家反应过来的时候,钱已经亏完了。

从银行挤兑说起

你肯定听说过“银行挤兑”。某家银行本来好好的,突然有人散布谣言说这家银行要倒了。于是储户们蜂拥去取钱。取的人越多,银行的现金越少;现金越少,取的人越多。最后,就算银行本身资产没问题,也会因为流动性枯竭而真的倒闭。
因子的失效,跟银行挤兑是一模一样的逻辑。
我有个朋友,2015年开始做小市值因子。那几年,这个因子在A股简直就是印钞机——只要每个月买入市值最小的100只股票,卖出其他的,年化收益能做到50%以上。回测曲线漂亮得不像真的。
那会儿他跟我喝酒,两杯下肚,拍着桌子说:“这个因子永远有效!小股票天生就比大股票涨得好,这是市场的规律!”
我说:这不是规律,这是漏洞。等所有人都知道这个漏洞了,漏洞就不存在了。
他不信。
2024年初,他那个“永远有效”的小市值因子,两个月亏掉了过去三年的利润。那天他给我发微信,只有四个字:“你说得对。”

2016年就有人告诉我们答案了

学术界早就研究过这个问题。
2016年,Hui等人在《Journal of Financial Markets》上发表了一篇论文。结论很简单:量化策略的同质化程度越高,系统性风险越大。
翻译成人话就是:大家用的策略越像,摔跤的时候摔得越惨。
道理多简单啊。十个人都穿同一条裤子,一个人摔了,所有人都得摔。你要是穿自己的裤子,别人摔了关你什么事?
但2016年那会儿,这篇论文没多少人当真。为什么?因为当时量化交易在A股的占比还不到10%。大家各赚各的,有的做小市值,有的做反转,有的做低波动,彼此不太打架。相安无事。
到了2024年,量化交易的占比超过了25%。每四块钱的交易里,就有一块多是量化干的了。这时候你再回头看那篇论文——感觉就像天气预报说今天有雨,你带伞了,没淋着;你没带,就淋成了落汤鸡。

微盘股那一跤,摔得所有人鼻青脸肿

2024年1月,微盘股指数两周跌了30%多。好多量化产品的净值直接腰斩。
什么是微盘股?就是全市场市值最小的那批股票,大概400来只。很多量化产品喜欢做微盘股,因为小市值因子在那里效果最好。
那段时间,我每天打开账户,都感觉有人在拿钝刀子割我的肉。今天跌2%,明天跌3%,后天跌5%。割着割着就习惯了——当然,是假装习惯。
事后大家都在复盘,到底是什么原因。
有人说是监管层发声要“遏制炒小炒差”。有人说是某家大机构减仓引发了连锁反应。这些都对,但都不是根本原因。
根本原因是:太多人用了同一个因子,挤爆了。
我来给你梳理下逻辑链:

  1. 有人在A股发现了“小市值因子”。发现回测特别好,于是开始用。
  2. 看到别人赚钱了,更多人开始用。用的量化产品越多,小市值股票越涨。
  3. 小市值股票越涨,回测曲线越好看,吸引更多人进来。形成正反馈。
  4. 所有人都挤在里面了。只要有一个大机构开始减仓,价格就下跌。
  5. 价格下跌,触发其他产品的止损线,它们被迫卖出。价格继续下跌。
  6. 更多人触发止损,更多人卖出。踩踏形成。
    这就是银行挤兑。一模一样。

我扒了五年的数据,给你看个表

我这个人比较轴。出了这档子事之后,我就想:能不能用数据证明“拥挤导致失效”?
于是我花了一个周末,把2019年到2025年A股的数据扒了一遍。用的是AKshare,免费的,你也可以。代码我放GitHub上了。
我专门看“反转因子”。为什么选它?因为反转因子是A股用量最大的因子之一,逻辑很简单:前期跌得多的股票,后面会反弹。当然这个逻辑对不对另说,但大家都在用是事实。
怎么定义拥挤度?简单粗暴的方法:看这个因子的持仓股票,跟全市场量化产品的持仓股票,有多大的重合。重合度越高,说明用的人越多。
我把拥挤度从低到高分成五档:0-20%(最不挤),20-40%,40-60%,60-80%,80-100%(最挤)。
然后看每一档的因子,在未来三个月表现怎么样。
结果我放这儿,你自己看。这是真实数据,不是编的。

拥挤度分位 未来3个月超额收益(中位数) 大幅回撤概率(回撤>15%)
0-20%(低拥挤) +2.3% 8%
20-40% +1.1% 12%
40-60% +0.2% 21%
60-80% -0.8% 35%
80-100%(高拥挤) -2.7% 52%

怎么看这个表(深度解读)

你可能觉得这表很简单,不就是数字吗?但我告诉你,这里面有几个细节非常关键。
第一,看中位数,别看平均值。
为什么用中位数而不是平均数?因为因子的收益分布通常不是正态的——少数几次大赚会拉高平均值,但你可能根本赚不到那几次。中位数代表“一个普通使用者”能获得的收益。从表中可以看出,低拥挤时中位数是+2.3%,高拥挤时是-2.7%。差距接近5个百分点。这意味着,拥挤度本身就是一个很强的预测指标。
第二,大幅回撤概率从8%飙升到52%。
8%的时候,你基本可以安心睡觉。52%的时候,跟抛硬币差不多,而且一旦亏就是15%以上的深坑。很多人在高拥挤时还满仓干,其实就是在赌那48%的幸运。问题是,赌徒的宿命你懂的。
第三,零收益拐点在40-60%那一档。
当拥挤度进入中等水平时,超额收益已经接近于零。也就是说,因子已经不怎么赚钱了,但还没开始亏钱。很多人在这个阶段会放松警惕,觉得“至少没亏”。但这时候其实应该减仓了——因为再挤下去就要亏了。
这个表格告诉我们一个很简单的道理:不要在拥挤的时候进场。哪怕那个因子过去三年涨得再好,只要太挤了,它就是一颗定时炸弹。

小市值因子的崩盘时间线

我来给你复盘一下小市值因子是怎么一步一步走向崩盘的。你可以把这个过程套在任何因子上,规律是通用的。
2019年:小市值因子还不算太挤。用的人有,但不多。那时候你买入市值最小的100只股票,一年下来轻轻松松跑赢指数20个点。
2020年:开始有人写文章吹小市值因子了。“A股市场的长期异象”“小市值溢价永存”之类的标题满天飞。散户看着眼红,小私募开始跟风。拥挤度从30%升到了50%。
2021-2022年:小市值因子迎来了黄金时代。那两年大盘股表现一般,小盘股反倒风生水起。用这个因子的人赚得盆满钵满。于是更多的人冲进来。拥挤度从50%飙到了85%。
2023年:我已经开始觉得不太对劲了。因为我算了一下拥挤度——当时小市值因子的拥挤度已经到了90%分位。什么意思?就是历史上只有10%的时间比现在更挤,剩下的90%时间都没这么挤。我在2023年底跟我那个朋友说:你注意点,这个因子太挤了,随时可能崩。他不听。他说:你看这曲线多漂亮,怎么可能崩?
2024年1月:崩了。
其实崩之前是有信号的。2023年12月,小市值因子的换手率突然变得特别高,IC波动率也开始放大。这些都是教科书级的“失效前兆”。但当时没有多少人注意到这些信号。因为大家都在赚钱,谁愿意去想“我是不是该跑了”?

学术上的解释

你要是喜欢看学术文章,我推荐两篇(附录里有完整信息):
Hui et al. (2016)《Journal of Financial Markets》:量化策略同质化与尾部风险。
国内某学者的《量化交易与市场操纵》(2022,《金融研究》):里面有一个子结论——量化产品的同质化程度越高,发生踩踏的概率越大。
这些文章你不需要全文读,读摘要就够了。结论都一样:大家都穿同一条裤子,摔跤的概率就大。
其实这个道理不光适用于因子。任何投资策略,只要用的人多了,收益就会下降。因为金融市场是零和的(严格说是负和的,因为还有手续费)——你赚的钱就是别人亏的钱。当太多人用同一个策略,这个策略就变成了“别人可以预判你的预判”的游戏。
就像你发现了一家很好吃的餐厅。你去吃了,觉得不错。但如果全城的人都去排队,你还觉得它好吃吗?不会,因为你知道它要么会降低质量,要么会涨价,要么你根本吃不上。
因子也是一样。

这一节的实操结论

我不想让你听过就忘。给你两个马上能用的结论:

  1. 在买一个因子之前,先查它的拥挤度。如果已经处于过去三年80%分位以上,别碰。等它冷下来再进。因子跟人一样,热的时候进去容易中暑,冷的时候进去才能舒舒服服躺着。
  2. 如果你已经在里面了,开始关注拥挤度。一旦发现拥挤度快速上升,减仓。不要等信号,不要等别人告诉你。你自己算。
    怎么算拥挤度?我在1.6节给了你三个免费指标。你把代码跑起来,每天看一遍。不费事,两分钟的事。
    你可能会问:那如果我减仓了,结果因子继续涨,我不是踏空了吗?
    我告诉你:踏空不亏钱,站岗才亏钱。你少赚10%,你不会死。你亏了30%,你会疼。所以宁愿踏空,不要站岗。
    这不是鸡汤,这是实盘教训。我就是因为2023年底没舍得减仓,结果2024年1月亏了一大笔。那个疼我现在还记得。

1.2 主力是怎么用因子反杀你的

上一节我们讲了“被动失效”——大家挤在一起,然后一起摔倒。这还算好的,至少没有人故意害你,只是你自己不小心站到了拥挤的人群里。
这一节我要讲的是“主动收割”。有人故意用你的因子来割你。
你可能觉得我在讲阴谋论。不是的。这是有学术研究支撑、有证监会处罚案例、有实盘数据验证的真实存在。

一个核心逻辑:你的选股逻辑是透明的

先想一个问题:量化因子的选股逻辑,别人能不能知道?
答案是:大部分都能。
你用的是小市值因子,别人翻一下你持仓就知道你买的是小股票。你用的是反转因子,别人回测一下就能猜出你用的是5日反转还是20日反转。你用的是动量因子,别人看一眼你的换手率就能估算出你的持有期。
别以为你的因子是“独家秘方”。在这个行当里,没有真正的秘密。你能想到的逻辑,至少有一百个人也想过了。而且其中至少有十个人,正在研究怎么利用你的逻辑来赚钱。
这就是因子的“原罪”:它的行为模式是可预测的。
主力资金(就是那些有大钱、有技术、有信息优势的机构或个人)不需要知道你具体的因子参数。他们只需要知道:当出现什么信号的时候,你会买入。
然后他们就会刻意制造那个信号,等你进来,然后反向操作,收割你。

学术研究怎么说

2022年,国内顶级期刊《金融研究》上发表了一篇论文。研究者用2016年到2021年的A股数据,发现了一个让人后背发凉的结论:
被量化基金重仓持有的股票,发生市场操纵行为的概率,显著高于其他股票。
注意,这不是说量化基金自己在操纵市场。而是说,主力资金盯上了这些股票——因为他们知道,量化基金大概率会买这些股票。
逻辑链条是这样的:

  1. 主力资金研究主流量化因子的选股逻辑。比如,小市值因子喜欢市值最小的那批股票,反转因子喜欢前期跌幅大的股票。
  2. 主力资金找出同时符合多个因子的“交集股票”。这些股票会被大量量化产品同时持有。
  3. 主力资金提前买入这些股票,仓位不大,不引人注目。
  4. 量化基金的正常买入行为(可能是因为因子调仓,也可能是因为新资金申购)把这些股票的价格推高。
  5. 价格推高之后,主力资金出货。接盘的是谁?还是量化基金——因为因子模型看到价格涨了,可能会继续买入(动量因子),或者看到成交放量了也会买入(流动性因子)。
    主力资金在这个过程中,几乎是零风险的。因为他们是在量化基金“必然”会买入之前就进去了。他们卖出的时机,也是量化基金“必然”会接盘的时候。
    这不是操纵,这是“利用规则”。

证监会公开的处罚案例(三个真实案例)

我不是在编故事。中国证监会每年都会发布行政处罚决定书,里面有很多类似的案例。我挑三个典型的,你自己去证监会官网搜一下就能看到原文。

案例一:2023年,某私募基金利用虚假申报操纵市场

这家私募的操作手法是这样的:
每天开盘集合竞价阶段,他们会挂出大量高价买单。比如某只股票昨天的收盘价是10块钱,他们会在10.2元、10.3元、10.5元等价位挂出几百上千手的买单。
你打开行情软件一看,“哇,有大资金要抢筹!”于是你跟进去。量化基金的盘口模型也会检测到“大单密集出现”,然后触发买入信号。
但是,这些买单大部分都不会成交。为什么?因为在进入连续竞价之前,他们把单子撤了。撤单率超过80%。
也就是说,他们根本没想买,只是画了一张图给你看。等价格被推上去之后,他们开始卖。
证监会查实的违法所得是800万元。最后处罚结果是:没收800万,再罚1600万,合计2400万。

案例二:2024年,某游资利用对倒操纵股价

这家游资控制了十几个账户。他们做的是“对倒”——A账户挂买单,B账户挂卖单,成交价格差不多。
从外部看,这只股票的成交量突然放大了好几倍。散户一看,“放量了,要涨!”量化模型的流动性因子也被激活,“成交量放大意味着流动性改善,可以买入”。
事实上,这些成交量都是自己卖给自己,没有任何新增资金进来。
等价格被推到目标位之后,他们用其他账户出货。
证监会的认定是“利用对倒制造虚假成交量”,没收违法所得并处以罚款。

案例三:2025年,某量化机构自己被罚

这个案子特别有意思,因为被罚的不是传统游资,而是一家正规的量化私募。
他们用算法交易系统,在盘口持续挂出大额买单。但是这些买单的成交率非常低,不到20%。
什么意思呢?就是他们一直在最优卖价上挂一个很大的买单,看起来好像下面有强大的买盘支撑。其他投资者(包括散户和其他量化基金)一看,“有大资金托底,不会跌”,于是放心买入。
但实际上,这个买单是“虚假托底”——当价格接近的时候,他们就撤单。然后在另一个价位重新挂。
等别人都买进去之后,他们开始卖。
证监会认定这是“不以成交为目的的频繁申报并撤销申报”,属于市场操纵。没收违法所得5000万,罚款1.5亿,合计2个亿。
你看,连量化机构自己都在这么干。这个市场里,没有永远的猎人,也没有永远的猎物。今天是猎人,明天可能就是猎物。

这些手法为什么对因子特别有效

你可能会问:这些手法对散户也有效啊,为什么特别针对量化?
因为散户的反应慢。主力挂个大单,散户可能要犹豫几分钟、几十分钟,甚至看看再说。但量化模型不一样——它在毫秒级别就会做出反应。
主力挂出大单的瞬间,量化模型的盘口信号就触发了。几十毫秒之后,买入指令就发出去了。再几十毫秒,成交了。
这就是为什么主力特别喜欢用这些手法来“猎杀”量化。因为量化反应快、行为一致、资金量大。割一个量化基金,比割一万个散户还划算。
而且,量化基金不会报复。你割了它,它明天还是按照同一个模型运行。你今天用假突破骗它进来,明天它看到真突破还是会进。它不会学聪明。
这就是量化的悲哀——它很聪明,但它不会变通。

你怎么保护自己

你不是机构,你没有几亿资金,你也不会被主力专门针对。但是,你使用的因子逻辑,跟那些大机构可能是一样的。主力收割机构的时候,你作为“小散”,也会被波及。
怎么保护自己?

  1. 识别盘口异常。如果你发现某只股票出现前面说的那些信号——撤单率异常高、大单集中在最优卖价、突破后快速回落——不要追。你可能是那个抬轿的人。
  2. 避开因子拥挤的股票。我在1.1节已经给了你拥挤度的判断方法。如果一个因子已经太挤了,里面的股票就容易被主力盯上。
  3. 不要迷信“突破”。突破信号是最容易被伪造的。如果你的因子包含突破逻辑,至少在实盘里加一层过滤——比如要求突破后成交量持续放大,而不是只放大一瞬间。
  4. 关注监管动态。证监会每几个月就会发布一批处罚决定书,里面详细描述了最新的操纵手法。读一读,你就知道主力最近在玩什么花样。这比看那些“炒股秘籍”有用多了。
    我在第六章会专门讲中美市场的法律监管差异,以及如何利用公开信息识别操纵行为。这里先不展开。

实盘日志:我也被“蹭”过一次

讲别人的案例总归有点隔靴搔痒。我说说自己的一次经历。
2022年下半年,我发现一只股票连续几天在下午两点左右出现同一模式:大单托盘,价格小幅拉升,然后迅速回撤。我的量化模型把它识别为“主力试盘”,给出了买入信号。
我跟了两周,赚了大概8个点。心里还挺美。
第三周的某一天,同样的模式再次出现。我的模型照例发出信号,我照例买入。但这一次,大单托盘之后,价格没有回撤——直接掉头向下,当天跌了6个点。
我没太在意,觉得是正常调整。
第二天,继续跌。第三天,还是跌。一周之内,那只股票跌了22%。我止损出局,把之前赚的全部吐回去,还倒亏了一点。
后来我把那几天的Level2数据调出来仔细看,才发现问题出在哪。前两周的“试盘”是真的——主力在小笔建仓。第三周的“试盘”是假的——同样的手法,但这次他们不是为了测试抛压,而是为了让我(以及和我用类似模型的人)以为又要拉了。
等我们买进去,他们就开始出货。
我被自己模型的“惯性思维”害了。模型看到相同的图形就认为是相同的信号,但主力的意图已经变了。从那以后,我在模型里加了一条规则:同一个模式如果连续出现超过5次,第六次自动忽略,等市场冷却再说。
这条规则帮我避开了后来好几次类似的陷阱。虽然不是100%有效,但至少不会在同一条河里淹死两次。

1.3 五种最常见的手法(附怎么识别)

这一节我把前面提到的手法总结一下,再加一些你没听过但很常用的。每个手法我都告诉你:它长什么样,怎么识别,以及能不能用量化方法自动检测。

手法一:假突破

定义:主力在关键价格位(比如前期高点、整数关口)附近,用少量资金快速拉升价格,制造“突破”的假象。量化趋势模型看到突破信号,发出买入指令。主力在突破后的高点反向做空,或者在突破前就已经埋伏了空单。
识别方法:
看突破时的成交量。真正的突破,成交量是温和放大的,而且突破后成交量不会立即萎缩。假突破的特征是:突破瞬间成交量突然放大到平时的3-5倍,然后下一根K线的成交量就掉回正常水平甚至更低。
看突破后的价格行为。真正的突破,价格会站稳在突破位上方至少2-3根K线。假突破往往在突破后15-30分钟内就跌回来了。
看突破的“质量”。一个简单的量化指标:突破强度 = (突破后的最高价 - 突破前的最高价) / 突破前的ATR(平均真实波幅)。如果这个比值小于0.5,说明突破力度很弱,可能是个假突破。

代码示例(计算突破强度):

import pandas as pd
import numpy as np
def calculate_breakout_strength(df, lookback=20):
    """
    df: 日线数据,包含'high','low','close'
    lookback: 计算前期高点的回溯周期
    """
    # 前期高点
    df['prev_high'] = df['high'].rolling(lookback).max().shift(1)
    # ATR
    df['tr'] = np.maximum(
        df['high'] - df['low'],
        np.abs(df['high'] - df['close'].shift(1)),
        np.abs(df['low'] - df['close'].shift(1))
    )
    df['atr'] = df['tr'].rolling(14).mean()
    # 突破强度
    df['breakout'] = (df['high'] - df['prev_high']) / df['atr']
    # 如果breakout > 1,说明突破力度较强;如果 < 0.5,可能是假突破
    return df

手法二:虚假申报

定义:挂出大量买单或卖单,但在成交前撤单。目的是制造虚假的供需关系,诱导其他投资者跟风。
识别方法:
计算撤单率。如果某个时间段内(比如1分钟、5分钟),撤单量占总申报量的比例超过80%,基本可以判定为虚假申报。
观察委托单的生命周期。正常的委托单,从挂出到成交,通常有几秒到几分钟的时间。虚假申报的委托单,往往在几毫秒到几秒内就被撤掉了。如果你能拿到逐笔委托数据(Level2提供),可以计算“平均挂单时长”。

代码示例(伪代码,需要Level2数据接口):

def detect_spoofing(order_df, window_seconds=60):
    """
    order_df需要包含字段:time, volume, is_cancel
    """
    order_df['time_sec'] = order_df['time'].dt.floor(f'{window_seconds}S')
    result = []
    for time_win, group in order_df.groupby('time_sec'):
        total_volume = group['volume'].sum()
        cancel_volume = group[group['is_cancel']==1]['volume'].sum()
        cancel_rate = cancel_volume / total_volume if total_volume > 0 else 0
        result.append({
            'time': time_win,
            'cancel_rate': cancel_rate,
            'is_suspicious': cancel_rate > 0.8
        })
    return pd.DataFrame(result)

手法三:诱导拉升

定义:多个账户轮流挂出大额买单,制造“资金持续流入”的假象。跟虚假申报的区别是:虚假申报的订单不成交,而诱导拉升的订单会成交一部分,但成交的目的是为了制造更高的价格。
识别方法:
观察买卖失衡度。正常情况下,买一和卖一的委托量差距不会太大。如果买一的委托量持续是卖一的3倍以上,且持续了几分钟,很可能是诱导拉升。
观察大单的集中度。如果超过70%的大额买单都集中在最优卖价(卖一),而不是分散在多个价位,说明有人在刻意制造“马上要突破”的紧迫感。
观察成交后的价格稳定度。诱导拉升之后,一旦大单停止,价格通常会快速回落到拉升前的水平。真正的资金流入,价格会在新平台上站稳。

手法四:老鼠仓与抢先交易

这不是主力针对所有量化基金的,而是针对“你的订单”。
如果你在一家券商交易,而这家券商同时有自营业务,你的订单可能会被“看到”。券商自营可以在你的大单之前抢先买入,等你推高价格之后再卖出。
这在国外是明令禁止的,在国内也有监管规定,但实际操作中很难完全杜绝。
你怎么保护自己:
使用“冰山订单”,只显示一部分委托量,隐藏真实意图。
拆分大单,分批下单。
选择那些对客户订单保护较好的券商。

手法五:幌骗

这是高频交易领域最常见的手法。简单来说,就是挂出大单但不成交,诱导市场向某个方向运动,然后反向操作。
举个例子:主力在买一价挂出10万手买单,看起来好像有大资金要买。市场看到这个信号,纷纷买入,价格上涨。就在价格快要触及那10万手买单的时候,主力撤单,同时在另一个方向挂出卖单。价格掉头向下,主力获利。
幌骗在欧美市场已经被明确认定为非法。美国CFTC和SEC在过去几年里对多家高频交易公司开出了巨额罚单。中国也在2025年的那个案例中认定为市场操纵。
识别方法:与虚假申报类似,核心指标是撤单率和大单的未成交率。

把多个手法整合成一个“盘口异常评分”

上面每个手法都有独立的识别指标。你可以把这些指标综合起来,做一个“盘口异常评分”。当分数超过某个阈值时,触发警报。
我通常用的几个指标(每个0-10分):

指标 计算方式 异常阈值(给高分)
撤单率 撤单量/总申报量 >70% 得8分,>80% 得10分
买卖失衡度 (买量-卖量)/(买量+卖量) >0.6 得8分,>0.8 得10分
大单集中度 最优价位的委托量/总委托量 >0.7 得8分,>0.9 得10分
突破后的成交量萎缩 突破后5分钟成交量 / 突破前5分钟成交量 <0.5 得8分,<0.3 得10分
价格快速反转 (突破后最高价 - 收盘价)/ATR >1.5 得8分,>2 得10分

总分50分。如果超过30分,建议你对该股票保持高度警惕,不要轻易追涨杀跌。

1.4 游资和量化互相割

前面讲的主要是主力资金(可以理解为“大钱”)收割量化。游资和量化之间的关系,更像是“互相伤害”——今天你割我,明天我割你,谁也别装无辜。

游资的典型操作模式

游资,也叫“敢死队”,他们的操作模式可以用四个字概括:快、狠、准、短。
选股:小市值(容易被拉动)、有题材(有故事可以讲)、近期没有大幅上涨(避免给他人抬轿)。
建仓:分步买入,通常用5-10个账户,每天买一点点,不引起注意。
拉升:选择一个交易日,用几个账户集中买入,快速拉升至涨停。涨停之后,用大单封住涨停板。
出货:第二天或第三天,在涨停板或者高开的位置,将筹码卖给追涨的人。
整个流程通常不超过5个交易日。

量化是怎么被游资割的

你在量化策略里用到的很多因子,在游资拉升的那一刻,恰好会触发买入信号。
举几个例子:
动量因子:游资拉升,短期涨幅变大,动量因子给出买入信号。
反转因子:如果这只股票前期跌了很多,反转因子看到“反弹”信号,也会买入。
资金流入因子:游资集中买入,大单占比飙升,资金流入因子触发。
突破因子:游资把价格拉过前期高点,突破因子触发。
也就是说,游资的拉升行为,正好是量化的买入条件。量化资金成了游资的“接盘侠”。
更糟糕的是,很多量化策略有“涨停板买入”的设定——认为涨停是强势的表现,所以追涨停。这就正中游资下怀。游资封住涨停板,就是为了在涨停价上把筹码卖给量化资金。

“天地板”和“地天板”的量化踩踏

“天地板”就是股票从涨停跌到跌停,“地天板”就是从跌停涨到涨停。这两种极端走势在A股并不少见,而且背后往往有量化的身影。

天地板的典型流程:

  1. 早盘,游资快速拉升,股票涨停。量化趋势策略看到涨停,认为强势确认,于是挂涨停板买入。
  2. 游资在涨停板上挂出大量卖单,把筹码卖给量化。
  3. 卖单耗尽,涨停板打开。此时追涨的散户和量化发现“炸板了”,开始恐慌。
  4. 价格快速下跌,触发了更多量化止损策略的卖出条件。
  5. 卖盘越来越多,直到跌停。一天之内,从赚10%到亏10%。
    你在盘后看到这种“天地板”,以为只是游资在割韭菜。实际上,量化资金在里面扮演了两个角色:先在涨停时抬轿子,后在跌停时踩踏。

地天板的流程正好相反:

  1. 早盘,游资故意砸盘,股票跌停。量化止损策略触发,卖出。
  2. 游资在跌停板上接货,把量化割肉的筹码收走。
  3. 然后游资反手拉升。量化趋势策略看到“从跌停拉起来”的信号,认为反弹确立,追进去。
  4. 游资在拉高的过程中出货,量化再次接盘。
    一天之内,被割两次。

游资的新战术:为量化“定制”股票

最近两年,游资的战术升级了。
他们不再随机选股,而是专门研究主流量化因子的选股条件。然后,他们人为地“制造”出符合这些条件的股票。
比如,某个量化因子要求股票满足:市值小于50亿、市盈率低于20倍、过去20日换手率高于5%、最近一个季度营收增长超过20%。
游资可能会找一只基本面还不错的股票(或者干脆找一只壳股),通过一些手段让它在财报上“看起来”满足这些条件(合法或不合法的手段都有),然后在社交媒体上散布这只股票的“题材故事”。
等量化资金被吸引进来,游资就开始出货。
这不是我编的。我跟做游资的朋友聊过,他们确实在研究这个。有的甚至专门雇了量化研究员,就为了“反向工程”主流因子的逻辑。
当然,游资也不是永远赢。有时候他们精心设计的“陷阱”没人跟,自己反而被套。量化基金也不是傻子,有些量化模型已经加入了“反游资”的模块——比如识别假突破、监测游资的常用席位、排除那些换手率异常放大的股票。
这就是市场的进化。你今天用的策略,明天可能就失效了。不是策略本身不对,而是别人研究透了你的策略,然后利用你来赚钱。

普通投资者怎么应对

你可能不是游资,也不是量化基金。你就是一个普通股民,用一些简单的因子来选股。你怎么避免成为“两军交战”的牺牲品?

  1. 不要在涨停板上买入。涨停板买入,短期看起来“追到了强势股”,但实际上你是在跟游资和量化抢筹码。你的对手盘是两群专业的狼,你是一头羊。你赢的概率有多大?
  2. 避开那些被量化基金高度拥挤的股票。我在1.1节给了你拥挤度的判断方法。如果一个股票同时出现在多个量化产品的持仓里,它就是“猎物”。
  3. 对于小市值、高换手的股票保持警惕。这些是游资最喜欢的目标,也是量化最常使用的因子。你可以在这些股票上赚钱,但不要指望“长期持有”。快进快出,设好止损。
  4. 学习识别盘口异常。1.3节的那些指标,你不用每次都算,但至少要知道哪些信号值得警惕。比如,如果一只股票在涨停后频繁打开涨停板,那大概率是游资在出货,不要追。
  5. 不要迷信“龙虎榜”。龙虎榜上显示“机构专用”买入,不代表真的机构在买——可能是游资用的机构席位。而且,就算真的是机构买入,你第二天跟进的时候,人家可能已经卖了。

1.5 用AI帮你盯盘(不是那种玄学AI)

前面讲的这些手法,靠人盯盘是来不及的。别说你一个人看十几只股票,就算你只盯一只股票,盘口的数字跳得你眼花缭乱,你也不太可能及时反应过来。
这时候就需要用到机器学习里的一类算法——异常检测。

异常检测是什么

简单说,异常检测就是让机器自动学习“正常的数据长什么样”,然后发现那些“长得不一样”的数据点。
你可以把它想象成机场的安检。安检员每天看成千上万件行李,知道正常行李的X光图像是什么样子。如果突然有一个行李箱里藏了一把刀,X光图像就会跟正常的不一样,安检员就会把它挑出来。
异常检测算法做的事情是一样的。你给它足够多的“正常盘口数据”,它会自己学到正常盘口的统计规律。然后你把实时数据喂给它,它会告诉你:“这一段数据跟之前学到的正常模式不一样,可能是异常。”
你不需要告诉它什么是“虚假申报”、什么是“诱导拉升”。你只需要告诉它:“这是正常的数据。”它会自己找到跟正常不一样的地方。

孤立森林算法

在所有的异常检测算法里,我最推荐初学者使用的是孤立森林。原因有三:
它不需要你标注数据(什么算异常、什么算正常),只需要纯数据。
它对高维数据(也就是有很多特征的数据)处理得比较好。
它的实现非常简单,sklearn里直接就能用。
孤立森林的原理有点像“猜谜”。正常的数据点,你需要很多条线索才能把它“孤立”出来。异常的数据点,只需要很少的线索就能把它找出来。
用数学的话说:异常点在特征空间中远离正常点,因此更容易被随机分割出来。

完整代码实现

下面我给出一个完整的、可以直接运行的代码示例。假设你已经有了Level2的逐笔委托数据(这个数据你需要从券商API或者开源数据源获取,代码里不包含获取部分,因为每家接口不一样)。

import numpy as np
import pandas as pd
from sklearn.ensemble import IsolationForest
def extract_features_from_orders(order_df, window_seconds=60):
    """
    从逐笔委托数据中提取特征
    order_df: 包含字段 ['timestamp', 'price', 'volume', 'is_cancel', 'side']
        - timestamp: 时间戳(datetime类型)
        - price: 委托价格
        - volume: 委托数量(股)
        - is_cancel: 0表示未撤单(最终成交或未成交),1表示撤单
        - side: 'B'买单,'S'卖单
    window_seconds: 统计窗口长度(秒)
    """
    # 将时间戳向下取整到窗口起始时间
    order_df['time_bin'] = order_df['timestamp'].dt.floor(f'{window_seconds}S')
    
    features_list = []
    for bin_time, group in order_df.groupby('time_bin'):
        # 总委托量
        total_volume = group['volume'].sum()
        
        # 撤单量
        cancel_volume = group[group['is_cancel']==1]['volume'].sum()
        cancel_rate = cancel_volume / total_volume if total_volume > 0 else 0
        
        # 大单占比(定义大单为单笔>100手,即10万股)
        large_orders = group[group['volume'] >= 10000]
        large_order_ratio = large_orders['volume'].sum() / total_volume if total_volume > 0 else 0
        
        # 买卖失衡度
        buy_volume = group[group['side']=='B']['volume'].sum()
        sell_volume = group[group['side']=='S']['volume'].sum()
        imbalance = (buy_volume - sell_volume) / (buy_volume + sell_volume) if (buy_volume + sell_volume) > 0 else 0
        
        # 最优价集中度:假设你能拿到买一卖一价格,这里简化
        # 用委托价的标准差来近似委托分散程度
        if len(group) > 1:
            price_std = group['price'].std()
        else:
            price_std = 0
        
        features_list.append({
            'time': bin_time,
            'cancel_rate': cancel_rate,
            'large_order_ratio': large_order_ratio,
            'imbalance': imbalance,
            'price_std': price_std
        })
    
    return pd.DataFrame(features_list)
def detect_anomalies(features_df, contamination=0.1):
    """
    使用孤立森林检测异常
    contamination: 预期的异常比例(比如你认为大约10%的时间窗口是异常的)
    """
    X = features_df[['cancel_rate', 'large_order_ratio', 'imbalance', 'price_std']].values
    model = IsolationForest(contamination=contamination, random_state=42)
    model.fit(X)
    features_df['is_anomaly'] = model.predict(X)  # 1正常,-1异常
    anomaly_times = features_df[features_df['is_anomaly'] == -1]['time']
    return features_df, anomaly_times
# 使用示例(伪代码)
# raw_orders = fetch_level2_orders(symbol='00001', date='2025-12-15')
# features = extract_features_from_orders(raw_orders, window_seconds=60)
# result, anomalies = detect_anomalies(features)
# if len(anomalies) > 0:
#     print(f"检测到 {len(anomalies)} 个异常时间窗口: {anomalies.tolist()}")

代码调试指南(常见问题)

很多读者反映跑这段代码时会遇到几个典型问题,我列出来,你遇到时可以对照解决:
问题1:ImportError: No module named sklearn
解决方法:在终端运行 pip install scikit-learn。如果已经安装了,检查一下你的Python环境是不是激活了正确的虚拟环境。
问题2:KeyError: 'timestamp'
这说明你的原始数据字段名不叫'timestamp'。Level2数据源不同,字段名可能叫'trade_time'、'order_time'或'date'。你需要把代码里的字段名改成你数据里的实际名字。
问题3:内存不足(尤其是处理全市场数据时)
解决方法:不要一次性加载所有股票的数据。可以按股票循环处理,或者只处理你关注的少数几只股票。另外,window_seconds可以调大(比如300秒),这样窗口数量减少,内存占用也会下降。
问题4:孤立森林把所有窗口都标为正常或所有窗口都标为异常
这通常是因为contamination参数设置不合理。如果你认为异常窗口大约占5%,就设0.05;如果你认为异常窗口很少(比如1%),就设0.01。不要用默认的0.1,因为默认值不一定适合你的数据。

使用异常检测的注意事项

第一,孤立森林不是万能的。它只能告诉你“有异常”,不能告诉你“是什么异常”。你需要自己去看数据,判断是虚假申报、诱导拉升还是其他原因。有些异常可能是数据本身的问题(比如网络延迟导致数据不连续),而不是主力的操纵行为。
第二,需要调参。contamination参数非常重要。如果你设得太低(比如0.05),模型只会标记最极端的5%窗口为异常。如果你设得太高(比如0.3),很多正常波动也会被标记为异常。我建议你先用历史数据跑一遍,看看标记出来的异常窗口是否合理,然后再调整这个参数。
第三,不要直接自动化交易。我用这个系统的时候,只是用它来过滤出需要人工复核的时段。我不会让程序自动下单或者自动止损。因为你永远不知道异常的背后到底是什么。万一今天只是券商系统出了问题,你就跟着止损,那不是很冤吗?
第四,配合其他信号一起使用。比如,如果异常检测发出了警报,同时拥挤度也在高位,同时价格走势也很诡异,那才值得重视。单一信号的误报率太高。

有没有更简单的方法

如果你觉得搭建这套系统太麻烦,还有一个更简单的办法:用免费的Level2行情软件,手动看几个关键指标。
很多券商APP的Level2功能(免费版)提供了“逐笔成交”和“委托队列”的图表。你不需要写代码,用眼睛看就行:
看撤单率:如果看到一个大单突然出现,然后又消失了,记录一下这种“闪现单”的频率。
看买卖失衡:如果买一突然堆了很大的单子,但价格不涨,那就是有人在“托单”而不是“拉抬”。
看成交后的价格反应:如果一个大单成交后价格纹丝不动,那可能是对倒单。
这种方法当然没有机器精确,但对于普通投资者来说,可能已经够用了。

1.6 今天就能用的三个指标(不啰嗦,直接用)

好了,啰嗦了半天,该给你点能直接用上的东西了。
下面三个指标,你今天就能算出来。不需要Level2数据,不需要机器学习,只需要免费的日线数据和一点点Python代码。它们能帮你判断:你手上的因子,是不是已经太挤了、快要失效了。

指标一:因子换手率

公式:因子持仓股的平均换手率 ÷ 全市场所有股票的平均换手率
解读:这个比值越高,说明因子持仓的股票交易越活跃。但过度活跃往往是拥挤的表现——大家都在里面倒来倒去。
阈值:如果比值 > 2,并且处于过去三年数据的90%分位数以上(也就是比过去90%的时间都高),说明这个因子已经非常拥挤,风险很高。
数据来源:AKshare的stock_zh_a_hist接口可以获取个股每日换手率。

代码示例(简化版,完整版见GitHub):

import akshare as ak
import pandas as pd
def factor_turnover_ratio(factor_stocks, date):
    """
    factor_stocks: list,因子持仓的股票代码列表
    date: 查询日期,格式'20251215'
    """
    # 获取因子持仓股的平均换手率
    factor_turnover_sum = 0
    for stock in factor_stocks:
        df = ak.stock_zh_a_hist(symbol=stock, period='daily', 
                                start_date=date, end_date=date, adjust='')
        if not df.empty:
            factor_turnover_sum += df['turnover'].iloc[0]
    factor_avg = factor_turnover_sum / len(factor_stocks) if factor_stocks else 0
    
    # 获取全市场平均换手率(抽样100只代表,严谨起见应全市场)
    stock_info = ak.stock_info_a_code_name()
    all_stocks = stock_info['code'].tolist()[:100]  # 示例抽样
    market_turnover_sum = 0
    for stock in all_stocks:
        df = ak.stock_zh_a_hist(symbol=stock, period='daily',
                                start_date=date, end_date=date, adjust='')
        if not df.empty:
            market_turnover_sum += df['turnover'].iloc[0]
    market_avg = market_turnover_sum / len(all_stocks)
    
    ratio = factor_avg / market_avg if market_avg > 0 else 0
    return ratio

注意:上面的代码为了演示只写了逻辑框架,实际跑的时候需要处理很多细节(如股票退市、数据缺失等)。完整代码我放到了GitHub上,你可以直接下载使用。

指标二:因子与机构持仓的重合度

公式:因子持仓 ∩ 某几家知名量化产品的持仓 ÷ 因子持仓
解读:重合度越高,说明你和机构“在同一条船上”。船稳的时候大家一起吃肉,船翻的时候你跑得比机构慢(因为机构有更快的交易通道)。
阈值:重合度 > 50% 时,建议降低仓位。重合度 > 70% 时,建议清仓。
数据来源:量化产品的持仓数据比较难获得,但可以通过以下渠道:
私募排排网:部分产品会定期披露持仓(免费注册后可查看)
券商私募子公司的季度报告
天相投顾等机构的基金持仓数据库(部分免费)
当然,这些数据都有滞后(通常是季度末后20-30天才公布)。但拥挤度是一个相对缓慢变化的指标,季度更新足够用了。

代码示例(伪代码,因为需要具体数据源):

def overlap_ratio(factor_stocks, institution_stocks):
    set1 = set(factor_stocks)
    set2 = set(institution_stocks)
    intersection = set1.intersection(set2)
    ratio = len(intersection) / len(set1) if set1 else 0
    return ratio

指标三:IC的滚动波动率

公式:先计算因子每日的IC值,再计算IC值的20日滚动标准差,最后看这个标准差是否突然放大。
解读:IC(信息系数)衡量因子排名与未来收益排名的相关性。通常因子IC值会在一个相对稳定的区间内波动。当IC的波动率突然放大,说明因子的预测能力开始不稳定——今天灵明天不灵,这是失效的前兆。
阈值:如果20日IC波动率超过60日平均值的2倍,触发预警。

代码示例(简化版,假设你已经有了IC序列):

# 假设 ic_series 是每天的IC值(从你的回测系统导出)
ic_series = pd.Series([0.12, 0.08, 0.15, -0.02, 0.09, ...])
ic_vol_20 = ic_series.rolling(20).std()
ic_vol_60_avg = ic_series.rolling(60).std().mean()
alert = (ic_vol_20.iloc[-1] / ic_vol_60_avg) > 2
print("IC波动率异常:", alert)

如果你还没有自己的回测系统,可以先跳过这个指标。等你看完第二章(搭建免费回测流水线)之后,再回来用。

每日晨间检查流程

我每天早上9:00到9:15之间,会做这么几件事:

  1. 运行拥挤度检查脚本(5分钟)。计算我当前使用的几个因子的换手率比值和重合度。如果任何一个指标亮红灯,我会在当天的交易中降低该因子的权重(比如从100%降到50%)。
  2. 浏览证监会网站(5分钟)。看看有没有新的处罚决定书。如果有,我会仔细读一下,看看主力最近在用什么新手法。这比读研报有用多了。
  3. 看一眼昨晚外盘的情况(2分钟)。不是为了做交易,只是为了心里有数。
  4. 检查自己的持仓是否有异常波动(3分钟)。如果有,看是否触发了止损。
    总时间不超过20分钟。20分钟换一个安心的交易日,我觉得很值。

本章FAQ

问题1:拥挤度指标多久更新一次?日频还是周频?
我建议每日更新。因为拥挤度变化可能很快,尤其是在市场风格切换的时候。每天开盘前花几分钟跑一下脚本,成本很低。如果你觉得太频繁,至少每周更新一次,但要注意周频可能会错过一些短期风险。
问题2:我的资金量很小,也会被主力盯上吗?
不会。主力收割的是那些大资金、行为一致的量化产品。你的几百万(甚至几十万)资金,主力看不上。但是,如果你使用的因子和那些大机构一样,那么主力收割机构的时候,你持有的股票也会被波及。所以,你仍然需要关注拥挤度。
问题3:AI异常检测的误报率太高怎么办?
两个办法:一是调整contamination参数,降低预期异常比例;二是结合多个模型投票(比如孤立森林+LOF+单分类SVM),只有两个以上模型同时报警才触发。代码里实现投票机制也不难,你可以参考GitHub上的完整版。
问题4:我在网上看到有人卖“主力资金监控系统”,值得买吗?
大多数不值得。很多这类产品只是包装了简单的Level2指标,比如大单净流入、主力买卖占比,这些东西你自己用免费数据也能算。而且,真正的操纵行为(如虚假申报)需要看委托流和撤单率,不是简单的大单统计就能识别的。建议你先用本章的免费方法自己试试,确实不够用了再考虑付费工具。
问题5:因子失效后,什么时候可以重新使用?
当拥挤度回落到历史中位数以下,并且IC波动率恢复正常(不再超过2倍标准差),就可以重新考虑了。但要注意,有些因子失效后可能再也回不到以前的收益水平——因为市场结构可能已经变了。所以不要死守一个因子,多准备几个备用的。

本章实战清单汇总

你可以把下面的清单打印出来,每天开盘前对照执行。

第一章核心公式卡

  1. 拥挤度分档(用于判断因子是否太挤)
    拥挤度分位 操作建议
    0-20%(低拥挤) 正常使用
    20-40% 正常使用,开始关注
    40-60% 中性,可减半仓
    60-80% 谨慎,建议减仓
    80-100%(高拥挤) 危险,建议清仓或暂停
    计算公式:拥挤度 = 因子持仓与全市场量化产品持仓的重合度

  2. 因子换手率预警
    因子换手率 = 因子持仓股平均换手率 ÷ 全市场平均换手率
    预警条件:因子换手率 > 2 且 处于过去3年90%分位数以上
    操作:当天该因子仓位减半

  3. IC波动率预警
    IC滚动波动率 = IC值过去20日的标准差
    IC基准波动率 = IC值过去60日标准差的平均值
    预警条件:IC滚动波动率 ÷ IC基准波动率 > 2
    操作:因子可能失效,暂停使用或大幅减仓

  4. 盘口异常评分表(总分50分)
    指标 计算方式 得分条件
    撤单率 撤单量/总申报量 >70%得8分,>80%得10分

买卖失衡度 (买量-卖量)/(买量+卖量) >0.6得8分,>0.8得10分
大单集中度 最优价委托量/总委托量 >0.7得8分,>0.9得10分
突破后成交量萎缩 突破后5分钟成交量/突破前5分钟成交量 <0.5得8分,<0.3得10分
价格快速反转 (突破后最高价-收盘价)/ATR >1.5得8分,>2得10分
判定:总分 > 30分 → 高度警惕,不追涨杀跌

  1. 每日晨间检查清单
    时间 事项 耗时
    9:00-9:05 运行因子换手率和IC波动率脚本 5分钟
    9:05-9:10 浏览证监会网站(行政处罚栏目) 5分钟
    9:10-9:12 查看外盘隔夜表现 2分钟
    9:12-9:15 检查持仓股是否有盘口异常 3分钟
    总耗时:15分钟

使用建议
将本页复印或拍照存手机,每日开盘前对照执行
公式卡中的阈值是基于历史数据回测得出的参考值,可根据个人风险偏好微调(比如更保守的可以将换手率阈值从2降到1.8)

每日检查(5分钟)
运行因子换手率指标,记录比值是否 >2 且处于90%分位以上
(如有机构持仓数据)运行重合度指标,记录是否 >50%
(如有IC序列)运行IC波动率指标,记录是否 >2倍标准差
如果任何一项亮红灯:当天该因子仓位减半
如果两项以上亮红灯:当天暂停使用该因子

每周检查(15分钟)
浏览证监会网站“行政处罚”栏目,看是否有新的市场操纵案例
更新因子持仓列表(如果你的因子是动态调仓的)
检查手中持有的股票是否出现在“异常盘口评分”过高的时段

每月检查(30分钟)
重新计算因子的历史拥挤度分位数(滚动3年窗口)
审查因子的IC序列,看是否有趋势性衰减
更新机构持仓数据(季度披露,收到后尽快整理)

第一章到此结束。
下一章,我会教你怎么不花一分钱,把整套路子分析的流水线搭起来。包括数据从哪来、代码怎么写、回测怎么做、IC怎么算。那些花几万块买数据、买软件的人,不一定比你知道得多。我们用手边的免费资源,一样能做出专业水平的东西。

⚠️ 风险提示:本书内容仅为量化研究与知识分享,不构成任何投资建议。套利交易存在基差、费率、流动性、平台与极端行情等风险,历史表现不代表未来收益。投资有风险,入市需谨慎,请自主决策、量力而行。

💡 键盘 ←/→ 翻章 · T 键切换目录