refactor(swap): EQD-6968 取价口径自洽化——排除日纯跳过+持仓延续重置日显式再定盘

取价规则只由交易属性决定(算不算尾/interest_rule/重置日历),平仓只切窗口:
① BuildSegmentRates 排除日(不算尾尾日)一概不取价(有价也不取)——事件利率恒为
   末段已消费利率,与金额同源、与平仓时刻无关(旧口径下午平仓落库新利率,金额
   却用旧利率,且上午/下午记录不同);金额零变更(排除日本就零消费)。
② GetFloatRate 不算尾重置日不再先试取尾日定盘(原'有价则取'分支删除)。
③ 剩余持仓的新周期利率改由 SwapEodPositionService 显式获取:平仓日恰为重置日
   且剩余>0 时,快照 FloatRate 经 ResolveOngoingResetFixing 再定盘为当日新定盘
   (生产 GetFixingOrThrow,缺价抛——与 ByEod 重置日/EodCheckSettlePrice 同口径;
   原'有价则取'顺带承担此载体职责,现显式分离)。全平/算尾/观察日无需再定盘。
④ 无日终快照播种 priorValueDate 恒=开始日-1:首重置日(=开始日)的定盘覆盖
   [开始日,下一重置日)全部计息日(不算头时 7/7 起仍属首段),必须落在取价窗内。
   原仅算头回拨一天,不算头时首段误用种子利率(靠②的尾日取价回填掩盖,现已根治)。
   '不算头少计一天'仍由计息边界 IncludeStart=false 承担,天数不变、利率归位。
FIX 日志同步:排除日不取价/EodCloseRefix 再定盘 全程可审计。

验证:全量 976 例 145 败与改动前基线失败名单 diff=0;内存套件(含
ContractReferenceOracle 金标准/InterestEodTailSnapshot)全绿
This commit is contained in:
hjhan
2026-08-19 11:06:52 +08:00
parent e779347488
commit fafae5cac0
2 changed files with 47 additions and 23 deletions
@@ -117,6 +117,14 @@ namespace YLErp.Modules.SwapModule
req.ClosePosiNotionalValue, req.ClosePercent, req.EventType, req.TdClose,
req.OrginPv, req.Add, settment: false, req.NewCalcLast, req.CloseList);
/// <summary>
/// 持仓延续腿重置日再定盘(EQD-6968 口径自洽化接缝)。
/// 生产:Fr007IndexFixer.GetFixingOrThrow——缺价抛异常,与 ByEod 重置日再定盘/EodCheckSettlePrice
/// 同口径(EOD 时点当日 FR007 已由收盘前检查把关);测试:override 注入受控定盘。
/// </summary>
protected virtual decimal ResolveOngoingResetFixing(swap_position position, DateTime valueDate)
=> Fr007IndexFixer.Instance.GetFixingOrThrow(valueDate, position.interest_rule, position.FloatRateUnderlyingCode);
// FindTrade 已上提到基类 SwapTradeBaseService(三子类实现一致,消除重复)
/// <summary>查找交易扩展(生产: DbContext.trade_extend;测试: 内存字典)</summary>
@@ -1361,6 +1369,20 @@ namespace YLErp.Modules.SwapModule
//持仓内容-利息腿(FloatRate 取计息结果)。InterestPrincipalFix 保持腿现值:
// ResolveInterestLegPositions 已提供平仓后的实时剩余本金,日终不再重复扣减(勿恢复 *(1-closePercent))。
CopyInterestLegFields(newEodPayPosition, position, interests.Count > 0 ? interests.First().FloatRate ?? 0 : 0);
// ── 持仓延续腿重置日再定盘(EQD-6968 自洽化)──
// 排除日取价已收口为"纯跳过":事件利率=末段已消费利率。但剩余持仓自当日起进入新计息周期,
// 快照 FloatRate 是后续非重置日(ByEod 沿用 preEod.FloatRate)与当日应计(intersetAcmount)的
// 利率载体——平仓日恰为重置日时必须显式取当日新定盘(与 ByEod 日增路径的重置日行为同构)。
// 全平(剩余=0)/算尾(事件利率已是新定盘)/观察日(autoSwap 恒1已含当日)无需再定盘。
if (!autoSwap && !calcLast && posiNotionalValue > 0m
&& !string.IsNullOrEmpty(position.FloatRateUnderlyingCode)
&& SwapDealService.IsResetDay(valueDate, td.StartDate.Value, position.interest_rest_days ?? 1))
{
var ongoingFixing = ResolveOngoingResetFixing(position, valueDate);
SwapCalcTrace.Critical(
$"FIX EodCloseRefix p{position.id} {valueDate:yyyy-MM-dd} 平仓日=重置日→剩余持仓快照再定盘 {newEodPayPosition.FloatRate:P6}→{ongoingFixing:P6}");
newEodPayPosition.FloatRate = ongoingFixing;
}
//利息端估值用信息
// TdInterestPrincipal 是“下一日继续计息的收盘后本金”,不是原始合同规模,也不是本次平仓本金。
// 模式9单利直接取剩余名义本金;复利还要保留重置时已经并入本金的待实现利息。