14 KiB
交接:三系统量化交易 · 2026-08-07 开盘前
这份是给下一个对话窗口用的。详细节点在
tradingSystem/DEVLOG.md,那里按时间记着每一条 「做了什么 / 动了哪些文件 / 部署方式 / 真机判收 / 还欠着什么」。这份只写坐标、状态和待办, 需要细节就去翻 DEVLOG,不要凭这份文件的概括去改代码。另一条更要紧的:以项目代码为准,不要迷信文档。 上一轮交接文档里有大量上一个对话 汇总时产生的幻觉(例如把已经存在的
A_OPEN说成不存在)。读代码,不读文档的结论。
一、三系统与部署方式(改错部署方式等于白改)
| 系统 | 位置 | 改码怎么生效 |
|---|---|---|
| tradingSystem(PMS,仓位管理) | factor@factorevaluation |
源码打进镜像,必须 make deploy;跑 make test 见 ALL SUITES PASS(当前 469 例);盯盘 make watch |
| bionic_trader(决策系统) | 192.168.16.188:38000 |
挂载卷,git pull 后 docker compose restart backend-api worker-brain;新增 env 必须 docker compose up -d --force-recreate,restart 不重读 env |
| akg-factor-bridge(因子桥) | factorevaluation,容器 akg_factor_bridge,API 8300 |
常驻 API 改码要 compose restart |
时区(08-06 查实、08-07 再证一次,按「哪种时间」分,不能按「哪个系统」一刀切)
- 容器时钟与容器日志正文 —— 北京时间,不加八小时。证据:bionic 容器内
date=15:37 CST。 - 数据库时间列(
strategy_audit_log.created_at、strategy_daily_results.updated_at)—— UTC,要加八小时。证据:08-07 北京 09:03 时该库SELECT NOW()=2026-08-07 01:03:32。 - 日期列(
audit_date、trade_date)—— 北京日期,不换算。 docker logs -t前缀是 UTC,跟正文里 Python logging 的时间不是一个口径,别混读。
上一轮交接文档写的是「bionic 容器时钟是 UTC,先加八小时」,错的,已在 DEVLOG 头部改正。
二、规矩(不变,逐条都被真实事故验证过)
- 先出方案再动手。 不要边想边改。
- 中文可读性第一:写完整自然句、不自造缩写、不发明术语。(我发明过「干跑」,项目自己的词是「试算」,被当场纠正。)
- 只做加法。 动线上系统只加不改,改既有行为要单独提、单独拍板。
- 宁可空池。 数据不干净就交空的,不要凑。
- 关键路径禁止丢弃返回值(静默失败是这个项目的头号 bug 模式,有 48 例专项单测盯着)。
- 全程 Docker,不给宿主机直跑 pip / python / psql。
- 每条命令必须标注运行在哪台机器,一块代码里只放一台机器。
- 判收标准是真机各见一次,不写「应该没问题」。
- 写回 Mac 的文件以 written 回执加 md5 为准。
- 测试脚本由用户在实机上跑,跑完把结果贴回来;不要自己跑复杂测试。
- 里程碑要提示用户及时创建/上传到项目目录。
- 动 tradingSystem 以外的系统之前先答三题,第一题是「是否影响了原有业务系统」。决策系统本来就不管仓位,要加仓位信息只能单独处理 PMS 那部分逻辑。
三个不许重犯的误判(外加这轮新增的第四个)
- 把巧合当证据。
- 时间不换算就下判断。
- 推理没落地就当结论。(这轮又犯了一次:我推断「新建仓没部署,所以那些
PMS_REJECT不可能来自它」,而用户当时已经盘中部署了。) - 新增:把「我没改过这个字符串」当成结论交付。 今早那个「【手动重跑AKG_PLAN】」,正确做法是全仓库检索出唯一写入点、把调用链一行行走通、再用落库时刻查实,而不是止步于「不是我改的」。
三、当前系统状态(2026-08-07 开盘前)
- 新建仓(OPEN)自主提议已上线并跑过实盘,
PMS_OPEN_AUTONOMY = full,QMT 是模拟池。 - 研判闸已真正接通(
PMS_JUDGE_API_BASE之前一直是空的,08-06 才第一次真发请求)。 - 决策系统的盘中买入信号已接进 PMS(此前一直被丢在门口)。
- 两个 bug 已修:研判请求体的
Decimal序列化、运维口径文本污染股票评述。
最近提交
| 仓库 | 最新提交 | 部署状态 |
|---|---|---|
| tradingSystem | bcf9ff0 08-07 09:13 处理评述问题 |
✅ 已 make deploy + make test 通过(用户确认) |
| bionic_trader | 6e82dcb 08-07 09:14 处理评述问题 |
⚠️ 未部署,等收盘后 docker compose restart worker-brain |
| akg-factor-bridge | d076c96 08-05 |
本轮未动 |
四、08-06 → 08-07 做完的事(细节见 DEVLOG 同名节点)
- 新建仓动作,两侧代码写完。PMS 侧动了
action_engine(新增eval_open/scan_open)、proposal_service(_scan_open/_route_one的 OPEN 分支)、judge(OPEN 硬数字裁剪,只送定性材料不送仓位数字)、exec_advisor(参照位漂移保护)、exec_timing(窗口末日强制完成只对命令生效)、signal_rules/signal_service(新增NOTE_BUY)、param_store/settings。新增test_batch12_units.py44 例,全量 469 例通过。bionic 侧只动tasks_intraday.py的两个PMS_JUDGE块(48 增 4 删),不加 env 所以 restart 即可。 - 决策系统买入信号接进 PMS:并入既有 Redis 信号链,不轮询。
- 窗口末日追高修正:
hard_gate的is_command改成必填无默认值,自主买入在窗口末日不强制完成、到期作废(可以接受买不上);卖出侧故意不动。 - 跳过原因分得开:
skip从集合改成带原因的字典,四种处境(在途提议 / 在途指令 / 规则闸拒过 / 研判闸驳回)各有各的话。 - 研判闸的
Decimal崩溃(危害渐进,值得记住):_recent_ledger()把price_at(DECIMAL 列)塞进请求体,requests.post(json=)序列化不了。只要一只票的评审账本里有过任何一行,它的研判就必然失败,而账本只会越积越多——过几天几乎所有票的研判都会失败并降级人工确认,而每一条看起来都只是「研判不可用,降级人工确认」这种系统里天天有的正常降级。修法是在请求出口统一做jsonable()递归转换,不是修单个字段。 - 运维口径护栏(今早):见下节。
五、今早这条单独说:【手动重跑AKG_PLAN】
现象:页面上部分股票的评述里冒出「【手动重跑AKG_PLAN】」这种看不懂的字段。
根因(全部源码验证,非推测):bionic_trader/scripts/rerun_pool.py:237-238 拼出
【手动重跑】手动重跑池 AKG_PLAN,然后 delay(c, reason, None, target_date) ——
第二个位置参数不是留痕字段,是 reviewer_feedback,风控官质询通道。
文本不带「【盘中」前缀,IntradayClassifier 返回 None,于是掉进 elif reviewer_feedback:,
被拼进提示词的 [📢 CRITICAL CHALLENGE FROM RISK OFFICER] 段,后面跟着
You MUST address this in your analysis。那是命令,大脑照办写进 analysis,
再经 save_to_database 覆盖进 strategy_daily_results.analysis_summary。
比字段本身重要得多的收获——悬项二从推测变成实证。 rerun_pool 落库是
ON DUPLICATE KEY UPDATE,把 signal_type / support_level / pressure_level / analysis_summary 一起就地覆盖。查实的落库时刻(库时钟 UTC,下表已换算北京时间):
| trade_date | 行数 | 落库时刻(北京) | 当时是什么时候 |
|---|---|---|---|
| 20260806 | 16 | 08-06 22:32 → 22:45 | 收盘后,安全 |
| 20260805 | 18 | 08-05 22:30 → 08-06 11:04 | 盘中,改写的是当时正被读的昨夜结论 |
| 20260804 | 11 | 08-05 13:04 → 08-07 00:50 | 盘中,补录历史日 |
这张表下游有两个读者:bionic pms_advisor(支撑压力位算 PMS 买卖区间、signal_type 走
BAD_Y_SIGNALS 闸)与桥 pool.py 的 BAD_SIGNALS(决定把哪只票请出候选池)。
所以「盘中不跑 push-pool」这条纪律不只针对桥,rerun_pool 同样在内。
改法(两处,缺一不可):rerun_pool.py 下发固定传 None(根治),--reason 保留但只印在
脚本输出里;tasks_brain.py 加 _is_ops_note() 前缀护栏认
【手动重跑】/【运维】/【回补】,先打日志再置空(兜底)。只做根治不做兜底不行——脚本用法
示例明写着鼓励人手填 --reason "调整X因子后重跑"。新增
scripts/selftest_ops_note_guard.py 24 项,做过三次变异验证确认它真会失败。
已污染的评述救不回来:就地覆盖,没有历史表。
六、待办(按优先级)
P0 — 收盘后第一件事
- bionic:
git pull→docker exec trader_worker_brain python scripts/selftest_ops_note_guard.py(见「全部通过」)→docker compose restart worker-brain。没有新增 env,不用--force-recreate;backend-api没动,不用重启它。 - 判收第二步:收盘后跑
rerun_pool.py --group AKG_PLAN --limit 1 --reason "护栏验证",确认 worker 日志有「🛡️ 运维口径说明已从提示词中剔除」,且该票新落库的analysis_summary不含「手动重跑」。
P1
- 队列里那三条
PRP_..._OPEN提议要在页面上驳回(它们的研判从来没成功过,留着会挡住这三只票的重新评估)。08-07 早上是否已驳回,未确认。 - 第一周要盯的五个数:每天有几只候选落在买入区间内、研判驳回率、研判 UNAVAILABLE 率(Decimal 事故后新加的第五个)、
intraday_exec一跳的耗时分布、评审账本每天的行数。 - OPEN 的研判驳回率要连着看几天。08-06 是 11 条全 REJECT(14:07–14:38,理由都在谈开新仓,框架是对的),零 PASS。理由引用宏观空头/熊市共振,当天 100% 驳回可能是对的,但 OPEN 的判据里有双重保守(「标准应当比加仓类更严」+「宁可错杀不可错放」),要盯几天看是不是压得过死。
P2 — 需要用户拍板
- 口径三:信号票是否可以放宽「不追高」或择时闸。背景:信号池与候选池重叠只有 1/67,唯一重叠的
300570.SZ倒在NO_CHASE_MA5: 距 MA5 12.22% > 上限 6%。而那 67 条信号理由全是「放量突破 / 量比 8.55 / 站上关键位」——按定义就是离 MA5 远的票。所以口径一(信号只重排序、不放宽任何闸)结构上注定拿不到增量,只有口径三才有真增量。但它动的是「不追高、接受买不上」这条纪律,必须用户决定。 SZ000800有两行打架的定性:trade_date=20260806是SELL(08-06 22:38 写入),trade_date=20260804是DROPPED(08-07 00:50 写入,晚了两个多小时)。补录历史日会写出「时间更新、日期更旧」的行,取数方按trade_date排还是按updated_at排会拿到不同答案。pms_advisor与桥pool.py两处口径要对一遍。- 已污染的三批评述(16/18/11 行)要不要收盘后洗一遍。洗=再跑一次全量重算,支撑压力位会再动,只能收盘后做。
P3
- 给
industry.get_many的gp_stock_category分支加按日缓存(每跳省几十次库查询,但改的是既有函数的时序行为,单独提、单独拍板)。 rerun_pool.py里--dry-run的中文说明写的是「干跑」,项目里同类东西叫「试算」,措辞不统一。- 文档补账:
WS_INTEGRATION_STATUS.md停在 07-30;BIONIC_PMS_INTERFACE.md要补新建仓这一路(研判闸第五类动作、硬数字裁剪、择时侧零改动)。
七、悬而未决
| # | 事 | 状态 |
|---|---|---|
| 二 | 盘中改写 strategy_daily_results 顶掉昨夜结论 |
已从推测变实证,08-05 / 08-06 各发生一次。PMS 侧有 PMS_OPEN_REF_DRIFT_MAX 漂移保护,但那是止损不是免疫 |
| 四 | 总资产与持仓市值的差额 | 已结:564(08-05)→ 51(08-06 盘中)→ 4.00 元(收盘后),是时点与价格精度差,不是口径差。但 + sell_return_today 双算的假设没测过(当天零卖出),仍开着 |
| 八 | trade_no 幂等键 |
trade_no 是随机串(T-SHADOW-420911c4b8),不是确定性的 SHADOW-xxxx#1。回放到底按 trade_no 还是按单调的 seq 去重,未确认 |
| — | trading_buy_plan |
死枝:最新一行停在 07-30,ENTRY_GATE 已关(ENTRY_GATE_ENABLED=False),无重复买入风险 |
八、速查
关键参数:PMS_AUTONOMY、PMS_OPEN_AUTONOMY(新,默认 full)、PMS_JUDGE_ACTIONS(默认 FILL,ADD,DCA,SWITCH,OPEN)、PMS_JUDGE_TIMEOUT=90、bionic 侧 PMS_JUDGE_TASK_TIMEOUT=75、PMS_OPEN_REF_DRIFT_MAX=0.03、PMS_JUDGE_TICK_BUDGET_SEC=150、PMS_OPEN_REQUIRE_WS_CASH=True、PMS_OPEN_SIGNAL_PRIORITY=True、PMS_PLAN_TOP_N=30、PMS_PLAN_TOP=300。
两道闸:规则闸(rule_gate.check,纯代码,所有指令都要过)→ 研判闸(judge.request → bionic POST /api/intraday/pms_judge,LLM,30–90 秒,只管自主提议,命令驱动不过)→ 自主档位路由(full / propose_only / off)。
择时:实现A = bionic POST /api/intraday/pms_exec(读昨夜支撑压力位推买卖区间,秒级);实现B = PMS 内置保守择时(exec_timing.decide)。
文档:DEVLOG.md(节点日志,最先读这个)、NEW_POSITION_ACTION_PLAN.md(新建仓方案 V3 + 八步判收)、BIONIC_PMS_INTERFACE.md(欠更新)、README.md。