Files
zszq-trs/Framework/YLErp.Core/Interest/InterestRate.cs
T
hjhan aff540801c feat(interest): 新增通用利息原语 InterestRate(与互换解耦)
单利/复利/连续复利收敛为 Compounding 一个 switch 分支,利息计算不再住在
SwapModule/互换词汇里,谁需要算息都能直接用。连续复利仅 e^(r·t) 一行。
2026-08-12 05:36:01 +08:00

72 lines
3.3 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 System;
namespace YLErp.Core.Interest;
/// <summary>
/// 利率 + 计息方式(单利 / 复利 / 连续复利)。
///
/// <para><b>通用金融原语,与互换、衍生品、任何具体业务均无耦合</b>——谁需要算利息都能用。
/// 利息计算不是互换特有的,所以它不住在 SwapModule,也不带任何 swap 词汇。</para>
///
/// <para>用法(年化时间 t,如 30天/365):</para>
/// <list type="bullet">
/// <item><description>计息因子 = <see cref="CompoundFactor(decimal)"/>;含息额 = 本金 × 因子;</description></item>
/// <item><description>利息 = 本金 × (因子 1) = <see cref="Interest(decimal, decimal)"/>。</description></item>
/// </list>
///
/// <para>与 QuantLib 模型一致:单利 / 复利 / 连续复利只是 <see cref="Compounding"/> 的一个分支,
/// 不是三套独立方法。TRS 的"重置日并本金"属于离散复利,用 <see cref="Compounding.Simple"/>
/// 按段计息、段末把利息滚入本金即可(见 SwapInterest.AccrueCompound),无需 Pow/Expdecimal 精度无损。</para>
///
/// <para>互换特有的会计态(每日先舍入再乘天数、平仓缩放、跨日滚动本金)不属于本原语,
/// 请在各自的 accrual 层处理。</para>
/// </summary>
public enum Compounding
{
/// <summary>单利:因子 = 1 + r·t。</summary>
Simple,
/// <summary>复利(理想化闭式):因子 = (1 + r/f)^(f·t)f 为年复利频次。</summary>
Compounded,
/// <summary>连续复利:因子 = e^(r·t)。</summary>
Continuous
}
/// <summary>
/// 不可变利率值对象。构造即完整,无副作用。
/// </summary>
public readonly struct InterestRate
{
/// <summary>年化利率 r。</summary>
public decimal Rate { get; }
/// <summary>计息方式。</summary>
public Compounding Compounding { get; }
/// <summary>年复利频次(仅 <see cref="Compounding.Compounded"/> 使用,其余忽略,默认 1)。</summary>
public int Frequency { get; }
public InterestRate(decimal rate, Compounding compounding, int frequency = 1)
=> (Rate, Compounding, Frequency) = (rate, compounding, frequency);
/// <summary>
/// 计息因子(输入年化时间 t)。
/// <list type="bullet">
/// <item><description><see cref="Compounding.Simple"/>decimal 精确运算。</description></item>
/// <item><description><see cref="Compounding.Compounded"/> / <see cref="Compounding.Continuous"/>:闭式(double 计算后回 decimal),
/// 满足通用定价 / 保证金场景;若要 decimal 精度的离散重置日复利,请用 Simple 按段计息并滚动本金。</description></item>
/// </list>
/// </summary>
public decimal CompoundFactor(decimal t)
=> Compounding switch
{
Compounding.Simple => 1m + Rate * t,
Compounding.Compounded => (decimal)Math.Pow((double)(1m + Rate / Frequency), (double)(Frequency * t)),
Compounding.Continuous => (decimal)Math.Exp((double)(Rate * t)),
_ => throw new ArgumentOutOfRangeException(nameof(Compounding))
};
/// <summary>利息 = 本金 × (因子 1)。</summary>
public decimal Interest(decimal principal, decimal t)
=> principal * (CompoundFactor(t) - 1m);
}