Files
zszq-trs/YLErpDAL/Modules/SwapModule/TEST-MATRIX.md
T
hjhanandClaude Opus 4.7 07764e7e3f test(swap): 契约参考实现落地,引擎主力族盘中重放首次对齐确认书公式 oracle
ContractReferenceCalc 独立实现 §8a 确认书公式(∏/重置期切分/末段收口/
利率确定日=重置日上一营业日),禁止引用生产计息类防同源;4 例手算锚点
自验证(真实规模 5000万/2.05%/90天=75999.04 与玩具锚点)。

引擎对照首批 3 例全绿:mode9/mode2 × 复利 × "10" × T+0 部分平仓30%,
盘中重放与契约 oracle 容差 0.01 元内逐分吻合——盘中口径=确认书公式
自此有机器强制,后续补格直接复用 oracle 供给(TEST-MATRIX §7.5 已登记)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-16 12:19:28 +08:00

11 KiB
Raw Blame History

融资腿计息测试矩阵

配套 ARCHITECTURE.md。目的:把"覆盖"从用例计数变成格子坐标运算—— 每个用例/fix 显式登记命中坐标,空洞一眼可见。2026-08 建立,依据近 6 周 fix 热力图回溯登记。

0. 范围声明

  • 本矩阵只覆盖融资腿 FundingLeg(mode 1 固定值 / 2 合约名义本金规模 / 9 标的期初全价)
  • mode 5/6(保证金/预付金)不属于本矩阵(历史遗留:被错误建模为计息腿,概念上与融资腿无关, 见 Margin/MarginModes.cs 注释)。保证金有独立的余额模型与专属黄金回放(96 库 60 条,0 差异)作为护栏。 禁止向本矩阵添加 5/6 格子。
  • 主力生产组合(确认书规定)必须全格覆盖,见 §1。

1. 主力族(第一优先级,必须全盖)

InterestMode = 9 标的期初全价 × FR007 浮动(±点差) × InterestType = 复利 × InterestCalcMode = "10"(算头不算尾)

代码锚点:SwapDealService.GetInterests(calcFirst=true / calcLast=false,SwapDealService.cs:646)。 近 6 周 ≥9 个 fix 落在本族内——生产用得最多 = 人工测试打得最狠,fix 清单就是炸点热力图。

2. 维度定义

维度 取值 代码/数据锚点
A 生命周期终点 持有至到期结算 / 盘中全平 / 盘中部分后持有 / 部分N次后全平 / EOD自动平仓(部分·全) / 互换(续作) SwapEventTypeEnum;到期:SwapEodPositionService 到期结算路径
B 重置几何 第1重置期内平仓 / 跨≥1完整重置期 / 第3重置期内 / 平仓日=重置日 / 重置日±1天 / 末段非整周期(di<7) 重置频率=7天(已定格,§8);契约重置期定义见 §8a
C 比例与次数 单次部分(30%) / 同日两次 / 跨重置期多次 / 全平(剩余=0) closePrecent;双语义转换 ClosePercentMath
D 交收 T+0 / T+1 valueDate vs unwindDate
E FR007 形态 每重置日有价 / 加点(+0.25%) / 减点(-2.10%) / 取价日=重置日上一营业日(契约规定) / 缺价分支 TryGetFloatRate / ResolveFloatRate;66a97e03 对应此维
F 入口 见 §3
G 断言投影 ①最终利息金额 ②TdInterestPrincipal 逐日携带链 ③InterestIncomeSum+flow_event 全字段 ④方向/符号(报表口径) 每格必须断言全部 4 个投影

3. 入口枚举(F 维)

入口 代码路径
盘中平仓/互换结息试算 SwapDealService.GetInterestsForUnwind(SwapDealService.cs:617,settment:false → CalcUnwindInterest)
EOD 正常收盘 GetInterests(settment:true)CalcEodInterest
EOD 平仓后收盘 SwapEodPositionService.SaveAutoEodWithCloseInterestPosition(:1246)→ CalcSwapInterests(:1579)
EOD 自动互换 CalcSwapInterests(:1161,EventType=自动互换)

已知风险:GetInterests 参数语义随入口漂移(EOD 平仓后收盘传"剩余本金+percent=1", 盘中传"平仓前本金+实际比例"),GetInterestsEntrySemanticsTest 曾实测双入口复利口径分歧(b01b485e)。

4. fix 热力图(本族,近 6 周)

fix 落点 格子坐标 自带测试
66a97e03 重置日=平仓日 calcLast 不跳过 FR007 取价 SwapDealService:1249/1295 B=重置日=平仓日 × E=取价边界 GLMS20260805FR007UnderlyingIdDiagnoseTest(581行)
48e84479 重置日部分平仓本金 SwapEodPositionService:1422 B=重置日=平仓日 × C=部分 SwapCloseConversationCasesRegressionTest(358行)
d3afa6d2 T+1 部分平仓复利本金(算头不算尾快速路径) SwapDealService:1243 D=T+1 × C=部分 × A=部分后持有 DealInterestsScenarioTest +36行
aa5a5ed8 算头不算尾期初复利部分平仓 SwapEodPositionService:1418-1573 本族正中心 DealInterestsScenarioTest
a0be0eb0 复利平仓已结利息扣除 SwapDealService:1294 已结利息差分(CalcDailyCompoundInterest 回放) ConsumedInterestScenarioTest
5539bd9c 复利部分平仓后 EOD 本金 SwapEodPositionService:782/1381 G=携带链投影 DealInterestsScenarioTest +34行
feffc196 Bug A/B/C 浮动部分/全平尾差 SwapDealService:1214/1292 C=部分/全平 × E=浮动 SwapInterestScenario3And4FloatingTest(24用例,Excel oracle)
2035e1df EOD 平仓后收盘结息本金语义 SwapDealService:1293 / EodService:860,1360 F=EOD平仓后收盘 × C 无测试
b01b485e 双入口口径分歧(实测发现) F=入口 × 全族 GetInterestsEntrySemanticsTest(字符化,非 oracle)

规律:fix 全部落在 CalcUnwindInterest(SwapDealService 1240-1300)和 SaveAutoEodWithCloseInterestPosition 族(SwapEodPositionService 1380-1580)两个带。

5. 现有用例登记

测试文件 覆盖格子 oracle 类型
SwapInterestScenario3And4FloatingTest(24) 本族 A=全平/部分30%→全平 × B=第3重置期内 × D=T+0/T+1 × E=加减点 × F=EOD平仓后收盘 × G=仅金额投影 Excel 手算(业务源)
SwapInterestScenario1And2Test(32) A=收盘平仓 × B=第1重置期内 × E=固定/浮动 Excel 手算
DealInterestsScenarioTest(24 方法,工单逐个追加) 部分平仓×复利族各点,含"10"×3 行 工单期望值
ConsumedInterestScenarioTest 已结利息差分族 工单期望值
SwapUnwindSameDayDoublePartialTest C=同日两次 字符化(非独立 oracle)
GetInterestsEntrySemanticsTest F=双入口一致性 字符化
ContractReferenceOracleTest(Accrual/,7) mode9/mode2 × 复利 × "10" × T+0 × 部分30% × B=跨12整期+末段(90/89天) × E=恒定利率(取价日免疫) 契约公式参考实现(§7.4 第一级)——引擎盘中重放已逐分对齐 oracle
GetInterestsUnitTest_T0/T1(89) mode 1 固定值 T+0/T+1 族(非本族) 单点断言
GLMS20260805FR007UnderlyingIdDiagnoseTest B=重置日=平仓日 × E 诊断+断言

6. 空洞清单(热力图 ∩ 未覆盖,按优先级)

  1. F=EOD平仓后收盘 × C=部分平仓 × 本族 —— 2035e1df 无测试落地即合入,该入口×比例格子全裸。
  2. G=携带链投影(全族) —— 现有断言几乎全是最终金额;TdInterestPrincipal 逐日携带链无一处断言 (7528670e 在单利上炸过同款,复利同投影裸奔)。
  3. B=重置日±1天 / 跨重置期多次部分平仓 —— 热力图边缘未扫。
  4. A=到期结算 × 本族 —— db46e48e 修过到期结算(28 断言),但非本族参数。
  5. A=互换(续作) × 本族 —— 7411b9d2/421662a0 炸过续作初始化,本族续作无 oracle。
  6. C=同日两次 —— 只有字符化测试,无独立 oracle(字符化=锁定现状,不证正确)。
  7. E=缺价/取价日边界 —— 66a97e03 只修了取价跳过,缺价分支行为未钉。

7. 补盖执行顺序

  1. 先铺守恒不变量(免 oracle,全格便宜):部分平仓后"期初=平掉+剩余"逐日守恒;全平后持仓=0; 复利重置日动态本金=前段本金+利息;多次平仓 closePercent 连乘=累计比例。
  2. 空洞 1/2 优先:按 §2-G 四投影补 EOD平仓后收盘 × 部分 用例,oracle 用确认书公式 Excel 模板。
  3. 空洞 6 补独立 oracle(确认书公式),替换字符化地位(保留字符化作回归钉)。
  4. 每格期望值来源分级(已升级,见 §8a):契约公式独立参考实现 > 生产已对账数字 > 业务签认 Excel > 新旧影子对比;禁止当前代码输出充当 oracle
  5. 契约参考实现(§8a 公式)已落地(UnitTestProject/Modules/SwapModule/Accrual/ContractReferenceCalc.cs, 独立于生产引擎,禁止引用计息类防同源),引擎对照首批 3 例全绿(mode9/mode2 × "10" × 部分30%, ContractReferenceOracleTest)。后续补格直接复用:期望值 = ClosedInterest(平掉额, ReferenceRateAbsolute(...))。 待办:变利率引擎侧对照(取价日 E 维)、确认书生成器参数同源断言(swap_position)。

8. 生产参数(已确认,2026-08)

  • 重置频率 = 7 天(确认书:"重置频率每【周】";完整重置期 di=7 天)
  • 年化基数 = 365(确认书:"计息基准 A/365",固定利率公式同除 365)
  • 生产只有这一种组合,无 360/其他重置频率。现有测试参数 ResetPeriod=7 / AnnualDays=365 即为生产主力参数,格子按此定格

8a. 契约 oracle(确认书公式原文)

模板:Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/*.docx(看多/看空 × 现券/债券ETF 共 4 份,计息条款一致); 变量替换:Plugins/YLErp.Plugins.GuoLian/DocumentGenerator/TradeConfirmationGenerator.cs (重置频率=interest_rest_days天利差=InterestRateDefault×10000bp,与计息引擎同源 swap_position 字段)。

浮动利率复利公式(本族契约正文):

参考利率(绝对) = ∏[i=1..k] ( 1 + (FR007i + 利差) × di / 365 )  1
  • k = 计息期包含的重置期个数;di = 第 i 个基准利率适用的日历日数,完整重置期 di=7,末段不足 7 按实际日历日(测试必须盖非整周期:如持有 17 天 = 2×7+3)
  • 利率确定日 = 每个重置期首日(重置日)的上一个营业日,取该日 FR007;营业日准则=上一营业日(→ E 维度取值锚点,与 66a97e03 修复直接对应)
  • FR007 取中国货币网每日公布值

计息期定义(= 算头不算尾的契约原文):自起始日(含)至到期日(不含)的自然日天数。 ⚠ 债券ETF 模板变体:计息期自期初观察日(含)至期末观察日(不含)——观察日→代码日期字段的映射需单独核实,是一个潜在口径分叉点。

重置期定义:每个重置期自上一重置日(含)至下一重置日(不含);首个重置期始于计息期首日;最后一个重置期的最后一日为计息期最后一日(末段收口)。重置日从计息期首日按重置频率依次推算。

固定利率公式:参考利率(绝对) = 固定利率 × 计息期 / 365。 期初预付金利息:支付日(含)至到期日()×利率/计息基准——注意预付金契约上是"含尾"的,与利率腿"不含尾"相反。

oracle 使用方式(升级 §7):最强形式是按契约公式写独立参考实现(约 20 行:重置日推算 + 分段取价 + ∏ 公式 + 末段收口),作为测试 oracle 与生产引擎对照,容差 0.01。它比逐格 Excel 手算更便宜且零同源风险;Excel 模板退化为抽样校验参考实现本身。

9. 合入规则(硬约束)

  1. 计息类 fix:先失败测试,后修代码;测试须登记本矩阵坐标。
  2. 修一格必须扫同矩阵行兄弟格子(同 fix 家族的邻格)。
  3. 任何触碰 GetInterests/CalcUnwindInterest/SaveAutoEodWithCloseInterestPosition 的 PR: 跑 DealInterestsGoldenReplayTest 全量 + 保证金黄金回放(防共享管线殃及)。
  4. 登记 fix 时发现同格已有用例而 bug 仍发生 → 先修断言投影,再修代码。
  5. oracle 用例与裁决材料一律取 §8 生产参数(7 天重置 / A365 / 真实点差 ±0.25%·−2.10% / 千万级名义本金,如 5000 万)。玩具参数(千元级/重置 3 天/点差 1%)仅限字符化钉子测试—— 其用途是锁行为防漂移,不承担"证明数字正确"职责;用玩具数字做裁决依据会掩盖金额量级 (0.03 vs 0.06 看着"不大",同参数放大到生产即 7.6 万 vs 25 万/笔)。