fix(预付金返回/平仓比例): 恢复占期初语义并在后端入口统一转占剩余
之前提交 4f46e263 误将平仓比例改为占剩余持仓(Definition B)语义,与需求不符。
正确需求:每次打开平仓/提前终止均基于最开始原始名义本金(Definition A),
但每次返回的预付金金额需正确(后端按占剩余计算)。
- SwapDealService: 新增 ToRemainingClosePercent/ToOriginalClosePercent 双语义转换;
SwapUnwind 入口把前端传来的占期初(A)转为占剩余(B),全计算链公式不动;
SaveSwapDealInternal 序列化前还原为 A 落库,事件列表读取即显示占期初比例。
- SwapTrade2Controller.GetUnwindInterestList: 接收期初/剩余名义本金,预览利息按 B 计算。
- unwindSwapTrade.js: 回退为占期初语义(ClosePercent/平仓名义本金用 NotionalValue,
oriClosePercent=剩余/期初),提前终止同理。
- 单测 UW_007/008 覆盖 A→B 全平/部分平仓判定。
不影响收盘后盯市/估值(仅平仓入口与展示口径)。
This commit is contained in:
@@ -187,5 +187,55 @@ namespace YLErp.Modules.SwapModule
|
||||
"SwapRealizedPnL 应=SwapCloseAmount(6000)");
|
||||
Console.WriteLine($"UW_006: CloseReCheck={service.CloseReCheckCallCount}次, SwapRealizedPnL={service.SaveSwapDealCalls[0].data.SwapRealizedPnL} ✅");
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 场景7:前端传"占期初(A)"语义,后端入口转"占剩余(B)" —— 全平判定
|
||||
// 原始名义本金 100M / 剩余 60M,前端传 A=0.6(平掉原始 60M = 剩余全部)
|
||||
// B = A × Notional/Posi = 0.6 × 100/60 = 1.0 → 触发全平
|
||||
// ================================================================
|
||||
[TestMethod]
|
||||
public void UW_007_SwapUnwind_占期初A转占剩余B_全平判定正确()
|
||||
{
|
||||
var td = SwapDealTestFactory.CreateTrade();
|
||||
var service = new TestableSwapDealService(td);
|
||||
var unwindData = SwapDealTestFactory.CreateUnwindData(
|
||||
swapRealizedPnL: 0m, closeMethod: (int)CloseMethodEnum.全部平仓, closePercent: 0.6m,
|
||||
closeQty: 600000m, closeNotionalValue: 600000m, positionQty: 600000m);
|
||||
unwindData.NotionalValue = 1000000m; // 期初名义本金
|
||||
unwindData.PosiNotionalValue = 600000m; // 剩余名义本金
|
||||
|
||||
service.SwapUnwind(unwindData);
|
||||
|
||||
// 桩 SaveSwapDeal 收集的是转换后的 B(落库 A 还原在生产 SaveSwapDealInternal 中,桩跳过)
|
||||
Assert.AreEqual(1.0m, service.SaveSwapDealCalls[0].data.ClosePercent, 0.0001m,
|
||||
"入口 A=0.6 应转为 B=1.0(占剩余全平)");
|
||||
Assert.AreEqual("已平仓", td.TradeStatus, "B==1 触发全平 TradeStatus=已平仓");
|
||||
Console.WriteLine($"UW_007: A=0.6→B={service.SaveSwapDealCalls[0].data.ClosePercent}, TradeStatus={td.TradeStatus} ✅");
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 场景8:占期初(A)转占剩余(B) —— 部分平仓
|
||||
// 原始 100M / 剩余 60M,前端传 A=0.3(平掉原始 30M = 剩余的 50%)
|
||||
// B = A × Notional/Posi = 0.3 × 100/60 = 0.5 → 部分平仓
|
||||
// ================================================================
|
||||
[TestMethod]
|
||||
public void UW_008_SwapUnwind_占期初A转占剩余B_部分平仓正确()
|
||||
{
|
||||
var td = SwapDealTestFactory.CreateTrade();
|
||||
var service = new TestableSwapDealService(td);
|
||||
var unwindData = SwapDealTestFactory.CreateUnwindData(
|
||||
swapRealizedPnL: 0m, closeMethod: (int)CloseMethodEnum.部分平仓, closePercent: 0.3m,
|
||||
closeQty: 300000m, closeNotionalValue: 300000m, positionQty: 600000m);
|
||||
unwindData.NotionalValue = 1000000m; // 期初名义本金
|
||||
unwindData.PosiNotionalValue = 600000m; // 剩余名义本金
|
||||
|
||||
service.SwapUnwind(unwindData);
|
||||
|
||||
Assert.AreEqual(0.5m, service.SaveSwapDealCalls[0].data.ClosePercent, 0.0001m,
|
||||
"入口 A=0.3 应转为 B=0.5(占剩余 50%)");
|
||||
Assert.AreEqual(1, td.HasPartialUnWind, "B≠1 应为部分平仓,设 HasPartialUnWind=1");
|
||||
Assert.AreEqual("确认成交", td.TradeStatus, "部分平仓 TradeStatus 保持不变");
|
||||
Console.WriteLine($"UW_008: A=0.3→B={service.SaveSwapDealCalls[0].data.ClosePercent}, HasPartialUnWind={td.HasPartialUnWind} ✅");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user