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 通过
152 lines
9.0 KiB
Markdown
152 lines
9.0 KiB
Markdown
# 计算字段公式说明
|
||
|
||
> 适用:策略 tab →「字段配置」→ 添加/编辑字段 → 类型选「**计算**」
|
||
> 版本:2026-09-10(R-026 计算字段 + R-028 判定型扩展)| 本文档与实现行为逐条对齐(已实机核对)
|
||
|
||
## 一、一句话
|
||
|
||
计算字段 = **你写一个公式**,服务端按**每个持仓行**实时算出一个值填到该列:公式里可以引用
|
||
**行情 / 合约信息 / 持仓账本 / 本策略手填字段**四类数据。值**不落库**、列**只读**、数据缺失时显示 `—`。
|
||
|
||
## 二、结果类型(先选这个)
|
||
|
||
字段表单「**结果**」下拉决定列的呈现方式,且**必须与公式形态一致**(服务端校验,不一致直接拒绝保存):
|
||
|
||
| 结果类型 | 公式形态 | 列上显示 | 可配项 |
|
||
|---|---|---|---|
|
||
| **数字**(默认) | 算式,如 `(现价 - 成本价) × 份额` | `700.00 元`(小数位 + 单位) | 小数位 0–4(默认 2)、单位 |
|
||
| **判定** | 顶层是比较,如 `涨停价 > 基准值 + 网格大小` | 满足 → `✓ 可下空单`(绿);不满足/缺数据 → `—`(灰) | 单位、小数位不适用(自动隐藏) |
|
||
|
||
- 判定列文字 = 该字段的**展示名**(所以展示名建议直接写成规则名,如「可下空单」);
|
||
- 「不满足」与「数据缺失」目前**都显示 `—`**(避免把「没数据」误读成「不满足」)。
|
||
|
||
## 三、可用变量(写中文名即可;点「+ 插入变量」自动插入)
|
||
|
||
| 分组 | 变量 | 含义 / 来源 |
|
||
|---|---|---|
|
||
| 行情 | `现价` `昨收` `今开` `最高` `最低` `成交量` `成交额` | 盘口内存快照(服务端 5s 刷新) |
|
||
| 合约 | `涨停价` `跌停价` | 合约信息(按交易日,当天不变) |
|
||
| 持仓 | `份额` `成本价` `最后成交价` | 持仓账本:本策略分配份额 / QMT 成本价 / 最后一笔实际成交价 |
|
||
| 自定义字段 | 本策略**手填字段的展示名**(如 `基准值` `网格大小` `网格交易量`) | 该持仓行手填的值 |
|
||
|
||
规则与注意:
|
||
|
||
1. **变量名 = 内置名(上表固定 12 个)或手填字段的展示名**。手填字段**改名后**,引用它的公式会失效
|
||
(该列变 `—`,再保存字段时会提示「未知变量」),把公式里的变量名同步改成新名字即可;
|
||
2. 字段展示名**不得与内置变量名冲突**(不能建一个叫「现价」的字段),同策略内展示名不得重复;
|
||
3. **计算字段不能被另一个公式引用**(零循环依赖):公式里写另一个计算字段的名字会报「未知变量」;
|
||
4. 手填字段的**非数字值**参与运算按「无值」处理(空文本 → 该行 `—`;布尔按 1/0)。
|
||
|
||
## 四、运算符
|
||
|
||
| 类别 | 写法 | 说明 |
|
||
|---|---|---|
|
||
| 四则 | `+ - * / ` | 全角 `× ÷ + -` 同样可用 |
|
||
| 括号 | `( )` | 全角 `( )` 同样可用 |
|
||
| 比较 | `> < >= <= == !=` | 全角 `≥ ≤ ≠ > < =` 同样可用;`==` 是**精确相等**(无容差) |
|
||
| 逻辑 | `and` / `or`(也可 `&&` / `||`) | 判定型专用,如 `A > 1 and B < 2` |
|
||
| 一元负 | `-现价` | — |
|
||
|
||
**优先级**(低 → 高):`or` → `and` → 比较 → 加减 → 乘除 → 一元负 → 括号。拿不准就加括号,最稳。
|
||
|
||
## 五、函数(只有这 4 个)
|
||
|
||
| 函数 | 参数 | 例子 | 结果 |
|
||
|---|---|---|---|
|
||
| `round(值, 位数)` | 1–2 个;位数 0–10(负数按 0 处理) | `round(106.666, 2)` | `106.67` |
|
||
| `abs(值)` | 恰好 1 个 | `abs(成本价 - 现价)` | `0.7` |
|
||
| `min(...)` | ≥1 个 | `min(涨停价, 现价 * 1.05)` | 取小 |
|
||
| `max(...)` | ≥1 个 | `max(0, 现价 - 成本价)` | 取大(不小于 0) |
|
||
|
||
## 六、计算规则与「缺值」语义
|
||
|
||
- **缺值短路**:公式里**任一变量没有数据**(无行情、无合约信息、手填字段为空)→ 整行结果为空 → 列显示 `—`
|
||
(不会显示 0 或 NaN,也不会报错、不会炸表);
|
||
- **除零 / 结果非有限数** → `—`;
|
||
- **浮点归一**:自动消除浮点噪声(不会出现 `0.7000000000000002` 这种值);
|
||
- **限制**:公式 ≤ **500 字符**、嵌套 ≤ **32 层**(超出提示「公式过长 / 过于复杂」);
|
||
- **安全**:自写解析引擎,不支持 `eval`,除四则/比较/逻辑/这 4 个函数外没有任何能力(不能读写文件或网络)。
|
||
|
||
## 七、列上怎么显示
|
||
|
||
| 场景 | 显示 |
|
||
|---|---|
|
||
| 数字型有值 | 按「小数位 + 单位」显示(如 `6.67 %`、`700.00 元`;单位留空则只显示数字) |
|
||
| 判定型满足 | `✓ <字段名>`(绿),如 `✓ 可下空单` |
|
||
| 判定型不满足 / 数字型无值 | `—`(灰) |
|
||
| 已清仓的历史持仓行 | `—`(不做历史时点计算) |
|
||
| 表头 | 列名前带 `ƒ` 标记;悬停列头/单元格可见公式原文(`= 公式`) |
|
||
| 刷新 | 随策略持仓接口轮询刷新(行情服务端 5s 更新;列值是「计算快照」,不做价格闪烁) |
|
||
|
||
## 八、常用公式(可直接抄)
|
||
|
||
### 网格超市
|
||
|
||
| 用途 | 结果类型 | 公式 |
|
||
|---|---|---|
|
||
| 可下空单 | 判定 | `涨停价 > 基准值 + 网格大小` |
|
||
| 可下多单 | 判定 | `跌停价 < 基准值 - 网格大小` |
|
||
| 触到上边界 | 判定 | `现价 >= 网格上边界` |
|
||
| 跌破下边界 | 判定 | `现价 <= 网格下边界` |
|
||
| 距上边界 % | 数字(单位 %) | `(网格上边界 - 现价) ÷ 现价 × 100` |
|
||
| 每格金额 | 数字(单位 元) | `网格交易量 × 网格大小` |
|
||
| 本行网格占用 | 数字(单位 元) | `现价 × 份额` |
|
||
| 空单且未触上边界(组合) | 判定 | `涨停价 > 基准值 + 网格大小 and 现价 < 网格上边界` |
|
||
|
||
### 手动做T / 通用
|
||
|
||
| 用途 | 结果类型 | 公式 |
|
||
|---|---|---|
|
||
| 浮动盈亏 | 数字(元) | `(现价 - 成本价) × 份额` |
|
||
| 盈亏比例 | 数字(%) | `round((现价 ÷ 成本价 - 1) × 100, 2)` |
|
||
| 市值 | 数字(元) | `现价 × 份额` |
|
||
| 距涨停 % | 数字(%) | `(涨停价 - 现价) ÷ 现价 × 100` |
|
||
| 成本上方空间 | 数字(元) | `max(0, 现价 - 成本价) × 份额` |
|
||
| 盈利中 | 判定 | `现价 > 成本价` |
|
||
| 成本上方且未涨停 | 判定 | `现价 > 成本价 and 现价 < 涨停价` |
|
||
| 相对 T 仓成本盈亏 | 数字(元) | `(现价 - T仓成本价) × 份额` |
|
||
|
||
## 九、保存校验与报错对照
|
||
|
||
保存字段时服务端会**先校验语法与变量**,不通过直接拒绝(公式框描红 + 提示,表单不关闭):
|
||
|
||
| 提示 | 原因 | 怎么办 |
|
||
|---|---|---|
|
||
| `公式不能为空` | 公式为空 | 填公式 |
|
||
| `公式不完整` / `缺少右括号` / `意外的符号` / `无法识别的字符` | 语法错 | 检查括号与运算符是否写全 |
|
||
| `未知变量『xx』——该字段已删除或名称有误` | 变量名不对(或引用了计算字段) | 用「+ 插入变量」插入,或核对字段展示名 |
|
||
| `未知函数『xx』(可用:round/abs/min/max)` | 用了未实现的函数 | 只用这 4 个 |
|
||
| `函数『xx』参数个数不对` | 参数多/少 | 见第五节 |
|
||
| `变量名『现价』与内置变量冲突,请修改字段展示名` | 字段名撞内置变量 | 改展示名 |
|
||
| `字段展示名重复: xx` | 同策略两字段同名 | 改其一 |
|
||
| `公式过长(上限 500 字符)` / `公式过于复杂(嵌套过深)` | 超限 | 拆成两个字段 |
|
||
| `结果类型选了「判定」,但公式没有比较运算(如 涨停价 > 基准值 + 1)` | 结果类型与公式形态不符 | 改结果类型为「数字」,或把公式写成比较 |
|
||
| `公式结果是判定,请把「结果类型」改为「判定」` | 同上(反向) | 把结果类型改为「判定」 |
|
||
|
||
配置时可点「**试算**」:服务端拿该策略**一行真实持仓**当场算给你看
|
||
(判定型显示 `✓ 满足 / — 不满足`;无持仓提示「暂无可试算的持仓数据」)。
|
||
|
||
## 十、常见问题
|
||
|
||
**Q:为什么整列都是 `—`?**
|
||
按序排查:① 该 code 暂无行情/合约快照(等 5s 同步,或点会话头部行情灯立即同步);
|
||
② 公式用到的手填字段该行没填值;③ 公式里有除零;④ 公式引用了已删除/改名的字段。
|
||
|
||
**Q:能不能写条件分支(三态:空 / 多 / 观望)?**
|
||
目前不支持 `if`/三元表达式;判定型只覆盖「满足 / 不满足」两态。要一列表达三态时,
|
||
可先用两个判定字段(`可下空单` + `可下多单`)代替 —— 两个都为 `—` 即观望。
|
||
|
||
**Q:能不能跨行求和(本策略总盈亏)?**
|
||
不能——公式是**逐行**计算,只看得到本行数据。
|
||
|
||
**Q:格子能手动改吗?**
|
||
不能,计算字段**只读**;手填字段才能在格子里点击编辑。
|
||
|
||
**Q:单位参与计算吗?**
|
||
不参与,只影响显示(拼在值后);判定型不需要单位。
|
||
|
||
## 十一、暂不支持(明确边界)
|
||
|
||
条件分支(`if`/三元)、`not` 取反、判定与数字混用的单字段、跨行聚合(求和/平均)、历史持仓行时点计算、
|
||
策略以外的数据集(账户域持仓、交易记录聚合——尚未接入为变量)。
|