← 返回量化与 AI 投研概念库

流动性与策略容量:钱一多,同一套方法就不好使了

最后更新 2026-08-18
R2 · 注意风险

有个现象你可能亲眼见过,也可能亲身经历过。

某个人用十万块做一套自己摸出来的方法,两年下来收益相当好,说得头头是道。后来他管的钱多了,几百万、上千万,同一套方法、同一个人、同样的纪律,收益却一年不如一年。他自己的解释通常是「市场变了」「风格不对」。

也可能是另一个版本:你在网上翻到一套写得明明白白的规则,作者甚至把历史成绩图都贴出来了。你照着做,做了半年,怎么也做不出那个样子。

这两件事背后是同一个词——容量。一套方法能装多少钱,是有上限的。而且这个上限不是拍脑袋定的,它由一件很具体的事决定:你想买的那些东西,市场上每天到底能吞下多少。

先说人话:早市上的鸡蛋

你早上去菜市场买鸡蛋。买两斤,摊主给你称,价格是牌子上写的那个价,一分不多。

买两百斤呢?摊主先愣一下,然后说我这儿只有一百二十斤,剩下的你得等明天。你说我等不了,那你去隔壁摊问,隔壁的价格比这家贵一点。跑完整条街你凑齐了两百斤,但你付出的平均价,明显高于牌子上那个价。

买两万斤,事情就完全变了。整条街的摊主看到你,第一反应不是卖给你,是先把牌子上的价格改了。等你走完这条街,鸡蛋已经不是原来那个价了。不是市场跟你作对,是你自己的买入动作把价格顶上去的。

这里有两件事要分开。「牌子上的价格」是你看得见的报价;「你实际付出的平均价」才是你真正的成本。买得越多,这两个数差得越远。 而牌子上的价格和历史成交记录,都只记得第一个数。

再看得远一点:这条街每天大概能卖出多少鸡蛋,是个相对稳定的量。这个量决定了「你最多能在这儿花多少钱而不把价格搞乱」。这就是容量。不管你的挑蛋眼光多好,这条街的日成交量摆在那儿,眼光换不来更多的鸡蛋。

投资层:流动性对你的决策意味着什么

流动性这个词平时被说得很虚,落到你的账户上,它其实只回答一个非常具体的问题:你这笔钱,能不能按你看到的那个价格进去、以及在你想走的时候按接近的价格出来。

对小资金来说,这个问题几乎不存在。你买一手大盘蓝筹,成交价和你看到的报价基本一样。所以小资金的人很容易得出一个结论:价格是外生的,我的动作不影响它。这个结论在你的资金量级上是对的,一旦跨过某个量级就完全不对了,而且没有人会提醒你什么时候跨过去。

三件对决策直接有影响的事:

第一,你的持仓相对于日成交额的比例,决定了你的退出难度。 一只股票每天成交五千万,你持有两百万,正常情况下一天之内出清没什么难度。你持有五千万,那就是要花好几天,而且这几天里价格很可能一路被你自己压下去。真正麻烦的是,你需要跑的时候通常是市场恐慌的时候——那恰恰是成交额萎缩的时候。术语卡里说的「流动性枯竭」就是这个意思:平时看着能出得来的东西,在你最需要出来的那天出不来。

第二,换手率高不等于容量大。 换手率是一段时间内成交量占流通盘的比例,它衡量的是「交易有多活跃」。但活跃有两种:一种是大量不同的人在真实换手,另一种是同一批筹码在少数账户之间来回倒。后者的换手率一样很高,可你真拿一笔大钱进去,会发现根本没有对手盘接得住。看盘口挂单也有同样的问题——挂在那儿的单子随时可以撤,你的单子一到,它可能先撤了。

第三,同样的方法,换个池子容量差好几个数量级。 一套方法如果只在成交清淡的小票上有效,它的容量可能就是几百万;同一套逻辑如果在大盘品种上也成立,容量能大好几个数量级。所以「这套方法有效吗」和「这套方法能装多少钱」是两个独立的问题,前者成立不代表后者成立。

容量上限到底是怎么算出来的

这一段是本篇的核心,值得慢一点看。

先建立一个中间量:参与率——你在某段时间里的成交额,占这个品种同期总成交额的比例。你买一百万,那天这只票总共成交五千万,你的参与率就是百分之二。这个数是理解容量的钥匙,因为它同时决定了两件事:能不能成交、以及成交要多付多少。

第一层:硬上限。 你不可能买到比市场当天全部成交量还多的东西。这是物理约束,谁也绕不过去。于是一个品种上你能建的最大仓位,大致是「日均成交额 × 你能接受的参与率 × 你愿意花几天来建仓」。把每个品种的这个上限,按你的持仓权重反推回组合规模,就得到组合层面的容量估计。这个估算很粗糙,但方向是对的:容量是被日成交额和持仓分散度共同框住的。

第二层,也是真正致命的一层:成本随规模上升的速度,比规模本身快。

想清楚这件事,容量的概念就通了。你的超额收益大致是「收益率 × 本金」,本金翻倍,赚到的钱翻倍——这是线性的。但你的冲击成本——也就是你自己把价格推走造成的损失——不是线性的。参与率越高,你要吃掉的挂单越深,每多买一份的代价就越贵。所以规模翻倍时,冲击成本涨的不止一倍。

两条曲线,一条线性往上,一条比线性更陡地往上。它们必然会相交。交点左边,规模越大赚得越多;交点右边,多出来的规模全部喂给了成本。那个交点就是容量上限。

这也解释了一个常被忽略的联动:调仓越频繁,容量越小。 因为容量吃的不是持仓量,是成交量。一套一年调两次的方法和一套一周调两次的方法,即使持仓完全相同,后者每年要在市场里吞吐的量是前者的几十倍,参与率也就高几十倍,成本按超线性放大。这一层和调仓频率那篇讲的是同一件事的两面。

第三件要注意的:容量不是你一个人的。 日成交额是所有人共享的池子。如果有另外五个人在做同样的判断、在同一时刻发出同方向的指令,那么真正推动价格的是你们的总量,而你在估算成本时只算了自己那一份。这是下一节的主线。

系统层:三套系统怎么处理这件事

概念讲完了,看看真实系统里它长什么样。有意思的是,三套系统给出了三种态度:认真建模、只在实盘里管、以及干脆不管。

qlib:把参与率写进撮合和成本

qlib 的交易所模块给了一个叫 volume_threshold 的配置项,作用是限制单笔订单最多能吃掉多少成交量。它的文档把两种口径分得很清楚:"cum" 表示这是一个随时间累积的量(比如日内累计成交量),用作限额时需要减掉已成交的部分;"current" 表示这是一个实时值(比如买一档挂单量),可以直接当作容量上限用。买、卖还可以各设各的,多个限制取最小值。

文档里给的示例配置形如:

"volume_threshold": {
    "all": ("cum", "0.2 * DayCumsum($volume, '9:45', '14:45')"),
    "buy": ("current", "$askV1"),
    "sell": ("current", "$bidV1"),
}

这是上游文档中的示例写法,不是推荐参数——具体取多少属于配置,随市场和资金规模而变。要看的是结构:一个限制来自「当日累计成交量的一个比例」,另一个限制来自「盘口对手方的实时挂单量」,两者取更严的那个。超出限额的部分怎么办?订单数量会被直接裁掉,相当于交易所拒掉了你多出来的那部分。

更值得盯着看的是它的冲击成本公式。剥掉上下文,核心就一行:

adj_cost_ratio = self.impact_cost * (trade_val / total_trade_val) ** 2

trade_val 是你这笔的成交金额,total_trade_val 是同期该品种的总成交金额,两者相除就是参与率。注意那个平方——参与率翻倍,这一项的成本翻四倍。 这正是上一节说的「成本涨得比规模快」,在代码里就是这么一个指数。impact_cost 本身是个可配置的系数(文档给了一个推荐值,属于当前默认口径、可配置),但真正决定形状的是那个平方项。

对照着看会更清楚:它还有 open_costclose_cost 这类按比例收的费率,那些是线性的,跟你买多少无关,只跟金额成正比。线性的那部分不会限制你的规模,超线性的这部分才会。 一份成本模型里有没有一个跟参与率挂钩的非线性项,基本决定了它认不认「容量」这回事。

freqtrade:实盘里认真管,回测里管不了

freqtrade 的做法是另一种思路。它有一整套按成交量筛选交易品种的插件,最典型的那个按报价成交额排序,只留成交额最高的若干个,还能设最低和最高的成交额门槛——低于门槛的太冷清不碰,高于门槛的可以剔掉(比如你不想跟着最拥挤的那几个品种做)。另有一个按买卖价差过滤的插件,价差太宽的品种直接踢掉,因为价差本身就是流动性的直接读数。

但这套东西有一行声明,比它的功能更值得读:

class VolumePairList(IPairList):
    is_pairlist_generator = True
    supports_backtesting = SupportsBacktesting.NO

这个按成交量选品种的插件,明确标注不支持回测。 它的枚举里一共四种取值:支持、不支持、不产生影响、有偏差。按成交量选品种被归到「不支持」,因为它依赖的是当下这一刻的实时成交额排名——历史上某一天的排名,回测时是拿不到的(拿今天的排名回到过去用,就是前视偏差的经典入口)。顺带一提,好几个别的筛选器被标成了「有偏差」,也是同一个道理。

更能说明问题的是它对成交的两套假设。回测文档里明确写着:只要价格落在这根 K 线的最高最低之间,所有订单都按你要的价格全额成交,不计滑点。而实盘模拟(dry-run,用真实行情但不真下单)的文档写的是另一套:市价单按下单那一刻的盘口挂单量成交,并且带一个最大滑点上限。

同一个系统,两套逻辑。回测里你的下单量不影响任何东西,实盘模拟里你的下单量要去啃盘口。这个落差就是容量在系统里的位置——它几乎总是被回测忽略,然后在实盘里全额收回。

Vibe-Trading:连「多少」这个参数都没有

第三套系统给的信号最直白。它的回测引擎基类里,滑点是个抽象方法,各市场自己实现。签名长这样:

def apply_slippage(self, price: float, direction: int) -> float:

只有价格和方向两个参数。没有数量。 具体到 A 股那个实现,就是把价格按一个固定比率往不利方向挪一下,比率从配置里读。

这意味着什么?意味着在这个引擎里,你买一万块和买一个亿,每股的执行价完全一样。资金曲线的形状与你的资金规模无关——把初始资金乘以一千,收益率一分不变。

这不是这套系统的疏忽,而是绝大多数回测引擎的默认状态。它们的成本模型是按比例收的,费率、印花税、固定滑点,全都是线性项。一堆线性项加起来还是线性的,而线性的成本永远吃不掉线性的收益。于是在数学上,这类回测里的策略容量是无穷大。 你看到的那条曲线,隐含地假设了市场是个无限深的水池。

值得一提的是,它在统计层面确实认真算了换手(一系列 turnover 指标,包括每根 K 线的换手和调仓换手的均值与最大值)。换手是容量的关键输入之一,把它算出来是好事——但算出来和用它去约束成交,是两件不同的事。

为什么一套好方法,公开之后就会失效

现在可以回答开头那个问题了。

一套方法之所以有效,往往是因为它抓住了某个还没被充分交易的价格偏离。这个偏离能提供的收益是有限的——它对应的是市场上真实存在的那部分错价,是一块有大小的蛋糕,不是一口取之不尽的井。

方法公开之后,会发生三件事,一件比一件狠。

第一,参与率被瓜分。 池子(日成交额)没变大,但往池子里伸手的人多了。每个人在估自己的冲击成本时,用的都是「我这一笔 ÷ 总成交额」,可实际推动价格的是所有人加总的那个量。每个人都低估了自己的成本,而且低估的幅度取决于有多少人和你想的一样——这个数你恰恰看不见。

第二,价格提前跑到位。 当足够多的人盯着同一个触发条件,交易会往前挪。原本在信号出现后才有的那段空间,会被抢在信号出现前吃掉。你按原样执行,买到的是别人已经推高过的价格。收益不是被分薄了,是从源头上消失了。

第三,也是最危险的一条:拥挤的仓位共享同一个出口。 一群人因为同样的理由持有同样的东西,就会因为同样的理由在同一时刻想卖。平时那个看起来足够深的成交额,是由买卖双方共同撑起来的;当所有人都站到卖方,买方那一侧会瞬间变薄。这时候你测算容量时用的那个日成交额,已经不存在了。 历史数据里那个数字是常态下的读数,而你需要用到它的那天恰恰不是常态。

所以「好方法公开后失效」并不需要任何阴谋论。它是容量这个约束在起作用:一套方法的容量,是所有使用者共享的;使用者变多,人均容量下降;下降到成本吃掉超额的那一刻,它对所有人同时失效。

🚧 避坑

回测收益率与资金规模无关,不是一个可以忽略的简化,而是一个会正好在你规模变大时反咬你的假设。 如果一套方法在回测里表现最好的那些品种恰好是成交最清淡的,那它的高收益很可能就是容量换来的——历史数据不会拦着你在一只日成交额很小的票上「买入」一大笔,但现实会。评估任何历史成绩时,先问一句:这些交易发生的品种,日成交额撑得起我准备投入的钱吗。

失效边界与常见误用

把容量当成一个能算准的数。 它不是。参与率对成本的影响随市场状态变,同一个品种在活跃期和清淡期完全是两回事。容量估算能告诉你的是数量级——是几百万、几千万还是几个亿,而不是一个精确值。把它当作精确值来用,等于给自己发了一张假的许可证。

只看平均成交额,不看它的分布。 一个品种的日均成交额可能被少数几天的暴量抬得很高,其余大部分日子清淡得多。用均值去估容量,会在最需要保守的那些日子里系统性高估。

以为分散持仓就能突破容量。 把钱铺到更多品种上确实能提高容量,但前提是这些品种真的有独立的流动性,且你的方法在它们身上同样成立。如果为了装下更多钱而把方法硬套到它本来不适用的品种上,你换来的不是容量,是一套被稀释掉的逻辑。

忽略退出侧。 很多人只算「我能不能买进去」,忘了算「我要花几天才能出来」。容量的真正约束往往在卖出侧,因为买入可以慢慢来,卖出常常由不得你慢。

把容量问题误诊成运气问题。 规模变大后收益下滑,最容易的解释是「最近行情不好」。区分方法其实不难:如果下滑的同时,你的实际成交价与决策时的价格之间的差距也在系统性变大,那多半是容量,不是运气。这类差距的量化口径,滑点那篇讲得更细。

小结

  • 流动性落到账户上只有一个含义:你这笔钱能不能按看到的价格进去、以及在你想走时按接近的价格出来。小资金感觉不到它,跨过某个规模后它会突然变成主要矛盾。
  • 关键中间量是参与率——你的成交额占市场同期成交额的比例。它同时决定了能不能成交、以及成交要多付多少。
  • 容量上限的来源:收益随规模线性增长,冲击成本随规模超线性增长,两条线必然相交,交点就是上限。qlib 把这件事写成了成本里的一个平方项,参与率翻倍这项成本翻四倍。
  • 调仓越频繁,容量越小——容量消耗的是成交量,不是持仓量。
  • 三套系统三种态度:把参与率写进撮合与成本、在实盘模拟里啃盘口但回测里不管、以及滑点函数连数量参数都没有。第三种是多数回测的默认状态,等价于假设市场无限深。
  • 方法公开后失效不需要阴谋论:容量由所有使用者共享,人多了人均容量下降,降到成本吃掉超额时,它对所有人同时失效;而且大家共用一个出口。

一句话记住这篇:再好的判断,也买不到市场上不存在的量。

本文所引源码与文档均来自上述快照版本,是阅读代码得出的机制说明,不是运行结果;具体行为请以你手上那个版本为准。回 量化与 AI 投研概念库 看其它概念各自在说什么;本站内容为投资教育,不构成任何投资建议,边界见 免责声明

内容有错、看不懂、或想看下一篇?告诉我们 →

本文为投资教育整理,不构成任何投资建议;不荐个股/基金、不预测点位、不承诺收益。关键数据与结论请结合权威来源自行验证,并见风险免责声明