refactor(swap): EQD-6977 消除罚息接缝代码臭味道——CalcPenalty 去掉冗余valueDate参数、ComputeCarryBreakdown 去掉未使用position、GetIntradayUnwindInterests 内联块抽为私有AppendPenaltyInterests

This commit is contained in:
hjhan
2026-08-20 13:37:24 +08:00
parent bb8130698f
commit 48ae429fb8
3 changed files with 30 additions and 25 deletions
@@ -68,12 +68,12 @@ public static class PenaltyInterestAppender
var policy = AccrualPolicy.BuildEod(position, annualDays, position.InterestType == (int)InterestTypeEnum.);
var (capitalized, carryIn) = SwapPenaltyInterestCalculator.ComputeCarryBreakdown(
position, unwindDate, resetAnchor, frozenRate, policy, closePrincipal);
unwindDate, resetAnchor, frozenRate, policy, closePrincipal);
var penalty = SwapPenaltyInterestCalculator.CalcPenalty(
td, position, closePrincipal, unwindDate, maturityDate,
unwindDaySettled, maturityCalcLast, capitalized, carryIn,
frozenRate, policy, resetAnchor, eventType, unwindDate);
frozenRate, policy, resetAnchor, eventType);
penalty.IsPenaltyInterest = 1;
interests.Add(penalty);
@@ -42,13 +42,11 @@ public static class SwapPenaltyInterestCalculator
/// <param name="maturityDate">合约原始到期日(窗口终点,= td.ExerciseDate</param>
/// <param name="unwindDaySettled">正常平仓利息是否已计平仓日(effectiveCalcLast = calcLast || newCalcLast</param>
/// <param name="maturityCalcLast">交易到期日算尾约定(tradeExtend.CalcLast</param>
/// <param name="carryInInterest">复利承接:被平部分已计至平仓日利息(正常平仓流 InterestAmount);单利传 0</param>
/// <param name="frozenRate">冻结利率(PenaltyLegRateResolver.ResolveFrozenRate 产物)</param>
/// <param name="frozenRate">冻结利率(PenaltyLegRateResolver.ResolveFrozenRate 产物)</param>
/// <param name="policy">计息政策(单复利/重置周期/年化天数;Convention 由本方法覆盖)</param>
/// <param name="resetAnchor">重置日锚点(对齐 GetFloatRate 的 td.StartDate 口径;锚点二义性注记见其声明)</param>
/// <param name="eventType">事件类型(平仓)</param>
/// <param name="valueDate">操作日期</param>
/// <param name="trace">计息轨迹(可选,SwapCalcTrace 落盘)</param>
/// <param name="trace">计息轨迹(可选,SwapCalcTrace 落盘)</param>
public static swap_flow_event CalcPenalty(
trade td,
swap_position position,
@@ -63,7 +61,6 @@ public static class SwapPenaltyInterestCalculator
AccrualPolicy policy,
DateTime resetAnchor,
int eventType,
DateTime valueDate,
AccrualTrace? trace = null)
{
var boundary = AccrualBoundary.Of(includeStart: !unwindDaySettled, includeEnd: maturityCalcLast);
@@ -82,7 +79,7 @@ public static class SwapPenaltyInterestCalculator
SwapTradeNo = td.TradeNumber,
EventType = eventType,
EventReason = PenaltyEventReason,
EventDate = valueDate,
EventDate = unwindDate,
UnwindDate = unwindDate,
PositionId = position.id,
InterestDirection = position.InterestDirection,
@@ -181,7 +178,7 @@ public static class SwapPenaltyInterestCalculator
/// 单利(无重置)时窗口无 carrycapitalized=全段利息、carryIn=0。
/// </summary>
public static (decimal Capitalized, decimal CarryIn) ComputeCarryBreakdown(
swap_position position, DateTime unwindDate, DateTime resetAnchor,
DateTime unwindDate, DateTime resetAnchor,
FundingLegRate frozenRate, AccrualPolicy policy, decimal closePrincipal)
{
if (policy.ResetPeriodDays <= 1)
+24 -16
View File
@@ -627,25 +627,33 @@ namespace YLErp.Modules.SwapModule
req.OrginPv, req.Add, settment: false, req.NewCalcLast, req.CloseList);
// EQD-6977 罚息:在 GetInterests 返回后追加(避开其 closeList 去重块),仅手动平仓路径(isPenaltyInterest)触发。
if (req.IsPenaltyInterest)
{
var fundingPositions = req.Positions.Where(p => !MarginModes.Contains(p.InterestMode)).ToList();
var annualDays = req.TradeExtend == null ? 365 : req.TradeExtend.ExtendObj.AnnualDays;
var calcLast = req.TradeExtend?.ExtendObj.CalcLast ?? true;
var trace = new AccrualTrace();
PenaltyInterestAppender.Append(
req.Td, fundingPositions, interests, req.UnwindDate, annualDays,
unwindDaySettled: calcLast || req.NewCalcLast,
maturityCalcLast: calcLast,
req.PosiNotionalValue, req.ClosePosiNotionalValue, req.ClosePercent,
getSpread: p => GetFixedRate(p, req.UnwindDate),
getPreEodFloatRate: p => req.EodPositions.FirstOrDefault(x => x.PositionId == p.id)?.FloatRate,
tryGetFixing: (d, code) => IndexFixer.TryGetFixing(d, code, out decimal r) ? (decimal?)r : null,
trace: trace);
SwapCalcTrace.Write(trace); // 与既有 4 处 SwapCalcTrace.Write 同款常驻落盘
}
AppendPenaltyInterests(req, interests);
return interests;
}
/// <summary>
/// EQD-6977 罚息接缝(委托注入 + 轨迹落盘):在 GetInterests 返回后把同构罚息流追加进列表。
/// 仅在此处耦合上帝类的利率解析(GetFixedRate / IndexFixer)与轨迹常驻落盘(SwapCalcTrace.Write),
/// 其余罚息计息数学全部下沉至 Penalty 模块,保持上帝类最小侵入。
/// </summary>
private void AppendPenaltyInterests(InterestCalcRequest req, List<swap_flow_event> interests)
{
var fundingPositions = req.Positions.Where(p => !MarginModes.Contains(p.InterestMode)).ToList();
var annualDays = req.TradeExtend == null ? 365 : req.TradeExtend.ExtendObj.AnnualDays;
var calcLast = req.TradeExtend?.ExtendObj.CalcLast ?? true;
var trace = new AccrualTrace();
PenaltyInterestAppender.Append(
req.Td, fundingPositions, interests, req.UnwindDate, annualDays,
unwindDaySettled: calcLast || req.NewCalcLast,
maturityCalcLast: calcLast,
req.PosiNotionalValue, req.ClosePosiNotionalValue, req.ClosePercent,
getSpread: p => GetFixedRate(p, req.UnwindDate),
getPreEodFloatRate: p => req.EodPositions.FirstOrDefault(x => x.PositionId == p.id)?.FloatRate,
tryGetFixing: (d, code) => IndexFixer.TryGetFixing(d, code, out decimal r) ? (decimal?)r : null,
trace: trace);
SwapCalcTrace.Write(trace); // 与既有 4 处 SwapCalcTrace.Write 同款常驻落盘
}
public List<swap_flow_event> GetInterests(
trade td,
trade_extend tradeExtend,