fix(swap): 修复重置日期利息计算逻辑

- 修正了 calcLast=false 时重置日取价被跳过的问题
- 确保重置日之前的复利能够正确并入本金
- 调整了计息日判断逻辑的位置以保证本金重置正常执行
- 修复了重置日当天利息不应被计入的逻辑错误
This commit is contained in:
张名锐
2026-08-07 21:54:04 +08:00
parent 19d8b2a926
commit 569002e551
2 changed files with 83 additions and 7 deletions
+22 -7
View File
@@ -1205,7 +1205,14 @@ 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, consumedInterest);
var remainingPercent = preEodPosition.TdInterestPrincipal > 0m
? closePosiNotionalValue / preEodPosition.TdInterestPrincipal
: 1m;
remainingPercent = Math.Max(0m, Math.Min(1m, remainingPercent));
var resetCarryInterest = preEodPosition.InterestIncomeSum * remainingPercent;
CalcDailyCompoundInterest(endDate, position, closePosiNotionalValue, interest, annualDays, needPrice,
floateRate, closePrecent, orginPv, calcFirst, calcLast, ref InterestAmount, ref TdInterestAmount,
consumedInterest, resetCarryInterest);
}
else
{
@@ -1233,7 +1240,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, decimal consumedInterest = 0m)
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, decimal resetCarryInterest = 0m)
{
var startDate = position.PosiStartDate;
decimal interestProfitSum = 0;
@@ -1265,15 +1272,14 @@ namespace YLErp.Modules.SwapModule
throw new Exception($"获取不到{position.FloatRateUnderlyingCode}在{fr007RateDate:yyyy年MM月dd日}的价格");
}
}
if (!calcFirst && accrueDate == startDate) continue; // 首日不算头
if (!calcLast && accrueDate == endDate) continue; // 到期日不算尾(只跳过计息,取价已在上方完成)
if (accrueDate >= startDate)
{
if (i % interestPeriod == 0)
{
// 复利时:利息并入本金(FR007 取价已提前到 calcFirst/calcLast 跳过之前完成)
dynomicPrincipal = principal + interest;
tdDynomicPrincipal = principal + interest;
var interestToReset = i == 0 || resetCarryInterest == 0m ? interest : resetCarryInterest;
dynomicPrincipal = principal + interestToReset;
tdDynomicPrincipal = principal + interestToReset;
flowEvent.InterestPrincipal = tdDynomicPrincipal;
TdInterestPrincipal = tdDynomicPrincipal;
}
@@ -1283,6 +1289,11 @@ namespace YLErp.Modules.SwapModule
flowEvent.InterestPrincipal = tdDynomicPrincipal;
TdInterestPrincipal = tdDynomicPrincipal;
}
}
if (!calcFirst && accrueDate == startDate) continue; // 首日不算头
if (!calcLast && accrueDate == endDate) continue; // 到期日不算尾(只跳过计息,重置本金已在上方完成)
if (accrueDate >= startDate)
{
flowEvent.FloatRate = Convert.ToDecimal(floatRate);
var interest1 = flowEvent.InterestPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate));
var tdinterest1 = TdInterestPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate));
@@ -1391,7 +1402,11 @@ namespace YLErp.Modules.SwapModule
var days = (endDate - tradeDate).Days;
if (days % interestPeriod == 0)
{
tdDynomicPrincipal = tdDynomicPrincipal + interestProfitSum;
var remainingPercent = preEodPosition.TdInterestPrincipal > 0m
? principal / preEodPosition.TdInterestPrincipal
: 1m;
remainingPercent = Math.Max(0m, Math.Min(1m, remainingPercent));
tdDynomicPrincipal = tdDynomicPrincipal + interestProfitSum * remainingPercent;
if (!string.IsNullOrEmpty(position.FloatRateUnderlyingCode))
{
// 获取合适的 rateDate