diff --git a/YLErpDAL/Modules/SwapModule/SwapDealService.cs b/YLErpDAL/Modules/SwapModule/SwapDealService.cs index 9fea70ca..23a7a908 100644 --- a/YLErpDAL/Modules/SwapModule/SwapDealService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapDealService.cs @@ -657,11 +657,11 @@ namespace YLErp.Modules.SwapModule var floateRate = preEodPosition.FloatRate; if (position.InterestType == (int)InterestTypeEnum.复利) { - CalcDailyCompoundInterest(preEodPosition, endDate, position, closePosiNotionalValue, posiNotionalValue, 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); } else { - CalcDailySimpleInterest(preEodPosition, endDate, position, closePosiNotionalValue, posiNotionalValue, interest, annualDays, needPrice, floateRate, closePrecent, orginPv, calcFirst, calcLast, ref InterestAmount, ref TdInterestAmount); + CalcDailySimpleInterest(preEodPosition, endDate, position, posiNotionalValue, interest, annualDays, needPrice, floateRate, closePrecent, orginPv, calcFirst, calcLast, ref InterestAmount, ref TdInterestAmount); } interest.InterestAmount = Math.Round(InterestAmount, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); @@ -685,26 +685,73 @@ namespace YLErp.Modules.SwapModule /// 是否年化 /// 年化天数 /// - public void CalcDailyCompoundInterest(eod_swap_position preEodPosition, DateTime endDate, swap_position position, decimal principal, decimal posiPrincipal, 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) { - // 复利:利息并入本金 - CalcDailyInterest(preEodPosition, endDate, position, principal, posiPrincipal, flowEvent, annualDays, needPrice, floateRate, closePercent, orginPv, compoundInterest: true, calcFirst, calcLast, ref InterestAmount, ref TdInterestAmount); + var startDate = position.PosiStartDate; + decimal interestProfitSum = 0; + decimal TdInterestPrincipal = 0; + decimal interest = interestProfitSum * closePercent; + decimal tdinterest = interestProfitSum * closePercent; + int interestPeriod = position.interest_rest_days ?? 1; + // 复利:只能用要平仓的名义本金从头开始算 + decimal dynomicPrincipal = principal; + decimal tdDynomicPrincipal = dynomicPrincipal; + var calcDays = (endDate - startDate).Days; + double floatRate = Convert.ToDouble(floateRate); + for (int i = 0; i <= calcDays; i++) + { + var accrueDate = startDate.AddDays(i); + if (!calcFirst && accrueDate == startDate) continue; // 首日不算头 + if (!calcLast && accrueDate == endDate) continue; // 到期日不算尾 + if (accrueDate >= startDate) + { + if (i % interestPeriod == 0) + { + // 复利时:利息并入本金 + dynomicPrincipal = principal + interest; + tdDynomicPrincipal = principal + interest; + // 获取新的浮动利率 + if (!string.IsNullOrEmpty(position.FloatRateUnderlyingCode)) + { + var fr007RateDate = QdpCalendarHelper.GetNonHolidayDefore(accrueDate.AddDays(position.interest_rule ?? 0)); + if (TryGetFloatRate(fr007RateDate, position.FloatRateUnderlyingCode, out double floatRate1)) + { + if (floatRate1 != 0) floatRate = floatRate1; + } + else + { + throw new Exception($"获取不到{position.FloatRateUnderlyingCode}在{fr007RateDate:yyyy年MM月dd日}的价格"); + } + } + flowEvent.InterestPrincipal = tdDynomicPrincipal; + TdInterestPrincipal = tdDynomicPrincipal; + } + else + { + // 复利非重置日:利息不并入本金,不用closePercent缩放(principal已反映平仓比例) + flowEvent.InterestPrincipal = tdDynomicPrincipal; + TdInterestPrincipal = tdDynomicPrincipal; + } + flowEvent.FloatRate = Convert.ToDecimal(floatRate); + var interest1 = flowEvent.InterestPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate)); + var tdinterest1 = TdInterestPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate)); + if (position.IsAnnualized) + { + interest1 /= annualDays; + tdinterest1 /= annualDays; + } + interest += interest1; + tdinterest += tdinterest1; + } + } + InterestAmount = Math.Round(interest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); + TdInterestAmount = Math.Round(tdinterest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); } /// /// 计算单利 盘中(按重置天数分段,每段使用对应浮动利率) /// - public void CalcDailySimpleInterest(eod_swap_position preEodPosition, DateTime endDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, decimal orginPv, bool calcFirst, bool calcLast, ref decimal InterestAmount, ref decimal TdInterestAmount) - { - // 单利:利息不并入本金 - CalcDailyInterest(preEodPosition, endDate, position, principal, posiPrincipal, flowEvent, annualDays, needPrice, floateRate, closePercent, orginPv, compoundInterest: false,calcFirst,calcLast, ref InterestAmount, ref TdInterestAmount); - } - - /// - /// 通用日度利息计算方法(单利/复利共用) - /// - /// 是否复利:true=利息并入本金,false=单利 - private void CalcDailyInterest(eod_swap_position preEodPosition, DateTime endDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, decimal orginPv, bool compoundInterest, bool calcFirst, bool calcLast, ref decimal InterestAmount, ref decimal TdInterestAmount) + public void CalcDailySimpleInterest(eod_swap_position preEodPosition, DateTime endDate, swap_position position, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, decimal orginPv, bool calcFirst, bool calcLast, ref decimal InterestAmount, ref decimal TdInterestAmount) { var startDate = position.PosiStartDate; decimal interestProfitSum = preEodPosition.InterestProfitSum; @@ -712,35 +759,27 @@ namespace YLErp.Modules.SwapModule decimal interest = interestProfitSum * closePercent; decimal tdinterest = interestProfitSum * closePercent; int interestPeriod = position.interest_rest_days ?? 1; - decimal dynomicPrincipal = (preEodPosition.TdInterestPrincipal + posiPrincipal - orginPv); + // 单利:可用上一日计息基数 + decimal dynomicPrincipal = preEodPosition.TdInterestPrincipal + posiPrincipal - orginPv; decimal tdDynomicPrincipal = dynomicPrincipal; var calcDays = (endDate - startDate).Days; double floatRate = Convert.ToDouble(floateRate); for (int i = 0; i <= calcDays; i++) { var accrueDate = startDate.AddDays(i); - if (!calcFirst && accrueDate == startDate) continue; // 首日不算头 - if (!calcLast && accrueDate == endDate) continue; // 到期日不算尾 + if (!calcFirst && accrueDate == startDate) continue; // 首日不算头 + if (!calcLast && accrueDate == endDate) continue; // 到期日不算尾 if (accrueDate > preEodPosition.ValueDate) { if (i % interestPeriod == 0) { - // 复利时:利息并入本金 - if (compoundInterest) - { - dynomicPrincipal = principal + interest; - tdDynomicPrincipal = principal + interest; - } // 获取新的浮动利率 if (!string.IsNullOrEmpty(position.FloatRateUnderlyingCode)) { var fr007RateDate = QdpCalendarHelper.GetNonHolidayDefore(accrueDate.AddDays(position.interest_rule ?? 0)); if (TryGetFloatRate(fr007RateDate, position.FloatRateUnderlyingCode, out double floatRate1)) { - if (floatRate1 != 0) - { - floatRate = floatRate1; - } + if (floatRate1 != 0) floatRate = floatRate1; } else {