using YLErp.DBModels; namespace YLErp.Modules.SwapModule; /// /// 平仓比例(ClosePercent) 数学——占期初(A) / 占剩余(B) 两种口径的转换。 /// 从 SwapDealService 提取为共享模块,两个 service 均可引用。 /// public static class ClosePercentMath { /// /// 取上一日终的浮动端名义本金(orginPv 的来源)。 /// 优先取浮动腿 PosiNotionalValue 之和,取不到用 eod_swap 多空绝对值之和,都没有用 currentNotional 兜底。 /// public static decimal ResolveUnwindPreviousNotional( eod_swap lastEod, IEnumerable lastEodPositions, decimal currentNotional) { var floatingPositions = lastEodPositions?.Where(x => x.PosiDirection > 0).ToList(); decimal previousNotional; if (floatingPositions?.Count > 0) { previousNotional = floatingPositions.Sum(x => x.PosiNotionalValue); } else { previousNotional = lastEod == null ? currentNotional : Math.Abs(lastEod.NotionalValueLong) + Math.Abs(lastEod.NotionalValueShort); } return previousNotional == 0m && currentNotional != 0m ? currentNotional : previousNotional; } /// /// A(占期初) → B(占剩余),用于把前端传入的占期初比例换算成后端计算用的占剩余比例。 /// public static decimal ToRemainingClosePercent(decimal originalClosePercent, decimal notionalValue, decimal posiNotionalValue) { if (posiNotionalValue <= 0) return originalClosePercent; var remaining = originalClosePercent * notionalValue / posiNotionalValue; return remaining > 1 ? 1 : remaining; } /// /// B(占剩余) → A(占期初),用于落库 / 事件列表展示还原。见 ToRemainingClosePercent。 /// public static decimal ToOriginalClosePercent(decimal remainingClosePercent, decimal notionalValue, decimal posiNotionalValue) { if (notionalValue <= 0) return remainingClosePercent; return remainingClosePercent * posiNotionalValue / notionalValue; } /// /// 计算 InitUnwind 默认占期初(A)平仓比例 = PosiNotionalValue / NotionalValue。 /// 未平仓时 =1(平100%);部分平仓后自动变为剩余比例。 /// public static decimal CalcDefaultInitClosePercent(decimal notionalValue, decimal posiNotionalValue) { return notionalValue > 0 ? posiNotionalValue / notionalValue : 1; } }