AlphaBound 手册
有边界的自主投资 Agent — 在明确风险边界内,通过持续网络研究、基本面分析、事件调查、市场情绪理解和长期记忆,自主管理 BTC 风险暴露。
宽信息入口,慢投资决策,快风险反应,窄交易出口。
| 范围 | OKX BTC-USDT 现货 · 约 100 USDT 实验资金 |
| 硬边界 | 基于历史高水位 (HWM) 的 10% 最大回撤 |
| 技术栈 | Zig 0.16.0 · SQLite WAL · systemd · 嵌入式 Dashboard |
| 仓库 | talkincode/alphabound |
| 当前 | Shadow 默认;小额 mode=live 已解锁(OKX_REAL_MONEY_OK=1);Dashboard 鉴权 + 只读 MCP |
一句话理解
把「AI 自主交易」拆成两个正交问题:
- 策略自主性交给 LLM Agent(观察、调查、假设、提案、反思)
- 资金安全交给确定性代码(状态引擎、风险内核、幂等执行)
Agent 可以提出任何交易观点,但不能直接调用交易凭证,也不能修改最大回撤边界。通往交易所的唯一路径是:
结构化 Proposal → Risk Kernel 准入 → Execution Engine 幂等下单
管理动作(pause / flatten / target-weight)只走本机 CLI;Dashboard 与 MCP 是只读观察面。
本手册怎么读
| 你是… | 从这里开始 |
|---|---|
| 想在本机先跑起来 | 快速开始 |
| 要改配置 / 接密钥 | 配置参考 · CLI 参考 |
| 要保护 Dashboard / 接 IDE | 鉴权与 MCP |
| 要上 VM 常驻 | 运维部署 |
| 要理解安全边界 | 四支柱架构 · 风险模型 |
| 要改代码 / 写测试 | 构建与测试 · 关键不变量 |
| 要对齐阶段闸门 | 路线图 · 下一步 · 验收矩阵 |
风险说明
「最大回撤 10%」是系统工程目标,不是绝对保证。极端跳空、流动性消失、交易所故障、网络中断或成交延迟均可能造成边界穿透。系统尽力提前保留退出缓冲,并如实记录任何突破。
文档构建
本手册由 mdBook 维护,源文件在仓库 book/src/。
# 需要 mdbook ≥ 0.4(本机可用 Homebrew: brew install mdbook)
./scripts/build-docs.sh # 构建到 book/book/
./scripts/build-docs.sh serve # 本地预览 http://127.0.0.1:3000
CI 在每次 push / PR 会执行 mdbook build,保证链接与语法不过期。
快速开始
本页带你在开发机上完成:构建 →(可选)钥匙串密钥 → 自检 → shadow 冒烟 → Dashboard。
shadow 永不下单:公共行情 + 模拟账户;有密钥时额外做只读私有余额探测(Gate 1 连通性)。
前置条件
| 依赖 | 版本 / 说明 |
|---|---|
| Zig | 必须 0.16.0(固定工具链,CI 同款) |
| 网络 | 能访问 https://www.okx.com(公共 REST) |
| 可选 | macOS Keychain 中的 OKX_API_*、sqlite3、curl |
zig version # 期望输出 0.16.0
1. 克隆与构建
git clone git@github.com:talkincode/alphabound.git
cd alphabound
zig build -Doptimize=ReleaseSafe # 产出 zig-out/bin/alphabound
zig build test
2. 本地配置
仓库提供开箱配置 config/local.toml:
- DB:
var/trading.db(先mkdir -p var) - Web:
127.0.0.1:18180(config/local.toml;避开 8080 / 18080 常见占用) mode = "shadow"
mkdir -p var
硬约束:
web.bind只能是127.0.0.1:port或容器用0.0.0.0:port。远程访问走 SSH tunnel。
3. (可选)从 macOS 钥匙串加载 OKX 密钥
钥匙串 service 名约定:OKX_API_KEY、OKX_API_SECRET、OKX_API_PASSPHRASE
(兼容旧名 OKX_API_ Passphrase)。
./scripts/load-okx-keychain.sh ./secrets.env # 0600,已 gitignore
set -a && source ./secrets.env && set +a # 值已 shell 转义,支持 passphrase 含 &
# 或一键:
./scripts/run-local.sh --self-check
./scripts/run-local.sh --ticks 5
| 环境变量 | 说明 |
|---|---|
OKX_API_KEY / OKX_API_SECRET / OKX_API_PASSPHRASE | 仅环境注入,禁止写 TOML |
OKX_SIMULATED=1 | 演示盘密钥时加 x-simulated-trading: 1 |
私有只读前提:OKX API Key 的 IP 白名单须包含本机公网 IP。未放行时日志为 private balance FAILED: ip_whitelist——签名已通,属运维策略,shadow 公共路径仍可跑。
curl -sS https://api.ipify.org; echo # 把该 IP 加到 OKX API Key 白名单
4. 自检
./zig-out/bin/alphabound --config config/local.toml --self-check
成功打印 config_hash、mode、db、web、okx_keys: present|absent。若有密钥会尝试 /api/v5/account/balance(只读)。
5. 有界 shadow 运行
./zig-out/bin/alphabound --config config/local.toml --ticks 5
期望日志:
[boot] OKX credentials present (key_len=... secret_len=... pass_len=... simulated=false)
[connect] okx server time ...
[reconcile] private balance ... # ok 或 ip_whitelist
[ready] mode=shadow live BTC-USDT data, simulated engine cash 100 USDT, web 127.0.0.1:18180, private_keys=yes, agent=on
[tick 0] bid ... equity 100 dd 0 mode normal
[shutdown] draining after 5 ticks
mode=live 需要 OKX_REAL_MONEY_OK=1 与小额子账号密钥;详见 运行模式。
6. 探活与 Dashboard
常驻或加长 --ticks 时:
curl -s http://127.0.0.1:18180/health/live
curl -s http://127.0.0.1:18180/health/ready
curl -s http://127.0.0.1:18180/api/v1/state
open http://127.0.0.1:18180/
| 端点 | 含义 |
|---|---|
GET / | 嵌入式 Overview Dashboard |
GET /health/live | 进程存活 |
GET /health/ready | READY 后 200 |
GET /api/v1/state | 版本化状态快照 |
GET /api/v1/events | 最近事件 |
GET /api/v1/orders | 订单/fills 投影 |
GET /api/v1/system | 进程与 agent 统计 |
若设置了 ALPHABOUND_API_TOKEN,数据 API 需 Authorization: Bearer … 或先登录;见 鉴权与 MCP。
7. 查库
sqlite3 var/trading.db \
"SELECT type, severity FROM events ORDER BY seq DESC LIMIT 10;"
常见事件:RECONCILE_COMPLETED / STATE_READY / PRIVATE_BALANCE_OK|FAILED / SHUTDOWN_CLEAN。
8. 优雅退出
# Ctrl-C 或
kill -TERM <pid>
9. 配置 LLM Agent(可选)
有 OpenAI 兼容 apiurl / key / model 时,写入 secrets.env:
# secrets.env 追加(chmod 600;值请自行替换)
LLM_API_KEY='你的key'
LLM_API_URL='https://你的兼容端点/v1' # 不要带 /chat/completions
LLM_MODEL='你的模型名'
set -a && source ./secrets.env && set +a
./zig-out/bin/alphabound --config config/local.toml --agent-once --ticks 5
完整说明 → Agent 配置(OpenAI)
下一步
- 配置项 → 配置参考
- Agent → Agent 配置(OpenAI)
- 模式差异 → 运行模式
- Dashboard / 鉴权 / MCP → Dashboard 与 API · 鉴权与 MCP
- Docker/GHCR → Docker 与 GHCR
- 运维 → 运维部署
配置参考
配置文件为 TOML。生产约定路径:
| 文件 | 权限建议 | 内容 |
|---|---|---|
/etc/alphabound/alphabound.toml | 0640 root:alphabound | 非密钥运行参数 |
/etc/alphabound/secrets.env | 0600 root:root | OKX / LLM 密钥(systemd EnvironmentFile) |
/etc/alphabound/prompts/ | 0640 | 版本化系统 Prompt |
密钥绝不写入 TOML,也绝不进入 Agent Context。
仓库示例:config/alphabound.toml。
完整示例
[app]
environment = "production" # development | production
instance_id = "azure-btc-01" # 写入事件,便于多实例区分
[exchange]
provider = "okx"
instrument = "BTC-USDT"
mode = "shadow" # shadow | demo | live
# rest_url = "https://www.okx.com"
poll_interval_ms = 5000
[risk]
max_drawdown = 0.10 # 不可热加载;Agent 不可修改
valuation = "conservative_liquidation"
allow_runtime_override = false
taker_fee_rate = 0.001
slippage_rate = 0.0005
initial_capital = 100.0 # shadow 模拟起始资金 (USDT)
[agent]
provider = "configured-adapter"
model = "configured-model"
decision_timeout_ms = 180000
prompt_dir = "/etc/alphabound/prompts"
[storage]
path = "/var/lib/alphabound/trading.db"
wal = true
[web]
bind = "127.0.0.1:8080"
static_dir = "/opt/alphabound/ui/current" # 预留;当前 Dashboard 已嵌入二进制
[review]
short_interval_ms = 28800000 # 定期复盘·小周期 8h(小时级;4h = 14400000,最小 600000;0 = 关闭)
long_interval_ms = 604800000 # 定期复盘·大周期 7d(最小 3600000;0 = 关闭)
timeout_ms = 180000 # 复盘 LLM 超时,默认 180000,最小 30000;独立于 [agent] decision_timeout_ms,不被其封顶
分段说明
[app]
| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
environment | string | — | 环境标签,进日志/事件 |
instance_id | string | — | 实例标识 |
[exchange]
| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
provider | string | okx | 交易所适配器 |
instrument | string | BTC-USDT | 交易标的 |
mode | string | shadow | 见 运行模式 |
rest_url | string | https://www.okx.com | REST 根地址 |
poll_interval_ms | u32 | 2000 | shadow 轮询间隔;下限 200ms(防打爆公共 API) |
[risk] — 硬边界区
| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
max_drawdown | decimal | 0.10 | HWM 相对最大回撤。启动时加载,禁止热改 |
valuation | string | conservative_liquidation | 净值口径 |
allow_runtime_override | bool | false | 必须为 false;解析保留字段 |
taker_fee_rate | decimal | 0.001 | 保守估值 taker 费率 |
slippage_rate | decimal | 0.0005 | 退出滑点缓冲 |
initial_capital | decimal | 100 | shadow 模拟账户起始 USDT;须 > 0 |
min_trade_notional | decimal | 0 | 每笔最低名义金额(USDT)。只抬高交易所 min_notional,不降低。低于此值的再平衡会 plan_hold;0 = 仅用交易所下限 |
改
max_drawdown/ 费率类参数 = 版本发布 + 人工确认,不是运行中调参。
[agent]
详见专章 Agent 配置(OpenAI)。
| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
provider | string | openai | 适配器名(当前仅 openai 兼容) |
model | string | gpt-4o-mini | 可被 LLM_MODEL 覆盖 |
base_url | string | https://api.openai.com/v1 | 可被 LLM_API_URL 覆盖 |
decision_timeout_ms | u32 | 120000 | 单次 LLM chat 墙钟超时(超时→HOLD,不阻塞 daemon) |
decision_interval_ms | u32 | 600000 | 慢环基础间隔(活跃时段);0 表示不按间隔调度 |
decision_interval_quiet_ms | u32 | 0 | 静默时段间隔;0 = 同基础间隔 |
decision_min_interval_ms | u32 | 120000 | 任意两次决策的硬性冷却下限(事件触发也受限) |
active_hours_utc | string | "" | UTC 活跃时段 "start-end"(end 不含,可跨 0 点如 "22-4");空 = 全天基础间隔 |
event_price_move | decimal | 0.005 | 距上次决策价格偏离 ≥ 该比例提前触发;0 关闭 |
event_drawdown_step | decimal | 0.01 | 回撤较上次决策加深 ≥ 该比例提前触发;0 关闭 |
volatility_enter | decimal | 0 | 约 15 分钟 (最高−最低)/最低 ≥ 该比例进入高波动档,放宽 HOLD 等待;0 关闭 |
volatility_exit | decimal | 0.006 | 振幅 ≤ 该比例且持续 volatility_exit_hold_ms 才退出高波动档 |
volatility_interval_ms | u32 | 180000 | 高波动档的复查间隔;仍受 decision_min_interval_ms 约束 |
volatility_exit_hold_ms | u32 | 900000 | 退出高波动档所需的连续低振幅时长 |
prompt_dir | path | prompts | Prompt 目录 |
enabled | bool | true | false 时永不调 LLM |
llm_reflection | bool | true | 有效提案后跑 LLM 结构化反思;失败回退确定性 |
llm_reflection_on_hold | bool | false | HOLD 提案是否也跑 LLM 反思;false 时 HOLD 只用确定性反思 |
慢环调度是多因素的:活跃/静默时段各有基础节奏,价格突变、回撤加深、
风险模式切换会提前触发一次决策,且所有触发都受 decision_min_interval_ms
冷却下限约束。HOLD 以及因低于最小下单额而 plan_hold 的 REBALANCE 会按提案的
review_after 推迟常规节奏(价格/回撤/风险模式/高波动事件仍可穿透)。
事件触发的复查不会取消已生效的 review_after:只有新的可解析 review_after、
实际成交,或一次未产出建议的失败(LLM 失败/提案无效)才会改变它。
风险内核不受此影响——它始终在快环独立执行。
每次触发在事件流记录 AGENT_TRIGGER(含 reason),便于审计调用频率。
[storage]
| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
path | path | — | SQLite 文件路径;父目录须可写 |
wal | bool | true | 强制 WAL 语义(单 writer) |
不要把 DB 放在网络文件系统上。
[web]
| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
bind | string | 127.0.0.1:8080 | 仅 127.0.0.1:port 或容器 0.0.0.0:port;宿主机发布仍应绑 loopback |
static_dir | path | — | 预留静态目录;当前 Overview 页面 @embedFile 进二进制 |
[review]
定期复盘节奏。每次运行至多一次 LLM 调用,只读账本、只写复盘报告与一条低置信度参考记忆,接触不到提案与下单路径。
| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
short_interval_ms | u32 | 28800000(8h) | 小周期复盘间隔,按小时级设置(常用 4h = 14400000);最小 600000;0 = 关闭 |
long_interval_ms | u32 | 604800000(7d) | 大周期复盘间隔;最小 3600000;0 = 关闭 |
timeout_ms | u32 | 180000 | 该次 LLM 调用的超时预算;最小 30000。独立于 [agent] decision_timeout_ms,不会被其封顶——复盘 prompt(窗口事实 + 记忆摘要 + 长周期时的短复盘摘要)通常比单次决策更大,调紧决策超时不应连带拖垮复盘可用性。实际生效值还会按 prompt 体量小幅上调(至多 +50%),见 periodicReviewTimeoutMs(src/main.zig)。 |
下限用于防止误配把复盘变成第二条决策回路。两个周期同时到期时大周期优先,小周期顺延到下一 tick(两次运行之间至少间隔 2 分钟)。进程重启后从库中该周期最新报告的时间戳恢复游标:停机数日只补跑一次,不会逐槽回放。
密钥环境变量(secrets.env)
密钥只经环境变量注入(systemd EnvironmentFile=、shell source、或 macOS 钥匙串导出)。禁止写入 TOML。
# secrets.env (chmod 0600) — 见 secrets.env.example
OKX_API_KEY=...
OKX_API_SECRET=...
OKX_API_PASSPHRASE=...
# mode=demo → OKX_SIMULATED=1
# mode=live → OKX_REAL_MONEY_OK=1(小额子账号;禁止 SIMULATED)
LLM_API_KEY=
LLM_API_URL=https://api.openai.com/v1
LLM_MODEL=gpt-4o-mini
# Dashboard / MCP(可选;空 = 本机开放 API)
# ALPHABOUND_API_TOKEN= # openssl rand -hex 32
# ALPHABOUND_TRUST_PROXY=1 # 仅受信任 TLS 反代后
# ALPHABOUND_TRUSTED_PROXY_HOPS=1
# ALPHABOUND_WEBAUTHN_RP_ID=localhost
# ALPHABOUND_WEBAUTHN_ORIGIN=http://127.0.0.1:18180
macOS 本地:
./scripts/load-okx-keychain.sh ./secrets.env # Keychain → 0600 文件(值已 shell-quote)
set -a && source ./secrets.env && set +a
进程只记录 key_len / secret_len / pass_len,从不打印密钥。有密钥时 shadow 会 只读 调用 GET /api/v5/account/balance;引擎现金仍用 initial_capital 模拟,不下单。
| 私有探测结果 token | 含义 |
|---|---|
| (成功) | 余额可用;日志打印 usdt/btc 数量 |
ip_whitelist | OKX 50110:把本机公网 IP 加入 API Key 白名单 |
invalid_sign / invalid_key / invalid_passphrase | 密钥或签名问题 |
http_failed | 网络/TLS |
| Dashboard 环境变量 | 含义 |
|---|---|
ALPHABOUND_API_TOKEN | 非空则保护 /api/v1/* 数据路由 |
ALPHABOUND_TRUST_PROXY | 仅反代后信任 X-Forwarded-For(右起 hops) |
ALPHABOUND_WEBAUTHN_* | Passkey rpId/origin;须与浏览器打开的 URL 一致 |
日志与事件经 observability/redaction.zig 脱敏;不要把 secrets.env 贴进 issue 或聊天。鉴权细节见 鉴权与 MCP。
校验与哈希
--self-check:解析 TOML、打开 DB、migration、bind;若有OKX_*则做私有只读探测。- 每次启动计算
config_hash(SHA-256),写入事件信封。 mode=live需要OKX_*+OKX_REAL_MONEY_OK=1(且禁止OKX_SIMULATED);mode=demo需要密钥 +OKX_SIMULATED=1。
热加载边界
| 可热加载(规划) | 不可热加载(必须发版) |
|---|---|
| Prompt 文本(SIGHUP,hash 变更进事件) | max_drawdown、费率、滑点、mode→live 切换 |
| 日志级别(若后续支持) | web bind、DB 路径、instrument |
Agent 没有写配置的代码路径——这是能力缺失,不是 prompt 约定。
Agent 配置(OpenAI 兼容)
AlphaBound 慢决策环使用 OpenAI Chat Completions 兼容 API。
shadow 下会生成并审计 Decision Proposal,绝不下单。
你需要准备
| 项 | 说明 |
|---|---|
| API URL | 根路径,如 https://api.openai.com/v1 或中转 https://xxx/v1(不要带 /chat/completions) |
| API Key | Bearer token |
| Model | 如 gpt-4o-mini、deepseek-chat 等 |
1. 写密钥(环境变量,不要写 TOML)
方式 A:手写 secrets.env
./scripts/load-okx-keychain.sh ./secrets.env # 可选 OKX
cat >> secrets.env <<'EOF'
LLM_API_KEY='你的key'
LLM_API_URL='https://api.openai.com/v1' # 或 Azure: https://xxx.openai.azure.com/openai/v1
LLM_MODEL='你的模型名或Azure部署名'
EOF
chmod 600 secrets.env
set -a && source ./secrets.env && set +a
方式 B:macOS 钥匙串
支持 service 名:
| 用途 | service |
|---|---|
| Key | LLM_API_KEY / OPENAI_API_KEY / AZURE_OPENAI_API_KEY |
| URL | LLM_API_URL / OPENAI_BASE_URL / AZURE_OPENAI_API_URL |
| Model | LLM_MODEL / OPENAI_MODEL / AZURE_OPENAI_DEPLOYMENT |
./scripts/load-llm-keychain.sh ./secrets.env
# 若钥匙串没有 model,默认 gpt-4o-mini —— Azure 上通常要改成真实 Deployment 名:
# 编辑 secrets.env 里 LLM_MODEL='你的deployment'
set -a && source ./secrets.env && set +a
Azure OpenAI:LLM_MODEL 必须是门户里的 Deployment 名称(不是随便写的模型 id)。
若日志出现 deployment_not_found,只改 LLM_MODEL 即可。
别名:OPENAI_* / AZURE_OPENAI_* 均可。
2. TOML [agent](非密钥)
config/local.toml:
[agent]
provider = "openai"
model = "gpt-4o-mini" # 可被 LLM_MODEL 覆盖
base_url = "https://api.openai.com/v1" # 可被 LLM_API_URL 覆盖
decision_timeout_ms = 180000
decision_interval_ms = 60000 # 慢环间隔;0=不按间隔调度
prompt_dir = "prompts"
enabled = true # false 则永不调模型
系统提示词:仓库内 prompts/system.md(已嵌入二进制)。
3. 运行
mkdir -p var
zig build -Doptimize=ReleaseSafe
# 自检(打印 agent 配置是否读到密钥,不强制调模型)
./zig-out/bin/alphabound --config config/local.toml --self-check
# 就绪后立刻做 1 次决策 + 跑若干 tick
./zig-out/bin/alphabound --config config/local.toml --agent-once --ticks 5
# 常驻:按 decision_interval_ms 周期决策
./scripts/run-local.sh
成功日志示例:
[boot] LLM credentials present (key_len=... base_url=https://... model=...)
[agent] calling https://... model=... snap=...
[agent] proposal ok id=dec_... action=HOLD ... (shadow: not executed)
失败(超时/坏 JSON/鉴权)→ HOLD,写 agent_runs 状态,不影响行情环。
4. 查审计
每次慢环会先拉 market.ticker / market.candles(OKX 公共 REST),写入 tool_calls,再把观察塞进 Context 的 tool_observations(data 不可信)。
# 汇总有效提案率
./zig-out/bin/alphabound --config config/local.toml --agent-stats
sqlite3 var/trading.db \
"SELECT run_id,model,status,snapshot_version FROM agent_runs ORDER BY started_ts DESC LIMIT 5;"
sqlite3 var/trading.db \
"SELECT tool,source,latency_ms,substr(result_digest,1,16) FROM tool_calls ORDER BY id DESC LIMIT 10;"
# 提案摘要在 events.payload_json(shadow 永不 executed)
sqlite3 var/trading.db \
"SELECT type,severity,payload_json FROM events WHERE type LIKE 'AGENT_%' ORDER BY seq DESC LIMIT 5;"
成功日志形如:
[agent] calling ... tools=2
[agent] proposal ok id=dec_... action=HOLD target_btc=0 conf=0.75 (shadow: not executed)
优先级
- 环境变量
LLM_*/OPENAI_* - TOML
[agent] model/base_url - 无
LLM_API_KEY→ agent 关闭,仅行情 shadow
安全
- Key 不进 git、不进 Dashboard、不进 Agent Context
- 提案在 shadow 不进执行层
mode=live需OKX_REAL_MONEY_OK=1;shadow 默认仍不执行订单
Reflection(决策后)
提案校验通过后会再跑一轮 Reflection:
- 默认
llm_reflection = true:第二次 LLM 调用(prompts/reflection.md),产出严格 Schema 的memory_ops并写入记忆库。 - LLM 失败 / 坏 JSON / Schema 拒绝 → fail-closed,回退确定性 shadow reflection(不改订单路径)。
- 环境变量
ALPHABOUND_LLM_REFLECTION=0可强制关闭 LLM reflection。
相关事件:AGENT_REFLECTION_OK、AGENT_REFLECTION_LLM_FAILED、AGENT_REFLECTION_INVALID。
短 soak
./scripts/soak-shadow.sh 20
CLI 参考
二进制:zig-out/bin/alphabound(安装后常见路径 /opt/alphabound/current/alphabound)。
用法
alphabound [--config PATH] [--self-check] [--version] [--ticks N]
[--agent-once] [--agent-stats]
[--control pause|resume|reconcile|cancel-all|flatten|target-weight=W|shutdown|status]
[--verify-db PATH]
无参或非法参数时打印 usage 并以非零退出。
参数
| 参数 | 必填 | 说明 |
|---|---|---|
--config PATH | 否 | TOML 配置路径。默认 config/alphabound.toml(相对 cwd) |
--self-check | 否 | 只做启动前检查后退出 0/非 0;不进主循环、不连行情轮询 |
--version | 否 | 打印 alphabound <version> 后退出 0 |
--ticks N | 否 | 有界运行:完成 N 次成功行情 tick 后走优雅退出。冒烟 / CI / 演示用 |
--agent-once | 否 | READY 后强制一轮 Agent(shadow 只审计,需 LLM_*) |
--agent-stats | 否 | 打印 agent_runs 有效率与 tool_calls 计数后退出 |
--control CMD | 否 | 本机管理(写控制文件后退出,不启 daemon)。见 Admin control |
--verify-db PATH | 否 | 离线审计链抽查(订单 → 决策锚点 / fills),不启 daemon |
退出码
| 码 | 含义 |
|---|---|
0 | 正常(含 self-check 通过、ticks 跑完、信号优雅退出) |
| 非 0 | 配置失败、DB 打不开、web listen 失败、连接阶段不可达等 |
生命周期日志锚点
便于 journalctl -u alphabound -f 过滤:
| 前缀 | 阶段 |
|---|---|
[boot] | 加载配置、开库、恢复 HWM、起 web;live 醒目 banner |
[connect] | 探测交易所 REST(时间同步) |
[ready] | 对账完成,进入主循环 |
[reconcile] | 私有余额只读探针 / live balance applied |
[agent] | 慢环决策 / 工具 / 降级 HOLD |
[admin] | 本机控制命令生效 |
[tick N] | 单次行情处理摘要(bid / equity / dd / mode) |
[risk] | 风险模式切换 |
[loop] | 行情拉取失败等可恢复错误 |
[shutdown] | 优雅退出开始 |
[journal] | 事件/净值落库失败(应告警) |
[web] | HTTP 服务异常停止 |
[agent-stats] | --agent-stats 输出 |
常用配方
# 版本
./zig-out/bin/alphabound --version
# 配置与 DB 冒烟
./zig-out/bin/alphabound --config /etc/alphabound/alphabound.toml --self-check
# 本地有界验证
./zig-out/bin/alphabound --config config/local.toml --ticks 10
# Agent 一轮 + 统计(需 secrets.env)
set -a && source ./secrets.env && set +a
./zig-out/bin/alphabound --config config/local.toml --agent-once --ticks 5
./zig-out/bin/alphabound --config config/local.toml --agent-stats
# 审计链
./zig-out/bin/alphabound --verify-db var/trading.db
# 常驻(前台);生产用 systemd,见运维章
./zig-out/bin/alphabound --config config/local.toml
信号处理
| 信号 | 行为 |
|---|---|
SIGTERM / SIGINT | 置位停止标志 → 结束当前 tick → 落 SHUTDOWN_CLEAN → 关 DB / web |
SIGKILL | 无法处理;依赖 systemd Restart= + 下次启动重新对账(fail-closed) |
管理命令
设计要求 pause / resume / reconcile / cancel-all / flatten / target-weight / safe-shutdown 走本机 CLI(控制文件),不走公网 HTTP。详见 Admin control。
运维报告(daemon 已在跑时):
./scripts/gate2-report.sh
HOST=<sshx-name> ./scripts/soak-report.sh 24
HOST=<sshx-name> ./scripts/check-remote.sh
Dashboard 与 API
Web 面默认只绑 127.0.0.1。远程看盘用 SSH 本地转发,或经受信任的 TLS 反代(nginx);不要把未鉴权端口裸奔到公网。
ssh -L 18180:127.0.0.1:18180 user@your-vm
# 本机浏览器打开 http://127.0.0.1:18180/
本地默认配置见 config/local.toml(端口 18180)。生产示例多为 127.0.0.1:8080。
鉴权(可选)
| 客户端 | 凭证 |
|---|---|
| 浏览器 Dashboard | Token 登录 → ab_session HttpOnly cookie;可选 Passkey |
| MCP / 脚本 | Authorization: Bearer <token> 或 X-API-Token: <token> |
| 健康探针 | 始终开放:/health/live、/health/ready |
ALPHABOUND_API_TOKEN为空:鉴权关闭(本机开发默认)。- 已设置 token:所有
/api/v1/*数据路由无凭证返回 401;HTML 壳仍可访问并显示登录门。 - Passkey 注册需要已有 session(先用 token 登录一次)。
- 反代场景见 鉴权与 MCP;默认不要开
ALPHABOUND_TRUST_PROXY。
# 登录拿 session(示例)
curl -sS -c cookies.txt -X POST http://127.0.0.1:18180/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"token":"YOUR_TOKEN"}'
curl -sS -b cookies.txt http://127.0.0.1:18180/api/v1/state | jq .
# 或
curl -sS -H "Authorization: Bearer YOUR_TOKEN" http://127.0.0.1:18180/api/v1/state | jq .
Dashboard
| 项 | 现状 |
|---|---|
| 形态 | 单文件 HTML + favicon 集,编译期嵌入二进制(dashboard/) |
| 入口 | GET / 与 GET /index.html |
| 依赖 | 零 Node 运行时;浏览器直接 fetch API |
| 刷新 | 前端约 2s 轮询 state / shadow / agent-runs / equity / candles / memories / events / system / orders / decisions / review-chats / statistics / intel / sentiment |
| 内容 | Overview + Shadow vs BH + Lightweight Charts(分时/多周期 K 线 + 成交量 + 净值/HWM + 恐惧贪婪指数日频曲线)+ 复盘(K 线决策标记 + 指标 + AI 复盘对话 + 复盘记录)+ 统计(资产/交易窗口账本 + 持久化 LLM Token/成本账本)+ 情报(签名外部投资情报历史)+ 提案/记忆/事件/订单 + System |
概览图表使用 Lightweight Charts(CDN)。周期按钮:分时(1m 收盘面积图)、1分/5分/15分/1时/4时/1日。离线无 CDN 时其余 UI 仍可用。
复盘标签页
K 线图(1m–1D 周期,MA/EMA/BOLL 主图指标,VOL/RSI/MACD 副图)上把每次 Agent 提案画成标记:● 持有、▲/▼ 调仓(按目标权重方向)、▪ 失败或准入拒绝。点击标记(或用决策下拉)后,下方三个子页联动:
- 决策:该提案的完整摘要(thesis、invalid_if、准入结论、关联订单/成交、原始 payload)。
- 事件流:该时点 ±30 分钟的事件账本窗口(行情、余额、准入、执行、备份等),由核心循环按需从 SQLite 提取。
- 复盘记录:定期复盘的报告列表(见下)。
- AI 复盘:与复盘助手就该时点对话。助手可发起一轮有界工具请求(≤6 个):决策时点指标(SMA/EMA/RSI/ATR/VOL/BOLL/RANGE,
at:anchor在锚点截断计算)、K 线窗口、提案历史、净值轨迹、记忆检索、只读外部情报(intel,at:now/anchor)——全部只读,接触不到交易路径。克制边界:助手只做归因分析,不给交易建议、无执行能力,人不能借它直接或间接改变决策;对话全部落库(review_chats表)。点「沉淀为记忆」可将对话压缩成一条 confidence 0.3 的 reflection 记忆(HR_<decision_id>,每个决策一条、就地更新),作为人类观点进入主 Agent 上下文的唯一通道,由 Agent 自行取舍。
K 线下方另有 AB 因子曲线图(实验性):仓位、净值收益、超额 α、回撤、波动、动量六个成分的 z-score 曲线与合成因子,时间轴与 K 线图双向联动,配 IC 表观测各成分对未来净值收益的预测力。仅用于复盘观测,不参与任何决策(详见下文 GET /api/v1/review/analytics)。
复盘记录子页(定期复盘)
前三个子页是人主动挑一个决策去追问;「复盘记录」是系统按固定节奏自己回看一整段窗口,两者并存互补,因此放在同一个复盘标签页下。
- 小周期(小时级,默认 8 小时,常用 4 小时):这一班的决策是否兑现了自己的论据?HOLD 是不是被当成了胜利?
- 大周期(默认 7 天):策略在跨班次上是否还成立?基准跑赢了吗?该改的是仓位、节奏,还是记忆?
子页顶部是两个周期的间隔与下次运行倒计时、最近一次结果;下方按时间倒序列出报告卡片(可按周期筛选),展开可见摘要、窗口内确定性事实(提案/准入/执行/净值/最大回撤/基准超额/异常计数)、模型给出的发现·经验·风险,以及沉淀出的记忆 ID 与原始 JSON。两个「立即复盘」按钮走同一条邮箱链路,用于手动加跑一次。
边界与既有复盘一致:只读账本,不触碰引擎、订单与风控状态,也不产生交易建议。窗口内的每个数字都来自 SQLite(equity_samples / events / agent_runs / fills / audit_reports),模型只负责归纳;结论压缩成一条 confidence 0.3 的 reflection 记忆(PR_short / PR_long,每周期一条、就地更新),是它影响未来决策的唯一通道,由主 Agent 自行取舍。LLM 未配置或返回不合法 JSON 时,仍会落一份 degraded 报告(只含确定性事实)并照常推进调度,坏掉的模型不会把循环卡在重试上。
本地打开
set -a && source ./secrets.env && set +a
./zig-out/bin/alphabound --config config/local.toml --ticks 0 &
open http://127.0.0.1:18180/
HTTP API
数据面以 GET 为主;鉴权相关为 POST/GET。响应体在请求缓冲区内拷贝,避免与核心环竞态。
健康检查(始终开放)
GET /health/live
{"status":"ok"}
GET /health/ready
| 状态 | HTTP | body |
|---|---|---|
| READY | 200 | {"status":"ready"} |
| 尚未对账 | 503 | {"status":"not_ready"} |
鉴权路由(公开入口)
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/v1/auth/status | auth_required / authenticated / passkey 计数 |
| POST | /api/v1/auth/login | body {"token":"..."} → Set-Cookie |
| POST | /api/v1/auth/logout | 清 cookie |
| GET/POST | /api/v1/auth/passkey/* | WebAuthn 注册/登录(需 secure context) |
数据 API(token 开启后需鉴权)
| 路径 | 内容 |
|---|---|
GET /api/v1/state | 组合快照:risk_mode、现金/BTC、bid、净值/HWM/DD、version、config_hash… |
GET /api/v1/events | 最近事件 JSON 数组 |
GET /api/v1/agent-runs | 最近 agent_runs(newest first) |
GET /api/v1/equity | 最近 equity_samples |
GET /api/v1/shadow | 实盘净值 vs 同起点 buy-and-hold |
GET /api/v1/candles | 多周期 K 线缓存 bars.{1m,5m,15m,1H,4H,1D} |
GET /api/v1/memories | 最新版本记忆 |
GET /api/v1/system | 进程/agent/paused/disk/CPU/内存/网络/latency 等 |
GET /api/v1/statistics | 资产/交易窗口账本 + 持久化 LLM 调用、Token、市场价成本、覆盖率与近期账本 |
GET /api/v1/decisions | 提案/反思审计事件(含 thesis) |
GET /api/v1/orders | {"orders":[...],"fills":[...]} 投影 |
GET /api/v1/review/chats | 复盘对话最近轮次(newest first,客户端按 id 升序重排) |
GET /api/v1/review/context | 最近一次请求的复盘事件窗口 {decision_id, from, to, events} |
GET /api/v1/review/analytics | AB 因子复盘分析(实验性):成分指标曲线 + IC 表,见下 |
GET /api/v1/review/periodic | 定期复盘报告(newest first,含窗口事实与模型结论) |
GET /api/v1/audit | 定时审计报告(newest first,含完整 findings 与 stats) |
GET /api/v1/intel | 外部签名情报历史(无 signature/nonce;含 grade/score/expired) |
GET /api/v1/sentiment | 恐惧贪婪指数日频曲线:now / class / as_of_ms / points[{t,v}](oldest first;class 由数值重推导) |
POST /api/v1/intel | 推送 alphabound.intel.v1 信封(需 ALPHABOUND_INTEL_HMAC) |
协议、TTL、HMAC 与评分见 投资情报协议。POST 在核心环落库前只入 mailbox(202 Accepted)。未配置 HMAC 时 ingest 返回 503,GET 历史仍可用。
GET /api/v1/shadow
{
"shadow_equity": "400.12",
"bh_equity": "399.80",
"alpha": "0.32",
"entry_bid": "64191",
"bh_btc": "0.00622",
"baseline_capital": "400.00",
"shadow_return": "0.0003",
"bh_return": "-0.0005",
"alpha_return": "0.0008"
}
- 首次有效 bid + 已对账权益时,用当时实盘净值建 BH(全仓假想 BTC,扣 taker fee)。
- 权益相对基准跳变 ≥8% 且 ≥15 USDT(转入/转出)时 自动重标定(事件
SHADOW_BH_REBASE)。 - 主指标看
alpha_return;美元alpha仅作同本金参考。
GET /api/v1/system
{
"software_version": "0.1.0",
"mode": "shadow",
"uptime_ms": 12000,
"paused": false,
"memories": 6,
"private_keys": true,
"private_ws_opt_in": false,
"agent": {"total": 4, "ok": 3, "invalid": 0, "errors": 1, "valid_rate": 75.0, "tool_calls": 8},
"status": {
"disk": "ok",
"disk_free_bytes": 12884901888,
"cpu_pct_x10": 8,
"host_cpu_pct_x10": 41,
"rss_bytes": 16000000,
"mem_used_bytes": 800000000,
"mem_total_bytes": 2000000000,
"net_rx_bps": 12000,
"net_tx_bps": 4000
}
}
GET /api/v1/statistics
Dashboard「统计」页的数据源,含两个子页:资产与交易、模型用量。核心循环从 SQLite 预渲染快照;HTTP 线程不直接查询 SQLite。响应按 UTC 聚合。
顶层仍保留 LLM 字段(last_24h / last_7d / last_30d / all_time / ledger_from / daily_utc / recent 等),并新增 portfolio 与 trading。all_time 是账本累计;ledger_from 是第一条入账时间,更早的调用不会补记:
{
"timezone": "UTC",
"currency": "USD",
"cost_unit": "nano_usd",
"price_basis": "market_estimate",
"last_24h": {
"calls": 12,
"ok_calls": 11,
"usage_reported_calls": 10,
"priced_calls": 10,
"prompt_tokens": 120000,
"cached_prompt_tokens": 30000,
"completion_tokens": 8000,
"input_cost_nano_usd": 25000000,
"output_cost_nano_usd": 5300000
},
"daily_utc": [{"day": "2026-08-21", "totals": {"calls": 12}}],
"by_kind_30d": [{"kind": "proposal", "totals": {"calls": 8}}],
"by_model_30d": [{"model": "DeepSeek-V4-Flash-0731", "totals": {"calls": 12}}],
"recent": [{"ts": "2026-08-21T00:00:00.000Z", "kind": "proposal", "outcome": "ok"}]
}
- 完整性优先:每次模型调用(成功、业务输出无效、超时/HTTP/解析失败)都写一条账本。
usage_reported=false表示 Provider 没有给出 usage;cost_known=false表示模型未识别、usage 缺失或调用失败。二者都不能当作零成本。 - 价格边界:目前识别 DeepSeek V4 Flash 的版本化市场价档;按调用开始时的 UTC 峰/非峰段分别计算缓存命中输入、缓存未命中输入和输出成本,使用整数 nano USD 结算。它是市场价估算,不是供应商、网关或代理商账单;未知模型保持未定价。
- 隐私边界:账本仅保存时间、调用类型、模型、关联 run/decision、延迟、Token、价格档、费用和短错误类别;不保存 Prompt、Completion、Provider URL、密钥或原始错误响应。
- 资产窗口:
portfolio.last_24h/7d/30d来自 1 分钟equity_samples。缺起点/终点或买入持有标记时对应字段为null,不会把未知收益或超额写成 0。 - 交易窗口:
trading.*按订单创建时间和成交时间计入。名义额与数量用 Decimal 累加;未关联订单的成交计入unlinked_fills,非 USDT 费用计入fee_other_fills,都不并入 USDT 费用合计。
GET /api/v1/candles
多周期缓存(核心环周期性刷新;失败保留上一份):
{
"instrument": "BTC-USDT",
"bars": {
"1H": [{"ts_ms": 1786237200000, "o": "64978.2", "h": "65011.4", "l": "64850", "c": "64871.3", "vol": "50.98"}]
},
"funding_rate": "0.00006928",
"next_funding_ms": 1786291200000
}
funding_rate 来自对应永续合约(BTC-USDT-SWAP)公开资金费率;拉取失败时为 null,不会为此新增接口或图表组件。概览 K 线标题栏直接显示该费率。
GET /api/v1/orders
订单 8 状态投影 + 近期 fills;Dashboard「订单」标签与决策详情按 decision_id 关联。
复盘 API(/api/v1/review/*)
复盘请求走邮箱模式:web 线程只入队(立即返回 202 {"ok":true,"queued":true}),核心循环每 tick 出队一件、查库/调 LLM,把结果发布为预渲染 JSON——与「web 线程不碰 SQLite」的单写者架构一致。该通道只读交易状态,写入面仅限 review_chats、记忆与审计事件,接触不到提案与下单路径。
| 方法 | 路径 | Body | 说明 |
|---|---|---|---|
| POST | /api/v1/review/context | {"decision_id","anchor_ts"} | 提取该时点 ±30min 事件窗口 → GET /api/v1/review/context |
| POST | /api/v1/review/chat | {"decision_id","anchor_ts","message"} | 复盘提问(≤1500B);回复落库后出现在 GET /api/v1/review/chats |
| POST | /api/v1/review/summarize | {"decision_id"} | 将对话压缩为一条低置信度 reflection 记忆(HR_<decision_id>) |
| POST | /api/v1/review/periodic | {"cycle":"short"|"long"} | 手动加跑一次定期复盘;结果进 GET /api/v1/review/periodic |
限制:队列深度 4(满载 429);同决策同类请求去重(409);每决策对话上限 40 轮;每次提问至多一轮工具请求(≤6 个,均为只读);LLM 未配置时提问仍会保存并得到降级答复。审计事件:REVIEW_CHAT_OK/FAILED(含 tools 计数)、REVIEW_SUMMARY_OK、PERIODIC_REVIEW。手动定期复盘同样会推进调度游标(下一次自动运行相应顺延)。
GET /api/v1/review/analytics(AB 因子,实验性)
复盘标签页 K 线下方曲线图与 IC 表的数据源。核心循环每分钟基于最近 48 小时的 1m equity 轨迹重算(src/analytics/ab_factor.zig),5 分钟采样输出:
{
"factor_version": "v1",
"experimental": true,
"n_1m": 2880,
"step_minutes": 5,
"orientation": {"pos": 1, "ret": 1, "alpha": 1, "dd": -1, "vol": -1, "mom": 1},
"points": [{"t": 1786237200, "pos": 0.9497, "ret": -0.0012, "alpha": 0.0034,
"dd": 0.0137, "vol": 0.0008, "mom": 0.0021, "ab": -0.42}],
"ic": [{"horizon_minutes": 60, "pos": {"r": 0.12, "n": 140}, "ab": {"r": 0.21, "n": 140}}]
}
- 成分(v1 等权,方向见
orientation):pos仓位占比(btc_value/equity)、ret30m 净值滚动收益、alpha相对 buy-and-hold 的超额(迁移 0006 marks)、dd回撤、vol30m 已实现波动(1m bid 对数收益 std)、mom30m BTC 动量。ab= 各成分 z-score 的定向等权均值(≥3 个成分可用才输出)。 - IC 表:各成分 z 值与
ab对未来 1h / 4h 净值收益的皮尔逊相关,n为配对样本数;样本不足(<30)时r为null。这是"哪些指标与未来表现相关、该不该留在因子里"的观测依据。 - 数据诚实性:迁移 0006 之前的行缺
bid_price/btc_qty/bh_equity标记,依赖它们的成分输出null(前端留白),不回填猜测;1m 轨迹出现 >2× 窗口的缺口时滚动窗口同样置null。 - 边界:纯研究视图。因子不进提案 prompt、不进准入/风控/下单路径(
src/agent、src/risk、src/execution禁止 import analytics 模块);调整成分或权重必须升factor_version。
定时审计(/api/v1/audit 与告警铃铛)
核心循环内置确定性规则审计器(src/observability/auditor.zig,判定路径无 LLM),默认每 4 小时([audit] interval_ms,0 关闭,下限 10 分钟)对五个面自检:
| 检查面 | 内容 |
|---|---|
| llm | run 成功率、连续失败、僵尸检测(超 3× 决策周期无提案) |
| tools | 工具调用缺失、延迟、MARKET_STALE 频次 |
| data | 净值恒等式重算、HWM 单调、drawdown 自洽、样本新鲜度、SQLite quick_check |
| flow | 触发→提案→准入→反思事件链完整性、备份、严重事件(FAULT 等) |
| self | 审计自身按时、风险模式非 NORMAL 可见 |
结果:完整报告落库 audit_reports(GET /api/v1/audit 可回放);事件流写 AUDIT_OK/WARN/ALERT;/api/v1/system 的 audit 块驱动 Dashboard 右上角告警铃铛(黄=警告、红=告警,点开看发现明细与历史)。启动即跑一次,之后按间隔。
规划中
| 接口 | 用途 | 状态 |
|---|---|---|
GET /api/v1/trades/{id} | 单笔情节完整回放 | 待做 |
WS /ws/v1/events | 增量推送 | 待做 |
SQLite 备份
主环约每小时调用 SQLite Backup API,写入 <db_path>.bak,事件 BACKUP_DONE / BACKUP_FAILED。
安全边界
- 无交易按钮暴露在公网 — 清仓 / 暂停 / target-weight 走本机
--control。 - 响应中的密钥 — API 状态快照不含凭证。
- Agent 不读 HTTP — Dashboard 是人的只读窗;MCP 同样只读。
- 对外暴露 — 长随机 token + HTTPS 反代;详见 鉴权与 MCP。
curl 速查
HOST=http://127.0.0.1:18180
AUTH=(-H "Authorization: Bearer ${ALPHABOUND_API_TOKEN:-}")
curl -sS "$HOST/health/live"
curl -sS "$HOST/health/ready"
curl -sS "${AUTH[@]}" "$HOST/api/v1/state" | jq .
curl -sS "${AUTH[@]}" "$HOST/api/v1/shadow" | jq .
curl -sS "${AUTH[@]}" "$HOST/api/v1/orders" | jq .
curl -sS "${AUTH[@]}" "$HOST/api/v1/decisions" | jq '.[0:3]'
curl -sS "${AUTH[@]}" "$HOST/api/v1/system" | jq .
curl -sS "${AUTH[@]}" "$HOST/api/v1/statistics" | jq .
curl -sS -o /dev/null -w "%{http_code}\n" "$HOST/"
只读 IDE 接入见 鉴权与 MCP 与仓库 tools/alphabound-mcp/。
鉴权与 Analytics MCP
Dashboard / API 可选用 Token + Session + Passkey 保护数据面;外部 Agent 通过 MCP 拉取同一批 HTTP API,并可用 submit_intel 转发已签名的情报信封。控制面(pause / flatten / 下单)永远不走 HTTP 或 MCP。
详细技术说明与仓库文件同步:
Dashboard Auth & Analytics MCP
Auth model
| Client | Credential |
|---|---|
| Browser Dashboard | Token login → ab_session HttpOnly cookie; optional Passkey |
| MCP / scripts | Authorization: Bearer <token> or X-API-Token: <token> |
| Health probes | Always open: /health/live, /health/ready |
- Empty
ALPHABOUND_API_TOKEN: auth disabled (local dev default). - Token set: all
/api/v1/*data routes return 401 without token/session; HTML shell stays public and shows login gate. - Passkey register requires an existing session (bootstrap with token once).
- Credentials file:
<db_path>.webauthn(gitignore via*.db*patterns / var layout).
Env
ALPHABOUND_API_TOKEN=... # long random (≥24 chars; 32+ recommended for public)
ALPHABOUND_WEBAUTHN_RP_ID=localhost # hostname only
ALPHABOUND_WEBAUTHN_ORIGIN=http://127.0.0.1:8080
ALPHABOUND_TRUST_PROXY=1 # ONLY behind a trusted TLS/proxy edge
ALPHABOUND_TRUSTED_PROXY_HOPS=1 # XFF: use Nth IP from the right (default 1)
X-Forwarded-For can be forged
| Setup | Client can spoof lockout key? |
|---|---|
TRUST_PROXY off (default) | No — FailGuard keys on TCP peer only |
TRUST_PROXY=1 + take left-most XFF | Yes — attacker rotates forged IPs, bypasses lockout |
TRUST_PROXY=1 + take right-most (our default hops=1) | No for a single append-style proxy that always adds the real peer |
Rules:
- Default off. Direct internet → alphabound: never enable trust proxy.
- Enable only when Azure App Gateway / Front Door / nginx terminates TLS and is the only path to the process (NSG / private bind / no public :8080).
- We parse XFF as append-chain and pick
hopsfrom the right (default 1 = right-most). Left-most client junk is ignored. - Prefer edge WAF rate limits; FailGuard is in-process last line. Peer IP of the proxy alone would collapse all users into one bucket if XFF were missing — still fail-closed for brute force.
Brute-force / rate limits
When token auth is enabled, the single-threaded web loop keeps an in-memory FailGuard:
| Signal | Counts as failure? | Effect |
|---|---|---|
POST /api/v1/auth/login wrong token | yes | per-IP fail counter |
POST .../passkey/login bad assertion | yes | per-IP fail counter |
Authorization / X-API-Token wrong | yes | per-IP fail counter |
| Missing credential (browser first paint) | no | plain 401 |
| Successful token/passkey login | clears IP slot |
Defaults (compile-time in src/web/auth.zig):
- 8 failures / IP / 15 min window → lockout 15 min → HTTP 429 +
Retry-After - Global login flood: 60 login POSTs / rolling minute (all IPs) → 429
This is process-local (resets on restart). Put Azure Front Door / WAF / nginx in front for edge rate limits; FailGuard is the in-process last line.
Public exposure checklist:
- Long random
ALPHABOUND_API_TOKEN(e.g.openssl rand -hex 32) - HTTPS terminator;
ALPHABOUND_TRUST_PROXY=1only if the edge is trusted and clients cannot reach the app directly - Prefer session cookie / passkey after first login; do not put the raw token in browser JS storage
- Keep
/health/*open for probes; never put secrets in health bodies - Do not expose dashboard port publicly without the proxy; forged XFF is useless if
TRUST_PROXYstays off
Passkey / WebAuthn 限制(重要)
浏览器要求 secure context:
| 打开方式 | Token 登录 | Passkey |
|---|---|---|
http://127.0.0.1:8080 / http://localhost:8080 | ✅ | ✅ |
https://your-host/... | ✅ | ✅ |
http://10.x.x.x:8080(内网 HTTP IP) | ✅ | ❌ API 被禁用 |
内网直连 IP 时请用 Token。要用 Passkey:
ssh -L 8080:127.0.0.1:8080 USER@HOST
# 浏览器打开 http://127.0.0.1:8080/
服务端会按请求 Host 解析 rpId/origin;仍无法绕过浏览器对非 localhost HTTP 的限制。
MCP (ideal remote path)
- Enable token on daemon (
secrets.env→ deploy). - Point an IDE at the MCP via npx auto-install (same token +
ALPHABOUND_API_BASE):
{
"mcpServers": {
"alphabound": {
"command": "npx",
"args": ["-y", "alphabound-mcp"],
"env": {
"ALPHABOUND_API_BASE": "http://127.0.0.1:18180",
"ALPHABOUND_API_TOKEN": "YOUR_TOKEN"
}
}
}
}
npx -y alphabound-mcp install --client copilot
# before npm publish: --source github
# from a clone: node tools/alphabound-mcp/src/index.js install --source local --client copilot
- stdio is the IDE default (
npx -y alphabound-mcp).npx -y alphabound-mcp --httpis a small remote tool gateway (bind loopback; tunnel as needed). - The same binary is a CLI for every MCP tool. Token comes from
ALPHABOUND_API_TOKEN(orDASHBOARD_API_TOKEN) at call time:
export ALPHABOUND_API_BASE=http://127.0.0.1:18180
export ALPHABOUND_API_TOKEN=YOUR_TOKEN
npx -y alphabound-mcp tools
npx -y alphabound-mcp get_system
npx -y alphabound-mcp submit_intel --file envelope.json
Hard rule: MCP does not place orders, flatten, resume, or read secrets.
Control stays on --control / local admin.
The sole write is submit_intel: a pre-signed alphabound.intel.v1
envelope forwarded to POST /api/v1/intel. MCP never holds
ALPHABOUND_INTEL_HMAC. See docs/INTEL.md.
See also: docs/AGENT_ANALYTICS_MCP_PLAN.md.
快速启用
# secrets.env(chmod 600)
ALPHABOUND_API_TOKEN=$(openssl rand -hex 32)
# 浏览器打开的 origin(本机)
ALPHABOUND_WEBAUTHN_RP_ID=localhost
ALPHABOUND_WEBAUTHN_ORIGIN=http://127.0.0.1:18180
重启 daemon 后:
curl -sS http://127.0.0.1:18180/api/v1/auth/status
# auth_required=true 时数据 API 需 token/session
MCP
IDE / Copilot 用 npx -y 自动安装,不必先 clone:
{
"mcpServers": {
"alphabound": {
"command": "npx",
"args": ["-y", "alphabound-mcp"],
"env": {
"ALPHABOUND_API_BASE": "http://127.0.0.1:18180",
"ALPHABOUND_API_TOKEN": "YOUR_TOKEN"
}
}
}
}
npx -y alphabound-mcp install --client copilot
# 尚未发布到 npm 时:--source github
# 本仓库源码:node tools/alphabound-mcp/src/index.js install --source local --client copilot
从源码跑 stdio / HTTP / CLI(token 走环境变量):
cd tools/alphabound-mcp
npm install
export ALPHABOUND_API_BASE=http://127.0.0.1:18180
export ALPHABOUND_API_TOKEN=YOUR_TOKEN # 与 daemon 相同
npx alphabound-mcp # stdio,给 IDE
npx alphabound-mcp tools # 列出全部 MCP 工具
npx alphabound-mcp get_system # CLI 调用同一工具面
# 或本机 HTTP 网关:
# npx alphabound-mcp --http
工具列表见 tools/alphabound-mcp/README.md。
规划背景:AGENT_ANALYTICS_MCP_PLAN.md。
投资情报协议
AlphaBound 不自行采集情报。外部 Agent 推送签名信封;Dashboard「情报」页与 MCP 共用同一 HTTP 面。
alphabound.intel.v1
AlphaBound does not collect investment intel. External collector agents push a signed envelope. The daemon stores it, lists it on Dashboard / MCP, and may feed a ranked subset into the slow decision context. Intel never enters the risk kernel, order planner, or admin control plane.
Payloads are untrusted data, not instructions.
Envelope
{
"schema": "alphabound.intel.v1",
"id": "intel_etf_flow_01",
"source_id": "collector.macro",
"kind": "macro",
"instrument": "BTC-USDT",
"headline": "US spot BTC ETF saw net inflows",
"body": "Issuers reported a second consecutive session of net creations.",
"claims": [{"text": "ETF creations continued", "polarity": "bull"}],
"tags": ["etf", "flows"],
"refs": [{"url": "https://example.com/note", "title": "issuer print"}],
"confidence": 0.62,
"as_of_ms": 1700000000000,
"expires_ms": 1700604800000,
"nonce": "0123456789abcdef0123456789abcdef",
"signature": "<64 lowercase hex>"
}
| Field | Rule |
|---|---|
id | intel_ + [A-Za-z0-9_-], 8–80 chars |
source_id | 3–64, starts with a letter |
kind | macro news flow regulatory narrative onchain |
instrument | BTC-USDT or * |
headline | 8–120 chars, UTF-8, no HTML / control chars |
body | 1–800 chars |
claims | 1–6 {text, polarity}; polarity bull/bear/neutral |
tags | ≤8, [A-Za-z0-9_-] |
refs | ≤3; url must be https:// |
confidence | 0.000–1.000 |
nonce | 16–64 lowercase hex |
as_of_ms | not more than 5 minutes in the future |
expires_ms is optional. Default / max TTL by kind:
| kind | default | max |
|---|---|---|
| news | 12h | 24h |
| onchain | 24h | 72h |
| flow / narrative | 48h | 72h |
| macro | 7d | 14d |
| regulatory | 7d | 30d |
Ingest is append-only. Duplicate id or same-day dedup_key
(sha256(kind|instrument|normalized_headline|utc_day)) is ignored.
HMAC
Canonical UTF-8 string:
v1|{id}|{source_id}|{kind}|{instrument}|{headline}|{body}|{conf_3dp}|{as_of_ms}|{expires_ms}|{nonce}
conf_3dp is always three decimals (0.620). Signature is lowercase hex
HMAC-SHA256(ALPHABOUND_INTEL_HMAC, canonical). Key length ≥ 16; set in
secrets.env (never in git). Empty key disables ingest; GET history still works.
# collector signs locally — AlphaBound / MCP never receive the key over the wire
printf '%s' "$CANONICAL" | openssl dgst -sha256 -hmac "$ALPHABOUND_INTEL_HMAC" -hex
Per-source rate limit: 30 accepted envelopes / hour. Queue depth 8.
How AlphaBound uses it
Live score = source_trust × confidence × freshness (all 0–1, milles internally).
Default source_trust is 1.0.
| score | grade | context |
|---|---|---|
| ≥ 0.700 | A | yes |
| ≥ 0.450 | B | yes |
| ≥ 0.200 | C | yes |
| else / expired | D | no |
Up to 8 ranked live A/B/C items go into the agent intel array. The model may
cite an id in thesis. Intel cannot change risk limits or force a trade.
Dashboard 情报 tab and GET /api/v1/intel show history without
signature / nonce.
Push paths
POST /api/v1/intel— same auth as other/api/v1/*(token / session).- MCP
submit_intel— forwards that POST. The collector signs first. - MCP
list_intel—GET /api/v1/intel.
MCP still cannot place orders, flatten, or read secrets.
Storage
SQLite table intel (migration 0009_intel.sql). Core loop is the only writer;
the web thread enqueues validated records.
运行模式
[exchange] mode 控制「钱是不是真的、单会不会发」。
| 模式 | 行情 | 账户 | 下单 | 适用阶段 |
|---|---|---|---|---|
| shadow | 实网公共行情 | 模拟(initial_capital) | 否 | 开发、CI、观察链路 |
| demo | OKX 模拟盘 | Demo 账户 | 模拟盘单 | 无实盘密钥时的联调 |
| live | 实盘 | 小额实盘子账号 | 真单 | 当前默认实盘路径(显式 opt-in) |
shadow(默认)
- 连接 OKX 公共 REST(时间、ticker 等),不需要 API Key。
- 启动时注入模拟账户(
initial_capitalUSDT,BTC=0),reconcile_result标记 clean。 - 风险内核、状态机、事件落库、Dashboard 全链路真实代码路径。
- Agent 若接入,提案可算、可审计,但执行层不得对交易所发单。
适合:
./zig-out/bin/alphabound --config dev.toml --ticks 20
demo(OKX 模拟盘)
- 使用 OKX 模拟盘密钥 + 请求头
x-simulated-trading: 1(环境变量OKX_SIMULATED=1必填)。 - 引擎现金/BTC 来自私有 REST 余额(不再用 shadow 的
initial_capital)。 - Agent 提案经 Risk 准入后:
APPROVE/REDUCE→ planner → 市价/限价单;HTTP 失败 →UNKNOWN→ 查询后处置。 - Admin:
cancel-all/flatten/target-weight走同一执行栈。
export OKX_API_KEY=...
export OKX_API_SECRET=...
export OKX_API_PASSPHRASE=...
export OKX_SIMULATED=1
# config: mode = "demo"
./zig-out/bin/alphabound --config config/local.toml --agent-once --ticks 8
兼容:历史部署可用
mode=demo+OKX_REAL_MONEY_OK=1跑小额真金;boot 会告警,请改mode=live。
live(小额实盘 — 当前路径)
- 真金白银,设计默认实验资金约 100 USDT 子账号。
- 已解锁,但必须同时满足:
mode = "live"OKX_*密钥(Read+Trade,禁止 Withdraw)OKX_REAL_MONEY_OK=1(显式 opt-in,从不默认)- 不得设
OKX_SIMULATED=1(live 拒绝模拟盘 header)
- Boot 打印醒目 banner;启动时探测 key 权限,带 withdraw 的 key 直接 FATAL。
- 风险边界 = 子账号余额 +
max_drawdown;主账户/大资金不在范围内。
export OKX_API_KEY=...
export OKX_API_SECRET=...
export OKX_API_PASSPHRASE=...
export OKX_REAL_MONEY_OK=1
# config: mode = "live"
./zig-out/bin/alphabound --config /etc/alphabound/alphabound.toml
# 日志: [boot] *** LIVE REAL-MONEY AUTHORIZED ...
# [ready] mode=live ... exec=live
Gate / 运维清单见 GATE3_CHECKLIST.md。
「更大资金 / MVP 成立判定」仍是路线图 Phase 4 的运维与验收问题,不是再开一把代码锁。
模式与风险状态机正交
无论哪种 mode,进程内风险模式仍是:
NORMAL → EXIT_ONLY → FLATTENING → HALTED
- 数据陈旧 / 未对账 → fail-closed,常从
EXIT_ONLY起步 - 回撤边界触发 →
FLATTENING→ 完成后可HALTED HALTED不自动恢复交易,需人工resume(含 operator_reset)
shadow 下也会演练状态机,只是不会碰到真实资金。
切换操作建议
# 1. 改配置(新文件或发版产物),不要热改内存
mode = "live" # 或 demo / shadow
# 2. 自检
alphabound --config /etc/alphabound/alphabound.toml --self-check
# 3. 原子发布 / restart(见运维章)
sudo systemctl restart alphabound
curl -sS --retry 30 --retry-delay 1 --fail \
http://127.0.0.1:8080/health/ready
切换到 live 时在变更单中记录:config_hash、软件版本、操作人、回滚版本路径。
运维部署
目标形态:单文件二进制 + systemd + SQLite 本地盘。生产 VM 不装 Docker / 运行时 Node / Python 业务依赖。
公开通用步骤见仓库 deploy/README.md;真实主机名 / IP / URL 只写本机 DEPLOY.local.md(gitignore)。
目录约定
| 路径 | 用途 |
|---|---|
/opt/alphabound/releases/<sha>-<ts>/ | 不可变发布目录(二进制) |
/opt/alphabound/current | symlink → 当前版本(原子切换) |
/etc/alphabound/alphabound.toml | 主配置 |
/etc/alphabound/secrets.env | 密钥,0600 |
/etc/alphabound/prompts/ | Prompt 树 |
/var/lib/alphabound/trading.db | SQLite(WAL 同目录) |
/var/lib/alphabound/deploys.log | 部署记录(soak 可识别计划重启) |
系统用户
sudo useradd --system --home /var/lib/alphabound --shell /usr/sbin/nologin alphabound
sudo mkdir -p /var/lib/alphabound /etc/alphabound/prompts
sudo chown -R alphabound:alphabound /var/lib/alphabound
sudo chown -R root:alphabound /etc/alphabound
sudo chmod 750 /etc/alphabound
sudo chmod 640 /etc/alphabound/alphabound.toml
sudo chmod 600 /etc/alphabound/secrets.env
systemd
仓库模板:deploy/alphabound.service
sudo cp deploy/alphabound.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now alphabound
sudo systemctl status alphabound
journalctl -u alphabound -f
单元要点:
EnvironmentFile=/etc/alphabound/secrets.envProtectSystem=strict+ReadWritePaths=/var/lib/alphaboundNoNewPrivileges/PrivateTmpRestart=always+RestartSec=5(崩溃后重新对账,不假设旧内存状态)
远端助手脚本
需本机 sshx 与 HOST=(主机名以 DEPLOY.local.md 为准,勿写回 public 文档):
HOST=<sshx-name> ./scripts/deploy-remote.sh
HOST=<sshx-name> ./scripts/check-remote.sh
HOST=<sshx-name> ./scripts/soak-report.sh 24
HOST=<sshx-name> ./scripts/restore-drill.sh
HOST=<sshx-name> ./scripts/rollback-remote.sh
HOST=<sshx-name> ./scripts/kill9-drill.sh
HOST=<sshx-name> ./scripts/restart-drill.sh 3
./scripts/llm-outage-drill.sh
check-remote / soak-report / gate2-report 在开启 API token 时会带鉴权头。
发布与回滚(原子 symlink)
推荐走 deploy-remote.sh / install-remote.sh:每次安装暂存
/opt/alphabound/releases/<sha>-<ts>/,原子翻转 current;/health/ready 失败则自动回滚上一版本;默认保留最近 5 个 release。
手动等价流程:
# 构建目标 OS/arch 后
sudo mkdir -p /opt/alphabound/releases/manual-$(date +%s)
sudo cp zig-out/bin/alphabound /opt/alphabound/releases/manual-.../
sudo ln -sfn /opt/alphabound/releases/manual-... /opt/alphabound/current
sudo systemctl restart alphabound
curl -fsS --retry 30 --retry-delay 1 http://127.0.0.1:8080/health/ready
备份
进程内约每小时 SQLite Backup API → <db_path>.bak。额外离线备份:
stamp=$(date -u +%Y%m%dT%H%M%SZ)
sqlite3 /var/lib/alphabound/trading.db \
".backup '/var/lib/alphabound/trading-$stamp.db'"
恢复演练(建议每周):HOST=... ./scripts/restore-drill.sh
Dashboard 访问
默认:SSH 本地转发,防火墙不对 Dashboard 端口放行公网。
ssh -N -L 8080:127.0.0.1:8080 ops@YOUR_HOST
公网 edge(可选):daemon 仍绑 loopback,nginx 终止 TLS;见 deploy/nginx-alphabound.conf.example。
必需环境变量(secrets):
ALPHABOUND_API_TOKEN— 长随机串ALPHABOUND_TRUST_PROXY=1+ALPHABOUND_TRUSTED_PROXY_HOPS=1(仅受信任反代后)ALPHABOUND_WEBAUTHN_RP_ID/ALPHABOUND_WEBAUTHN_ORIGIN与公网 hostname 一致
详见 鉴权与 MCP。
Admin on the box
sudo -u alphabound /opt/alphabound/current/alphabound \
--config /etc/alphabound/alphabound.toml --control status
资源与告警(建议)
| 信号 | 为何重要 |
|---|---|
| RSS / fd 数量 | 长稳泄漏 |
| 磁盘可用 & DB 目录 | 满盘 → 停新交易 / HALTED |
| WAL 文件大小 | checkpoint 是否健康 |
health/ready 连续失败 | 对账或依赖故障 |
| 风险模式 ≠ NORMAL 持续时长 | 边界或数据问题 |
journal 落库失败日志 | 审计断裂 |
| soak-report 窗口 | 计划部署 vs 意外退出 |
OKX / 网络
- API Key Read+Trade,禁止 Withdraw;出口公网 IP 加入白名单
- 出站:OKX、LLM、必要工具域名;无通用网页爬取权限给 Agent 进程
- NTP 可靠;日志统一 UTC
mode=live须OKX_REAL_MONEY_OK=1,且不得OKX_SIMULATED=1
安全检查清单
-
secrets.env0600,不进 git - 服务用户无 shell、无 sudo
- web 为 127.0.0.1,或仅经受信任 TLS 反代
-
对外暴露时已设
ALPHABOUND_API_TOKEN;TRUST_PROXY仅反代后开启 -
mode与资金环境一致(live 有变更单 + 子账号) - 上一 release 可回滚;备份恢复演练未过期
容器分发与 GHCR 发布见 Docker 与 GHCR。
本机管理控制
AlphaBound 管理命令不走网络:CLI 写入 DB 同目录控制文件,daemon 主环每 tick 消费一次。
命令
./zig-out/bin/alphabound --config config/local.toml --control pause
./zig-out/bin/alphabound --config config/local.toml --control resume
./zig-out/bin/alphabound --config config/local.toml --control reconcile
./zig-out/bin/alphabound --config config/local.toml --control cancel-all
./zig-out/bin/alphabound --config config/local.toml --control flatten
./zig-out/bin/alphabound --config config/local.toml --control 'target-weight=0.05'
./zig-out/bin/alphabound --config config/local.toml --control shutdown
./zig-out/bin/alphabound --config config/local.toml --control status
| 命令 | 行为 |
|---|---|
pause | 停止 agent 决策环;行情/风险/对账继续 |
resume | 恢复 agent;若风险态为 HALTED,同时 operator_reset → EXIT_ONLY(再经对账回到 NORMAL) |
reconcile | 立即触发一次私有 REST 余额对账 |
cancel-all | 取消开放订单。Shadow:只记审计事件;demo/live(交易模式):拉 pending 并逐笔 cancel-order |
flatten | 操作员退出:进入 FLATTENING,主环自动市价卖向 weight=0;BTC 低于 lot dust 后 flatten_complete → HALTED |
target-weight=W | 操作员目标仓位(0–1 小数);经同一 planner/执行栈;写审计锚点 ADMIN_TARGET_WEIGHT |
shutdown | 等价安全停机(与 SIGTERM 相同排空路径) |
status | 读 *.control.state(daemon 写入) |
控制文件:var/trading.control(one-shot,消费后删除)
状态文件:var/trading.control.state
Dashboard /api/v1/system 含 "paused": true|false。
安全
- 控制面不暴露为 HTTP API;MCP 也不能 pause/flatten/下单。
target-weight/flatten在 shadow 下不触达交易所;demo/live 会真实发单(live 须已 opt-in)。- 生产操作请用服务用户:
sudo -u alphabound /opt/alphabound/current/alphabound --config ... --control ...
Docker 与 GHCR 发布
设计默认生产形态仍是 Azure VM + systemd 裸二进制。Docker 镜像用于:
- 可复现的 release 分发(GHCR)
- 本地 / CI shadow 实验室
- 多架构(
linux/amd64(arm64 可后续加回))预构建
不是「上了 Docker 就等于生产就绪」——真钱闸门见 路线图。
镜像
| 仓库 | ghcr.io/talkincode/alphabound |
| 默认标签 | 仅 git tag v* 发布:X.Y.Z、X.Y、latest、sha-<short> |
| 用户 | uid 10001 alphabound(非 root) |
| 配置 | 镜像内 /etc/alphabound/alphabound.toml(config/docker.toml) |
| 数据卷 | /var/lib/alphabound(SQLite) |
| Web | 容器内 0.0.0.0:8080;宿主机务必只映射 127.0.0.1 |
拉取
# 公共包可直接拉;若包仍是 private,先登录
echo $GHCR_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
docker pull ghcr.io/talkincode/alphabound:0.1.0 # 推荐:与 git tag v0.1.0 对应
docker pull ghcr.io/talkincode/alphabound:latest # 最近一次 v* 发布
首次 push 后若组织默认 private package,在 GitHub → Packages → alphabound → Package settings → Change visibility → Public(或保持 private 仅 CI/内部拉)。
运行(shadow)
docker run --rm \
--name alphabound \
-p 127.0.0.1:8080:8080 \
-v alphabound-data:/var/lib/alphabound \
ghcr.io/talkincode/alphabound:latest
curl -sS http://127.0.0.1:8080/health/live
open http://127.0.0.1:8080/
自检:
docker run --rm ghcr.io/talkincode/alphabound:latest \
--config /etc/alphabound/alphabound.toml --self-check
Compose
docker compose up --build # 本地构建
IMAGE=ghcr.io/talkincode/alphabound:latest docker compose up
docker-compose.yml 已写死 127.0.0.1:8080:8080。
自定义配置
docker run --rm -p 127.0.0.1:8080:8080 \
-v "$PWD/my.toml:/etc/alphabound/alphabound.toml:ro" \
-v alphabound-data:/var/lib/alphabound \
ghcr.io/talkincode/alphabound:latest
[web] bind 在容器内应为 0.0.0.0:<port>,否则 port-publish 进不来。配置解析拒绝任意公网 IP 绑定,只允许 127.0.0.1 与 0.0.0.0。
CI 发布
工作流:.github/workflows/release-docker.yml
| 触发 | 行为 |
|---|---|
push main | 不构建镜像(只跑 CI 编译/测试) |
push tag v* | 构建并推送 X.Y.Z、X.Y、latest、sha-* |
workflow_dispatch | 手动;可附额外 tag(无 semver 时主要靠 tag_extra / sha) |
使用 docker/build-push-action + Buildx,linux/amd64,GHA cache,provenance/SBOM 开启。权限:packages: write(GITHUB_TOKEN)。
构建上下文必须包含 prompts/(嵌入二进制);.dockerignore 不得排除 prompts/**。
打版本 release
git tag -a v0.1.0 -m "alphabound v0.1.0"
git push origin v0.1.0
# Actions → Release Docker → ghcr.io/talkincode/alphabound:0.1.0 等
本地构建
docker build -t alphabound:local .
docker run --rm -p 127.0.0.1:8080:8080 alphabound:local --ticks 3
需要 Docker Buildx(多架构时)与出网下载 Zig 0.16.0。
安全注意
- 不要把
secrets.env打进镜像层;用 runtime 挂载 / orchestrator secret。 - 宿主机端口只绑
127.0.0.1;远程用 SSH tunnel。 - 镜像默认
mode = shadow,无交易密钥也跑得起来。 - 容器 ≠ 过 Gate 3;Demo/Live 仍走验收矩阵。
故障排查
按「先安全、后功能」顺序:确保不会错误增仓,再修观察面。
启动失败
FATAL config
| 可能原因 | 处理 |
|---|---|
| TOML 语法错误 | 用编辑器 / taplo 校验 |
web.bind 不是 127.0.0.1:port | 改回 loopback |
poll_interval_ms < 200 | 提高间隔 |
initial_capital ≤ 0 | 设正数 |
| 路径无读权限 | 检查用户与 SELinux/AppArmor |
alphabound --config /path/to.toml --self-check
FATAL db open
- 父目录不存在或不可写 →
mkdir+chown alphabound - 磁盘满 → 腾挪 / 扩容;不要删 WAL 凑合
- 文件损坏 → 禁止静默新建空库继续 live 交易;走备份恢复(见 运维)
FATAL web listen / [web] server stopped: AddressInUse
- 端口占用:
lsof -nP -iTCP:18180 -sTCP:LISTEN(或配置里的 port) - 本机
18080常被其他桌面工具占用 →config/local.toml默认改用 18180 - 改
[web].bind = "127.0.0.1:<空闲端口>"后重启 - 权限或 bind 地址被改坏(只能 loopback / 容器
0.0.0.0) - 注意:web 线程 listen 失败时 shadow 行情环仍可继续;只是 Dashboard 不可用
连接与 READY
[connect] unreachable
- 出网 / DNS / 代理
- OKX 地域限制 → 换 Region 或合规网络路径
rest_url配错
shadow 在连接失败时不会假装 READY 去交易。
private balance FAILED: ip_whitelist
OKX 返回 50110:当前公网 IP 不在该 API Key 白名单。
curl -sS https://api.ipify.org; echo
# 在 OKX → API → 编辑 Key → IP 白名单中加入上述地址
# 建议:只读权限 Key,专用于 shadow/Gate1 对账
签名与 passphrase 已通过(否则会是 invalid_sign / invalid_passphrase)。shadow 仍会用公共行情 + 模拟资金进入 READY;仅私有对账未通。
OKX credentials absent 但已 source secrets
- passphrase 含
&等字符时必须用./scripts/load-okx-keychain.sh生成的 quotedsecrets.env,或 export 时加引号 - 变量名必须是
OKX_API_KEY/OKX_API_SECRET/OKX_API_PASSPHRASE(不是OKX_SECRET_KEY) - 确认子进程继承环境:
python3 -c 'import os; print(len(os.environ.get("OKX_API_KEY","")))'
/health/ready 一直 503
- 仍在 BOOTING/CONNECTING/RECONCILING
- 对账未 clean(demo/live 私有数据不一致)
- 看 journal:
journalctl -u alphabound -n 100 --no-pager
live 探针绿但模式是 EXIT_ONLY
常见于:行情 freshness 不足、unresolved_orders、启动 fail-closed。这是保护,不是单纯 bug。查:
curl -s http://127.0.0.1:8080/api/v1/state | jq '{risk_mode,reconciled,drawdown}'
数据与审计
事件不涨
- 进程是否真在跑
[journal] append failed→ 磁盘、权限、SQLite busy- 直接查库:
sqlite3 /var/lib/alphabound/trading.db "SELECT seq,type,ts FROM events ORDER BY seq DESC LIMIT 20;"
Dashboard 空白 / 不是 HTML
- 是否打到错误端口
- 旧二进制未嵌入 dashboard(升级后确认
GET /Content-Type 含text/html) - 浏览器控制台看
/api/v1/state是否 CORS/连接失败(本机不应有 CORS 问题)
风险模式异常
| 现象 | 优先动作 |
|---|---|
| 突然 FLATTENING | 检查回撤是否触界;不要为了「救策略」改 max_drawdown 热重启乱调 |
| HALTED | 人工审查事件与持仓;恢复交易走发版/变更流程,无自动爬出 |
| 频繁 EXIT_ONLY | 网络抖动、时钟、WS 断线;修基础设施,而非放松 freshness |
性能
- CPU 打满:确认没有过密
poll_interval_ms;单写者状态机本就单线程热点 - RSS 爬升:抓 24h 曲线;怀疑泄漏时用固定
--ticks对比重启基线 - 磁盘:WAL 过大时检查是否有长事务/备份锁
安全事件
若怀疑密钥泄漏:
- 立刻在 OKX 作废 API Key
- 停 live / 切 EXIT 能力优先的维护窗口
- 轮换
secrets.env,限制新 Key 权限与 IP - 审计
events/ 交易所成交是否与decision_id可对上
收集诊断包(脱敏)
alphabound --version
cat /etc/alphabound/alphabound.toml # 无密钥
curl -s localhost:8080/api/v1/state
curl -s localhost:8080/health/ready
journalctl -u alphabound -n 200 --no-pager
sqlite3 /var/lib/alphabound/trading.db "PRAGMA integrity_check;"
# 不要打包 secrets.env;日志已依赖 redaction,仍人工扫一眼
测试侧回归
改代码后:
zig build test --summary all
./scripts/build-docs.sh # 若动了手册链接
CI 应保持绿:zig build + zig build test + --self-check + mdbook build。
私有 WebSocket 探测
默认不在启动时做 OKX private WS login 探测(避免慢 DNS/IPv6 与实验性传输路径拖慢 READY)。
- Gate 1 账户可见性依赖 REST
GET /api/v5/account/balance周期对账(已验证)。 - 需要尝试 private WS 时:
export ALPHABOUND_PRIVATE_WS=1后启动。 - 若日志出现
login_read_failed且 detail 含 close881a0fa4…(OKX 4004 / No data received): TLS upgrade(101) 已成功,但 login 帧在std.http.Client原始连接路径上仍不稳定;协议编解码单测仍有效,长连修复前请继续依赖 REST。
Dashboard 鉴权
401 unauthorized on /api/v1/*
- 已设置
ALPHABOUND_API_TOKEN时,脚本需带:
curl -sS -H "Authorization: Bearer $ALPHABOUND_API_TOKEN" http://127.0.0.1:18180/api/v1/state
- 浏览器:打开 Dashboard 登录门,用同一 token;或先
POST /api/v1/auth/login。 - 运维脚本:确保远端
secrets.env与本机check-remote/soak-report能读到 token。
Passkey 不可用 / passkey API 禁用
- 浏览器要求 secure context:
https://…或http://127.0.0.1/http://localhost。 - 内网
http://10.x.x.x仅 Token 登录可用;需要 Passkey 时 SSH 转到本机 loopback。 - 核对
ALPHABOUND_WEBAUTHN_RP_ID/ORIGIN与地址栏一致(或依赖 Host 自动解析)。
429 rate_limited
- FailGuard:错误 token/登录失败过多会按 IP 锁定一段时间。
- 等
Retry-After,或重启进程清内存计数(生产仍应修凭证而非依赖重启)。
四支柱架构
AlphaBound 用一句话约束产品形态:
宽信息入口,慢投资决策,快风险反应,窄交易出口。
四者正交:扩大观察面不会自动加快下单;加快风险反应不依赖 LLM;出口永远收敛到同一条准入路径。
总览
┌──────────────────────────────────────────────┐
│ 宽信息入口 (tools) │
│ market / derivatives / onchain / news / … │
│ ToolResult.data = 不可信数据 │
└──────────────────────┬───────────────────────┘
▼
┌──────────────────────────────────────────────┐
│ 慢投资决策 (agent + memory) │
│ Context → Investigate → Propose → Reflect │
│ 可 HOLD · 可超时 · 不阻塞关键路径 │
└──────────────────────┬───────────────────────┘
│ Decision Proposal
▼
┌──────────────────────────────────────────────┐
│ 窄交易出口 │
│ Schema 校验 → Risk 准入 → 幂等 Execution │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────┴───────────────────────┐
│ 快风险反应 (critical path, 无 LLM) │
│ Exchange → State Engine → Equity / SM / Admit │
└──────────────────────────────────────────────┘
支柱 ↔ 代码
| 支柱 | 含义 | 主要模块 |
|---|---|---|
| 宽信息入口 | 工具只扩展观察,不规定顺序;载荷不可信 | src/tools/registry.zig |
| 慢投资决策 | 稳定能力边界 + 结构化提案/反思 + 长期记忆 | src/agent/* · src/memory/store.zig |
| 快风险反应 | 行情进进程后确定性估值与状态机 | src/risk/* · src/core/state.zig |
| 窄交易出口 | 唯一出口:Proposal → Admission → Orders | src/agent/proposal.zig → risk/admission.zig → src/execution/* |
双通道 + 单写者
- 关键路径:不调用 LLM,不等待新闻/链上;目标 p99(进程内风险计算)< 10ms。
- Agent 路径:可等待、可失败;失败最多本轮无新提案。
- State Engine 是唯一状态写入者;Agent 与 Dashboard 只读不可变快照(
snapshot_version)。
能力缺失,而非口头约束
下列限制必须是代码层做不到,而不是 prompt 里写「请不要」:
- Agent 模块不依赖 OKX 密钥、签名、下单客户端
- Agent 不能改
max_drawdown或风险配置 - 未绑定当前
snapshot_version的提案必拒 - 工具返回值不能变成系统指令(只进
data)
详见 关键不变量。
闭环
观察 → 工具调查 → 假设 → 交易提案 → 风险准入 → 执行
↑ ↓
长期记忆 ← 结果归因 ← 交易结算 ← 订单与成交事件 ←──┘
「慢」体现在决策与反思的节奏;「快」体现在边界与数据故障时的降级。两者抢同一状态时,安全侧优先(Fail Closed)。
风险模型
风险内核是确定性关键路径的核心:用可清算净值守住 HWM 回撤边界,并在准入时对提案做压力检查。
保守净值
不直接拿 mark price 当「你有多少钱」。估值扣除:
- 退出 taker 费用(
taker_fee_rate) - 退出滑点缓冲(
slippage_rate) - 挂单与未决风险(实现演进中)
相关代码:src/risk/equity.zig。
HWM 与回撤
- HWM(High Water Mark):保守净值的历史高点,单调不减(仅在已对账数据上推进)
- Drawdown:相对 HWM 的回撤比例,与设计公式一致,非负
- 边界:
drawdown ≥ max_drawdown(默认 10%)触发收敛流程
HWM 会持久化(equity 采样 / 启动恢复),避免重启「忘记」峰值。
风险状态机
NORMAL ──(数据陈旧/不一致/…)──► EXIT_ONLY
NORMAL ──(触界)──► FLATTENING ──► HALTED
任何状态在硬故障下可进入更安全侧
HALTED ──✗──► (无自动回到可开仓)
| 模式 | 允许 |
|---|---|
NORMAL | 在准入通过下可增险 / 减险 |
EXIT_ONLY | 只减险或 HOLD,不新开增险 |
FLATTENING | 撤增险挂单 → 退出 → 对账至 BTC 可用≈0 |
HALTED | 停止自主交易;等人 |
实现:src/risk/state_machine.zig。启动未 reconcile 时 fail-closed,常以 EXIT_ONLY 起步。
准入(Admission)
提案进入执行前必须通过 Risk Kernel(src/risk/admission.zig),典型检查:
snapshot_version仍是当前版本- 数据 freshness 足够
- 无 order ambiguity / 未对账阻断
- 压力净值 ≥
HWM × (1 - max_drawdown) + ExitReserve(地板) - 输出
APPROVE/REDUCE/REJECT(可降目标仓位)
坏 JSON、缺字段的提案在 Schema 层已作废,进不了准入。
ExitReserve
边界不是贴着 10% 才跑——需要预留「刹车距离」。ExitReserve 校准依赖真实流动性与费用模型;设计承认极端行情仍可能穿透,系统职责是:
- 尽量提前动作
- 如实记录穿透幅度与成交成本(不掩饰)
与 Agent 的关系
- Agent 看不见也不配置风险参数
- 内核 不解释 thesis 是否高明,只问「这笔若成交,压力下会不会穿界」
- LLM 挂了时,风险监控与退出能力必须继续工作(NFR / 故障矩阵)
配置注意
| 项 | 规则 |
|---|---|
max_drawdown | 仅启动加载;发版变更 |
allow_runtime_override | 保持 false |
| 费率 / 滑点 | 偏保守;过乐观 = 边界虚设 |
单测覆盖见验收矩阵 AC-RK1…RK3、AC-FR05 等条目。
Agent、工具与记忆
慢循环负责「想清楚再建议」,从不直接碰下单接口。
决策闭环(设计 §5.4)
| 步 | 名称 | 要点 |
|---|---|---|
| 1 | Trigger | 定时 / 行情异常 / invalid_if / 人工 |
| 2 | Snapshot | 不可变快照 + snapshot_version |
| 3 | Context | 检索记忆与近期事件 |
| 4 | Investigate | 自主选工具;全审计 |
| 5 | Propose | Decision Proposal;Schema 校验 |
| 6 | Admit | Risk Kernel |
| 7 | Execute | 幂等订单(shadow 不下真单) |
| 8 | Reconcile | 账户与订单确认 |
| 9 | Evaluate | 多时间窗结果,不只看盈亏 |
| 10 | Reflect | 结构化反思 + memory_ops |
Context(agent/context.zig)
每轮送给模型的是稳定能力边界,不是聊天流水账。固定五段 JSON:
current_state— 净值、仓位、btc_weight、HWM、回撤、模式、是否已对账recent_events— 有界最近事件memories— 检索命中的长期记忆tools— 注册表中的可用工具与时效/成本元数据risk_rules— 不可变边界说明(immutable: true)
渲染字节级确定性,便于 agent_runs.input_digest 回放比对。
Proposal(agent/proposal.zig)
唯一合法「想交易」的形状。必填语义包括:
decision_id(dec_…)snapshot_versionaction:HOLD|REBALANCEtarget(再平衡时 BTC 权重)order_policy/confidence/thesis/invalid_if/reduce_evalposition_tension(btc_weight ≥ 0.85且连续 HOLD ≥ 4)为真时,HOLD 必须带reduce_eval;invalid_if不是减仓触发器
任何坏 JSON、缺字段、越界置信度 → 整单作废(fail-closed HOLD)。
工具注册表(tools/registry.zig)
| 域前缀 | 例子 |
|---|---|
market.* | K 线、成交、簿、波动 |
derivatives.* | 资金费率、OI、基差 |
onchain.* / wallet.* | 网络与地址活动 |
macro.* / news.* | 宏观与新闻 |
统一 ToolResult:
status: OK | UNAVAILABLE | STALE | ERROR
source, as_of, confidence?, latency_ms, cost_usd
data_json ← 不可信
raw_ref?
- 超时/不可用 →
UNAVAILABLE,禁止把缺失编成 0 - 超过
max_age_ms或as_of不明 → 有效状态降为STALE - 每次调用写审计(digest),供「哪些数据真改善了决策」统计
五层记忆(memory/store.zig)
| 层 | 内容 | 检索 |
|---|---|---|
| Current State | 账户与风险(来自状态机,非本表) | 每轮必带 |
| Working | 近事件、开放情节 | 时间窗 + 重要度 |
| Episodic | 完整交易摘要 | 相似环境 |
| Strategy | 假设与证据 | 相关 + 证据数 |
| Reflection | 偏差与改进 | 近 + 高影响 |
版本化记录 (memory_id, version) 追加;结构化 memory_ops:
CREATE/UPDATE/INVALIDATE/MERGE
置信度钳制在 [0,1];非法 op 在 Reflection 解析期整篇作废。
索引上限 1024。满员时确定性淘汰:已终结 → E_run_* / R_run_* / 带日期的 PR_short_* → 其他 reflection → 其他 episodic。E_hold_streak / R_hold_streak / PR_short / PR_long / W_* / H_* 不淘汰。SQLite 仍保留全量审计。启动时会压缩出 32 个空位。
Reflection(agent/reflection.zig)
只产出可审计结构:预期 vs 多窗口实际结果、error_type、lessons、memory_ops。
不保存隐藏 chain-of-thought。
当前实现边界
已落地(单测覆盖):Schema、Context 渲染、Registry、Memory ops、Reflection 解析与 store 联动、DB 表与 Repo。
已本机验证:OpenAI 兼容 LLM 实调 + shadow 提案审计。仍待:具体 provider 工具、Dashboard 回放、Shadow 影子收益对比长跑。详见 路线图 Phase 2。
事件与审计
「每笔订单可追溯到 decision、快照、风控与配置」是上线硬条件之一。事件日志是真相源,Dashboard 只是视图。
事件信封
顶层字段固定,避免消费者每次挖 payload:
| 字段 | 含义 |
|---|---|
seq / event_id | 单调序号与全局 ID |
ts | 时间戳 |
type | 事件类型枚举名 |
source | 产生模块 |
severity | 严重级 |
correlation_id | 通常为 decision_id / run_id |
state_version | 当时快照版本 |
software_version | 二进制版本 |
config_hash | 配置摘要 |
payload | 类型相关细节 JSON |
实现:src/core/events.zig + storage EventsRepo。
典型类型(示例)
| type | 何时 |
|---|---|
RECONCILE_COMPLETED | 对账结束 |
STATE_READY | 进入 READY |
RISK_MODE_CHANGED | 状态机迁移 |
RISK_DECISION | 准入批准/缩减/拒绝 |
ORDER_* | 订单投影变化 |
SHUTDOWN_CLEAN | 优雅退出 |
CONFIG_APPLIED | 配置/Prompt 生效(规划) |
以代码与 migration 为准;新类型必须带齐信封字段。
SQLite 表(migration 0001)
| 表 | 作用 |
|---|---|
events | 只追加事件流 |
orders / fills | 订单与成交投影 |
equity_samples | 净值 / HWM / DD 采样 |
agent_runs | 模型调用与提案摘要 |
tool_calls | 工具调用审计 |
memories | 记忆版本 |
路径见配置 [storage].path;WAL 模式,单 writer。
查询示例
DB=/var/lib/alphabound/trading.db
# 最近风险相关
sqlite3 "$DB" "SELECT ts,type,correlation_id FROM events
WHERE type LIKE 'RISK%' ORDER BY seq DESC LIMIT 20;"
# 某决策全链路
sqlite3 "$DB" "SELECT seq,type,payload_json FROM events
WHERE correlation_id = 'dec_01J...' ORDER BY seq;"
# 净值曲线尾部
sqlite3 "$DB" "SELECT ts,equity,hwm,drawdown FROM equity_samples
ORDER BY ts DESC LIMIT 30;"
脱敏
observability/redaction.zig 在日志路径屏蔽密钥形态字符串。原则:
- 宁可不打,也不打半截 secret
- issue / 聊天贴日志前再人工扫一遍
- 备份加密与访问控制同生产库
回放
状态引擎支持同序消息 逐位确定性 回放(单测守护)。审计争议时:
- 取
config_hash+software_version对齐二进制与配置 - 按
seq重放相关输入消息 - 比对
state_version与订单投影
这是 Replay 测试与事故复盘的共同基础。
构建与测试
工具链
| 工具 | 版本 |
|---|---|
| Zig | 0.16.0(与 CI mlugg/setup-zig@v2 固定一致) |
| mdBook | ≥ 0.4(文档;Homebrew: mdbook) |
| SQLite | 源码 vendor 进仓库,无需系统库 |
Zig 0.16 API 与 0.13/0.14 不兼容;不要用「手头最新」随意升级。
常用命令
zig build # Debug 默认,产出 zig-out/bin/alphabound
zig build -Doptimize=ReleaseSafe
zig build test --summary all # 全量单元 / 回放测试
./zig-out/bin/alphabound --self-check --config config/alphabound.toml
文档
./scripts/build-docs.sh # mdbook build → book/book/
./scripts/build-docs.sh serve # 预览 :3000
./scripts/build-docs.sh check # build + 失败即非零(CI 用)
CI
工作流:
| 文件 | 职责 |
|---|---|
.github/workflows/ci.yml | Zig build + test + self-check(main / PR) |
.github/workflows/docs.yml | mdBook 构建(可选发布 Pages) |
.github/workflows/release-docker.yml | GHCR 镜像(仅 tag v* / 手动,不跟 main) |
本地应用同等门槛再推送。
vendor SQLite
- 路径:
vendor/sqlite/ build.zig编为静态库并link_libc- migration 经
addAnonymousImport("migration_0001", …)嵌入 - Dashboard HTML 经
addAnonymousImport("dashboard_index_html", …)嵌入 exe 模块
新增 migration:加 SQL 文件 + 改 build.zig import + db.zig migrations 数组。
测试层次(目标金字塔)
| 层 | 现状 |
|---|---|
| Unit | 主力量;zig build test |
| Replay | 状态引擎确定性 |
| Property | 风险不变量逐步加强 |
| Integration | 需 Demo 凭证 |
| Fault / Soak | 需环境与时间 |
不要用 mock 掉 Risk Kernel 的「假绿」集成代替内核 property。
调试技巧
- 有界运行:
--ticks N避免手动杀进程 - 临时 DB:
/tmp/...+ 跑完删除 - 单测:
zig build test --summary all后按失败测试名定位文件 - 注意 0.16:顶层函数名不要与局部变量同名(shadowing 是编译错误)
代码结构
alphabound/
├── build.zig / build.zig.zon
├── book.toml # mdBook 工程(输出 book/book/,已 gitignore)
├── book/src/ # 本手册源码(guide / concepts / dev / planning)
├── scripts/ # build-docs、run-local、deploy/soak/drill 助手
├── .github/workflows/
├── src/
│ ├── main.zig # daemon 生命周期 + CLI
│ ├── root.zig # 模块导出 + refAllDecls 测试
│ ├── config.zig
│ ├── core/ # decimal, clock, events, state
│ ├── risk/ # equity, state_machine, admission
│ ├── execution/ # orders, planner, venue client
│ ├── agent/ # proposal, context, openai, reflection
│ ├── tools/ # registry, market (+ derivatives L1)
│ ├── memory/ # store + retrieval
│ ├── exchange/okx/ # auth, rest, ws
│ ├── storage/ # db, policy, disk
│ ├── admin/ # 本机控制文件
│ ├── security/ # isolation / limits 不变量
│ ├── fault/ # 故障矩阵单测 FD1–10
│ ├── intel/ # alphabound.intel.v1 协议 + ingest mailbox
│ ├── web/ # server 路由 + auth(token/session/passkey)
│ └── observability/ # redaction, latency
├── migrations/ # SQL
├── dashboard/ # 嵌入式 Overview + favicon
├── tools/alphabound-mcp/ # Analytics MCP + CLI(只读观察 + 签名 intel ingest)
├── config/ # alphabound.toml / local.toml / docker.toml
├── deploy/ # systemd, nginx 示例, install 脚本
├── docs/ # 设计分析 / 路线图 / 验收 / Gate / Auth
└── vendor/sqlite/
模块依赖方向(允许)
main → config, storage, web, exchange, core/state, risk, execution, admin, …
agent → core/decimal, memory, tools (禁止 → exchange 私钥路径)
risk → core/decimal, state 类型
execution → core/decimal, orders 类型
tools / memory → 仅 core 与标准库
web/auth → 不持有交易所密钥;MCP 不碰交易控制面
新增 use / @import 时保持:慢路径依赖快路径类型可以,反向把密钥或 socket 塞进 agent 不行。
关键入口
| 文件 | 职责 |
|---|---|
main.zig | BOOTING→…→READY、shadow/demo/live 循环、web 线程、信号、控制文件 |
core/state.zig | 单写者 mailbox / 快照 |
risk/admission.zig | 提案最后一道门 |
execution/ | 目标仓位 → 幂等订单 |
web/server.zig + web/auth.zig | 纯路由可单测 + 鉴权 |
admin/control.zig | pause/flatten/target-weight 控制文件 |
storage/db.zig | SQLite 与 Repo |
fault/matrix.zig | 故障降级矩阵单测 |
测试放置
- 与模块同文件的
test "…"块(Zig 习惯) root.zig的refAllDecls保证模块被链进测试二进制- 故障场景:
src/fault/matrix.zig - 沉重 integration 可放
tests/(需凭证的勿默认跑)
关键不变量
所有代码变更不得破坏下列不变量。Code review 与 CI 测试应以它们为验收核心。
1. 权限隔离
Agent 无法访问 OKX 密钥、直接下单函数或风险配置 — 只能提交 Proposal。
- 依赖图可检查:
src/agent/**不 import 签名/下单客户端 - 密钥只在
exchange/okx/auth.zig与进程环境
2. 快照绑定
任何提案必须绑定
snapshot_version;状态变化后旧提案自动失效。
admission对失配 → REJECT- Context 里的 version 与 State Engine 一致
3. 订单幂等与 UNKNOWN
client_order_id由 decision / 版本 / 序号导出;超时视为 UNKNOWN,先查后处置,禁止盲目重发。
execution/orders.zig状态机含 UNKNOWN- 部分成交后重算差额,不原样重报
4. Fail Closed
数据过期 / 状态不一致 / 未知订单 → 进入安全状态,不增加风险。
- 未 reconcile 起步
EXIT_ONLY(或更严) - 工具 STALE/UNAVAILABLE ≠ 数值 0
5. 边界参数冻结
max_drawdown与 Risk Kernel 参数不可热加载,必须走版本发布 + 人工确认。
- 配置仅启动解析
allow_runtime_override = false
6. 端到端可追溯
每笔订单可追溯到
decision_id、snapshot_version、risk decision 与config_hash。
- 事件信封顶层字段齐全
agent_runs/tool_calls/orders可关联
7. 提示注入边界
工具与第三方文本是数据,不是指令。
- 只进
ToolResult.data_json - 不拼接进系统 prompt 的指令位
- 不暴露 shell / 任意 URL / 文件系统给模型侧
8. 回撤诚实性
边界穿透时如实记录幅度与成本,不掩饰。
- 禁止在展示层「夹」回 10% 以内
- FLATTENING 过程事件完整
破坏不变量时
- 停相关 PR 合并
- 若已在 demo/live:切维护 / EXIT 能力,评估资金
- 补回归测试后再发版
- 更新验收矩阵证据
这些条目与设计 ADR、验收矩阵 上线标准 AC-GO2/GO5/GO6 对齐。
设计分析
以下内容与仓库 docs/DESIGN_ANALYSIS.md 同步引入,便于在手册内检索。
AlphaBound 系统设计分析
基于《AlphaBound System Design v0.1》(2026-08-09, MVP 设计基线)。 本文是工程视角的独立分析:评估关键决策、指出风险与薄弱点、列出实现阶段需要重点验证的事项。
1. 一句话理解
AlphaBound 把「AI 自主交易」拆成两个正交问题:策略自主性交给 LLM Agent,资金安全交给确定性代码。 Agent 拥有完整的观察、推理与提案自由,但唯一通往交易所的路径被 Risk Kernel + Execution Engine 把守; 10% 最大回撤是结果边界,不是方法约束。
2. 关键决策评估
| 决策 | 评价 | 分析 |
|---|---|---|
| Bounded Autonomy(提案-准入分离) | ✅ 核心亮点 | ADR-004 将模型不确定性与交易权限隔离。Agent 输出严格 Schema 的 Proposal 并绑定 snapshot_version,Risk Kernel 是唯一准入点。这是全系统最重要的安全设计,值得用 property test 重点守护。 |
| 双通道 + 单写者状态 | ✅ 正确 | 关键路径(风险/执行)不等待 LLM;State Engine 单写者消除并发写幽灵仓位。代价是所有状态变更都要走 mailbox 顺序化,吞吐受限于单核处理速度——对 1 标的 100 USDT 完全够用。 |
| 保守净值 + HWM 回撤定义 | ✅ 严谨 | 用「可清算净值」(扣退出费用/滑点/挂单风险) 而非 mark price 计净值;HWM 随盈利上移。ExitReserve 作为动态刹车距离是亮点。注意: E_t 公式中 Slippage_exit 与 PendingRisk 的估计模型是未决项,需要实盘订单簿数据校准(设计 9.5 已承认)。 |
| Zig 0.16.0 固定版本 | ⚠️ 最大技术风险 | pre-1.0 语言 + 官方承认 0.16.x 存在 miscompilation 风险。生态几乎没有久经考验的 TLS/WebSocket/HTTP 库,Phase 0 spike 是整个计划的关键闸门——若 TLS/WS 不达产线质量,应有 fallback 预案(vendor 轻量 C 库或降级语言选型)。ReleaseSafe + 回放测试可缓解但不能消除。 |
| SQLite WAL 单 writer | ✅ 合适 | 单机审计场景标准解。设计正确指出不可放网络文件系统。注意 WAL checkpoint 与备份 API 的交互要纳入 soak 测试(WAL size 是关键指标之一)。 |
| 无 Docker、systemd 直跑 | ✅ 务实 | 单文件二进制 + 原子 symlink 切换 + 快速回滚,发布路径短。代价是环境一致性靠 CI 固定 toolchain 保证。 |
| 分层长期记忆(5 层) | ⚠️ 价值待验证 | 结构合理(Current/Working/Episodic/Strategy/Reflection),但「按相关性检索」在无向量库前提下如何实现?MVP 大概率是标签 + 时间窗 + 市场环境特征匹配,检索质量是 Phase 2 shadow mode 需要实证的假设。 |
| 不保存 chain-of-thought | ✅ 合规友好 | 只存结构化 thesis/evidence/invalid_if/outcome,可审计且避免依赖模型隐藏状态。 |
3. 主要风险与薄弱点
3.1 边界穿透的物理极限(设计已声明,仍需强调)
10% DD 是工程目标。BTC 跳空、流动性瞬时消失时,FLATTENING 的实际成交价可能显著穿透边界。 设计的应对是 ExitReserve + 如实记录穿透,这是诚实的做法,但意味着:
- ExitReserve 校准是安全性的实际决定因素,参数错误 = 边界虚设;
- 验收必须包含「模拟极端行情下的穿透幅度测量」(fault injection + replay)。
3.2 Zig 生态缺口(Phase 0 必须回答)
- TLS 1.2/1.3 客户端(OKX + LLM API 均为 HTTPS/WSS): std.crypto 的 TLS 实现成熟度?
- WebSocket 客户端: 自研还是 vendor?断线重连、ping/pong、压缩支持。
- 建议 Phase 0 产出一份《依赖决议记录》,把每个网络组件的选型 + 验证结果写死。
3.3 LLM 结构化输出的可靠性
Proposal 是严格 JSON Schema,但模型偶发输出坏 JSON / 幻觉字段。设计的处理是校验失败即作废(HOLD),
安全但可能造成决策饥饿。指标 invalid outputs 已列入观测,建议在验收上加阈值(如 invalid rate < 5%)。
3.4 时间与时钟
签名依赖时钟同步(clock_skew 已监控),但回撤计算、evidence as_of、订单超时都依赖单调时钟与墙钟的正确区分。
Zig 层面需要明确 monotonic vs wall clock 的使用规范(core/clock 模块的职责)。
3.5 提示注入面
工具返回(news.、wallet. 标签)是不可信数据,设计已要求隔离在 data 字段。真正的执行保障在于:
Agent worker 没有 shell / 文件 / 任意 URL 能力——这必须是代码层面的能力缺失,而非 prompt 层约束。
验收矩阵中对应「Agent 无法绕过 Risk Kernel / 访问密钥」的红队测试。
3.6 成本可见性
100 USDT 本金 vs LLM 调用成本:一次决策若 $0.05–0.2,高频触发会让运营成本超过本金。 设计原则 Cheap to Operate 要求成本可见,建议 Dashboard System 视图把「模型累计成本 vs 本金」做成一级指标, 并在触发策略上设成本预算闸(9.5 未决项之一)。
4. 实现阶段的关注顺序(与路线图对应)
- Phase 0 是真正的 go/no-go: Zig TLS/WS/SQLite/长稳,任何一项不过关都影响全盘。
- Decimal 与订单状态机先行: 全部资金计算走定点;订单 8 状态机 + 幂等 client_order_id 是 replay 测试的基础。
- Risk Kernel 纯函数化: 无网络/无 DB/无 LLM,输入快照输出决策——这是 property test 能压住它的前提。
- 事件日志先于功能: Event First 原则意味着 events 表 + 事件信封是所有模块的公共依赖,应最早稳定。
- Reconcile 是恢复正确性的核心: 启动状态机 BOOTING→CONNECTING→RECONCILING→READY, 未完成对账不得开仓,值得单独的 integration 测试组。
5. 与验收的衔接
设计 9.3 节给出 8 条上线验收标准,已在 ACCEPTANCE_MATRIX.md 中 展开为「需求 → 验收标准 → 验证方法 → 所属阶段」的完整矩阵,覆盖 FR-01..10、NFR-01..06、 安全边界(7.3/7.4)、故障降级矩阵(7.2)与运维演练(8.4/7.5)。
6. 结论
设计整体成熟度高:边界清晰、失效模式想在前面、诚实面对不可保证项。 两个决定成败的赌注是 Zig 0.16 生态可行性(技术)与 ExitReserve 校准(风险)。 建议严格按 Phase 0 → 5 推进,不跳过 shadow 与 demo 阶段,每阶段以验收矩阵对应条目作为退出闸门。
路线图
以下内容与仓库 docs/ROADMAP.md 同步引入。
AlphaBound 路线图
依据系统设计 v0.1 §9.4「MVP 迭代阶段」展开,每阶段含范围、交付物、退出条件(闸门)。 阶段串行推进,退出条件未满足不得进入下一阶段;各条目与 验收矩阵 的 AC 编号对应。
当前进度(2026-08-13): Phase 0–3 代码主路径已通;小额 mode=live 已解锁(OKX_REAL_MONEY_OK=1)。
本机/生产已验证: OKX 公共行情 + 私有余额 REST 对账、Agent 提案/反思、Dashboard(Token/Session/Passkey)、
只读 Analytics MCP、小额实盘下单(operator + agent REBALANCE → FILLED)、flatten/cancel-all/target-weight、
部署回滚与 soak/drill 脚本、故障矩阵单测 FD1–10、L1 market.derivatives 持仓包。
私有 WS 仍 opt-in;REST 对账为主路径。
尚未完成: ≥7 日滚动 soak(AC-GO8)、部分故障场景实网注入、Phase 5 L1 引用率观察。
下一步: 稳盘证据与 Gate3 收口;见 NEXT.md。
Phase 0 ──► Phase 1 ──► Phase 2 ──► Phase 3 ──► Phase 4 ──► Phase 5
可行性 Spike 只读市场 Shadow Mode 交易路径 MVP 运维判定 数据工具扩展
(go/no-go) + Dashboard (不下单) (demo|live) (长稳/验收) (按需增强)
Phase 0 — 技术可行性 Spike(go/no-go 闸门)
目标: 证明 Zig 0.16.0 技术栈能支撑生产级长时运行,任何一项不过关即触发选型回退预案。
范围
- Zig 0.16
std.Io下的 TLS 客户端、WebSocket 客户端、HTTP 客户端验证(对 OKX 与 LLM 端点) - SQLite amalgamation 集成(vendor sqlite3.c/h,WAL,单 writer)
- systemd 服务化 + ReleaseSafe 静态构建 + 原子发布/回滚脚本雏形
- 内存长稳测试(24h 连续运行,监控 RSS / fd / 句柄泄漏)
- Azure Region 延迟实测脚本(OKX REST / 公共 WS / 私有 WS / LLM 端点 p50/p95)
交付物
- 可运行的最小 daemon(连接 OKX 公共 WS,落 SQLite 事件)
- 《依赖决议记录》: TLS/WS/HTTP 每个组件的选型(标准库 or vendor)与验证证据
- CI 骨架: 固定 Zig 0.16.0 下载 + SHA256 校验 + build + test
- Azure Region 选型报告
退出条件(Gate 0)
- 所有关键库可固定版本并连续运行 24h 无泄漏、无崩溃(短时验证通过;24h 长稳待跑)
- TLS/WS 对 OKX 实际端点稳定收发,断线可检测(REST over TLS 实网验证;WS 帧编解码单测)
- SQLite WAL 读写并行验证通过(vendor 3.53.4,WAL 模式,存储层测试 + daemon 实测落库)
Phase 1 — 只读市场与 Dashboard
目标: 无交易能力的完整「观察者」——行情、账户、状态引擎、事件日志、可视化。
范围
- Exchange Gateway: OKX 公共/私有 WS 订阅、REST 快照、心跳、重连、时间同步、instrument 配置加载
- State Engine: 单写者 mailbox、PortfolioState(版本化不可变快照)、HWM/DD 计算
- core/decimal: 定点金额运算(禁止二进制 float 结算)
- Storage: migrations、events/equity_samples 表、事件信封(顶层 type/correlation_id/state_version/config_hash)
- Journal Writer: 有界队列、关键事件强制提交
- 启动状态机: BOOTING → CONNECTING → RECONCILING → READY
- Dashboard v1: Overview + Market(K 线) + Events + System 视图,
/api/v1/state|candles|equity|events,/health/* - 备份: 每小时 SQLite Backup API 快照 + 保留策略
交付物: 在 Azure VM 上 systemd 常驻的只读实例 + 浏览器 Dashboard(SSH tunnel 访问)
退出条件(Gate 1)
- 无交易也能对账与展示(基础): REST 只读余额周期探针 + HWM 持久化 + Dashboard state(shadow 引擎现金仍为模拟)
- WS 断线自动重连并触发 reconcile(TLS upgrade 已通;login/长连/重连待稳定;REST 周期对账兜底)
-
净值/回撤样本在 Dashboard 呈现(
/api/v1/equity+ 表);K 线 1H sparkline(/api/v1/candles)已交付
Phase 2 — Agent Shadow Mode
目标: 完整决策闭环但不执行订单——验证 Context、工具、提案 Schema 与记忆的质量。
范围
- Agent Runtime: Context 构建(5 层记忆检索)、模型适配器、Decision Proposal Schema 校验
- ✅
agent/context.zig确定性 Context + input_digest;✅ Proposal 严格校验 - ✅
agent/openai.zigOpenAI/Azure 兼容 chat completions;本机 Azure 实调proposal ok
- ✅
- Tool Registry: market.* / derivatives.* 工具、统一 ToolResult 信封、时效/成本/可信度记录
- ✅
tools/registry.zig+ ✅tools/market.zigticker/candles provider(OKX REST 实调)
- ✅
- Memory & Reflection: episodes、假设(Strategy Memory)、结构化 Reflection 与 memory_ops
- ✅
memory/store.zig+agent/reflection.zig(ops 确定性生效,坏 JSON 整体作废) - ✅ boot 从 SQLite 重建 + bootstrap seed;决策环
retrieve注入 Context;提案 episode 落库 - ✅ 决策后 LLM reflection(
prompts/reflection.md→ 严格 Schema → memory_ops;ALPHABOUND_LLM_REFLECTION=0可关) - ✅ 失败回退确定性 shadow reflection(
R_*+ strategy touch) - ✅ 事件
AGENT_REFLECTION_OK/_LLM_FAILED/_INVALID
- ✅
- agent_runs / tool_calls / memories 表与审计链路 — ✅ shadow 写 run + tool_calls + memories +
AGENT_*payload - Prompt 版本化(hash 进事件日志,SIGHUP 热加载) — ✅ prompt_hash 入 agent_runs;热加载待做
- Dashboard: Trade Detail(提案链路回放)+ Memory/System 视图 — ✅ 提案/Memories/Events/System + agent-runs/memories/events/system API
- 审计事件进 Context — ✅
listCompactForContext→ agent recent_events - SQLite 小时备份 — ✅ Backup API →
<db_path>.bak+ BACKUP_* 事件 - 提示注入防线: 工具返回一律进 data 字段;Agent worker 无 shell/文件/任意 URL 能力
- ✅ ToolResult.data 不可信边界在类型层强制;LLM 凭证不进 Context
- 影子对比: 提案 vs 基准(如 buy-and-hold)的假设性表现记录 — ✅
shadow_bench+/api/v1/shadow - Market K 线只读面 — ✅
/api/v1/candles+ Dashboard Lightweight Charts(K 线/量/净值 + TradingView 归因) - 统计: ✅
--agent-stats有效提案率 / tool_calls 计数 - 短 soak 脚本: ✅
scripts/soak-shadow.sh - 本机管理控制: ✅
--control pause|resume|reconcile|cancel-all|flatten|shutdown|status(控制文件,无网络面;cancel 交易所路径待 Demo) - 提案准入审计: ✅ shadow 路径
admission.admit→RISK_ADMISSION(仍不执行订单) - 工具 UNAVAILABLE: ✅ HTTP 失败不伪造零行情
- systemd unit + deploy 说明: ✅
deploy/
退出条件(Gate 2)
- 提案可审计(基础): run_id + input/output digest + tool_calls + events.payload
-
invalid/ok 率可统计(
--agent-stats);阈值与长跑样本待 Gate 2 评审 - LLM 超时/坏 JSON 均安全降级为 HOLD,不影响关键路径(本机失败路径已验证)
Phase 3 — Trading path(demo | 小额 live)
目标: 打通 Risk Kernel + Execution 全链路;可在 OKX 模拟盘或小额实盘子账号经受故障注入与 soak。
范围
- Risk Kernel: 保守净值/压力净值/ExitReserve/风险预算、提案准入(APPROVE/REDUCE/REJECT)、
风险状态机 NORMAL/EXIT_ONLY/FLATTENING/HALTED
- ✅ admission 单测 + shadow/demo 决策环调用
- Execution Engine: 目标仓位→订单、幂等 client_order_id、部分成交、撤单、UNKNOWN 处置、最终对账
- ✅ planner + client_order_id + demo 市价/limit place/query/cancel;✅ 部分成交再规划(≤3 腿 + REST 对账)
- orders/fills 表、订单 8 状态投影(PLANNED..UNKNOWN)
- ✅ orders 投影写入;✅
/api/v1/orders+ Dashboard 订单 Tab;✅ demo resolve 写 fills 聚合行(WS 多笔 fill 仍可增强)
- ✅ orders 投影写入;✅
- 管理控制: pause / resume / reconcile / cancel-all / flatten / safe-shutdown(本机 CLI/Unix socket)
- ✅ 控制文件 CLI 全套;cancel-all 在 demo 拉 pending 撤单
- 故障注入全组: 断网、DNS、时钟漂移、磁盘满、SQLite busy、LLM 超时、坏 JSON、工具污染
- 测试金字塔补全: property(Risk Kernel 不变量)、replay(状态确定性)、integration(OKX Demo)
- 发布流水线完整化: manifest + SHA256 + self-check + 自动回滚
- 清单: GATE3_CHECKLIST.md
退出条件(Gate 3)
- 交易模式(demo 或小额 live)连续稳定运行 ≥ 7 天(soak)
- 至少一次断线恢复演练 + 一次版本回滚演练通过(2026-08-12)
-
故障降级矩阵(§7.2)单测 FD1–10 齐(
src/fault/matrix.zig);部分实网注入仍可选 - Risk Kernel property / 费用滑点部分成交相关验收项已落地(见 ACCEPTANCE_MATRIX)
-
mode=live小额路径解锁(OKX_REAL_MONEY_OK=1,非主账户)
Phase 4 — MVP 运维判定(非「再开 live 锁」)
目标: 小额 live 已可跑的前提下,用长稳与运营证据判定 MVP 成立;不是再解一把代码锁。
范围
- 子账户纪律: API Key 仅 Read+Trade、出口 IP 白名单、密钥 0600 + systemd 加固
- 上线验收清单(§9.3)逐项签署与滚动 soak 证据归档
- 每日人工检查流程 + 周度 restore drill
- 回撤边界实弹: FLATTENING → HALTED 在真实市场可重复
进入条件: Gate 3 故障矩阵与 7 日 soak 收口;任何无法解释的状态不一致都阻止扩容
退出条件(Gate 4,判定 MVP 成立)
- 无状态不一致事件;所有风险事件可解释、可追溯
- 运营成本(基础设施 + 模型调用)可见且未失控
- HALTED/EXIT_ONLY 触发行为与设计一致
Phase 5 — 数据工具扩展(持续迭代)
目标: 按 Agent 的实际信息缺口逐个接入 onchain.* / wallet.* / macro.* / news.*,用数据说话。
范围
- 每个数据源作为独立工具适配器接入(Schema、时效、成本、可信度、缓存 TTL)
- 数据提供商评估: API 成本、标签质量、速率限制、许可
- 工具价值评估闭环: 使用率、引用进 evidence 的频率、对决策质量的增量贡献(Reflection 统计)
- 逐步校准: 风险压力参数、ExitReserve、Agent 触发策略(成本预算闸)
进展
-
market.derivatives(2026-08-12): SWAP 资金费率 + 未平仓量,OKX 公共端点、零新增外部依赖;Agent 上下文 tools=3 -
L1 持仓/情绪包(2026-08-12): 同工具扩
long_short_ratio/taker_buy_vol/taker_sell_vol/mark_px/index_px/basis_bps; prompt 强制 REBALANCE 引用数值;scripts/tool-value-report.sh - 计划全文: PHASE5_DATA_PLAN.md(L0 理想 → L1 本切片 → 外部 news/macro/onchain 延后)
- 滚动价值评估: 部署后 7 日 citation 门限 + 至 ~2026-09-09 四周评估
退出条件(滚动)
- 每个新工具/字段上线后完成使用率与 thesis 引用率评估,低价值降级或下线
-
L1:
derivatives_vs_ticker_ratio≈1且 REBALANCE citation_rate≥30%(见 tool-value-report)
横切工作流(贯穿所有阶段)
| 事项 | 节奏 |
|---|---|
| CI: unit + property + replay + integration + dashboard build | 每次 PR |
| 备份 + restore drill | 每小时快照 / 每周演练(Phase 1 起) |
| 依赖与 Zig 版本升级 | 冻结;升级须过回放 + 长稳 + 故障注入 |
| 未决项决议(§9.5) | LLM Provider(P2 前)、HTTP/WS 选型(P0)、数据商(P5)、压力参数(P3-4)、触发策略(P2-4)、Region(P0) |
| 文档: ADR 追加、验收矩阵状态更新 | 每阶段闸门评审时 |
下一步
以下内容与仓库 docs/NEXT.md 同步引入。
下一步执行计划(滚动)
当前焦点(2026-08-13): 小额实盘已是主路径;mode=live + OKX_REAL_MONEY_OK=1 已解锁。
mode=demo 仅保留给 OKX 模拟盘(OKX_SIMULATED=1);demo+REAL_MONEY 仍兼容但 boot 告警,请迁 live。
已合并: PR #1–#8 链(实盘解锁、ops/auth、equity buffer、favicon 等)+ live 模式正式化。
模式约定(2026-08-12 起)
| mode | 场所 | 必填 env |
|---|---|---|
shadow | 模拟引擎现金,不下单 | 无 |
demo | OKX 模拟盘 | OKX_* + OKX_SIMULATED=1 |
live | 小额实盘子账号 | OKX_* + OKX_REAL_MONEY_OK=1(禁 SIMULATED) |
现在做什么(按序)
P0 — 稳盘(滚动)
- ✅ 生产
mode = "live"+OKX_REAL_MONEY_OK=1(2026-08-12) - ✅ 运维脚本带 Dashboard token:
check-remote/soak-report/gate2-report - ✅ Dashboard 鉴权 + 只读 Analytics MCP(PR #6 链)
- 滚动 soak:继续
HOST=<host> ./scripts/soak-report.sh 24(24h PASS;向 7 日窗口滚) - 控制面演练:
cancel-all→flatten→ 拒增仓 →target-weight=0.05恢复(flatten 已验;cancel-all 有挂单时再验) - ✅ 对账:live balance applied;新单
exchange_order_id非空(历史 FILLED 空 id 为修前数据)
P1 — Gate3 收口
- ✅ Fault 矩阵单测 FD1–10 齐(含 FD10 restart fail-closed);实网 WS/超时注入仍可选
- 7 日滚动 soak 窗口继续积累(AC-GO8)
- ✅ Dashboard/API:orders
exchange_order_id抽查(新单 8/8)
P1.5 — Agent 决策质量(实盘证据,2026-08-19)
- Context 给出权威
btc_weight,以及 HOLD 连胜次数 / 距上次成交 / vs 买持有alpha_return事实(不给建议) - Prompt:HOLD = 维持当前权重;thesis 有方向就必须 REBALANCE;连胜不是正确性证据
- 不做:放松风险内核、强制加仓、抬高仓位上限
- Agent K 线:1D×45 / 4H×42 / 1H×48 / 30m×48 / 15m×48(紧凑数组)+ 本地计算的 1D/4H structure(SMA/range/前高突破)
P2 — Phase 5 L1 观察
- 部署后 7 日:derivatives≈ticker;REBALANCE citation≥30%(
tool-value-report.sh) - 不做 外部 news/macro/onchain,直到 L1 引用闭环成立
P3 — 不做
- 主账户 / 大资金扩容(仍属 Phase 4 运维判定,不是再开代码锁)
- 私有 WS 作主路径
- 盲目加仓 / 高频 target-weight
明确不做
- 主账户大资金、无 opt-in 的隐式实盘
- 私有 WS 长连作为主路径(REST 对账为主)
- 无引用度量前接入 news/macro/onchain 供应商
验证命令
zig build test --summary all
./scripts/gate2-report.sh
# Live(需密钥 + OKX_REAL_MONEY_OK=1,mode=live)
./zig-out/bin/alphabound --config config/local.toml --control cancel-all
./zig-out/bin/alphabound --config config/local.toml --control flatten
验收矩阵
以下内容与仓库 docs/ACCEPTANCE_MATRIX.md 同步引入。状态列以仓库文件为准。
AlphaBound 验收矩阵
将系统设计 v0.1 的功能需求(FR)、非功能需求(NFR)、上线验收标准(§9.3)、安全边界(§7.3/7.4) 与故障降级矩阵(§7.2)映射为可执行、可勾选的验收条目。
- 验证方法 对应 §9.2 测试金字塔: Unit / Property / Replay / Integration / Fault / Soak / Shadow / Manual(人工演练或评审)
- 阶段 指该条目必须通过的最晚阶段闸门(见 ROADMAP.md);进入 Phase 4 实盘前,P0–P3 条目必须全绿
- 状态: ☐ 未开始 · ◐ 进行中 · ☑ 通过
状态快照(2026-08-13): 核心软件 + shadow/demo/live 主路径已验证(
zig build test全绿; Dashboard 提案/BH/订单; 鉴权+MCP; 本机/生产 OKX 公共行情与私有余额、LLM 提案、market/derivatives 工具落库; 小额 live 下单与 flatten)。 下表 ◐ = 代码+单测/部分实网已落地, 完整 7 日 Soak 与部分实网 Fault 仍缺。
A. 功能需求(FR)
| ID | 需求摘要 | 验收标准 | 验证方法 | 阶段 | 状态 |
|---|---|---|---|---|---|
| AC-FR01 | 行情与账户接入 | 订阅 OKX 公共+私有 WS;启动与断线后 REST 快照对账一致;序列缺口触发 DEGRADED+reconcile | Integration(OKX Demo)+ Fault(断线注入) | P1 | ◐ REST ticker/余额实网 + 周期 REST 对账;公共 WS 帧编解码单测;私有 WS login/push 协议单测;TLS 私有流与断线注入待做 |
| AC-FR02 | 状态引擎 | 内存维护价格/余额/BTC/挂单/净值/HWM/DD;快照带版本;replay 同版本结果逐位一致 | Unit + Replay | P1 | ☑ core/state.zig 单写者引擎;replay 确定性逐位一致测试通过(state engine: replay determinism) |
| AC-FR03 | Agent 决策 | 决策基于一致性快照+检索记忆;可按需调用工具;全程可审计 | Shadow + Integration | P2 | ◐ Context+LLM + market 工具 + 记忆/events + LLM reflection + Risk 准入审计(不执行)+ 全审计; 长跑阈值评审仍待 |
| AC-FR04 | 交易提案 | Proposal 严格 Schema(target/order_policy/confidence/thesis/evidence/invalid_if);坏 JSON/缺字段即作废 | Unit(Schema)+ Fuzz | P2 | ☑ agent/proposal.zig 严格解析(单测)+fuzz:随机字节/全前缀截断/4000 轮字节翻转均不 crash,可解析变体保持全部不变量 |
| AC-FR05 | 风险准入 | 校验 snapshot_version、数据新鲜度、压力净值≥HWM×90%+ExitReserve;能输出 APPROVE/REDUCE/REJECT | Property + Unit | P3 | ◐ 单测+property 基础; shadow 路径已调用 admit 并落 RISK_ADMISSION; Demo 执行联动仍待 |
| AC-FR06 | 订单执行 | client_order_id 幂等(decision_id+版本+序号);部分成交重算差额;超时→UNKNOWN→查询后处置 | Integration + Fault + Replay | P3 | ◐ 单测 + demo 市价/limit place/query/cancel + UNKNOWN 查询 + partial 再规划(≤3腿); Fault/7d soak 待做 |
| AC-FR07 | 长期 Context | 五层记忆可写入/检索/版本化;Reflection 产出结构化 memory_ops 并生效 | Shadow + Unit | P2 | ◐ store+reflection 单测; Shadow: boot/retrieve/episode/LLM+确定性 reflection ops + Dashboard memories |
| AC-FR08 | 可选数据工具 | 工具注册含 Schema/时效/成本;返回统一 ToolResult;调用与结果全部落事件日志 | Unit + Integration | P2(市场类)/ P5(扩展类) | ◐ registry + market.ticker/market.candles OKX REST provider 实调落 tool_calls;扩展域 provider 待做 |
| AC-FR09 | Dashboard | Overview/Market/Trade Detail/Events/Memory/System 六视图;K 线+交易/风险标记;保留 TradingView attribution | Manual(UI 走查)+ Integration(API) | P1(基础)/ P2(全视图) | ◐ Overview+提案+BH+Lightweight Charts K线/量/净值HWM+Memories+Events+System+订单/fills API+Tab+TV 归因;提案链路完整 Trade Detail 回放仍待 |
| AC-FR10 | 管理控制 | pause/resume/reconcile/cancel-all/flatten/safe-shutdown 全部可用且只经本机 CLI/Unix socket | Integration + Manual 演练 | P3 | ◐ CLI 全套;demo cancel-all 会撤 pending;人工演练/长稳仍待 |
B. 非功能需求(NFR)
| ID | 属性 | 验收标准 | 验证方法 | 阶段 | 状态 |
|---|---|---|---|---|---|
| AC-NFR01 | 延迟 | 行情事件进程内风险计算 p99 < 10ms(不含公网);有持续测量与告警 | Soak(基准测量) | P3 | ◐ observability/latency.zig Histogram(2048 环形窗口,nearest-rank 分位)+主循环 market_tick→engine.apply µs 测量,system JSON latency_us{p50,p99,max,samples} 持续可见;soak-report p99 门限告警已接(samples≥20 且 p99>P99_BUDGET_US 默认 10ms → SOAK FAIL);长窗口基准累积中 |
| AC-NFR02 | 可用性 | 断开 LLM/新闻/链上/Dashboard 后,风险监控、订单对账与退出能力仍工作 | Fault Injection | P3 | ◐ LLM 断连注入演练 PASS(2026-08-12,scripts/llm-outage-drill.sh:不可达端点→tick/风险循环继续、HOLD 兜底、干净退出、DB verify PASS);新闻/链上无外呼路径;Dashboard 断开注入待做 |
| AC-NFR03 | 一致性 | 提案未绑定当前 snapshot_version 即拒绝;状态变化后旧提案自动失效 | Property + Unit | P2 | ✅ admission 单测 + 随机化 property(1000 例:版本失配在任意快照状态组合下必 REJECT stale_snapshot) |
| AC-NFR04 | 恢复 | 重启→恢复 DB→OKX 对账→READY;对账完成前不产生增仓提案 | Integration + Fault(kill -9 注入) | P3 | ◐ 生命周期 BOOTING→CONNECTING→RECONCILING→READY 已实现并实网验证;未对账时 fail-closed 起步 exit_only(单测);kill -9 演练 PASS(2026-08-12 生产 SIGKILL→systemd 拉起→10s 恢复 READY,scripts/kill9-drill.sh 可重复执行,soak-report 入账不误报) |
| AC-NFR05 | 部署发布 | 生产 VM 无 Python/Node/Docker;核心二进制与 Dashboard 均可原子回滚;health fail 自动回滚 | Manual(发布演练) | P3 | ◐ 二进制 musl 静态链接(ldd "not a dynamic executable",daemon 零运行时依赖);releases+current symlink 原子回滚+health fail 自动回滚演练 PASS(2026-08-12);共享 VM 上存在他项目的 docker/python,daemon 不依赖 |
| AC-NFR06 | 审计资源 | 关键事件带 state_version/software_version/config_hash/correlation_id;资源(CPU/RSS/fd/WAL/磁盘)有告警 | Unit(信封)+ Soak | P3 | ◐ core/events.zig 事件信封四字段已单测;daemon 落库事件实测含全部戳;soak-report 资源门限已接(RSS>256MB/fd>256/WAL>64MB → SOAK FAIL;磁盘 statvfs 已在 daemon 内) |
C. 上线验收标准(§9.3,Phase 4 实盘闸门)
| ID | 标准 | 验证方法 | 状态 |
|---|---|---|---|
| AC-GO1 | 重启后可从 OKX 对账出正确余额、BTC 数量、开放订单和 HWM | Integration(重启演练×3) | ◐ 重启演练×3 PASS(2026-08-12 生产,scripts/restart-drill.sh:每轮 HWM 恢复+461 memories 重载+OKX 私有余额对账 ok+READY≤9s);开放订单对账待 demo 挂单场景 |
| AC-GO2 | Agent 无法直接访问交易凭证或绕过 Risk Kernel(代码层能力缺失,非 prompt 约束) | Manual(红队评审)+ Unit(接口不可达) | ◐ 架构落地:agent/ 仅产出 Proposal 值类型;凭证只在 exchange/okx/auth.zig;security/isolation.zig 源码扫描单测持续强制隔离;红队评审待做 |
| AC-GO3 | Risk Kernel 核心性质过 property test,覆盖边界/费用/滑点/部分成交 | Property | ☑ admission 2000 次随机 + halted/flattening 模式 + 费用/滑点/shock 单调性(stress equity 非增)+ max_drawdown 收紧单调 + planner 部分成交迭代收敛(qty 单调减不翻向) property 全过 |
| AC-GO4 | 断开 LLM、新闻、链上和 Dashboard 后,风险监控与订单对账仍工作 | Fault Injection | ◐ LLM 断连演练 PASS(同 AC-NFR02);新闻/链上无外呼路径;Dashboard 进程内无独立断开面 |
| AC-GO5 | 所有订单可追溯到 decision_id、snapshot_version、risk decision 和 config_hash | Replay(审计链抽查) | ◐ --verify-db 审计链:订单→AGENT_PROPOSAL_OK 或 ADMIN_TARGET_WEIGHT + ORDER_* + 无孤儿 fills;单测含 operator 锚点;scripts/audit-go5.sh 远端抽查;2026-08-12 真实 agent REBALANCE 样本已有 exchange_id |
| AC-GO6 | 未知订单/陈旧数据/数据库异常进入安全状态,不默认继续增仓 | Fault Injection | ◐ 未知订单→order_ambiguity→degraded(单测);陈旧数据→admission REJECT stale_data(property);DB 审计写失败→journal_ok=false→exit_only、写恢复自愈(2026-08-12 新增,state 单测锁定;行情新鲜不能单独清除降级);进程级 fault 注入演练待做 |
| AC-GO7 | Dashboard 可完整回放一笔交易从观察到反思的链路 | Manual(UI 走查) | ◐ 决策展开含 admission/exec + 按 decision_id 关联订单/成交; 完整链路 UI 走查待 Demo |
| AC-GO8 | 交易模式连续稳定 ≥7 天,完成 ≥1 次断线恢复和 ≥1 次版本回滚演练 | Soak + Manual | ◐ 版本回滚演练 ≥1 次 PASS(2026-08-12 双向);kill -9/重启恢复演练 PASS;执行场所已就绪(mode=live+小额子账号+OKX_REAL_MONEY_OK=1);7 天滚动 soak 窗口积累中 |
D. 风险内核专项(§5)
| ID | 验收标准 | 验证方法 | 阶段 | 状态 |
|---|---|---|---|---|
| AC-RK1 | 保守净值 E_t 扣除退出费用/滑点/挂单风险;HWM 单调不减;DD 公式与设计一致 | Unit + Property | P3 | ☑ risk/equity.zig:保守估值扣费/滑点、HWM 单调、DD 公式、非负回撤全部单测通过 |
| AC-RK2 | 任意输入下 Risk Kernel 不批准使压力净值 < HWM×90%+ExitReserve 的提案 | Property / Fuzz | P3 | ● 压力净值地板单测 + 随机化 property×2(2000+2000 例)+ decimal 极值 fuzz(4000 例:0/1/i64max/1e18 单位级 raw 组合,不 panic、Overflow fail-closed、APPROVE/REDUCE 压力净值 ≥ floor) |
| AC-RK3 | 风险状态机转换(NORMAL/EXIT_ONLY/FLATTENING/HALTED)与 §5.3 条件表一致;HALTED 不自动恢复交易 | Unit(状态机)+ Fault | P3 | ◐ 转换表全路径单测 + 随机序列 property(500 walk×64 步:HALTED 无 reset 不出、出边仅 EXIT_ONLY、FLATTENING 不被健康信号中止);进程级 Fault 注入待做 |
| AC-RK4 | FLATTENING 先撤增险挂单,再退出,持续对账至 BTC 可用≈0 | Integration(Demo 演练) | P3 | ☐ |
| AC-RK5 | 边界穿透时如实记录实际穿透幅度与成交成本(不掩饰) | Fault(极端行情 replay) | P3 | ☐ |
| AC-RK6 | max_drawdown 与 Risk Kernel 参数不可热加载、Agent 不可修改 | Unit + Manual(配置评审) | P3 | ◐ config 仅启动时解析,allow_runtime_override=false 强制;Agent 模块无 config 写路径;评审待做 |
E. 故障降级矩阵(§7.2,逐项注入验证)
| ID | 故障场景 | 期望自动动作 | 验证方法 | 状态 |
|---|---|---|---|---|
| AC-FD1 | LLM 超时/报错 | 本轮 HOLD,无订单;风险与对账继续 | Fault | ◐ shadow HOLD + fault/matrix 分类/坏 JSON 单测;实网断连注入 PASS(scripts/llm-outage-drill.sh) |
| AC-FD2 | 外部工具不可用 | ToolResult=UNAVAILABLE;不得把缺失数据编造成零值 | Fault + Unit | ◐ UNAVAILABLE/null data 单测(fault/matrix)+ market HTTP 路径 |
| AC-FD3 | 公共行情过期 | 进入 EXIT_ONLY;重连 + REST 校验;不增险 | Fault | ◐ stale→EXIT_ONLY + admission 拒增仓(fault/matrix); 实网断线待做 |
| AC-FD4 | 私有账户 WS 断开 | EXIT_ONLY + REST 对账;未知期间不自主开仓 | Fault | ◐ unresolved/stale account 拒增仓单测; WS 断线注入待做 |
| AC-FD5 | 下单超时 | 订单 UNKNOWN→查询后处置;禁止直接重发 | Fault + Integration | ◐ UNKNOWN 禁止 submit 单测 + demo query 路径; 实网超时注入待做 |
| AC-FD6 | SQLite busy | 短暂重试+降采样遥测;关键事件优先落库 | Fault | ◐ stepCritical 对 events/orders/fills/… 写路径重试 + busy_timeout; 注入待做 |
| AC-FD7 | 磁盘接近满 | 停新交易,清理可重建缓存;严重时 HALTED | Fault | ◐ storage/disk statvfs + disk_ok 进健康检查; low→EXIT_ONLY critical→HALTED; 缓存清理待做 |
| AC-FD8 | 数据库损坏 | 仅保留退出能力+应急文本日志;禁止静默新建空库继续交易 | Fault | ◐ boot:已存在文件 open 失败 → FATAL refuse recreate; 应急文本日志/只退能力待扩 |
| AC-FD9 | 回撤边界触发 | FLATTENING → HALTED;记录穿透与成本 | Fault + Replay | ◐ FLATTENING→HALTED + 无自动恢复(fault/matrix);极端行情 replay 待做 |
| AC-FD10 | 进程崩溃 | systemd 重启→重新对账→READY;重启前状态不被假定正确 | Fault(kill -9) | ☑ 生产 kill -9 演练 PASS(2026-08-12) + fault/matrix 单测:fresh engine EXIT_ONLY/未 reconcile 拒增仓,对账后才 NORMAL |
F. 安全边界(§7.3 / §7.4)
| ID | 验收标准 | 验证方法 | 阶段 | 状态 |
|---|---|---|---|---|
| AC-SEC1 | OKX API Key 仅 Read+Trade(无 Withdraw),绑定 Azure 固定出口 IP 白名单 | Manual(配置审查) | P4 | ◐ boot 代码门禁:实盘授权时探测 /account/config,withdraw 权限直接拒绝启动;生产验证 read=true trade=true withdraw=false(2026-08-12);IP 白名单绑定为 OKX 侧人工配置 |
| AC-SEC2 | 密钥文件 root 管理 0600;服务进程只读;密钥不进备份 | Manual + 脚本检查 | P4 | ✅ check-remote.sh SEC2 段自动检查:600 root:alphabound + 数据目录无密钥泄漏 + DB/备份/WAL 字节级抽查真实密钥值不存在,生产 PASS(2026-08-12) |
| AC-SEC3 | LLM Context/日志/错误栈/Dashboard 响应中无 secret/passphrase/签名材料(redaction 生效) | Unit(redaction)+ Manual 抽查 | P2 | ◐ redaction.redact 单测 + logEventPayload 落库前 redact/looksLeaky 拦截;check-remote SEC3 段抽查全部 Dashboard API(system/state/events/decisions/orders/memories/shadow)不含真实密钥值,生产 PASS(2026-08-12);LLM context 出站抽查待做 |
| AC-SEC4 | systemd 加固: NoNewPrivileges/PrivateTmp/ProtectSystem/受限写目录 | Manual(unit 审查) | P1 | ✅ 生产核验(2026-08-12 systemctl show):NoNewPrivileges=yes PrivateTmp=yes ProtectSystem=strict ProtectHome=yes ReadWritePaths=/var/lib/alphabound User=alphabound |
| AC-SEC5 | 外部 HTTP 响应有大小/解压/超时/JSON 深度限制 | Unit + Fuzz | P2 | ◐ security/limits.zig 上限常量+jsonStructureSane 结构扫描(单测含深度炸弹/breakout/截断);OKX REST 512KB、LLM 1MB、egress 探针 4KB 固定容量 sink 接线,超限→记录并拒绝;解压炸弹面(gzip)待评审 |
| AC-SEC6 | Agent 禁止项全部不可达: 读环境变量/密钥/DB 文件、执行 shell、任意 URL、直接获得 OKX client、修改风险配置/Prompt/二进制 | Manual(红队)+ Unit | P2 | ◐ security/isolation.zig @embedFile 源码扫描测试:agent 纯逻辑禁 std.http/net/fs/process/getenv/Child/exchange/execution/storage/risk-admission/凭证 token,openai.zig 仅白名单 std.http;人工红队评审待做 |
| AC-SEC7 | 工具返回视为不可信数据,只进 data 字段;第三方文字不得成为系统指令(注入测试) | Fault(工具污染注入) | P2 | ☑ formatObservation 对 data_json 结构扫描,失败→null;fault/matrix.zig 注入测试:提示注入文本仅存于 data.note 字符串值内,risk_rules 不可变,breakout/深度炸弹 payload 全部中和 |
| AC-SEC8 | Dashboard 默认仅绑定 127.0.0.1;管理命令仅本机 CLI/Unix socket | Integration(端口扫描) | P1 | ◐ 默认 bind 127.0.0.1;生产为私网 VM 上 0.0.0.0(局域网 Dashboard),互联网侧探测出口 IP:8080 不可达(NAT 无端口映射,2026-08-12 实测);管理仅本地控制文件 CLI;完整端口扫描(nmap 全端口)待做 |
G. 数据与运维(§6 / §7.5 / §8)
| ID | 验收标准 | 验证方法 | 阶段 | 状态 |
|---|---|---|---|---|
| AC-OPS1 | SQLite WAL 位于本地磁盘(非网络 FS);Journal Writer 唯一写者;关键事件限时提交 | Unit + Soak | P1 | ◐ WAL+单写者已落地;小时 Backup API→.bak;Soak 待做 |
| AC-OPS2 | 事件信封顶层含 type/correlation_id/state_version/software_version/config_hash | Unit | P1 | ☐ |
| AC-OPS3 | 每小时备份快照(留 24)+ 每日(留 30);备份失败不影响交易关键路径 | Fault + Manual | P1 | ◐ storage/retention.zig 命名/轮换/selectDoomed 纯函数(property 测试)+rotateBackups 接线:hourly(留24)/daily(留30)快照+latest .bak,全部 best-effort 只记日志不阻断主循环;生产恢复演练待做 |
| AC-OPS4 | 每周 restore drill: 备份启动只读实例,校验 schema/事件序列/HWM/订单投影 | Manual(演练记录) | P3 起 | ◐ --verify-db PATH(只读打开,integrity_check/user_version/7 表行数/seq 连续/HWM 可解析)+scripts/restore-drill.sh(最新快照→scratch→校验→新鲜度<2h);生产演练 PASS(2026-08-12,hourly 快照 9s 新);周期化排程待做 |
| AC-OPS5 | 发布 8 步流程可执行;dashboard-only 更新不重启 daemon;核心更新 pause→checkpoint→切换→重启 | Manual(发布演练) | P3 | ◐ 版本化部署上线:/opt/alphabound/releases/<sha>-<ts>/+current 原子 symlink 切换(ln+mv -T),保留 5 版;dashboard-only 免重启路径待做 |
| AC-OPS6 | ready health check 失败自动回滚上一 symlink 并重新对账 | Fault(坏版本注入) | P3 | ◐ install-remote.sh health 门禁(15×2s 探测 /health/ready)失败自动回滚上一 release+记录 deploys.log;scripts/rollback-remote.sh 手动回滚演练 PASS(2026-08-12,双向);真实坏版本注入已发生一次(health grep bug 触发 auto-rollback 路径) |
| AC-OPS7 | 配置热加载规则符合 §8.5 表(Prompt 可热载;max_drawdown 不可) | Unit + Manual | P2 | ☐ |
| AC-OPS8 | 模型调用成本、基础设施成本可见可统计(成本 vs 本金一级指标) | Manual(Dashboard 走查) | P2 | ◐ system JSON 暴露 llm_calls/prompt_tokens/completion_tokens/total_tokens 会话累计;USD 折算与基础设施成本项待做 |
| AC-OPS9 | equity_samples 保留策略生效(1s 保 7 天,1min 永久);tool_calls 原始 30 天 | Unit(保留任务) | P3 | ◐ retention.zig cutoff/prune SQL(单测)+每小时 runRetentionSweep 接线:tool_calls>30d、equity '1s'>7d 清理,'1m' 永久保留;长跑验证待做 |
H. 阶段闸门汇总
| 闸门 | 必须全绿的条目 |
|---|---|
| Gate 0(P0 退出) | 依赖决议 + 24h 长稳(见 ROADMAP,无正式 AC,产出决议记录) |
| Gate 1(P1 退出) | AC-FR01/02、AC-FR09(基础)、AC-SEC4/8、AC-OPS1/2/3 |
| Gate 2(P2 退出) | AC-FR03/04/07/08(市场类)、AC-NFR03、AC-SEC3/5/6/7、AC-OPS7/8 |
| Gate 3(P3 退出) | AC-FR05/06/10、AC-NFR01/02/04/05/06、AC-RK1..6、AC-FD1..10、AC-OPS4/5/6/9 |
| Gate 4(MVP 运维判定) | AC-GO1..8 + AC-SEC1/2 + 以上全部;小额 live 已在 Gate3 解锁 |
维护约定: 每次闸门评审更新状态列并附证据链接(CI run / 演练记录 / 评审纪要); 新增需求先补矩阵行再写代码。