fix(swap): 解决互换平仓时保证金返息重复计算问题

- 添加保证金返息去重机制,防止平仓时返息被重复计入资金记录
- 新增 GetMainCashRealizedPnL 方法专门处理返息剔除逻辑
- 更新 DealUnwind 和 ApproveSwapTrade 方法使用统一的返息处理口径
- 修改 ReleaseMarginByFundTag 方法增强标签分流功能
- 添加多个单元测试验证返息处理的正确性
- 将 SaveAllChanges 设为可测试化接缝便于测试验证
- 调整 FundTag 分流逻辑支持授信和现金腿分别处理
This commit is contained in:
张名锐
2026-08-27 16:13:59 +08:00
parent 679117f82a
commit d2b6dff598
4 changed files with 351 additions and 9 deletions
@@ -83,6 +83,19 @@ namespace YLErp.Modules.SwapModule
public bool RestoreEffectiveFundPositionForTest(UnwindData unwindData, DateTime valueDate)
=> TryRestoreAndValidateUnwindData(unwindData, valueDate);
public void DealUnwindForTest(UnwindData unwindData, string actionMsg = "系统操作_自动平仓")
=> DealUnwind(unwindData, _trade, actionMsg);
/// <summary>
/// FundTag 分流 stub 的可配置返回值:非 null 时直接返回(模拟授信/现金腿拆分,
/// 见 UW_003B);null 时保持旧行为——传入金额全额现金
/// CashMargin=marginAmount, CashRebate=marginRebate),等价于"全现金/无标签"场景。
/// </summary>
public UnwindTagSplit ReleaseMarginByFundTagResult { get; set; }
/// <summary>保留已忽略的历史互换场景测试所需的兼容属性。</summary>
public List<bool> ReleaseMarginPrincipalFlags { get; } = new();
protected override int AddClientCash(trade td, double amount, string action, DateTime valueDate)
{
ClientCashCalls.Add((amount, action, valueDate));
@@ -114,10 +127,26 @@ namespace YLErp.Modules.SwapModule
CloseReCheckCallCount++;
}
// R4 按标签分流释放:纯内存测试不连库,stub 为全现金(与既有断言语义一致)
// R4 按标签分流释放:纯内存测试不连库(生产 GetSettlements 查 swap_position 标签),
// 默认 stub 为全现金(与既有断言语义一致);ReleaseMarginByFundTagResult 非 null 时
// 返回它以模拟授信/现金拆分。
protected override UnwindTagSplit ReleaseMarginByFundTag(trade td, DateTime valueDate, List<swap_flow_event> interestEvents,
decimal marginAmount, decimal marginRebate)
=> new UnwindTagSplit { CashMargin = Convert.ToDouble(marginAmount), CashRebate = Convert.ToDouble(marginRebate) };
{
var marginLegs = interestEvents
.Where(x => string.IsNullOrEmpty(x.UnderlyingCode)
&& (x.InterestMode == (int)InterestModeEnum.
|| x.InterestMode == (int)InterestModeEnum.))
.ToList();
return ReleaseMarginByFundTagResult
?? new UnwindTagSplit
{
CashMargin = Convert.ToDouble(marginAmount),
CashRebate = Convert.ToDouble(marginLegs.Any()
? marginLegs.Sum(x => x.InterestClosePnL)
: marginRebate)
};
}
protected override void SaveAllChanges() { SaveAllChangesCount++; }
protected override void ExecuteInTransaction(Action action) => action(); // 不包事务,直接执行