13 KiB
工作交接 · 2026-09-10
写给下一个接手的会话。读完这一份就能接着干,不需要回头翻聊天记录。
一、一句话现状
三个系统今天都有改动落地。持仓管理系统与择时决策系统的改动已经重启生效;选股系统还有一批改动躺在服务器上没生效,等休市后重启。今天开盘前出过一次页面超时故障,已经修好并验证。
二、最要紧的待办:休市后重启一个容器
做什么。 重启选股系统的接口容器,让今天中午之后的三件改动生效。
在哪台机器。 155,用户名 factor,端口 2280。
ssh -p 2280 factor@192.168.16.155 'cd /home/factor/project/akg-factor-bridge && docker compose restart -t 20'
重启之后必须立刻做两件事。 第一件是预热,因为重启会清空进程内缓存,不预热的话下一个访问的人要等三十三秒:
ssh -p 2280 factor@192.168.16.155 'curl -s -o /dev/null -w "预热 %{time_total}s\n" --max-time 120 "http://192.168.16.155:8300/plan?top=300&obs_top=100"'
第二件是确认新代码真的在跑:
ssh -p 2280 factor@192.168.16.155 'docker exec akg_factor_bridge python3 -c "import api;print(\"缓存存活\", api.PLAN_CACHE_SEC, \"秒;快照路径开关\", api.PLAN_FROM_SNAPSHOT)"'
预期读数是「缓存存活 43200 秒;快照路径开关 True」。
为什么不能现在重启。 现在是交易时段。重启会让持仓管理系统那一跳拉不到计划,还会清空缓存触发一次三十三秒的冷启动。而今天不重启也没有损失,理由见第四节。
三、今天做完了什么
甲、开盘前的页面超时故障(已修好并生效)
现象。 09-10 早上 09:02,持仓管理系统页面报「上游的选股计划读不到 · timeout of 60000ms exceeded」,加仓和建仓命令因此没有票可选。
根因,两半。 一是选股计划接口的缓存只活十分钟,盘前 08:40 预热那次花了三十九秒、08:50 就过期,用户 09:02 打开页面正好撞上冷启动。二是装配那一句写在锁外面,页面一次加载并发拉好几路,全部判缓存未命中、各自跑一趟三十多秒的装配、还互相抢同一批数据库连接,叠加破了六十秒。
修法。 缓存存活从十分钟改成十二小时(缓存键里带的是真实数据日,上游换日后旧那份立刻失效,新鲜度本来就不靠时间保);同一个键同时只算一次,第一个去算、后到的等它算完直接吃缓存,不同参数组合互不阻塞。
状态。 已重启生效,实测三路并发总墙钟三十四秒,等于单跑一次。台账记在选股系统第 056 条。
乙、那个故障的正解(代码就位,等重启)
用户问了一句「这个严重依赖实时失效的缓存的设计是对的么」。答案是不对,缓存只是把「每次都三十三秒」变成「每天第一次三十三秒」。于是做了正解,三件事:
-
接口改读当日全量快照。 出计划时本来就落了一份全量快照(不裁剪、不设主题限额),注释里写明它是「复盘与对账的唯一底本」,只是接口一直没读它。现在接口先读那份底本、按请求参数截取,读不到或太旧就自动回落到现算。实测零点四一秒对三十二点三秒,快七十八倍。
-
新鲜度守卫。 快照太旧就不能当今天的计划下发。两条判据:代码版本要与当前一致;生成时刻距今不超过十六小时。任一不满足就退回现算。
-
取因果论断的查询补确定排序。这是今天最值钱的一条。 那条查询原来没有排序,而它的文档串写着「每票取最近披露日的最多三条」。数据库在没有排序时返回顺序不保证,于是同一个数据日、同一份代码,相隔三十二秒的两次装配结果就不一样:候选卡差五处、逻辑线差五处、候选卡名次差二十处,顶层的候选单与关注名单也不同。计划因此不可复现。补上排序后两次现算完全一致。
状态。 代码已推到 155,选股系统十个测试文件全部通过,但服务进程还没重启,尚未生效。台账记在选股系统第 057 条。
丙、盘中改判与信号聚合(09-09 做的,已重启生效)
两件事,都已在 09-09 傍晚重启生效:
- 点股票看它今天的全部信号。 持仓管理系统新增按代码回扫五个上游源的接口,页面三处入口可点开抽屉。顺带修了四处「弹了遮罩但没有信息」。
- 盘中改判。 持仓管理系统新增解锁重问(研判驳回后的当日闸可解除一次);择时决策系统新增盘中强势扫描(进攻侧第一条主动通道)与研判强制刷新;资金流分发加了方向闸、覆盖面闸与冷启动配额。
台账记在持仓管理系统第 001 到 005 条、择时决策系统第 001 到 004 条。
丁、通道横幅读错配置源(另一个会话做的,已生效,我复核过)
持仓管理系统的通道进程启动横幅说「模式 未启用(空转)」,而通道其实是启用的、握手在线。那一行读的是环境变量层,真实启停由运行参数表决定。已改成读同一个源。
我用六个维度做了复核,三十一条疑点全部被对抗性验证驳回,零个确认的问题。证据是同一份日志里三次启动的横幅对比:旧代码两次都说「未启用」但下一行就握手成功,新代码说「启用」,对上了。
四、还没生效的改动清单
只有选股系统这一批。重启后自动生效,不需要额外操作。
| 改动 | 生效条件 | 今天不生效有没有损失 |
|---|---|---|
| 接口读快照 | 重启 | 没有。快照路径今天本来就会因为代码版本不一致而回落到现算 |
| 新鲜度守卫 | 重启 | 没有。它本来就是配合上一条用的 |
| 取论断补排序 | 重启,且要等下次出计划才影响快照 | 没有。今天现算的结果已经被缓存住,重不重启下游拿到的都是同一份 |
明早自然验证。 次日早上七点十分出计划时会用带排序的新代码,之后接口就走快照路径了。查这条:
ssh -p 2280 factor@192.168.16.155 'docker exec akg_factor_bridge sh -c "grep \"^plan \" data/access.log 2>/dev/null | tail -3"'
预期日志里的 source= 是 snapshot、耗时零点几秒。看到 source=live 时,同一份日志里会有一行警告说明为什么没走快照。
五、盘中改判那两件事的上线顺序(尚未开始)
代码全部就位、测试全绿,但开关还收着,要分五段上,前两段不能同时开。
| 段 | 做什么 | 前提 | 观察多久 |
|---|---|---|---|
| 一 | 打开解锁重问:页面把 PMS_OPEN_REASK_ENABLED 改开,即时生效不用重启 |
现在就能开 | 三个交易日 |
| 二 | 打开强势扫描的观察档:STRENGTH_SCAN_ENABLED=True 且 STRENGTH_SCAN_DRY_RUN=True,一次大模型都不打 |
第一段观察满三天 | 两个交易日 |
| 三 | 关掉观察档,真派单 | 第二段读数正常 | 三个交易日 |
| 四 | 资金流分发半开:WATCHER_METRICS_DISPATCH_MODE=full,配 WATCHER_METRICS_FULL_SIDES=inflow 与 WATCHER_METRICS_SCOPE=covered |
必须单独一段 | 两个交易日 |
| 五 | 资金流分发全开:SIDES=both |
第四段全绿,且当日兜底卖出条数恒为零 | 两个交易日 |
第一段与第二段为什么不能同时开。 它们会互相喂 —— 强势扫描产的转多广播正好是解锁重问的第一条解锁条件。同时开就分不清「今天解锁了五次」是解锁阈值定得准,还是扫描在制造信号。
第四段为什么必须单独。 它改的是一条全市场的流,量级与前两件差两个数量级。任何异常读数出现时,必须能一眼确定是它引起的。
完整说明在两个仓库各自的 docs/盘中改判与信号聚合方案_2026-09-09.md。
六、机器与部署方式
| 系统 | 仓库 | 机器 | 代码怎么生效 |
|---|---|---|---|
| 数据基座 astock-kg | astock-kg | 178(ssh -p 2280 tlai@192.168.16.178) |
— |
| 选股系统 | akg-factor-bridge | 155(ssh -p 2280 factor@192.168.16.155),仓库在 /home/factor/project/akg-factor-bridge |
源码挂载,docker compose restart 即可 |
| 持仓管理系统 | tradingSystem | 155(同上),仓库在 /home/factor/project/tradingSystem |
源码挂载(有 override 文件),docker compose --profile sched --profile ws restart -t 30。-t 30 是必须的,通道进程要二十五秒优雅退出 |
| 择时决策系统 | bionic_trader | 188(ssh -p 2280 tlai@192.168.16.188),仓库在 /mnt/work/project/bionic_trader |
源码挂载,docker compose restart 即可 |
不动运行中的容器就跑测试的办法。 持仓管理系统那边挂载工作树到临时容器:
ssh -p 2280 factor@192.168.16.155 'cd /home/factor/project/tradingSystem && docker compose run --rm --no-deps -v /home/factor/project/tradingSystem:/app pms-web python scripts/run_tests.py'
择时决策系统那边直接 exec 一个新进程(运行中的工作进程用的还是旧代码,互不影响):
ssh -p 2280 tlai@192.168.16.188 'docker exec trader_worker_brain python3 scripts/selftest_strength_scan.py'
七、绝对不能碰的东西
188 上那套持仓管理系统的容器(pms-web、pms-ws)是对着实盘通道部署的正式实例。 判据三条任一成立即可定性:账本表前缀是 real_、通道端点指向 192.168.16.98(实盘端点)、配了独立的实盘密钥且通道开关开着。它的代码停在 08-28,从没拉过 09-09 之后的提交,通道一直握手失败,是「实盘配置全部就位、通道未通、一单没下过」的状态。正因为这样才更不能碰 —— 只差通道联通和一个参数就会真下单。
155 上那套才是模拟实例(表前缀为空、端点 192.168.18.182)。但要注意:它的下发模式是 ws 不是影子模式,2026-08-03 由用户手动设的,会真向模拟盘发委托。出口表里有 196 笔真实指令单,时间跨度 8 月 4 日到 9 月 7 日。
红线。 禁止关机与重启机器。容器的重启、重建与其他关联操作必须先经用户同意。提交、拉取、验证可以直接做。服务器上只做 git pull,不要跑 git stash —— 09-09 我在 155 上跑过一次,把它本地未提交的一个脚本改动藏走了,靠 git stash pop 才还原。
八、两个容易再踩的坑
一、时区。 155 的宿主机与选股系统容器跑在世界协调时上,日志、快照里的生成时刻、构建日志的时刻全是世界协调时,加八小时才是北京时间。持仓管理系统的四个容器设了上海时区,所以它们的日志是北京时间。同一台机器上两种时区并存。判断「这个任务什么时候跑的」之前先确认容器时区:
ssh -p 2280 factor@192.168.16.155 'docker exec akg_factor_bridge date "+%F %T %Z"'
我因为这个坑犯过两次错。一次把宿主的 07:47 当成早上(实际是北京时间 15:47),一次把快照的 2026-09-09T23:10 当成「前一晚跑的」(实际是北京时间 09-10 早上 07:10),差点据此去修一个不存在的问题。
二、一条方法上的教训。 想验证「甲和乙为什么不一样」时,先做「甲和甲自己比」。今天本来以为是快照过时,做了「连着现算两次」的对照才发现现算自己跟自己都对不上,根因是查询没有排序。不做这一步就会去修一个不存在的问题。
每日节奏(北京时间)。 07:10 选股系统出计划并落全量快照;08:40 持仓管理系统拉计划;08:45 把当日区制追加进同一份快照。所以交易日盘中,最新数据日是前一交易日,它的快照当天早上就生成好了。
九、未决的事,等用户拍板
-
README 与实际状态不符。 持仓管理系统的 README 第 171 行写「当前仍是影子模式」、第 198 行写「依然没有任何系统会自动下单」,而实际从 8 月 3 日起就是
ws下发模式、发出并成交了 196 笔。这不是代码缺陷(页面顶部有实时横幅显示真实模式),但是那种读了会做出错误安全判断的过时说法。我问过要不要改,用户还没答。 -
不追高那道闸的口径名不副实。 变量名与错误信息都说「当日涨幅」,实际算的是相对今日开盘的涨幅。改它会影响所有买入,要单独评估。已记台账(持仓管理系统第 002 条),本次没改。
-
两处量比口径不一致。 择时决策系统的弱市闸按「从开盘算的已过时段」折算,而新代码按「分钟线实际覆盖的时段」折算。后者才对(行情库那张键是滚动窗口,不保证从开盘存起)。改前者会影响所有建仓仲裁,已记台账(择时决策系统第 003 条),本次没改。
十、台账在哪
每个仓库各有一份,记的是每一条影响下单或候选单的规则改动、依据、预期、复核日期。
- 选股系统:
akg-factor-bridge/docs/复盘决定台账.md,最新到第 057 条 - 持仓管理系统:
tradingSystem/docs/复盘决定台账.md,第 001 到 005 条 - 择时决策系统:
bionic_trader/docs/复盘决定台账.md,第 001 到 004 条