Files
zszq-trs/UnitTestProject/Modules/SwapModule/InitUnwindDefaultClosePercentTest.cs
hjhan 43679393bb test(swap): 补 e2fb456b InitUnwind 默认 ClosePercent 单元测试
抽 CalcDefaultInitClosePercent 静态纯函数(PosiNotionalValue/NotionalValue), InitUnwind L270 改为调用此函数, 新增 6 个单元测试覆盖: 未平仓/已平30%/除零保护/GLMS-20260701-0013 真实快照/与 ToRemainingClosePercent 联动自洽不变式/全平完边界场景. 填补 e2fb456b 提交的测试覆盖缺口.
2026-07-17 08:23:50 +08:00

104 lines
5.5 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
namespace YLErp.Modules.SwapModule
{
/// <summary>
/// InitUnwind 默认 ClosePercent 计算的回归测试。
/// ---------------------------------------------------------------
/// 守卫提交 e2fb456b "fix 平仓(InitUnwind L267)硬编码 1 而不是剩余平仓比例"。
///
/// 旧 bugInitUnwind 默认把 ClosePercent 硬编码为 1(按"占剩余 100%"),
/// 但前端约定 ClosePercent 是"占期初(original)"口径(A)1 表示平掉原始本金的 100%。
/// 多次部分平仓后剩余本金 < 期初本金,此时默认 1 在前端语义上意味着"还要平掉原始全部",
/// 与"平掉剩余全部"意图不符,且会触发后端 ToRemainingClosePercent 转换后 >1 被 cap 到 1
/// 表面看无差异但语义混乱,且若前端 / 事件展示直接用此值会出错。
///
/// 修复:ClosePercent = PosiNotionalValue / NotionalValue(占期初口径的"平剩余全部")。
/// 抽出为纯函数 CalcDefaultInitClosePercent 以支持无库单测。
/// </summary>
[TestClass]
public class InitUnwindDefaultClosePercentTest
{
// ================================================================
// 场景1:未平仓 PosiNotionalValue == NotionalValue → ClosePercent = 1
// ================================================================
[TestMethod]
public void 未平仓_剩余等于期初_默认ClosePercent为1()
{
var result = SwapDealService.CalcDefaultInitClosePercent(
notionalValue: 1_000_000m, posiNotionalValue: 1_000_000m);
Assert.AreEqual(1m, result, "未平仓:默认应平 100%(占期初)");
}
// ================================================================
// 场景2:已平 30%(剩 70%)→ ClosePercent = 0.7
// ================================================================
[TestMethod]
public void 已平30_70_默认ClosePercent为0_7()
{
var result = SwapDealService.CalcDefaultInitClosePercent(
notionalValue: 1_000_000m, posiNotionalValue: 700_000m);
Assert.AreEqual(0.7m, result, 0.0001m, "已平 30% 剩 70%:默认 ClosePercent=0.7(占期初)");
}
// ================================================================
// 场景3:除零保护 NotionalValue = 0 → 返回 1(容错)
// ================================================================
[TestMethod]
public void 期初名义本金为零_返回1_容错不除零()
{
var result = SwapDealService.CalcDefaultInitClosePercent(
notionalValue: 0m, posiNotionalValue: 100_000m);
Assert.AreEqual(1m, result, "期初本金为 0 时容错返回 1,不应抛除零异常");
}
// ================================================================
// 场景4GLMS-20260701-0013 真实快照(已平 2 次)
// 期初 NotionalValue = 980,000 / 剩余 PosiNotionalValue = 686,000.07
// 期望 ClosePercent ≈ 0.7686000.07/980000
// ================================================================
[TestMethod]
public void GLMS20260701_0013_已平两次_默认ClosePercent约为0_7()
{
var result = SwapDealService.CalcDefaultInitClosePercent(
notionalValue: 980_000m, posiNotionalValue: 686_000.07m);
// 686000.07 / 980000 = 0.700000071...
Assert.AreEqual(0.7m, result, 0.0001m,
"GLMS-20260701-0013 已平两次:默认 ClosePercent 应≈0.7(占期初),旧 bug 会硬编码 1");
}
// ================================================================
// 场景5:与 ToRemainingClosePercent 联动验证
// 前端拿 InitUnwind 返回的 A(占期初) 默认值,经 ToRemainingClosePercent 转 B(占剩余)
// 应恰好 = 1.0(因为"平剩余全部"在占剩余语义下就是 100%)
// ================================================================
[TestMethod]
public void 默认A经ToRemainingClosePercent转B应为1_平剩余全部()
{
const decimal notionalValue = 1_000_000m;
const decimal posiNotionalValue = 600_000m; // 已平 40%,剩 60%
var defaultA = SwapDealService.CalcDefaultInitClosePercent(notionalValue, posiNotionalValue);
var convertedB = SwapDealService.ToRemainingClosePercent(defaultA, notionalValue, posiNotionalValue);
Assert.AreEqual(0.6m, defaultA, 0.0001m, "占期初默认 A=0.6");
Assert.AreEqual(1.0m, convertedB, 0.0001m,
"A=0.6 经 ToRemainingClosePercent 转换 → B=1.0(占剩余 100% = 平剩余全部),此为占期初/占剩余双语义自洽的关键不变式");
}
// ================================================================
// 场景6:全平完(PosiNotionalValue=0)→ ClosePercent=0(边界,实际不会进 InitUnwind)
// ================================================================
[TestMethod]
public void 全平完剩余为零_ClosePercent为零()
{
var result = SwapDealService.CalcDefaultInitClosePercent(
notionalValue: 1_000_000m, posiNotionalValue: 0m);
Assert.AreEqual(0m, result, "剩余本金为 0 时 ClosePercent=0(边界场景,实际全部平完不会再进 InitUnwind");
}
}
}