# 任务 4:盘中复利从 EOD 续接(而非 PosiStartDate 全程重放) ## 状态:待立项(高风险,需专项验证) ## 现状 `CalcDailyCompoundInterest` 从 `position.PosiStartDate` 全程重放到 `endDate`,每个重置日把累计利息并入本金(复利),最后扣 `consumedInterest * closePercent`。 **调用链**:`InitSwapDealInterest` → `CalcDailyCompoundInterest(endDate, PosiStartDate→endDate 全程重放)` **问题**:交易存续期长(数月~数年)时,每次盘中平仓都从起息日重放,计算量随天数线性增长。 ## 提议 改为从上一日终快照(`preEodPosition`)续接: - 起点 = `preEodPosition.ValueDate + 1` - 初始本金 = `preEodPosition.TdInterestPrincipal`(已含历史滚入利息) - 只算 `ValueDate+1` 到 `endDate` 的增量利息 ## 风险分析(为什么不能直接改) ### 风险 1:并本金起点不同导致终值不等 | | 全程重放(当前) | EOD 续接(提议) | |---|---|---| | 起点 | `principal`(原始平仓名义本金) | `preEod.TdInterestPrincipal`(已滚利息) | | 滚法 | 每段 `basis = principal + accrued` | 每段 `basis = preEod.TdInterestPrincipal + segmentAccrued` | 两段路径在**中间重置日的四舍五入路径不同**(精度 12 的 Round 作用在不同的中间值上),终值**不一定逐分相等**。 ### 风险 2:consumedInterest 语义翻转 - 全程重放:总利息 - consumedInterest × closePercent = 增量 - EOD 续接:直接算增量,**不需要**扣 consumedInterest 如果 EOD 快照的 `InterestIncomeSum` 与 consumedInterest 口径不完全一致,直接去掉扣减会引入误差。 ### 风险 3:resetCarryInterest 耦合 当前逻辑:`resetCarryInterest`(上一日终待实现 × remainingPercent)只在 `endDate` 恰好是重置日时并入本金。EOD 续接模式下,重置日的判定、remainingPercent 的计算、carry 的注入时机都不同。 ### 风险 4:全平重放逻辑(lines 1293-1304) `InitSwapDealInterest` 在 `closePrecent == 1m` 时做 **两次** `CalcDailyCompoundInterest` 重放(截至平仓日 + 截至上一日终),取差值。EOD 续接模式下这段逻辑需要完全重新设计。 ## 验证方案(立项前提) 1. 构造测试用例:同一笔复利交易,跨越 ≥2 个重置周期,有 preEod 快照 2. 用**旧全程重放**算出 `(InterestAmount, TdInterestAmount, finalBasis)` 3. 用**新 EOD 续接**算出同样三个值 4. 断言差额 < 0.01(到分) 5. 覆盖场景: - 部分平仓(closePercent < 1) - 全平(closePercent == 1) - 平仓日 = 重置日 - 平仓日 ≠ 重置日 - 有/无 consumedInterest - 有/无 resetCarryInterest ## 建议排期 单独 sprint 处理,不混入日常重构。改动范围: - `CompoundInterestAccrual.AccruePeriod` 新增 `startBasis` 参数(或新方法 `AccrueFromEod`) - `CalcDailyCompoundInterest` wrapper 改为传 `preEod.TdInterestPrincipal` 作为起点 - `InitSwapDealInterest` 全平重放逻辑简化(不再需要两次重放取差值) - `consumedInterest` 扣减逻辑移除或调整