refactor(accrual): 抽取BuildSegmentRates共享分段取率+清理needPrice死参数
- 抽取 BuildSegmentRates:统一单利/复利分段取率循环,参数化 fetchAfterDate (单利传 ValueDate 仅取新段,复利传 null 全程取) - 修复 BuildSegmentRates static→instance:访问实例属性 IndexFixer - 清理 CalcDaily 层 needPrice 死参数:4个 CalcDaily* 方法签名移除 needPrice;上层 CalcSwapInterests/GetInterests 保留 (virtual seam/位置参数兼容) - 修复 6 处调用点 needPrice 参数传递 - 新增影子测试:单利+FR007浮动+部分平仓+历史归档,验证 segmentRates 一致 - 新增 TdCarryInCharacterizationTest:钉死部分平仓 TdInterestAmount carry-in 行为 测试: 511通过 / 7预存在失败(数据依赖) / 9跳过
This commit is contained in:
@@ -946,12 +946,12 @@ namespace YLErp.Modules.SwapModule
|
||||
if (position.InterestType == (int)InterestTypeEnum.复利)
|
||||
{
|
||||
// 复利计算
|
||||
CalcDailyCompoundInterestByEod(preEod, valueDate, td.StartDate.Value, position, closePrincipal, posiPrincipal, interest, annualDays, false, eodFloatRate, 1m, ref interestAmount, ref tdInterestAmount);
|
||||
CalcDailyCompoundInterestByEod(preEod, valueDate, td.StartDate.Value, position, closePrincipal, posiPrincipal, interest, annualDays, eodFloatRate, 1m, ref interestAmount, ref tdInterestAmount);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 单利计算
|
||||
CalcDailySimpleInterestByEod(preEod, valueDate, td.StartDate.Value, position, closePrincipal, posiPrincipal, interest, annualDays, false, eodFloatRate, 1m, ref interestAmount, ref tdInterestAmount);
|
||||
CalcDailySimpleInterestByEod(preEod, valueDate, td.StartDate.Value, position, closePrincipal, posiPrincipal, interest, annualDays, eodFloatRate, 1m, ref interestAmount, ref tdInterestAmount);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1121,7 +1121,7 @@ namespace YLErp.Modules.SwapModule
|
||||
// 把上日尚未实现的的利息 按本次平掉的这部分计息基数分给本次平仓 并在重置日并入计息基数
|
||||
// 它只在当前 endDate 恰好为重置日时使用,避免把同一笔历史利息重复资本化。
|
||||
var resetCarryInterest = preEodPosition.InterestIncomeSum * remainingPercent;
|
||||
CalcDailyCompoundInterest(endDate, position, closePosiNotionalValue, interest, annualDays, needPrice,
|
||||
CalcDailyCompoundInterest(endDate, position, closePosiNotionalValue, interest, annualDays,
|
||||
floateRate, closePrecent, calcFirst, calcLast, ref InterestAmount, ref TdInterestAmount,
|
||||
consumedInterest, resetCarryInterest);
|
||||
if (preEodPosition.id != 0 && closePrecent == 1m)
|
||||
@@ -1149,7 +1149,7 @@ namespace YLErp.Modules.SwapModule
|
||||
}
|
||||
// 计算截至本次平仓日的累计利息 amountAtEnd
|
||||
CalcDailyCompoundInterest(replayEndDate, position, closePosiNotionalValue,
|
||||
interestAtEnd, annualDays, needPrice, floateRate, closePrecent,
|
||||
interestAtEnd, annualDays, floateRate, closePrecent,
|
||||
calcFirst, calcLast, ref amountAtEnd, ref tdAmountAtEnd, consumedInterest);
|
||||
var interestAtPreviousEod = new swap_flow_event { InterestRate = rate };
|
||||
decimal amountAtPreviousEod = 0m;
|
||||
@@ -1158,7 +1158,7 @@ namespace YLErp.Modules.SwapModule
|
||||
// 因此此处按闭区间包含上一日终当天,避免算头不算尾时重复加入该日利息。
|
||||
// 计算截至上一日终累积的利息 amountAtPreviousEod
|
||||
CalcDailyCompoundInterest(preEodPosition.ValueDate, position, closePosiNotionalValue,
|
||||
interestAtPreviousEod, annualDays, needPrice, floateRate, closePrecent,
|
||||
interestAtPreviousEod, annualDays, floateRate, closePrecent,
|
||||
calcFirst, true, ref amountAtPreviousEod, ref tdAmountAtPreviousEod, consumedInterest);
|
||||
// 例如 0004:5/18 待实现 -118631.261797,加 5/19 新增约 -4648.912760,
|
||||
// 得到最终应结 -123280.174557,按金额两位落为 Excel BN 的 -123280.17。
|
||||
@@ -1170,7 +1170,7 @@ namespace YLErp.Modules.SwapModule
|
||||
}
|
||||
else
|
||||
{
|
||||
CalcDailySimpleInterest(preEodPosition, endDate, position, posiNotionalValue, interest, annualDays, needPrice, floateRate, closePrecent, orginPv, calcFirst, calcLast, ref InterestAmount, ref TdInterestAmount);
|
||||
CalcDailySimpleInterest(preEodPosition, endDate, position, posiNotionalValue, interest, annualDays, floateRate, closePrecent, orginPv, calcFirst, calcLast, ref InterestAmount, ref TdInterestAmount);
|
||||
}
|
||||
|
||||
interest.InterestAmount = Math.Round(InterestAmount, InterestCalculationPrecision, MidpointRounding.AwayFromZero);
|
||||
@@ -1231,7 +1231,7 @@ namespace YLErp.Modules.SwapModule
|
||||
/// <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, bool calcFirst, bool calcLast,
|
||||
int annualDays, decimal floateRate, decimal closePercent, bool calcFirst, bool calcLast,
|
||||
ref decimal InterestAmount, ref decimal TdInterestAmount, decimal consumedInterest = 0m, decimal resetCarryInterest = 0m)
|
||||
{
|
||||
var startDate = position.PosiStartDate;
|
||||
@@ -1270,7 +1270,7 @@ namespace YLErp.Modules.SwapModule
|
||||
/// <summary>
|
||||
/// 计算单利 盘中(按重置天数分段,每段使用对应浮动利率)
|
||||
/// </summary>
|
||||
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, decimal consumedInterest = 0m)
|
||||
public void CalcDailySimpleInterest(eod_swap_position preEodPosition, DateTime endDate, swap_position position, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, decimal floateRate, decimal closePercent, decimal orginPv, bool calcFirst, bool calcLast, ref decimal InterestAmount, ref decimal TdInterestAmount, decimal consumedInterest = 0m)
|
||||
{
|
||||
var startDate = position.PosiStartDate;
|
||||
int interestPeriod = position.interest_rest_days ?? 1;
|
||||
@@ -1320,7 +1320,7 @@ namespace YLErp.Modules.SwapModule
|
||||
/// <param name="isAnnualized">是否年化</param>
|
||||
/// <param name="annualDays">年化天数</param>
|
||||
/// <returns></returns>
|
||||
public void CalcDailyCompoundInterestByEod(eod_swap_position preEodPosition, DateTime endDate, DateTime tradeDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, ref decimal InterestAmount, ref decimal TdInterestAmount)
|
||||
public void CalcDailyCompoundInterestByEod(eod_swap_position preEodPosition, DateTime endDate, DateTime tradeDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, decimal floateRate, decimal closePercent, ref decimal InterestAmount, ref decimal TdInterestAmount)
|
||||
{
|
||||
int interestPeriod = position.interest_rest_days ?? 1;
|
||||
var isResetDay = (endDate - tradeDate).Days % interestPeriod == 0;
|
||||
@@ -1367,7 +1367,7 @@ namespace YLErp.Modules.SwapModule
|
||||
/// <summary>
|
||||
/// 计算单利 收盘(按重置天数分段,每段使用对应浮动利率)
|
||||
/// </summary>
|
||||
public void CalcDailySimpleInterestByEod(eod_swap_position preEodPosition, DateTime endDate, DateTime tradeDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, ref decimal InterestAmount, ref decimal TdInterestAmount)
|
||||
public void CalcDailySimpleInterestByEod(eod_swap_position preEodPosition, DateTime endDate, DateTime tradeDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, decimal floateRate, decimal closePercent, ref decimal InterestAmount, ref decimal TdInterestAmount)
|
||||
{
|
||||
// 首次操作(preEod.id == 0):计息基数按存量本金初始化——保留旧行为(含对 preEod 的就地修正)。
|
||||
if (preEodPosition.id == 0)
|
||||
|
||||
Reference in New Issue
Block a user