资讯动态

Trading-as-Git:用版本管理思想构建本地量化Agent风控闭环

发布时间:2026/10/6 6:30:47 来源:尧图企业网站定制
如果你也曾在实盘账户里尝到过“手痒”和“不服输”的滋味那你看到 OpenAlice 这个名字时应该会跟我一样好奇。OpenAlice 是一个把 Trading-as-Git 作为设计哲学的开源本地量化 Agent 框架所有策略、参数、风控规则都放进 Git 仓库里管理Agent 在本地负责读取行情、生成信号、执行交易而每一次改参数、每一次上线、每一次回滚都像提交代码一样有迹可循。这套思路真正解决的不是“预测得更准”而是“亏得有原因、亏得有底线、亏完还能复盘到具体某一笔”。这篇文章适合在实盘里吃过亏的交易者、想搭量化框架的开发工程师也适合正在研究本地 Agent 架构、想搞清楚风控闭环该落在哪个环节的产品和技术同学。1. 为什么是 Trading-as-Git把交易系统当成代码库治理1.1 盲目实盘暴仓的三个典型病灶我观察过不少从主观交易转向量化的人最先被淘汰的往往不是策略不行而是交易行为不可控。第一个病灶是“没有证据”。下单的时候凭盘感等亏损了再回看 K 线怎么都记不起当时触发信号的依据是什么。第二个病灶是“没有熔断”。浮亏 2% 时不走3% 时想扛一扛5% 时已经不敢停最后账户被一次极端行情带走。第三个病灶是“没有回滚”。程序改了某个参数后连亏三笔想回到原来的行为却只记得大概改过哪个变量完全无法复现。这三个问题放到软件开发里就是典型的“没有版本管理、没有自动化测试、没有部署回滚”。Git 早就把代码工程这条路走通了那交易系统为什么不能用同一套方法Trading-as-Git 的核心就是把策略代码、参数配置、风控规则、甚至数据版本都当成仓库里的资产让每一次行为变更都有 commit、有 diff、有 tag。你不需要赌“这次一定对”只需要保证“错了能定位、能还原”。1.2 Trading-as-Git 到底在说哪件事Trading-as-Git 不是一个具体软件而是 OpenAlice 架构的第一性原则。它把软件工程里已经成熟的 Git 工作流映射到量化交易的每个环节策略因子对应代码仓库里的factors/目录每个因子有独立测试策略参数和风控阈值对应configs/risk.yaml必须有提交记录某一版本的策略上线对应打 tag比如v0.3.0-live想试新思路对应开分支experiment/xxx先跑回测再决定要不要合并上线后发现数据源有问题对应git revert把交易行为退回到上一个稳定版本。这个比喻听起来很简单但它改变了 Agent 的工作方式。传统的量化 Agent 是“策略装在脑子里执行靠手脚”Trading-as-Git 的 Agent 是“策略存在仓库里执行靠一个严格遵循仓库当前状态的进程”。Agent 不拥有决策权它只执行仓库里已经被验证过的规则。想让 Agent 改变行为第一步不是去改代码而是先提交一个 commit再走验证流程。这种做法天然地把“冲动交易”挡在了系统外面。1.3 本地量化 Agent为什么不在云端跑可能有人会问既然要自动化为什么 OpenAlice 坚持本地部署而不是放到云端服务器上跑我拆完这个项目后觉得有三点是刻意设计的。第一是延迟。本地部署可以让行情数据的接收、信号计算、订单发送都在一个低延迟网络环境内完成避免由于公网波动导致“信号出来了指令却迟到”的后果。第二是隐私与安全。交易所 API key、持仓数据、策略细节都只留在本机不经过任何第三方中转。第三是可干预性。本地 Agent 可以直接被停止可以一键断网可以手动撤单这对还在实盘初期、需要时刻保留人工干预能力的人非常重要。当然本地量化不是没有缺点机器宕机、断电、网络中断都需要额外预案。这个我会在后面的实操部分展开讲。整体上OpenAlice 选择本地作为默认运行环境更多是为了“风控闭环不依赖外部资源”这个原则。2. OpenAlice 的本地量化 Agent 架构拆解2.1 数据接入层先有可靠数据才有可信策略量化系统里最容易被忽略的就是数据层。OpenAlice 把数据接入当作独立模块而不是策略脚本里的一个函数。它由定时任务从行情源拉取历史 K 线、实时 tick、成交明细和部分财务数据经过清洗后统一落成 parquet 或 SQLite 格式并打上data_version。每个策略 commit 会记录它依赖的数据版本回测时用相同的数据版本避免“同一个策略两次回测结果不一致”。这一层能做到什么程度我见过不少人在本地搭环境时直接把交易所 API 下载的数据随便存成 CSV时间戳混着时区除权没有处理导致信号在回测中看起来很漂亮实盘却一塌糊涂。OpenAlice 的做法是用统一的 UTC 毫秒时间戳、统一的字段命名数据写入前做重复值和缺失值检查并生成数据完整性校验和。这个设计对新手可能觉得“过度工程”但当你要回放某个异常行情日、复盘那几分钟到底发生了什么时版本化数据是唯一能依靠的现场。2.2 策略仓库Agent 的行为快照OpenAlice 的默认仓库结构并不复杂但每层都有明确边界。我整理过这样一个最小目录strategies/ factors/ # 因子定义 entry_models/ # 入场模型 exit_models/ # 出场模型 configs/ strategy.yaml # 策略参数 risk.yaml # 风控参数 execution.yaml # 下单参数 data/ snapshot/ # 不可变数据快照 logs/ trades/ # 交易日志 tests/ backtest/ # 回测用例其中最关键的是configs/risk.yaml不属于策略工程师个人所有它在 Git 仓库里需要单独的权限保护。因为 OpenAlice 的风控闭环有一个前提决策 Agent 不能自己修改限制自己的规则。如果同一个进程既能改策略又能改风控那风控就只是摆设。策略仓库通过分支权限、commit 签名、合并审核等方式让风控参数的变更像生产环境配置一样被严格管理。2.3 Agent 执行引擎信号如何变成订单OpenAlice 的执行引擎是一个事件循环接收到新的行情事件把它交给策略模块计算信号信号进入风控模块校验校验通过后再交给执行模块发送订单。这里的 Agent 与“harness”有一个容易混淆的点harness 通常只是调度的壳负责拉起进程、喂数据、收集结果而 Agent 是能根据状态做出决策的单元。OpenAlice 里Agent 的“智能”完全来自仓库中的策略版本不为某一个模型加戏真正干活的是风控模块的硬约束。执行引擎还有一个容易被忽略的细节订单幂等。每次生成订单时Agent 会为订单生成一个全局唯一的client_order_id并在本地数据库中记录。如果网络超时Agent 不会盲目重发同一笔订单而是先查询这个订单的状态再决定是否重发。这个设计避免了最常见的“网卡一下重复下单”事故。多个策略同时运行时执行引擎还会用一个共享仓位管理器汇总总仓位避免 A 策略开了 2 个 BTC、B 策略又开 2 个 BTC最终超出账户总仓位上限。2.4 本地 Agent 的运行沙箱与进程隔离Agent 跑在本地不意味着它可以为所欲为。OpenAlice 会为策略代码提供受限运行环境文件系统只读、网络访问只允许白名单域名、进程资源占用有限。策略脚本里哪怕有人故意写一个死循环也不会拖垮整个交易系统。这种“沙箱”思想在 Agent 安全的话题里经常被讨论但真正落实到本地量化 Agent 的项目其实不多。风控模块则单独跑在一个独立进程中通过本地 IPC 或消息队列接收交易请求和账户状态。这样即便策略进程崩溃风控进程仍然可以继续监控账户并在触发熔断条件时直接发送止损指令。这就是为什么说 OpenAlice 的风控闭环不是功能插件而是独立于 Agent 的守护层。3. 风控闭环四道闸门把暴仓挡在门外3.1 第一道闸门交易前检查任何订单在发出前都要先过一遍 pre-trade risk。OpenAlice 的configs/risk.yaml里会有类似这样的配置risk: max_position_size: 0.2 # 单币资金占比上限 max_open_positions: 5 # 最大同时持仓数 risk_per_trade: 0.01 # 单笔最大风险 1% max_leverage: 3 # 最大杠杆 forbidden_symbols: [] min_liquidity_threshold: 5000 # 5s 深度阈值这里有个需要理解的计算单笔最大风险 1% 并不是说这笔交易最多亏损本金的 1%而是用止损距离反推仓位。假设账户本金 10 万 USDT风险预算 1000 USDT策略在 100000 的价格买入止损设在 99000止损距离 1000 USDT。那么可开仓数量就是1000 / 1000 1也就是 1 个 BTC。如果止损距离是 200 USDT则可以买 5 个。这种仓位计算方式比“感觉仓位轻一点”可靠得多因为它把亏损固定住了。如果订单不能通过这些检查Agent 会记录拒绝原因并发送告警而不是直接强行下单。我见过很多系统把 pre-trade 做成 “if 风控 not passed then pass anyway” 的摆设OpenAlice 的做法是风控拒绝的订单永远无法到达交易所这是物理层面的约束。3.2 第二道闸门实时监控和动态熔断pre-trade 再严格也无法覆盖市场瞬间反转。OpenAlice 的实时监控服务会以固定频率读取账户权益、持仓、浮盈浮亏并计算两类关键指标日内回撤和整体回撤。日内回撤指今天从最高权益到当前权益的跌幅整体回撤指从历史最高权益到当前权益的跌幅。熔断规则可以设置成阶梯式回撤触发线动作日内回撤 3%告警禁止新开仓日内回撤 5%自动减掉一半仓位日内回撤 8%全部平仓关闭当天交易整体回撤 12%锁定所有策略等待人工复核为什么用动态回撤而不是固定盈利回撤因为账户权益会随市场波动如果固定“亏损 5% 就停”在权益已经创新高之后很容易被正常的波动扫出局。动态回撤永远锚定“当前周期的最高点”能更准确反映账户真实的回撤风险。这个模块是独立进程即使策略进程因 bug 卡死熔断逻辑依然可以生效。3.3 第三道闸门事后审计与 Git 回滚交易发生之后OpenAlice 会把每一笔订单、每一次信号、每一次风控拒绝都写进结构化的审计日志。日志字段大约包括策略 commit hash、参数版本、数据版本、信号详情、下单时间、成交价格、滑点、延迟等。这意味着复盘一个亏损日时你可以像读代码历史一样把当天的所有决策链还原出来。如果发现某次异常亏损源于一个糟糕的参数改动或者一个错误的数据版本就可以直接回滚。回滚有两种用法一种是git revert commit把代码状态退回去另一种是用git checkout tag临时切到验证过的稳定版本。关键是logs/trades里记录的 commit hash 能让你知道“当前跑的是哪一版代码”而不是靠记忆猜。3.4 第四道闸门人工干预通道与紧急回调再完善的风控闭环都要给“人”留一个最高优先级入口。OpenAlice 默认设计了一键暂停、一键清仓、一键恢复三个命令。暂停是停止开新仓已持仓继续按策略管理清仓是把所有仓位按市价单平掉恢复是重新载入当前仓库版本继续执行。这三个命令都会记录到审计日志并且需要二次确认。还有一个容易被忽略的细节当策略进程和风控进程同时发现冲突时以风控进程的指令为准。比如策略认为应该继续加仓但风控发现整体回撤已经超过阈值那么风控进程会直接平仓并记录一条 reason。人工干预通道就是为了解决“机器完全自动时谁来按最后那个急停按钮”的问题。4. 实操从零把一个策略接进 OpenAlice4.1 环境准备与安装先说运行环境。OpenAlice 的核心执行引擎当前默认支持 Python 3.10同时我会建议把 Rust 工具链装上因为部分数据解析和事件循环模块是用 Rust 编译的没有工具链也可以从预编译 wheel 安装。安装本身不复杂git clone openalice_repo_url cd openalice python -m venv .venv source .venv/bin/activate pip install -r requirements.txt python openalice init --name risklab初始化命令会创建一个包含上面目录结构的 Git 仓库并生成默认配置文件。接下来就按照“先建仓库再给系统录入交易所凭据”的顺序。交易所 API key 我建议只放在本地.env文件里并且设置读取权限为当前用户可读写千万不要提交到 Git否则一旦仓库泄露等于把风控大门钥匙交出去了。4.2 把你的第一版策略写成配置OpenAlice 的策略不一定要写一大段 Python 代码它允许先用声明式 YAML 定义策略让新手也能跑通。一个最简单的双均线交叉策略可以是这样strategy: name: ma_cross timeframe: 1h entry: rule: crossover fast_window: 10 slow_window: 30 exit: rule: crossunder risk: stop_loss_atr_multiplier: 2.0 take_profit_atr_multiplier: 3.0把文件放到configs/strategy.yaml然后执行git add . git commit -m feat: add ma_cross v1。这一步的作用不是“存档”而是让策略的状态第一次成为可回滚的快照。之后每一次改动都遵循同样的流程开分支、改配置、跑回测、合并、打 tag。4.3 用 Git 工作流管理策略迭代我强烈建议新手从一上手就养成“实验分支”的习惯。想试一个新参数组合不是直接改main分支的配置而是git checkout -b experiment/ma_cross_trail # 修改 configs/strategy.yaml git commit -m experiment: use trailing stop openalice backtest --branch experiment/ma_cross_trail回测通过后再回到main合并并打上下一个版本的 tag。这里有个反直觉的地方打 tag 不是只在“上线赚钱”时做而是在“准备接受实盘验证”时做。比如v0.1.0-live可能是一个亏损版本但它仍然是一个里程碑因为它记录了“这一次尝试的全部状态”。亏损版本同样值得保存否则你无法在事后准确回答“当时为什么亏这么多”。4.4 回测、模拟盘、实盘的三段式验证OpenAlice 把验证过程拆成三段每一段必须通过上一段的检查回测用历史数据验证策略输出收益率、最大回撤、夏普比率和交易频次模拟盘接入交易所的 testnet 或 paper trading用小金额或模拟资金跑 2~4 周确认订单执行、风控触发路径都正常实盘小资金只有在模拟盘没有出现风控漏触发的情况下才开始用很小比例的本金实盘并开启所有熔断规则。这个过程真的会过滤掉大量“看起来很好、跑起来就废”的策略。我有一次把一个回测年化很好的策略丢进模拟盘结果因为本地环境时区问题每天第一根 K 线的入场信号都晚了几秒模拟盘里连续一周都是微小亏损。要不是有模拟盘这一段实盘账户早就替我交了学费。5. 常见问题与避坑手册5.1 时间戳时区不一致导致信号错位本地量化最常见也最坑的问题就是行情数据里同时存在 UTC 和本地时间。比如数据库里用本地时区但交易所返回的时间戳是 UTC两个时间不校准策略会在错误的 K 线上计算信号回测结果和实盘行为完全对不上。解决办法只有一个系统内部统一用 UTC 毫秒时间戳所有展示层再转换成本地时间。数据写入前加检查发现时间偏移不一致就拒绝入库而不是静默容忍。5.2 回测不考虑手续费和滑点实盘必然变脸回测里手续费设成零、滑点设成零这属于给自己制造惊喜。OpenAlice 的默认回测配置里会按交易对参数注入一个保守成本模型比如单边手续费 0.05%滑点按最近 1 分钟平均买卖价差的 50% 估算。如果你的策略是高频小赚、每天几十笔手续费和滑点加在一起会直接吃掉利润。我用一个简单的算法验证假设每天交易 20 次每次单边成本 0.05%一天来回就是 2% 的成本一个月 22 个交易日就是 44%任何毛利低于这个成本线的策略都活不下去。所以只看毛利就上实盘的时代可以结束了。5.3 Agent 重复下单与订单幂等网络超时是最难排查的故障之一。请求发出后交易所可能已经成交但客户端没收到回执。如果不做幂等Agent 会再发一个相同的订单结果造成双倍仓位。OpenAlice 的解决办法是每笔订单生成唯一的client_order_id并在本地数据库中记录状态。发送前先查本地状态如果已经存在且状态不明就向交易所查询后再决定下一步。这是一个非常小却保命的细节。5.4 风控规则被策略绕过如果风控模块和策略模块位于同一个进程、同一个权限空间那么策略代码完全可以在某个分支里把风控阈值改掉。这不是恶意可能是工程师为了方便调试留下的后门。OpenAlice 把风控模块独立成另一个进程并且配置文件对策略进程只读。策略进程无法动态修改风控参数只能通过仓库的变更审核流程来调整。这就是我前面说的“做题的人不能自己改评分标准”。5.5 手动干预之后Agent 状态没有同步有些用户看到账户浮盈很高忍不住手动平了一部分仓但 Agent 内部的持仓状态还是旧的结果下一次风控检查算出来的仓位比例、回撤数字全部失真甚至触发错误操作。正确的做法是任何人工干预之后先执行一次openalice sync --from-exchange让 Agent 从交易所重新拉取最新持仓和权益再继续自动运行。别跳过这一步否则系统会基于错误状态做决策。5.6 数据源故障时Agent 必须进入降级模式本地量化不是只要机器在跑就万事大吉行情源可能断流、交易所 API 可能超时。OpenAlice 的做法是在 Agent 中加入“降级模式”感知如果连续 N 个心跳周期没有收到行情就停止开新仓已持仓保持不动如果行情恢复再重新评估持仓和风控状态。最忌讳的是数据断了策略还按最后一块数据强行出信号那基本等于蒙眼下单。注意第一次实盘前一定确认configs/risk.yaml里的熔断阈值是你自己在冷静状态下写下来的而不是盘中临时调的。盘中调风控等于给暴仓开门。我这里最后再多说一句把 Trading-as-Git 当成口号很容易真正难的是接受“Agent 只是仓库状态的执行者”这个设定。我在本地跑 OpenAlice 大半年最大的体会不是它帮我多赚了多少而是它让我每一笔亏损都能被解释、被回放、被避免。朋友来找我看策略我第一句话永远是先给我看你的 Git 提交历史再谈你的收益曲线。能做到这一点的系统即便不完美至少不会在暴仓时让你连自己是怎么亏的都不知道。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑