Files
zszq-trs/YLErpDAL/Modules/SwapModule/Accrual/AccrualPolicy.cs
T
hjhan 40756a28b3 refactor(accrual): BuildLegRate/BuildEodPolicy移到各自类型(Phase1补完)
BuildLegRate → FundingLegRate.Build(position, spread, float) — 利率值对象的自然工厂
BuildEodPolicy → AccrualPolicy.BuildEod(position, annualDays, isCompound) — 计息政策的自然工厂

SwapDealService删除2个private static定义, 4处调用点改用类型方法
SwapModule零回归(7基线/510通过)
2026-08-12 16:32:04 +08:00

37 lines
2.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using YLErp.Derivatives.Interest;
namespace YLErp.Modules.SwapModule.Accrual;
/// <summary>
/// 计息政策(不可变配置)。把"算头算尾 / 单复利率 / 重置频率 / 年化天数"收敛为一处,
/// 取代旧代码里散落各处的 calcFirst/calcLast 布尔对与魔法数字。
///
/// 单/复利不再另立枚举——直接复用既有 DB 枚举 InterestTypeEnum(单利=0 / 复利=1),
/// 通过 <see cref="IsCompound"/> 暴露为类型安全的 bool。
/// </summary>
public sealed class AccrualPolicy
{
/// <summary>算头算尾约定(复用 SwapInterest 已有的 AccrualBoundary,物理上杜绝 calcFirst/calcLast 传反)。</summary>
public AccrualBoundary Convention { get; }
/// <summary>是否复利(利滚利)。来自 DB 的 InterestTypeEnum;单利=false,复利=true。</summary>
public bool IsCompound { get; }
/// <summary>利率重置周期(天)。FR007 通常为 7;复利时亦为"利息并入本金"的周期。</summary>
public int ResetPeriodDays { get; }
/// <summary>年化基数(365 / 360)。</summary>
public int AnnualDays { get; }
/// <summary>是否年化(position.IsAnnualized)。决定利息是否再除以 <see cref="AnnualDays"/>
/// 与 <see cref="AnnualDays"/> 一同收敛 daycount 语义,不再作为裸 bool 散落在计息签名里。</summary>
public bool IsAnnualized { get; }
public AccrualPolicy(AccrualBoundary convention, bool isCompound, int resetPeriodDays, int annualDays, bool isAnnualized = false)
=> (Convention, IsCompound, ResetPeriodDays, AnnualDays, IsAnnualized) = (convention, isCompound, resetPeriodDays, annualDays, isAnnualized);
/// <summary>从 swap_position 构造 EOD 计息政策(算头算尾,重置周期取 interest_rest_days)。</summary>
public static AccrualPolicy BuildEod(DBModels.swap_position position, int annualDays, bool isCompound)
=> new(AccrualBoundary.Both, isCompound, position.interest_rest_days ?? 1, annualDays, position.IsAnnualized);
}