tradingSystem/HANDOFF_2026-08-06.md

151 lines
11 KiB
Markdown
Raw Normal View History

2026-08-06 12:34:57 +08:00
# 交接:三系统量化交易 · 2026-08-06 收盘前
> 这份东西是写给下一个对话开头的。可以整段贴过去,也可以留在仓库里当阶段存档。
我们在推进三个相互衔接的量化交易系统。请先读项目记忆里的 **tradingsystem-bionic-bridge**
**clock-and-timezones**、**tradingsystem-silent-failure** 三篇(都在 08-06 更新过),
背景需要时再读 tradingsystem-ws-channel 和 quant-factor-synthesis工作方式看
feedback-plan-first 和 writing-style-readability。读完再看下文然后等我给任务不要自行开工。
---
## 一、三系统与部署方式(改错部署方式等于白改)
**tradingSystemPMS持仓管理** 跑在 `factor@factorevaluation`。源码是打进镜像的,
所以改码必须 `make deploy`,跑完再 `make test` 看到 ALL SUITES PASS盯盘用 `make watch`
**容器时钟是北京时间。**
**bionic_trader决策系统** 跑在 `192.168.16.188:38000`tlaipro 机)。挂载卷,
`git pull` 之后 `docker compose restart backend-api worker-brain` 即可生效;
但**新增 env 必须 `docker compose up -d --force-recreate``restart` 不重读 env**。
**容器时钟是 UTC。**
**akg-factor-bridge因子桥** 在桥机 `factorevaluation`,容器名 `akg_factor_bridge`
API 在 8300。常驻 API 改码要 compose restart。**容器时钟是 UTC。**
线上运行中的系统只做加法。
## 二、规矩(不变)
先出方案再动手;中文可读性第一,写完整自然句、不自造缩写;只做加法;宁可空池;
关键路径禁止丢弃返回值;全程 Docker不给宿主机直跑 pip/python/psql每条命令必须标注
运行在哪台机器,一块代码里只放一台机器;判收的标准是真机各见一次;写回 Mac 的文件以
written 回执加 md5 为准;**看桥和 bionic 的任何时间戳,先加八小时再和对话里的时间对齐。**
测试脚本由我在实机上运行,跑完把结果发给你,你不用跑复杂测试。里程碑的代码和文档
请提示我及时创建或上传到项目目录。
## 三、下一个任务:给动作引擎加「新建仓」动作
**要解决的问题**:不能每天靠人手工走一遍下命令、排方案那一串。正常应该是上游选股计划
出现之后PMS 按规则自己执行。
**已经查清的现状,不用重查**:整条链除了「下命令」这一步,其余全是自动的。调度表里
08:40 拉候选池08:50 盘前准备,**每分钟**跑命令轮询(把已下达的命令排成方案)、盘中执行
(方案转指令 + 自主提议扫描 + 择时出手)、成交入账加轻对账、消化决策系统的盘中信号,
14:50 T 仓平回15:10 日终结算加窗口收口15:30 日报。`make t-*` 只是这些调度位的手动
等价物,是排查用的,不是日常流程。
**唯一要人的就是下命令,而且是刻意的**:计划回答「能买哪些」,命令回答「今天打算投多少」。
**三条路,性质完全不同**
一是把下命令挂成定时,每天自动下一条升仓命令。改动最小,加一个调度位;代价是仓位单向
增长到撞上组合上限,而且不看市场状态。
二是把自主档位调到 full。**这条解决不了问题**——它只让已有持仓的增持类提议不用人确认,
而动作引擎产出的只有补足底仓、回踩补仓、盈利加仓、减持这四类,**根本没有「新建仓」
这个动作**。
三是给动作引擎加新建仓动作,让自主提议除了管已有持仓,也能从候选池里挑新票,走同样的
规则闸、研判闸、档位分流。这才对得上要解决的问题,是新逻辑不是新调度位。
**我选第三条。先出方案,我拍板之后再动手。**
**开工前要知道的约束**:择时读的那张 `strategy_daily_results` 表,在盘中跑 push-pool
触发补扫时会被就地改写(详见第六节)。开发期靠「盘中不跑 push-pool」这条纪律规避
没有改代码。设计新建仓动作时要把这件事放进考虑,别让无人值守的建仓建在会漂移的输入上。
## 四、当前系统状态2026-08-06 盘中,约 11:15
账户总资产 2,000,288.86,可用 1,881,764.86,组合仓位 5.92%。参数:总规模 200 万,
自主档位 propose_only下发模式 ws择时档位 A组合上限 70%,单股上限 8%,最多 20 只,
执行窗口默认 3 个交易日。
**持仓三只**600150.SH 一千七百股、可卖一千二、摊薄成本 34.625、安全垫 +0.16%,参考位
支撑 34 压力 37 止损 34来源 bionic002335.SZ 一千九百股、可卖零、摊薄成本 30.984、
安全垫 +0.41%000035.SZ 一百股、可卖零、摊薄成本 5.028、安全垫 -1.55%**决策系统对它
的定性是 SELL**。
**在途四条**000035 的减持一百股来源自主提议11:13 我在页面人工放行002335 的清仓
一千九百股(来源决策系统风控信号,置信度 95%002518 的买入九百股(**被新装的定性闸
拦着**窗口今天到期000063 的买入一千七百股(现价高于买入区间上沿,不追,窗口今天到期)。
前两条都要等明天 T+1 才能出手。
## 五、08-05 到 08-06 做完的事
**买入侧补上了一道闸,两侧都已部署,真机判收成立。** 起因是发现候选层的结论对执行层
完全不可见:桥用 `strategy_daily_results.signal_type` 落在 SELL、AVOID、DROPPED 就把票请出
候选池,而决策系统的择时应答读同一个字段、放进 `observed.y_signal` 原样回传却从不用它判断,
PMS 又只解析 verdict、limit_price、reason。同一条结论一边当判决一边当摆设。
600841 就差一根 3.3% 的阴线会被买进来。
改动:决策系统 `app/services/pms_advisor.py``BAD_Y_SIGNALS` 常量和买入分支的闸,
`config/settings.py` 加开关 `PMS_EXEC_BLOCK_BAD_Y_SIGNAL`PMS 侧 `app/core/rule_gate.py`
`BAD_SIGNAL` 检查项并把定性无条件写进 hard_numbers`app/services/exec_advisor.py`
`observed.y_signal` 存进 advice 并挂到决策上,`app/services/executor.py` 传进规则闸 flags
`scripts/test_batch3_units.py` 加一条用例。**08-06 真机拦下第一笔002518 停在 PROPOSED、
成交 0、理由是新写的那句。** PMS 那道 `BAD_SIGNAL` 至今没真的触发过(决策系统先回 WAIT
就走不到规则闸),符合当初「第二道闸平时空转、只为留痕」的预期。
其余600841 的在途买入指令已撤(回执是 `cancelled:0` 加「仅本地置撤销」PROPOSED 从没
下发过子单时走的就是这个分支freeze 的 manifest.json 判收通过08-03 和 08-04 两天
都在XXL 例行调度的根因查实——从来没有自动拉起过,日志里只有手动触发的行,配置已重新设计。
## 六、悬而未决(按优先级)
1. **主线**:动作引擎加新建仓动作,见第三节。
2. **昨夜结论会被盘中补扫就地改写**。push-pool 跑完触发增量补扫,补扫用 `trade_date=昨日`
就地覆盖已有那行,而 `fetch_yesterday_strategy` 是取最新一行、不按日期过滤。实证:
000035 在 09:53 成交时定性是 WATCH、压力 5.2,补扫之后变 SELL、压力 5.15002335 的支撑
从 31.27 变成 29.00,差 7.3%。**开发期靠「盘中不跑 push-pool」规避代码未改。**
真要修,最小加法是给 `fetch_yesterday_strategy` 加「只取今天之前」的过滤,但那样盘中
补扫的产出就完全用不上了,是不是想要的要先拍板。
3. **卖出侧的镜像缺口**。桥对「持仓且形态恶化」只警示、明确不出池,而 PMS 没有任何机制
会因为决策系统的定性去减仓——研判闸只管买入侧的补足、加仓、补仓,规则闸的冻结和黑名单
只挡增持。买入侧补上了卖出侧还是空的。000035 现在就是这个状态。
4. **总资产与持仓市值的口径**。总资产来自 QMT 的 ws 资金快照,被组合刹车当权益基准用
高水位与回撤15:10 跑);持仓市值是 PMS 拿 Redis 分钟线自算的。08-05 两边差 564 元,
08-06 盘中只差 51 元。倾向是取数时点差不是口径差,收盘后价格静止时再对一次才能定案。
5. **时区显示错位八小时**。`_today_exit_verdict` 把 created_at 直接截成「01:35」拼进理由
传到 PMS 页面和北京时间戳并排显示。给 bionic 容器设 `TZ=Asia/Shanghai`(新增 env
必须 force-recreate或者格式化时显式转。低优先。
6. **600150 最后五百股买在区间上沿**。区间连续四个交易日都是 [33.66, 34.9] 没变过,
今天现价正好等于上沿,闭区间判定放行,成交在 34.89,摊薄成本被从 34.514 抬到 34.625、
安全垫从峰值 +1.99% 压到 +0.01%。这是分批建仓遇上区间长期不变的固有副作用。
要不要改(现价等于上沿时不买,或者区间连续 N 天不变时降档)是策略取舍,未拍板。
7. **XXL 例行调度已重新配置**,验证点是看桥的 `data/xxl_build.log` 有没有在北京时间 07:10
自动长出新行(日志是 UTC会写成前一天的 23:10
8. `trade_no` 格式核验(关系 S3 收尾函第一节的阻断项):
`docker compose run --rm --no-deps pms-web python scripts/ws_smoke.py inbox --type trade --width 600`
`SHADOW-xxxx#1` 这种确定式就闭环,还是 T-SHADOW 随机串就继续追。这条一直没做。
9. 命令目录里 `FREEZE_STOCK` 的说明写着「在途买入撤销」,与实现不符(它是参数类命令、
没有 planner只让规则闸的冻结项拦文案要补账。
10. 文档补账:`WS_INTEGRATION_STATUS.md` 停在 07-30`BIONIC_PMS_INTERFACE.md` 第三节要
加一句新闸README 待办 9 和 10 标判收。
11. 老悬项不变分歧票候选层拦截未拍板AKG_PLAN 并入 TECH_POOL 的共管规矩未拍板;
07-29 那 19 条 SIG_INVALID 未查明。
## 七、这轮我犯过的三个误判,别重犯
**一是看见巧合就当线索。** 600150 的现价 34.900 恰好等于两笔委托的限价,我据此断定取价
有问题还推出「安全垫其实是负的」。实际行情源是活的、分钟线连续34.900 就是当时的
真实价。**先验证数据源是否在更新,再怀疑取值。**
**二是没换算时区。** 审计行写着 01:35我当成北京时间于是把一个正常的四分钟赛跑
09:31 咨询干净、09:32 成交、09:35:51 结论落库、09:36 信号到达)判成了「老闸漏读」的 bug
差点去改代码。**桥和 bionic 的时间戳一律先加八小时。**
**三是推理没落地就当结论。** 我推定 `audit_date` 会因为容器在 UTC 而错位一天,实际写入侧
用的是北京日期,洞根本不存在。**时间相关的猜测必须先查实际数据再下判断。**