fix(swap): 单利路径扣除历史已结利息consumedInterest

复利路径已由c6adb3bb修复(加consumedInterest扣除),单利路径
CalcDailySimpleInterest未同步。互换结清后再平仓默认值偏大。

改动(SwapDealService.cs 3处):
- cs:437 去掉InterestType==复利条件,单利也取GetConsumedInterest
- cs:707 单利调用传入consumedInterest参数
- cs:802/856 CalcDailySimpleInterest签名加consumedInterest+末尾扣除

验证(Step1_SimpleInterestRedTest): 1813单利样本
34203偏大量8271→0, 34204预付金偏大量58→0(修正测试口径漏乘ratio)
复利回归(1889): 6-30默认值仍6.44无退化
This commit is contained in:
hjhan
2026-07-01 13:02:15 +08:00
parent 3118c44365
commit 1eb791381a
2 changed files with 23 additions and 16 deletions
@@ -231,7 +231,7 @@ namespace YLErp.Modules.SwapModule
// 4. 对每个单利腿,对比"默认值"vs"应计基数(待实现-已结利息)"
Console.WriteLine($"\n[3] 单利路径诊断:默认值 vs 应计基数");
Console.WriteLine($" {"PositionId",10} {"InterestMode",14} {"",14} {"eod待实现IPS",14} {"CI",14} {"(IPS-CI)",14} {"",14} {"",6}");
Console.WriteLine($" {"PositionId",10} {"InterestMode",14} {"",6} {"ClosePnL",14} {"InterestAmt",14} {"eod待实现IPS",14} {"CI",14} {"ratio",6} {"(IPS-CI)",14} {"",14} {"",6}");
int redCount = 0;
foreach (var d in defaults.Where(x => x.InterestDirection > 0))
@@ -248,31 +248,36 @@ namespace YLErp.Modules.SwapModule
// 历史已结利息(复利路径用的 GetConsumedInterest,单利路径没用)
decimal ci = service.GetConsumedInterest(tradeId, d.PositionId, testDate);
// 应计基数 = 待实现 - 已结(这才是正确的"未实现利息"
decimal expected = ips - ci;
// InterestClosePnL = InterestAmount × interestRatio(方向系数
// interestRatio = InterestDirection==收取(1) ? 1 : -1
decimal interestRatio = d.InterestDirection == (int)SwapDirectionEnum. ? 1m : -1m;
// 应计基数 = (待实现 - 已结) × ratio(与 InterestClosePnL 同口径)
decimal expected = (ips - ci) * interestRatio;
decimal actual = d.InterestClosePnL;
decimal diff = actual - expected;
bool isRed = Math.Abs(ci) > 0.01m && Math.Abs(diff) > Math.Abs(ci) * 0.5m;
if (isRed) redCount++;
string modeName = ((InterestModeEnum)d.InterestMode).ToString();
Console.WriteLine($" {d.PositionId,10} {modeName,14} {actual,14:F4} {ips,14:F4} {ci,14:F4} {expected,14:F4} {diff,14:F4} {(isRed ? "" : "绿"),6}");
string dirName = ((SwapDirectionEnum)d.InterestDirection).ToString();
Console.WriteLine($" {d.PositionId,10} {modeName,14} {dirName,6} {actual,14:F4} {d.InterestAmount,14:F4} {ips,14:F4} {ci,14:F4} {interestRatio,6} {expected,14:F4} {diff,14:F4} {(isRed ? "" : "绿"),6}");
}
Console.WriteLine($"\n[结论]");
if (redCount > 0)
{
Console.WriteLine($" ⚠ 坐实单利路径 bug{redCount} 条单利腿默认值偏大(含历史已结利息。");
Console.WriteLine($" 根因:CalcDailySimpleInterest(cs:802) 未加 consumedInterest 扣除(复利 cs:793 已加)。");
Console.WriteLine($" ⚠ 单利路径仍存在偏大{redCount} 条单利腿默认值含历史已结利息。");
Console.WriteLine($" 根因:CalcDailySimpleInterest 未加 consumedInterest 扣除。");
}
else
{
Console.WriteLine($" 单利路径未检测到偏大(可能已修或样本无历史互换)。");
Console.WriteLine($" 单利路径已修复:默认值正确扣除历史已结利息,无偏大。");
}
// 灯断言:单利路径存在偏大
Assert.IsTrue(redCount > 0,
"红灯:单利路径应存在默认值偏大(含历史已结利息)。修复后此断言应反转。");
// 绿灯断言(修复后):单利路径不应再存在偏大
Assert.AreEqual(0, redCount,
$"绿灯:单利路径默认值应正确扣除历史已结利息(consumedInterest)" +
$"但仍有 {redCount} 条腿偏大。");
}
finally
{