BugFix 复利计算的没有扣除手动互换长生的利息端费用
This commit is contained in:
@@ -338,6 +338,27 @@ namespace YLErp.Modules.SwapModule
|
||||
interests = GetInterests(td, tradeExtend, valueDate, unwindDate, lastEodPositions, positions, stockEqvNotional, posiLongNotionalValue, posiShortNotionalValue, posiNotionalValue, closePercent, eventType, tdClose, false, grossPrice ?? 0, orginPv, true, false,false, closeList);
|
||||
return interests;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取利息腿"已通过历史互换结出的累计利息"(用于复利重算时扣除,类比分红的 CalcConsumedDividend)。
|
||||
/// 数据源为事件级 swap_flow_event.InterestAmount(互换/自动互换 完成态事件,互换当时即落库,不依赖日终归档)。
|
||||
/// </summary>
|
||||
/// <param name="tradeId">交易id</param>
|
||||
/// <param name="positionId">利息腿id</param>
|
||||
/// <param name="beforeDate">结算日(不含,仅汇总此日之前的历史已结利息;当日事件由 closeList 去重逻辑单独处理)</param>
|
||||
/// <returns>历史已结利息累计金额(绝对值)</returns>
|
||||
public decimal GetConsumedInterest(int tradeId, long positionId, DateTime beforeDate)
|
||||
{
|
||||
List<int> swapEventTypes = new List<int>() { (int)SwapEventTypeEnum.互换, (int)SwapEventTypeEnum.自动互换 };
|
||||
var consumed = DbContext.swap_flow_event
|
||||
.Where(x => x.SwapTradeId == tradeId && x.PositionId == positionId
|
||||
&& swapEventTypes.Contains(x.EventType)
|
||||
&& x.DataState == (int)SwapFlowDateStateEnum.完成
|
||||
&& x.EventDate < beforeDate)
|
||||
.Sum(s => (decimal?)s.InterestAmount) ?? 0m;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算利息腿计息详细
|
||||
/// </summary>
|
||||
@@ -412,7 +433,11 @@ namespace YLErp.Modules.SwapModule
|
||||
else
|
||||
{
|
||||
// 盘中互换场景,使用 CalcUnwindInterest
|
||||
interests.Add(CalcUnwindInterest(td, valueDate, endDate, positionClone, rate, floatRate, posiPrincipal, closePrincipal, newClosePercent, annualDays, preEodPosition, eventType, add, swap, orginPv, calcFirst, calcLast||newCalcLast));
|
||||
// 取历史已结利息(事件级,互换当时落库),供复利重算扣除(仅复利需要;单利基于日终快照自带状态)
|
||||
var consumedInterest = position.InterestType == (int)InterestTypeEnum.复利
|
||||
? GetConsumedInterest(td.id, position.id, endDate)
|
||||
: 0m;
|
||||
interests.Add(CalcUnwindInterest(td, valueDate, endDate, positionClone, rate, floatRate, posiPrincipal, closePrincipal, newClosePercent, annualDays, preEodPosition, eventType, add, swap, orginPv, calcFirst, calcLast||newCalcLast, consumedInterest));
|
||||
}
|
||||
}
|
||||
//当日有平仓或互换记录时,避免重复结算
|
||||
@@ -592,7 +617,7 @@ namespace YLErp.Modules.SwapModule
|
||||
/// <summary>
|
||||
/// 计算盘中利息(平仓/互换)
|
||||
/// </summary>
|
||||
private swap_flow_event CalcUnwindInterest(trade td, DateTime valueDate, DateTime endDate, swap_position position, decimal rate, decimal floatRate, decimal posiPrincipal, decimal closePrincipal, decimal closePercent, int annualDays, eod_swap_position preEod, int eventType, bool add, bool swap, decimal orginPv, bool calcFirst, bool calcLast)
|
||||
private swap_flow_event CalcUnwindInterest(trade td, DateTime valueDate, DateTime endDate, swap_position position, decimal rate, decimal floatRate, decimal posiPrincipal, decimal closePrincipal, decimal closePercent, int annualDays, eod_swap_position preEod, int eventType, bool add, bool swap, decimal orginPv, bool calcFirst, bool calcLast, decimal consumedInterest = 0m)
|
||||
{
|
||||
if (preEod.id == 0)
|
||||
{
|
||||
@@ -606,7 +631,7 @@ namespace YLErp.Modules.SwapModule
|
||||
}
|
||||
}
|
||||
|
||||
return InitSwapDealInterest(td, valueDate, endDate, rate, position, add, swap, posiPrincipal, closePrincipal, closePercent, annualDays, eventType, preEod, false, orginPv, calcFirst, calcLast);
|
||||
return InitSwapDealInterest(td, valueDate, endDate, rate, position, add, swap, posiPrincipal, closePrincipal, closePercent, annualDays, eventType, preEod, false, orginPv, calcFirst, calcLast, consumedInterest);
|
||||
}
|
||||
/// <summary>
|
||||
/// 初始化利息腿信息
|
||||
@@ -638,8 +663,9 @@ namespace YLErp.Modules.SwapModule
|
||||
eod_swap_position preEodPosition,
|
||||
bool needPrice,
|
||||
decimal orginPv,
|
||||
bool calcFirst,
|
||||
bool calcLast
|
||||
bool calcFirst,
|
||||
bool calcLast,
|
||||
decimal consumedInterest = 0m
|
||||
)
|
||||
{
|
||||
decimal interestProfitSum = preEodPosition.InterestProfitSum;
|
||||
@@ -674,7 +700,7 @@ namespace YLErp.Modules.SwapModule
|
||||
var floateRate = preEodPosition.FloatRate;
|
||||
if (position.InterestType == (int)InterestTypeEnum.复利)
|
||||
{
|
||||
CalcDailyCompoundInterest( endDate, position, closePosiNotionalValue, interest, annualDays, needPrice, floateRate, closePrecent, orginPv, calcFirst, calcLast, ref InterestAmount, ref TdInterestAmount);
|
||||
CalcDailyCompoundInterest( endDate, position, closePosiNotionalValue, interest, annualDays, needPrice, floateRate, closePrecent, orginPv, calcFirst, calcLast, ref InterestAmount, ref TdInterestAmount, consumedInterest);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -702,7 +728,7 @@ namespace YLErp.Modules.SwapModule
|
||||
/// <param name="isAnnualized">是否年化</param>
|
||||
/// <param name="annualDays">年化天数</param>
|
||||
/// <returns></returns>
|
||||
public void CalcDailyCompoundInterest( DateTime endDate, swap_position position, decimal principal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, decimal orginPv, bool calcFirst, bool calcLast, ref decimal InterestAmount, ref decimal TdInterestAmount)
|
||||
public void CalcDailyCompoundInterest( DateTime endDate, swap_position position, decimal principal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, decimal orginPv, bool calcFirst, bool calcLast, ref decimal InterestAmount, ref decimal TdInterestAmount, decimal consumedInterest = 0m)
|
||||
{
|
||||
var startDate = position.PosiStartDate;
|
||||
decimal interestProfitSum = 0;
|
||||
@@ -761,6 +787,11 @@ namespace YLErp.Modules.SwapModule
|
||||
tdinterest += tdinterest1;
|
||||
}
|
||||
}
|
||||
// 复利从头重放得到的是"假设从未结出"的整段总利息,需扣除历史已通过互换结出的利息,
|
||||
// 否则已结部分会重复计息(类比分红 PosiDividendSum = totalToDate − RealizedDividend)。
|
||||
// consumedInterest 为绝对值口径(swap_flow_event.InterestAmount 之和),与 interest 口径一致。
|
||||
interest -= consumedInterest;
|
||||
tdinterest -= consumedInterest;
|
||||
InterestAmount = Math.Round(interest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
|
||||
TdInterestAmount = Math.Round(tdinterest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user