4.7 版本控制:你的投资体系必须支持回滚

📅 2026/7/12 1:19:58
4.7 版本控制:你的投资体系必须支持回滚
2021年一个在蚂蚁做基础设施的工程师在GitHub上开源了一个他用业余时间写的量化交易框架。项目发布的那天他写了很长的README其中有一段话我记得很清楚“这个框架最开始只是我自己用来跑策略回测的小工具。过去三年里我在这个框架上迭代了上百个版本大部分版本的Sharpe Ratio最后都归于平庸少部分版本在生产环境里跑过一段时间后也被我回滚了。如果没有Git我根本记不住自己在哪个版本上赚了钱、在哪个版本上亏了钱、以及为什么把那个赚钱的版本改成了后来亏钱的版本。是Git的commit log而不是我的记忆保存了我这三年所有的认知迭代。”他的这段话说出了投资中最容易被忽视的一个事实你的投资策略是一个软件项目。它有需求变更、有功能迭代、有Bug修复、有性能优化也必然有发布失败和紧急回滚。但绝大多数散户对待自己的投资策略的方式和那些不写注释、不做版本管理、直接在服务器上改代码的“裸奔开发”完全一样——他们每一次拍脑袋做出的策略调整都是一次没有commit message的强制推送覆盖掉之前可能运行良好的逻辑而且一旦发现新版本有问题根本不知道怎么恢复到上一个能用的版本。Commit规范每一笔交易都应该有它的Hash值Git的commit message有一个约定俗成的格式你一定见过第一行是简短的摘要说明这次提交做了什么空一行之后是详细的变更说明解释为什么要做这个变更、变更的影响范围是什么、以及任何和这个变更相关的上下文信息。一个写得好的commit message能让三个月后的你自己或者你的同事在翻阅提交历史时不用重新看一遍代码就能明白当时发生了什么。你的投资日志应该遵循完全相同的规范。每次买入操作就是一次commit。commit message的摘要可以简单到一行“建仓XX公司仓位5%类型长线触发条件季度财报营收超预期且估值处于历史低位。”摘要下面追加的详细说明里写下你买入的具体依据——是哪一份财报的哪个数字让你做出了这个判断你对它的未来预期是什么你为它预设的止损条件和持有期限是什么。每次卖出操作也是一次commit。摘要写“清仓XX公司原因为触及15%止损线”或者“减仓XX公司原因为季度再平衡仓位从12%恢复至目标8%”。详细说明里写下这次卖出的复盘你买入时的逻辑有没有被验证如果亏损了亏损的原因是逻辑错误还是随机性惩罚如果是逻辑错误你从这笔交易里学到了什么需要写入下一条断言规则的东西这些commit串起来就是你投资生涯里最诚实的一部编年史。它不会骗你因为每一个commit都是在交易发生的当天写下来的它保留了你当时所有真实的判断和情绪不会被后来的结果污染。除了常规的commit你还需要Tag。Git里的Tag是用来标记重要里程碑的——比如发布了一个稳定版本或者完成了一次重大重构。你的投资Tag应该标记在那些你对自己的系统做了结构性变更的时刻。比如你第一次读完这个系列文章之后按照第二章的架构重新设计了自己的资产配置体系那次大改就应该打一个Tagv2.0-微内核三层架构上线。半年后你在实盘中发现债券配置比例需要从20%调整到25%这个调整经过完整的沙箱测试和季度评审后正式纳入体系你可以打一个Tagv2.1-债券比例调整至25%。再过一年你经历了一次完整的牛熊周期从中学到了三条新的断言规则并写入了你的投资日志打Tagv3.0-完整牛熊迭代。Tag的意义不是给你自己看的一个形式化的标签而是当你未来某一天迷失在市场噪声里的时候你可以沿着Tag列表快速回溯看到自己是从哪里出发的经过了哪些重要的转折点以及当前这个版本是在哪个稳定版本的基础上一步步迭代过来的。分支策略Master是你的命Dev是你的实验室任何一个成熟的软件项目都不会直接在Master分支上开发新功能。Master分支只用来跑已经验证过的稳定版本任何新的实验性功能都在Dev分支上进行等充分测试、没有明显Bug之后再合并回Master。你的钱也应该分成Master和Dev两个分支来管理。Master分支是你的核心仓位。它执行的是你经过季度架构评审确认的长期资产配置策略——沪深300、中证500、债券、QDII、黄金每季度做一次再平衡其他时间不动。Master分支上的资金占据你总资产的绝对主体至少80%以上。它不接受任何临时的、冲动的、未经季度评审批准的变更。它不是用来让你证明自己有多聪明的它是用来让你在市场中长期活下来的。Master分支上的策略不需要惊艳它只需要稳定。Dev分支是你的实验账户。就是我们在第二章第八节和第三章第六节反复提到过的那个沙箱。你在这个分支里尝试各种新想法——一个新的行业轮动策略、一套基于你自己技术背景挖掘出的科技股筛选逻辑、一个你从某篇论文里看来的波动率套利思路。Dev分支的资金上限是你总资产的5%到10%亏完就砍掉重建亏不完就继续跑但永远不能因为你“觉得这次把握特别大”就突破上限。Dev分支和Master分支之间有一个严格的合并流程。你在Dev上跑满至少四个季度之后把它的业绩和Master做对比。如果Dev在四个季度里稳定跑赢了Master并且你在运行这个策略期间的心理状态和操作纪律都满足自己的标准那么你可以启动一次合并流程。合并不是简单地把Dev的策略全量替换Master而是在一次正式的季度架构评审上把Dev策略中经过验证的那些要素——比如某个选股因子、某个择时信号——以受控的方式集成进Master的配置里。合并之后立刻打一个Tag记录下这次架构变更的完整决策链条。如果Dev在四个季度里没有跑赢Master或者虽然跑赢了但你在执行过程中发现自己频繁违反规则、情绪波动过大那就不合并。把Dev清掉重新在下一个季度开一个新的实验。回滚机制当你迷失的时候回到上一个稳定版本运维线上系统时最让人安心的是什么不是你对自己的代码绝对有信心——任何有经验的工程师都不会对自己写的代码绝对有信心。最让人安心的是你知道如果新版本出了问题你只需要一条命令就能回滚到上一个稳定版本服务恢复用户无感知。这个回滚能力不是锦上添花它是你必须在上线之前就准备好的保命绳索。你的投资体系也必须有回滚能力。什么时候触发回滚我给你一个明确的硬条件当你在Dev分支上尝试的新策略连续三个月产生负收益而且这个负收益不是因为市场整体下跌——你可以用Dev的收益率减去同期Master的收益率看超额收益是否为负——那就触发回滚。回滚操作不是去调试那个亏钱的策略。不要试图在亏损中进行策略优化。当你正处于连续亏损中的时候你的心态已经不适合做任何技术性的判断了。你会想把止损调宽一点再试一次你会想在参数上做微调然后重新上线你会想“已经亏了这么多了说不定马上要反转了”。所有这些想法都是你那台已经进入内核恐慌的大脑在给自己找继续留在赌桌上的借口。回滚操作只有一步把Dev分支的全部仓位清掉把资金全部转回Master分支。Master分支上的策略是什么是你已经被历史验证过、经历过至少一轮完整牛熊、在多个mock场景下通过单元测试的那套策略。在最坏的情况下它可能是你刚开始做投资时用的那个最笨的策略——每个月定投沪深300其他什么都不做。没关系。这个“最笨”的策略只要它能让你在市场里活下去它就是一个合格的稳定版本。你回滚之后要做的事情不是立刻开始设计下一个新策略。回滚之后的第一件事是给自己至少一个季度的冷静期。在这个季度里你把Dev分支上的钱老老实实放在Master里只做定期再平衡不主动开任何新仓位。你利用这个季度的时间重新读一遍你的投资日志重新审视你那三个月亏损期间写的commit记录在心态完全恢复之后再做根因分析。如果你发现自己每次尝试新策略都以连续亏损收场那可能不是策略的问题是你的Dev分支实验方法论有问题——你每次都是在市场最热的时候开新实验在市场最冷的时候被迫关闭你的实验时序本身就是反向的。这个发现本身就是回滚机制给你带来的最有价值的认知。你不需要永远在Master分支上苟着。你是一个工程师你的天性就是探索、迭代、优化。回滚不是让你放弃探索是让你在探索走进死胡同的时候有一条安全的退路可以回到起点整理好行囊再重新出发。Git从来不阻止你创建新的分支它只是在你搞砸的时候给你一个回到稳定版本的选择。到这里第四章全部结束。从GDB模式的单步执行到Crash Dump的内核转储到堆栈回溯的四层调用栈到断言机制的不可绕过性到二分法排查的Bug定位到单元测试的Mock注入和覆盖率再到今天这一节的版本控制和回滚——我们用七节内容把你从亏损后的茫然无措武装成了一个拥有完整调试工具链的投资工程师。你现在缺少的不是一个百战百胜的策略。你现在拥有的是更重要的东西当你的策略失败的时候你知道怎么复盘、怎么定位、怎么修复、以及怎么在修复不了的时候安全撤退。下一章我们要离开调试的世界进入一个全新的维度。市场不是一台安静的服务器它是一个巨大的噪声源。你每天接收到的价格波动99%是噪声只有1%是信号。怎么用你熟悉的信号处理理论设计一个能把噪声滤掉、把信号留下的滤波器——这是第五章要给你的全部内容。