Repository navigation
v2.0.0
主版本 · 智能炒股「五期 · 闭环补齐」(
L01–L10)。
一/二/三/四期把「能跑、能记账、能学、能提案」做完了,五期补的是最后几块不闭环的地方:
自动闭环只闭了一半(会复盘、会验证,但不会自己把经验变成提案)· 策略没有身份与版本锁 ·
决策缺「当时看到了什么、用什么模型算的」的时间字段 · 账本缺部分成交 / 成交量约束 / 停牌 / 公司行为 / 逐市场 tick ·
行情口令与下单口令是同一把、放行靠拒绝名单 · 报告只有站内一个出口且「发出去没发出去」从不写 ·
外面没法启动 / 查询 / 暂停 / 取消工作流 · 新闻 / 基本面没接定时采集、情绪完全无表。
本期把这几块一一补齐,并把全过程整合成一份自包含 HTML(docs/开发文档/五期-闭环补齐-整合报告.html)。新增七个数据库迁移
0047–0053(只做加法、可重复执行、不改任何历史行、文件内不带BEGIN;/COMMIT;),
由api启动时按schema_migrations账本增量自动执行。台账从 47 个文件 / 47 行
走到 54 个文件 / 54 行(max = 0053_collection_complete.sql)。动到
api/fin-worker/paper三个镜像(web/llm-shim/opencode代码未动,版本号随发版一起走)。新增两个环境变量:
HUNTER_EXEC_KEY(下单执行凭证,与行情读取的HUNTER_INTERNAL_KEY分开;
都没有默认值,缺任一paper/fin-worker拒绝启动)。默认值没变:
FIN_MEMORY_ENABLED=0/FIN_EVOLUTION_MODE=off/FIN_AUTO_APPLY=0/FIN_LIVE_ORDER_ENABLED=0。升级:
.env的HUNTER_VERSION与FIN_TAG两个旋钮一起改2.0.0,再
docker compose --profile fin pull && docker compose --profile fin up -d(--profile fin必须带,
否则paper/fin-worker不参与重建)。逐步清单见docs/开发文档/L10-五期上线与整合报告.md(含回滚一步)。
⚠️ 升级前先备份:pg_dump -Fc记下路径 / 大小 /sha256/ PG 版本 /schema_migrations行数。
本版只加表加列、不改任何历史行。
⚠️ HUNTER_EXEC_KEY是本期新加的必填项:老.env里没有它,升级后paper/fin-worker
会因为缺凭证拒绝启动 —— 先在.env里生成一个(openssl rand -hex 32)再up -d。
✨ 新增 · Added
L01· 「经验 → 提案」接上(fin.propose工作流 + 「实验」实体)。 原来那个能提提案的
POST /internal/fin/evolution/proposal写好了却全仓没有调用方(自动闭环只闭了一半)。
现在fin.propose是 Temporal Schedule 里的一条(不另起 cron / 线程定时器),
按市场、对进行中的项目自动、有闸门地把可用经验变成提案;并补出**「实验」实体**
(方案 §12 时间线里缺的那一格「样本外 / 滚动验证」)。只自动「提」,不自动「生效」 ——
FIN_AUTO_APPLY恒 0 未动,生效仍要人工confirm=true。迁移0047_evolution_experiment.sql。L03· 决策「出身证」。 补 §6.2 的缺失时间字段(available_at/revision_id/decision_as_of)·
§10.2 的DataSnapshot对象 · §10.3 的决策上下文(execution_model_version/ 显式mode/portfolio_version)。
拿不到真值的一律NULL(红线 5),不拿now()/ 自增号 / 默认值冒充。迁移0048_decision_provenance.sql。L04· 自有策略服务。 「策略定义」这一层原来根本没有:唯一的策略是写死的示例策略,身份是
fin_param.strategies里一个可被任意改写的自由字符串。现在有只追加的登记表 + 内容哈希 + 触发器锁版本,
外加strategy.submit/strategy.get/strategy.cancel三个正式入口;示例策略降级为一个登记在册、
可被替换的内置策略(不删 —— 个人本地开源部署靠它开箱可用)。迁移0049_strategy_registry.sql。L05· 账本补齐五项。 ① 成交量约束真的读liquidity_max_participation(成交股数 ≤floor(盘口量 × 参与率));
② 部分成交part_fill开关真的生效(开着成交一部分 + 剩余挂着;关着行为逐字节不变);
③ 停牌fin_instrument.halted+ 风控先读它 + 拒单;④ 公司行为只追加事件表
fin_corporate_action+ 账务(分红入现金 / 拆送股调股数与成本);⑤ 逐市场 tick
(标的 → 市场分档 → 全局回落三级解析,三市场各不同,替掉原来写死的全局0.01)。
停牌 / 公司行为数据源没有 → 只做「状态位 / 事件表 + 账务 + 人工登记入口」,如实标注「数据源未接」,一个字节都没编。
迁移0050_account_ledger_complete.sql。L06· 凭证分离 + 执行允许名单(默认拒绝)。 两把钥匙分开:行情读取用HUNTER_INTERNAL_KEY,
下单执行用新的HUNTER_EXEC_KEY(两个不同环境变量、都没有默认值)。门改成「允许名单」:
paper会改账本的四个端点入口先查新表fin_exec_allowance(只追加)—— 空名单 = 谁都不许,
要显式登记才放行(POST /api/v1/exec-allowances)。实盘字段的拒绝名单(LIVE_FIELD_DENYLIST)
继续保留,两道防线都在。GET /healthz多报一个执行允许名单现行条目数。迁移0051_exec_allowance.sql。L07· 发布适配器 +UNKNOWN待核实。 发布从生成流程里拆出来独立一步、渠道走适配器:
in_app(原样搬,行为不变)· 通用webhook·file落盘(记路径 +sha256)。
只做这三个,不接任何要注册 / 要付费 / 要审资质的第三方内容平台。新增publish.submit/publish.get
两个入口,回执统一落fin_publish_receipt。UNKNOWN待核实 + 不盲目重发:超时 / 回执不明 → 写UNKNOWN
并进待核实队列;UNKNOWN下再发同一份报告拒绝(除非显式「重发」标记且留痕)。
补上故障注入第 7 项(「内容已发布,但返回超时或网络断开」)。迁移0052_publish_adapter.sql。L08· 控制通道 + MCP 控制类 + 长任务取消。 四个控制入口runtime.workflow_start / get / pause / cancel
(只认白名单模板名 + 类型化参数,不接受任意代码或 shell;状态从 Temporal 现查,不另存一份;
四个都幂等)。新增一个控制类 MCP(scripts/opencode-mcp/runtime_mcp.py),
在gen-config.py里与数据类 MCP 分开登记 —— 这就是方案 §6.3 的「控制通道与数据通道分离」。
长任务取消接通:workflow_cancel→ 查工作流当前fin_job→ Temporal 取消 → 调 paper 的cancel
→fin_job落CANCEL_REQUESTED,补上 §10.4 的「可请求取消」。L09· 采集补齐。 方案要的「24 小时自动采集」里,新闻与基本面真的接上了定时采集
(每个交易日按市场触发、写库、记来源 / 发布时刻 / 入库时刻 / 缺口);情绪没有数据源 → 只建表 + 登记口 + 口径,
一个情绪值都没编。三条链路全走 Temporal Schedule,没有另起任何 cron / 线程定时器。
迁移0053_collection_complete.sql。L10· 整合报告(自包含 HTML)。scripts/gen_wuqi_report.py生成
docs/开发文档/五期-闭环补齐-整合报告.html—— 一份文件、六部分(开发方案 / 开发计划 /
开发完成后总结 / 开发部署 / 开发详细测试方案 / 测试后截图),截图 base64 内嵌,离线可读。
脚本随仓库提交、可重跑(同一--date+ 同一输入 → 逐字节相同的输出)。
🔧 变更 · Changed
L02· 同一事实只留一份(工程债)。 三处最要命的「同一事实多副本」各合成一份,并加了
会真失败的守护用例:① 港股交易时段 3 份 → 1 份字面量(market_sessions.py双镜像逐字节相同)- DB 行为权威(api 种子脚本改成读 DB 行);②
apps/api业务代码里的
timezone(timedelta(hours=±N))27 处 → 0、IANA 时区名字面量 11 处 → 0(只在market_time.py);
③ensure_schema里重复定义的 DDL 2 处 → 0(paper 内 3 份收成aux_ddl.py一份)。
新代码不许再制造「同一事实多副本」(五期新增红线 14)。
- DB 行为权威(api 种子脚本改成读 DB 行);②
L05· 风控规则清单从六条变七条(停牌作为第一条,方案要求「风控先读它」)。
🆕 新增环境变量 · Added env
| 变量 | 默认 | 说明 |
|---|---|---|
HUNTER_EXEC_KEY |
无(必填) | 下单执行凭证。与行情读取的 HUNTER_INTERNAL_KEY 分开。缺任一 → paper / fin-worker 拒绝启动。 |
迁移
0047–0053均为只做加法;0051新建的fin_exec_allowance默认空名单 = 拒绝,
空库 / 老部署升级后需要显式登记才放行(这是设计,不是故障)。
⚠️ 与上游文档 / 旧方案不同、需要知道的
- 发布渠道只做
in_app/webhook/file(方案 §6.1 的缩小范围)——不接任何要注册、要付费、
要审资质的第三方内容平台。 - 停牌 / 公司行为 / 情绪没有数据源:只做表 + 账务 / 规则 + 人工登记入口,如实写「数据源未接」,
绝不编造(红线 5)。清单见各段成果文档的「未接数据源清单」一节。 L04的策略服务不写fin_param—— 策略参数改动仍走control.py的唯一写入口(红线 7)。- api 全量用例里有 17 条(
tests/test_fin_evolution_router.py)在「整目录一次跑」时失败 ——
这是既有的跨文件测试污染(test_fin_evolution_propose.py泄漏模块级_INTERNAL_KEY),
与本期无关:同一文件单独跑 18 passed,排除污染源后全量 986 · 0 fail · 4 skip。
本期不改别人的用例(红线 6)。
🧪 测试 · Tests
apps/api:998 条 · 17 fail(上述既有污染)· 0 err · 4 skip;排除污染源 986 · 0 fail · 4 skip · 982 passed。apps/fin-worker:319 passed · 0 failed · 0 skipped。apps/paper:320 · 319 passed · 1 skipped · 0 failed。- 迁移幂等:54 个文件 = 54 行台账,连跑两遍 0 报错(第二遍
本次待执行 0 个)。 03 §6十二条必测场景(scripts/r10_demo_verify.py):24/24 通过。- 真浏览器(Playwright):
r13/r9(empty/degraded)0 pageErrors。
Container images(amd64 + arm64 · 匿名可拉):
ghcr.io/agentpit-io/hunter-community-api:v2.0.0ghcr.io/agentpit-io/hunter-community-web:v2.0.0ghcr.io/agentpit-io/hunter-community-opencode:v2.0.0ghcr.io/agentpit-io/hunter-community-llm-shim:v2.0.0