diff --git a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
index d4b14f00..ead71307 100644
--- a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
+++ b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
@@ -2168,8 +2168,6 @@ namespace YLErp.Modules.SwapModule
var positions = eodSwapPositions.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode)).ToList();//持仓腿
// 框架合约的方向约定:多头为正、空头为负;总名义本金取交易原始规模,
// 不能直接用多空腿相加,否则会把对冲方向误当成合约规模变化。
- eod_Swap.NotionalValueLong = Math.Round(positions.Where(x => x.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.PosiNotionalValue), ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
- eod_Swap.NotionalValueShort = Math.Round(-Math.Abs(positions.Where(x => x.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.PosiNotionalValue)), ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
eod_Swap.NotionalValue = Math.Round(Convert.ToDecimal(td.OriginalStockEqvNotional ?? td.StockEqvNotional), ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
eod_Swap.SwapTradeId = td.id;
eod_Swap.SwapTradeNo = td.TradeNumber;
@@ -2177,19 +2175,8 @@ namespace YLErp.Modules.SwapModule
eod_Swap.BookId = td.AssetId;
eod_Swap.ValueDate = settleDate;
eod_Swap.StructureType = td.StructureType;
- eod_Swap.MarketValueLong = positions.Where(x => x.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.UnderlyingMarketValue);
- eod_Swap.MarketValueShort = positions.Where(x => x.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.UnderlyingMarketValue);
- eod_Swap.FloatingPnL = positions.Sum(s => s.PosiProfitSum);
- eod_Swap.dv01 = positions.Sum(s => s.dv01 ?? 0);
- decimal interestPnL = 0;
- // 利息腿按我方视角归集。保证金腿的利息现金流方向与普通利息腿相反,
- // 因此保证金腿需要额外反转符号,确保 InterestPnL 表示我方的合约利率端收益。
- interestPositions.ForEach(x =>
- {
- var ratio = DirectionRatio.InterestLegPnl(x.InterestDirection, x.InterestMode);
- interestPnL += x.InterestProfitSum * ratio;
- });
- eod_Swap.InterestPnL = interestPnL;
+ FillPositionLegSummary(eod_Swap, positions);
+ eod_Swap.InterestPnL = SumInterestPnL(interestPositions);
eod_Swap.PostionValue = eodSwapPositions.Sum(s => s.SwapPositionValue);
// 保证金腿的利息现金流方向与保证金本金方向相反。
// 不能直接汇总 RealizedPnl,否则“收取客户保证金”的腿会把应支付给客户的
@@ -2242,17 +2229,8 @@ namespace YLErp.Modules.SwapModule
var interestPositions = eodSwapPositions.Where(x => string.IsNullOrEmpty(x.UnderlyingCode)).ToList();//利息腿
var positions = eodSwapPositions.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode)).ToList();//持仓腿
eod_Swap.NotionalValue = Math.Round(Convert.ToDecimal(td.OriginalStockEqvNotional ?? td.StockEqvNotional), ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
- eod_Swap.NotionalValueLong = Math.Round(positions.Where(x => x.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.PosiNotionalValue), ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
- eod_Swap.NotionalValueShort = Math.Round(-Math.Abs(positions.Where(x => x.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.PosiNotionalValue)), ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
- eod_Swap.MarketValueLong = positions.Where(x => x.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.UnderlyingMarketValue);
- eod_Swap.MarketValueShort = positions.Where(x => x.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.UnderlyingMarketValue);
- eod_Swap.FloatingPnL = positions.Sum(s => s.PosiProfitSum);
- eod_Swap.dv01 = positions.Sum(s => s.dv01 ?? 0);
- interestPositions.ForEach(x =>
- {
- var ratio = DirectionRatio.InterestLegPnl(x.InterestDirection, x.InterestMode);
- eod_Swap.InterestPnL += x.InterestProfitSum * ratio;
- });
+ FillPositionLegSummary(eod_Swap, positions);
+ eod_Swap.InterestPnL += SumInterestPnL(interestPositions);
eodSwapPositions.ForEach(x =>
{
var ratio = DirectionRatio.InterestLegPnl(x.InterestDirection, x.InterestMode);
@@ -2260,7 +2238,6 @@ namespace YLErp.Modules.SwapModule
});
eod_Swap.PostionValue = eodSwapPositions.Sum(s => s.SwapPositionValue);
eod_Swap.RealizedPnL = eodSwapPositions.Sum(CalculateSwapRealizedPnl);
- eod_Swap.TdCloseQty = positions.Sum(s => s.TdCloseQty);
var tradeInitMarginObj = DbContext.trade_initial_margin.FirstOrDefault(x => x.TradeId == td.id);
var initMarginList = interestPositions.Where(x => x.InterestMode == (int)InterestModeEnum.初始预付金 && x.HappenDate == settleDate).ToList();
var addMarginList = interestPositions.Where(x => x.InterestMode == (int)InterestModeEnum.追加预付金 && x.HappenDate == settleDate).ToList();
@@ -2290,6 +2267,28 @@ namespace YLErp.Modules.SwapModule
+ position.RealizedInterestFee;
}
+ /// 填充框架合约的持仓腿汇总字段(多空名义本金/市值/浮动盈亏/dv01/平仓量)。
+ /// SaveEodSwap 与 UpdateEodSwap 共用,消除 ~10 行重复。
+ private static void FillPositionLegSummary(eod_swap eod_Swap, List positions)
+ {
+ eod_Swap.NotionalValueLong = Math.Round(positions.Where(x => x.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.PosiNotionalValue), ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
+ eod_Swap.NotionalValueShort = Math.Round(-Math.Abs(positions.Where(x => x.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.PosiNotionalValue)), ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
+ eod_Swap.MarketValueLong = positions.Where(x => x.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.UnderlyingMarketValue);
+ eod_Swap.MarketValueShort = positions.Where(x => x.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.UnderlyingMarketValue);
+ eod_Swap.FloatingPnL = positions.Sum(s => s.PosiProfitSum);
+ eod_Swap.dv01 = positions.Sum(s => s.dv01 ?? 0);
+ eod_Swap.TdCloseQty = positions.Sum(s => s.TdCloseQty);
+ }
+
+ /// 利息腿 PnL 汇总(按方向比例 + 保证金翻转)。原 SaveEodSwap/UpdateEodSwap 各一段 ForEach。
+ private static decimal SumInterestPnL(List interestPositions)
+ {
+ decimal interestPnL = 0;
+ foreach (var x in interestPositions)
+ interestPnL += x.InterestProfitSum * DirectionRatio.InterestLegPnl(x.InterestDirection, x.InterestMode);
+ return interestPnL;
+ }
+
///
/// 风险报表符号归一化:把历史两种符号口径的 TdCloseInterest/RealizedInterest
/// 统一按"绝对金额 × 业务方向"重写。普通利息腿收取为正、支付为负;