假设你真的动手了。开了一个空项目,起名叫 stock-sim,然后盯着空白屏幕,第一个问题就来了:第一行代码该写什么?
大多数人的直觉是:先写一条股价。让它动起来——涨涨跌跌,像真的行情软件那样。于是写下某个随机数发生器:上一刻的价格加上一个随机扰动,得到这一刻的价格。跑起来,屏幕上一条曲线扭来扭去,乍一看,还真有点像股票。
但这个开局已经错了。错在哪,这本书要用十二章来回答。而答案可以先用一句话说完:
真实市场里,价格从来不是一个「被生成的数」,而是一群人互相出价、互相成交之后剩下的痕迹。你用随机数直接画价格,等于跳过了整个故事,只描了故事的影子。
影子和踩出影子的人
拿一个类比。你要做一个足球游戏的模拟器。有两种做法:
- 做法 A:直接生成「比分」。写一个函数,按真实比赛的比分分布随机吐出 2:1、0:3,再配上时间轴。屏幕上比分牌会动,球迷看着也像那么回事。
- 做法 B:模拟球员、球、草地和规则。比分不是被「生成」的,是 22 个球员踢完 90 分钟之后剩下来的。
做法 A 的问题不是「不像」,而是它没法交互。玩家说「我要买入一万股」——这相当于玩家说「我要铲球」——可你的系统里根本没有球,只有比分牌。玩家的一切动作都没有受力对象,你只能假装他做了点什么,然后继续放你的随机曲线。
股市一模一样。价格就是比分牌。真正在被踢的那个球,是订单——一句大白话:某个人喊出来的「我愿以多少钱买/卖多少股」。价格是无数句这样的喊话撞在一起的结果。所以搭一个股市模拟器,你模拟的第一公民不是价格,而是人,和人喊出来的订单。
「可信」和「准确」是两回事
开工之前还有一个更要命的目标问题,必须在白板上写清楚:你要的是一台「准确」的模拟器,还是一台「可信」的模拟器?
「准确」的意思是:模拟出来的价格走势和真实市场统计特征一致——波动率像、肥尾像、聚集性像。这是金融学界干的事,他们叫随机过程建模,用大白话说就是「给随机数发生器调参数,调到吐出来的曲线和真行情长得很像」。这条路很成熟,但对做游戏基本没用,理由和上面比分牌的例子一样:统计上再像,玩家也没法「进去玩」。
「准确」追求的是曲线像。「可信」追求的是:玩家在里面的每个动作都有真实的对手、真实的后果、真实的反馈。前者是数学家的事,后者才是游戏设计师的事。
「可信」的意思完全不同:玩家挂出一个买单,得真的有另一个(可能是 NPC 的)卖单在对面等着;玩家砸出十万股市价单,价格得真的被他砸下去一块;玩家满仓杠杆,暴跌时得真的收到爆仓通知。可信的模拟器不要求曲线像历史,它要求因果链像现实——每一个结果都能往回追到某个人的某个动作。
这个区分决定了后面每一章的取舍。全书会反复回到它:遇到设计分歧,就问「这个选择是让数字更像真的,还是让玩家的体验更像真的」——我们永远选后者。
整台机器的轮廓
把「模拟人」这个目标拆开,一台市场模拟器其实只有三层:
- 撮合层(第二、三章):一台铁面无私的机器,收订单、配对、吐出成交和价格。它没有任何智能,像物理引擎。
- 世界层(第四、九章):基本面、新闻、信息流——给市场一个「值得吵起来」的理由。
- 人群层(第五到八章):一群性格各异的 NPC 交易者,带着各自的信念、偏见和错误,对着世界层的信息做出反应,往撮合层里扔订单。
价格,是这三层跑起来之后自己长出来的东西——所以它甚至不在这张清单上。这就是标题里那个问题的答案:你模拟的从来不是股价,是人;股价是人模拟好之后,附赠的礼物。
剩下的事,是从最硬的那层开始:撮合引擎。下一章我们就造这颗心脏。