refactor(swap): 合并多空名义本金参数为单一 posiTotalNotional 并加固测试

- DealInterests 的 posiLongNotionalValue + posiShortNotionalValue 合并为 posiTotalNotional(调用点以 posiLongNotional+posiShortNotional 求和传入),净减一个参数

- SwapDealService / SwapEodPositionService / InterestCalcRequest 同步收敛多空死管道参数

- 19 个测试调用点适配新签名

- SwapEodPositionServiceIntegrationTest 参数计数断言由裸数字改为参数名集合断言(CollectionAssert.AreEquivalent,对增删/重排/改名敏感)
This commit is contained in:
hjhan
2026-08-14 17:30:46 +08:00
parent fdf6357c4f
commit ef37c8e71d
23 changed files with 116 additions and 120 deletions
@@ -145,7 +145,7 @@ namespace YLErp.Modules.SwapModule
protected override List<swap_flow_event> CalcSwapInterests(
trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue,
decimal posiNotionalValue,
decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose,
decimal orginPv, bool add = false, bool settment = true, bool newCalcLast = false,
List<swap_flow_event> closeList = null)
@@ -125,7 +125,7 @@ namespace YLErp.Modules.SwapModule
var position = CreateCompoundPosition();
var interests = service.GetInterests(td, td.trade_extend, unwindDate, unwindDate,
new List<eod_swap_position>(), new List<swap_position> { position },
Principal, Principal, Principal, Principal, closePercent,
Principal, Principal, closePercent,
(int)SwapEventTypeEnum., false, Principal,
add: false, settment: false, newCalcLast: false);
Assert.AreEqual(1, interests.Count);
@@ -356,7 +356,7 @@ namespace YLErp.Modules.SwapModule
var interests = ServiceByDate().GetInterests(td, td.trade_extend, unwindDate, unwindDate,
new List<eod_swap_position>(), new List<swap_position> { position },
Principal, Principal, Principal, Principal, 1m,
Principal, Principal, 1m,
(int)SwapEventTypeEnum., false, Principal,
add: false, settment: false, newCalcLast: false);
@@ -420,7 +420,7 @@ namespace YLErp.Modules.SwapModule
var result = service.GetInterests(td, td.trade_extend, resetDate, resetDate,
new List<eod_swap_position> { preEod }, new List<swap_position> { position },
remainingPrincipal, remainingPrincipal, 0m, remainingPrincipal, 1m,
remainingPrincipal, remainingPrincipal, 1m,
(int)SwapEventTypeEnum., true, remainingPrincipal,
add: false, settment: false, newCalcLast: false).Single();
@@ -466,7 +466,7 @@ namespace YLErp.Modules.SwapModule
var result = service.GetInterests(td, td.trade_extend, unwindDate, unwindDate,
new List<eod_swap_position> { preEod }, new List<swap_position> { position },
remainingPrincipal, remainingPrincipal, 0m, remainingPrincipal, 1m,
remainingPrincipal, remainingPrincipal, 1m,
(int)SwapEventTypeEnum., false, remainingPrincipal,
add: false, settment: false, newCalcLast: false).Single();
@@ -47,7 +47,7 @@ namespace YLErp.Modules.SwapModule
{
DealInterests(interestList, eodPositions, new List<eod_swap_position>(),
settleDate, td, new List<swap_flow_event>(), new List<swap_flow_event>(), null,
posiLongNational, 0m, 0m, grossPrice, orginPv);
posiLongNational + 0m, 0m, grossPrice, orginPv);
}
}
@@ -63,7 +63,7 @@ namespace YLErp.Modules.SwapModule
trade td, trade_extend tradeExtend,
DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue,
decimal posiNotionalValue,
decimal closePosiNotionalValue, decimal closePrecent,
int eventType, bool tdClose,
decimal orginPv,
@@ -77,7 +77,7 @@ namespace YLErp.Modules.SwapModule
}
return (DealService ?? new SwapDealService(this)).GetInterests(td, tradeExtend, valueDate, unwindDate,
eodPositions, positions, posiNotionalValue, posiLongNotionalValue, posiShortNotionalValue,
eodPositions, positions, posiNotionalValue,
closePosiNotionalValue, closePrecent, eventType, tdClose,
orginPv, add, settment, newCalcLast, closeList);
}
@@ -99,7 +99,7 @@ namespace YLErp.Modules.SwapModule
decimal orginPv = DealInterestsScenarioTest.Principal)
{
SaveAutoEodInterestPosition(eodPayPosition, null, position, td, valueDate, interval,
lastEodSwap, posiLongNotional, 0m, 1m, orginPv);
lastEodSwap, posiLongNotional + 0m, 1m, orginPv);
return PersistedPositions.LastOrDefault();
}
@@ -110,7 +110,7 @@ namespace YLErp.Modules.SwapModule
decimal closeNotional, bool autoSwap)
{
SaveAutoEodWithCloseInterestPosition(eodPayPosition, null, position, td, valueDate, interval,
posiLongNotional, posiShortNotional, flowEvents, closeNotional, autoSwap, 1m,
posiLongNotional + posiShortNotional, flowEvents, closeNotional, autoSwap, 1m,
DealInterestsScenarioTest.Principal);
return PersistedPositions.LastOrDefault();
}
@@ -121,7 +121,7 @@ namespace YLErp.Modules.SwapModule
decimal grossPrice, decimal orginPv)
{
SaveEodInterestPositionCopy(eodPayPosition, null, valueDate, td, position, null,
false, posiLongNotional, posiShortNotional, grossPrice, orginPv);
false, posiLongNotional + posiShortNotional, grossPrice, orginPv);
return PersistedPositions.LastOrDefault();
}
@@ -134,7 +134,7 @@ namespace YLErp.Modules.SwapModule
{
DealInterests(interestList, eodPositions, new List<eod_swap_position>(),
settleDate, td, flowEvents, new List<swap_flow_event>(), null,
posiLongNational, posiShortNational, closeNational, grossPrice, orginPv);
posiLongNational + posiShortNational, closeNational, grossPrice, orginPv);
}
}
@@ -1229,7 +1229,7 @@ namespace YLErp.Modules.SwapModule
var result = new SwapDealService(service).GetInterests(
td, td.trade_extend, closeDate, closeDate,
new List<eod_swap_position> { previousEod }, new List<swap_position> { position },
remainingNotional, remainingNotional, 0m, remainingNotional, 1m,
remainingNotional, remainingNotional, 1m,
(int)SwapEventTypeEnum., false, orginPv,
false, settment: false, newCalcLast: false, closeList: null).Single();
@@ -1268,7 +1268,7 @@ namespace YLErp.Modules.SwapModule
var firstCloseInterest = dealService.GetInterests(
td, td.trade_extend, firstCloseDate, firstCloseDate,
new List<eod_swap_position>(), new List<swap_position> { position },
originalNotional, originalNotional, 0m, remainingNotional, 0.5m,
originalNotional, remainingNotional, 0.5m,
(int)SwapEventTypeEnum., false, originalNotional,
settment: false).Single();
var firstCloseCash = Math.Round(firstCloseInterest.InterestAmount, ConsGlobal.MoneyRound,
@@ -1286,13 +1286,13 @@ namespace YLErp.Modules.SwapModule
var replayAtPreviousEod = dealService.GetInterests(
td, td.trade_extend, firstCloseDate, firstCloseDate,
new List<eod_swap_position>(), new List<swap_position> { position },
remainingNotional, remainingNotional, 0m, remainingNotional, 1m,
remainingNotional, remainingNotional, 1m,
(int)SwapEventTypeEnum., false, originalNotional,
settment: false).Single();
var replayAtFinalClose = dealService.GetInterests(
td, td.trade_extend, finalCloseDate, finalCloseDate,
new List<eod_swap_position>(), new List<swap_position> { position },
remainingNotional, remainingNotional, 0m, remainingNotional, 1m,
remainingNotional, remainingNotional, 1m,
(int)SwapEventTypeEnum., false, originalNotional,
settment: false).Single();
var expectedFinalInterest = firstCloseEod.InterestIncomeSum
@@ -1306,7 +1306,7 @@ namespace YLErp.Modules.SwapModule
var finalCloseInterest = dealService.GetInterests(
td, td.trade_extend, finalCloseDate, finalCloseDate,
new List<eod_swap_position> { firstCloseEod }, new List<swap_position> { position },
remainingNotional, remainingNotional, 0m, remainingNotional, 1m,
remainingNotional, remainingNotional, 1m,
(int)SwapEventTypeEnum., false, originalNotional,
settment: false).Single();
var finalCloseCash = Math.Round(finalCloseInterest.InterestAmount, ConsGlobal.MoneyRound,
@@ -1434,7 +1434,7 @@ namespace YLErp.Modules.SwapModule
var partial = service.GetInterests(
td, td.trade_extend, partialCloseDate, partialCloseDate,
new List<eod_swap_position> { previousEod }, new List<swap_position> { position },
notional, notional, 0m, partialNotional, partialPercent,
notional, partialNotional, partialPercent,
(int)SwapEventTypeEnum., false, notional,
settment: false).Single();
AssertDecimal(84090.95m, Math.Round(partial.InterestAmount, ConsGlobal.MoneyRound,
@@ -1444,7 +1444,7 @@ namespace YLErp.Modules.SwapModule
var final = service.GetInterests(
td, td.trade_extend, maturityDate, maturityDate,
new List<eod_swap_position>(), new List<swap_position> { position },
remainingNotional, remainingNotional, 0m, remainingNotional, 1m,
remainingNotional, remainingNotional, 1m,
(int)SwapEventTypeEnum., false, remainingNotional,
settment: false, newCalcLast: true).Single();
AssertDecimal(268428.73m, Math.Round(final.InterestAmount, ConsGlobal.MoneyRound,
@@ -1575,7 +1575,7 @@ namespace YLErp.Modules.SwapModule
var intermediateInterest = dealService.GetInterests(
td, td.trade_extend, intermediateDate, intermediateDate,
new List<eod_swap_position> { partialEod }, new List<swap_position> { position },
remainingNotional, remainingNotional, 0m, remainingNotional, 1m,
remainingNotional, remainingNotional, 1m,
(int)SwapEventTypeEnum., false, originalNotional,
settment: false, newCalcLast: true).Single();
Assert.IsTrue(Math.Abs(259348.386714765m - intermediateInterest.InterestAmount) <= 0.01m,
@@ -1706,7 +1706,7 @@ namespace YLErp.Modules.SwapModule
var intermediateInterest = dealService.GetInterests(
td, td.trade_extend, intermediateDate, intermediateDate,
new List<eod_swap_position> { partialEod }, new List<swap_position> { position },
remainingNotional, remainingNotional, 0m, remainingNotional, 1m,
remainingNotional, remainingNotional, 1m,
(int)SwapEventTypeEnum., false, originalNotional,
settment: false, newCalcLast: true).Single();
Assert.IsTrue(Math.Abs(259348.386714765m - intermediateInterest.InterestAmount) <= 0.01m,
@@ -1739,7 +1739,7 @@ namespace YLErp.Modules.SwapModule
var finalInterest = dealService.GetInterests(
td, td.trade_extend, finalCloseDate, finalCloseDate,
new List<eod_swap_position> { intermediateEod }, new List<swap_position> { position },
remainingNotional, remainingNotional, 0m, remainingNotional, 1m,
remainingNotional, remainingNotional, 1m,
(int)SwapEventTypeEnum., false, originalNotional,
settment: false, newCalcLast: false).Single();
AssertDecimal(expectedFinalInterest, finalInterest.InterestAmount,
@@ -1829,7 +1829,7 @@ namespace YLErp.Modules.SwapModule
var result = dealService.GetInterests(
td, td.trade_extend, finalCloseDate, finalCloseDate,
new List<eod_swap_position> { previousEod }, new List<swap_position> { position },
remainingNotional, remainingNotional, 0m, remainingNotional, 1m,
remainingNotional, remainingNotional, 1m,
(int)SwapEventTypeEnum., false, remainingNotional,
settment: false).Single();
@@ -1927,7 +1927,7 @@ namespace YLErp.Modules.SwapModule
var partialInterest = dealService.GetInterests(
td, td.trade_extend, partialCloseDate, partialCloseDate,
new List<eod_swap_position> { preCloseEod }, new List<swap_position> { position },
originalNotional, originalNotional, 0m, partialNotional, partialClosePercent,
originalNotional, partialNotional, partialClosePercent,
(int)SwapEventTypeEnum., false, originalNotional,
settment: false).Single();
AssertExcelMoney(scenario.ExpectedPartialInterest, partialInterest.InterestAmount,
@@ -1976,7 +1976,7 @@ namespace YLErp.Modules.SwapModule
var finalInterest = dealService.GetInterests(
td, td.trade_extend, finalCloseDate, finalCloseDate,
new List<eod_swap_position> { finalPreEod }, new List<swap_position> { position },
remainingNotional, remainingNotional, 0m, remainingNotional, 1m,
remainingNotional, remainingNotional, 1m,
(int)SwapEventTypeEnum., false, remainingNotional,
settment: false).Single();
AssertExcelMoney(scenario.ExpectedFinalInterest, finalInterest.InterestAmount,
@@ -209,7 +209,7 @@ namespace YLErp.Modules.SwapModule
CloseDate, CloseDate, // valueDate / unwindDate
new List<eod_swap_position>(), // eodPositions(空)
new List<swap_position> { position },
Notional, Notional, Notional, Notional, // posiNotional / long / short / closePosiNotional
Notional, Notional, // posiNotional / closePosiNotional
1m, // closePercent
(int)SwapEventTypeEnum.,
false, Notional, // tdClose / orginPv
@@ -142,11 +142,11 @@ namespace YLErp.Modules.SwapModule
var intraday = CreateService().GetIntradayUnwindInterests(InterestCalcRequest.IntradayUnwind(
td, td.trade_extend, UnwindDate, UnwindDate, eodPositions, positions,
PreClose, PreClose, 0m, Closed, ClosePercent,
PreClose, Closed, ClosePercent,
(int)SwapEventTypeEnum., tdClose: true, orginPv: PreClose, add: true, newCalcLast: false, closeList: null));
var eodPostClose = CreateService().GetInterests(td, td.trade_extend, UnwindDate, UnwindDate,
eodPositions, positions, Remaining, Remaining, 0m, Closed, 1m,
eodPositions, positions, Remaining, Closed, 1m,
(int)SwapEventTypeEnum., tdClose: false, orginPv: PreClose,
add: true, settment: false, newCalcLast: false, closeList: null);
@@ -177,11 +177,11 @@ namespace YLErp.Modules.SwapModule
var intraday = CreateService().GetIntradayUnwindInterests(InterestCalcRequest.IntradayUnwind(
td, td.trade_extend, UnwindDate, UnwindDate, eodPositions, positions,
PreClose, PreClose, 0m, Closed, ClosePercent,
PreClose, Closed, ClosePercent,
(int)SwapEventTypeEnum., tdClose: true, orginPv: PreClose, add: true, newCalcLast: false, closeList: null));
var eodPostClose = CreateService().GetInterests(td, td.trade_extend, UnwindDate, UnwindDate,
eodPositions, positions, Remaining, Remaining, 0m, Closed, 1m,
eodPositions, positions, Remaining, Closed, 1m,
(int)SwapEventTypeEnum., tdClose: false, orginPv: PreClose,
add: true, settment: false, newCalcLast: false, closeList: null);
@@ -209,7 +209,7 @@ namespace YLErp.Modules.SwapModule
// 全平:剩余=0,平掉=全部 1000
var result = CreateService().GetInterests(td, td.trade_extend, UnwindDate, UnwindDate,
eodPositions, positions, 0m, 0m, 0m, PreClose, 1m,
eodPositions, positions, 0m, PreClose, 1m,
(int)SwapEventTypeEnum., tdClose: false, orginPv: PreClose,
add: true, settment: false, newCalcLast: false, closeList: null);
@@ -244,7 +244,7 @@ namespace YLErp.Modules.SwapModule
trade td, trade_extend tradeExtend,
DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue,
decimal posiNotionalValue,
decimal closePosiNotionalValue, decimal closePrecent,
int eventType, bool tdClose,
decimal orginPv,
@@ -282,7 +282,7 @@ namespace YLErp.Modules.SwapModule
var req = InterestCalcRequest.EodPostCloseSettle(
td, td.trade_extend, UnwindDate, UnwindDate,
new List<eod_swap_position> { preEod }, positions,
remainingNotionalAfterClose: Remaining, remainingLongNotional: Remaining, remainingShortNotional: 0m,
remainingNotionalAfterClose: Remaining,
closedNotional: Closed,
eventType: (int)SwapEventTypeEnum., tdClose: false,
orginPv: PreClose, add: true, newCalcLast: false);
@@ -228,7 +228,7 @@ namespace YLErp.Modules.SwapModule
var position = CreateFloatInterestPosition(interestRule, interestType, fixedRate);
var interests = _service.GetInterests(td, td.trade_extend, valueDate, unwindDate,
eodPositions, new List<swap_position> { position },
posiNotional, posiNotional, posiNotional, posiNotional, closePercent,
posiNotional, posiNotional, closePercent,
(int)SwapEventTypeEnum.,
false, posiNotional, false, settment: false, newCalcLast: newCalcLast, closeList: closeList);
AssertInterestEqual(1, interests.Count);
@@ -244,7 +244,7 @@ namespace YLErp.Modules.SwapModule
var position = CreateFloatInterestPosition(interestRule, interestType, fixedRate);
var interests = _service.GetInterests(td, td.trade_extend, valueDate, valueDate,
eodPositions, new List<swap_position> { position },
Principal, Principal, Principal, Principal, 1m,
Principal, Principal, 1m,
(int)SwapEventTypeEnum.,
false, Principal, false, settment: true, newCalcLast: false, closeList: closeList);
AssertInterestEqual(1, interests.Count);
@@ -263,7 +263,7 @@ namespace YLErp.Modules.SwapModule
var position = CreateFixedInterestPosition(fixedRate, interestRule);
var interests = _service.GetInterests(td, td.trade_extend, valueDate, unwindDate,
eodPositions, new List<swap_position> { position },
posiNotional, posiNotional, posiNotional, posiNotional, closePercent,
posiNotional, posiNotional, closePercent,
(int)SwapEventTypeEnum.,
false, posiNotional, false, settment: false, newCalcLast: newCalcLast, closeList: closeList);
AssertInterestEqual(1, interests.Count);
@@ -279,7 +279,7 @@ namespace YLErp.Modules.SwapModule
var position = CreateFixedInterestPosition(fixedRate, interestRule);
var interests = _service.GetInterests(td, td.trade_extend, valueDate, valueDate,
eodPositions, new List<swap_position> { position },
Principal, Principal, Principal, Principal, 1m,
Principal, Principal, 1m,
(int)SwapEventTypeEnum.,
false, Principal, false, settment: true, newCalcLast: false, closeList: closeList);
AssertInterestEqual(1, interests.Count);
@@ -322,7 +322,7 @@ namespace YLErp.Modules.SwapModule
valueDate, unwindDate,
eodPositions,
new List<swap_position> { position },
posiNotional, posiNotional, posiNotional, posiNotional, closePercent,
posiNotional, posiNotional, closePercent,
(int)SwapEventTypeEnum.,
false, posiNotional, false, settment: false, newCalcLast: newCalcLast, closeList: closeList);
@@ -346,7 +346,7 @@ namespace YLErp.Modules.SwapModule
valueDate, valueDate,
eodPositions,
new List<swap_position> { position },
Principal, Principal, Principal, Principal, 1m,
Principal, Principal, 1m,
(int)SwapEventTypeEnum.,
false, Principal, false, settment: true, newCalcLast: false, closeList: closeList);
@@ -371,7 +371,7 @@ namespace YLErp.Modules.SwapModule
valueDate, valueDate,
eodPositions,
new List<swap_position> { position },
Principal, Principal, Principal, Principal, closePercent,
Principal, Principal, closePercent,
(int)SwapEventTypeEnum.,
false, Principal, false, settment: false, newCalcLast: false, closeList: closeList);
@@ -407,7 +407,7 @@ namespace YLErp.Modules.SwapModule
valueDate, unwindDate,
eodPositions,
new List<swap_position> { position },
posiNotional, posiNotional, posiNotional, posiNotional, closePercent,
posiNotional, posiNotional, closePercent,
(int)SwapEventTypeEnum.,
false, posiNotional, false, settment: false, newCalcLast: newCalcLast, closeList: closeList);
@@ -430,7 +430,7 @@ namespace YLErp.Modules.SwapModule
valueDate, valueDate,
eodPositions,
new List<swap_position> { position },
Principal, Principal, Principal, Principal, 1m,
Principal, Principal, 1m,
(int)SwapEventTypeEnum.,
false, Principal, false, settment: true, newCalcLast: false, closeList: closeList);
@@ -1716,7 +1716,7 @@ namespace YLErp.Modules.SwapModule
valueDate, unwindDate,
eodPositions,
new List<swap_position> { position },
posiNotional, posiNotional, posiNotional, posiNotional, closePercent,
posiNotional, posiNotional, closePercent,
(int)SwapEventTypeEnum.,
false, posiNotional, false, settment: false, newCalcLast: newCalcLast, closeList: closeList);
@@ -1747,7 +1747,7 @@ namespace YLErp.Modules.SwapModule
valueDate, unwindDate,
eodPositions,
new List<swap_position> { position },
posiNotional, posiNotional, posiNotional, posiNotional, closePercent,
posiNotional, posiNotional, closePercent,
(int)SwapEventTypeEnum.,
false, posiNotional, false, settment: false, newCalcLast: newCalcLast, closeList: closeList);
@@ -99,7 +99,7 @@ namespace UnitTestProject.Modules.SwapModule.Margin
{
oldList = svc.GetInterests(td, extend, valueDate, valueDate,
preEods, marginPositions,
0m, 0m, 0m, 0m, 1.0m,
0m, 0m, 1.0m,
(int)SwapEventTypeEnum., tdClose: false,
orginPv: 0m,
add: false, settment: true, newCalcLast: false, closeList: null);
@@ -119,7 +119,7 @@ namespace YLErp.Modules.SwapModule
var position = CreateInterestPosition();
var interests = service.GetInterests(td, td.trade_extend, unwindDate, unwindDate,
new List<eod_swap_position>(), new List<swap_position> { position },
Principal, Principal, Principal, Principal, 1m,
Principal, Principal, 1m,
(int)SwapEventTypeEnum., false, Principal,
add: false, settment: false, newCalcLast: false);
return interests.Count > 0 ? interests[0].InterestAmount : 0m;
@@ -142,7 +142,7 @@ namespace YLErp.Modules.SwapModule
};
var interests = service.GetInterests(td, td.trade_extend, valueDate, valueDate,
new List<eod_swap_position> { preEod }, new List<swap_position> { position },
Principal, Principal, Principal, Principal, 1m,
Principal, Principal, 1m,
(int)SwapEventTypeEnum., false, Principal,
add: false, settment: true, newCalcLast: false);
if (interests.Count == 0) return (0m, 0m);
@@ -313,7 +313,7 @@ namespace YLErp.Modules.SwapModule
var svc5 = new StubDealService(0m, floatRate: 0.001);
var i5 = svc5.GetInterests(td, td.trade_extend, day5, day5,
new List<eod_swap_position>(), new List<swap_position> { position },
Principal, Principal, Principal, Principal, 1m,
Principal, Principal, 1m,
(int)SwapEventTypeEnum., false, Principal,
settment: false);
decimal swap1 = i5.Count > 0 ? i5[0].InterestAmount : 0m;
@@ -322,7 +322,7 @@ namespace YLErp.Modules.SwapModule
var svc10 = new StubDealService(swap1, floatRate: 0.001);
var i10 = svc10.GetInterests(td, td.trade_extend, day10, day10,
new List<eod_swap_position>(), new List<swap_position> { position },
Principal, Principal, Principal, Principal, 1m,
Principal, Principal, 1m,
(int)SwapEventTypeEnum., false, Principal,
settment: false);
decimal swap2 = i10.Count > 0 ? i10[0].InterestAmount : 0m;
@@ -332,7 +332,7 @@ namespace YLErp.Modules.SwapModule
var svc15 = new StubDealService(totalConsumed, floatRate: 0.001);
var i15 = svc15.GetInterests(td, td.trade_extend, day15, day15,
new List<eod_swap_position>(), new List<swap_position> { position },
Principal, Principal, Principal, Principal, 1m,
Principal, Principal, 1m,
(int)SwapEventTypeEnum., false, Principal,
settment: false);
decimal finalUnwind = i15.Count > 0 ? i15[0].InterestAmount : 0m;
@@ -362,7 +362,7 @@ namespace YLErp.Modules.SwapModule
var svc = new StubDealService(0m, floatRate: 0.001);
var interests = svc.GetInterests(td, td.trade_extend, unwindDate, unwindDate,
new List<eod_swap_position>(), new List<swap_position> { position },
Principal, Principal, Principal, Principal, 1m,
Principal, Principal, 1m,
(int)SwapEventTypeEnum., false, Principal,
settment: false);
return interests.Count > 0 ? interests[0].InterestAmount : 0m;
@@ -103,7 +103,7 @@ namespace YLErp.Modules.SwapModule
SwapCalcTrace.Reset();
var eod = new List<eod_swap_position> { MakeEod(valueDate, PrepayRemaining, 0m) };
var fe = _svc.GetInterests(td, td.trade_extend, FullDate, FullDate, eod,
new List<swap_position> { pos }, PrepayFix, PrepayFix, PrepayFix, PrepayFix, 1m,
new List<swap_position> { pos }, PrepayFix, PrepayFix, 1m,
(int)SwapEventTypeEnum., false, PrepayFix, false,
settment: false, newCalcLast: calcLast, closeList: null)[0];
var trace = SwapCalcTrace.Dump();
@@ -101,7 +101,7 @@ namespace YLErp.Modules.SwapModule
protected override List<swap_flow_event> CalcSwapInterests(
trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue,
decimal posiNotionalValue,
decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose,
decimal orginPv, bool add = false, bool settment = true, bool newCalcLast = false,
List<swap_flow_event> closeList = null)
@@ -80,7 +80,7 @@ namespace YLErp.Modules.SwapModule
var result = service.GetInterests(
trade, trade.trade_extend, closeCase.CloseDate, closeCase.CloseDate,
new List<eod_swap_position> { previousEod }, new List<swap_position> { position },
closeCase.RemainingNotional, closeCase.RemainingNotional, 0m,
closeCase.RemainingNotional,
closeCase.RemainingNotional, 1m, (int)SwapEventTypeEnum.,
false,
closeCase.InterestType == 0 ? closeCase.RemainingNotional : closeCase.OriginalNotional,
@@ -1,3 +1,4 @@
using System.Linq;
using System.Reflection;
using YLErp.DBModels.Enums;
@@ -272,7 +273,16 @@ namespace YLErp.Modules.SwapModule
Console.WriteLine($" ✓ {scenario.Scenario}");
}
Assert.AreEqual(13, parameters.Length, "DealInterests应有13个参数");
// 校验参数集合(按名称,对参数增删/重排/改名均敏感,比裸数字更稳)
var expectedParamNames = new[]
{
"interestList", "eodPositions", "todyEodPositions", "settleDate",
"td", "flowEvents", "autoInterests", "lastEodSwap",
"posiTotalNotional", "closeNational", "grossPrice", "orginPv"
};
var actualParamNames = parameters.Select(p => p.Name).ToArray();
CollectionAssert.AreEquivalent(expectedParamNames, actualParamNames,
"DealInterests 参数集合应与预期一致(新增/重排/改名参数时请同步更新此列表)");
Console.WriteLine("✅ 分支覆盖分析完成");
}
}
@@ -56,7 +56,7 @@ namespace UnitTestProject.Modules.SwapModule
protected override List<swap_flow_event> CalcSwapInterests(
trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue,
decimal posiNotionalValue,
decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose,
decimal orginPv, bool add = false, bool settment = true, bool newCalcLast = false,
List<swap_flow_event> closeList = null)
@@ -64,7 +64,7 @@ namespace UnitTestProject.Modules.SwapModule
var svc = new StubSwapDealService(
new OptUserInfo(0, nameof(SwapInterestScenario1And2Test), OptUserFrom.UnitTest), _floatRates);
return svc.GetInterests(td, tradeExtend, valueDate, unwindDate,
eodPositions, positions, posiNotionalValue, posiLongNotionalValue, posiShortNotionalValue,
eodPositions, positions, posiNotionalValue,
closePosiNotionalValue, closePrecent, eventType, tdClose,
orginPv, add, settment, newCalcLast, closeList);
}
@@ -74,7 +74,7 @@ namespace UnitTestProject.Modules.SwapModule
List<swap_flow_event> flowEvents, decimal closeNotional, eod_swap_position prevEod)
{
SaveAutoEodWithCloseInterestPosition(prevEod, null, position, td, valueDate, null,
posiLongNotional, posiShortNotional, flowEvents, closeNotional, false, 1m,
posiLongNotional + posiShortNotional, flowEvents, closeNotional, false, 1m,
posiLongNotional + posiShortNotional);
return PersistedPositions.LastOrDefault();
}
@@ -211,7 +211,7 @@ namespace UnitTestProject.Modules.SwapModule
var interests = svc.GetInterests(
td, td.trade_extend, valueDate, valueDate,
prevEod, new List<swap_position> { position },
closeNotional, closeNotional, 0m, closeNotional, 1m,
closeNotional, closeNotional, 1m,
(int)SwapEventTypeEnum.,
false, closeNotional, false, settment: false, newCalcLast: isMaturity);
Assert.AreEqual(1, interests.Count);
@@ -178,7 +178,7 @@ namespace UnitTestProject.Modules.SwapModule
protected override List<swap_flow_event> CalcSwapInterests(
trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue,
decimal posiNotionalValue,
decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose,
decimal orginPv, bool add = false, bool settment = true, bool newCalcLast = false,
List<swap_flow_event> closeList = null)
@@ -186,7 +186,7 @@ namespace UnitTestProject.Modules.SwapModule
var svc = new RealSwapDealService(
new OptUserInfo(0, nameof(SwapInterestScenario3And4FloatingTest), OptUserFrom.UnitTest), _floatRates, FlowEvents);
var interests = svc.GetInterests(td, tradeExtend, valueDate, unwindDate,
eodPositions, positions, posiNotionalValue, posiLongNotionalValue, posiShortNotionalValue,
eodPositions, positions, posiNotionalValue,
closePosiNotionalValue, closePrecent, eventType, tdClose,
orginPv, add, settment, newCalcLast, closeList);
// 捕获 base InterestPrincipal= EOD:1406 行赋给 TdInterestPrincipal 的值,反推前),供 TdInterestPrincipal 断言镜像分叉。
@@ -226,7 +226,7 @@ namespace UnitTestProject.Modules.SwapModule
List<swap_flow_event> flowEvents, decimal closeNotional, eod_swap_position prevEod)
{
SaveAutoEodWithCloseInterestPosition(prevEod, null, position, _td, valueDate, null,
posiLongNotional, posiShortNotional, flowEvents, closeNotional, false, 1m,
posiLongNotional + posiShortNotional, flowEvents, closeNotional, false, 1m,
posiLongNotional + posiShortNotional);
return PersistedPositions.LastOrDefault();
}
@@ -394,7 +394,7 @@ namespace UnitTestProject.Modules.SwapModule
var interests = svc.GetInterests(
td, td.trade_extend, valueDate, valueDate,
prevEod, new List<swap_position> { position },
closeNotional, closeNotional, 0m, closeNotional, 1m,
closeNotional, closeNotional, 1m,
(int)SwapEventTypeEnum.,
false, closeNotional, false, settment: false, newCalcLast: isMaturity);
Assert.AreEqual(1, interests.Count);
@@ -79,14 +79,14 @@ namespace YLErp.Modules.SwapModule
protected override List<swap_flow_event> CalcSwapInterests(
trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue,
decimal posiNotionalValue,
decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose,
decimal orginPv, bool add = false, bool settment = true, bool newCalcLast = false,
List<swap_flow_event> closeList = null)
{
LastInterestCalculationPositions = positions;
return base.CalcSwapInterests(td, tradeExtend, valueDate, unwindDate,
eodPositions, positions, posiNotionalValue, posiLongNotionalValue, posiShortNotionalValue,
eodPositions, positions, posiNotionalValue,
closePosiNotionalValue, closePrecent, eventType, tdClose,
orginPv, add, settment, newCalcLast, closeList);
}
@@ -59,7 +59,7 @@ namespace UnitTestProject.Modules.SwapModule
protected override List<swap_flow_event> CalcSwapInterests(
trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue,
decimal posiNotionalValue,
decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose,
decimal orginPv, bool add = false, bool settment = true, bool newCalcLast = false,
List<swap_flow_event> closeList = null)
@@ -67,7 +67,7 @@ namespace UnitTestProject.Modules.SwapModule
var svc = new StubSwapDealService(
new OptUserInfo(0, nameof(SwapSingleTradeVerificationTest), OptUserFrom.UnitTest), _floatRates);
return svc.GetInterests(td, tradeExtend, valueDate, unwindDate,
eodPositions, positions, posiNotionalValue, posiLongNotionalValue, posiShortNotionalValue,
eodPositions, positions, posiNotionalValue,
closePosiNotionalValue, closePrecent, eventType, tdClose,
orginPv, add, settment, newCalcLast, closeList);
}
@@ -77,7 +77,7 @@ namespace UnitTestProject.Modules.SwapModule
List<swap_flow_event> flowEvents, decimal closeNotional, eod_swap_position prevEod)
{
SaveAutoEodWithCloseInterestPosition(prevEod, null, position, td, valueDate, null,
posiLongNotional, posiShortNotional, flowEvents, closeNotional, false, 1m,
posiLongNotional + posiShortNotional, flowEvents, closeNotional, false, 1m,
posiLongNotional + posiShortNotional);
return PersistedPositions.LastOrDefault();
}
@@ -213,7 +213,7 @@ namespace UnitTestProject.Modules.SwapModule
var interests = svc.GetInterests(
td, td.trade_extend, valueDate, valueDate,
prevEod, new List<swap_position> { position },
closeNotional, closeNotional, 0m, closeNotional, 1m,
closeNotional, closeNotional, 1m,
(int)SwapEventTypeEnum.,
false, closeNotional, false, settment: false, newCalcLast: isMaturity);
Assert.AreEqual(1, interests.Count);
@@ -93,7 +93,7 @@ namespace YLErp.Modules.SwapModule
var position = MakePrepayPosition();
var interests = _svc.GetInterests(td, td.trade_extend, UnwindDate, UnwindDate,
eodPositions, new List<swap_position> { position },
UnderlyingNotional, UnderlyingNotional, UnderlyingNotional, UnderlyingNotional, closePercent,
UnderlyingNotional, UnderlyingNotional, closePercent,
(int)SwapEventTypeEnum.,
false, UnderlyingNotional, false, settment: false, newCalcLast: false, closeList: null);
Assert.AreEqual(1, interests.Count, "预付金腿应生成 1 条 flow_event");
@@ -111,7 +111,7 @@ namespace YLErp.Modules.SwapModule
var position = MakePrepayPosition(fix, rate);
var interests = _svc.GetInterests(td, td.trade_extend, UnwindDate, UnwindDate,
eodPositions, new List<swap_position> { position },
notional, notional, notional, notional, closePercent,
notional, notional, closePercent,
(int)SwapEventTypeEnum.,
false, notional, false, settment: false, newCalcLast: false, closeList: null);
Assert.AreEqual(1, interests.Count, "预付金腿应生成 1 条 flow_event");
@@ -279,7 +279,7 @@ namespace YLErp.Modules.SwapModule
};
var interests = _svc.GetInterests(td, td.trade_extend, ProdUnwindDate, ProdUnwindDate,
eod, new List<swap_position> { position },
fix, fix, fix, fix, closePercent,
fix, fix, closePercent,
(int)SwapEventTypeEnum.,
false, fix, false, settment: false, newCalcLast: false, closeList: null);
Assert.AreEqual(1, interests.Count, "预付金腿应生成 1 条 flow_event");
@@ -373,7 +373,7 @@ namespace YLErp.Modules.SwapModule
// orginPv 传 notional:非预付金腿不走 877-881 的 Fix 对齐,dynomicPrincipal = notional + notional - notional = notional
var interests = _svc.GetInterests(td, td.trade_extend, ProdUnwindDate, ProdUnwindDate,
eod, new List<swap_position> { position },
notional, notional, notional, notional * closePercent, closePercent,
notional, notional * closePercent, closePercent,
(int)SwapEventTypeEnum.,
false, notional, false, settment: false, newCalcLast: false, closeList: null);
Assert.AreEqual(1, interests.Count, "非预付金腿应生成 1 条 flow_event");
@@ -488,7 +488,7 @@ namespace YLErp.Modules.SwapModule
};
var interests = _svc.GetInterests(td, td.trade_extend, ProdUnwindDate, ProdUnwindDate,
eodPos, new List<swap_position> { position },
baseP, baseP, baseP, baseP * closePercent, closePercent,
baseP, baseP * closePercent, closePercent,
(int)SwapEventTypeEnum.,
false, baseP, false, settment: eodPath, newCalcLast: false, closeList: null);
Assert.AreEqual(1, interests.Count, $"mode={mode} 应生成 1 条 flow_event");
@@ -121,7 +121,7 @@ namespace YLErp.Modules.SwapModule
var position = MakePosition(currentNotional);
var interests = _svc.GetInterests(td, td.trade_extend, UnwindDate, UnwindDate,
MakeLastEod(), new List<swap_position> { position },
currentNotional, currentNotional, currentNotional, currentNotional * closePercent, closePercent,
currentNotional, currentNotional * closePercent, closePercent,
(int)SwapEventTypeEnum.,
false, N, false, settment: false, newCalcLast: false, closeList: null);
Assert.AreEqual(1, interests.Count, "标的期初全价腿应生成 1 条 flow_event");
@@ -8,7 +8,8 @@ namespace YLErp.Modules.SwapModule;
/// GetInterestsEntrySemanticsTest 的口径留档),位置参数无法表达该约束。
///
/// 用法:只能经两个场景工厂构造——工厂形参名即该场景语义(平仓前剩余 / 平仓后剩余 / 实际平掉额),
/// 物理上防止两套语义混传。needPrice/grossPrice原方法死参数(体内零消费),本对象不承载。
/// 物理上防止两套语义混传。needPrice/grossPrice原方法死参数)与 posiLong/posiShortNotionalValue
/// (多空组合子系统删除后计息链零消费的管道死参数)均不承载。
/// </summary>
public sealed class InterestCalcRequest
{
@@ -21,8 +22,6 @@ public sealed class InterestCalcRequest
/// <summary>当日适用名义本金。语义随场景:盘中=平仓【前】剩余;EOD平仓后收盘=平仓【后】剩余;EOD增量=当前剩余。</summary>
public decimal PosiNotionalValue { get; }
public decimal PosiLongNotionalValue { get; }
public decimal PosiShortNotionalValue { get; }
/// <summary>本次实际平掉本金(两场景恒同义)。mode2 无条件覆盖 / mode9 全平兜底的输入。</summary>
public decimal ClosePosiNotionalValue { get; }
@@ -40,15 +39,14 @@ public sealed class InterestCalcRequest
private InterestCalcRequest(
trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue,
decimal posiNotionalValue,
decimal closePosiNotionalValue, decimal closePercent,
int eventType, bool tdClose, decimal orginPv,
bool add, bool newCalcLast, List<swap_flow_event> closeList)
{
Td = td; TradeExtend = tradeExtend; ValueDate = valueDate; UnwindDate = unwindDate;
EodPositions = eodPositions; Positions = positions;
PosiNotionalValue = posiNotionalValue; PosiLongNotionalValue = posiLongNotionalValue;
PosiShortNotionalValue = posiShortNotionalValue; ClosePosiNotionalValue = closePosiNotionalValue;
PosiNotionalValue = posiNotionalValue; ClosePosiNotionalValue = closePosiNotionalValue;
ClosePercent = closePercent; EventType = eventType; TdClose = tdClose; OrginPv = orginPv;
Add = add; NewCalcLast = newCalcLast; CloseList = closeList;
}
@@ -62,13 +60,11 @@ public sealed class InterestCalcRequest
public static InterestCalcRequest IntradayUnwind(
trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal preCloseNotional, decimal preCloseLongNotional, decimal preCloseShortNotional,
decimal closedNotional, decimal closePercentRemaining,
decimal preCloseNotional, decimal closedNotional, decimal closePercentRemaining,
int eventType, bool tdClose, decimal orginPv,
bool add, bool newCalcLast, List<swap_flow_event> closeList)
=> new(td, tradeExtend, valueDate, unwindDate, eodPositions, positions,
preCloseNotional, preCloseLongNotional, preCloseShortNotional,
closedNotional, closePercentRemaining,
preCloseNotional, closedNotional, closePercentRemaining,
eventType, tdClose, orginPv, add, newCalcLast, closeList);
/// <summary>
@@ -80,12 +76,10 @@ public sealed class InterestCalcRequest
public static InterestCalcRequest EodPostCloseSettle(
trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal remainingNotionalAfterClose, decimal remainingLongNotional, decimal remainingShortNotional,
decimal closedNotional,
decimal remainingNotionalAfterClose, decimal closedNotional,
int eventType, bool tdClose, decimal orginPv,
bool add, bool newCalcLast)
=> new(td, tradeExtend, valueDate, unwindDate, eodPositions, positions,
remainingNotionalAfterClose, remainingLongNotional, remainingShortNotional,
closedNotional, 1m, // 恒1:本次事件全额结息(非 closeNational / 期初比例)
remainingNotionalAfterClose, closedNotional, 1m, // 恒1:本次事件全额结息(非 closeNational / 期初比例)
eventType, tdClose, orginPv, add, newCalcLast, closeList: null);
}
@@ -467,16 +467,11 @@ namespace YLErp.Modules.SwapModule
// 迭代源仍用 origPositions(保留 orig.id → eod_swap_position.PositionId 的日终匹配)
// 仅对预付金腿以实时腿的剩余本金克隆覆盖,故此处不改任何日终匹配行为。
var positions = ResolveInterestLegPositions(origPositions, realPostitions);
var fpositions = origPositions.Where(x => x.PosiDirection > 0).ToList();
var longPositions = fpositions.Where(x => x.PositionType == (int)PositionTypeFlag.Long).ToList();
var shortPositions = fpositions.Where(x => x.PositionType == (int)PositionTypeFlag.Short).ToList();
var tradeExtend = DbContext.trade_extend.FirstOrDefault(x => x.TradeId == tradeId);
List<int> eventTypes = new List<int>() { (int)SwapEventTypeEnum., (int)SwapEventTypeEnum., (int)SwapEventTypeEnum. };
var lastEod = DbContext.eod_swap.Where(x => x.ValueDate < unwindDate && x.SwapTradeId == tradeId).OrderByDescending(o => o.ValueDate).FirstOrDefault();
var _preSetteDate = lastEod == null ? unwindDate.AddDays(-1) : lastEod.ValueDate;
List<eod_swap_position> lastEodPositions = new SwapEodPositionService(this).GetPreEodPositions(tradeId, _preSetteDate);//上一交易数据
var posiLongNotionalValue = longPositions.Sum(s => s.PosiNotionalValue);// 剩余名义本金
var posiShortNotionalValue = shortPositions.Sum(s => s.PosiNotionalValue);// 剩余名义本金
var stockEqvNotional = realPostitions.Where(x => x.PosiDirection > 0).Sum(s => s.PosiNotionalValue); // 当前平仓前的实时剩余本金
var posiNotionalValue = stockEqvNotional * closePercent;// 本次平仓名义本金
var orginPv = ResolveUnwindPreviousNotional(lastEod, lastEodPositions, stockEqvNotional); // 上一日终的浮动端本金
@@ -489,7 +484,7 @@ namespace YLErp.Modules.SwapModule
// 显式入口:平仓前剩余本金 + 实际平掉额 + B语义比例,盘中重放(语义见 InterestCalcRequest.IntradayUnwind
interests = GetIntradayUnwindInterests(InterestCalcRequest.IntradayUnwind(
td, tradeExtend, valueDate, unwindDate, lastEodPositions, positions,
stockEqvNotional, posiLongNotionalValue, posiShortNotionalValue, posiNotionalValue,
stockEqvNotional, posiNotionalValue,
closePercent, eventType, tdClose, orginPv, add: true, newCalcLast: false, closeList));
return interests;
}
@@ -626,7 +621,7 @@ namespace YLErp.Modules.SwapModule
/// </summary>
public List<swap_flow_event> GetIntradayUnwindInterests(InterestCalcRequest req)
=> GetInterests(req.Td, req.TradeExtend, req.ValueDate, req.UnwindDate, req.EodPositions, req.Positions,
req.PosiNotionalValue, req.PosiLongNotionalValue, req.PosiShortNotionalValue, req.ClosePosiNotionalValue,
req.PosiNotionalValue, req.ClosePosiNotionalValue,
req.ClosePercent, req.EventType, req.TdClose,
req.OrginPv, req.Add, settment: false, req.NewCalcLast, req.CloseList);
@@ -638,8 +633,6 @@ namespace YLErp.Modules.SwapModule
List<eod_swap_position> eodPositions,
List<swap_position> positions,
decimal posiNotionalValue,
decimal posiLongNotionalValue,
decimal posiShortNotionalValue,
decimal closePosiNotionalValue,
decimal closePrecent,
int eventType,
@@ -90,7 +90,7 @@ namespace YLErp.Modules.SwapModule
trade td, trade_extend tradeExtend,
DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue,
decimal posiNotionalValue,
decimal closePosiNotionalValue, decimal closePrecent,
int eventType, bool tdClose,
decimal orginPv,
@@ -98,7 +98,7 @@ namespace YLErp.Modules.SwapModule
List<swap_flow_event> closeList = null)
{
return new SwapDealService(this).GetInterests(td, tradeExtend, valueDate, unwindDate,
eodPositions, positions, posiNotionalValue, posiLongNotionalValue, posiShortNotionalValue,
eodPositions, positions, posiNotionalValue,
closePosiNotionalValue, closePrecent, eventType, tdClose,
orginPv, add, settment, newCalcLast, closeList);
}
@@ -112,7 +112,7 @@ namespace YLErp.Modules.SwapModule
/// </summary>
protected virtual List<swap_flow_event> CalcEodPostCloseSettleInterests(InterestCalcRequest req)
=> CalcSwapInterests(req.Td, req.TradeExtend, req.ValueDate, req.UnwindDate, req.EodPositions, req.Positions,
req.PosiNotionalValue, req.PosiLongNotionalValue, req.PosiShortNotionalValue,
req.PosiNotionalValue,
req.ClosePosiNotionalValue, req.ClosePercent, req.EventType, req.TdClose,
req.OrginPv, req.Add, settment: false, req.NewCalcLast, req.CloseList);
@@ -369,7 +369,7 @@ namespace YLErp.Modules.SwapModule
var closePosiNotional = curEodPosis.Where(s => s.TdCloseQty > 0).Sum(s => s.TdCloseQty * s.ContractSize * s.PosiGrossPrice);
var grossPrice = curEodPosis.Where(x => x.PosiDirection > 0).FirstOrDefault()?.PosiGrossPrice ?? 0;
//处理利息腿
DealInterests(interestList, eodPositions, todyEodPositions, settleDate, td, flowEvents, autoInterests, lastEodSwap, posiLongNotional, posiShortNotional, closePosiNotional, grossPrice, orginPv);
DealInterests(interestList, eodPositions, todyEodPositions, settleDate, td, flowEvents, autoInterests, lastEodSwap, posiLongNotional + posiShortNotional, closePosiNotional, grossPrice, orginPv);
//获取自动互换的 interval 信息,用于确定结算日期
IntervalModel autoInterval = null;
foreach (var interest in interestList)
@@ -441,8 +441,7 @@ namespace YLErp.Modules.SwapModule
List<swap_flow_event> flowEvents,
List<swap_flow_event> autoInterests,
eod_swap lastEodSwap,
decimal posiLongNational,
decimal posiShortNational,
decimal posiTotalNotional,
decimal closeNational,
decimal grossPrice,
decimal orginPv)
@@ -453,7 +452,7 @@ namespace YLErp.Modules.SwapModule
Log.Info($"[DealInterests] 参数验证 - settleDate: {settleDate:yyyy-MM-dd}, td.id: {td?.id}, td.TradeNumber: {td?.TradeNumber}");
Log.Info($"[DealInterests] 参数验证 - interestList.Count: {interestList?.Count ?? 0}, eodPositions.Count: {eodPositions?.Count ?? 0}, todyEodPositions.Count: {todyEodPositions?.Count ?? 0}");
Log.Info($"[DealInterests] 参数验证 - flowEvents.Count: {flowEvents?.Count ?? 0}, autoInterests.Count: {autoInterests?.Count ?? 0}");
Log.Info($"[DealInterests] 参数验证 - posiLongNational: {posiLongNational}, posiShortNational: {posiShortNational}, closeNational: {closeNational}, grossPrice: {grossPrice}, orginPv: {orginPv}");
Log.Info($"[DealInterests] 参数验证 - posiTotalNotional: {posiTotalNotional}, closeNational: {closeNational}, grossPrice: {grossPrice}, orginPv: {orginPv}");
// 验证关键参数
if (td == null)
@@ -501,7 +500,7 @@ namespace YLErp.Modules.SwapModule
{
if (!hasClose)//当日无平仓
{
var _autoInterests = SaveAutoEodInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, lastEodSwap, posiLongNational, posiShortNational, grossPrice, orginPv);
var _autoInterests = SaveAutoEodInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, lastEodSwap, posiTotalNotional, grossPrice, orginPv);
if (_autoInterests.Count > 0)
{
autoInterests.AddRange(_autoInterests);
@@ -509,7 +508,7 @@ namespace YLErp.Modules.SwapModule
}
else
{
var _autoInterests = SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiLongNational, posiShortNational, swapEvents, closeNational, true, grossPrice, orginPv);
var _autoInterests = SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiTotalNotional, swapEvents, closeNational, true, grossPrice, orginPv);
if (_autoInterests.Count > 0)
{
autoInterests.AddRange(_autoInterests);
@@ -522,11 +521,11 @@ namespace YLErp.Modules.SwapModule
}
else if (hasClose)
{
SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiLongNational, posiShortNational, swapEvents, closeNational, false, grossPrice, orginPv);
SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiTotalNotional, swapEvents, closeNational, false, grossPrice, orginPv);
}
else//无自动互换、互换/平仓,复制上一日终信息,并计算当日新增利息
{
SaveEodInterestPositionCopy(eodPosition, tdEodPosition, settleDate, td, interest, lastEodSwap, true, posiLongNational, posiShortNational, grossPrice, orginPv);
SaveEodInterestPositionCopy(eodPosition, tdEodPosition, settleDate, td, interest, lastEodSwap, true, posiTotalNotional, grossPrice, orginPv);
}
}
}
@@ -1093,7 +1092,7 @@ namespace YLErp.Modules.SwapModule
/// <param name="preDealDate">上一平仓/互换日期</param>
/// <param name="closeAmount">当日平仓金额</param>
/// <param name="lastEodSwap">上一日终框架合约估值</param>
protected List<swap_flow_event> SaveAutoEodInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, eod_swap lastEodSwap, decimal posiLongNotional, decimal posiShortNational, decimal grossPrice, decimal orginPv)
protected List<swap_flow_event> SaveAutoEodInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, eod_swap lastEodSwap, decimal posiTotalNotional, decimal grossPrice, decimal orginPv)
{
Log.Info($"[SaveAutoEodInterestPosition] 开始执行 - valueDate: {valueDate:yyyy-MM-dd}, td.id: {td?.id}, position.id: {position?.id}");
@@ -1132,7 +1131,7 @@ namespace YLErp.Modules.SwapModule
}
var tradeExtend = td.trade_extend.ExtendObj;
decimal posiNotionalValue = posiLongNotional + posiShortNational;
decimal posiNotionalValue = posiTotalNotional;
decimal closePercent = 1;
var ratio = DirectionRatio.InterestLegPnl(position.InterestDirection, position.InterestMode);
if (eodPayPosition == null)
@@ -1159,7 +1158,7 @@ namespace YLErp.Modules.SwapModule
{
orginPv = eodPayPosition.InterestPrincipalFix;
}
var interests = CalcSwapInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNotional, posiShortNational, posiNotionalValue, closePercent, (int)SwapEventTypeEnum., false, orginPv, true);
var interests = CalcSwapInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiNotionalValue, closePercent, (int)SwapEventTypeEnum., false, orginPv, true);
decimal interestAmountBeforeSettlement = interests.Sum(x => x.InterestAmount);
decimal tdInterestAmount = interests.Sum(x => x.TdInterestAmount);
@@ -1244,7 +1243,7 @@ namespace YLErp.Modules.SwapModule
/// <param name="closeAmount">当日平仓金额</param>
/// <param name="lastEodSwap">上一日终框架合约估值</param>
/// <param name="unwintotal">平仓主信息</param>
protected List<swap_flow_event> SaveAutoEodWithCloseInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, decimal posiLongNotional, decimal posiShortNational, List<swap_flow_event> flowEvents, decimal closeNational, bool autoSwap, decimal grossPrice, decimal orginPv)
protected List<swap_flow_event> SaveAutoEodWithCloseInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, decimal posiTotalNotional, List<swap_flow_event> flowEvents, decimal closeNational, bool autoSwap, decimal grossPrice, decimal orginPv)
{
Log.Info($"eodPayPosition is {JsonHelper.Serialize(eodPayPosition, false)},newEodPayPosition is {JsonHelper.Serialize(newEodPayPosition, false)}");
var tradeExtend = td.trade_extend.ExtendObj;
@@ -1255,8 +1254,8 @@ namespace YLErp.Modules.SwapModule
// 调用共享计息器。因此策略的 "posiNotional × closePercent" 在本例会得到 212197382.46
// 而本次实际应结的平仓本金是 closeNational=90941735.34。该语义错位由
// SwapDealService.GetInterests 的模式2无条件修正、模式9全平零值兜底分流处理,不能删除。
decimal oriPosiNotionalValue = posiLongNotional + posiShortNational + closeNational;
decimal posiNotionalValue = posiLongNotional + posiShortNational;
decimal oriPosiNotionalValue = posiTotalNotional + closeNational;
decimal posiNotionalValue = posiTotalNotional;
// ratio 只负责把腿内原始金额转换为本方盈亏方向,不参与计息金额本身的计算。
var ratio = DirectionRatio.InterestLegPnl(position.InterestDirection, position.InterestMode);
// 首次日终结算可能包含当日收盘,因此尚无先前的日终利息持仓。
@@ -1324,7 +1323,7 @@ namespace YLErp.Modules.SwapModule
// 该组合触发 GetInterests 内共享计息器的模式2/9本金修正(见其"根因位置"注释,勿删)。
var interests = CalcEodPostCloseSettleInterests(InterestCalcRequest.EodPostCloseSettle(
td, td.trade_extend, valueDate, valueDate, preEodPositions, positions,
posiNotionalValue, posiLongNotional, posiShortNational, closeNational,
posiNotionalValue, closeNational,
eventType, tdClose: false, orginPv, add: true, newCalcLast: autoSwap || calcLast));
// TdInterestAmount:计息器返回的全腿当日/累计参考值,用于拆出 EOD 的当日新增。
// interestAmountBeforeSettlement:本次事件发生前理论应结的高精度利息。
@@ -1505,7 +1504,7 @@ namespace YLErp.Modules.SwapModule
/// <param name="preSettleDate">上一交易日</param>
/// <param name="valueDate">当前结算日</param>
/// <param name="td">互换交易主干</param>
protected void SaveEodInterestPositionCopy(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, DateTime valueDate, trade td, swap_position position, eod_swap lastEodSwap, bool needPrice, decimal posiLongNational, decimal posiShortNational, decimal grossPrice, decimal orginPv)
protected void SaveEodInterestPositionCopy(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, DateTime valueDate, trade td, swap_position position, eod_swap lastEodSwap, bool needPrice, decimal posiTotalNotional, decimal grossPrice, decimal orginPv)
{
Log.Info($"eodPayPosition is {JsonHelper.Serialize(eodPayPosition, false)},newEodPayPosition is {JsonHelper.Serialize(newEodPayPosition, false)}");
List<IntervalModel> intervals = position.SwapIntervalList;
@@ -1529,7 +1528,7 @@ namespace YLErp.Modules.SwapModule
eodPayPosition.InterestPrincipalFix = position.InterestPrincipalFix;
eodPayPosition.InterestRateDefault = position.InterestRateDefault;
eodPayPosition.InterestSwapInterval = position.InterestSwapInterval;
eodPayPosition.TdInterestPrincipal = interestModes.Contains(position.InterestMode) ? eodPayPosition.InterestPrincipalFix : posiLongNational + posiShortNational;
eodPayPosition.TdInterestPrincipal = interestModes.Contains(position.InterestMode) ? eodPayPosition.InterestPrincipalFix : posiTotalNotional;
eodPayPosition.PosiStartDate = td.StartDate.Value;
eodPayPosition.PosiMatuirityDate = td.ExerciseDate.Value;
eodPayPosition.IsAnnualized = position.IsAnnualized;
@@ -1552,7 +1551,7 @@ namespace YLErp.Modules.SwapModule
orginPv = eodPayPosition.InterestPrincipalFix;
}
bool longShort = td.StructureType == ClientMarginTypeEnum..ToString();
decimal oriPosiNotionalValue = posiLongNational + posiShortNational;
decimal oriPosiNotionalValue = posiTotalNotional;
decimal posiNotionalValue = oriPosiNotionalValue;
if (lastEodSwap == null)
{
@@ -1577,7 +1576,7 @@ namespace YLErp.Modules.SwapModule
{
preEodPositions.Add(eodPayPosition);
}
var interests = CalcSwapInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNational, posiShortNational, posiNotionalValue, closePercent, 0, false, orginPv);
var interests = CalcSwapInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiNotionalValue, closePercent, 0, false, orginPv);
UpdateDbOption(newEodPayPosition);
newEodPayPosition.PosiStatus = 0;