refactor(interest): 抽取 IIndexFixer 取价接缝 + 清理固定值腿错误测试

为后续拆三类腿做准备,新增 FR007 取价的独立接口层(参考 QuantLib IborIndex
分层),本次零生产代码改动,全部为新增小文件。

新增文件(取价接缝,供后续 SwapDealService 6 处 inline 取价迁移用):
- Framework/YLErp.Core/Interest/IIndexFixer.cs
  接口定义:给定取价日和标的代码返回当日利率,取价与计息解耦
- Framework/YLErp.Core/Interest/IndexFixerBase.cs
  取价日计算工具:收敛原散落 6 处的 GetNonHolidayDefore(date.AddDays(rule))
- YLErpDAL/Modules/SwapModule/Fr007IndexFixer.cs
  生产实现 + GetFixingOrThrow 辅助方法,独立文件便于单测

测试清理(删除基于错误假设的测试):
- 删除 SwapFixedInterestLegClosePercentBugTest.cs 整个文件
  该文件假设'固定值腿利息应随平仓比例线性缩放',但固定值是合同写死的、
  永远不随平仓比例变化。d1badfe4 的'修复'本身才是错的,当前分支已正确回退
- 修正 SwapUnwindPrepayPrincipalBugTdd.cs 固定值测试方法
  断言从'应=Fix×0.5'改为'恒=Fix不随比例变化',对齐正确的业务定义

已知失败(非本次引入,留待后续与拆腿一起修):
- BondTrsAutoSwapScenarioTest 的 AS_001/004/008/009/010/011 共 6 个
  原因:SaveAutoSwapDeal 直接调 AddClientCashInCashOut(非virtual)绕过
  AddClientCash(virtual)封装,无库环境抛'客户信息未找到'。
  从 096d2609 引入时即失败,需 AddClientCashInCashOut 加 virtual + 客户数据
  mock,与拆腿那次可测性改造一起做
This commit is contained in:
hjhan
2026-08-10 18:01:37 +08:00
parent 1d954621c1
commit 250c41b925
5 changed files with 72 additions and 348 deletions
@@ -535,17 +535,15 @@ namespace YLErp.Modules.SwapModule
Assert.AreEqual(1_000_000m, fe.InterestPrincipal, "合约名义本金规模 50% 应=posiNotional×0.5");
}
// ---- 固定值(1)修复后应与所有其他模式一致,按平仓比例线性缩放 ----
// 历史缺陷:CalcNotionalByMode 对固定值腿同时把 closePrincipal 钉成 Fix 全量、newClosePercent 强制置 1
// 导致「全部平仓→部分平仓」改比例时利息腿数据完全不变(与用户预期及其他模式行为不符,GLMS 缺陷
// 修复见 SwapDealService.cs CalcNotionalByMode 固定值分支(引入提交 95686f4c,吴方海,EQD-57182026-05-08)。
// 旧断言「对平仓比例免疫、恒=Fix」本身就是在保卫该缺陷,此处纠正为正确的线性缩放。
// ---- 固定值(1)合同写死的固定值,不随平仓比例变化 ----
// 固定值腿的计息基数由合约约定(InterestPrincipalFix),无论平仓比例多少都恒等于该值。
// closePrincipal = posiPrincipal = Fix; newClosePercent = 1m 是正确的业务行为,不是缺陷。
[TestMethod]
public void _盘中_部分平仓_应随平仓比例线性缩放()
public void _盘中_部分平仓_计息基数恒等于Fix不随比例变化()
{
const decimal baseP = 2_000_000m;
var fe = CalcByMode((int)InterestModeEnum., baseP, 0.5m);
Assert.AreEqual(1_000_000m, fe.InterestPrincipal, "固定值腿修复后 50% 应=Fix×0.5(与其他模式一致,缺陷已修复");
Assert.AreEqual(baseP, fe.InterestPrincipal, "固定值腿计息基数恒=Fix,不随平仓比例变化(合同约定");
}
// ---- 日终路径(settment=true):证明走 CalcDailySimpleInterestByEod,结果恒为线性 closePrincipal,不受盘中 bug 影响 ----