1996年6月4日,法属圭亚那库鲁航天中心。
欧洲航天局耗资70亿美元研制的阿丽亚娜5型火箭,在发射升空后仅仅37秒,突然偏离预定轨道,在空中解体爆炸。火箭上搭载的四颗价值连城的科学卫星,在浓烟和火光中化为碎片。
事故调查委员会在事后找到的Bug,让全世界软件工程师集体沉默。
原因不是硬件故障,不是设计缺陷,而是一行代码。一个用来将64位浮点数转换成16位有符号整数的函数,在接收到一个超出16位整数范围的数值时,没有做任何异常处理。程序直接崩溃。更讽刺的是,这个崩溃的模块其实在发射后37秒就已经不需要运行了——它只是一个发射前的惯性参考系统校准模块,火箭起飞后它就是个僵尸进程。但工程师没有把它关掉,也没有给它的异常处理加保护。一个已经没用的模块,拖垮了整个系统。
调查报告里有一句话,我抄在了我的笔记本上,也请每一位读这篇文章的工程师记在心里:
“这一错误不是偶然的编程失误,而是系统设计哲学的错误。它假定软件不会出错。”
它假定软件不会出错。
你听到这句话的时候,有没有觉得后背发凉?因为这句话精准地描述了你过去几年在股市里的全部操作哲学——你假定你的策略不会出错,你假定你的分析足够全面,你假定你能在亏损扩大之前及时撤离。你假定你手里握着GDB,你假定你可以随时打断点。
但市场,不是一个可以随时暂停的调试环境。它是一个升空37秒后就会爆炸的火箭。
而你要做的,不是写一行更完美的代码——你永远写不出来。你要做的,是彻底改变你的系统设计哲学。
从FAT32到ZFS:你的财富系统需要静默数据损坏保护
你还记得第一次被FAT32文件系统坑了的场景吗?
你写了一个重要的文档,保存,关机,第二天打开——乱码。或者你插在电脑上的U盘,因为某次突然断电,整个分区表丢了,所有文件变成了无法读取的二进制碎片。你找过各种数据恢复软件,它们扫描了整个磁盘表面,最后还给你一堆文件名缺失、内容残缺的“僵尸文件”。那一刻你学到了一个残酷的教训:原来保存了不等于安全,存进去了不等于以后都能读出来。
FAT32的问题,不在于它存储数据的能力不行。而在于它没有校验机制。它把数据写进去,就假定数据是对的。如果某个扇区的某个比特因为电磁干扰、介质老化、或者写操作时的一个电压波动,悄悄地从0变成了1,FAT32毫不知情。它没有校验码,没有快照,没有写时复制。它是一个“信任一切”的文件系统。
后来你换成了ZFS,或者至少是NTFS带日志的版本。你发现一个新的世界:每一次写入都有校验和,每一条元数据都有多个副本,系统定期静默扫描所有数据块,一旦发现某个块校验不匹配,自动从冗余副本里修复。你拔掉电源再插上,数据毫发无损。
现在,请把你的财富系统,想象成一个文件系统。
你在过去几年里建立的这个系统,是FAT32,还是ZFS?
如果你符合以下几个特征中的任意两条,你的财富系统就是FAT32级别——在平稳运行的时候看起来一切都好,一旦遇到真正的冲击,就会静默损坏,甚至全盘崩溃:
- 你的主要资产全部放在同一类标的里(比如全是A股,或者全是科技股);
- 你从没做过资产之间的“校验”——你不知道你的股票仓位和债券仓位之间是什么关系,谁在保护谁;
- 你没有应急储备金,或者应急金和投资账户混在一起,随时可以被行情感冒挪用;
- 你没有保险,或者保险买得极其随意,像是在代码里随便写了个
try-catch然后让异常空飘; - 你从来没有做过“如果明天大盘跌停且你同时失业”的推演。
一个ZFS级别的财富系统,应该是这样的:
第一,写时复制——永远不要在原始数据上直接修改。当你想要尝试一个新策略的时候,不要一上来就把全部身家切过去。开一个“快照”——用小资金建立观察仓,记录下你切换策略时的全部上下文(为什么要换、预期是什么、观测什么指标),然后让这个快照独立运行一段时间。如果效果不好,回滚到快照之前的主版本,你的主体资产毫发无损。
第二,校验和——每一类资产都要有独立的安全验证。你的股票仓位应该有一个最大回撤阈值,触发即执行,没有任何商量的余地。你的债券仓位应该有一个最低持有到期的比例,不管股市多火爆都不能动。你的应急储备金应该有一个绝对不跌破的金额底线,和你的投资账户物理隔离。这三个校验位,就是你的财富文件系统的元数据。如果任何一个校验失败,系统应该自动触发修复流程,而不是假装没看到。
第三,静默数据损坏检测——定期做全盘快照和校验扫描。每个季度,做一次全量的资产盘点。看你的各类资产比例是否偏离了预设的目标,看你的总资产净值是否连续两个季度停滞或下降,看你的被动收入是否覆盖了越来越多的生活支出比例。这个动作,ZFS叫scrub。你不需要每天做,但你不能从来不做。一个从来不做scrub的ZFS池,和FAT32没有区别。
第四,冗余副本——不要把鸡蛋放在同一个篮子里,也不要把篮子放在同一辆卡车上。你有股票,也要有债券。你有A股,也要有一部分海外资产。你有金融资产,也要有一部分实物资产(比如自住房)。你有主动收入的工资卡,也要开始构建一条被动收入的管道——股息、租金、版权、或者一个不需要你全职投入的副业。冗余不是浪费,冗余是当你的主副本被单粒子打穿时,唯一能救你命的东西。
单粒子翻转:承认亏损是宇宙射线,不是你的Bug
在航天工程里,有一个让所有硬件工程师头痛的问题,叫单粒子翻转。
地球外太空充斥着各种高能粒子——宇宙射线、太阳风带来的质子、被地球磁场捕获的电子。当这些粒子以接近光速穿过一颗运行中的芯片时,有可能正好击中某个存储单元。这个单元的电荷状态被瞬间改变——原来存0的变成了1,原来存1的变成了0。整个芯片没有任何物理损伤,所有电路都在正常工作,但内存里的某个比特,悄悄地翻转了。
这就是为什么航天级的CPU,从来不用普通的消费级芯片。它们用的是专门设计的抗辐射芯片,制程更大、电压更高、关键模块三模冗余——同一份数据存三份,表决器取多数。即使这样,单粒子翻转仍然不可能被完全消除。航天工程师的哲学从来不是“防止所有翻转”,而是“翻转必然发生,我设计一个翻转后还能继续跑的系统”。
你在股市里每一次意想不到的亏损,就是一次单粒子翻转。
不是你的分析框架有致命缺陷,不是你的策略一无是处,不是你的智商被人碾压。只是有一束宇宙射线,在你完全没有防备的时候,击穿了你的持仓。它可能是一个突然的宏观政策变化,可能是一个谁都没想到的行业利空,可能是大洋彼岸某家你听都没听过的对冲基金爆仓了,连带着把你持有的一只完全无关的股票也拖下水。
这些东西,就像太空中的高能粒子。你不可能预测每一颗粒子的轨迹。你不可能给每一只黑天鹅提前写好应急预案。你能做的,不是追求“永远不被击中”,而是“被击中之后,还能继续运行”。
这意味着:
第一,不要把全部计算任务压在单一核心上。分散投资不是承认自己无能,是承认宇宙射线客观存在。单粒子翻转是必然会发生的,分散是唯一能确保翻转后整个系统不发生致命错误的办法。
第二,设计看门狗。当某一个模块连续亏损,超过了预设的阈值,看门狗自动把它从系统中隔离出去——暂停该策略、清仓该标的、或者至少把你的手绑起来不许再加仓。看门狗不是承认策略写错了,而是承认任何策略都有可能被宇宙射线击穿。看门狗是你最后的保护,它在你的情绪接管大脑之前,替你执行了理性决策。
第三,设计回滚机制。当系统因为某种原因崩溃——比如你违反了自己的纪律,追高重仓,结果一个月亏掉了半年的利润——不要继续在崩溃的状态下试图“扳回来”。停下来。承认当前状态已经不可信。回到你上一份稳定的资产配置快照,从那个干净的状态重新启动。你可以丢了半年的利润,但你不能丢掉继续留在牌桌上的资格。
而最重要的,是第四点:
不要试图屏蔽所有粒子。
很多工程师在经历了一两次随机性惩罚之后,会走入另一个极端——他们试图设计一个“没有任何亏损可能”的策略。他们把止损线设到极小,把条件加到极多,试图用极度精确的参数把每一次下跌都过滤掉。但这不是在做投资,这是在太空中建一个完全没有辐射的真空室。你确实屏蔽了亏损的可能性,但你也屏蔽了收益的可能性。而且最终,总有一颗粒子能量大到穿过你所有的屏蔽层。
航天工程的智慧是:接受单粒子翻转,然后设计冗余。投资的智慧是:接受亏损,然后设计容错。
你亏损的那笔交易,不是你的Bug。它是宇宙射线。你唯一需要反思的,不是“为什么被击中”,而是“为什么被击中一次就差点挂了”。如果你的系统因为一笔亏损就全盘崩溃,那问题不在那笔亏损,在你的系统没有冗余。
告别“上帝模式”:你只是市场中的一个线程
我们回到这一章最底层的命题。
你在过去的投资生涯里,一直在试图扮演上帝。你以为你是市场的编译器开发者——你定义了变量,规定了逻辑,设定了边界条件,然后按下运行键,期待输出符合预期。你觉得你站在系统之外,俯视着K线的起伏,随时可以暂停、调试、修正。
但你不是上帝。你甚至不是编译器。
你只是这个系统里的一个线程。
市场是一个有上亿线程同时在跑的超级计算机。每个线程都在做自己的操作——买入、卖出、持有、观望。每个线程都在根据它收到的信息做决策,而它收到的信息里,包含其他线程的操作结果。你的每一次买卖,都在改变其他线程收到的输入数据。其他线程的反应,又会在未来的某个时刻变成你的输入。
在这个系统里,没有任何一个线程能看见全貌。没有任何一个线程能控制全局调度。你以为你在执行一个确定性的算法,但实际上你只是在一个永远在变化的、分布式、无全局时钟、消息延迟不确定的混沌系统里,尽力响应事件。
承认这一点,不是自我贬低。承认这一点,是解开了你给自己绑上的枷锁。
你不需要再为每一次亏损找出一个确定的“我错在哪里”的答案,因为有些亏损的发生,不是因为“你错了”,而是因为“你是一个线程,你看不到其他线程在做什么”。
你不需要再为“为什么别人赚钱而我亏钱”而自我折磨,因为线程之间没有公平可言。有些线程运气好,收到了先到的消息;有些线程内存大,扛得住延迟;有些线程跑在内核态,有特权访问——你不是它们,它们的策略你复制不了。
你不需要再设计一个能预判所有行情的“上帝策略”,因为上帝视角根本不存在。你能设计的,是一个能在各种行情里活下去、并且长期期望为正的“线程策略”——你守住自己的时间片,管理好自己的栈空间,响应自己能响应的事件,放弃那些你根本不可能处理的信号。
当你不再假装自己是上帝,你才能真正开始像一个优秀工程师那样工作:不是去控制你控制不了的东西,而是去设计一套能在不可控环境中稳健运行的系统。
这才是投资中最根本的认知重构。
在下一章,我们将正式动工。我会用一整章的篇幅,教你如何设计这套系统的架构——从哪里开始分层,怎么定义模块之间的通信协议,如何设置权限隔离,以及如何防止一个模块的崩溃污染整个内核。
你将不再是那个在K线前焦虑地来回改参数的“散户”。你将成为一个财富操作系统的架构师。
而你的系统,将从一个简单的、单体的、容错性为零的小程序,变成一套分层的、去耦的、带校验和冗余的、能够在各种极端行情下自我修复的生产级系统。
架构设计的第一步,是画出分层图。我们第二章见。