diff --git a/YLErpDAL/Modules/SwapModule/Accrual/FundingLegAccrual.cs b/YLErpDAL/Modules/SwapModule/Accrual/FundingLegAccrual.cs
index 8c5902ca..a621e489 100644
--- a/YLErpDAL/Modules/SwapModule/Accrual/FundingLegAccrual.cs
+++ b/YLErpDAL/Modules/SwapModule/Accrual/FundingLegAccrual.cs
@@ -4,60 +4,17 @@ using YLErp.Derivatives.Interest;
namespace YLErp.Modules.SwapModule.Accrual;
///
-/// 融资腿计息编排层(NEW,替换 SwapDealService 内 CalcDaily* 家族的"纯数学"部分)。
+/// 融资腿计息编排层——纯数学部分(替换 SwapDealService 内 CalcDaily* 家族的纯计算)。
///
/// 职责边界(与 SwapInterest 原语、SwapDealService 适配器三者正交):
///
- /// - 本类:持有跨日 ,逐日循环,经 IIndexFixer 取当日率并封装为 ,
- /// 调用 SwapInterest 原子原语算账,处理平仓缩放 / 已实现扣除,replay 求 Δ。
+/// - 本类:持有已解析的 与 ,执行单利日终计息纯函数。
/// - SwapInterest:原子 "本金×利率×天数/年化" 纯函数,无状态。
-/// - SwapDealService.GetInterests:仅做 DB 读、swap_flow_event 构造与落库(IO)。
+/// - SwapDealService:负责 DB 读、取率、swap_flow_event 构造与落库(IO)。
///
-///
-/// 命名规范:本文件内所有概念一律使用自描述英文名。旧代码 typo 一律不出现:
-///
-/// - closePrecent→ 的 closeRatio(且语义固定为"占剩余持仓比例")
-/// - orginPv→ OriginalPv(原始名义本金,用于保证金腿差分基数)
-/// - floateRate→ FloatRate(FR007 浮动利率,拼写修正)
-/// - dynomicPrincipal→ AccrualPrincipal(逐日滚动计息本金)
-///
-///
-/// 重要——以下 当前为"结构骨架":
-/// 精确的跨日不变量(T+1 本金缩到剩余、重置日本金保留、consumedInterest 扣除、保证金腿差分公式)
-/// 依 branch-merge-analysis §7 的 DI_* 不变量,必须在把 _0808(人工已过)的利息核心并入后,
-/// 从 CalcDaily* 迁移而来并以 Excel oracle 验收。骨架故意只跑"朴素逐日累加",
-/// 不等价于已验证口径——切勿在未迁移前接入生产。
///
public static class FundingLegAccrual
{
- // 中性锚点日期:AccrueDay 只需"同日起止 → 1 天"的语义,不依赖真实时钟,保持纯函数。
- private static readonly DateTime Epoch = new(2000, 1, 1);
-
- // 资金腿计息精度(生产口径)。与 SwapDealService.InterestCalculationPrecision 一致。
- // 注意:SwapInterest.Precision=11 仅服务于保证金腿(MarginAccount),与资金腿 12 不一致属已知 TODO;
- // 资金腿所有落库/对账均以 12 为准,此处显式锁定,避免静默引入尾差。
- private const int ProductionPrecision = 12;
-
- ///
- /// 单日原子计息("AccrueDay")。委托 SwapInterest.AccrueSimple(同一天、Convention 边界 → 1 天),
- /// 直接复用 SwapInterest 已有的 (Accrued/AccruedToday)作为返回,
- /// 不再另立结果类型。编排层按日把"当天本金 + 当天率"喂入此入口,使浮动利率逐日不同也能正确累积。
- /// 复利时收盘本金 = 当日本金 + 当日利息(利滚利),该推导在 内完成,
- /// 不塞进返回结构,保持与 SwapInterest 单一结果类型的契约一致。
- ///
- /// 当日计息本金(来自 )。
- /// 当日生效年利率(由调用方经 IIndexFixer + 合约利差构造后传入,已含 spread)。
- /// 计息政策(含算头算尾 / 年化天数 / 单复利)。
- public static InterestResult AccrueDay(
- decimal accrualPrincipal,
- decimal dailyRate,
- AccrualPolicy policy,
- int precision = SwapInterest.Precision)
- {
- // 单日计息:start == end,按 policy.Convention 决定首日是否计;Both 时恰 1 天。
- return SwapInterest.AccrueSimple(accrualPrincipal, dailyRate, Epoch, Epoch, policy.Convention, policy.AnnualDays, precision);
- }
-
///
/// 单利日终计息(纯函数,替换 SwapDealService.CalcDailySimpleInterestByEod 的"纯数学"部分)。
///
@@ -65,7 +22,7 @@ public static class FundingLegAccrual
///
/// - 计息基数 baseTdInterestPrincipal = priorAccrualPrincipal + positionPrincipal − originalPv;
/// - 当日利息 = baseTdInterestPrincipal × closeRatio × rate.AllInRate,年化则再 ÷ AnnualDays;
- /// - 累计未实现 = priorUnrealized + 当日利息;末位按资金腿精度 12 舍入。
+ /// - 累计未实现 = priorUnrealized + 当日利息;末位按资金腿精度 舍入。
///
///
/// 取率与重置日重取浮动利率由适配器(CalcDailySimpleInterestByEod)负责,并封装为 传入;
@@ -102,83 +59,7 @@ public static class FundingLegAccrual
var totalUnrealized = priorUnrealized + dayInterest;
return new InterestResult(
- Math.Round(totalUnrealized, ProductionPrecision, MidpointRounding.AwayFromZero),
- Math.Round(tdInterest, ProductionPrecision, MidpointRounding.AwayFromZero));
- }
-
- ///
- /// 逐日计息编排(骨架)。从 到 逐日循环,
- /// 推进 ,并返回期末状态。
- ///
- /// 期初状态(通常来自上一日日终,见 )。
- /// 计息区间起点。
- /// 计息区间终点。
- /// 取计息日生效年利率的委托(适配器处由 IIndexFixer + 合约利差构造;测试可传 day => 0.0134m)。
- /// 计息政策。
- /// 可选平仓比例(占剩余,0~1)。非空则在期末应用平仓缩放。
- public static AccrualState AccruePeriod(
- AccrualState opening,
- DateTime startDate,
- DateTime endDate,
- Func dailyRate,
- AccrualPolicy policy,
- decimal? closeRatio = null)
- {
- var state = opening;
-
- for (var day = startDate.Date; day <= endDate.Date; day = day.AddDays(1))
- {
- var rate = dailyRate(day);
- var dayResult = AccrueDay(state.AccrualPrincipal, rate, policy);
-
- // 收盘本金:复利时并入当日利息(利滚利),单利时维持原基数。
- var nextPrincipal = state.AccrualPrincipal + (policy.IsCompound ? dayResult.AccruedToday : 0m);
- var nextUnrealized = state.UnrealizedInterest + dayResult.AccruedToday;
- state = new AccrualState(nextPrincipal, nextUnrealized, state.RealizedInterest);
-
- // ── PORT(合并 _0808 后从 CalcDaily* 迁移,受 DI_* 不变量 + Excel oracle 验收)──
- // 1. 重置日(距 StartDate 每 resetPeriodDays 天):复利时累计利息并入本金(已在 ClosingAccrualPrincipal 体现);
- // 但"重置日部分平仓后 EOD 本金必须保留计算出的复利本金、不得被 closeRatio 二次缩放"。
- // 2. 部分平仓次日(T+1):AccrualPrincipal 必须缩到剩余(× (1-closeRatio));
- // 重置日 / 算尾日不得二次缩放,否则剩余本金被打折。
- // 3. consumedInterest(历史已实现)在平仓日经 SwapInterest.ApplyUnwind 扣除。
- // 4. 保证金腿差分基数 OriginalPv:dynomicPrincipal = AccrualPrincipal + PositionPrincipal - OriginalPv,此处分支处理。
- // 5. replay 求 Δ:本 EOD 状态 − 上一 EOD 状态,由调用方(适配器层)负责,不在纯数学内。
- }
-
- if (closeRatio.HasValue)
- {
- state = ApplyPartialClose(state, closeRatio.Value, state.RealizedInterest, policy);
- }
-
- return state;
- }
-
- ///
- /// 部分 / 全部平仓缩放:把剩余待实现按 (1-closeRatio) 保留,并扣除历史已实现;
- /// 计息本金同步缩到剩余持仓。委托 SwapInterest.ApplyUnwind / AccrueUnrealized(与 Margin 共用同一纯函数)。
- ///
- /// 平仓前状态(未实现部分)。
- /// 平仓比例(占剩余持仓,0~1;1=全平)。
- /// 历史已实现利息累计,从剩余未实现中扣除。
- /// 计息政策(精度取 SwapInterest.Precision)。
- public static AccrualState ApplyPartialClose(
- AccrualState state,
- decimal closeRatio,
- decimal realizedInterest,
- AccrualPolicy policy)
- {
- // 待实现利息缩放:unrealized × (1-closeRatio) − realizedInterest
- var scaled = SwapInterest.ApplyUnwind(
- new InterestResult(state.UnrealizedInterest, state.UnrealizedInterest),
- closeRatio, realizedInterest, SwapInterest.Precision);
-
- // 计息本金按剩余持仓缩放(全平 closeRatio=1 → 归零)
- var principalRemaining = Math.Round(
- state.AccrualPrincipal * (1m - closeRatio),
- SwapInterest.Precision,
- MidpointRounding.AwayFromZero);
-
- return new AccrualState(principalRemaining, scaled.Accrued, realizedInterest);
+ Math.Round(totalUnrealized, SwapInterest.FundingLegPrecision, MidpointRounding.AwayFromZero),
+ Math.Round(tdInterest, SwapInterest.FundingLegPrecision, MidpointRounding.AwayFromZero));
}
}