Computing Greeks
ChebyshevSharp computes option Greeks (and any partial derivatives) analytically using spectral differentiation matrices -- no finite differences needed.
Derivative Specification
Derivatives are specified as an array of integers, one per dimension. Each integer is the derivative order with respect to that dimension.
For a 5D function \(V(S, K, T, \sigma, r)\):
| Greek | derivativeOrder |
Mathematical |
|---|---|---|
| Price | [0, 0, 0, 0, 0] |
\(V\) |
| Delta | [1, 0, 0, 0, 0] |
\(\partial V / \partial S\) |
| Gamma | [2, 0, 0, 0, 0] |
\(\partial^2 V / \partial S^2\) |
| Vega | [0, 0, 0, 1, 0] |
\(\partial V / \partial \sigma\) |
| Rho | [0, 0, 0, 0, 1] |
\(\partial V / \partial r\) |
Any combination is valid up to MaxDerivativeOrder. For example, cross-gamma
\(\partial^2 V / \partial S \, \partial \sigma\) would be [1, 0, 0, 1, 0]:
// Cross-gamma: d²V / dS dsigma
double crossGamma = cheb.VectorizedEval(point, new[] { 1, 0, 0, 1, 0 });
Example: Black-Scholes Greeks
using ChebyshevSharp;
double BlackScholesCall(double[] x, object? data)
{
double S = x[0], K = x[1], T = x[2], sigma = x[3], r = x[4];
// ... your pricing function here
return price;
}
var cheb = new ChebyshevApproximation(
function: BlackScholesCall,
numDimensions: 5,
domain: new[]
{
new[] { 80.0, 120.0 }, // Spot
new[] { 90.0, 110.0 }, // Strike
new[] { 0.25, 1.0 }, // Maturity
new[] { 0.15, 0.35 }, // Volatility
new[] { 0.01, 0.08 } // Rate
},
nNodes: new[] { 11, 11, 11, 11, 11 }
);
cheb.Build();
double[] point = { 100.0, 100.0, 1.0, 0.25, 0.05 };
// All Greeks at once (most efficient)
double[] results = cheb.VectorizedEvalMulti(point, new[]
{
new[] { 0, 0, 0, 0, 0 }, // Price
new[] { 1, 0, 0, 0, 0 }, // Delta
new[] { 2, 0, 0, 0, 0 }, // Gamma
new[] { 0, 0, 0, 1, 0 }, // Vega
new[] { 0, 0, 0, 0, 1 }, // Rho
});
double price = results[0];
double delta = results[1];
double gamma = results[2];
double vega = results[3];
double rho = results[4];
VectorizedEvalMulti shares intermediate barycentric weight computation across all
requested derivative orders, making it significantly faster than calling
VectorizedEval five separate times.
How It Works
- At build time: Pre-compute the spectral differentiation matrix \(D\) from the Chebyshev node positions. This matrix maps function values at nodes to derivative values at those same nodes.
- At query time: Apply \(D\) to the function value tensor before barycentric interpolation. For dimension \(k\) with derivative order \(m_k\), the tensor is contracted against \(D^{m_k}\) along axis \(k\).
- For second derivatives: Apply \(D\) twice (\(D^2 \mathbf{f}\)). This computes second-derivative values at the nodes, which are then interpolated to the query point.
- Interpolate the resulting derivative values to the query point using the standard barycentric formula.
This provides exact derivatives of the interpolating polynomial. Because the differentiation matrix computes derivatives of the degree-\(n\) polynomial \(p(x)\) exactly (within machine precision), and \(p(x)\) converges spectrally to \(f(x)\), the derivative \(p'(x)\) also converges spectrally to \(f'(x)\) (Trefethen 2013, Ch. 11).
Mathematically, the spectral differentiation matrix \(D\) satisfies:
For the barycentric differentiation matrix formulas, see Berrut & Trefethen (2004), Section 9.
MaxDerivativeOrder
The maxDerivativeOrder constructor parameter (default 2) controls how many powers
of \(D\) are pre-computed at build time. If you need third-order derivatives, set it to 3:
var cheb = new ChebyshevApproximation(
function: MyFunction,
numDimensions: 3,
domain: new[] { new[] { 0.0, 1.0 }, new[] { 0.0, 1.0 }, new[] { 0.0, 1.0 } },
nNodes: new[] { 15, 15, 15 },
maxDerivativeOrder: 3
);
cheb.Build();
// Third derivative is now available
double d3f = cheb.VectorizedEval(point, new[] { 3, 0, 0 });
Higher derivative orders require more nodes for accurate results. As a rule of thumb, use at least \(n \geq 2k + 5\) nodes per dimension for derivative order \(k\).
Runtime validation. Evaluating a derivative order higher than
maxDerivativeOrderthrowsInvalidOperationException. If you need third-order Greeks, setmaxDerivativeOrder: 3in the constructor.
Accuracy
With 11 nodes per dimension on a 5D Black-Scholes test:
| Greek | Max Relative Error |
|---|---|
| Delta | < 0.01% |
| Gamma | < 0.01% |
| Vega | ~1.98% |
| Rho | < 0.01% |
Vega has slightly higher error because the volatility sensitivity involves a product of multiple terms in the Black-Scholes formula, but remains well within practical tolerance for most applications. Increasing the node count to 13--15 per dimension reduces Vega error below 0.1%.
Tensor Train derivatives.
ChebyshevTTuses finite differences instead of analytical derivatives, because the spectral differentiation matrix requires the full tensor (which TT avoids storing). Central finite differences with step size \(h = (b-a) \times 10^{-4}\) provide 4--8 fewer digits of accuracy than spectral derivatives, but are adequate for most financial applications. See Tensor Train Interpolation for details.
Slider cross-group derivatives. In
ChebyshevSlider, the additive decomposition means that derivatives with respect to variables in different groups are exactly zero. For example, if dimensions 0--1 form one group and dimensions 2--4 form another, then \(\partial^2 V / \partial x_0 \, \partial x_2 = 0\) identically. Only derivatives within the same group are non-trivial.
References
- Berrut, J.-P. & Trefethen, L. N. (2004). "Barycentric Lagrange Interpolation." SIAM Review 46(3):501--517.
- Trefethen, L. N. (2013). Approximation Theory and Approximation Practice. SIAM. Chapter 11.