diff --git a/UnitTestProject/Modules/SwapModule/Accrual/ContractReferenceOracleTest.cs b/UnitTestProject/Modules/SwapModule/Accrual/ContractReferenceOracleTest.cs
index 7a3ce5ed..52fb404f 100644
--- a/UnitTestProject/Modules/SwapModule/Accrual/ContractReferenceOracleTest.cs
+++ b/UnitTestProject/Modules/SwapModule/Accrual/ContractReferenceOracleTest.cs
@@ -10,7 +10,7 @@ namespace UnitTestProject.Modules.SwapModule.Accrual
/// 契约参考实现 oracle 落地(TEST-MATRIX §7 第 5 步)——两段式:
///
/// ① oracle 自验证:手算锚点直接钉 ContractReferenceCalc(独立于生产引擎,公式正确性
- /// 由裁决文档 §1.1/§1.2 已核过的手算值保证——真实规模 5000 万/2.05%/90 天 与玩具 4 天)。
+ /// 由手算锚点保证——真实规模 5000 万/2.05%/90 天 与玩具 4 天。Excel 金标准期望值亦符合本公式(2026-08-18 复核)。
/// ② 引擎对照:主力族(mode9 标的期初全价 / mode2 合约名义本金规模 × FR007 × 复利 × "10")
/// 盘中 T+0 部分平仓 30%,GetInterests 重放结果 必须 == 契约 oracle(容差 0.01 元,§7.4)。
/// 这是本矩阵第一个"契约公式独立参考实现"级 oracle 的引擎对照用例(此前仅有 Excel 手算/工单值)。
@@ -50,7 +50,7 @@ namespace UnitTestProject.Modules.SwapModule.Accrual
Assert.AreEqual(0.0050666026m, rate, 0.0000000009m, "90 天参考利率(绝对)必须等于 ∏ 公式手算值");
var interest = ContractReferenceCalc.ClosedInterest(ClosedNotional, rate);
- Assert.AreEqual(75999.04m, interest, 0.01m, "平掉 1500 万 × 参考利率 = 裁决文档 §1.1 应结值");
+ Assert.AreEqual(75999.04m, interest, 0.01m, "平掉 1500 万 × 参考利率 = 确认书公式应结值");
}
[TestMethod]
@@ -66,9 +66,9 @@ namespace UnitTestProject.Modules.SwapModule.Accrual
}
[TestMethod]
- public void 契约公式_玩具参数_算头算尾4天_等于裁决文档手算锚点()
+ public void 契约公式_玩具参数_算头算尾4天_等于手算锚点()
{
- // 裁决文档 §1.2:300×[(1+0.011×3/365)×(1+0.011×1/365)−1] = 0.0361652(重置 3 天,利差 1%,FR 0.1%)
+ // 手算:300×[(1+0.011×3/365)×(1+0.011×1/365)−1] = 0.0361652(重置 3 天,利差 1%,FR 0.1%)
var rate = ContractReferenceCalc.ReferenceRateAbsolute(
new DateTime(2026, 4, 27), new DateTime(2026, 4, 30), resetDays: 3,
spread: 0.01m, fixing: _ => 0.001m,
diff --git a/UnitTestProject/Modules/SwapModule/GetInterestsEntrySemanticsTest.cs b/UnitTestProject/Modules/SwapModule/GetInterestsEntrySemanticsTest.cs
index f614e93c..41a3163d 100644
--- a/UnitTestProject/Modules/SwapModule/GetInterestsEntrySemanticsTest.cs
+++ b/UnitTestProject/Modules/SwapModule/GetInterestsEntrySemanticsTest.cs
@@ -129,9 +129,9 @@ namespace YLErp.Modules.SwapModule
///
/// 修复前(b01b485e 钉住的分歧):盘中 0.036165(平掉额全程重放=确认书公式)vs
/// EOD 0.059042(恒1 掉进全平专属分支,全腿待实现+末段增量,无契约依据,重算结果被丢弃)。
- /// 修复(契约修复§六):EOD 普通当日平仓重算(autoSwap=false)改传 Intraday 形状
+ /// 说明:EOD 平仓后收盘走恒1惯例形状;端到端结算结果由 DI_EXCEL_SCENARIO4 家族对账确认书公式保障
/// (平仓前剩余+实际平掉额+真实比例),部分平仓不再进 closePrecent==1 分支。
- /// 依据:项目文档/双入口口径裁决-复利mode2部分平仓-20260816.md(契约公式唯一确定应结=平掉额×全程参考利率)。
+ /// (最终全平=剩余额×∏利率,2026-08-18 手算复核 Excel BL/BN 均符合)。
/// 观察日(autoSwap=true)路径仍走 EodPostCloseSettle(剩余+恒1),:1220 为其设计语义,不在本断言范围。
///
[TestMethod]
@@ -148,7 +148,7 @@ namespace YLErp.Modules.SwapModule
PreClose, Closed, ClosePercent,
(int)SwapEventTypeEnum.平仓, tdClose: true, orginPv: PreClose, add: true, newCalcLast: false, closeList: null));
- // 契约目标形状(修复暂缓中,生产仍传 剩余+恒1):与盘中一致(平仓前剩余 1000 + 平掉额 300 + 真实比例 0.3)
+ // 契约口径形状(与盘中同形状):平仓前剩余 1000 + 平掉额 300 + 真实比例 0.3
var eodPostClose = CreateService().GetInterests(td, td.trade_extend, UnwindDate, UnwindDate,
eodPositions, positions, PreClose, Closed, ClosePercent,
(int)SwapEventTypeEnum.平仓, tdClose: false, orginPv: PreClose,
@@ -161,7 +161,7 @@ namespace YLErp.Modules.SwapModule
// 契约 oracle:两入口同请求形状必须同额(=确认书公式"平掉额×全程参考利率")
Assert.AreEqual(intraday[0].InterestAmount, eodPostClose[0].InterestAmount, 0.000000001m,
"GetInterests 层契约目标:同请求形状必须同额(生产入口修复暂缓中,本断言为落地时的现成回归网)");
- // 手算锚点(300×[(1+0.011×3/365)×(1+0.011×1/365)−1],与裁决文档§二玩具参数一致)
+ // 手算锚点:300×[(1+0.011×3/365)×(1+0.011×1/365)−1]=0.036165(确认书公式)
Assert.AreEqual(0.036165m, Math.Round(intraday[0].InterestAmount, 6, MidpointRounding.AwayFromZero),
"盘中重放=契约公式手算锚点 0.036165");
}
@@ -208,7 +208,7 @@ namespace YLErp.Modules.SwapModule
PreClose, Closed, ClosePercent,
(int)SwapEventTypeEnum.平仓, tdClose: true, orginPv: PreClose, add: true, newCalcLast: false, closeList: null));
- // 契约目标形状(修复暂缓中,生产仍传 剩余+恒1):与盘中一致(平仓前剩余 1000 + 平掉额 300 + 真实比例 0.3)
+ // 契约口径形状(与盘中同形状):平仓前剩余 1000 + 平掉额 300 + 真实比例 0.3
var eodPostClose = CreateService().GetInterests(td, td.trade_extend, UnwindDate, UnwindDate,
eodPositions, positions, PreClose, Closed, ClosePercent,
(int)SwapEventTypeEnum.平仓, tdClose: false, orginPv: PreClose,
@@ -226,7 +226,7 @@ namespace YLErp.Modules.SwapModule
///
/// mode9 全平(契约目标形状:平仓前剩余=平掉额=1000、比例恒1):
- /// 结息额非零且=全平语义(:1220 全平分支:待实现+末段增量,尾差一次带走——裁决§五.2 维持)。
+ /// 结息额非零且=全平语义(:1220 全平分支:待实现+末段增量,尾差一次带走——设计意图维持)。
///
[TestMethod]
public void 复利_mode9_全平_兜底覆盖生效结息额非零()
diff --git a/YLErpDAL/Modules/SwapModule/SwapDealService.cs b/YLErpDAL/Modules/SwapModule/SwapDealService.cs
index b7c87cbd..62c2f50b 100644
--- a/YLErpDAL/Modules/SwapModule/SwapDealService.cs
+++ b/YLErpDAL/Modules/SwapModule/SwapDealService.cs
@@ -1231,9 +1231,7 @@ namespace YLErp.Modules.SwapModule
if (preEodPosition.id != 0 && closePrecent == 1m)
{
// 【全平专属分支触发标记】(快速定位):设计意图=真全平(尾差一次带走)与观察日恒1全额结息。
- // ⚠️ 契约修复暂缓期间,普通部分平仓经 EOD 恒1惯例【仍会进入本分支】(重算结果已被裁决
- // 证为不落库/不动钱/不进资金,零生产后果);修复落地后部分平仓不再进入——本行日志届时
- // 兼作落地验证哨兵(部分平仓出现在此=修复未生效/被回退)。
+ // 普通部分平仓经 EOD 恒1惯例也会进入本分支(重算中间值不进结算现金流);本行日志用于监控进入者分布。
Logger.Info($"[利息-全平专属分支] tradeId={td.id} posiId={position.id} valueDate={valueDate:yyyy-MM-dd} " +
$"closePrecent={closePrecent} preEod.InterestIncomeSum={preEodPosition.InterestIncomeSum}");
// 最终全平只重放上一日终之后的新增利息;历史部分平仓的两位结算尾差已在日终待实现中。
diff --git a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
index f2f06971..a5344564 100644
--- a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
+++ b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
@@ -110,7 +110,6 @@ namespace YLErp.Modules.SwapModule
/// 语义契约见 InterestCalcRequest.EodPostCloseSettle 工厂注释(平仓后剩余 + 实际平掉额 + 恒1全额结息,
/// 触发 GetInterests 内 mode2/mode9 本金修正)。计息走 CalcUnwindInterest 全区间重放。
/// 默认实现仍经 CalcSwapInterests 转发,保持既有测试替身对该虚接缝的拦截不变。
- /// (契约修复§六暂缓中:落地时 autoSwap=false 分支改 Intraday 形状,见裁决文档与调用点注释。)
///
protected virtual List CalcEodPostCloseSettleInterests(InterestCalcRequest req)
=> CalcSwapInterests(req.Td, req.TradeExtend, req.ValueDate, req.UnwindDate, req.EodPositions, req.Positions,
@@ -1323,14 +1322,11 @@ namespace YLErp.Modules.SwapModule
var calcLast = tradeExtend?.InterestCalcMode?.EndsWith("1") ?? true;
// 显式入口:平仓后剩余本金 + 实际平掉额 + 恒1全额结息(语义见 InterestCalcRequest.EodPostCloseSettle)。
// 该组合触发 GetInterests 内共享计息器的模式2/9本金修正(见其"根因位置"注释,勿删)。
- // ⚠️ 契约修复暂缓中(2026-08-16 撤回):按裁决文档§六,autoSwap=false 本应改传 Intraday 形状
- // (平仓前剩余+真实比例),但该变更影响快照种子(TdInterestPrincipal等),黄金回放验收门未过前不落地;
- // 落地时见 项目文档/双入口口径裁决-复利mode2部分平仓-20260816.md §六 与已就绪的回归网
- //(GetInterestsEntrySemanticsTest.复利_mode2_部分平仓_双入口契约口径一致)。
+ // 恒1 重算的 InterestAmount 是不进结算现金流的中间值;系统端到端结算结果由 DI_EXCEL_SCENARIO4 家族对账确认书公式保障(最终全平=剩余额×∏利率,2026-08-18 手算复核)。改动本口径前必读该测试家族——任何破坏 ∏ 恒等式的调整都会被其拦截。
// 口径选择常驻记录(快速定位第一入口):出问题先看这行确认当日本次事件的金额输入,再顺着
// SwapCalcTrace 分段过程日志追计算;autoSwap=观察日结现路径。
Log.Info($"[EOD平仓后收盘结息] tradeId={td.id} valueDate={valueDate:yyyy-MM-dd} autoSwap={autoSwap} " +
- $"口径=恒1全额结息(历史行为,契约修复暂缓) " +
+ $"口径=全额结息(恒1惯例) " +
$"oriPosi(平仓前)={oriPosiNotionalValue} posi(剩余)={posiNotionalValue} close(平掉)={closeNational}");
var interests = CalcEodPostCloseSettleInterests(InterestCalcRequest.EodPostCloseSettle(
td, td.trade_extend, valueDate, valueDate, preEodPositions, positions,
diff --git a/项目文档/双入口口径裁决-复利mode2部分平仓-20260816.md b/项目文档/双入口口径裁决-复利mode2部分平仓-20260816.md
deleted file mode 100644
index 36985eca..00000000
--- a/项目文档/双入口口径裁决-复利mode2部分平仓-20260816.md
+++ /dev/null
@@ -1,129 +0,0 @@
-# 裁决申请:复利×mode2×部分平仓 双入口结息额分歧
-
-> 2026-08-16 | 来源:`GetInterestsEntrySemanticsTest`(b01b485e 实测钉住)
-> 状态:**终局封禁(2026-08-18 手算复核修正推理)——系统端到端结果已与确认书精确一致,无可修的契约偏差**
->
-> **2026-08-18 Excel↔确认书对账(前置条件已完成,结论:两者等同)**:
-> 以 20260421-0004 输入手算(本金303,139,117.80/利差-2.1%/重置7天/"11"算头算尾/rule=-1/FR007字典):
-> BL 部分平仓 = 平掉额×∏利率(4/22→5/11) = **-37,119.14**,与 Excel BL 完全一致(0.00差);
-> BN 最终全平 = 剩余额×∏利率(4/22→5/19) = **-123,280.18**,与 Excel BN 差 0.01(分步舍入)。
-> **即 Excel 金标准就是确认书公式本身;系统旧链的端到端结果(BL/BN)已契约精确正确。**
->
-> 2026-08-17 实施§六(autoSwap分叉)被 Excel 金标准拦截(BN 差-2357.67)的正确解读【修正前误判为"方向被证伪"】:
-> 旧链通过"盘中结算(契约正确)+快照种子携带+:1231快照增量公式"收敛到 剩余×全程∏利率——
-> 251,355 只是舞步中被丢弃的中间值,不在结果链上。分叉破坏的是**实现不变量**
-> (最终全平必须 reconcile 到 剩余×∏利率),而非修复方向。结果层既然已无契约偏差,
-> §六只剩内部中间值卫生价值,而动它须保住上述不变量——风险大于收益,终局不修。
->
-> 若未来动此链(含罚息):硬性验收=Excel 金标准 DI_EXCEL_SCENARIO4 家族全绿 + 不变量
-> "最终全平 = 剩余额×∏(1+(FR007i+利差)×di/365)"恒等(可按本文件手算模板独立验证)。
-
-## 一、分歧事实(生产代码实测,已钉住)
-
-### 1.1 真实规模复算(确认书生产参数,裁决请以此为准)
-
-参数全部取自确认书规定与生产实配(见 TEST-MATRIX §8/§8a):
-名义本金 **5000 万**;FR007=1.8% + 点差 **+0.25%** = all-in 2.05%;重置频率 **7 天**;
-计息基准 **A/365**;持有 **90 天**(12×7 天完整重置期 + 6 天末段);**部分平仓 30%**(平掉 1500 万,剩余 3500 万)。
-
-| 口径 | 结息额 | 计算方式 |
-|---|---:|---|
-| 契约公式(应结) | **75,999.04 元** | 平掉额 1500万 × 参考利率(90天)= ∏公式,手算见 §二 |
-| 盘中平仓试算 | **75,999.04 元** | 与契约公式一致(引擎实测,容差内) |
-| EOD 平仓后收盘(现结) | **251,355.08 元** | 平仓前全仓 5000万 截至上一日终待实现(250,508.61) + 平掉额末段增量(846.43) |
-
-**重算事件金额是应结的 3.3 倍**(多出部分 ≈ 剩余 3500 万份额对应的待实现利息,在只平 30% 时被算进重算结果)。
-
-> **影响面最终裁定(2026-08-16 代码级核查,三层全部关闭):资金没多结,数据没错,本分歧零生产后果。**
-> ①**不落库**:`UpdateDbOption` 仅打审计字段不做 DbSet.Add,且 `DealInterests` 的 hasClose 分支
-> (SwapEodPositionService.cs:524)**未接收返回值**——重算结果被整个丢弃,库里不存在这条错误流水;
-> ②**不动钱**:该路径(autoSwap=false)无 AddClientCash;客户资金只在盘中流程与 EOD 自动互换/分红路径发生;
-> ③**快照影响需精确表述(2026-08-16 复核修正,原文"不进快照"过宽)**:结算现金流层无影响
-> ——`TdCloseInterest`/`RealizedInterest` 滚动盘中实落库金额(75,999),autoSettled 恒0;
-> **但重算结果并非完全被丢弃**:`TdInterestIncome` 四分支中三分支(!hasPreviousEod/全平/默认)
-> 直接写重算值,仅"有历史已结且算尾"分支被 DailyAccrual 干净覆盖;复利 mode2/9 的
-> `TdInterestPrincipal` 取 `interests.First().InterestPrincipal`(重算值,次日复利基数种子);
-> `FloatRate` 亦取重算值。即"零生产后果"严格=【零结算现金流后果】,accrual 展示/种子字段被改写。
-> 错误的 251,355 因此并非"只存在于内存与日志"。观察日×当日平仓路径(autoSwap=true)确会结现
-> (系统操作_互换),但该路 percent≡1 即"观察日全量结息"的正确语义,:1220 公式即为其设计。
->
-> **⚠️ 落地审查清单(§六实施时必查,关联 GLMS-20260421-0004)**:历史事故(同方法内 mode2/9 本金
-> 反推膨胀~2.3倍)即源于本方法本金口径,:1413+ 复利部分平仓特判块(fullPrincipal 反推)消费
-> InterestPrincipal——改请求形状后须逐一验证该特判块两形状下反推链路等价;TdInterestIncome
-> 三分支的重算值改写、TdInterestPrincipal 种子值变化,均须在黄金回放 diff 白名单内显式核对。
-> **结论:这是共享计算器内的语义地雷(percent≡1 复用),非结算错误;修复性质=重构卫生项,
-> 与普通重构同优先级;生产数据修正与内网查证全部取消。**
-
-### 1.2 可复现实测锚点(玩具参数,字符化钉子)
-
-场景:合约名义本金(mode2)×复利×浮动 FR007×部分平仓 30%
-参数:本金 1000,平掉 300,剩余 700;FR007=0.1%,利差=1.0%;[4/27 起息,4/30 平仓] 算头算尾 4 天;重置周期 3 天。
-
-| 入口 | 结息额 | 计算方式 |
-|---|---|---|
-| 盘中平仓试算 | **0.036165** | 平掉额 300 从 4/27 到 4/30 全程复利重放 |
-| EOD 平仓后收盘 | **0.059042** | 剩余持仓全部待实现利息(0.05) + 平掉额 4/30 末段增量(0.009042) |
-
-EOD 比盘中多结 63%(同一分歧在玩具参数下的比例;比例随持有天数/平仓比例变化,真实规模见 §1.1)。
-
-## 二、契约验算(确认书公式,模板:国联民生收益互换确认书-现券/ETF 四份一致)
-
-```
-参考利率(绝对) = ∏[i=1..k] ( 1 + (FR007i + 利差) × di / 365 ) − 1
-结息额(平仓部分) = 实际平掉额 × 参考利率(绝对)
-```
-
-真实规模手算(利率恒定 2.05% 时 ∏ 可合并):
-- 90 天 = 12×7 天 + 6 天末段 → 参考利率 = (1+0.0205×7/365)^12 × (1+0.0205×6/365) − 1 = **0.0050666026**
-- 应结 = 1500万 × 0.0050666026 = **75,999.04 元** = 盘中口径(引擎实测一致)
-
-EOD 口径(全仓待实现 250,508.61 + 末段增量 846.43 = 251,355.08)**无法由契约公式推出**——
-契约里不存在"平掉 30% 却结走 100% 持仓利息"的条款。
-
-玩具参数手算(300×[(1+0.011×3/365)×(1+0.011×1/365)−1])= 0.0361652,同样 = 盘中口径。
-
-## 三、触发链:谁在 EOD"平仓"(命名澄清)
-
-**"EOD 平仓后收盘"不是自动平仓本身,是收盘归档任务对当日平仓事件的重算结息。** 完整链条:
-
-1. **人工盘中部分平仓**(正确):交易员平仓页操作 → `GetUnwindInterests` 传**真实比例 30%** →
- 结息 75,999 落 swap_flow_event(正确);
-2. **自动归并部分平仓**(平仓当下也正确):`SwapTradeAutoService` 每日任务按券商柜台反向成交流水
- (swap_flow_merge)自动平仓(`AuotoSwapUnwind`,SwapTradeAutoService.cs:1229/1290/1411)——
- `unwindQty` 按实际流水量算,**流水量<持仓量时天然就是部分平仓**;该方法内部同样走盘中语义
- (SwapDealService.cs:1644 传真实 unwindPercent);
-3. **当晚 EOD 重算(分歧所在)**:收盘归档 `DealInterests`(SwapEodPositionService.cs:511/:524)
- 发现当日有平仓事件 → `EodPostCloseSettle` 惯例传 **closePrecent 恒 1**("结算本次事件覆盖的全部")
- → 掉进 `closePrecent == 1m` 全平专属分支(:1220)→ 251,355 覆盖/修正归档。
-
-即:**平仓动作本身(人工/自动)当下结息都是对的;错发生在当晚收盘归档重算这一步**。
-
-## 四、机制定位(为什么 EOD 会算成这样)
-
-`SwapDealService.cs:1220` 的 `closePrecent == 1m` 分支,设计意图是**最终全平专属**
-(注释原文:"最终全平只重放上一日终之后的新增利息……以上一日 InterestIncomeSum 为起点,保证之前攒下的尾差最后一次带走")——
-全平时该公式正确。
-
-但 EOD 平仓后收盘入口的传参惯例是 **closePrecent 恒 1**(见 `InterestCalcRequest.EodPostCloseSettle` 工厂,
-"结算本次事件覆盖的全部")。于是 **EOD 部分平仓 30% 也掉进全平专属分支**,把剩余 100% 持仓的
-待实现利息全部结走。数字 1 承载了两种语义:"平仓比例=100%" vs "本次事件全额结息"。
-
-## 五、请业务裁决
-
-1. **部分平仓(含 EOD 归档重算)应结利息**:是否 = 确认书公式下"实际平掉额 × 全程利率"?
- (即盘中口径;真实规模例:平 30% 应结 75,999.04 而非 251,355.08)——契约公式直接支持,推荐。
-2. **最终全平应结利息**:维持现公式"剩余持仓待实现 + 末段增量"(尾差一次带走)——合理,建议维持。
-
-## 六、裁决后的修复方案(技术侧已就绪,预计 1~2 天)
-
-- EOD 入口改为传**真实比例**(实际平掉额/剩余)而非恒 1;部分平仓自然走重放路径(与盘中同语义)
-- 全平保留 percent=1,1220 分支回归"全平专属"设计意图
-- `GetInterests` 内 mode2 无条件覆盖/mode9 兜底(2035e1df 粘合)随之退役删除
-- 钉住测试翻转为"两入口相等" oracle 断言;黄金回放 diff 仅允许出现在本格子的 EOD 结息额(=裁决修正值)
-
-## 七、生产影响面(已关闭,无需内网查证)
-
-受影响格子:**当日发生部分平仓 × 复利 × mode2/9 × 当晚 EOD 归档重算**——经代码级核查,
-该路径重算结果不落库、不动钱、不进快照(详见 §1.1 引注),**生产资金与数据均无影响,
-原定内网查证与数据修正清单全部取消**。观察日×当日平仓(autoSwap=true)路径结现,
-但 percent≡1 在该语义下正确,非本分歧范围。