ParameterBase.Clone() 保留运行时类型深拷贝; ValueCalculator 两个薄接入方法; GreeksBumpCalculator/GreeksRiskFactor 引擎。加法性重定价桥,不动现有定价输出。
115 lines
5.2 KiB
C#
115 lines
5.2 KiB
C#
using YLErp.BLL.Calculation.V2;
|
||
|
||
namespace UnitTestProject.Modules.SwapModule
|
||
{
|
||
/// <summary>
|
||
/// GreeksBumpCalculator 纯数学契约测试(先写,锁定 ε / 差分逻辑)。
|
||
/// 不碰 DB / QDP:用已知解析导数的函数(f(x)=x²,d/dx=2x,d²/dx²=2)验证中心差分本身正确。
|
||
/// 业务侧集成测试(真实定价路径 + 真实 FR007)见后续 ValueCalculator 薄接入落地后再补。
|
||
/// </summary>
|
||
[TestClass]
|
||
public class GreeksBumpCalculatorTests
|
||
{
|
||
/// <summary>
|
||
/// 一阶中心差分对 f(x)=x² 在 x=3 应精确等于 2x=6。
|
||
/// 二次多项式的中心差分对任意 ε 都精确(截断误差为 0),因此用相对步长 0.05% 仍得 6。
|
||
/// </summary>
|
||
[TestMethod]
|
||
public void CentralDelta_of_x2_equals_2x()
|
||
{
|
||
var calc = new GreeksBumpCalculator();
|
||
Func<decimal, decimal> f = x => x * x; // d/dx = 2x
|
||
var delta = calc.Delta(f, 3m, BumpSpec.Relative(0.0005m));
|
||
Assert.AreEqual(6m, delta);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 二阶中心差分对 f(x)=x² 在 x=3 应精确等于 2(二阶导数恒为 2)。
|
||
/// 验证 Gamma 的二阶差分算子正确。
|
||
/// </summary>
|
||
[TestMethod]
|
||
public void CentralGamma_of_x2_equals_2()
|
||
{
|
||
var calc = new GreeksBumpCalculator();
|
||
Func<decimal, decimal> f = x => x * x; // d²/dx² = 2
|
||
var gamma = calc.Gamma(f, 3m, BumpSpec.Relative(0.0005m));
|
||
Assert.AreEqual(2m, gamma);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 1BP 变体(Dollar Greek)对 f(x)=x² 在 x=3、bump 1bp 应等于 (3.0001)² - 3²。
|
||
/// 验证 BumpPv1Bp 直接前向 bump 的 PV 差逻辑。
|
||
/// </summary>
|
||
[TestMethod]
|
||
public void BumpPv1Bp_of_x2_forward()
|
||
{
|
||
var calc = new GreeksBumpCalculator();
|
||
Func<decimal, decimal> f = x => x * x;
|
||
var bumped = calc.BumpPv1Bp(f, 3m);
|
||
Assert.AreEqual(3.0001m * 3.0001m - 3m * 3m, bumped);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 线性函数 f(x)=2x+1:一阶中心差分应精确等于斜率 2,二阶中心差分应精确为 0(线性无曲率)。
|
||
/// 验证算子对"一次/零次"函数的精确性(二次之外另一种精确情形)。
|
||
/// </summary>
|
||
[TestMethod]
|
||
public void CentralDelta_of_linear_is_slope()
|
||
{
|
||
var calc = new GreeksBumpCalculator();
|
||
Func<decimal, decimal> f = x => 2m * x + 1m; // d/dx = 2, d²/dx² = 0
|
||
Assert.AreEqual(2m, calc.Delta(f, 5m, BumpSpec.Relative(0.0005m)));
|
||
Assert.AreEqual(0m, calc.Gamma(f, 5m, BumpSpec.Relative(0.0005m)));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 三次函数 f(x)=x³:中心差分对任意 ε 不精确(仅二次及以下精确),结果逼近解析导 3x² 但有 O(ε²) 误差。
|
||
/// 验证 Layer B 集成测试必须带容差,不能 Assert.AreEqual 死等精确值。x=2 解析导=12。
|
||
/// </summary>
|
||
[TestMethod]
|
||
public void CentralDelta_of_cubic_is_approx_analytic_with_tolerance()
|
||
{
|
||
var calc = new GreeksBumpCalculator();
|
||
Func<decimal, decimal> f = x => x * x * x; // d/dx = 3x² = 12 at x=2
|
||
var delta = calc.Delta(f, 2m, BumpSpec.Relative(0.0005m));
|
||
Assert.IsTrue(Math.Abs(delta - 12m) < 0.001m, $"中心差分三次函数应有 O(ε²) 误差,实际={delta}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 扭结点测试:看涨 payoff f(x)=max(x-3,0) 在行权价 x=3 处不可导。
|
||
/// 中心差分跨扭结取到左右斜率的平均 (0+1)/2 = 0.5,说明对障碍/美式等扭结结构必须用单边差分。
|
||
/// </summary>
|
||
[TestMethod]
|
||
public void CentralDelta_at_kink_is_average_of_one_sided()
|
||
{
|
||
var calc = new GreeksBumpCalculator();
|
||
Func<decimal, decimal> f = x => x > 3m ? x - 3m : 0m; // call payoff K=3
|
||
var delta = calc.Delta(f, 3m, BumpSpec.Relative(0.0005m));
|
||
Assert.AreEqual(0.5m, delta); // 中心差分给出左右斜率平均,非真实单边 Greek
|
||
}
|
||
|
||
/// <summary>
|
||
/// 边界 x=0(相对步长会触到 Floor):f(x)=x² 在 0 处对称,Δ 应精确为 0,证明 Floor 兜底不产生噪声。
|
||
/// </summary>
|
||
[TestMethod]
|
||
public void CentralDelta_at_zero_uses_floor_but_stays_correct()
|
||
{
|
||
var calc = new GreeksBumpCalculator();
|
||
Func<decimal, decimal> f = x => x * x;
|
||
Assert.AreEqual(0m, calc.Delta(f, 0m, BumpSpec.Relative(0.0005m)));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 利率量级小值 x=0.0001(1bp 量级)用相对步长:Resolve 返回 max(0.0001·0.0005, 1e-8)=5e-8,
|
||
/// 远大于 Floor,证明利率类小量级不会被舍入噪声吞掉。f=x² 在 0.0001 解析导=2·0.0001=0.0002。
|
||
/// </summary>
|
||
[TestMethod]
|
||
public void CentralDelta_of_tiny_rate_like_x_is_stable()
|
||
{
|
||
var calc = new GreeksBumpCalculator();
|
||
Func<decimal, decimal> f = x => x * x;
|
||
Assert.AreEqual(0.0002m, calc.Delta(f, 0.0001m, BumpSpec.Relative(0.0005m)));
|
||
}
|
||
}
|
||
}
|