tradingSystem/README.md

146 lines
13 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.

# tradingSystem — 综合交易系统PMS 持仓管理)
命令驱动的持仓管理系统:**用户通过管理页面下达大方向命令**(总规模/仓位上限/升降仓/对某股做T**持仓系统制订分股分批方案并管理账本**(批次、摊薄成本、安全垫、纪律)→ **决策系统负责研判与择时**(其形态计算、每日定时分析等核心功能照旧运行)→ **下游系统QMT 侧)挂单成交**
架构要点:持仓系统 ↔ 决策系统直接交互;持仓系统 ↔ 下游系统交互;**决策系统与下游断开**——对下游的管理权限(建仓审批、卖出指挥)由决策系统移交持仓系统,其全部分析产出保留并成为持仓系统的输入。上游量化系统输出不变,持仓系统的建仓计划围绕上游输出建立。
仓位框架:百分比制(规模 200 万 / 总仓 ≤60% / 单股 ≤8% / ≤15 只,均为用户参数命令、页面可调),单股分批 50/25/25含一手可行性检查行业集中度硬性拦截划分依据留接口。决策方式规则引擎为主定性研判委托决策系统持仓系统不自建研判栈。安全垫三义分批建仓留缓冲、浮盈垫后加仓、做T降成本命令授权制
## 文档与交付物
| 文件 | 内容 |
|---|---|
| `POSITION_MGMT_DESIGN.md` | 总体设计 **V0.4(定稿,开发启动)**:命令系统与管理页面/账本/仓位框架/动作引擎/两道关口/择时执行/下游通道。功能一次性开发,上线按依赖分三步切换 |
| `QMT_INTERFACE_REQUIREMENTS.md` | 与 QMT 侧下游系统协商用的数据与接口需求清单(含资金快照、统一指令通道建议 DDL按编号答复回填 |
| `ddl_pms_v1.sql` | PMS 全部自有表建表语句153 代理侧10 张) |
| `config/settings.py` | 配置(基础设施键名对齐 bionic业务参数为初值页面调参持久化到 `pms_runtime_param` 后优先) |
## 模块地图
```
app/
core/ 纯逻辑, 零外部依赖, 可单测 —— 系统的算数与纪律都在这里
sizer.py 批次拆分与一手合并 / 组合约束 / 风险敞口披露
cushion.py 摊薄成本 / 安全垫状态机 / 保垫触发 / 卖出核销次序
command_spec.py 命令目录(A/B/C 全量 27 类) / 参数校验 / 双状态机 / 冲突识别
planner.py 方案生成器: 降仓凑额四档 / 升仓 / 建仓 / 清仓 / 行业 / 撤单
recon.py 成交认领与入账映射 / 对账差异与修正 / 除权检测 / T+1 可用量
rule_gate.py 规则闸终检: 上限/一手/可卖/冻结/刹车/行业/不追高 (减持只放行不阻拦)
exec_timing.py 择时实现B: 分日配额 / 分笔 / 买卖出手判定 / 14:45 兜底 / 窗口收口
action_engine.py 动作引擎: FILL 回踩补足 / ADD 盈利加仓 / DCA 补仓 / TRIM 保垫减仓
tradedays.py 交易日历: 调度守卫与执行窗口计算
db/session.py 三库连接 + **严格单表访问守卫** (JOIN/逗号连表/跨表子查询一律拒绝)
repo/ 单表数据访问: pms_repo (自有 10 表) / downstream_repo (下游只读三表)
services/ 编排层
param_store.py 运行参数中心 (表值优先于 settings 初值, 页面调参即时生效)
portfolio.py 组合快照 (账本+行情+行业 → 方案/规则闸/页面的统一输入)
command_service.py 命令下达→校验→冲突→生效/规划→进度推进→撤销
executor.py 方案→指令→分日出手→窗口收口 (规则闸与择时的编排落点)
dispatcher.py 下发通道三适配器: shadow(默认) / plan_x / channel_y
proposal_service.py 自主提议: 扫描→规则闸→研判闸→按自主档位分流 (执行/入队)
judge.py 研判闸客户端 (决策系统未接通时自动降级为人工确认)
ledger_service.py 成交回放 / 对账 / 除权 / 盘前 / 日终结算 / 运营日报
market.py 行情 (Redis db13) 与参考位 (决策系统主口径 + 兜底自算)
industry.py 行业划分可插拔适配器 (custom_table / gp_stock_category / 停用)
web/ FastAPI + 单页 (Vue3 + ElementPlus),页面四块 + 运维/日报抽屉
scheduler.py Celery beat 调度总表 (设计 §10 八个调度位 + 三条守卫)
scripts/
run_tests.py 一次跑完全部单测 (见下方「Docker 部署」)
test_core_units.py 仓位与安全垫核心逻辑 14 例
test_batch2_units.py 命令 / 方案 / 回放对账 纯逻辑 35 例
test_batch3_units.py 规则闸 / 择时执行器实现B 纯逻辑 18 例
test_batch4_units.py 动作引擎 四类自主动作触发与数量口径 11 例
test_wiring.py 装配自检: 服务层→核心→落表 全链路 (内存桩) 30 例
init_db.py 建表 (应用 ddl_pms_v1.sql, 幂等, 默认演练)
check_db.py 实机连通性与表结构自检 (需真实 .env)
```
## 三条铁律
1. **命令至上**:自动决策不得突破用户命令参数;冲突时命令优先;命令间冲突由用户裁决。
2. **分工不越权**:持仓系统管「做什么、多少」,决策系统管「该不该、何时」,下游只管执行;研判不可用时降级为保守规则 + 人工确认,不自建第二套研判。
3. **先记账后动作 + 故障即守成**:指令先落表再下发;故障不产生新指令;账本与下游定期对账,以下游为实际持仓事实源。
## Docker 部署(项目统一以容器方式构建运行)
服务共用一个镜像:`pms-web`(管理页面,端口 38100+ `pms-beat` / `pms-worker`Celery 调度与执行,挂在 `sched` profile 下)。
```bash
# 服务器首次部署
git clone <仓库地址> && cd tradingSystem
cp .env.example .env && vim .env # 填入真实连接串 (.env 不入库)
docker compose build # 默认走清华 PyPI 镜像; 可 --build-arg PIP_INDEX_URL=... 覆盖
# 构建验证 (不连库, 秒级): 应输出 ALL SUITES PASS
docker compose run --rm pms-web python scripts/run_tests.py
# 建表 (幂等; 不加 --yes 只演练打印)
docker compose run --rm pms-web python scripts/init_db.py --yes
# 实机自检 (连库, 需 .env): 库连通 + pms_* 十表 + 下游表完整列定义 + 行情 Redis
docker compose run --rm pms-web python scripts/check_db.py
docker compose up -d # 管理页面
curl http://127.0.0.1:38100/health # 健康检查 + 配置装载自证 + 库连通自证
# 浏览器打开 http://<服务器IP>:38100/ → 参数设置 / 命令台 / 持仓与账本 / 提议确认
docker compose --profile sched up -d # 启用调度器 (beat + worker)
docker compose logs -f pms-beat pms-worker
# 日常更新
git pull && docker compose build && docker compose up -d
```
基础镜像 `python:3.11-slim` 拉取慢时,先给服务器 Docker 配置 registry 镜像加速。日志落 `./logs`(已挂载卷);容器时区 Asia/Shanghai。管理页面的前端资源Vue3 / ElementPlus / axios走 unpkg CDN浏览器需能访问外网若内网隔离把页面头部三行 `<script>/<link>` 换成本地文件即可(页面本身无构建步骤)。
**依赖版本坑**`redis` 必须锁在 5.x。redis-py 6.x 默认按 RESP3 握手(先发 `HELLO 3`),而 208/150 两台 Redis 是 6.0 以前的版本,会回 `unknown command HELLO`,行情与 Celery 总线一起断。`requirements.txt` 已锁版本,代码侧另有 `protocol=2` 双保险;升级依赖时别把这条放开。
## 调度总表(`--profile sched` 生效,设计 §10
| 调度 | 时间 | 任务 | 本批状态 |
|---|---|---|---|
| 盘前准备 | 交易日 08:50 | T+1 可卖重置 / 参考位取数 / 刹车结算 | ✅ |
| 命令轮询 | 每 1 分钟(全天) | 新命令解析 → 方案生成 → 状态机推进 | ✅ |
| 成交回放 | 交易时段每 5 分钟 | `trading_order` 增量回放 + 盘中轻对账 | ✅ |
| 盘中执行 | 交易时段每 1 分钟 | 方案转指令 → 自主提议扫描 → 择时出手(规则闸终检 → 下发 → 记子单) | ✅ |
| 信号消化 | 交易时段每 1 分钟 | 订阅决策系统盘中信号 | 🔜 下一批 |
| T 仓平回 | 14:50 | 做T强制平回 | 🔜 二期(现只自证 T 仓为 0 |
| 日终结算 | 15:10 | 除权检测 / 全量对账 / 安全垫 / 命令进度日结 | ✅ |
| 运营日报 | 15:30 | 关注区 + 全量统计(页面「日报」按钮可查) | ✅ |
调度器三条守卫:交易日守卫、故障即守成(任务内异常吞掉记 ERROR绝不因调度异常产生新指令、全局暂停执行休假模式下除对账与日报外全部跳过
## 指令下发通道(设计 §9参数 `PMS_DISPATCH_MODE`,默认 `shadow`
| 模式 | 行为 | 什么时候用 |
|---|---|---|
| `shadow`(默认) | 指令照常过规则闸、照常置 DISPATCHED但**不写下游**。你在 QMT 侧人工执行,成交由回放按 FIFO 认领回账本 | 通道协商完成前的一期口径(设计 §9命令类降仓/清仓由用户人工执行、PMS 记账跟踪) |
| `plan_x` | 买入写 `trading_buy_plan``is_active=6` 待挂单、署名 `approved_by='pms'`**卖出无对应通道,自动退回影子** | QMT 侧确认沿用旧通道过渡时 |
| `channel_y` | 写统一指令表 `pms_order_request`DDL 见需求清单 B1 | B1 协商落地、表建好之后 |
影子模式下的完整闭环:页面下命令 → 方案落表 → 方案转指令 → 择时按日配额给出「今天该出多少、什么价」→ 你照着在 QMT 下单 → 5 分钟一次的回放把成交认领回批次账本 → 命令进度自动推进。整条链路除了「人手下单」这一步,其余与实盘接管后完全一致。
## 自主提议的分流(设计 §6 / §7
动作引擎每分钟扫一遍持仓,产出 FILL / ADD / DCA / TRIM 四类候选,然后依次过三道:
1. **规则闸**(一级,纯代码)——不过就拒,未通过项落评审账本。自主动作受组合刹车约束(命令驱动不受)。
2. **研判闸**(二级,仅补足/加仓/补仓,委托决策系统)——`PMS_JUDGE_API_BASE` 为空即视为未接通,按设计**自动降级为人工确认**并记 ERROR绝不把「研判拿不到」当成「研判通过」。
3. **按自主档位分流**——`full` 执行、`propose_only` 入队(一期默认)、`off` 不扫描。
两条无条件覆盖档位的规矩:**减持方向不设确认门槛**TRIM 保垫减仓任何档位都直接落指令);**15% 及更深的补仓永远需用户确认**(即便档位是 full 也强制入队)。同一只票的同一动作若已有在途提议或在途指令,不重复提。
## 已实现 / 待开发
**已实现**:建表 DDL 与建表脚本配置与运行参数中心仓位规划器与安全垫账命令系统27 类命令全目录 + 双状态机 + 冲突识别);方案生成器(降仓凑额四档、升仓、建仓分批、清仓/减至、行业清仓与限额、暂停买入撤单);账本回放与对账引擎(成交认领、外部成交并入 BASE 告警、以下游为准修正、除权检测、T+1 可用量、连续不一致升级);规则闸终检;择时执行器实现 B分日配额、分笔、VWAP/回踩/不追高、14:45 兜底、停牌一字板顺延、窗口耗尽收口);三模式下发通道;**动作引擎四类自主动作 + 研判闸客户端 + 提议分流**;管理页面四块 + 运维/日报抽屉;调度器八个调度位;单测 108 例。
**待开发(下一批)**:决策系统盘中信号订阅(风控 SELL / 止盈 / 反转 → 卖出方案或提议)、择时实现 A委托决策系统盘中择时、T0 做T二期。研判闸客户端已就位等 bionic 侧 `process_intraday_audit` 新增 PMS 请求 direction 后,在页面填 `PMS_JUDGE_API_BASE` 即接通。
**待外部协商**`QMT_INTERFACE_REQUIREMENTS.md` 的 A/B/C/D 各项——尤其 A1`trading_position` 完整 DDL 与可用数量列、A2`trading_order` 状态枚举与**来源标识**、B1统一指令通道。在来源标识到位前回放按「同股同向 + 下发早于成交 + FIFO」贪心认领认领不上即判外部成交并告警持仓数量列用候选名探测探测结果可经页面「运维 → 导出下游表结构」查看,也是回填 D1 的现成材料。
## 开发约定
- 开发机与服务器经 git 同步代码;**构建与运行统一走 Docker**`docker compose build` → 容器内 `python scripts/run_tests.py``up -d`),测试结果回传后迭代。
- 153 代理侧数据库严格单表访问;该纪律已落到 `app/db/session.py` 的静态守卫,违规 SQL 在执行前抛 `MultiTableSQL`。持仓系统内部代码统一 Tushare 点式(`600000.SH`),读决策系统结论表时转前缀式。
- 配置分两层:基础设施连接串在 `.env`(服务器手工维护,不入库,模板见 `.env.example`);业务参数在 `config/settings.py` 只是初值,上线后经管理页面修改并持久化到 `pms_runtime_param` 表。**业务代码禁止直接读 settings 取业务参数**,一律走 `services/param_store.py`
- 新增纯逻辑一律进 `app/core/`(零外部依赖 + 配套单测);需要连库的编排进 `app/services/`,并保证连库失败时降级而非崩页。
- 里程碑(设计定稿、建表、各期上线)及时 git 提交。