ParameterBase.Clone() 保留运行时类型深拷贝; ValueCalculator 两个薄接入方法; GreeksBumpCalculator/GreeksRiskFactor 引擎。加法性重定价桥,不动现有定价输出。
134 lines
6.1 KiB
C#
134 lines
6.1 KiB
C#
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<decimal,decimal></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);
|
||
}
|
||
}
|
||
}
|