Files
zszq-trs/项目文档/互换价格字段命名规范决策文档.md
T
2026-07-02 18:09:27 +08:00

18 KiB
Raw Blame History

互换价格字段命名规范决策

本文档是命名规范的决策与论证,回答"应该叫什么、为什么这么叫"。 现状梳理(字段流向、存储显示规则)见姊妹文档 互换交易价格字段存储与显示规范.md。 适用范围:互换业务(收益互换)涉及的价格、方向、时点字段。期权/远期业务字段不在本文档范围。


一、为什么命名必须先定下来

现状是同一概念多套名字、名字与含义颠倒,已经反复造成 Bug。三条最严重的证据:

  1. PosiNetPrice 名为"Net",实为"含费全价"。真正的净价是 PosiNetNoFeePrice。连现状文档(《互换交易价格字段存储与显示规范》)都把它误标成"期初净价"——文档作者都被字段名骗了。
  2. 两套并行命名无对应关系:持仓表 PosiNetPrice ↔ 流水表 TradingAmountFeeAvg,持仓表 PosiGrossPrice ↔ 流水表 TradingAmountAvg,名字里没有一处对得上。
  3. 前端同一中文标签绑不同字段成交净价 一处绑 TradingAmountNet,另一处绑 TradingAmountNetAvg期初标的价格 录入页绑 PosiGrossPrice,平仓明细页绑 PosiNetPrice

命名不定下来,后续每个改动都要反复核对数据流向,且极易引入新 Bug。本文档的目的是把每个维度的命名一次性钉死,给出对比理由


二、三个维度的决策

互换价格有三个正交维度,必须分别命名:

维度 取值 现状混乱
A. 价格种类 全价 / 净价 Net/Gross 颠倒;Posi vs TradingAmount 两套
B. 是否含交易费 含费 / 不含费 Fee 标记位置在两套体系里相反
C. 时点 期初 / 期末 / 盯市 Start/Begin/End/Initial/Final/Spot/Open 散布,无统一规则

外加一个方向维度(收取方/支付方),目前用中文枚举,trade_swap 老表用 Get/Pay。

下面逐项决策。


三、维度 A:价格种类 —— 采用 Clean / Dirty

候选对比

方案 优点 缺点 评价
Clean / Dirty 债券行业标准术语;歧义最小;与中债估值表 dirty_price_close/net_price、量化库常见命名一致 非 OTDer 可能需要学习成本 推荐
Net / Gross(现状持仓表) 简短 本项目已颠倒PosiNetPrice 是含费全价);Net/Gross 在金融里本身就有"净值/毛额"歧义,不专指债券净价全价 已证明不可行
Clean / Full Full 含义尚可 不如 Dirty 标准;中债表用 dirty,不统一
净价 / 全价(中文直译) 业务人员熟悉 C# 字段用中文不合规;与现有英文体系混搭更乱

决策

全价用 Dirty,净价用 Clean

理由:

  1. 行业术语,零歧义。Clean/Dirty 是债券领域全世界通用的无歧义术语(clean price = 不含应计利息,dirty price = 含应计利息)。
  2. 与数据源一致。录入默认价格来源 china_bond_valuation 表用的就是 dirty_price_close(日终估值全价)和 net_price(估价净值)。字段命名与数据源对齐,减少心智负担。
  3. 现状 Net/Gross 已被证明失败。它在本项目里语义颠倒,且 Net 在不同字段里含义不同(PosiNetPrice 的 Net = 含费,PosiNetNoFeePrice 的 Net = 净价),是混乱根源,必须废弃。

与"费"维度组合后的完整 4 象限见第五节。


四、维度 B:费用 —— 采用 Fee / NoFee

先澄清:"费"是什么

"费" = 交易费用 / 佣金(TradingFee,由 TradeFeeHelper.CalcPriceWithFee(price, fee, qty) 计算:含费价 = 不含费价 + 单位佣金。它不是应计利息(应计利息体现在 Clean/Dirty 维度),也不是利息腿费用。

候选对比

方案 优点 缺点 评价
Fee / NoFee(后缀) 现状已在用(PosiNetNoFeePrice/TradingAmountFeeAvg);直白 推荐(沿用现有约定,零迁移成本)
Gross / Net(用 Net 表示含费) 与维度 A 的 Clean/Dirty 严重冲突,两套词打架
WithFee / WithoutFee 更明确 太长;后缀冗余
PreFee / PostFee 金融衍生品常见 偏衍生品语境,互换收益端用着别扭

决策

含费用 Fee 后缀,不含费用 NoFee 后缀。

理由:现状流水表已经是这套(TradingAmountAvg 不含费 / TradingAmountFeeAvg 含费 / TradingAmountNetAvg 净价不含费 / TradingAmountNetFeeAvg 净价含费),这个约定本身没问题,问题是持仓表用了另一套颠倒的 Posi 命名。统一到 Fee/NoFee 即可。


五、维度 A+B 组合:价格 4 象限最终命名

决策表

业务含义 规范命名 现状持仓表 现状流水表
全价 · 不含费 XxxDirtyPrice PosiGrossPrice TradingAmountAvg
全价 · 含费 XxxDirtyFeePrice PosiNetPrice ⚠️ TradingAmountFeeAvg
净价 · 不含费 XxxCleanPrice PosiNetNoFeePrice TradingAmountNetAvg
净价 · 含费 XxxCleanFeePrice PosiNetFeePrice TradingAmountNetFeeAvg

其中 Xxx 是时点前缀(见第六节)。

命名规则一句话

{时点}{Dirty|Clean}{Fee|}{Price} —— Dirty/Clean 选价格种类,Fee 出现表示含费、不出现表示不含费。

例:EntryDirtyPrice(期初全价不含费)、EntryDirtyFeePrice(期初全价含费)、ExitCleanPrice(期末净价不含费)。


六、维度 C:时点 —— 采用 Entry / Exit+ Market

这是你重点要求对比的部分。先看现状,再逐词对比。

现状:时点词散布(统计自实体字段)

现状词 出现次数(实体字段) 用在什么字段
Start 36 StartDate(起始日)
Spot 28+4 SpotPrice(期初价,期权/远期)、GetSpotPrice/PaySpotPricetrade_swap
Open 3 OpenPrice、OpenTradePrice(开仓价)
Init/Initial 4 InitYtm、InitialSpotPrice[NotMapped]
Final 10 FinalPrice(期末价)、GetFinalPrice/PayFinalPrice
End 12 EndDate(结束日)
Close 21 ClosePrice(收盘价,行情侧)
Maturity 14 MaturityDate(到期日)
Entry/Exit 0 未使用

现状问题:表达"期初价"用了 SpotOpenInitInitial 四种;表达"期末价"用了 FinalEndClose 三种;且 Close 还和"行情收盘价"语义重叠。

候选词逐个对比

期初价(开仓成本价)候选

方案 含义直觉 优点 缺点 评价
Entry 入场/建仓 交易术语,明确"进入持仓那一刻";与 Exit 对称;不与现有任何日期/价格词冲突 全新词,需迁移 推荐
Start 开始 StartDate(起始日)一致,延续性最好 与日期混淆StartPrice 容易被误读成"起始日当天的价格"而非"建仓成本价";价格 vs 日期语义纠缠
Begin 开始 同 Start 同 Start;且与 Start 二选一造成二次混乱(现已有 Start,再加 Begin 是雪上加霜)
Initial / Init 初始 语义尚可 Init 是缩写不规整;现状 InitYtm 已用,但 InitialPrice 太长;Init/Initial 两种并存(现状就有 InitYtmInitialSpotPrice)本身就是混乱证据
Spot 即期 现状 trade_swap 在用 语义错误Spot 在金融里指"即期(spot vs forward",不是"期初";互换里强行用 Spot 表示期初是误用;且与"即期价格"概念冲突
Open 开仓 有"开仓"意味 OpenPrice 在期权语境指"开盘价"open=开盘 vs close=收盘),互换用 Open 会与行情术语打架

期末价(平仓/到期价)候选

方案 含义直觉 优点 缺点 评价
Exit 出场/了结 与 Entry 对称;明确"退出持仓那一刻";不与 Close/Maturity 冲突 全新词,需迁移 推荐
Final 最终 现状在用(FinalPrice Final 在期权语境常指"到期(final/expiration)",与互换"平仓了结"语义有偏差;且 Final 给人"永远结束"的感觉,但互换可能多次部分平仓(每次都是 Exit)
End 结束 简短 EndDate(结束日)混淆,同 Start 的问题
Close 收盘 行情侧在用(ClosePrice 语义已被占用:Close = 收盘行情价;互换平仓价用 Close 会和"每日盯市收盘价"混淆。这是现状混乱之一
Maturity 到期 债券标准术语 只适用于"持有到期",不适用于"提前平仓";互换平仓≠到期 (仅 MaturityDate 用于到期日)

决策

期初用 Entry,期末用 Exit,每日盯市用 Market

为什么是 Entry/Exit 而不是其他 —— 三条核心理由

理由 1Entry/Exit 是唯一一组"互相对称、且不与现有词冲突"的方案。

对称组 冲突情况
Entry / Exit 零冲突,现有代码 0 处使用
Start / End 与 StartDate/EndDate 日期字段冲突
Open / Close 与行情开盘价/收盘价冲突
Initial / Final △ Initial 太长,Final 偏"到期"语义
Begin / End 与 Start 重复造词

互换价格的核心心智模型是"Entry(建仓成本)vs Exit(了结价格)"——盈亏 = Exit Entry。Entry/Exit 直接表达这个对偶关系,其他词都带着别的语义包袱。

理由 2:互换"多次部分平仓"语义下,Entry/Exit 比 Start/End/Final 更准确。

互换持仓期间可以有多次部分平仓(每次部分平仓都是一次 Exit),不是"一次性 Start→End"。Final(最终)暗示"只有最后一次",Start/End 暗示"单一起止点",都不符合"多次 Exit"的现实。Exit 天然支持"多次出场"语义(每次平仓 = 一次 Exit)。

理由 3:与"盯市价"清晰分层。

时点 命名 含义
建仓时 Entry* 成本价(固定)
平仓时 Exit* 了结成交价(每次平仓一个)
持仓期间每日 Market* 盯市价(随行情变动)

三者职责清晰:Entry 是成本基线,Exit 是实现盈亏的时点,Market 是浮动盈亏的基准。现状 UnderlyingPrice(盯市价)改为 MarketDirtyPrice 后,与 Entry/Exit 形成 Entry / Market / Exit 完整时点链。

收益率字段同理

含义 规范命名 现状
期初 YTM EntryYtm InitYtm
平仓 YTM ExitYtm ytm / Ytm

七、维度 D:方向 —— 收取/支付方的命名

现状

位置 现状命名 问题
SwapDirectionEnumV2 在用) 收取 / 支付(中文) C# 字段用中文不合规;与英文代码混排突兀
trade_swap(老表,已弃用互换主流程) Get* / Pay*(如 GetSpotPrice/PaySpotPrice Get 语义弱,不像金融术语;你已指出这是老互换遗留
PositionTypeFlag(多空) Long / Short 这个没问题,标准术语
业务文档/前端 "收取方/支付方"、"固定端/浮动端" 中文展示 OK

候选对比(英文方向词)

方案 优点 缺点 评价
Rcv / Pay 金融工程标准(IRS 收付固定方叫 Receive/Pay);FINCAD/Bloomberg/量化库通用;3字母缩写简洁 Rcv 需要新人熟悉"是 receive 缩写" 推荐
Receive / Pay 不缩写,更明确 Receive 较长,字段名 ReceiveDirtyPrice 偏长
Get / Pay(现状老表) 现状 Get 不是金融术语,语义弱("获得"太泛);与 Pay 不对称(Pay 是金融词,Get 是口语)
Long / Short 标准术语 语义不同Long/Short 是多头/空头(PositionType),不是收取/支付方(SwapDirection);互换里收取方可能是空头。两者不能混用 (维度不同)
Buy / Sell 通用 互换不是买卖关系,是交换现金流;Buy/Sell 易误导

决策

英文方向词用 Rcv / Pay,仅用于代码字段名(如 RcvEntryDirtyPrice);枚举值和前端展示保持中文"收取/支付"。

理由:

  1. 金融标准。利率互换(IRS)行业里固定方/浮动方标准叫法就是 Receive fixed / Pay fixedFINCAD、Bloomberg、主流量化库都用 Rcv/Pay。
  2. 纠正老表 Get 的错误。trade_swap 的 Get/Pay 里 Get 不是金融词,是早期随手起的,正好借命名规范统一为 Rcv/Pay。
  3. 不与 Long/Short 冲突。Rcv/Pay 是 SwapDirection(收取/支付哪一端现金流),Long/Short 是 PositionType(多空),两个维度独立,不能互相替代。
  4. 中文枚举保留SwapDirectionEnum.收取/支付 已被业务文档、前端、监管报表广泛使用,强行改英文枚举值成本高且无收益。只在新英文字段名里用 Rcv/Pay。

注:当前 V2 互换主流程(swap_position/eod_swap_position)已经不按"收取/支付腿"存价格(价格存在不分腿的持仓记录里,方向用 PosiDirection 字段标记),所以 Rcv/Pay 前缀只在需要显式区分双腿的场景(如 trade_swap 录入、双边互换)使用,不是所有字段都加。


八、最终命名总表(一锤定音)

8.1 价格 4 象限(含时点前缀)

业务含义 规范命名 现状(持仓/流水)
期初全价·不含费 EntryDirtyPrice PosiGrossPrice / —
期初全价·含费 EntryDirtyFeePrice PosiNetPrice ⚠️ / —
期初净价·不含费 EntryCleanPrice PosiNetNoFeePrice / —
期初净价·含费 EntryCleanFeePrice PosiNetFeePrice / —
期末/平仓全价·不含费 ExitDirtyPrice — / TradingAmountAvg
期末/平仓全价·含费 ExitDirtyFeePrice — / TradingAmountFeeAvg
期末/平仓净价·不含费 ExitCleanPrice — / TradingAmountNetAvg
期末/平仓净价·含费 ExitCleanFeePrice — / TradingAmountNetFeeAvg
盯市全价 MarketDirtyPrice UnderlyingPrice
期初收益率 EntryYtm InitYtm
期末收益率 ExitYtm ytm

8.2 方向

业务含义 代码字段名 枚举/展示值
收取方 Rcv*(如需区分腿) 收取(SwapDirectionEnum.收取)
支付方 Pay*(如需区分腿) 支付(SwapDirectionEnum.支付)
多头 LongPositionTypeFlag.Long 多头
空头 ShortPositionTypeFlag.Short 空头

8.3 命名规则速记

价格 = {Entry|Exit|Market}{Dirty|Clean}{Fee|}Price 方向 = Rcv|PaySwapDirection)与 Long|ShortPositionType)是两个独立维度,不混用 收益率 = {Entry|Exit}Ytm


九、落地策略(渐进式,不一次性改)

直接全局重命名风险极高(DB 列 + EF 实体 + ~15 服务类 + ~20 前端文件 + 交易确认书 + Excel 导入)。建议分阶段:

阶段 动作 风险 产出
0. 文档定调(本文档) 命名规则钉死,团队达成共识 本文档
1. 注释止血 在现状最混乱的字段(PosiNetPrice/PosiGrossPrice)加 [Obsolete] + XML 注释,写明真实含义与规范名 防止再被字段名误导
2. 前端统一取值封装 新增 swapPriceHelper.js,把分散的 item.PosiGrossPrice 等收敛成 getEntryDirtyPrice(item);先修"同标签绑不同字段"的混乱 前端混乱点消除
3. 新代码强制规范 新增字段/新功能必须用规范命名;对外 API 新增 DTO 用规范名,内部旧字段靠 Mapper 转换 增量规范化
4. 大重构(慎重) DB 列重命名 + EF 映射 + 全量替换,配合数据迁移。建议趁大版本升级做 彻底统一

阶段 1 最该立刻做:给 PosiNetPrice(含费全价,非净价)和 PosiGrossPrice(不含费全价)加注释,因为连现状文档都被它们误导过。


附录:现状混乱全证据清单(决策依据)

以下每条都有代码/DDL/前端文件佐证,是上述决策的事实基础。

# 混乱点 关键证据位置
1 PosiNetPrice 名为 Net 实为含费全价 SwapTradeService.cs:372-373 赋值:PosiNetPrice←TradingAmountFeeAvg(含费均价)
2 PosiGrossPrice 名为 Gross 实为不含费全价 同上:PosiGrossPrice←TradingAmountAvg(不含费均价)
3 同字段两表 DDL 注释矛盾 PosiNetPriceswap_position 注释"持仓净价"eod_swap_position 注释"期初标的价格"
4 持仓表/流水表两套命名无对应 Posi*Net/Grossvs TradingAmount*Avg/FeeAvg),名字对不上
5 前端同标签绑不同字段 成交净价 绑 TradingAmountNet(303) 也绑 TradingAmountNetAvg(508),见 SwapflowList.js
6 作者自曝字段语义错位 SwapIncome.cshtml:155SwapDealService.cs:279 注释:"TradingAmountNetAvg 字段名为期末语义,实装期初值"
7 trade_swap 第三套命名 GetSpotPrice/PaySpotPrice/GetFinalPrice/PayFinalPrice,与 Posi* 平行无对应
8 时点词散布 期初价用了 Spot/Open/Init/Initial 四种;期末价用 Final/End/Close 三种
9 Close 语义被占用 ClosePrice=行情收盘价 vs 互换平仓价混用
10 Get 不是金融术语 trade_swap 的 Get/PayGet 语义弱,与 Pay 不对称
11 现状文档自身被误导 《互换交易价格字段存储与显示规范》把 PosiNetPrice 标为"期初净价",实为含费全价