直接切入主题:如果你做过实盘量化,大概率体会过那种净值曲线突然“跳水”的窒息感。策略在回测里漂亮得不行,上实盘却莫名暴仓,回头复盘时翻遍了日志也说不清哪一步出了问题。这种“盲目实盘”的真正问题,往往不在某一笔交易上,而是整个工作流缺少版本管理、缺少可追溯性、缺少一个强制的风控闭环。OpenAlice 正是围绕这个痛点做的设计:把交易当作代码来管理,把 Agent 当作团队里的分析员而不是独裁者,用一套本地化的“Trading-as-Git”架构,让量化过程的每一步都有提交记录、可回滚、可以被审计。
这篇文章我会从架构设计的角度拆解 OpenAlice 的思路,包括为什么它坚持本地 Agent、Git 语义如何映射到交易生命周期、风控闭环的工程实现方式,以及一套可以直接落地的最小复现方案。适合的人群是:已经有策略代码基础,试过把 LLM Agent 引入交易流程,但总觉得失控风险太高的人;也适合想把量化研究从“笔记本乱改”升级成工程化体系的人。
1. 为什么“盲目实盘”会爆仓:传统工作流的三个致命伤
在拆解 OpenAlice 之前,必须先厘清一个现实问题:大部分人做量化暴仓,不是死在策略逻辑上,而是死在工作流的缺陷上。
1.1 策略改一改,回测全白做
很多人的日常工作流是这样的:在 Jupyter Notebook 里加载数据,改一个参数,跑一段回测,看到收益变高了,就直接把同样的逻辑搬到实盘。中间没有记录“为什么改这个参数”,没有保存改动前后的对比结果,更没有一个正式的回测报告入库。等实盘运行一周后发现表现变差,想回退到上一个稳定版本时,发现代码已经改得面目全非,甚至自己都想不起来上一版到底用了哪个参数组合。
这类问题的本质是:策略代码和其他工程代码一样,必须有版本管理。但量化策略的版本管理比普通软件更复杂——因为“运行同一段代码”还需要依赖同一份数据、同一套特征计算逻辑、甚至同一个 Agent 的参数配置。如果这些都没有被版本化,那么“回测得过得去”和“实盘赚得到钱”之间就隔着一层永远无法复现的黑箱。
1.2 模型和数据之间没有契约
传统量化里,数据源是很容易被忽略的“脏东西”。同一个指标,用 pandas 算和用 NumPy 算可能结果不同;同一个因子,前复权价格和原始价格处理出来的信号完全不一样。更常见的是,你明明改了一版 Python 依赖库,回测时没注意版本变化,结果信号和原来对不上,而你想排查都无从下手。
OpenAlice 对此有一个很清晰的立场:数据和代码一样,是仓库里的一等公民。凡是进入策略计算过程的数据,都必须有确定性的寻址和校验信息。换句话说,一条数据记录对应的应当是“某个数据源、某个清洗脚本、某个时间戳”的组合,而不是一个随时可能被覆盖的 CSV 文件。
1.3 风控靠自觉,没有闭环
第三个致命伤,也是最常见的:风控是“靠人盯”的纪律,而不是“靠代码锁死”的机制。很多人的风控只是心里有个止损线,实盘时情绪一上来就违规加仓,甚至因为浮亏而扛单。就算有资金管理模块,也往往是开仓前计算一次仓位,之后就不再干预,不可能实时防止回撤扩大。
这背后是一个伦理学问题:在自动化交易场景里,Agent 的分析能力再强,也不该拥有自由的执行权。任何由 Agent 产生的交易建议,都必须经过一层独立于 Agent 的强约束风控层,没有例外。OpenAlice 的风控闭环,就是把“建议”和“执行”彻底拆开,让系统即便在无人值守的情况下,也能保证杠杆可控、仓位合规、止损强制执行。
2. OpenAlice 的顶层设计:Trading-as-Git 到底在解决什么问题
把“Git”这个思路引入交易,不是简单地在项目里跑一个git commit就算完事。Trading-as-Git 是一种系统设计哲学:交易领域的每一个重要环节,都像 Git 管理代码一样,具备变更可追溯、历史可回滚、协作可隔离的性质。
2.1 本地 Agent 而不是远程 API:延迟、私有、稳定
Quant Agent 为什么特别强调本地化?三个原因很实在。
第一是延迟。交易信号对时延敏感,尤其是 T+0 或高频场景,如果在中间隔了一层公共 API 的调用,请求排队和网络抖动都会直接影响执行时机。本地 Agent 可以直接读取行情快照,在同进程或同局域网内完成分析和建议生成,延迟可以压到微秒到毫秒级,而远程调用通常难以达到这个量级。
第二是私有性。策略本身就是资产,Agent 对话上下文里可能包含持仓、资金量、风险偏好等敏感信息。本地 Agent,尤其是在本地运行的推理框架,不需要把任何数据传到外部服务,从硬件层面保证了数据不出机房。
第三是稳定性。很多时候公共 API 的可用性无法由自己保证,一旦服务商限流或故障,策略的决策链就断了。本地 Agent 没有这个问题,它的运行只依赖本地算力和本地数据源。
2.2 Git 作为唯一事实来源
OpenAlice 把 Git 仓库设计为整个交易系统的“唯一事实来源”。这个说法听起来简单,做起来很有讲究。系统里所有的重要对象,都应当能在仓库里找到对应的“提交”:
- 策略代码的每次改动,对应一次提交;
- 一份市场数据的接入与清洗过程,对应提交元信息里的数据指纹;
- 一次 Agent 的完整思考与决策过程,对应一个提交信息或者一个附属的工单记录;
- 每一次风控拦截或放行,对应一条不可篡改的审计日志。
这个设计带来的直接好处是:当你想弄清“为什么今天会开这笔仓”,你只需要查看该时段的提交记录,就能还原当天使用的策略版本、模型权重和数据快照,整条链路完全可复现。
2.3 Agent 编排而不是单体脚本
很多人对“量化 Agent”的第一印象,是一个能直接跑策略、下指令的全能机器人。OpenAlice 恰恰相反:它采用多个 Agent 分工协作的设计,每个 Agent 只负责一种职责。
典型的分工包括:
- 策略 Agent:根据当前市场数据和用户需求,生成策略建议,例如“当前适合做多哪个标的、理由是什么、参考胜率是多少”。
- 风控 Agent:对策略建议执行独立的合规检查,负责仓位、止损、杠杆等约束,不关心建议是否高胜率,只关心是否满足底线规则。
- 执行 Agent:仅在风控放行后,生成标准化的订单指令,连接到券商接口或本地交易接口,完成实盘下单。
- 审计 Agent:阅读所有其他 Agent 的日志和提交记录,生成每日总结,并主动标记异常模式。
这种设计的核心逻辑是“最小权限原则”:策略 Agent 和风控 Agent 之间没有从属关系,它们共同向执行层提交一个被验证过的建议;执行层则像一个忠实但只认规则的机器人,只有收到带有风控签名的指令才动作。
3. 核心数据模型与版本化设计
把 Git 语义映射到交易,需要定义清楚映射关系。OpenAlice 的模型并不复杂,但每一步都经过设计考量。
3.1 策略版本:从 main 分支到 release 标签
策略研发流程可以完全借鉴软件工程的 Git Flow。你在main分支上开发新因子,在dev分支上跑回测,验证通过后合并到release标签,实盘系统只认带标签的提交。这样的一整套流程,让策略上线不再是一个模糊的“复制代码”动作,而是一个可追溯的发布事件。
具体语义可以这样约定:
- 分支名
feat/xxx:表示某个新策略特性在开发中。 - 标签
v1.2.0:表示这个策略版本已经通过验证,可以实盘。 - 每次回测运行,必须在仓库里生成一个
backtest记录,内容包括回测区间、参数组合、数据指纹、运行结果摘要。
如果实盘策略出了问题,回滚操作就是git checkout v1.2.0的等价物:你回到上一个稳定版本,重新构建环境,继续运行。整个过程不会把未验证的中间实验污染到实盘。
3.2 市场数据与指标结果:对象寻址与哈希校验
市场数据具有高频和组合性,不适合直接塞进文本文件做版本管理,但也不意味着数据不能在 Git 语义下被管理。OpenAlice 的做法是对数据对象做哈希寻址:把原始数据、清洗脚本版本、处理参数、日期范围作为输入,计算出一个稳定的哈希值作为数据对象的“地址”。系统运行时用这个地址去数据存储里取数据,而不是依赖临时文件路径。
这种设计带来的直接收益是:如果有人偷偷改了原始数据,或者用了不同版本的清洗脚本,计算出的哈希值就会变化,系统会在上游就把这种不一致暴露出来,而不是等到实盘亏钱才知道。
3.3 Agent 运行记录的提交语义:commit message 即交易日志
Git 的提交信息通常是给人看的摘要,OpenAlice 将这个能力扩展成了机器可解析的交易日志。每次 Agent 完成一轮分析,都会生成结构化的提交记录,里面包含:
- 当前市场环境的摘要;
- Agent 推荐的交易方向、目标仓位、预期盈亏比;
- 风控检查结果,包括是否通过、如果被拦截,拦截原因是什么;
- Agent 自己的置信度或参考依据。
这样的提交记录既可以给人读,也可以给审计 Agent 做自动审计。任何一天运行结束,你可以直接通过git log查看当天 Agent 的全部决策轨迹,而不需要翻散布在多个文件里的原始日志。
4. 风控闭环的工程实现
风控闭环是 OpenAlice 里我最看重的一块。坦白说,Agent 模型再聪明,也可能在极端行情下给出激进建议。风控闭环的作用不是让 Agent 变得更聪明,而是让系统在 Agent 犯错时,仍然能守住资金安全的底线。
4.1 三层风控:预执行校验、盘中护栏、事后审计
风控不能只做一次,必须要形成时间维度的三层闭环。
第一层是预执行校验。当策略 Agent 发出某个建仓建议后,风控 Agent 会立刻检查一系列硬性条件:当前总仓位暴露是否超过上限、单标的持仓占资产净值比例是否合规、计划使用的杠杆倍数是否在允许范围内。如果任何一条不合格,建议会被拒绝,拒绝原因会写进提交记录。
第二层是盘中护栏。即便预执行校验通过了,下单后也不能放任不管。OpenAlice 的盘中护栏会持续监控实际成交情况、持仓浮动盈亏和账户权益变化。如果权益回撤超过预设阈值,护栏会自动触发减仓或清仓操作,不需要任何 Agent 参与决策。
第三层是事后审计。每天收盘后,审计 Agent 会把当天的所有提交记录、风控拦截事件、实际交易执行明细放在一起交叉验证,输出一份“有没有哪个环节越权/出错”的结论。这份结论会进入第二天的决策上下文,形成一个反馈闭环。
4.2 关键风控参数与止损公式
风控参数没有万能值,但 OpenAlice 提供了一套默认建议,你可以根据自己的资金体量和偏好去调整。
| 参数项 | 默认建议 | 说明 |
|---|---|---|
| 单标的仓位上限 | 20% | 防止单票黑天鹅导致的集中暴仓 |
| 总杠杆倍数上限 | 2.0 | 默认不加杠杆,留足容错空间 |
| 单笔最大止损 | 2% | 单笔亏损达到该比例直接离场 |
| 日内最大回撤 | 5% | 触发后停止新开仓,只做减仓 |
| 账户最大回撤 | 15% | 触发后全部清仓,进入冷却期 |
| 冷却时间 | 24小时 | 防止冲动型连续操作 |
止损公式可以写成固定金额止损和移动止损两种。固定止损最简单:止损价 = 买入价 × (1 - 止损比例)。移动止损则跟随最高价移动:止损价 = 自持仓以来的最高收盘价 × (1 - 回撤比例)。实盘经验告诉我,移动止损在趋势行情中更适用,固定止损在震荡行情里更容易触发,两者搭配使用效果更好。
4.3 隔离执行:Agent 只有建议权,执行器才有决策权
风控闭环的底层原则是:Agent 永远不会直接接触交易接口。理论上,所有订单都必须由“执行器”统一发出,执行器的输入是一个已经通过风控校验的指令对象,而不是一段自然语言描述。
这个隔离不是说 Agent 不能生成交易想法,恰恰相反,Agent 可以大胆想、大胆分析,但分析结果必须先变成结构化的建议,再经过风控规则引擎的审批,最后才能转化为订单。这个流程里,风控规则不是辅助建议,而是强制的签名环节。没有有效签名的指令,执行器直接丢弃并记录日志。
这样即使某个 Agent 出现幻觉、被提示词注入或者单纯策略执行错误,它也最多只能生成一堆不会被执行的分析文本,无法对真实账户造成直接伤害。
5. 从零搭一个最小可复现的 OpenAlice 本地环境
很多人看了设计觉得不错,但不知道从哪里开始。下面我给出一个最小可复现的环境搭建方案,基于 Python,依赖尽量少,核心是跑通“策略 Agent 生成建议 → 风控检查 → 执行器模拟下单”的闭环。
5.1 环境清单与安装
我建议在 Linux 或 macOS 上操作,Windows 也可以,但需要自行处理一些依赖编译问题。最小依赖:
- Python 3.10 以上
- Git 2.30 以上
- openai SDK 或其他兼容本地推理框架的 API(如果你想接入本地 LLM)
- pandas 和 numpy
创建一个干净的环境:
mkdir openalice-minimal && cd openalice-minimal python -m venv venv && source venv/bin/activate pip install pandas numpy openai git init如果不想接外部推理 API,也可以用 Llama.cpp 或 Ollama 在本地跑一个小模型,OpenAlice 只要求 Agent 能通过统一接口返回 JSON 结构,不强制绑定某个模型。
5.2 核心代码:Git 提交封装与风控检查
先实现一个最基础的风控校验模块。这里面有两个关键点:一是检查逻辑必须独立,二是检查结果必须带签名。我习惯定义一个RiskManager类,输入是一笔交易建议,输出是一个带approved字段的结论对象。
下面是一段可直接用的风控检查代码:
class RiskManager: def __init__(self, account_equity): self.account_equity = account_equity self.max_single_position = 0.2 self.max_leverage = 2.0 self.max_drawdown = 0.15 def check(self, proposal): # proposal: {"symbol": "BTC/USDT", "side": "buy", # "target_position_pct": 0.3, "notional_value": 1000} errors = [] if proposal["target_position_pct"] > self.max_single_position: errors.append(f"单标仓位超出限制: {proposal['target_position_pct']:.2%}") leverage = proposal["notional_value"] / self.account_equity if leverage > self.max_leverage: errors.append(f"杠杆超出限制: {leverage:.2f}") # 这里还可以扩展更多规则,比如 KYC、涨跌停检查等 if errors: return {"approved": False, "reasons": errors} return {"approved": True, "reasons": []}再封装一个最简单的“Git 提交即日志”工具。每次策略或风控事件,都会生成一条结构化提交,提交信息的作者统一标记为对应 Agent 的名字,便于审计:
import subprocess def commit_event(message: str, author: str, allow_empty=True): cmd = ["git", "commit", "--allow-empty", "-m", message, "--author", f"{author} <system@openalice.local>"] subprocess.run(cmd, check=True)5.3 跑通一个最小策略闭环
为了演示闭环,我用一个非常简单的均值回归策略作为示例,重点观察 Agent 建议如何经过风控检查后被接受或拒绝。
from risk_manager import RiskManager from git_utils import commit_event risk = RiskManager(account_equity=100000) # 模拟策略 Agent 的输出 proposal = { "symbol": "BTC/USDT", "side": "buy", "target_position_pct": 0.5, "notional_value": 50000, } result = risk.check(proposal) if result["approved"]: commit_event(f"ok: 策略建议通过风控,建仓 {proposal['symbol']}", "strategy_agent") print("执行器开始下单...") else: commit_event(f"blocked: {result['reasons']}", "risk_agent") print(f"风控拦截: {result['reasons']}")这里设置的账户权益是 10 万,提案目标是 50% 仓位,明显超过 20% 的单标上限,所以风控会拦截,并且拦截原因是结构化数据,方便后续排查。
如果你想真的接入实盘,只需要把“执行器开始下单”这一段替换成券商 API 的实际下单函数,其余部分不需要改动。
6. 实操过程复盘:我踩过的坑与排查实录
原理讲完,代码也给了一段,最后这部分是纯实盘经验。OpenAlice 这种架构在实际搭建和使用过程中,有几个坑几乎是必踩的,我列出来供你避雷。
6.1 常见问题排查表
| 问题现象 | 可能原因 | 解决思路 |
|---|---|---|
| Agent 建议一天到晚变来变去 | 上下文窗口里塞入了太多噪声数据 | 限制单轮分析的输入字段,对数据做摘要后再喂给 Agent |
| 风控频繁误杀,好策略也过不去 | 仓位限制参数设得太严,没有考虑对冲组合 | 在风控规则里加入组合级别的敞口计算,而不是只看单标的 |
| 实际下单时间和建议时间有较大延迟 | 本地推理模型太慢,或接口调用排队 | 使用量化蒸馏过的轻量模型,只保留决策关键能力 |
| Git 日志太多,分析时找不到关键事件 | 每个中间过程都提交,缺少分级 | 用标签区分事件类型,比如strategy:、risk:、execution:前缀 |
| 回测和实盘偏离很大 | 数据指纹没有做严格校验 | 每次回测和实盘开始前,先比对数据哈希值和策略版本标签 |
6.2 避坑心得
我特别想强调自己踩过的一次坑:早期为了省事,我把“策略 Agent”和“风控 Agent”合并成了同一个大模型调用,结果出现了模型自己批准自己建议的事情。表面上看没什么问题,但你永远无法证明它是否真的做了风险检查。后来我改成独立模块加独立签名,虽然多花了点时间,可每次运行都有明确的证据链。
另一个很重要的经验是,Agent 的上下文应该被严格设计成“只读行情上下文 + 决策输出”的模式。如果允许 Agent 自由读取历史交易记录,它很容易在亏损后产生追涨杀跌倾向。现在 OpenAlice 给策略 Agent 的上下文里只有当前市场快照和账户风控边界,它不被告知历史盈亏,这样它的建议才是真正基于当前信号的,而不是基于情绪。
6.3 关于模型选择的补充
本地部署 LLM 做 Agent 时,每个人都想用最大最强的模型,但我建议优先考虑两个指标:推理延迟和输出稳定性。量化场景里,一个 7B 级别的量化蒸馏模型往往比一个 70B 满血模型更适合做盘中决策,因为它响应快,输出格式也更不容易漂移。你可以让大模型离线生成策略研究报告,而让小模型处理盘中实时建议,这种分工在实际使用里效果更好。
6.4 后续扩展方向
这套架构的想象力不止于简单的策略回测。你可以把同一套 Trading-as-Git 体系扩展到多个交易市场,甚至把 Agent 的每日审计摘要自动生成一份 Markdown 文档提交到仓库,这样每个周日你就能看到一份完整的、可回溯的周报,里面包含了本周所有交易的“为什么”。
我个人在实际操作中的体会是:量化交易里真正难得的往往不是某个神奇策略,而是一套让你每次决策都不出格的框架。OpenAlice 的 Trading-as-Git 架构最打动我的地方,是把“稳”变成了代码层面的强制约束,而不是主观自律。往里走,你还可以加更多属于自己的风控规则、实证分析和二次验证机制。
最后再分享一个小技巧:给每个 Agent 的提交信息加上统一的机器可读前缀,会极大提升审计效率。比如signal:表示策略信号,risk:表示风控结论,exec:表示执行结果。当你用git log --grep="risk:blocked"去搜索时,一秒钟就能定位到所有被拦下的危险建议,这才是 Trading-as-Git 真正给人省心的地方。