ec02a791ee
- R-027 静态化:策略恒为内置两项(不可增删改名,保留显隐/排序);设置页移除「策略分组」; 字段配置入口迁到策略 tab 内「列设置」旁(FieldConfigDialog + schema-update 单策略写入) - R-026 计算字段:自写公式引擎(中文变量、四则/括号/round·abs·min·max、缺值短路→—)+ 变量目录(行情/合约/持仓/自定义字段)+ strategy-positions 逐行现算(只读内存缓存,不落库、列只读) - R-028 判定型:比较运算 + and/or + inferResultKind + 结果类型一致性校验 + 判定列 ✓/— 渲染; 网格超市落地 可下空单=涨停价>基准值+网格大小、可下多单=跌停价<基准值-网格大小 - 变量选择改标签平铺(老师反馈);公式手册 docs/99-其他材料/计算字段公式说明.md - 约束同步:产品约束-002/003/004/009/013/014、技术约束-014/015/022/023/024、UI约束-002/003/005/008 - 回归:新增 test-r026/test-r027,更新 r011/r013/r017,17 个脚本全绿;typecheck/build 通过
128 lines
8.6 KiB
Markdown
128 lines
8.6 KiB
Markdown
# 需求:R-026 策略计算字段(公式字段)· 已定稿
|
||
|
||
> 登记:2026-09-10 | 来源:老师指令(2026-09-10 功能讨论「策略组字段配置优化」)| 状态:**已定稿(2026-09-10 老师确认)**
|
||
> 归属:**22-策略计算字段与策略tab静态化 · 第二阶段**(PLAN-019)| 实现状态:**已实现(2026-09-10 完成,typecheck/build/17 个回归脚本全绿),待老师人工验收**
|
||
> **入口条款修订(2026-09-10,R-027 取代)**:字段配置入口由「设置页 → 策略分组 → 策略行展开」**迁至「策略 tab 内、列设置旁的『字段配置』弹层」**;本文档 §9 配置 UI 的入口位置随 R-027 变更,字段模型 / 公式语义 / 只读列 / 列机制均不变。
|
||
> 前身:草稿 T-010(已转正,草稿文件已清理)
|
||
|
||
## 诉求(老师,2026-09-10)
|
||
|
||
> 策略组字段配置优化:添加的字段,目前仅是支持用户指定值;接下来添加新的字段类型,就是**可以计算**,
|
||
> 目标是让用户**写一个公式**,公式中支持来自几个**服务端缓存的数据集**,然后通过计算得出结果。
|
||
|
||
## 背景(现状 R-013/迭代 11)
|
||
|
||
- 策略字段定义 = `settings.strategies[].configSchema`:`{ key, label, type(text|number|boolean|enum), enum[], def, unit }`;
|
||
- 字段值 = `strategy_holdings.values` JSON 列(**用户手工填写**,单元格内联编辑);
|
||
- 展示 = 持仓表列化(列显隐/顺序由 `strategyColumns` 每策略独立配置);
|
||
- 本次扩展:新增**第五种字段类型「计算(formula)」**——值不是填的,是**算的**。
|
||
|
||
## 定稿结论(2026-09-10 老师逐项确认)
|
||
|
||
### 1. 字段类型与存储语义
|
||
|
||
- `configSchema.type` 增加 `'formula'`;新增 `formula` 表达式串字段(与 `unit` 同级,随策略定义存 settings);
|
||
- **计算字段不落库**:不读写 `strategy_holdings.values`,每次读 `strategy-positions` 时**逐行实时现算**;
|
||
- 表格内**只读**(点击不进内联编辑);列配置兼容零改动(formula 字段自动进列集,新增默认追加末尾)。
|
||
|
||
### 2. 公式可引用的数据集(首批 = 行情/合约 + 持仓账本 + 本行自定义字段)
|
||
|
||
| 数据集 | 来源(服务端缓存) | 可引用字段 | 刷新 |
|
||
|---|---|---|---|
|
||
| 行情盘口 | QuoteHub.quotes(内存) | 现价 / 昨收 / 今开 / 最高 / 最低 / 成交量 / 成交额 | 5s REST |
|
||
| 合约信息 | QuoteHub.instruments(内存) | 涨停价 / 跌停价 / 昨收 | 按交易日 |
|
||
| 持仓账本 | SQLite strategy_holdings | 策略份额 / 成本价 / 最后一笔成交价 | 交易关联驱动 |
|
||
| 本行自定义字段值 | strategy_holdings.values | 本行手填字段(如网格间距、目标价) | 内联编辑 |
|
||
|
||
**后补(本期不做)**:QMT 账户域持仓(全账户 volume/可用/市值,跨策略视角)、交易记录聚合(当日已成交量/买卖笔数)——用例尚不明确。
|
||
|
||
### 3. 变量命名:**中文变量名**
|
||
|
||
- 公式形如 `(现价 - 成本价) × 份额`,可读性优先;
|
||
- 配置时校验**变量名唯一**;配置 UI 提供**变量选择器**(按数据集分组,点击插入);
|
||
- 引擎需支持中文标识符(自写解析器,见 §4)。
|
||
|
||
### 4. 公式引擎:自写小型表达式解析器(零依赖)
|
||
|
||
- 能力:四则运算 + 括号 + 常见函数(round / abs / min / max);
|
||
- 选型理由:中文标识符需自定义词法,第三方库(expr-eval/mathjs/jexl)均不支持中文变量;该层未来即 T-006 数据池的表达式层,值得自有。
|
||
|
||
### 5. 计算位置与粒度:**服务端计算 + 仅行级**
|
||
|
||
- 服务端在 `strategy-positions` 返回时逐行现算随行带回(行情单一入口 QuoteHub 在服务端);前端仅渲染;
|
||
- 行级上下文 = 本行行情 + 本行持仓账本 + 本行自定义字段值 → 一个结果;
|
||
- **策略级聚合(跨行求和,如本策略总盈亏)留二期**。
|
||
|
||
### 6. 循环引用边界:公式**只允许引用非公式字段**
|
||
|
||
- 变量目录直接排除 formula 字段 → 不存在循环依赖(不做检测与拓扑排序)。
|
||
|
||
### 7. 结果类型与格式
|
||
|
||
- 首批结果**只做数字**(布尔型公式后续再议);
|
||
- 复用现有 `unit`(展示拼在值后);新增**小数位**配置(默认 2 位)。
|
||
|
||
### 8. 缺数据与错误处理
|
||
|
||
- **保存时校验**:语法 + 变量存在性(服务端编译试算一次),非法公式直接拒绝保存并提示;
|
||
- **运行期**:缺行情 / 除零 / 无法计算 → 该单元格显示 `—`(不显示 NaN、不报错、不炸整表)。
|
||
|
||
### 9. 配置 UI(设置页「策略分组」字段表单)
|
||
|
||
- 类型下拉增加「计算」→ 出现公式输入框 + 变量选择器(分组:行情 / 合约 / 持仓 / 自定义字段)+ 变量速查;
|
||
- 加分项:**试算预览**(取一行真实持仓数据现场算出结果)。
|
||
|
||
### 10. 历史持仓行(已清仓)
|
||
|
||
- 历史 tab 的公式列统一显示 `—`:清仓行无「现价」语义,**不做历史时点计算**(属另一需求,不混入本期)。
|
||
|
||
### 11. 与服务端数据池(T-006)的关系
|
||
|
||
- 本期先落**轻量变量目录**(服务端声明:数据集 → 字段清单 → 取数函数),公式引擎跑在目录之上;
|
||
- 该目录即 T-006「数据池中间层」的第一块砖,**不一次性建完整数据池**(避免过度设计)。
|
||
|
||
## 典型用例(老师视角验收样例)
|
||
|
||
| 字段 | 公式 |
|
||
|---|---|
|
||
| 浮动盈亏 | `(现价 - 成本价) × 份额` |
|
||
| 盈亏比例 | `(现价 ÷ 成本价 - 1) × 100` |
|
||
| 距涨停 | `(涨停价 - 现价) ÷ 现价 × 100` |
|
||
| 网格占用(手填+计算组合) | `现价 × 份额 × 网格间距` |
|
||
|
||
## 决策记录
|
||
|
||
| 项 | 结论 | 讨论 |
|
||
|---|---|---|
|
||
| 字段类型 | configSchema.type 加 `formula` + `formula` 串 | 老师指令(新字段类型) |
|
||
| 存储语义 | **不落库**,读接口时逐行现算 | 「计算」的本质;values 列不参与 |
|
||
| 数据集范围 | 首批 行情+合约 / 持仓账本 / 本行自定义字段值 | 选择题确认(1+2+3);QMT账户域、交易聚合后补 |
|
||
| 变量命名 | **中文变量名** + 选择器插入 | 选择题确认;配置时校验唯一 |
|
||
| 计算粒度 | **仅行级**;策略级聚合二期 | 选择题确认 |
|
||
| 计算位置 | 服务端(strategy-positions 现算随行返回) | 老师方向「引用服务端缓存数据集」;行情单一入口在服务端 |
|
||
| 公式引擎 | 自写小型解析器(零依赖,支持中文标识符) | 第三方库不支持中文变量;未来即数据池表达式层 |
|
||
| 循环引用 | 只允许引用非公式字段 | 目录层排除,无循环问题 |
|
||
| 结果类型 | 数字 + unit + 小数位(默认 2) | 布尔型后议 |
|
||
| 错误处理 | 保存校验拒绝 + 运行期显示 `—` | 不炸整表 |
|
||
| 配置 UI | 公式输入 + 变量选择器(+试算预览) | 计算字段只读不内联编辑 |
|
||
| 历史行 | 公式列显示 `—` | 不做历史时点计算 |
|
||
| 数据池关系 | 轻量变量目录先行(T-006 第一块砖) | 避免一次性建完整中间层 |
|
||
|
||
## 关联
|
||
|
||
- 上游:R-013(自定义字段配置,字段类型与列机制)/ 迭代 11(列配置 strategyColumns);
|
||
- 数据来源:R-015(QuoteHub 盘口内存快照)、R-014(PositionSync 账户域)、R-010(最后一笔成交价)、R-018(份额账本);
|
||
- 延展:T-006(数据池中间层草稿)——本需求的变量目录为其起点;
|
||
- 约束条目待实施时补充(拟:产品功能约束 / 技术方案约束 / UI交互约束 各一条,沿用 R-013 惯例)。
|
||
|
||
## 讨论过程
|
||
|
||
- 2026-09-10 老师提出功能方向(策略组字段配置优化 → 可计算公式字段);
|
||
- AI 摸清 R-013 现状 + 盘活服务端缓存数据集清单,提出 Q1-Q10 设计问题清单(各附建议);
|
||
- 老师「定」:Q4-Q10 按 AI 建议;
|
||
- 选择题三项确认:Q1 数据集 1+2+3、Q2 中文变量名、Q3 仅行级计算;
|
||
- 转正定稿:T-010 草稿 → R-026(草稿文件已清理,索引同步);
|
||
- 2026-09-10 迭代 22 交互设计过审:老师逐项拍板 D-1~D-7(全采纳 AI 建议)→ `docs/04-迭代记录/22-策略计算字段与策略tab静态化/UI交互设计.md` 定稿;
|
||
- 2026-09-10 老师提出重构想法(策略 tab 静态化 + 字段配置入口迁移)→ 定稿 **R-027**:本需求的**字段配置入口**随之从设置页迁到「策略 tab 内、列设置旁的『字段配置』弹层」(迭代 22 调整为「第一阶段=重构、第二阶段=本需求」);
|
||
下一步:技术实现方案 + 验收标准(本轮按老师指令未做技术方案与编码)。
|