Files
zszq-trs/YLErpDAL/BLL/Calculation/V2/GreeksBumpCalculator.cs
T
hjhan 985162242d feat(greeks): 新增 risk-factor bump 计算与注册
ParameterBase.Clone() 保留运行时类型深拷贝; ValueCalculator 两个薄接入方法; GreeksBumpCalculator/GreeksRiskFactor 引擎。加法性重定价桥,不动现有定价输出。
2026-07-21 15:28:15 +08:00

134 lines
6.1 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.BLL.Calculation.V2
{
/// <summary>
/// 风险因子种类,用于后续 ValueCalculator 薄接入层签名(CalcPvAtBumpedRiskFactor)。
/// 当前 GreeksBumpCalculator 纯类本身不依赖它,仅作为对外契约的一部分。
/// </summary>
public enum RiskFactorKind
{
/// <summary>标的价 S</summary>
Price,
/// <summary>无风险利率 r</summary>
Rate,
/// <summary>波动率 σ</summary>
Volatility
}
/// <summary>
/// 扰动步长规格:决定有限差分用的 ε。
/// <list type="bullet">
/// <item><description>Relative:ε = max(|x| * Value, Floor),适合指数等大量级标的,避免绝对 1bp 落入浮点舍入区。</description></item>
/// <item><description>Absolute:ε = Value,等价系统现行“标的价格偏移绝对 1bp”的做法。</description></item>
/// </list>
/// 默认 Floor 极小,仅防止 x=0 时 ε=0 导致除零。
/// </summary>
public readonly struct BumpSpec
{
/// <summary>步长模式</summary>
public enum Mode
{
/// <summary>相对步长(推荐,量级自适应)</summary>
Relative,
/// <summary>绝对步长</summary>
Absolute
}
/// <summary>步长模式</summary>
public Mode Kind { get; }
/// <summary>步长数值(Relative 时为相对比例,Absolute 时为绝对量)</summary>
public decimal Value { get; }
/// <summary>相对步长下限(防止 |x| 过小导致 ε→0</summary>
public decimal Floor { get; }
/// <summary>构造步长规格</summary>
public BumpSpec(Mode kind, decimal value, decimal floor = 0.00000001m)
{
Kind = kind;
Value = value;
Floor = floor;
}
/// <summary>相对步长(value 为相对比例,如 0.0005m = 0.05%</summary>
public static BumpSpec Relative(decimal value) => new(Mode.Relative, value);
/// <summary>绝对步长(value 为绝对量,如 0.0001m = 1bp</summary>
public static BumpSpec Absolute(decimal value) => new(Mode.Absolute, value);
/// <summary>把规格解析成实际 ε(用 decimal,避免 double 精度漂移)</summary>
public decimal Resolve(decimal x)
{
if (Kind == Mode.Absolute) return Value;
var eps = Math.Abs(x) * Value;
return eps < Floor ? Floor : eps;
}
}
/// <summary>
/// 有限差分希腊字母计算引擎(纯函数,不依赖 QDP / DB)。
/// <para>
/// 通过委托 <c>pv(bumpedFactor)</c> 取得“风险因子被扰动到某值时的衍生品价值”,
/// 再用中心差分估算一阶 / 二阶导。这是仓库层对 Greeks 口径的显式控制点,
/// 可绕开 QDP 内部黑盒的步长 / 差分选择,并解决指数类标的使用绝对 1bp 步长失真的口径问题。
/// </para>
/// <para>
/// 用法:业务侧把“价格 / 利率 / 波动率”各自封装成一个 <c>Func&lt;decimal,decimal&gt;</c> 委托传给本类;
/// Delta/Gamma/Vega/Rho 等命名方法数学上都是同一差分算子,仅扰动的风险因子不同。
/// </para>
/// </summary>
public sealed class GreeksBumpCalculator
{
/// <summary>一阶中心差分 Δ = [PV(x+ε) - PV(x-ε)] / (2ε),误差 O(ε²)</summary>
public decimal FirstOrderCentral(Func<decimal, decimal> pv, decimal x, BumpSpec bump)
{
ArgumentNullException.ThrowIfNull(pv);
var eps = bump.Resolve(x);
return (pv(x + eps) - pv(x - eps)) / (2m * eps);
}
/// <summary>二阶中心差分 Γ = [PV(x+ε) - 2·PV(x) + PV(x-ε)] / ε²,误差 O(ε²)</summary>
public decimal SecondOrderCentral(Func<decimal, decimal> pv, decimal x, BumpSpec bump)
{
ArgumentNullException.ThrowIfNull(pv);
var eps = bump.Resolve(x);
return (pv(x + eps) - 2m * pv(x) + pv(x - eps)) / (eps * eps);
}
// —— 以下为按业务希腊字母命名的暴露,数学上都是上面两个差分算子,仅扰动因子不同 ——
/// <summary>Delta:对标的价 S 的一阶中心差分</summary>
public decimal Delta(Func<decimal, decimal> pv, decimal s, BumpSpec bump) => FirstOrderCentral(pv, s, bump);
/// <summary>Gamma:对标的价 S 的二阶中心差分</summary>
public decimal Gamma(Func<decimal, decimal> pv, decimal s, BumpSpec bump) => SecondOrderCentral(pv, s, bump);
/// <summary>Vega:对波动率 σ 的一阶中心差分</summary>
public decimal Vega(Func<decimal, decimal> pv, decimal sigma, BumpSpec bump) => FirstOrderCentral(pv, sigma, bump);
/// <summary>Vega_r:对波动率 σ 的一阶中心差分(需求命名变体,等价于 Vega</summary>
public decimal VegaR(Func<decimal, decimal> pv, decimal sigma, BumpSpec bump) => FirstOrderCentral(pv, sigma, bump);
/// <summary>Rho:对无风险利率 r 的一阶中心差分</summary>
public decimal Rho(Func<decimal, decimal> pv, decimal r, BumpSpec bump) => FirstOrderCentral(pv, r, bump);
/// <summary>Delta_r:对无风险利率 r 的一阶中心差分(需求命名变体,等价于 Rho</summary>
public decimal DeltaR(Func<decimal, decimal> pv, decimal r, BumpSpec bump) => FirstOrderCentral(pv, r, bump);
/// <summary>Gamma_r:对无风险利率 r 的二阶中心差分</summary>
public decimal GammaR(Func<decimal, decimal> pv, decimal r, BumpSpec bump) => SecondOrderCentral(pv, r, bump);
/// <summary>
/// 1BP 变体(Dollar Greek):直接前向 bump 1bp 的 PV 差 = PV(x+1bp) - PV(x),不除 ε,量纲为金额。
/// 对应需求中的 Delta_r(1BP) / Gamma_r(1BP) / Vega_r(1BP)。
/// </summary>
public decimal BumpPv1Bp(Func<decimal, decimal> pv, decimal x, decimal oneBp = 0.0001m)
{
ArgumentNullException.ThrowIfNull(pv);
return pv(x + oneBp) - pv(x);
}
}
}