using YLErp.DBModels; namespace YLErp.Modules.SwapModule.Margin; /// /// 保证金计算工具。从 SwapDealService 剥离的保证金纯函数。 /// public static class MarginCalc { /// /// 取上一日终保证金余额。 /// /// 三级优先级(均有测试覆盖,不可简化): /// 1. InterestPrincipalFix——EOD 归档赋值时的首选字段 /// 2. TdInterestPrincipal——部分 EOD 归档路径未写 InterestPrincipalFix(值为0), /// 此时 TdInterestPrincipal 含正确的保证金本金(生产 eod_swap_position(35774) 即此场景) /// 3. fallback——首次平仓(preEod.id==0, 无归档)时用当日保证金余额 /// public static decimal PreviousBalance(eod_swap_position preEod, decimal fallback) { var previous = preEod.InterestPrincipalFix != 0m ? preEod.InterestPrincipalFix : preEod.TdInterestPrincipal; return preEod.id != 0 && previous != 0m ? previous : fallback; } /// /// 保证金方向翻转。保证金利息是券商付给客户(方向与融资腿相反)。 /// public static int FlipDirection(int direction) => direction == (int)SwapDirectionEnum.收取 ? (int)SwapDirectionEnum.支付 : (int)SwapDirectionEnum.收取; /// /// 汇总保证金腿的平仓返还金额(SwapMarginAmount)和保证金返息(SwapMarginRebatePnl)。 /// 保证金方向与融资腿相反:interestRatio = InterestDirection==1 ? -1 : 1。 /// public static void AccumulateSettlement(List interestList, UnwindData unwindData) { foreach (var x in interestList) { if (!MarginModes.Contains(x.InterestMode)) continue; var interestRatio = x.InterestDirection == 1 ? -1m : 1m; unwindData.SwapMarginRebatePnl += x.InterestClosePnL; unwindData.SwapMarginAmount += x.InterestPrincipal * interestRatio; } } }