客户设置互换天数&利息计算重置频率

This commit is contained in:
吴方海
2025-04-14 16:31:35 +08:00
parent cbe8b2dc91
commit 5250a37d08
29 changed files with 637 additions and 389 deletions
+62 -43
View File
@@ -400,8 +400,8 @@ namespace YLErp.Modules.SwapModule
}
else if (position.InterestMode == (int)InterestModeEnum.)
{
_closePosiNotionalValue = _posiNotionalValue * grossPrice * closePrecent;
_posiNotionalValue = _posiNotionalValue * grossPrice;
_closePosiNotionalValue = _posiNotionalValue * closePrecent;
_posiNotionalValue = _posiNotionalValue;
}
else if (position.InterestMode == (int)InterestModeEnum. || position.InterestMode == (int)InterestModeEnum.)
{
@@ -409,24 +409,36 @@ namespace YLErp.Modules.SwapModule
_posiNotionalValue = position.InterestPrincipalFix * closePrecent;
positionClone.InterestDirection = position.InterestDirection == (int)SwapDirectionEnum. ? (int)SwapDirectionEnum. : (int)SwapDirectionEnum.;
}
var calendar = "chn";
if (!string.IsNullOrEmpty(position.FloatRateUnderlyingCode))
{
var rateDate = td.StartDate.Value.AddDays(-1);
if (EodPriceQueryService.TryGetPrice(rateDate, position.FloatRateUnderlyingCode, out double floatRate))
// 获取重置频率,如果为空则默认为1
int interestPeriod = position.interest_rest_days ?? 1;
// 计算从 td.StartDate 到 endDate 的天数
var days = (endDate - td.StartDate.Value).Days;
// 获取合适的 rateDate
DateTime rateDate = GetRateDate(position.interest_rule, td.StartDate.Value, endDate, days, interestPeriod, calendar);
// 如果不需要重置,并且上一日已有 FloatRate,则不再查找
if (preEodPosition.id != 0 && days % interestPeriod != 0)
{
position.FloatRate = Convert.ToDecimal(floatRate);
positionClone.FloatRate = position.FloatRate;
if (preEodPosition.id == 0)
position.FloatRate = preEodPosition.FloatRate;
positionClone.FloatRate = preEodPosition.FloatRate;
}
else
{
// 如果没有 preEodPosition 数据或需要查找新 Rate,则去查询最新的浮动利率
if (EodPriceQueryService.TryGetPrice(rateDate, position.FloatRateUnderlyingCode, out double floatRate))
{
preEodPosition.FloatRate = positionClone.FloatRate;
preEodPosition.TdInterestPrincipal = _posiNotionalValue;
position.FloatRate = Convert.ToDecimal(floatRate);
positionClone.FloatRate = position.FloatRate;
}
else if (needPrice)
{
throw new Exception($"获取不到{position.FloatRateUnderlyingCode}在{rateDate:yyyy年MM月dd日}的价格");
}
}
else if (needPrice)
{
throw new Exception($"获取不到{position.FloatRateUnderlyingCode}在{rateDate:yyyy年MM月dd日}的价格");
}
}
decimal rate = position.InterestRateDefault;
if (swapIntervalToday == null)//当日无适用观察日
@@ -453,6 +465,20 @@ namespace YLErp.Modules.SwapModule
return interests;
}
/// <summary>
/// 根据给定条件获取 rateDate
/// </summary>
private DateTime GetRateDate(int? interest_rule, DateTime startDate, DateTime endDate, int days, int interestPeriod, string calendar)
{
// 判断是否达到重置周期
if (days % interestPeriod == 0)
{
return QdpCalendarHelper.GetNonHolidayDefore(endDate.AddDays(interest_rule ?? 0), calendar);
}
// 如果不在重置周期内,使用 td.StartDate 来获取 rateDate
return QdpCalendarHelper.GetNonHolidayDefore(startDate.AddDays(interest_rule ?? 0), calendar);
}
/// <summary>
/// 初始化利息腿信息
/// </summary>
/// <param name="tradeId">交易编码</param>
@@ -591,7 +617,7 @@ namespace YLErp.Modules.SwapModule
var TdInterestPrincipal = preEodPosition.TdInterestPrincipal;
decimal interest = 0;
decimal tdinterest = 0;
int interestPeriod = 7;
int interestPeriod = position.interest_rest_days ?? 1;
decimal dynomicPrincipal = principal;
decimal tdDynomicPrincipal = posiPrincipal;
var calcDays = (endDate - tradeDate).Days;
@@ -605,14 +631,9 @@ namespace YLErp.Modules.SwapModule
{
dynomicPrincipal = dynomicPrincipal + interest;
tdDynomicPrincipal = tdDynomicPrincipal + interest;
//if (rateDate > tradeDate)
//{
// dynomicPrincipal += interestProfitSum;
// tdDynomicPrincipal += interestProfitSum;
//}
if (!string.IsNullOrEmpty(position.FloatRateUnderlyingCode))
{
var fr007RateDate = rateDate.AddDays(-1);
var fr007RateDate = QdpCalendarHelper.GetNonHolidayDefore(endDate.AddDays(position.interest_rule ?? 0)); // 获取前一工作日;
if (EodPriceQueryService.TryGetPrice(fr007RateDate, position.FloatRateUnderlyingCode, out double floatRate1))
{
if (floatRate1 != 0)
@@ -675,7 +696,7 @@ namespace YLErp.Modules.SwapModule
decimal interestProfitSum = preEodPosition.InterestProfitSum;
decimal interest = preEodPosition.TdInterestIncome;
decimal tdinterest = preEodPosition.TdInterestIncome;
int interestPeriod = 7;
int interestPeriod = position.interest_rest_days ?? 1;
decimal tdDynomicPrincipal = posiPrincipal;
double floatRate = Convert.ToDouble(floateRate);
var days = (endDate - tradeDate).Days;
@@ -684,7 +705,8 @@ namespace YLErp.Modules.SwapModule
tdDynomicPrincipal = tdDynomicPrincipal + interestProfitSum;
if (!string.IsNullOrEmpty(position.FloatRateUnderlyingCode))
{
var fr007RateDate = endDate.AddDays(-1);
// 获取合适的 rateDate
var fr007RateDate = QdpCalendarHelper.GetNonHolidayDefore(endDate.AddDays(position.interest_rule ?? 0)); // 获取前一工作日;
if (EodPriceQueryService.TryGetPrice(fr007RateDate, position.FloatRateUnderlyingCode, out double floatRate1))
{
if (floatRate1 != 0)
@@ -696,32 +718,29 @@ namespace YLErp.Modules.SwapModule
{
throw new Exception($"获取不到{position.FloatRateUnderlyingCode}在{fr007RateDate:yyyy年MM月dd日}的价格");
}
flowEvent.InterestPrincipal = tdDynomicPrincipal * closePercent;
interest = flowEvent.InterestPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate));
tdinterest = tdDynomicPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate));
if (position.IsAnnualized)
{
interest /= annualDays;
tdinterest /= annualDays;
}
}
else
flowEvent.InterestPrincipal = tdDynomicPrincipal * closePercent;
interest = flowEvent.InterestPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate));
tdinterest = tdDynomicPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate));
if (position.IsAnnualized)
{
flowEvent.InterestPrincipal = (preEodPosition.TdInterestPrincipal + tdDynomicPrincipal - orginPv) * closePercent;
var interest1 = flowEvent.InterestPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate));
var tdinterest1 = (preEodPosition.TdInterestPrincipal + tdDynomicPrincipal - orginPv) * (flowEvent.InterestRate + Convert.ToDecimal(floatRate));
if (position.IsAnnualized)
{
interest1 /= annualDays;
tdinterest1 /= annualDays;
}
interest = interest1;
tdinterest = tdinterest1;
interest /= annualDays;
tdinterest /= annualDays;
}
}
else
{
flowEvent.InterestPrincipal = preEodPosition.TdInterestPrincipal * closePercent;
flowEvent.InterestPrincipal = (preEodPosition.TdInterestPrincipal + tdDynomicPrincipal - orginPv) * closePercent;
var interest1 = flowEvent.InterestPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate));
var tdinterest1 = (preEodPosition.TdInterestPrincipal + tdDynomicPrincipal - orginPv) * (flowEvent.InterestRate + Convert.ToDecimal(floatRate));
if (position.IsAnnualized)
{
interest1 /= annualDays;
tdinterest1 /= annualDays;
}
interest = interest1;
tdinterest = tdinterest1;
}
flowEvent.FloatRate = Convert.ToDecimal(floatRate);
InterestAmount = Math.Round(interest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);