tradingSystem/docs/下一阶段开发方案与规格书_2026-09-14.md

578 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 下一阶段开发方案与规格书2026-09-14
> 供拍板与实施。开发者可以是人,也可以是大模型。
> 写法遵守 `.claude/output-styles/readable-chinese.md`。
> 第一到第九节是正文,读完就知道做什么、为什么、怎么验证。
> 附录是实现细节,标了「可不读」。但开发者动手前必须读自己那个工作包的附录。
> 评审依据见《三源合议阶段评审_2026-09-14.md》。
---
## 一、这件事为最终目标买什么
最终目标是持仓管理系统在真实仓上全自动运行。分工不变:选股系统出候选,决策系统出研判与择时,持仓管理系统定做什么与多少,下游只管执行。
到今天,模拟仓上三源合议的整条链已经部署,但一个交易日都还没跑过。真实仓卡在下游 QMT 侧,等对方。所以这一阶段不是再加功能。这一阶段做四件事。一,把已经上线的纪律变成能量化复核的纪律。二,把方案里欠的那块补齐。三,把写好的功能按不互相干扰的顺序开起来。四,为真实仓准备好追平清单。
这一阶段买三样东西。
1. 复核的依据。没有读数就没有复核,没有复核就不能把这套东西部署到真实仓。
2. 技术面对入场时点的盘中判断。现在技术面那一票全是昨夜数据,方案第三节的盘中确认没落地。
3. 真实仓上线的安全前提。一份初始参数清单加一个自检脚本,保证追平部署不会把模拟仓的默认值带进真实账户。
## 二、原则
沿用方案的三条设计原则。一是入场靠投票,离场靠纪律。二是无读数等于弃权。三是研判闸不当选票。本阶段再加四条。
1. 先观察后调参。台账 006 到 011 的阈值不按复盘读数回调。要调,先回台账写一条。
2. 一次只开一个会互相喂的开关。观察窗口不重叠。
3. 每一处改动都守「开关关掉逐字回旧」,并先写这条单测再改。
4. 判收只认真机。开发机单测绿只是进门票。
## 三、做哪几件事
八个工作包,按建议的动工顺序排。前四个是代码。第五个只改参数。第六个在另一仓库。第七个等 QMT 侧。第八个是文档。
每个工作包的名字就是它做的事,不另起代号。
### 观察读数包(最先做)
**做什么。** 把每轮扫描里合议相关的判定落表,一天最多写四次。给一个复核脚本与一个日报小节,把台账要的四个读数直接打出来。
**为什么先做。** 台账 006 到 009 的复核日期是合议分流上线后满三个交易日,也就是 09-17。到那天没有读数就复核不了。后面所有调参与上真实仓的决定都没有依据。
**做哪几件。**
1. 新表 pms_consensus_stat。一天一票一类一行重复记到只加次数。
2. 动作引擎给合议相关的跳过项打上类别标签。只在开关开着时打,关掉时一个字都不多。
3. 新服务把一轮扫描的结果归类落表。只在四个检查点写,转空离场实弹随时写。试算不写。
4. 技术面映射重建时记下「相关票里没有读数的」和「覆盖只数」。
5. 复核脚本 `scripts/consensus_review.py`,外加 `make consensus-review` 目标。
6. 日报加「合议观察」小节。
细节见附录甲。
### 盘中确认包
**做什么。** 给技术面这一票加方案第三节写明的盘中确认,只用于入场。时段是 09:45 到 14:30。量比口径与解锁重问同源也就是台账 003 的时段折算量比。
**两条规则。**
1. 收口突破。相位是收口等待的候选,盘中现价站上昨日布林上轨,且时段折算量比不低于 1.5,当轮视为开口向上。重新合议后进候选。
2. 开口确认。相位是开口向上的候选,盘中要求现价不低于当日均价,且量比不低于 1.5。不满足就当轮进观察,处置词是「等盘中确认」。下一轮再看。
**一个要拍板的读法。** 开口向上的候选在 09:45 之前与 14:30 之后进观察,等确认时段。收口等待的候选在时段之外照旧观察。
**为什么做。** 技术面决定「什么时候投」。没有盘中那一道,它只能说昨天。
细节见附录乙。
### 页面收尾包
1. 单票研究面接口补齐基本面、择时、合议、来源四块。页面抽屉那一节改成「研究面 · 三源合议」四枚芯片。
2. 候选栏每行加质地芯片与技术芯片。
3. 管理视图持仓总览加研究面列。
细节见附录丙。
### 加固包
1. 转空去重集只在映射明确为多时清除。
2. 持仓行的择时票带上盘中转多留痕。
3. 登记 PMS_CONSENSUS_WEAK_CONFIRM 并接进合议路由。
4. 第二十四批用例改成相对当前时刻构造陈旧告警。
细节见附录丁。
### 分段启用包(只改参数,不改代码)
**现状。** 今天 09-14 是合议分流跑的第一个交易日。策略层总开关已经是开的。解锁重问从 09-10 起就开着。这三样都在跑。
**顺序。**
| 段 | 做什么 | 前提 | 观察多久 |
|---|---|---|---|
| 零,进行中 | 合议分流、增持门、转空离场、策略层两道离场、解锁重问都开着。不再开任何新开关 | 无 | 到 09-16 收盘,三个交易日 |
| 一 | 09-17 用复核脚本做台账 006 到 009 的第一次复核。同时复核解锁重问,台账 001 已满三天 | 观察读数包已部署 | 一次 |
| 二 | 决策系统的强势扫描开观察档,只记不派 | 第一段复核无异常。动决策系统要先答三题并经审批 | 两个交易日 |
| 三 | 强势扫描真派单 | 第二段读数正常 | 三个交易日 |
| 四 | 资金流分发半开 | 必须单独一段 | 两个交易日 |
| 五 | 资金流分发全开 | 第四段全绿,且当日兜底卖出恒为零 | 两个交易日 |
| 六,候选 | 模拟仓新建仓自主档从 propose_only 提到 full | 合议链路两轮复核无系统性偏差。要拍板 | 三个交易日 |
**策略层那件事。** 如果总开关是有意打开的,今天 09:40 那一跳就是 SAR 止损线刷新与弱基本面紧止盈挂载的第一次实弹。今天盘后要看那一跳的摘要,命令在第六节。如果不是有意的,今天就关掉,等合议观察期过了再单独开一段。
### 选股打分包(另一仓库,单独审批)
按方案第五节工作包四执行,不改设计。质地好加 8 分,差减 8 分,在同一传导档内重排,不跨档。环境变量设为零即关。台账记到选股系统第 058 条。细节见附录戊。
### 真实仓准备包(准备件现在做,执行等 QMT 侧)
1. 一份真实仓初始参数清单,写进台账。
2. 一个自检脚本 `scripts/real_init_params.py`,只读比对当前值与清单,有偏差就报。表名前缀不是 real_ 时拒绝执行。
3. 一份追平差异清单,列清 188 落后的表、调度位、参数。
细节见附录己与附录庚。
### 文档包
1. README 第 173 到 207 行关于影子模式的过时说法改掉。改成「下发模式由参数决定,页面顶部横幅为准」,并写清模拟仓与真实仓各自现在是什么模式。
2. CLAUDE.md 入库。
3. 方案文档第六节加一句标注。PMS_CONSENSUS_WEAK_CONFIRM 在加固包登记,三个盘中确认参数在盘中确认包登记。
4. 台账追加 012 盘中确认阈值、013 观察读数与复核口径、014 真实仓初始参数清单。
5. 开发节点记录按五段式追加。
6. 接口契约文档补单票研究面接口的返回结构。
## 四、顺序与时间
按交易日排。部署一律收盘后,先经审批,看容器内时间判盘中盘后。
| 交易日 | 做什么 |
|---|---|
| 09-14 到 09-16 | 合议链路第一轮观察。期间只做不改行为的活:观察读数包、加固包、文档包。观察读数包要重建容器,安排在 09-14 或 09-15 收盘后 |
| 09-17 | 用复核脚本做台账 006 到 009 与 001 的第一次复核。决定要不要调阈值,要调先回台账 |
| 09-17 收盘后 | 部署盘中确认包与页面收尾包 |
| 09-18 到 09-22 | 盘中确认观察三个交易日。同时启动分段启用包第二段 |
| 09-23 | 盘中确认第一次复核,台账 012 |
| 等审批 | 选股打分包 |
| 等 QMT 侧 | 真实仓准备包的执行部分 |
## 五、开关与参数
全部经参数中心读,页面可改即时生效。每个键都有真实读取处,否则死参数扫描会红。
| 键 | 默认 | 属于 | 说明 |
|---|---|---|---|
| PMS_CONSENSUS_STAT_TIMES | 0935,1030,1330,1445 | 观察读数包 | 落表的检查点,四位时刻用逗号分隔。设为空串即不写检查点行,只写转空实弹行 |
| PMS_TECH_INTRADAY_CONFIRM | True | 盘中确认包 | 盘中确认总闸。关掉两条规则都不走,行为逐字如旧 |
| PMS_TECH_INTRADAY_BREAKOUT | True | 盘中确认包 | 收口突破规则的开关。关掉只剩开口确认规则 |
| PMS_TECH_VOL_CONFIRM | 1.5 | 盘中确认包 | 时段折算量比阈值。与解锁重问的 PMS_OPEN_REASK_VOL_MIN 同值同义 |
| PMS_TECH_INTRADAY_WINDOW | 0945-1430 | 盘中确认包 | 确认时段。与解锁重问的时段同义 |
| PMS_CONSENSUS_WEAK_CONFIRM | True | 加固包 | 只有一方表态时交人。关掉则放行 |
## 六、验证方式
每条命令标明在哪台机器上运行。一个命令块只放一台机器的命令。
### 观察读数包
**开发机。** 预期最后一行 ALL SUITES PASS。第二十四批那条时钟用例在加固包修掉之前要在 09:36 之后跑。
```bash
cd /Users/baobao/Documents/work/project/tradingSystem && /private/tmp/claude-501/-Users-baobao-Documents-work-project-tradingSystem/f7c4a696-e3d8-4465-961a-04f82eb3e424/scratchpad/venv/bin/python scripts/run_tests.py
```
**模拟仓 155收盘后先经审批。** 预期 make test 最后一行 ALL SUITES PASS建表输出 21 张表,其中有 pms_consensus_stat。
```bash
cd /home/factor/project/tradingSystem && git pull --ff-only && make deploy && make test
```
**模拟仓 155下一个交易日 09:37 之后。** 预期打出当天的表:相关票数、无读数占比、等开口只数、跳过原因分布、增持门拦截次数、转空离场条数。第一天转空离场应为零。
```bash
cd /home/factor/project/tradingSystem && make consensus-review DAYS=1
```
### 盘中确认包
**模拟仓 155交易日 09:45 到 14:30 之间,只读试算。** 预期跳过项里出现处置词 wait_confirm或者出现「盘中收口突破」的候选。两种至少见到一种。若当天没有收口等待或开口向上的候选就看不到改天再看。
```bash
cd /home/factor/project/tradingSystem && docker compose run --rm --no-deps pms-web python -c "from app.services import proposal_service as p; import json; d=p.scan_and_route(dry_run=True); print(json.dumps([s for s in d.get('skipped',[]) if s.get('disp') in ('wait_confirm','wait_tech') or '盘中' in str(s.get('why'))], ensure_ascii=False)[:1500])"
```
**模拟仓 155任意时间。** 预期四个参数都在快照里,且带范围。
```bash
cd /home/factor/project/tradingSystem && docker exec pms-web python -c "from app.services import param_store as ps; print({k: ps.get(k, None) for k in ('PMS_TECH_INTRADAY_CONFIRM','PMS_TECH_INTRADAY_BREAKOUT','PMS_TECH_VOL_CONFIRM','PMS_TECH_INTRADAY_WINDOW')})"
```
### 页面收尾包
**开发机。** 预期两道页面守卫都打 ALL OK。
```bash
cd /Users/baobao/Documents/work/project/tradingSystem && python3 scripts/test_page_wiring_guard.py && python3 scripts/test_page_enum_guard.py
```
**页面判收,模拟仓 155 部署后。** 点任一持仓,抽屉第一节标题是「研究面 · 三源合议」,有基本面、技术面、择时、合议四枚芯片。候选栏每行有质地与技术两枚芯片。管理视图持仓总览多一列研究面。
### 加固包
**开发机。** 预期第三十批与第二十八批新增用例全部通过,且第二十四批在任何时刻跑都通过。
```bash
cd /Users/baobao/Documents/work/project/tradingSystem && /private/tmp/claude-501/-Users-baobao-Documents-work-project-tradingSystem/f7c4a696-e3d8-4465-961a-04f82eb3e424/scratchpad/venv/bin/python scripts/test_batch30_units.py && /private/tmp/claude-501/-Users-baobao-Documents-work-project-tradingSystem/f7c4a696-e3d8-4465-961a-04f82eb3e424/scratchpad/venv/bin/python scripts/test_batch28_units.py && /private/tmp/claude-501/-Users-baobao-Documents-work-project-tradingSystem/f7c4a696-e3d8-4465-961a-04f82eb3e424/scratchpad/venv/bin/python scripts/test_batch24_units.py
```
### 分段启用包
**模拟仓 155今天 09:40 之后,看策略层那一跳。** 预期摘要里的时刻是今天 09:4x没有 error 字样。若策略层是有意打开的,这就是第一次实弹的读数。
```bash
cd /home/factor/project/tradingSystem && docker exec pms-web python -c "from app.services import param_store as ps; print((ps.get('PMS_AUTO_LAST_SCAN','') or '')[:1200])"
```
**模拟仓 155任意时间解锁重问的三天读数。** 预期打印当日被驳回的票数与逐只解锁判定。每天解锁一到五次是正常,零次说明太紧,超过八次说明太松。
```bash
cd /home/factor/project/tradingSystem && docker compose run --rm --no-deps pms-web python -c "from datetime import datetime; from app.services import proposal_service as ps, reask_service as rs; jk = ps._judge_rejected_open_keys(); print('当日被研判驳回:', len(jk), '只'); print('解锁:', rs.evaluate_all(jk, datetime.now()) or '(无)')"
```
### 选股打分包
**模拟仓 155改之前先记基线。** 预期打印主榜前五十名里质地好的只数。今天的基线是前一百名里六只。
```bash
curl -s "http://192.168.16.155:8300/plan?top=50" | python3 -c "import sys,json; d=json.load(sys.stdin); rows=d.get('main') or []; print('前50质地好:', sum(1 for r in rows if (r.get('company_review') or {}).get('overall')=='好'), '/', len(rows))"
```
**模拟仓 155重启桥容器后避开 07:10先经审批。** 预期同一条命令的读数上升,且每一行的 rank 连续。
### 真实仓准备包
**真实仓 188只读现在就能做。** 预期打印 51bd6dc 附近的提交与两个容器。这一步只是确认起点,不动任何东西。
```bash
cd /mnt/work/project/tradingSystem && git log -1 --format='%h %ad %s' --date=iso && docker ps --format '{{.Names}}\t{{.Status}}' | grep pms
```
**真实仓 188追平部署之后先经审批。** 预期打印表名前缀 real_ 与一张对照表,每一行都是「符合」。任何一行「偏差」都不许进阶段 B。
```bash
cd /mnt/work/project/tradingSystem && docker compose run --rm --no-deps pms-web python scripts/real_init_params.py --check
```
## 七、回退
每个工作包独立回退,互不牵连。
| 工作包 | 回退方式 | 要不要重启 |
|---|---|---|
| 观察读数包 | 页面把 PMS_CONSENSUS_STAT_TIMES 设为空串。要彻底撤,回滚提交再部署。表留着不删 | 改参数不用;回滚要重建容器 |
| 盘中确认包 | 页面把 PMS_TECH_INTRADAY_CONFIRM 设为关,行为逐字回旧 | 不用 |
| 页面收尾包 | 回滚提交再部署 | 要重建容器 |
| 加固包 | PMS_CONSENSUS_WEAK_CONFIRM 默认开就是旧行为。其余三处回滚提交 | 回滚要重建容器 |
| 分段启用包 | 每一段把对应开关改回去。决策系统侧的开关改环境文件后重建那一个容器 | 持仓管理系统侧不用 |
| 选股打分包 | 环境变量把加分设为零,或回滚提交,重启桥容器 | 要重启桥容器 |
| 真实仓准备包 | 自检脚本只读,无需回退 | 不用 |
## 八、拍板点
这八条要用户拍板,拍板前对应的活不动。
1. 策略层总开关现在是开的,是不是有意的。若不是,今天就关。
2. 盘中确认里,开口向上的候选在 09:45 之前与 14:30 之后进观察。这个读法认不认。
3. 策略票的网格买入腿,技术面看空时要不要也停。方案没写,现在不停。
4. 选股打分包动 akg-factor-bridge 仓库,批不批。
5. README 影子模式的过时说法按文档包第 1 条改,认不认。
6. 检查点默认四个时刻,认不认。多了写库多,少了读数粗。
7. 观察读数表用新表而不是运行参数承载。新表要改 DDL 表数哨兵。认不认。
8. 分段启用包第六段,新建仓自主档提到 full 的时机,等两轮复核后再议。
## 九、交付要求
给开发者的硬要求,人和大模型一样。
1. 每个工作包一个提交。提交信息用短中文说行为,带台账号。
2. 先写「开关关掉逐字回旧」的单测,再改代码。开关关掉时,输出的字典要用 JSON 序列化后逐字节相等。
3. 新批次同时登记进 `scripts/run_tests.py` 的 SUITES 清单与例数表。哨兵按附录辛逐条过一遍。
4. 开发机全量绿之后,才在模拟仓 155 收盘后部署。部署要重建容器,先经审批。判收命令在第六节,判收读数记进开发节点记录的五段式节点。
5. 不动真实仓 188。真实仓准备包的执行部分等 QMT 侧就绪后另开一轮。
6. 服务器上只做 git pull不跑 git stash。
7. 判盘中盘后看容器内时间,不看宿主时间。宿主是世界协调时。
8. 业务参数一律经参数中心读。密钥只从 .env 注入。
9. 一条 SQL 只碰一张表。要联的数据在服务层分两次查再在内存里拼。
---
## 附录甲(可不读):观察读数包的表、标签与落表规则
### 表
新表名 pms_consensus_stat加进 `ddl_pms_v1.sql`,是第 21 张表。
```sql
CREATE TABLE IF NOT EXISTS pms_consensus_stat (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
stat_date INT NOT NULL, -- 北京日期 yyyymmdd
ts_code VARCHAR(16) NOT NULL, -- 代码; 全局行用 *
kind VARCHAR(24) NOT NULL, -- 类别, 见下表
reason VARCHAR(255) NULL, -- 一句原因, 取跳过原因原文截断
detail TEXT NULL, -- JSON: 三票 / 方向 / 强弱 / 相位 / 路由 / 盘中确认
first_at DATETIME NOT NULL, -- 北京时间, 首次记到
last_at DATETIME NOT NULL, -- 北京时间, 最近记到
rounds INT NOT NULL DEFAULT 1, -- 记到的次数
UNIQUE KEY uk_day_code_kind (stat_date, ts_code, kind),
KEY idx_day_kind (stat_date, kind)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 类别
| kind | 含义 | 来源 |
|---|---|---|
| open_skip_fund | 新建仓因没有买方评析跳过 | 合议路由为跳过,原因是没有买方评析 |
| open_skip_bear | 新建仓因方向看空跳过 | 合议路由为跳过,其余原因 |
| open_wait_tech | 等技术面开口或转向 | 合议路由为观察 |
| open_wait_confirm | 等盘中确认 | 盘中确认包 |
| open_breakout | 盘中收口突破视为开口 | 盘中确认包 |
| open_confirm | 合议交人 | 合议路由为交人 |
| open_pass | 合议放行 | 合议路由为放行 |
| gate_block | 增持门拦下 | 持仓扫描的跳过项detail 里记 fill、add、dca 三者之一 |
| tech_exit | 转空离场实弹,执行或入队 | 扫描后真处理过的集合 |
| tech_noread | 相关票没有技术面读数 | 映射重建时相关票减去有状态的票 |
| fund_noread | 基本面无读数 | 装配结果 |
| timing_noread | 择时无读数 | 装配结果 |
| map_cover | 映射覆盖只数ts_code 为 * | 映射重建时detail 记 codes 与 states 两个数 |
### 打标签
`app/core/action_engine.py` 里,合议分流与增持门产生的跳过项加一个 tag 键,值就是上表的 kind。只在 consensus_on 或 cblocks 为真的分支里加。开关关掉时这些分支一行不执行,所以 tag 键不会出现,逐字回旧成立。
增持门的跳过项 detail 里带 gate_kind取值 fill、add、dca。
### 装配时留一份紧凑记录
`proposal_service._attach_consensus` 每装配一只候选,往 out["consensus_seen"] 追加一条紧凑记录ts_code、fund、tech、timing、direction、route、phase。这份记录给落表用也给候选处置快照用。
### 落表
新服务 `app/services/consensus_stats.py`,一个入口函数 record_round(out, scanned, params, now)。
1. 从 out["consensus_seen"] 生成 open_* 三类无读数行与 open_pass、open_confirm 行。
2. 从 out["skipped"] 里带 tag 的项生成 open_skip_*、open_wait_*、gate_block 行。
3. 从 scanned["candidates"] 里来源是 tech_exit 且没被闸拒的项生成 tech_exit 行。
4. 检查点判断now 的时分在 PMS_CONSENSUS_STAT_TIMES 任一时刻或它的下一分钟之内才写第 1、2 类。tech_exit 行任何时候都写。dry_run 一律不写。
5. 写失败只记警告,返回 ok 为假,不影响扫描。这个函数登记进第十批 SOFT_FAIL 名单。
调用点在 `proposal_service.scan_and_route` 末尾,去重集写回之后。
`tech_service.build_map` 在写映射之后,写 tech_noread 行与 map_cover 行。失败只记日志。
### 仓库
新文件 `app/repo/consensus_stat_repo.py`,三个函数,每个只碰这一张表。
1. upsert_many(rows)。用 INSERT 加 ON DUPLICATE KEY UPDATE。更新子句用 VALUES(列) 引用插入值rounds 写成 rounds 加一。绝不在更新子句里放绑定参数,那是 09-11 真机踩过的坑。
2. list_range(date_from, date_to, kinds=None)。
3. count_by_kind(date_from, date_to)。返回按日期与类别的计数字典。
### 复核脚本
`scripts/consensus_review.py --days N`,默认 3。打印四张表。
1. 逐日:相关票数、技术面无读数占比、基本面无读数只数、择时无读数只数。占比用 map_cover 行算。
2. 逐日:等开口只数、等盘中确认只数、跳过原因分布、交人只数、放行只数、增持门拦截次数。
3. 转空离场逐条:日期、代码、确认与否、数量。
4. 合议方向与人工裁决的比对:从提议表取这几天带合议六键且已被人裁决的提议。合议看多而人驳回,或合议交人而人采纳,逐只列出。终态的名字用提议服务里现有的枚举,不另造。
Makefile 加目标 consensus-review接受 DAYS 变量,默认 3。
### 日报
`ledger_service.build_daily_report` 加一节 consensus内容是当天按类别的计数。取不到就写空不拖垮日报。
## 附录乙(可不读):盘中确认包的判定函数与接线位置
### 纯函数
加在 `app/core/tech_rules.py`
```python
def intraday_confirm(state, *, price, vwap, upper_prev, vol_ratio, now,
window="0945-1430", vol_min=1.5, breakout_on=True) -> dict:
"""返回 {"state": 新技术面块或原块, "changed": bool,
"kind": None | "breakout" | "opened_ok" | "opened_wait" | "outside_window",
"why": str, "reads": {"price", "vwap", "upper_prev", "vol_ratio", "at"}}"""
```
判定次序如下。
1. 相位不是收口等待也不是开口向上原样返回kind 为空。
2. 不在时段内。相位是开口向上,返回 outside_window。相位是收口等待原样返回。
3. 相位是收口等待。breakout_on 为真,且 price、upper_prev、vol_ratio 三个都有值,且 price 大于 upper_prev且 vol_ratio 不低于 vol_min返回 breakout。新块的立场是看多强弱是强相位是「盘中开口向上」。任何一项不满足原样返回。
4. 相位是开口向上。price、vwap、vol_ratio 三个都有值,且 price 不低于 vwap且 vol_ratio 不低于 vol_min返回 opened_ok块不变。任何一项取不到或不满足返回 opened_wait。取不到按等待处理而不是放行因为这是入场的门方向要保守。
时段判断复用 `app/core/reask_rules.py` 的 in_window。量比由调用方算用 reask_rules.vol_ratio。单测要钉住是同一个函数对象这是台账 003 三处同源的哨兵。
### 映射多带一个值
`tech_rules.synthesize` 的 base 加 boll_upper。`tech_service._compact` 加 boll_upper。收口突破要拿昨日上轨从映射里取不再回库。
### 接线
`proposal_service._attach_consensus` 里,每只候选装配完四块之后加一段。开关 PMS_TECH_INTRADAY_CONFIRM 关掉时整段不执行。
1. 相位不在收口等待与开口向上之内,跳过。
2. 取读数price 与 vwap 来自 market.day_snapshotvol_ratio 用与 reask_service 相同的算法upper_prev 来自技术面块的 boll_upper。本轮用一个字典缓存同一只票不取两次。任何取数失败按取不到传 None。
3. 调 intraday_confirm。
4. 结果是 breakout把新块写回 blocks["tech"],用新立场重新调 consensus.decide更新 blocks["consensus"]、c["consensus"]、硬数字六键。硬数字的 tech 块里加 intraday 一键记 reads 与 kind。
5. 结果是 opened_wait 或 outside_window把 c["consensus"]["route"] 改成观察route_reason 写 why另加 disp 键为 wait_confirm。
6. 结果是 opened_ok只在硬数字的 tech 块里记 intraday。
`_scan_open``_attach_consensus` 都要多接一个 now 参数,从 scan_and_route 传下来。
### 处置词
`action_engine` 加常量 DISP_WAIT_CONFIRM 为 wait_confirm。scan_open 里路由为观察时con 带 disp 就用它,否则用 wait_tech。
页面 dispOf 加一行wait_confirm 显示「等盘中确认」,样式与在盯那一档相同。页面文案守卫若登记了处置词枚举,补这一项。
### 参数登记
四个参数登记进 param_store 的 RUNTIME_EXTRA 与范围表。PMS_TECH_VOL_CONFIRM 范围 0.5 到 10。PMS_TECH_INTRADAY_WINDOW 的校验照 PMS_OPEN_REASK_WINDOW 的写法。
### 观察读数
open_breakout 每天零到三只。open_wait_confirm 每天零到十只。突破超过五只说明太松。这两条写进台账 012。
## 附录丙(可不读):页面收尾包的接口字段
### 单票研究面接口
`GET /api/research/{ts_code}` 的返回结构改成六块。
| 键 | 内容 | 来源 |
|---|---|---|
| company | 质地档、估值、十视角计数、三类、硬疑点、报告日龄、报告链接、评析摘要 | 持仓票从逻辑状态映射取 company_review。候选票从当日计划的主榜与观察档取。都没有就是空 |
| fund | fund_rules 的结果块 | 用 company 算 |
| tech | 现有的技术面块 | 不变 |
| timing | 立场、昨夜定性、结论日期、盘中转多时刻 | consensus_service.nightly_map 取一只。转多时刻点击时不回扫,留空 |
| consensus | consensus.decide 的结果 | 用上面三票算 |
| sources | 每一路的状态ok、无读数、或错误文字 | 逐路标 |
页面单票抽屉那一节标题改成「研究面 · 三源合议」。四枚芯片依次是基本面、技术面、择时、合议。每枚芯片悬停显示一句理由。芯片下面保留现有的三个指标块。有报告链接就显示「评析报告」。
### 候选栏
候选处置快照的每行加三小块fund 带立场与质地档tech 带立场与相位consensus 带方向与路由。数据从 out["consensus_seen"] 来。页面每行加两枚芯片,颜色沿用 techStanceCls 与 propCompanyTag。
### 管理视图持仓总览
加一列研究面,内容与我的持仓那一列相同,用同一个渲染函数。
## 附录丁(可不读):加固包的改动点
### 去重集清除条件
`app/services/proposal_service.py` 第 150 到 154 行把「SAR 方向是空才保留」改成「SAR 方向明确是多才清除」。
```python
params["tech_exit_done"] = {c for c in _done
if (_tech_states.get(c) or {}).get("sar_side") != "多"}
```
第三十批加三例。映射里没有这只票则保留。明确为多则清除。明确为空则保留。
### 持仓行的转多留痕
decorate_positions 的 flip_map 由调用方传入。来源与候选相同,就是信号消化写在候选行上的当日转多时刻。持仓行没有这个字段时,按持仓代码从同一来源取。第二十八批加一例:持仓行昨夜中性、当日转多,择时票升为看多。
### 弱表态开关
consensus.decide 加参数 weak_confirm默认真。_route 里「只有一方表态」那一行weak_confirm 为真返回交人为假返回放行。consensus_service._params 读 PMS_CONSENSUS_WEAK_CONFIRM 并传入。第二十八批加两例:开着交人,关着放行。
### 第二十四批用例
`_today_ms(9, 35)` 改成「当前时刻减十分钟」。断言里的时刻字符串从那个时间戳算,不写死 09:35。
## 附录戊(可不读):选股打分包的规格
仓库是 akg-factor-bridge文件是 `plan.py`
1. 装配阶段已经读到评析字典。对主榜与观察档的每一行算质地调整分:质地好加 8差减 8其余 0。
2. 分数编码是主榜等于 200 加传导档位乘 20 加组内分,组内分夹在正负 9.9 之间。加 8 后最大 17.9,仍小于档步长 20先档后分的次序不破。
3. 主榜与观察档按调整分重排并重编名次。原分数保留在 score 字段供档位解码。新字段 score_adj 进接口与快照。
4. 不动因子表。不在每早 07:10 的因子构建里读数据基座库。判决收敛仍只降不升。
5. 环境变量 PLAN_QUALITY_BONUS默认 8设为 0 即关。
6. 新测试文件 test_plan_quality_rank.py守四条不变式。加分从不跨档。加分为 0 时次序与原来逐字相同。重编后名次连续。快照带 score_adj。
7. 台账记到选股系统第 058 条。
8. 部署代码与自测本地做完并提交。155 上拉代码后重启桥容器,先经审批,避开 07:10。
顺带守一条既有不变式POOL_TOP 不低于 PMS_PLAN_TOP_N。决策系统的夜间分析池从这份排名取前 50质地进了排序好公司才进得了分析池择时那一票的覆盖才会上来。
## 附录己(可不读):真实仓初始参数清单与自检脚本
### 清单
进阶段 B 之前必须是这些值。写进台账 014。
| 键 | 值 | 为什么 |
|---|---|---|
| PMS_DISPATCH_MODE | shadow | 影子期先不写下游 |
| PMS_AUTONOMY | propose_only | 持仓自主动作交人 |
| PMS_OPEN_AUTONOMY | off | 新建仓关 |
| PMS_TECH_EXIT_AUTONOMY | propose_only | 转空离场交人,不自动卖 |
| PMS_STRATEGY_ENABLED | false | 策略层关 |
| PMS_LOGIC_DOUBT_TRIM | false | 研究走弱减持关 |
| PMS_OPEN_REASK_ENABLED | false | 新建仓关着时无意义,明确关掉免误读 |
| PMS_CONSENSUS_ROUTE | true | 合议只拦不放,开着更保守 |
| PMS_TECH_GATE_INCREASE | true | 增持门只拦不放 |
| PMS_PLAN_RANK_BY_QUALITY | true | 排序无副作用 |
| PMS_TECH_ENABLED | true | 前提是接口根地址指向 188 的决策系统 |
| PMS_FUND_REQUIRED | true | 无评析不建仓 |
| PMS_TOTAL_SCALE | 按真实资金 | 与账户实际资金要对得上 |
### 脚本
`scripts/real_init_params.py`
1. --check 只读。打印表名前缀,再打印一张对照表:键、期望值、当前值、符合或偏差。有偏差退出码为 1。
2. --apply 写入,必须同时带 --yes。写之前再打印一遍对照表。
3. 表名前缀不是 real_ 时拒绝执行,除非带 --allow-sim。这是防止在模拟仓上误跑。
4. Makefile 加目标 real-params-check。
单测三例。对照表算对。前缀为空时拒绝。有偏差时退出码为 1。
## 附录庚(可不读):真实仓 188 追平差异清单
按开发机上 51bd6dc 到 969d189 的差异统计。
| 项目 | 差异 |
|---|---|
| 提交 | 落后 69 个 |
| 表 | 多两张pms_nav_daily、pms_tech_daily。观察读数包之后再多一张 pms_consensus_stat |
| 调度位 | 多两个06:30 tech_pull、15:20 nav_snapshot。188 阶段 A 不起调度器,暂不生效 |
| 参数 | 多四十多个键。默认值按模拟仓定,见附录己的清单 |
| 页面 | 登录与两角色不变。提议卡重构、研究面、合议行都是新的 |
| 接口 | 多技术面状态、手动拉取、单票研究面、按代码回扫信号四个 |
追平步骤,全部先经审批。
1. 按真实仓部署方案阶段 A 把 ws 协议判收完。
2. 在 188 拉代码到最新。
3. 用 ws 剖面重建容器,建表自动带 real_ 前缀。输出必须出现「表名前缀 real_ 生效」。
4. 跑 real_init_params.py --check全部符合才继续。
5. 按真实仓部署方案阶段 B 进影子期。
## 附录辛(可不读):哨兵同步与登记清单
改了对应的东西就得回到这里改断言,断言不动就是漏了。
| 哨兵 | 位置 | 本阶段要改什么 |
|---|---|---|
| DDL 表数 | scripts/test_batch6_units.py 约第 593 行 | 20 改 21 |
| 批次登记 | scripts/run_tests.py 的 SUITES 与例数表 | 加第三十一、三十二、三十三批,改总数 |
| 软失败函数 | scripts/test_batch10_units.py 顶部 SOFT_FAIL | 加 consensus_stats.record_round |
| 死参数名单 | scripts/test_batch10_units.py 的 KNOWN_DEAD | 不变。六个新参数都要有读取处 |
| 桩签名比对 | scripts/test_batch10_units.py 用例 M1 | 不改 pms_repo 签名就不用动。新仓库是独立文件 |
| 路由清单 | scripts/test_wiring.py 的 need 列表 | 不加新路由就不动 |
| 页面枚举名单 | scripts/test_page_enum_guard.py 的 ENUM_FIELDS | 处置词若在名单里,加 wait_confirm |
| 动作求值器次序 | scripts/test_batch12_units.py | 不变 |
| 密钥名单 | 两处 | 不变 |
新批次与例数估计。
| 批次 | 内容 | 例数 |
|---|---|---|
| 第三十一批 | 观察读数包标签只在开关开着时出现四种路由各打对应标签增持门三种拦截打标签归类落表检查点窗口转空实弹随时写试算不写upsert 用 VALUES 列;单表;映射重建记无读数与覆盖;复核脚本聚合;合议与人工裁决比对;参数登记与校验;日报小节失败不拖垮 | 约 14 |
| 第三十二批 | 盘中确认包:时段边界四点;收口突破要价与量同时满足;开口确认要均价与量;取不到按等待;突破开关关掉不升;总闸关掉时候选的合议块 JSON 逐字相同;接线后路由从观察变放行;开口未确认进观察带处置词;硬数字带 intraday量比同源哨兵映射带上轨参数登记与范围 | 约 16 |
| 第三十三批 | 页面收尾包:研究面接口持仓票、候选票、都没有三情形;来源逐路标明;处置快照带三小块;页面守卫 | 约 6 |
| 第三十批加 | 去重集三例 | 3 |
| 第二十八批加 | 转多留痕一例、弱表态开关两例 | 3 |
| 第二十四批改 | 时钟用例改相对时刻 | 0 |
合计新增约四十二例,总数约 862。以实跑为准例数表按实跑校正。