halo 的技术博客

返回

你有没有想过一个问题:为什么市场不会彻底崩掉,也不会永远锁死在一边? 如果所有交易者都「追涨杀跌」,价格早该发散;如果都「逆向抄底」,又该长期贴着极值不动。真实市场里,这两种人永远在互相踩——有人做趋势,有人做反转,有人专门当流动性提供者。少数者博弈(Minority Game, MG) 用一个极简设定,把这件事的骨架抽了出来。

结论先放这:N 个 Agent 每轮同时选 0 或 1,选到「人少那一侧」的赢。没有任何上帝告诉谁该选什么,每个 Agent 只揣着几张「历史→动作」的查表策略,按虚拟得分挑最好的一张用。结果——当 Agent 的「记忆」够长,他们能从一片混乱里,自发把「到场人数」协调到资源容量 L=N/2 附近:不崩溃(没人全挤一边)、不锁死(还在小幅波动找机会)。在我们的模拟里,记忆 m=2 时协调效率仅 4.2%(近乎乱选、还带偏置),m=10 时升到 49.2%(紧紧聚在容量附近)。这恰好是「逆向交易者」存在的市场价值:当多数人涌向一侧,反方向那侧反而成了少数者赢面。

少数者博弈(m=10):Agent 把到场人数协调到容量 L 附近,不崩溃也不锁死


一、规则:一个赌局,赢家是「少数派」#

设 N 个 Agent(取奇数,比如 101),每轮同时决定「去 0 号酒吧」还是「去 1 号酒吧」。规则只有一条:

a_t = 选 0 的人数
L   = N/2  (资源容量:酒吧只能舒服地容纳一半人)
win_t = 0  若 a_t < L   (选 0 的是少数 → 他们赢)
win_t = 1  若 a_t > L   (选 1 的是少数 → 他们赢)
plaintext

赢的人得分 +1,输的人 −1(或对称计分)。关键在 Agent 的决策机制

  • 每个 Agent 持有 S 张策略。一张策略是一张查表:给定「最近 m 轮少数人动作拼成的历史串」(共 2m2^m 种可能),输出「这轮我选 0 还是 1」。
  • 每张策略有一个虚拟得分,初始 0;每轮用「这张策略如果当时被采用,会不会猜中 win_t」来更新(猜中 +1)。
  • 每轮 Agent 实际采用的,是当前得分最高的那张策略(best-response)。

注意两个反直觉点:① Agent 不看价格、不看基本面,只看「过去少数者往哪边走」;② 策略是虚拟计分、不是真金白银下注,所以 Agent 边玩边学、策略权重会漂移。没有中央协调者,秩序是从「各自揣着几张查表互相踩」里长出来的。


二、从零实现:纯 numpy 复刻 MG#

我们用纯 numpy 把上面设定跑起来。核心是一个「历史键」的维护:每轮把最近 m 个 win 拼成整数 key,查每个 Agent 最高分策略在该 key 下的动作。

两个工程上不能省的点:

  • tie 破局:当某 Agent 两张策略同分,argmax 会永远选索引小的那张,导致策略集「退化」成只用少数几张——这会人为制造同步、破坏相变。我们加 1e-6 * rng.random 的微小扰动随机破 tie,让策略使用保持多样。这是 MG 复现相变的关键细节,漏了就跑不出干净结果。
  • 预热段 warm:前 2000 轮策略得分还在「冷启动」,统计不平稳,一律丢弃再算指标。

三、核心现象:记忆 m 越长,协调效率越高#

「协调效率」是我们关心的序参量:定义 eff=P(atL10)\text{eff} = P(|a_t - L| \le 10),即「到场人数落在容量 ±10 人以内」的时间占比。越高,说明 Agent 越能把系统稳定在资源舒适区。

把 m 从 1 扫到 11(每个 m 跑 8 个随机种子取均值),结果:

相变:记忆 m 越长,Agent 越能自我组织到容量附近(从 ~4% 跃升到 ~49%)

记忆 m平均到场人数协调效率 eff(±10)
245.94.2%
457.414.4%
657.924.6%
851.354.5%
1059.249.2%

这张表要拆开读:m=2 时 Agent 几乎像乱选——到场人数发散、还带明显偏置(均值 45.9 偏离 L=50),协调效率只有 4.2%,系统处于「各自为战、浪费资源」的混乱相。随着 m 变长,Agent 记住的历史越长、能区分的情境越多,策略分工越细,到场人数被一点点「摁」回容量附近;到 m=8~10,近一半时间系统稳稳待在舒适区,既没崩溃(没人全挤一边)、也没锁死(还在小幅波动找机会)

分布图把这件事说得更直白——小记忆时到场人数发散偏置,大记忆时紧紧聚在 L 附近:

分布对比:小记忆时到场人数发散偏置(浪费),大记忆时紧紧聚在 L 附近


四、它对应金融市场的哪一类人#

MG 最迷人的地方,是它和真实交易生态的结构性对应:

  • 「少数者」= 逆向 / 反转 / 流动性提供者。当多数人涌向 0 号(追涨、挤某侧),win_t 落在 1 号——恰恰是反方向那侧的人赢。这解释了为什么市场里永远需要「敢接飞刀、敢在恐慌里挂单」的流动性提供者:他们的盈利来源,本质就是「当 crowd 站错边时,自己是少数派」。
  • 「记忆 m」= 交易者的情境复杂度。只看「昨天涨没涨」(m=1) 的人,决策粗糙、容易和别人同步踩踏;能综合「过去十几轮 regime」的人,分工更细、互相踩得更巧,整体更接近有效。
  • 「协调效率」= 市场有效性但不僵化。高效市场不是「所有人意见一致」,而是「多空力量被协调到不极端失衡」——这正是 MG 在 m 合适时长出的状态。

五、诚实拆穿:四类真实陷阱#

① tie 策略退化:不破 tie,相变就跑不出来。 第二节强调的 1e-6 扰动不是装饰。若直接 argmax 不破 tie,同分 Agent 永远锁死索引最小策略,策略多样性坍缩,模拟会陷入人为同步(要么全挤一边、要么死锁),你看到的「效率曲线」完全是 artifact。复现 MG 第一件事就是正确破 tie。

② 「最优记忆 m≈log₂N」是另一层相变,本文聚焦的是协调效率视角。* 完整 MG 文献里还有一个更著名的相变:到场人数的波动率 σ(a_t) 随 m 呈 U 形,mlog2Nm^* \approx \log_2 N 处取最小——记忆太短(策略不够分情境)→ 过度震荡浪费;记忆太长(策略趋同)→ 同步踩踏、σ 反弹。我们用 N=101 时 mlog21016.7m^*≈\log_2 101≈6.7。本文为稳健可复现,主图改用「协调效率」这个更单调、更不易被 tie/种子噪声污染的序参量;若你想看 σ 的 U 形,把指标从 eff 换成 std(a_t) 并扫更细的 m 网格即可,结论一致:存在最优记忆。

③ 大 N 极限才有解析相变,小 N 噪声大。 MG 的漂亮结论(m* 标度、σ 下界 √L)在 NN\to\infty 极限下才严格成立。N=101 这种规模,单次运行受种子影响大,必须多种子平均(本文 8 种子)。实务意义:把 MG 当「市场隐喻」可以,但直接拿小样本 MG 去标定真实参数,统计意义很弱。

④ 与现实市场的边界。 MG 是对称零和、容量恒定、信息只有历史动作的极简模型。真实市场:收益非零和(经济在增长)、容量随价格动态变、信息维度爆炸(基本面/订单流/宏观)。MG 的价值不在「预测价格」,而在定性揭示「异质有限理性 Agent + 自适应策略」如何内生产生接近有效却不锁死的协调——它是复杂金融的「思想实验」,不是择时模型。


六、落到量化:你的日常工作流#

  1. 先复刻、再引申:用 run_mg 把 MG 跑通,逐 m 画出效率/σ 曲线,确认相变位置——很多「MG 没相变」的困惑,其实是 tie 没破或预热没丢。
  2. 把它当「逆向策略的存在性证明」:设计反转/流动性提供策略时,记住 MG 的教训——你的盈利前提是「多数人会站错边」,所以这类策略的容量天然受 crowd 规模限制,不能无脑加杠杆。
  3. 记忆/情境复杂度类比:你的因子或 RL 策略「看多长历史」对应 MG 的 m;历史窗口太短易过拟合噪声、太长易和别人趋同,存在类似 m* 的最优。
  4. 复杂系统视角看市场:遇到「为什么没崩也没疯涨」的疑问,MG 给了一种答案——异质交易者的互相踩踏,本身就是稳定器。

真实落地时,MG 更适合做研究隐喻与压力测试的思维框架,而非直接下单信号。本文纯 numpy 合成只为把「Agent 查表 → 虚拟计分 → 自组织协调」的每一步摊开。记住:少数者博弈告诉我们,市场有效性不是谁来设计的,而是无数「想当少数派」的逆向交易者,互相踩出来的——而这恰恰需要有人永远愿意站在 crowd 的对面。

少数者博弈金融市场模型:异质 Agent 如何把「逆向交易」自组织成有效市场
https://blog.halo26812.eu.org/blog/minority-game-model
Author halo
Published at 2026年7月22日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨