fix(swap): 修复利息互换平仓结算中的尾差处理和本金计算问题
- 修复ExecuteSaveAutoEodInterestPosition方法参数传递,添加lastEodSwap、posiLongNotional和orginPv参数 - 修正平仓利息计算逻辑,区分手动结算和平仓后自动结算的利息处理 - 新增ResolveUnwindPreviousNotional静态方法,优化平仓前本金计算逻辑 - 修复部分平仓后利息累积边界问题,确保仅从上次EOD快照后开始计算 - 完善自动结算利息的四舍五入处理,避免精度丢失 - 修正支付端方向符号应用,确保方向只应用一次 - 更新TdInterestPrincipal计算逻辑,处理不同利息模式下的本金赋值 - 修复TdCloseInterest计算,合并手动和自动结算利息金额 - 优化InterestIncomeSum计算,正确处理结算后剩余未实现利息
This commit is contained in:
@@ -1161,13 +1161,7 @@ namespace YLErp.Modules.SwapModule
|
||||
}
|
||||
|
||||
var tradeExtend = td.trade_extend.ExtendObj;
|
||||
decimal oriPosiNotionalValue = posiLongNotional + posiShortNational;
|
||||
decimal posiNotionalValue = oriPosiNotionalValue;
|
||||
bool longShort = td.StructureType == ClientMarginTypeEnum.多空组合.ToString();
|
||||
if (lastEodSwap != null)
|
||||
{
|
||||
posiNotionalValue = lastEodSwap.NotionalValue;
|
||||
}
|
||||
decimal posiNotionalValue = posiLongNotional + posiShortNational;
|
||||
decimal closePercent = 1;
|
||||
decimal ratio = position.InterestDirection == (int)SwapDirectionEnum.收取 ? 1m : -1m;//收取为正,支付为负
|
||||
if (marginTypes.Contains(position.InterestMode))
|
||||
@@ -1293,10 +1287,11 @@ namespace YLErp.Modules.SwapModule
|
||||
var lastInterestFeeSum = eodPayPosition?.InterestFeeSum ?? 0m;
|
||||
var lastRealizedInterest = eodPayPosition?.RealizedInterest ?? 0m;
|
||||
var lastRealizedInterestFee = eodPayPosition?.RealizedInterestFee ?? 0m;
|
||||
eodPayPosition = new eod_swap_position();
|
||||
// 保留上一日日终标识和计息上下文,部分平仓只从 ValueDate 之后续算,不能重置到交易起始日。
|
||||
eodPayPosition = eodPayPosition?.Clone() ?? new eod_swap_position();
|
||||
eodPayPosition.ClientId = td.ClientId;
|
||||
eodPayPosition.SwapTradeId = td.id;
|
||||
// CalcSwapInterests 按 PositionId 查找上一日日终;id 仍保持 0,沿用盘中平仓的原有计息日期语义。
|
||||
// CalcSwapInterests 按 PositionId 匹配上一日日终。
|
||||
eodPayPosition.PositionId = position.id;
|
||||
eodPayPosition.PosiStartDate = td.StartDate.Value;
|
||||
eodPayPosition.PosiMatuirityDate = td.ExerciseDate.Value;
|
||||
@@ -1338,7 +1333,17 @@ namespace YLErp.Modules.SwapModule
|
||||
preEodPositions.Add(eodPayPosition);
|
||||
var interests = CalcSwapInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNotional, posiShortNational, closeNational, 1, eventType, false, true, grossPrice, orginPv, true, settment: false, newCalcLast: true);
|
||||
decimal TdInterestAmount = interests.Sum(x => x.TdInterestAmount);
|
||||
decimal InterestAmount = interests.Sum(x => x.InterestAmount);
|
||||
decimal interestAmountBeforeSettlement = interests.Sum(x => x.InterestAmount);
|
||||
decimal manualSettledInterestAmount = flowEvents.Sum(x => x.InterestAmount);
|
||||
decimal autoSettledInterestAmount = 0m;
|
||||
if (autoSwap && interests.Count > 0)
|
||||
{
|
||||
autoSettledInterestAmount = RoundMoney(interestAmountBeforeSettlement - manualSettledInterestAmount);
|
||||
var autoInterest = interests[0];
|
||||
autoInterest.InterestAmount = autoSettledInterestAmount;
|
||||
autoInterest.InterestClosePnL = autoSettledInterestAmount
|
||||
* (autoInterest.InterestDirection == (int)SwapDirectionEnum.收取 ? 1m : -1m);
|
||||
}
|
||||
newEodPayPosition.ValueDate = valueDate;
|
||||
newEodPayPosition.PositionId = position.id;
|
||||
UpdateDbOption(newEodPayPosition);
|
||||
@@ -1359,7 +1364,9 @@ namespace YLErp.Modules.SwapModule
|
||||
newEodPayPosition.interest_rest_days = position.interest_rest_days;
|
||||
newEodPayPosition.interest_rule = position.interest_rule;
|
||||
//利息端估值用信息
|
||||
newEodPayPosition.TdInterestPrincipal = interests.Count > 0 ? interests.First().InterestPrincipal : 0;
|
||||
newEodPayPosition.TdInterestPrincipal = position.InterestMode == (int)InterestModeEnum.标的期初全价
|
||||
? posiNotionalValue
|
||||
: interests.Count > 0 ? interests.First().InterestPrincipal : 0;
|
||||
if (interval != null)
|
||||
{
|
||||
newEodPayPosition.TdInterestRate = interval.Rate;
|
||||
@@ -1371,7 +1378,7 @@ namespace YLErp.Modules.SwapModule
|
||||
//当日已实现,平仓时已处理
|
||||
newEodPayPosition.TdInterestFee = flowEvents.Sum(s => s.InterestFee);
|
||||
newEodPayPosition.TdCloseInterestFee = newEodPayPosition.TdInterestFee;
|
||||
newEodPayPosition.TdCloseInterest = flowEvents.Sum(s => s.InterestClosePnL);
|
||||
newEodPayPosition.TdCloseInterest = manualSettledInterestAmount + autoSettledInterestAmount;
|
||||
var intersetAcmount = newEodPayPosition.TdInterestPrincipal * (newEodPayPosition.TdInterestRate + newEodPayPosition.FloatRate);
|
||||
if (position.IsAnnualized)
|
||||
{
|
||||
@@ -1390,7 +1397,8 @@ namespace YLErp.Modules.SwapModule
|
||||
}
|
||||
else
|
||||
{
|
||||
newEodPayPosition.InterestIncomeSum = InterestAmount;
|
||||
newEodPayPosition.InterestIncomeSum = RoundEodInterest(
|
||||
interestAmountBeforeSettlement - newEodPayPosition.TdCloseInterest);
|
||||
newEodPayPosition.InterestFeeSum = eodPayPosition.InterestFeeSum + newEodPayPosition.TdInterestFee - newEodPayPosition.TdCloseInterestFee;
|
||||
}
|
||||
//持仓内容-利息腿-损益统计(本方视角)
|
||||
|
||||
Reference in New Issue
Block a user