API Reference¶
Core — Autodiff Engine¶
Tensor class with reverse-mode automatic differentiation.
This is the core data structure for TensorQuantLib. Every computation flows through Tensor objects, which track the computational graph and enable gradient computation via backpropagation.
- class tensorquantlib.core.tensor.Tensor(data, requires_grad=False, _children=(), _op='')[source]¶
Bases:
objectA multi-dimensional array with automatic differentiation support.
Stores data as a NumPy float64 array, optionally tracking gradients. When requires_grad=True, all operations on this tensor build a computational graph that enables reverse-mode autodiff via .backward().
- Parameters:
- data¶
The underlying NumPy array (float64).
- grad¶
Gradient array, populated after .backward(). None until first backward pass.
- requires_grad¶
Whether this tensor participates in gradient computation.
- backward()[source]¶
Compute gradients via reverse-mode automatic differentiation.
Performs a topological sort of the computational graph, then propagates gradients from this tensor back to all ancestors with requires_grad=True.
This tensor’s grad is seeded with ones (dL/dL = 1).
- Return type:
None
- detach()[source]¶
Return a new Tensor with the same data but detached from the graph.
The returned tensor has
requires_grad=Falseand no_children, so gradients will not flow through it. Use this to treat an intermediate result as a constant:y = x * x y_const = y.detach() # gradients stop here
- Return type:
- free_graph()[source]¶
Release all references to the computational graph.
Clears
_childrenand the_backwardclosure for this node and all ancestors, breaking reference cycles and allowing GC to reclaim memory. Call afterbackward()in long-running loops to prevent unbounded memory growth.- Return type:
None
- tensorquantlib.core.tensor.tensor_neg(a)[source]¶
Element-wise negation: z = -a.
- Parameters:
a (Tensor) – Input tensor.
- Returns:
dz/da = -1.
- Return type:
New tensor with negated values. Gradient
Example
>>> x = Tensor(np.array([3.0, -2.0]), requires_grad=True) >>> y = tensor_neg(x) >>> y.data array([-3., 2.])
- tensorquantlib.core.tensor.tensor_pow(a, exponent)[source]¶
Power: z = a^exponent (exponent is a constant, not a Tensor).
- tensorquantlib.core.tensor.tensor_exp(a)[source]¶
Element-wise exponential: z = exp(a).
- Parameters:
a (Tensor) – Input tensor.
- Returns:
dz/da = exp(a).
- Return type:
New tensor with exp(a). Gradient
Example
>>> x = Tensor(np.array([0.0, 1.0]), requires_grad=True) >>> y = tensor_exp(x) >>> np.allclose(y.data, [1.0, np.e]) True
- tensorquantlib.core.tensor.tensor_log(a)[source]¶
Element-wise natural logarithm: z = log(a).
Input is clamped to a minimum of 1e-12 to avoid log(0).
- Parameters:
a (Tensor) – Input tensor (values should be positive).
- Returns:
dz/da = 1/a.
- Return type:
New tensor with log(a). Gradient
Example
>>> x = Tensor(np.array([1.0, np.e]), requires_grad=True) >>> y = tensor_log(x) >>> np.allclose(y.data, [0.0, 1.0]) True
- tensorquantlib.core.tensor.tensor_sqrt(a)[source]¶
Element-wise square root: z = sqrt(a).
- Parameters:
a (Tensor) – Input tensor (values should be non-negative).
- Returns:
dz/da = 1 / (2 * sqrt(a)).
- Return type:
New tensor with sqrt(a). Gradient
Example
>>> x = Tensor(np.array([4.0, 9.0]), requires_grad=True) >>> y = tensor_sqrt(x) >>> np.allclose(y.data, [2.0, 3.0]) True
- tensorquantlib.core.tensor.tensor_mean(a, axis=None, keepdims=False)[source]¶
Mean: z = mean(a, axis).
- tensorquantlib.core.tensor.tensor_maximum(a, val=0.0)[source]¶
Element-wise maximum: z = max(a, val). Used for ReLU and payoff clipping.
- tensorquantlib.core.tensor.tensor_sin(a)[source]¶
Element-wise sine: z = sin(a).
- Parameters:
a (Tensor) – Input tensor (in radians).
- Returns:
dz/da = cos(a).
- Return type:
New tensor with sin(a). Gradient
Example
>>> x = Tensor(np.array([0.0, np.pi / 2]), requires_grad=True) >>> y = tensor_sin(x) >>> np.allclose(y.data, [0.0, 1.0], atol=1e-10) True
- tensorquantlib.core.tensor.tensor_cos(a)[source]¶
Element-wise cosine: z = cos(a).
- Parameters:
a (Tensor) – Input tensor (in radians).
- Returns:
dz/da = -sin(a).
- Return type:
New tensor with cos(a). Gradient
Example
>>> x = Tensor(np.array([0.0, np.pi]), requires_grad=True) >>> y = tensor_cos(x) >>> np.allclose(y.data, [1.0, -1.0], atol=1e-10) True
- tensorquantlib.core.tensor.tensor_tanh(a)[source]¶
Element-wise hyperbolic tangent: z = tanh(a).
- Parameters:
a (Tensor) – Input tensor.
- Returns:
dz/da = 1 - tanh(a)^2.
- Return type:
New tensor with tanh(a). Gradient
Example
>>> x = Tensor(np.array([0.0, 1.0]), requires_grad=True) >>> y = tensor_tanh(x) >>> abs(y.data[0]) < 1e-10 # tanh(0) = 0 True
- tensorquantlib.core.tensor.tensor_abs(a)[source]¶
Element-wise absolute value: z = |a|.
Uses sign(a) as the subgradient, with subgradient 0 at a=0.
- Parameters:
a (Tensor) – Input tensor.
- Returns:
dz/da = sign(a).
- Return type:
New tensor with |a|. Gradient
Example
>>> x = Tensor(np.array([-3.0, 0.0, 5.0]), requires_grad=True) >>> y = tensor_abs(x) >>> y.data array([3., 0., 5.])
- tensorquantlib.core.tensor.tensor_clip(a, a_min, a_max)[source]¶
Element-wise clip: z = clip(a, a_min, a_max).
Gradient is 1 where a is within [a_min, a_max], 0 otherwise.
- tensorquantlib.core.tensor.tensor_where(condition, a, b)[source]¶
Element-wise selection: z = a where condition else b.
- tensorquantlib.core.tensor.tensor_softmax(a, axis=-1)[source]¶
Softmax along an axis: z_i = exp(a_i) / sum_j(exp(a_j)).
Numerically stable via max subtraction.
- tensorquantlib.core.tensor.tensor_getitem(a, idx)[source]¶
Index into a Tensor, preserving gradient flow.
Supports any NumPy-compatible index (int, slice, array, bool mask). Gradient is scattered back to the original positions.
Example:
x = Tensor([1.0, 2.0, 3.0], requires_grad=True) y = x[1] ** 2 # y = 4.0; x.grad[1] = 4.0 after backward
Finance — Pricing & Greeks¶
Black-Scholes option pricing — both NumPy (analytic) and Tensor (autograd) versions.
- Provides:
bs_price_numpy: Pure NumPy analytic pricing (ground truth)
bs_price_tensor: Tensor-based pricing that flows through autograd
bs_delta, bs_gamma, bs_vega, bs_theta, bs_rho: Analytic Greeks (NumPy)
- tensorquantlib.finance.black_scholes.bs_price_numpy(S, K, T, r, sigma, q=0.0, option_type='call')[source]¶
Analytic Black-Scholes price (pure NumPy).
- Parameters:
- Returns:
Option price (same shape as S).
- Return type:
- tensorquantlib.finance.black_scholes.bs_delta(S, K, T, r, sigma, q=0.0, option_type='call')[source]¶
Analytic Delta: dV/dS.
- tensorquantlib.finance.black_scholes.bs_gamma(S, K, T, r, sigma, q=0.0)[source]¶
Analytic Gamma: d²V/dS² (same for call and put).
- tensorquantlib.finance.black_scholes.bs_vega(S, K, T, r, sigma, q=0.0)[source]¶
Analytic Vega: dV/dsigma (same for call and put).
- tensorquantlib.finance.black_scholes.bs_theta(S, K, T, r, sigma, q=0.0, option_type='call')[source]¶
Analytic Theta: -dV/dT (time decay per year).
- tensorquantlib.finance.black_scholes.bs_rho(S, K, T, r, sigma, q=0.0, option_type='call')[source]¶
Analytic Rho: dV/dr.
- tensorquantlib.finance.black_scholes.bs_price_tensor(S, K, T, r, sigma, q=0.0, option_type='call')[source]¶
Black-Scholes price using Tensor operations (supports autograd).
All inputs can be Tensor objects. The computation graph is built so that calling .backward() on the result will produce gradients (Delta = dPrice/dS, Vega = dPrice/dsigma, etc.).
Implied volatility solver for Black-Scholes options.
Provides both scalar and vectorized implied volatility computation using Brent’s method (bisection + secant) via scipy.optimize.brentq, plus a fast Newton-Raphson (Halley) starter based on the Jaeckel (2015) approximation.
- Functions:
implied_vol – scalar IV for a single (price, S, K, T, r) tuple implied_vol_batch – vectorized IV for arrays of market prices iv_surface – build a 2-D IV surface over (K, T) grids
- tensorquantlib.finance.implied_vol.implied_vol(market_price, S, K, T, r, q=0.0, option_type='call', *, tol=1e-08, max_iter=100, sigma_lo=0.0001, sigma_hi=10.0)[source]¶
Compute implied volatility for a single European option via Brent’s method.
Inverts the Black-Scholes formula: finds sigma such that
bs_price_numpy(S, K, T, r, sigma) == market_price.- Parameters:
market_price (float) – Observed option market price.
S (float) – Spot price.
K (float) – Strike price.
T (float) – Time to expiry (years).
r (float) – Risk-free rate.
q (float) – Continuous dividend yield (default 0).
option_type (str) – ‘call’ or ‘put’.
tol (float) – Convergence tolerance on volatility (default 1e-8).
max_iter (int) – Maximum Brent iterations (default 100).
sigma_lo (float) – Lower bound for volatility search (default 1e-4).
sigma_hi (float) – Upper bound for volatility search (default 10.0).
- Returns:
Implied volatility (annualised).
- Raises:
ValueError – If market_price is outside the no-arbitrage bounds, or if the root is not bracketed within [sigma_lo, sigma_hi].
- Return type:
Example
>>> iv = implied_vol(10.45, S=100, K=100, T=1.0, r=0.05) >>> abs(iv - 0.2) < 0.001 True
- tensorquantlib.finance.implied_vol.implied_vol_nr(market_price, S, K, T, r, q=0.0, option_type='call', *, tol=1e-10, max_iter=50)[source]¶
Implied volatility via Newton-Raphson with vega denominator.
Faster than Brent for well-behaved cases (ATM options, moderate T). Falls back to Brent if Newton diverges or vega is too small.
- Parameters:
market_price (float) – Observed option price.
S (float) – Black-Scholes parameters.
K (float) – Black-Scholes parameters.
T (float) – Black-Scholes parameters.
r (float) – Black-Scholes parameters.
q (float) – Black-Scholes parameters.
option_type (str) – Black-Scholes parameters.
tol (float) – Convergence tolerance.
max_iter (int) – Maximum Newton iterations.
- Returns:
Implied volatility.
- Return type:
- tensorquantlib.finance.implied_vol.implied_vol_batch(market_prices, S, K, T, r, q=0.0, option_type='call', *, tol=1e-08, method='brent')[source]¶
Compute implied volatility for arrays of market prices.
All array arguments are broadcast together; scalars are repeated.
- Parameters:
- Returns:
Array of implied volatilities (same broadcast shape). NaN where the solver failed (e.g. below intrinsic).
- Return type:
Example
>>> import numpy as np >>> ivs = implied_vol_batch([5.0, 10.0, 15.0], S=100, K=100, T=1.0, r=0.05)
- tensorquantlib.finance.implied_vol.iv_surface(market_prices, S, K_grid, T_grid, r, q=0.0, option_type='call', tol=1e-08)[source]¶
Build a 2-D implied volatility surface over a (K, T) grid.
- Parameters:
market_prices (ndarray) – 2-D array of shape (len(K_grid), len(T_grid)).
S (float) – Spot price.
K_grid (ndarray) – 1-D array of strikes.
T_grid (ndarray) – 1-D array of expiries.
r (float) – Risk-free rate.
q (float) – Dividend yield.
option_type (str) – ‘call’ or ‘put’.
tol (float) – Solver tolerance.
- Returns:
2-D array of implied volatilities, shape (len(K_grid), len(T_grid)). NaN where solver failed.
- Return type:
Example
>>> import numpy as np >>> from tensorquantlib.finance.black_scholes import bs_price_numpy >>> K = np.array([90.0, 100.0, 110.0]) >>> T = np.array([0.5, 1.0]) >>> prices = np.array([[bs_price_numpy(100, k, t, 0.05, 0.2) for t in T] for k in K]) >>> surf = iv_surface(prices, 100.0, K, T, 0.05) >>> np.allclose(surf, 0.2, atol=1e-4) True
Heston stochastic volatility model — analytical pricing and Monte Carlo simulation.
The Heston (1993) model augments Black-Scholes with a mean-reverting variance process:
dS = (r - q) S dt + sqrt(V) S dW_S dV = kappa (theta - V) dt + xi sqrt(V) dW_V Corr(dW_S, dW_V) = rho * dt
- This module provides:
heston_price_mc – Monte Carlo price (reference implementation) heston_price – Semi-analytic price via COS/Carr-Madan characteristic function heston_greeks – Delta, Gamma, Vega, Theta via finite differences on heston_price HestonCalibrator – Calibrate Heston parameters to market IV surface
References
Heston, S.L. (1993). A Closed-Form Solution for Options with Stochastic Volatility with Applications to Bond and Currency Options. RFS 6(2), 327-343.
Fang, F. & Oosterlee, C.W. (2008). A Novel Pricing Method for European Options Based on Fourier-Cosine Series Expansions. SIAM J. Sci. Comput., 31(2), 826-848.
- class tensorquantlib.finance.heston.HestonParams(kappa=2.0, theta=0.04, xi=0.3, rho=-0.7, v0=0.04)[source]¶
Heston model parameters.
- tensorquantlib.finance.heston.heston_price(S, K, T, r, params, q=0.0, option_type='call', *, integration_limit=200.0, n_points=100)[source]¶
Semi-analytic Heston call/put price via Gil-Pelaez inversion.
Uses numerical integration of the characteristic function.
- Parameters:
S (float) – Spot price.
K (float) – Strike price.
T (float) – Time to expiry (years).
r (float) – Risk-free rate.
params (HestonParams) – HestonParams instance.
q (float) – Continuous dividend yield.
option_type (str) – ‘call’ or ‘put’.
integration_limit (float) – Upper limit for numerical integration (default 200).
n_points (int) – Number of integration points (higher = more accurate).
- Returns:
Option price.
- Return type:
Example
>>> p = HestonParams(kappa=2.0, theta=0.04, xi=0.3, rho=-0.7, v0=0.04) >>> price = heston_price(100.0, 100.0, 1.0, 0.05, p) >>> 5.0 < price < 20.0 True
- tensorquantlib.finance.heston.heston_price_mc(S, K, T, r, params, q=0.0, option_type='call', *, n_paths=100000, n_steps=252, seed=None, return_stderr=False, scheme='qe')[source]¶
Monte Carlo Heston price using the Quadratic-Exponential (QE) discretisation scheme.
The QE scheme (Andersen 2008) provides high accuracy for the CIR variance process, virtually eliminating the discretisation bias of Euler-Maruyama.
- Parameters:
S (float) – Spot.
K (float) – Strike.
T (float) – Time to expiry (years).
r (float) – Risk-free rate.
params (HestonParams) – HestonParams.
q (float) – Dividend yield.
option_type (str) – ‘call’ or ‘put’.
n_paths (int) – Number of simulation paths (default 100k).
n_steps (int) – Time steps (default 252 = daily).
seed (int | None) – Random seed.
return_stderr (bool) – If True, returns (price, stderr) tuple.
scheme (str) – Discretisation scheme — ‘qe’ (default, Andersen 2008) or ‘euler’ (Euler full-truncation, faster but biased).
- Returns:
Price, or (price, stderr) if return_stderr=True.
- Return type:
References
Andersen, L.B.G. (2008). Efficient Simulation of the Heston Stochastic Volatility Model. Journal of Computational Finance, 11(3).
Example
>>> p = HestonParams() >>> price, se = heston_price_mc(100, 100, 1.0, 0.05, p, return_stderr=True, seed=42) >>> 5.0 < price < 20.0 True
- tensorquantlib.finance.heston.heston_greeks(S, K, T, r, params, q=0.0, option_type='call', *, dS=0.5, dT=0.0027397260273972603, dv0=0.001)[source]¶
Compute Heston Greeks via finite differences on the semi-analytic price.
- Parameters:
S (float) – Spot price.
K (float) – Option parameters.
T (float) – Option parameters.
r (float) – Option parameters.
q (float) – Option parameters.
option_type (str) – Option parameters.
params (HestonParams) – HestonParams instance.
dS (float) – Bump size for Delta/Gamma (default 0.5).
dT (float) – Bump size for Theta (default 1/365 year).
dv0 (float) – Bump size for Vega (relative to v0, default 0.001).
- Returns:
‘delta’, ‘gamma’, ‘theta’, ‘vega’. Vega is reported per unit change in v0 (not in sigma).
- Return type:
Dictionary with keys
Example
>>> p = HestonParams() >>> g = heston_greeks(100.0, 100.0, 1.0, 0.05, p) >>> 0.0 < g['delta'] < 1.0 True
- class tensorquantlib.finance.heston.HestonCalibrator(S, r, q=0.0, option_type='call', params_=<factory>)[source]¶
Calibrate Heston model parameters to a market implied-volatility surface.
Usage:
from tensorquantlib.finance.heston import HestonCalibrator, HestonParams import numpy as np cal = HestonCalibrator(S=100.0, r=0.05) K_grid = np.array([90., 95., 100., 105., 110.]) T_grid = np.array([0.5, 1.0, 1.5]) # Build synthetic market IV (20% flat) iv_mkt = np.full((len(K_grid), len(T_grid)), 0.20) cal.fit(iv_mkt, K_grid, T_grid) print(cal.params_)
- Parameters:
S (float)
r (float)
q (float)
option_type (str)
params_ (HestonParams)
- params_¶
Calibrated HestonParams (set after fit()).
- fit(iv_market, K_grid, T_grid, *, n_restarts=3, maxiter=500, verbose=False)[source]¶
Fit Heston parameters to market IV surface.
- Parameters:
iv_market (ndarray) – 2-D array of market implied vols, shape (len(K_grid), len(T_grid)).
K_grid (ndarray) – 1-D array of strikes.
T_grid (ndarray) – 1-D array of expiries.
n_restarts (int) – Number of random re-starts for the optimiser.
maxiter (int) – Maximum optimiser iterations per restart.
verbose (bool) – Print progress.
- Returns:
self
- Return type:
American option pricing via the Longstaff-Schwartz (2001) Least-Squares Monte Carlo (LSM) algorithm.
American options grant the holder the right to exercise early. LSM approximates the continuation value at each time step using polynomial regression on simulated paths, then decides whether early exercise is optimal.
- This module provides:
american_option_lsm – Single-asset American option price american_option_grid – Price a grid of (S, K) or (S, T) combinations american_greeks – Delta, Gamma, Theta via finite-difference bumps on LSM
References
Longstaff, F.A. & Schwartz, E.S. (2001). Valuing American Options by Simulation: A Simple Least-Squares Approach. RFS 14(1), 113-147.
- tensorquantlib.finance.american.american_option_lsm(S, K, T, r, sigma, q=0.0, option_type='put', *, n_paths=100000, n_steps=252, basis_degree=3, seed=None, return_stderr=False)[source]¶
Price an American option via Longstaff-Schwartz LSM.
Simulates GBM paths and uses polynomial regression to estimate the continuation value at each exercise date, then takes the maximum of early exercise and continuation.
- Parameters:
S (float) – Current spot price.
K (float) – Strike price.
T (float) – Time to expiry (years).
r (float) – Risk-free rate.
sigma (float) – Volatility (constant).
q (float) – Continuous dividend yield (default 0).
option_type (str) – ‘put’ or ‘call’.
n_paths (int) – Number of Monte Carlo paths (default 100k).
n_steps (int) – Number of exercise dates (default 252 = daily).
basis_degree (int) – Degree of Laguerre polynomial basis (default 3).
seed (int | None) – Random seed for reproducibility.
return_stderr (bool) – If True, returns (price, stderr).
- Returns:
American option price, or (price, stderr) if return_stderr=True.
- Return type:
Example
>>> price = american_option_lsm(100.0, 100.0, 1.0, 0.05, 0.2, seed=42) >>> 3.0 < price < 8.0 True
- tensorquantlib.finance.american.american_option_grid(S_grid, K, T, r, sigma, q=0.0, option_type='put', *, n_paths=50000, n_steps=100, seed=None)[source]¶
Price American options over a grid of spot prices.
Uses the same path set (bumped spot) to reduce variance across prices.
- Parameters:
S_grid (ndarray) – 1-D array of spot prices.
K (float) – Option parameters.
T (float) – Option parameters.
r (float) – Option parameters.
sigma (float) – Option parameters.
q (float) – Option parameters.
option_type (str) – Option parameters.
n_paths (int) – Simulation parameters.
n_steps (int) – Simulation parameters.
seed (int | None) – Simulation parameters.
- Returns:
1-D array of prices, same length as S_grid.
- Return type:
Example
>>> import numpy as np >>> S_grid = np.linspace(80, 120, 5) >>> prices = american_option_grid(S_grid, K=100, T=1.0, r=0.05, sigma=0.2, seed=0) >>> prices.shape[0] == 5 True
- tensorquantlib.finance.american.american_greeks(S, K, T, r, sigma, q=0.0, option_type='put', *, n_paths=50000, n_steps=100, seed=None, dS=0.5, dT=0.0027397260273972603, dsigma=0.01)[source]¶
Compute American option Greeks via finite differences on LSM prices.
- Parameters:
S (float) – Option parameters.
K (float) – Option parameters.
T (float) – Option parameters.
r (float) – Option parameters.
sigma (float) – Option parameters.
q (float) – Option parameters.
option_type (str) – Option parameters.
n_paths (int) – Simulation settings.
n_steps (int) – Simulation settings.
seed (int | None) – Simulation settings.
dS (float) – Bump size for Delta/Gamma (default 0.5).
dT (float) – Bump size for Theta (default 1/365 year).
dsigma (float) – Bump size for Vega (default 0.01).
- Returns:
‘delta’, ‘gamma’, ‘theta’, ‘vega’.
- Return type:
Dictionary with keys
Example
>>> g = american_greeks(100.0, 100.0, 1.0, 0.05, 0.2, seed=0) >>> 0.0 < abs(g['delta']) < 1.0 True
Exotic options: Asian, digital (binary), and barrier options.
Provides both analytic closed-forms (where available) and Monte Carlo pricing for the following option types built on log-normal GBM dynamics:
- Asian (arithmetic average):
asian_price_mc – Monte Carlo arithmetic Asian call/put asian_geometric_price – Analytic geometric-average Asian (closed-form)
- Digital (binary):
digital_price – Analytic cash-or-nothing and asset-or-nothing digital_price_mc – Monte Carlo digital price (validation)
- Barrier options (single barrier, European):
barrier_price – Analytic single-barrier option (Reiner-Rubinstein) barrier_price_mc – Monte Carlo barrier option price
All analytic formulas assume GBM with constant parameters.
References
Kemna & Vorst (1990). A Pricing Method for Options Based on Average Asset Values. Journal of Banking and Finance, 14(1), 113-129.
Rubinstein, M. & Reiner, E. (1991). Breaking Down the Barriers. Risk 4(8), 28-35.
Reiner, E. (1992). Quanto Mechanics. Risk 5(3), 59-63.
- tensorquantlib.finance.exotics.asian_price_mc(S, K, T, r, sigma, q=0.0, option_type='call', average_type='arithmetic', *, n_paths=100000, n_steps=252, seed=None, return_stderr=False)[source]¶
Price an Asian average-rate option by Monte Carlo.
- The payoff is based on the average of the asset price over [0, T]:
Call: max(avg(S) - K, 0) * exp(-rT) Put: max(K - avg(S), 0) * exp(-rT)
- Parameters:
S (float) – Spot price.
K (float) – Strike.
T (float) – Time to expiry (years).
r (float) – Risk-free rate.
sigma (float) – Volatility.
q (float) – Dividend yield.
option_type (str) – ‘call’ or ‘put’.
average_type (str) – ‘arithmetic’ or ‘geometric’.
n_paths (int) – Monte Carlo paths.
n_steps (int) – Averaging time steps.
seed (int | None) – Random seed.
return_stderr (bool) – If True, return (price, stderr).
- Returns:
Asian option price, or (price, stderr).
- Return type:
Example
>>> price = asian_price_mc(100, 100, 1.0, 0.05, 0.2, seed=0) >>> 5.0 < price < 12.0 True
- tensorquantlib.finance.exotics.asian_geometric_price(S, K, T, r, sigma, q=0.0, option_type='call')[source]¶
Closed-form price for continuous geometric-average Asian option (Kemna & Vorst 1990).
Applicable to continuous monitoring (limit of n_steps → ∞).
- Parameters:
- Returns:
Geometric Asian option price.
- Return type:
Example
>>> p = asian_geometric_price(100, 100, 1.0, 0.05, 0.2) >>> 5.0 < p < 12.0 True
- tensorquantlib.finance.exotics.digital_price(S, K, T, r, sigma, q=0.0, option_type='call', payoff_type='cash', payoff_amount=1.0)[source]¶
Analytic Black-Scholes price for a digital (binary) option.
- Parameters:
S (float) – Spot price.
K (float) – Strike.
T (float) – Time to expiry (years).
r (float) – Risk-free rate.
sigma (float) – Volatility.
q (float) – Dividend yield.
option_type (str) – ‘call’ (pays if S_T > K) or ‘put’ (pays if S_T < K).
payoff_type (str) – ‘cash’ (fixed cash) or ‘asset’ (deliver asset if triggered).
payoff_amount (float) – Size of the cash payment if payoff_type=’cash’ (default 1.0).
- Returns:
Digital option price.
- Return type:
Example
>>> p = digital_price(100, 100, 1.0, 0.05, 0.2, payoff_type='cash') >>> 0.0 < p < 1.0 True
- tensorquantlib.finance.exotics.digital_greeks(S, K, T, r, sigma, q=0.0, option_type='call', payoff_type='cash', payoff_amount=1.0)[source]¶
Analytic Black-Scholes Greeks for digital options.
Returns delta, gamma, vega, theta, rho.
Example
>>> g = digital_greeks(100, 100, 1.0, 0.05, 0.2) >>> 'delta' in g and 'gamma' in g True
- tensorquantlib.finance.exotics.digital_price_mc(S, K, T, r, sigma, q=0.0, option_type='call', payoff_type='cash', payoff_amount=1.0, *, n_paths=100000, seed=None, return_stderr=False)[source]¶
Monte Carlo price for a digital option (validation).
Example
>>> p = digital_price_mc(100, 100, 1.0, 0.05, 0.2, seed=0) >>> 0.0 < p < 1.0 True
- tensorquantlib.finance.exotics.barrier_price(S, K, T, r, sigma, barrier, barrier_type, q=0.0, option_type='call', rebate=0.0)[source]¶
Analytic price for European single-barrier options (Rubinstein-Reiner 1991).
Supports all 8 standard barrier option types:
‘down-and-in’ call/put – activated if S crosses H from above ‘down-and-out’ call/put – extinguished if S crosses H from above ‘up-and-in’ call/put – activated if S crosses H from below ‘up-and-out’ call/put – extinguished if S crosses H from below
- Parameters:
S (float) – Spot price.
K (float) – Strike price.
T (float) – Time to expiry.
r (float) – Risk-free rate.
sigma (float) – Volatility.
barrier (float) – Barrier level H.
barrier_type (str) – One of {‘down-and-in’, ‘down-and-out’, ‘up-and-in’, ‘up-and-out’}.
q (float) – Dividend yield.
option_type (str) – ‘call’ or ‘put’.
rebate (float) – Cash rebate paid if barrier is not hit (for out options).
- Returns:
Barrier option price.
- Raises:
ValueError – If barrier_type or option_type are invalid.
- Return type:
Example
>>> p = barrier_price(100, 100, 1.0, 0.05, 0.2, barrier=90, barrier_type='down-and-out') >>> p > 0 True
- tensorquantlib.finance.exotics.barrier_price_mc(S, K, T, r, sigma, barrier, barrier_type, q=0.0, option_type='call', rebate=0.0, *, n_paths=200000, n_steps=252, seed=None, return_stderr=False)[source]¶
Monte Carlo price for a European single-barrier option.
- Parameters:
S (float) – Standard parameters.
K (float) – Standard parameters.
T (float) – Standard parameters.
r (float) – Standard parameters.
sigma (float) – Standard parameters.
q (float) – Standard parameters.
barrier (float) – Barrier level.
barrier_type (str) – ‘down-and-in’, ‘down-and-out’, ‘up-and-in’, ‘up-and-out’.
option_type (str) – ‘call’ or ‘put’.
rebate (float) – Rebate paid when knocked out/never knocked in.
n_paths (int) – Simulation parameters.
n_steps (int) – Simulation parameters.
seed (int | None) – Simulation parameters.
return_stderr (bool) – Return (price, stderr) if True.
- Returns:
Price, or (price, stderr).
- Return type:
Example
>>> p = barrier_price_mc(100, 100, 1.0, 0.05, 0.2, barrier=90, barrier_type='down-and-out', seed=0) >>> p > 0 True
- tensorquantlib.finance.exotics.lookback_fixed_analytic(S, K, T, r, sigma, q=0.0, option_type='call')[source]¶
Analytic fixed-strike lookback option price (Goldman-Sosin-Gatto 1979).
For a fixed-strike lookback call, the payoff is max(S_max - K, 0). For a fixed-strike lookback put, the payoff is max(K - S_min, 0).
- Parameters:
S (standard option parameters.)
K (standard option parameters.)
T (standard option parameters.)
r (standard option parameters.)
sigma (standard option parameters.)
q (standard option parameters.)
option_type (standard option parameters.)
- Returns:
Option price.
- Return type:
- tensorquantlib.finance.exotics.lookback_floating_analytic(S, T, r, sigma, q=0.0, option_type='call')[source]¶
Analytic floating-strike lookback option price.
At inception S_min = S_max = S.
- tensorquantlib.finance.exotics.lookback_price_mc(S, K, T, r, sigma, q=0.0, option_type='call', strike_type='fixed', n_paths=100000, n_steps=252, seed=None)[source]¶
Monte Carlo lookback option price.
- tensorquantlib.finance.exotics.cliquet_price_mc(S, T, r, sigma, q=0.0, n_periods=4, cap=None, floor=None, global_cap=None, global_floor=None, n_paths=100000, n_steps_per_period=63, seed=None)[source]¶
Monte Carlo cliquet (ratchet) option pricer.
- tensorquantlib.finance.exotics.rainbow_price_mc(spots, K, T, r, sigmas, corr, q=None, option_type='call', rainbow_type='best-of', n_paths=100000, n_steps=252, seed=None)[source]¶
Monte Carlo rainbow option pricer (best-of / worst-of).
Basket option pricing via Monte Carlo simulation.
- Provides:
simulate_basket: Multi-asset GBM simulation for basket option pricing
- build_pricing_grid: Construct a multi-dimensional pricing tensor
for Tensor-Train compression
- tensorquantlib.finance.basket.simulate_basket(S0, K, T, r, sigma, corr, weights, n_paths=100000, q=None, option_type='call', seed=None)[source]¶
Price a basket option via Monte Carlo simulation.
Uses correlated geometric Brownian motion (GBM) under the risk-neutral measure to simulate terminal asset prices.
Payoff_call = max(sum(w_i * S_i(T)) - K, 0) Price = exp(-rT) * E[Payoff]
- Parameters:
S0 (ndarray) – Initial spot prices, shape (d,).
K (float) – Strike price.
T (float) – Time to expiry (years).
r (float) – Risk-free rate.
sigma (ndarray) – Volatilities, shape (d,).
corr (ndarray) – Correlation matrix, shape (d, d).
weights (ndarray) – Basket weights, shape (d,).
n_paths (int) – Number of Monte Carlo paths.
q (ndarray | None) – Dividend yields, shape (d,). Defaults to zero.
option_type (str) – ‘call’ or ‘put’.
seed (int | None) – Random seed for reproducibility.
- Returns:
Discounted expected payoff and its standard error.
- Return type:
(price, stderr)
- tensorquantlib.finance.basket.build_pricing_grid(S0_ranges, K, T, r, sigma, corr, weights, n_points=30, n_mc_paths=1000, q=None, option_type='call', seed=42)[source]¶
Build a multi-dimensional pricing tensor for TT compression.
For each combination of spot prices on the grid, runs a Monte Carlo simulation to compute the basket option price. Returns a d-dimensional tensor of shape (n_points, n_points, …, n_points).
- Parameters:
S0_ranges (list[tuple[float, float]]) – List of (min, max) tuples for each asset’s spot range.
K (float) – Strike price.
T (float) – Time to expiry.
r (float) – Risk-free rate.
sigma (ndarray) – Volatilities, shape (d,).
corr (ndarray) – Correlation matrix, shape (d, d).
weights (ndarray) – Basket weights, shape (d,).
n_points (int) – Number of grid points per asset.
n_mc_paths (int) – MC paths per grid point (use fewer for speed).
q (ndarray | None) – Dividend yields.
option_type (str) – ‘call’ or ‘put’.
seed (int) – Base random seed.
- Returns:
The pricing tensor and list of 1D grid axes.
- Return type:
(grid_tensor, axes)
- tensorquantlib.finance.basket.build_pricing_grid_analytic(S0_ranges, K, T, r, sigma, weights, n_points=30)[source]¶
Build a pricing grid using log-normal moment-matching (Gentle 1993).
Approximates the basket option price by matching the first two moments of the basket value to a single log-normal distribution, then applying the Black-Scholes formula to that equivalent asset. This is the standard “moment-matching” approximation used in practice for European basket options.
The approximation is accurate to within ~1-3% for typical parameters and produces a smooth, low-rank tensor ideal for TT compression.
For deep ITM/OTM or highly correlated assets (rho > 0.9), consider using
build_pricing_grid(Monte Carlo) for higher accuracy.- Parameters:
S0_ranges (list[tuple[float, float]]) – List of (min, max) tuples for each asset’s spot range.
K (float) – Strike price.
T (float) – Time to expiry.
r (float) – Risk-free rate.
sigma (ndarray) – Volatilities per asset, shape (d,).
weights (ndarray) – Basket weights, shape (d,).
n_points (int) – Grid points per axis.
- Returns:
Pricing tensor and grid axes.
- Return type:
(grid_tensor, axes)
Autograd-based Greeks computation.
Computes option sensitivities by running the pricing function through the Tensor autograd engine and extracting gradients.
Delta (dV/dS) via first-order autograd
Vega (dV/dσ) via first-order autograd
Gamma (d²V/dS²) via second-order autograd (gamma_autograd)
Vanna (d²V/dS dσ) via second-order autograd (vanna_autograd)
Volga (d²V/dσ²) via second-order autograd (volga_autograd)
- tensorquantlib.finance.greeks.compute_greeks(price_fn, S, K, T, r, sigma, q=0.0, option_type='call', include_second_order=True)[source]¶
Compute Delta, Vega, Gamma (and optionally Vanna, Volga) using autograd.
First-order Greeks (Delta, Vega) come from a single backward pass. Second-order Greeks (Gamma, Vanna, Volga) use the hybrid semi-analytic method from
tensorquantlib.core.second_order: analytical gradients differentiated once more by central differences (~1e-10 accuracy).- Parameters:
price_fn (Callable[[...], Tensor]) – Pricing function accepting
(S, K, T, r, sigma, q, option_type)and returning a Tensor.S (float) – Spot price.
K (float) – Strike price.
T (float) – Time to expiry.
r (float) – Risk-free rate.
sigma (float) – Volatility.
q (float) – Dividend yield.
option_type (str) –
'call'or'put'.include_second_order (bool) – If True (default), also compute Gamma, Vanna, and Volga. Set False for speed when only first-order Greeks are needed.
- Returns:
Dict with keys
'price','delta','vega', and (wheninclude_second_order=True)'gamma','vanna','volga'.- Return type:
- tensorquantlib.finance.greeks.compute_greeks_vectorized(price_fn, S_array, K, T, r, sigma, q=0.0, option_type='call')[source]¶
Compute Greeks for a vector of spot prices.
- Parameters:
- Returns:
Dict with ‘price’, ‘delta’, ‘vega’ as arrays matching S_array.
- Return type:
Variance reduction techniques for Monte Carlo option pricing.
This module provides drop-in variance-reduced Monte Carlo pricers that remain compatible with the rest of TensorQuantLib.
- Techniques:
Antithetic variates (halves variance for symmetric payoffs)
Control variates (using geometric average as control for arithmetic Asian)
Quasi-Monte Carlo (Sobol) (faster convergence with low-discrepancy sequences)
Importance sampling (shift drift to reduce rare-event variance)
Stratified sampling (Gaussian stratification via quantile transform)
Each function mirrors the signature of the standard Monte Carlo pricers
but adds a method or technique argument.
References
Glasserman, P. (2003). Monte Carlo Methods in Financial Engineering. Springer. Joe, S. & Kuo, F.Y. (2008). Constructing Sobol sequences with better two-dimensional projections. SIAM J. Sci. Comput. 30(5), 2635-2654.
- tensorquantlib.finance.variance_reduction.bs_price_antithetic(S, K, T, r, sigma, q=0.0, option_type='call', *, n_paths=100000, seed=None, return_stderr=False)[source]¶
European option price via MC with antithetic variates.
For a standard GBM payoff, using the paired (z, -z) construction reduces variance by roughly 50% compared to crude Monte Carlo.
- Parameters:
S (float) – Standard Black-Scholes parameters.
K (float) – Standard Black-Scholes parameters.
T (float) – Standard Black-Scholes parameters.
r (float) – Standard Black-Scholes parameters.
sigma (float) – Standard Black-Scholes parameters.
q (float) – Standard Black-Scholes parameters.
option_type (str) – Standard Black-Scholes parameters.
n_paths (int) – Total number of paths (must be even; half are antithetic).
seed (int | None) – Random seed.
return_stderr (bool) – If True, return (price, stderr).
- Returns:
Price, or (price, stderr).
- Return type:
Example
>>> p = bs_price_antithetic(100, 100, 1.0, 0.05, 0.2, seed=42) >>> 9.0 < p < 12.0 True
- tensorquantlib.finance.variance_reduction.asian_price_cv(S, K, T, r, sigma, q=0.0, option_type='call', *, n_paths=100000, n_steps=252, seed=None, return_stderr=False)[source]¶
Asian arithmetic-average option with geometric control variate.
Uses the closed-form geometric Asian price (Kemna & Vorst 1990) as a control variate, exploiting the high correlation between arithmetic and geometric averages to dramatically reduce estimator variance.
- Parameters:
S (float) – Option parameters.
K (float) – Option parameters.
T (float) – Option parameters.
r (float) – Option parameters.
sigma (float) – Option parameters.
q (float) – Option parameters.
option_type (str) – Option parameters.
n_paths (int) – MC paths.
n_steps (int) – Time steps for averaging.
seed (int | None) – Random seed.
return_stderr (bool) – Return (price, stderr) tuple.
- Returns:
Asian option price (control-variate-adjusted), or (price, stderr).
- Return type:
Example
>>> p = asian_price_cv(100, 100, 1.0, 0.05, 0.2, seed=42) >>> 5.0 < p < 12.0 True
- tensorquantlib.finance.variance_reduction.bs_price_qmc(S, K, T, r, sigma, q=0.0, option_type='call', *, n_paths=65536, scramble=True, seed=None, return_stderr=False)[source]¶
European option price via Quasi-Monte Carlo (1-D Sobol sequence).
Low-discrepancy sequences converge at O(1/N) vs O(1/sqrt(N)) for pseudo-random MC, giving ~10-100x better accuracy for the same N.
Requires scipy >= 1.7 for qmc.Sobol.
- Parameters:
S (float) – Black-Scholes parameters.
K (float) – Black-Scholes parameters.
T (float) – Black-Scholes parameters.
r (float) – Black-Scholes parameters.
sigma (float) – Black-Scholes parameters.
q (float) – Black-Scholes parameters.
option_type (str) – Black-Scholes parameters.
n_paths (int) – Number of QMC samples (ideally a power of 2).
scramble (bool) – Use Owen scrambling (recommended, better uniformity).
seed (int | None) – Scrambling seed.
return_stderr (bool) – Return (price, stderr).
- Returns:
Price, or (price, stderr).
- Return type:
Example
>>> p = bs_price_qmc(100, 100, 1.0, 0.05, 0.2, seed=42) >>> 9.0 < p < 12.0 True
- tensorquantlib.finance.variance_reduction.bs_price_importance(S, K, T, r, sigma, q=0.0, option_type='call', *, n_paths=100000, seed=None, return_stderr=False)[source]¶
European option price via importance sampling.
Shifts the sampling distribution to centre around the region where the option pays off. Particularly effective for deep OTM options where crude MC needs huge N.
The optimal drift shift is: mu* = log(K/S) / (sigma * sqrt(T)) - sigma * sqrt(T) / 2
- Parameters:
S (float) – Standard parameters.
K (float) – Standard parameters.
T (float) – Standard parameters.
r (float) – Standard parameters.
sigma (float) – Standard parameters.
q (float) – Standard parameters.
option_type (str) – Standard parameters.
n_paths (int) – Number of paths.
seed (int | None) – Random seed.
return_stderr (bool) – Return (price, stderr).
- Returns:
Price, or (price, stderr).
- Return type:
Example
>>> p = bs_price_importance(100, 100, 1.0, 0.05, 0.2, seed=0) >>> 9.0 < p < 12.0 True
- tensorquantlib.finance.variance_reduction.bs_price_stratified(S, K, T, r, sigma, q=0.0, option_type='call', *, n_paths=100000, n_strata=100, seed=None, return_stderr=False)[source]¶
European option price via stratified sampling over the unit interval.
Divides [0,1] into n_strata equal strata and draws one uniform sample from each, then maps via the quantile function. This reduces variance by eliminating within-stratum variability.
- Parameters:
S (float) – Parameters.
K (float) – Parameters.
T (float) – Parameters.
r (float) – Parameters.
sigma (float) – Parameters.
q (float) – Parameters.
option_type (str) – Parameters.
n_paths (int) – Total paths (rounded to nearest multiple of n_strata).
n_strata (int) – Number of strata.
seed (int | None) – Random seed.
return_stderr (bool) – Return (price, stderr).
- Returns:
Price, or (price, stderr).
- Return type:
Example
>>> p = bs_price_stratified(100, 100, 1.0, 0.05, 0.2, seed=0) >>> 9.0 < p < 12.0 True
- tensorquantlib.finance.variance_reduction.compare_variance_reduction(S, K, T, r, sigma, q=0.0, option_type='call', n_paths=50000, seed=42)[source]¶
Compare all variance reduction methods for a European option.
Returns a dict mapping method name -> {‘price’: …, ‘stderr’: …, ‘vr_ratio’: …} where vr_ratio = stderr_crude_mc / stderr_method (higher is better).
- Parameters:
S (float) – Black-Scholes parameters.
K (float) – Black-Scholes parameters.
T (float) – Black-Scholes parameters.
r (float) – Black-Scholes parameters.
sigma (float) – Black-Scholes parameters.
q (float) – Black-Scholes parameters.
option_type (str) – Black-Scholes parameters.
n_paths (int) – Paths used for each method.
seed (int) – Random seed.
- Returns:
Dictionary of results per method.
- Return type:
Example
>>> results = compare_variance_reduction(100, 100, 1.0, 0.05, 0.2, seed=0) >>> 'crude_mc' in results and 'antithetic' in results True
Risk metrics for option portfolios and underlying assets.
- Provides:
PortfolioRisk – Class to compute VaR, CVaR, volatility, Sharpe, max drawdown var_historical – Historical simulation VaR var_parametric – Parametric (normal) VaR var_mc – Monte Carlo VaR via GBM cvar – Conditional VaR (Expected Shortfall) scenario_analysis – P&L under a set of stress scenarios greeks_portfolio – Aggregate Greeks across a book of options
- Definitions:
VaR(alpha): loss L such that P(L > VaR) = 1 - alpha (e.g. 95% VaR) CVaR(alpha): E[L | L > VaR(alpha)] (also called Expected Shortfall / ES)
All loss figures are expressed as a fraction of current portfolio value unless stated otherwise.
References
McNeil, A.J., Frey, R. & Embrechts, P. (2005). Quantitative Risk Management. Princeton University Press.
- tensorquantlib.finance.risk.var_parametric(mu, sigma, alpha=0.95, horizon=0.003968253968253968)[source]¶
Parametric (Gaussian) VaR at confidence level alpha.
Assumes P&L is normally distributed: P&L ~ N(mu*h, sigma^2*h).
- Parameters:
- Returns:
VaR as a positive number (= loss at alpha-quantile).
- Return type:
Example
>>> v = var_parametric(0.0, 0.20, alpha=0.95) >>> v > 0 True
- tensorquantlib.finance.risk.var_historical(returns, alpha=0.95)[source]¶
Historical simulation VaR.
- Parameters:
- Returns:
VaR as a positive number (lower tail quantile of losses).
- Return type:
Example
>>> import numpy as np >>> r = np.random.default_rng(0).normal(0, 0.01, 1000) >>> v = var_historical(r, alpha=0.95) >>> v > 0 True
- tensorquantlib.finance.risk.cvar(returns, alpha=0.95)[source]¶
Conditional VaR (Expected Shortfall) at confidence level alpha.
CVaR = E[loss | loss > VaR(alpha)] — the average loss in the worst (1-alpha) tail.
- Parameters:
- Returns:
CVaR as a positive number.
- Return type:
Example
>>> import numpy as np >>> r = np.random.default_rng(0).normal(0, 0.01, 1000) >>> es = cvar(r, alpha=0.95) >>> es >= var_historical(r, alpha=0.95) True
- tensorquantlib.finance.risk.var_mc(S, sigma, horizon=0.003968253968253968, r=0.0, q=0.0, alpha=0.95, n_paths=100000, seed=None)[source]¶
Monte Carlo VaR and CVaR for a single equity position.
Simulates GBM returns over the given horizon and computes VaR and CVaR from the simulated distribution.
- Parameters:
- Returns:
(VaR, CVaR) as positive numbers representing fractional loss of S.
- Return type:
Example
>>> v, es = var_mc(100.0, 0.20, alpha=0.95, seed=42) >>> v > 0 and es >= v True
- tensorquantlib.finance.risk.scenario_analysis(S, position_value_fn, scenarios)[source]¶
Compute P&L under a set of spot-price stress scenarios.
- Parameters:
- Returns:
Dict mapping scenario name -> {‘S_stressed’, ‘value’, ‘pnl’, ‘pnl_pct’}.
- Return type:
Example
>>> def v(s): return max(s - 100, 0) # long call >>> results = scenario_analysis(100.0, v, {'down': 90.0, 'up': 110.0}) >>> 'down' in results and 'up' in results True
- class tensorquantlib.finance.risk.OptionPosition(option_type, K, T, sigma, quantity=1.0, multiplier=1.0)[source]¶
A single option position in a portfolio.
- tensorquantlib.finance.risk.greeks_portfolio(positions, S, r, q=0.0)[source]¶
Aggregate Black-Scholes Greeks for a portfolio of options on the same underlying.
- Parameters:
positions (list[OptionPosition]) – List of OptionPosition objects.
S (float) – Current spot price.
r (float) – Risk-free rate.
q (float) – Dividend yield.
- Returns:
Dict with aggregated ‘delta’, ‘gamma’, ‘vega’, ‘theta’, ‘rho’, and ‘value’.
- Return type:
Example
>>> pos = [OptionPosition('call', K=100, T=1.0, sigma=0.2, quantity=1)] >>> g = greeks_portfolio(pos, S=100, r=0.05) >>> 0.0 < g['delta'] < 1.0 True
- class tensorquantlib.finance.risk.PortfolioRisk(returns, alpha=0.95, risk_free_daily=0.0)[source]¶
Compute risk metrics for a time series of portfolio returns.
Usage:
import numpy as np risk = PortfolioRisk(returns=np.random.normal(0.0002, 0.01, 252)) risk.summary()
- returns¶
1-D array of daily log-returns or P&L fractions.
- Type:
- volatility(annualise=True)[source]¶
Return volatility (std dev). Annualised by sqrt(252) if annualise=True.
Volatility surface models: SABR and SVI parameterizations.
Implements industry-standard volatility surface parameterizations: - SABR (Hagan et al., 2002): stochastic alpha-beta-rho model - SVI (Gatheral, 2004): stochastic volatility inspired parameterization
- tensorquantlib.finance.volatility.sabr_implied_vol(F, K, T, alpha, beta, rho, nu)[source]¶
Compute SABR implied volatility using the Hagan (2002) approximation.
- Parameters:
- Returns:
SABR implied Black volatility.
- Return type:
float or array
- tensorquantlib.finance.volatility.sabr_calibrate(market_vols, F, strikes, T, beta=0.5, initial_guess=None)[source]¶
Calibrate SABR parameters (alpha, rho, nu) to market implied vols.
- Parameters:
market_vols (array) – Market implied volatilities.
F (float) – Forward price.
strikes (array) – Strike prices corresponding to market_vols.
T (float) – Time to expiry.
beta (float) – Fixed CEV exponent (default 0.5).
initial_guess (tuple, optional) – Initial (alpha, rho, nu). Defaults to (0.2, -0.3, 0.4).
- Returns:
{‘alpha’: …, ‘beta’: …, ‘rho’: …, ‘nu’: …, ‘rmse’: …}
- Return type:
- tensorquantlib.finance.volatility.svi_raw(k, a, b, rho, m, sigma)[source]¶
SVI raw parameterization for total implied variance.
w(k) = a + b * (rho * (k - m) + sqrt((k - m)^2 + sigma^2))
- Parameters:
- Returns:
Total implied variance w(k).
- Return type:
float or array
- tensorquantlib.finance.volatility.svi_implied_vol(k, T, a, b, rho, m, sigma)[source]¶
Convert SVI total variance to Black implied volatility.
- Parameters:
- Returns:
Implied volatility (annualized).
- Return type:
float or array
- tensorquantlib.finance.volatility.svi_calibrate(market_vols, strikes, F, T, initial_guess=None)[source]¶
Calibrate SVI raw parameters to market implied vols.
- Parameters:
- Returns:
{‘a’: …, ‘b’: …, ‘rho’: …, ‘m’: …, ‘sigma’: …, ‘rmse’: …}
- Return type:
- tensorquantlib.finance.volatility.svi_surface(strikes, expiries, F, params_per_expiry)[source]¶
Build an implied volatility surface from SVI parameters per expiry.
- Parameters:
- Returns:
Implied volatility surface.
- Return type:
array, shape (n_expiries, n_strikes)
Interest rate models: Vasicek, CIR, Nelson-Siegel, and yield curve bootstrap.
Implements short-rate models and yield curve fitting: - Vasicek (1977): mean-reverting Gaussian short rate - CIR (1985): mean-reverting square-root short rate - Nelson-Siegel (1987): parametric yield curve
- tensorquantlib.finance.rates.vasicek_bond_price(r0, kappa, theta, sigma, T)[source]¶
Zero-coupon bond price under the Vasicek model.
dr = kappa * (theta - r) * dt + sigma * dW
- tensorquantlib.finance.rates.vasicek_yield(r0, kappa, theta, sigma, T)[source]¶
Continuously compounded yield under Vasicek: y = -ln(P)/T.
- tensorquantlib.finance.rates.vasicek_option_price(r0, kappa, theta, sigma, T_option, T_bond, K, option_type='call')[source]¶
European option on a zero-coupon bond under Vasicek.
- Parameters:
r0 (float) – Current short rate.
kappa (float) – Vasicek parameters.
theta (float) – Vasicek parameters.
sigma (float) – Vasicek parameters.
T_option (float) – Option expiry.
T_bond (float) – Bond maturity (T_bond > T_option).
K (float) – Strike price of the option.
option_type (str) – ‘call’ or ‘put’.
- Returns:
Option price.
- Return type:
- tensorquantlib.finance.rates.vasicek_simulate(r0, kappa, theta, sigma, T, n_steps=252, n_paths=10000, seed=None)[source]¶
Simulate Vasicek short rate paths.
- tensorquantlib.finance.rates.cir_bond_price(r0, kappa, theta, sigma, T)[source]¶
Zero-coupon bond price under the CIR model.
dr = kappa * (theta - r) * dt + sigma * sqrt(r) * dW
- Parameters:
- Returns:
Bond price P(0, T).
- Return type:
- tensorquantlib.finance.rates.cir_yield(r0, kappa, theta, sigma, T)[source]¶
Continuously compounded yield under CIR.
- tensorquantlib.finance.rates.cir_simulate(r0, kappa, theta, sigma, T, n_steps=252, n_paths=10000, seed=None)[source]¶
Simulate CIR short rate paths (full truncation scheme).
- tensorquantlib.finance.rates.feller_condition(kappa, theta, sigma)[source]¶
Check the Feller condition: 2*kappa*theta >= sigma^2.
When satisfied, CIR process stays strictly positive.
- tensorquantlib.finance.rates.nelson_siegel(T, beta0, beta1, beta2, tau)[source]¶
Nelson-Siegel (1987) yield curve model.
- y(T) = beta0 + beta1 * (1 - exp(-T/tau)) / (T/tau)
beta2 * ((1 - exp(-T/tau)) / (T/tau) - exp(-T/tau))
- Parameters:
- Returns:
Yield(s) at the given maturity/maturities.
- Return type:
float or array
- tensorquantlib.finance.rates.nelson_siegel_calibrate(maturities, yields, initial_guess=None)[source]¶
Calibrate Nelson-Siegel parameters to market yields.
- tensorquantlib.finance.rates.bootstrap_yield_curve(maturities, prices)[source]¶
Bootstrap zero-coupon yields from bond prices.
Assumes prices are for zero-coupon bonds with face value 1.
- Parameters:
maturities (array) – Bond maturities.
prices (array) – Bond prices (face value 1).
- Returns:
Continuously compounded zero rates.
- Return type:
array
FX options: Garman-Kohlhagen and Quanto models.
Implements FX-specific option pricing: - Garman-Kohlhagen (1983): Black-Scholes adapted for FX with foreign rate - Quanto options: options on foreign assets settled in domestic currency
- tensorquantlib.finance.fx.garman_kohlhagen(S, K, T, r_d, r_f, sigma, option_type='call')[source]¶
Garman-Kohlhagen FX option pricing model.
This is the Black-Scholes formula adapted for FX, where the foreign risk-free rate acts as a continuous dividend yield.
- Parameters:
- Returns:
Option price in domestic currency.
- Return type:
- tensorquantlib.finance.fx.gk_greeks(S, K, T, r_d, r_f, sigma, option_type='call')[source]¶
Compute Garman-Kohlhagen Greeks.
- tensorquantlib.finance.fx.fx_forward(S, r_d, r_f, T)[source]¶
FX forward rate via covered interest rate parity.
F = S * exp((r_d - r_f) * T)
- tensorquantlib.finance.fx.quanto_option(S, K, T, r_d, r_f, sigma_s, sigma_fx, rho, fx_rate, option_type='call')[source]¶
Quanto option pricing (option on foreign asset, settled in domestic currency).
The quanto adjustment modifies the drift of the foreign asset due to the correlation between the asset and the FX rate.
- Parameters:
S (float) – Spot price of the foreign asset (in foreign currency).
K (float) – Strike price (in foreign currency).
T (float) – Time to expiry.
r_d (float) – Domestic risk-free rate.
r_f (float) – Foreign risk-free rate.
sigma_s (float) – Volatility of the foreign asset.
sigma_fx (float) – Volatility of the FX rate.
rho (float) – Correlation between the asset and FX rate.
fx_rate (float) – Fixed FX rate at which payoff is converted.
option_type (str) – ‘call’ or ‘put’.
- Returns:
Quanto option price in domestic currency.
- Return type:
Credit risk models: Merton structural model and reduced-form CDS pricing.
Merton (1974) structural model treats equity as a call option on firm assets. Reduced-form models price CDS using hazard rates and survival probabilities.
- tensorquantlib.finance.credit.merton_default_prob(V, D, T, r, sigma_V)[source]¶
Probability of default under Merton (1974) structural model.
Default occurs when firm value V_T < D at maturity.
- tensorquantlib.finance.credit.merton_credit_spread(V, D, T, r, sigma_V)[source]¶
Credit spread implied by the Merton model.
spread = -(1/T) * ln(B / (D * exp(-r*T))) where B is the risky bond price = D*exp(-r*T) - Put(V, D, T).
- Parameters:
V (float) – Same as
merton_default_prob().D (float) – Same as
merton_default_prob().T (float) – Same as
merton_default_prob().r (float) – Same as
merton_default_prob().sigma_V (float) – Same as
merton_default_prob().
- Returns:
Annual credit spread (continuously compounded).
- Return type:
- tensorquantlib.finance.credit.survival_probability(hazard_rate, T)[source]¶
Survival probability under constant hazard rate.
Q(T) = exp(-lambda * T)
- tensorquantlib.finance.credit.hazard_rate_from_spread(spread, recovery=0.4)[source]¶
Implied constant hazard rate from CDS spread.
lambda ≈ spread / (1 - R)
- tensorquantlib.finance.credit.cds_spread(hazard_rate, T, recovery=0.4, r=0.05, n_premium_dates=4)[source]¶
Par CDS spread for constant hazard rate.
Premium leg = spread * sum( DF_i * Q_i * delta_i ) Protection leg = (1-R) * sum( DF_i * (Q_{i-1} - Q_i) )
We solve for spread = protection_leg / risky_annuity.
- tensorquantlib.finance.credit.cds_price(hazard_rate, T, recovery=0.4, r=0.05, spread=0.01, notional=1000000.0, n_premium_dates=4)[source]¶
Mark-to-market value of a CDS position (protection buyer).
MTM = protection_leg - spread * risky_annuity
- Parameters:
- Returns:
MTM value of the CDS position for the protection buyer.
- Return type:
Jump-diffusion models for option pricing.
Merton (1976) jump-diffusion: analytic + MC
Kou (2002) double-exponential jump-diffusion: MC
- tensorquantlib.finance.jump_diffusion.merton_jump_price(S, K, T, r, sigma, lam, mu_j, sigma_j, option_type='call', n_terms=50)[source]¶
Merton (1976) jump-diffusion price via series expansion.
The stock follows dS/S = (r - lambda*k)*dt + sigma*dW + J*dN where N is Poisson(lambda*T), J ~ LogNormal(mu_j, sigma_j^2), and k = E[e^J - 1] = exp(mu_j + sigma_j^2/2) - 1.
- Parameters:
S (float) – Spot price.
K (float) – Strike price.
T (float) – Time to expiry (years).
r (float) – Risk-free rate.
sigma (float) – Diffusion volatility.
lam (float) – Jump intensity (expected number of jumps per year).
mu_j (float) – Mean of log-jump size.
sigma_j (float) – Std dev of log-jump size.
option_type (str) –
'call'or'put'.n_terms (int) – Number of terms in the series expansion.
- Returns:
Option price.
- Return type:
- tensorquantlib.finance.jump_diffusion.merton_jump_price_mc(S, K, T, r, sigma, lam, mu_j, sigma_j, option_type='call', n_paths=100000, n_steps=252, seed=None)[source]¶
Merton jump-diffusion price via Monte Carlo.
- Parameters:
S (float) – Same as
merton_jump_price().K (float) – Same as
merton_jump_price().T (float) – Same as
merton_jump_price().r (float) – Same as
merton_jump_price().sigma (float) – Same as
merton_jump_price().lam (float) – Same as
merton_jump_price().mu_j (float) – Same as
merton_jump_price().sigma_j (float) – Same as
merton_jump_price().option_type (str) – Same as
merton_jump_price().n_paths (int) – Number of MC paths.
n_steps (int) – Time steps per path.
seed (int, optional) – Random seed.
- Returns:
MC estimate of the option price.
- Return type:
- tensorquantlib.finance.jump_diffusion.kou_jump_price_mc(S, K, T, r, sigma, lam, p, eta1, eta2, option_type='call', n_paths=100000, n_steps=252, seed=None)[source]¶
Kou (2002) double-exponential jump-diffusion via Monte Carlo.
- Jump sizes J follow a double-exponential distribution:
- f(x) = p * eta1 * exp(-eta1*x) * 1_{x>=0}
(1-p) * eta2 * exp(eta2*x) * 1_{x<0}
- Parameters:
S (float) – Spot price.
K (float) – Strike price.
T (float) – Time to expiry.
r (float) – Risk-free rate.
sigma (float) – Diffusion volatility.
lam (float) – Jump intensity.
p (float) – Probability of upward jump (0 < p < 1).
eta1 (float) – Rate parameter for upward jumps (eta1 > 1 for finite expectation).
eta2 (float) – Rate parameter for downward jumps (eta2 > 0).
option_type (str) –
'call'or'put'.n_paths (int) – Number of MC paths.
n_steps (int) – Time steps.
seed (int, optional) – Random seed.
- Returns:
MC estimate of option price.
- Return type:
Local volatility model (Dupire).
The Dupire (1994) local volatility formula extracts local vol from an implied volatility surface, enabling exact calibration to European option prices.
- tensorquantlib.finance.local_vol.dupire_local_vol(strikes, expiries, iv_surface, S, r=0.0, q=0.0)[source]¶
Compute Dupire local volatility from an implied vol surface.
Uses the Dupire (1994) formula:
- sigma_loc^2(K,T) = (dC/dT + (r-q)*K*dC/dK + q*C)
/ (0.5 * K^2 * d2C/dK^2)
where C(K,T) is the Black-Scholes price at implied vol sigma(K,T).
- Parameters:
- Returns:
local_vol – Local volatility surface.
- Return type:
array, shape (nK, nT)
- tensorquantlib.finance.local_vol.local_vol_mc(S, K, T, r, strikes, expiries, local_vol_surface, option_type='call', q=0.0, n_paths=100000, n_steps=252, seed=None)[source]¶
Price an option using local vol MC simulation.
Simulates paths under dS = (r-q)*S*dt + sigma_loc(S,t)*S*dW.
- Parameters:
S (float) – Spot price.
K (float) – Strike.
T (float) – Expiry.
r (float) – Risk-free rate.
strikes (array) – Strike grid for local vol interpolation.
expiries (array) – Time grid for local vol interpolation.
local_vol_surface (array, shape (nK, nT)) – Local volatility surface.
option_type (str) –
'call'or'put'.q (float) – Dividend yield.
n_paths (int) – MC paths.
n_steps (int) – Time steps.
seed (int, optional) – Random seed.
- Returns:
MC price.
- Return type:
Interest rate derivatives: swaptions, caps, and floors.
Pricing under the Black (1976) model for European swaptions and caplets.
- tensorquantlib.finance.ir_derivatives.black76_caplet(forward, strike, T, sigma, df, notional=1.0, tau=0.25)[source]¶
Price a single caplet using the Black (1976) model.
- Parameters:
forward (float) – Forward rate for the period.
strike (float) – Cap strike rate.
T (float) – Time to caplet expiry (option maturity).
sigma (float) – Black implied volatility for the forward rate.
df (float) – Discount factor to payment date.
notional (float) – Notional amount.
tau (float) – Day count fraction for the period.
- Returns:
Caplet price.
- Return type:
- tensorquantlib.finance.ir_derivatives.black76_floorlet(forward, strike, T, sigma, df, notional=1.0, tau=0.25)[source]¶
Price a single floorlet using Black (1976).
- Parameters:
forward (float) – Same as
black76_caplet().strike (float) – Same as
black76_caplet().T (float) – Same as
black76_caplet().sigma (float) – Same as
black76_caplet().df (float) – Same as
black76_caplet().notional (float) – Same as
black76_caplet().tau (float) – Same as
black76_caplet().
- Returns:
Floorlet price.
- Return type:
- tensorquantlib.finance.ir_derivatives.cap_price(forwards, strike, expiries, sigma, dfs, notional=1.0, tau=0.25)[source]¶
Price an interest rate cap (sum of caplets).
- Parameters:
forwards (array, shape (n,)) – Forward rates for each period.
strike (float) – Cap strike.
expiries (array, shape (n,)) – Expiry time for each caplet.
sigma (float or array) – Black vol (flat or per-caplet).
dfs (array, shape (n,)) – Discount factors to each payment date.
notional (float) – Notional.
tau (float) – Day count fraction.
- Returns:
Total cap price.
- Return type:
- tensorquantlib.finance.ir_derivatives.floor_price(forwards, strike, expiries, sigma, dfs, notional=1.0, tau=0.25)[source]¶
Price an interest rate floor (sum of floorlets).
Parameters same as
cap_price().
- tensorquantlib.finance.ir_derivatives.swap_rate(dfs, tau=0.5)[source]¶
Par swap rate from discount factors.
S = (df_0 - df_n) / (tau * sum(df_i))
- tensorquantlib.finance.ir_derivatives.swaption_price(swap_r, strike, T_option, sigma, annuity, notional=1.0, payer=True)[source]¶
Price a European swaption using Black (1976).
- Parameters:
swap_r (float) – Forward swap rate.
strike (float) – Swaption strike.
T_option (float) – Time to swaption expiry.
sigma (float) – Black implied vol for the swap rate.
annuity (float) – PV of the swap’s fixed-leg annuity factor.
notional (float) – Notional.
payer (bool) – If True, price a payer swaption (right to pay fixed). If False, price a receiver swaption.
- Returns:
Swaption price.
- Return type:
Data — Market Data¶
Market data wrappers using yfinance.
All functions require the yfinance package, which is an optional
dependency installable via pip install tensorquantlib[data].
- tensorquantlib.data.market.get_stock_price(ticker)[source]¶
Get the latest closing price for a ticker.
- tensorquantlib.data.market.get_historical_prices(ticker, start, end)[source]¶
Fetch historical OHLCV data.
- tensorquantlib.data.market.get_options_chain(ticker, expiry=None)[source]¶
Fetch options chain data.
- Parameters:
- Returns:
Keys:
'calls'and'puts', each a dict with numpy arrays for'strike','lastPrice','bid','ask','impliedVolatility','volume','openInterest'.- Return type:
Backtesting¶
Performance metrics for backtesting.
- tensorquantlib.backtest.metrics.sharpe_ratio(returns, rf=0.0, periods_per_year=252)[source]¶
Annualised Sharpe ratio.
- tensorquantlib.backtest.metrics.max_drawdown(equity)[source]¶
Maximum drawdown from peak.
- Parameters:
equity (array-like) – Equity curve (absolute values).
- Returns:
Maximum drawdown as a positive fraction (e.g. 0.15 = 15%).
- Return type:
- tensorquantlib.backtest.metrics.sortino_ratio(returns, rf=0.0, periods_per_year=252)[source]¶
Annualised Sortino ratio (downside deviation only).
- tensorquantlib.backtest.metrics.win_rate(trades)[source]¶
Fraction of profitable trades.
- Parameters:
trades (array-like) – P&L per trade (positive = profit).
- Returns:
Win rate in [0, 1].
- Return type:
- tensorquantlib.backtest.metrics.profit_factor(trades)[source]¶
Profit factor = gross profits / gross losses.
- Parameters:
trades (array-like) – P&L per trade.
- Returns:
Profit factor. Returns inf if no losses.
- Return type:
- tensorquantlib.backtest.metrics.annualized_return(equity, periods_per_year=252)[source]¶
Compound annualized growth rate (CAGR) from an equity curve.
- tensorquantlib.backtest.metrics.calmar_ratio(equity, periods_per_year=252)[source]¶
Calmar ratio = annualized return / maximum drawdown.
- tensorquantlib.backtest.metrics.information_ratio(strategy_returns, benchmark_returns, periods_per_year=252)[source]¶
Annualised information ratio (IR).
IR = E[active_return] / std(active_return) * sqrt(periods_per_year)
- tensorquantlib.backtest.metrics.turnover(trades, initial_capital=1000000.0)[source]¶
Annualized one-way turnover as a fraction of initial capital.
turnover = total_notional_traded / initial_capital
- tensorquantlib.backtest.metrics.hedge_pnl_attribution(equity_curve, deltas, gammas, prices)[source]¶
Decompose per-step portfolio P&L into Delta, Gamma, and residual.
For a continuously delta-hedged portfolio, the per-step P&L can be approximated as:
\[\text{Total P\&L} \approx \underbrace{\Delta \cdot \Delta S}_{\text{delta P\&L}} + \underbrace{\tfrac{1}{2}\Gamma (\Delta S)^2}_{\text{gamma P\&L}} + \text{residual}\]The residual captures higher-order terms (Theta decay, vanna, etc.) and hedging error from discrete rebalancing.
- Parameters:
- Returns:
Keys
'delta_pnl','gamma_pnl','residual_pnl'. Each is an array of length N-1.- Return type:
- tensorquantlib.backtest.metrics.hedge_efficiency(hedged_equity, unhedged_equity)[source]¶
Variance reduction achieved by a hedge.
\[\text{efficiency} = 1 - \frac{\operatorname{Var}(\text{hedged P\&L})}{ \operatorname{Var}(\text{unhedged P\&L})}\]Returns 1.0 for a perfect hedge, 0.0 if the hedge adds no value, and a negative number if the hedge increases variance.
- Parameters:
hedged_equity (array-like) – Equity curve of the hedged portfolio.
unhedged_equity (array-like) – Equity curve of the same portfolio without hedging.
- Returns:
Hedge efficiency in (-inf, 1].
- Return type:
Backtesting engine with realistic execution cost models.
- class tensorquantlib.backtest.engine.SlippageModel(fixed_spread=0.0, market_impact=0.0, adv=1000000.0)[source]¶
Bases:
objectMarket-impact and bid-ask spread model.
Total slippage = half-spread cost + square-root market-impact cost.
- Parameters:
fixed_spread (float) – One-way half-spread as a fraction of price. E.g.
0.0005= 5 bps one-way (10 bps round-trip).market_impact (float) – Square-root market-impact coefficient. Cost per unit =
price × market_impact × sqrt(|qty| / adv). Set to 0 to disable market impact.adv (float) – Average daily volume (units). Used for impact scaling only.
- class tensorquantlib.backtest.engine.CommissionModel(per_trade=0.0, per_unit=0.0, percentage=0.0, minimum=0.0)[source]¶
Bases:
objectCommission / brokerage fee model.
Total commission = max(per_trade + per_unit×|qty| + percentage×notional, minimum).
- Parameters:
- tensorquantlib.backtest.engine.ZERO_COST = CommissionModel(per_trade=0.0, per_unit=0.0, percentage=0.0, minimum=0.0)¶
Zero-cost model (default when no model is supplied).
- tensorquantlib.backtest.engine.EQUITY_COMM = CommissionModel(per_trade=0.0, per_unit=0.005, percentage=0.0, minimum=1.0)¶
Interactive Brokers-style equity commission ($0.005/share, $1 min).
- tensorquantlib.backtest.engine.FX_COMM = CommissionModel(per_trade=0.0, per_unit=0.0, percentage=2e-05, minimum=0.0)¶
Typical institutional FX desk (0.2 bps of notional).
- tensorquantlib.backtest.engine.EQUITY_SLIP = SlippageModel(fixed_spread=0.0005, market_impact=0.0, adv=1000000.0)¶
Liquid-equity half-spread slippage (5 bps one-way).
- tensorquantlib.backtest.engine.ILLIQUID_SLIP = SlippageModel(fixed_spread=0.002, market_impact=0.1, adv=50000)¶
20 bps spread + square-root market impact.
- Type:
Illiquid name
- class tensorquantlib.backtest.engine.BacktestResult(equity_curve, trades, returns, final_equity, total_commission=0.0, total_slippage=0.0, total_turnover=0.0, n_trades=0, greeks_history=<factory>)[source]¶
Bases:
objectContainer for backtest output.
- Parameters:
- class tensorquantlib.backtest.engine.BacktestEngine(strategy, prices, initial_capital=1000000.0, slippage=None, commission=None)[source]¶
Bases:
objectRun a
Strategyover a price series with realistic execution.- Parameters:
strategy (Strategy) – Strategy instance to run.
prices (array-like) – 1-D array of asset prices (one per time step).
initial_capital (float) – Starting cash.
slippage (SlippageModel, optional) – Slippage model. Defaults to
SlippageModel()(zero slippage). UseEQUITY_SLIPfor a realistic liquid-equity preset.commission (CommissionModel, optional) – Commission model. Defaults to
CommissionModel()(zero fees). UseEQUITY_COMMfor an Interactive Brokers-style preset.
Examples
Zero-cost (default):
engine = BacktestEngine(strategy, prices)
With realistic costs:
from tensorquantlib.backtest.engine import EQUITY_SLIP, EQUITY_COMM engine = BacktestEngine( strategy, prices, slippage=EQUITY_SLIP, commission=EQUITY_COMM, )
- run()[source]¶
Execute the backtest and return a
BacktestResult.- Return type:
Abstract base strategy and concrete strategy implementations.
- class tensorquantlib.backtest.strategy.Trade(step, quantity, price, label='', slippage=0.0, commission=0.0)[source]¶
Bases:
objectRecord of a single trade.
- Parameters:
- class tensorquantlib.backtest.strategy.Strategy[source]¶
Bases:
ABCBase class for backtesting strategies.
Sub-classes must implement
on_data().
- class tensorquantlib.backtest.strategy.DeltaHedgeStrategy(K, T_total, r, sigma, option_type='call', n_steps=252)[source]¶
Bases:
StrategyDelta-hedge a short option position using Black-Scholes delta.
At each step compute BS delta and rebalance the hedge portfolio. Also tracks per-step Delta and Gamma in
_greeks_historyfor P&L attribution viahedge_pnl_attribution().- Parameters:
- class tensorquantlib.backtest.strategy.GammaScalpingStrategy(K, T_total, r, sigma_implied, n_steps=252)[source]¶
Bases:
StrategyGamma scalping: delta-hedge a long straddle and harvest realized volatility.
The strategy holds a synthetic long straddle (long gamma) and continuously delta-hedges to remain directionally neutral. It profits when realized volatility exceeds the implied volatility embedded in the initial option price.
Per-step P&L attribution (stored in
_greeks_history):Daily P&L ≈ ½Γ(ΔS)² (gamma P&L — profits from large moves) + Θ · Δt (theta P&L — loses time value daily) + residual (higher-order / hedging error)When realized_vol > implied_vol the gamma P&L dominates and the strategy is profitable over the full holding period.
- Parameters:
- class tensorquantlib.backtest.strategy.DeltaGammaHedgeStrategy(K1, K2, T_total, r, sigma, n_steps=252, option_type='call')[source]¶
Bases:
StrategyDelta-Gamma neutral hedge using two options and the underlying.
Holds a primary long option (strike
K1) and hedges Gamma using a second option (strikeK2). Any residual Delta is neutralised using the underlying asset.At each rebalancing step the hedge ratios are:
\[ \begin{align}\begin{aligned}Q_{\text{hedge}} = \frac{\Gamma_1(S,T)}{\Gamma_2(S,T)} \qquad \text{(makes net Gamma = 0)}\\N_{\text{stock}} = -(\Delta_1 - Q_{\text{hedge}} \cdot \Delta_2) \qquad \text{(makes net Delta = 0)}\end{aligned}\end{align} \]The
_greeks_historydict recordsnet_delta,net_gamma,hedge_ratio, andstock_positionat every step.- Parameters:
K1 (float) – Strike of the primary (long) option.
K2 (float) – Strike of the hedge option (must differ from K1 for the gamma hedge to be non-trivial).
T_total (float) – Time to expiry at inception (years).
r (float) – Risk-free rate.
sigma (float) – Implied volatility (flat smile assumed).
n_steps (int) – Total rebalancing steps.
option_type (str) –
'call'or'put'for both legs.
- class tensorquantlib.backtest.strategy.StraddleStrategy(interval=21)[source]¶
Bases:
StrategyBuy a straddle at regular intervals.
This is a simple strategy that opens a new straddle position every
intervalsteps by buying one unit of the asset and recording the entry price.- Parameters:
interval (int) – Number of steps between new straddle entries.
TT Compression¶
Tensor-Train decomposition algorithms.
- Implements:
tt_svd: TT-SVD decomposition (Oseledets, 2011)
tt_round: TT-rounding via orthogonalization + truncated SVD
- tt_cross: Black-box TT-Cross approximation (Oseledets & Tyrtyshnikov, 2010)
Builds a TT decomposition without forming the full tensor, making 6+ asset problems feasible.
- tensorquantlib.tt.decompose.tt_svd(tensor, eps=1e-06, max_rank=None)[source]¶
Tensor-Train SVD decomposition.
Decomposes a d-dimensional tensor A of shape (n1, n2, …, nd) into a list of TT-cores [G1, G2, …, Gd] where G_k has shape (r_{k-1}, n_k, r_k) and r_0 = r_d = 1.
The reconstruction satisfies
||A - A_TT||_F <= eps * ||A||_F.Algorithm: Sequential left-to-right unfolding with truncated SVD. Per-step truncation threshold:
delta = eps * ||A||_F / sqrt(d-1).
- tensorquantlib.tt.decompose.tt_round(cores, eps=1e-06, max_rank=None)[source]¶
Reduce TT-ranks via orthogonalization + truncated SVD sweep.
Two-pass algorithm: 1. Right-to-left QR sweep (right-orthogonalize) 2. Left-to-right SVD sweep with truncation
This is used after TT arithmetic (e.g., tt_add) which inflates ranks.
- tensorquantlib.tt.decompose.tt_cross(fn, shape, eps=0.0001, max_rank=20, n_sweeps=8, seed=42)[source]¶
TT-Cross black-box approximation (Oseledets & Tyrtyshnikov, 2010).
Constructs a Tensor-Train decomposition of a d-dimensional function without forming the full tensor. Only queries
fnat a carefully selected set of index combinations — O(d · r² · n) evaluations instead of O(n^d) for TT-SVD.This makes 6+ asset problems feasible:
6 assets, 15 pts/axis, rank 10 → ~54,000 evaluations
vs. 15^6 = 11,390,625 for full-grid TT-SVD
Algorithm¶
Initialise right index sets J_k randomly.
Left-to-right sweep: for each core k, evaluate the cross C_k = f(I_k × {0..n_k-1} × J_k) and select new left pivots I_{k+1} via greedy maxvol on the QR factor of C_k.
Build TT-cores using the cross-interpolation formula: Core_k = C_k @ pinv(Z_k) where Z_k = f(I_{k+1} ++ J_k) is the (r_k × r_k) interface matrix.
Alternating sweeps refine accuracy.
- param fn:
Function accepting
dinteger arguments (grid indices) and returning a float:fn(i_0, i_1, ..., i_{d-1}) -> float
Use
functools.partialor a lambda to curry other parameters.- type fn:
callable
- param shape:
Mode sizes
(n_0, n_1, ..., n_{d-1}). These are index sizes. To convert continuous axes to indices, wrapfnaccordingly.- type shape:
tuple of int
- param eps:
Target relative accuracy. Controls rank selection via the tolerance passed to the SVD truncation after each cross.
- type eps:
float
- param max_rank:
Hard upper bound on TT-ranks.
- type max_rank:
int
- param n_sweeps:
Number of left-to-right + right-to-left alternating sweeps.
n_sweeps=1gives a single L→R pass (fast, lower accuracy).n_sweeps=4is sufficient for smooth pricing surfaces.- type n_sweeps:
int
- param seed:
Random seed for initialising right index sets.
- type seed:
int
- returns:
TT-cores[k].shape =
(r_{k-1}, n_k, r_k)withr_0 = r_d = 1.- rtype:
list of np.ndarray
Examples
Compress a 6-asset basket payoff without forming the 15^6 grid:
import numpy as np from tensorquantlib.tt.decompose import tt_cross # Suppose price_lookup(i0, i1, i2, i3, i4, i5) evaluates the # basket option price at the i-th point on each asset's price axis. axes = [np.linspace(80, 120, 15)] * 6 def price_lookup(*indices): spots = [axes[k][i] for k, i in enumerate(indices)] return basket_mc(spots, ...) # your existing pricer cores = tt_cross(price_lookup, shape=(15,)*6, max_rank=15, n_sweeps=6)
Notes
After calling
tt_cross, wrap the result in aTTSurrogate:from tensorquantlib.tt.surrogate import TTSurrogate surr = TTSurrogate(cores=cores, axes=axes, eps=eps)
Tensor-Train operations — evaluation, reconstruction, arithmetic, diagnostics.
- Provides:
tt_eval: Evaluate a single element from TT cores
tt_eval_batch: Vectorized multi-point evaluation
tt_to_full: Reconstruct full tensor from TT cores (validation only)
tt_add: Add two TT tensors (rank-additive)
tt_scale: Multiply a TT tensor by a scalar
tt_hadamard: Element-wise product of two TT tensors
tt_dot: Inner product of two TT tensors (no reconstruction)
tt_ranks: Get TT-ranks
tt_memory: Compute memory usage of TT format
tt_error: Compute relative reconstruction error
- tensorquantlib.tt.ops.tt_eval(cores, indices)[source]¶
Evaluate a single element of a tensor in TT format.
- Computes A[i1, i2, …, id] by contracting core slices:
result = G1[:, i1, :] @ G2[:, i2, :] @ … @ Gd[:, id, :]
Complexity: O(d * r^2) where r is the max rank.
- tensorquantlib.tt.ops.tt_eval_batch(cores, indices_array)[source]¶
Evaluate multiple elements of a tensor in TT format.
Vectorized version of tt_eval for batch evaluation.
- tensorquantlib.tt.ops.tt_to_full(cores)[source]¶
Reconstruct the full tensor from TT cores.
WARNING: Only use for validation on small tensors. Memory usage is O(n1 * n2 * … * nd).
- tensorquantlib.tt.ops.tt_error(cores, original)[source]¶
Compute relative Frobenius reconstruction error.
error = ||A - A_TT||_F / ||A||_F
WARNING: Requires full tensor reconstruction — only for small tensors.
- tensorquantlib.tt.ops.tt_compression_ratio(cores, original_shape)[source]¶
Compute compression ratio: full_size / tt_size.
- tensorquantlib.tt.ops.tt_add(cores_a, cores_b)[source]¶
Add two TT tensors: C = A + B.
The result has TT-ranks that are the sum of the input ranks. Use tt_round() afterwards to compress back down.
Both tensors must have the same mode sizes (n_k).
- tensorquantlib.tt.ops.tt_scale(cores, alpha)[source]¶
Multiply a TT tensor by a scalar: B = alpha * A.
Only modifies the first core (ranks unchanged).
- tensorquantlib.tt.ops.tt_hadamard(cores_a, cores_b)[source]¶
Element-wise (Hadamard) product of two TT tensors: C = A ⊙ B.
The result has TT-ranks that are the product of the input ranks. Use tt_round() afterwards to compress.
- tensorquantlib.tt.ops.tt_dot(cores_a, cores_b)[source]¶
Inner product of two TT tensors: <A, B> = sum(A ⊙ B).
Computed efficiently without full reconstruction via sequential transfer-matrix contraction. O(d * r_a^2 * r_b^2 * n).
- tensorquantlib.tt.ops.tt_frobenius_norm(cores)[source]¶
Frobenius norm of a TT tensor: ||A||_F = sqrt(<A, A>).
Computed without reconstruction.
TT-Surrogate — fast approximate option pricing via Tensor-Train compression.
- The TTSurrogate class wraps the full pipeline:
Build a pricing grid (MC or analytic)
Compress it with TT-SVD
Evaluate prices at arbitrary points via TT interpolation
Compute Greeks via autograd through the surrogate
For 6+ assets, use from_function() which applies TT-Cross and never builds the full grid.
Typical usage:
from tensorquantlib.tt.surrogate import TTSurrogate
# ≤5 assets — TT-SVD on full grid
surr = TTSurrogate.from_basket(
S0_ranges=[(80, 120)] * 3,
K=100, T=1.0, r=0.05, sigma=[0.2]*3,
corr=np.eye(3), weights=[1/3]*3,
n_points=30, eps=1e-4,
)
# 6+ assets — TT-Cross (no full grid)
surr6 = TTSurrogate.from_function(
fn=my_pricer, # fn(*integer_indices) -> float
axes=[np.linspace(80, 120, 15)] * 6,
max_rank=15, eps=1e-4, n_sweeps=6,
)
price = surr.evaluate([100, 105, 95])
greeks = surr.greeks([100, 105, 95])
- class tensorquantlib.tt.surrogate.TTSurrogate(cores, axes, eps, build_time=0.0, compress_time=0.0, original_shape=None, original_nbytes=None)[source]¶
Bases:
objectTensor-Train surrogate pricing model.
Stores a TT-compressed pricing grid and provides fast evaluation by mapping continuous spot prices to grid indices via linear interpolation.
- Parameters:
- cores¶
List of TT-cores.
- axes¶
List of 1D arrays — grid points along each asset axis.
- n_assets¶
Number of assets.
- build_time¶
Time (sec) to build the pricing grid.
- compress_time¶
Time (sec) to run TT-SVD.
- eps¶
TT-SVD tolerance used.
- classmethod from_grid(grid, axes, eps=0.0001, max_rank=None)[source]¶
Build surrogate from a pre-computed pricing grid.
- classmethod from_basket_analytic(S0_ranges, K, T, r, sigma, weights, n_points=30, eps=0.0001, max_rank=None)[source]¶
Build surrogate from analytic basket pricing grid.
Uses weighted Black-Scholes approximation — fast but approximate.
- classmethod from_basket_mc(S0_ranges, K, T, r, sigma, corr, weights, n_points=30, n_mc_paths=50000, eps=0.0001, max_rank=None)[source]¶
Build surrogate from Monte-Carlo basket pricing grid.
Slow but accurate. Suitable for validation.
- classmethod from_function(fn, axes, eps=0.0001, max_rank=20, n_sweeps=6, seed=42)[source]¶
Build surrogate via TT-Cross — no full grid needed.
This is the recommended constructor for 6+ asset problems. TT-Cross samples the pricing function at O(d · r² · n) selected index combinations instead of the full n^d grid, making high-dimensional problems feasible.
- Parameters:
fn (callable) –
Function accepting
dinteger grid-index arguments and returning a float price:fn(i_0, i_1, ..., i_{d-1}) -> float
The simplest way to build this is to pre-compute an axis array for continuous spots and index into it inside
fn. Example:axes = [np.linspace(80, 120, 15)] * 6 def my_pricer(*indices): spots = [axes[k][i] for k, i in enumerate(indices)] return basket_mc(spots, K, T, r, sigma, corr) surr = TTSurrogate.from_function(my_pricer, axes)
axes (list of np.ndarray) – 1D grid arrays, one per asset.
len(axes)is the number of assets.axes[k][i]gives the spot price at indexifor assetk.eps (float) – Relative accuracy target passed to TT-Cross.
max_rank (int) – Hard upper bound on TT-ranks. Increase if accuracy is insufficient; decrease if speed is the priority.
n_sweeps (int) – Number of left-to-right + right-to-left alternating sweeps. Default 6 is sufficient for smooth option pricing surfaces.
seed (int) – Random seed for TT-Cross initialisation.
- Return type:
- evaluate(spots)[source]¶
Evaluate the surrogate price at given spot prices.
Uses multi-linear interpolation on the TT grid.
- evaluate_tensor(spots)[source]¶
Evaluate surrogate price and return a Tensor for autograd.
This enables computing Greeks via backward().
- greeks(spots, h=0.0001)[source]¶
Compute Greeks via autograd through the surrogate.
Delta: ∂price/∂S_i for each asset (via autograd). Gamma: (Delta(S+h) - Delta(S-h)) / 2h (finite-diff on Delta).
- plot_surface(dims=(0, 1), fixed_indices=None, title='Pricing Surface', mode='heatmap', **kwargs)[source]¶
Plot a 2D pricing surface slice.
Evaluates the full pricing grid from TT-cores and plots a 2D heatmap or 3D surface. Any extra keyword arguments are forwarded to
plot_pricing_surface.- Parameters:
- Returns:
(fig, ax)matplotlib tuple.- Return type:
- plot_greeks(dims=(0, 1), fixed_indices=None, h=0.01, **kwargs)[source]¶
Plot Delta and Gamma surfaces as side-by-side heatmaps.
Computes Greek grids via finite differences on the TT surrogate and plots them using
plot_greeks_surface.
TT-accelerated pricing — build compressed surrogates for MC-based pricers.
Provides factory functions that build TT-surrogate models by evaluating Monte-Carlo pricers on structured grids and compressing via TT-SVD.
- Supported pricers:
Heston stochastic volatility (
heston_surrogate)American options via LSM (
american_surrogate)Exotic options — asian, barrier, lookback (
exotic_surrogate)Jump-diffusion — Merton analytic (
jump_diffusion_surrogate)
Usage:
from tensorquantlib.tt.pricing import heston_surrogate
surr = heston_surrogate(
S_range=(80, 120), K_range=(90, 110),
T_range=(0.25, 2.0), n_points=15, eps=1e-4,
)
price = surr.evaluate([100, 105, 1.0])
- tensorquantlib.tt.pricing.heston_surrogate(S_range=(80, 120), K_range=(90, 110), T_range=(0.25, 2.0), r=0.05, v0=0.04, kappa=2.0, theta=0.04, xi=0.3, rho=-0.7, n_points=15, eps=0.0001, max_rank=None, n_mc_paths=50000, option_type='call')[source]¶
Build a TT-surrogate for Heston MC prices over (S, K, T).
- Parameters:
r (float) – Risk-free rate.
v0 (float) – Heston parameters.
kappa (float) – Heston parameters.
theta (float) – Heston parameters.
xi (float) – Heston parameters.
rho (float) – Heston parameters.
n_points (int) – Grid points per axis.
eps (float) – TT-SVD tolerance.
max_rank (int | None) – Maximum TT-rank.
n_mc_paths (int) – Paths for Heston MC.
option_type (str) – “call” or “put”.
- Returns:
TTSurrogate with axes [S, K, T].
- Return type:
- tensorquantlib.tt.pricing.american_surrogate(S_range=(80, 120), K_range=(90, 110), T_range=(0.25, 2.0), r=0.05, sigma=0.2, n_points=15, eps=0.0001, max_rank=None, n_paths=50000, n_steps=100, option_type='put')[source]¶
Build a TT-surrogate for American option (LSM) prices over (S, K, T).
- Parameters:
- Returns:
TTSurrogate with axes [S, K, T].
- Return type:
- tensorquantlib.tt.pricing.exotic_surrogate(exotic_type='asian', S_range=(80, 120), K_range=(90, 110), T_range=(0.25, 2.0), r=0.05, sigma=0.2, n_points=15, eps=0.0001, max_rank=None, n_paths=50000, **pricer_kwargs)[source]¶
Build a TT-surrogate for exotic option MC prices over (S, K, T).
- Parameters:
exotic_type (str) – One of “asian”, “barrier_up_out”, “barrier_down_out”, “lookback_fixed”, “lookback_floating”.
r (float) – Risk-free rate.
sigma (float) – Volatility.
n_points (int) – Grid points per axis.
eps (float) – TT-SVD tolerance.
max_rank (int | None) – Maximum TT-rank.
n_paths (int) – MC paths.
**pricer_kwargs – Extra keyword arguments passed to the underlying pricer.
- Returns:
TTSurrogate with axes [S, K, T].
- Return type:
- tensorquantlib.tt.pricing.jump_diffusion_surrogate(S_range=(80, 120), K_range=(90, 110), T_range=(0.25, 2.0), r=0.05, sigma=0.2, lam=1.0, mu_j=-0.05, sigma_j=0.1, n_points=15, eps=0.0001, max_rank=None, option_type='call')[source]¶
Build a TT-surrogate for Merton jump-diffusion prices over (S, K, T).
Uses the analytic series expansion (fast) rather than MC.
- Parameters:
r (float) – Risk-free rate.
sigma (float) – Diffusion volatility.
lam (float) – Jump intensity.
mu_j (float) – Mean jump size.
sigma_j (float) – Jump size volatility.
n_points (int) – Grid points per axis.
eps (float) – TT-SVD tolerance.
max_rank (int | None) – Maximum TT-rank.
option_type (str) – “call” or “put”.
- Returns:
TTSurrogate with axes [S, K, T].
- Return type:
Utilities¶
Numerical gradient validation utilities.
Provides central-difference gradient checking to validate the autograd engine. Used in tests to verify that backward() produces correct gradients.
- tensorquantlib.utils.validation.numerical_gradient(fn, inputs, eps=1e-05)[source]¶
Compute numerical gradients via central differences.
For each input tensor with requires_grad=True, perturbs each element by ±eps and computes (f(x+eps) - f(x-eps)) / (2*eps).
- Parameters:
- Returns:
List of gradient arrays, one per input. None for inputs where requires_grad=False.
- Return type:
- tensorquantlib.utils.validation.check_grad(fn, inputs, eps=1e-05, tol=1e-05)[source]¶
Compare autograd gradients with numerical gradients.
Runs forward + backward through fn, then computes numerical gradients via central differences, and reports the maximum relative error.
- Parameters:
- Returns:
‘max_error’: float — maximum relative error across all inputs ‘errors’: list of per-input max relative errors (None if not checked) ‘passed’: bool — True if max_error < tol
- Return type:
Dict with keys
Visualization¶
Plotting functions for TensorQuantLib.
All functions return (fig, ax) tuples so callers can customise further.
Matplotlib is imported lazily — the rest of the library works without it.
- tensorquantlib.viz.plots.plot_pricing_surface(grid, axis_values, dims=(0, 1), fixed_indices=None, title='Pricing Surface', xlabel=None, ylabel=None, cmap='viridis', figsize=(8, 6), mode='heatmap')[source]¶
Plot a 2D slice of a pricing grid as heatmap or 3D surface.
- Parameters:
grid (np.ndarray) – N-dimensional pricing grid (NumPy array).
axis_values (Sequence[np.ndarray]) – List of 1D arrays giving tick values along each axis.
dims (tuple[int, int]) – Which two axes to plot. The remaining axes are sliced at
fixed_indices(default: midpoints).fixed_indices (dict[int, int] | None) –
{axis: index}overrides for slicing.title (str) – Plot title.
xlabel (str | None) – Label for x-axis (default: “Axis {dims[0]}”).
ylabel (str | None) – Label for y-axis (default: “Axis {dims[1]}”).
cmap (str) – Matplotlib colour-map name.
figsize (tuple[float, float]) – Figure size in inches
(width, height).mode (str) –
"heatmap"(default) or"surface"(3D).
- Returns:
(fig, ax)tuple.- Return type:
tuple[matplotlib.figure.Figure, matplotlib.axes.Axes]
- tensorquantlib.viz.plots.plot_greeks_surface(greek_grids, axis_values, dims=(0, 1), fixed_indices=None, cmap='RdBu_r', figsize=(14, 4))[source]¶
Plot multiple Greeks as side-by-side heatmaps.
- Parameters:
greek_grids (dict[str, np.ndarray]) –
{"Delta": array, "Gamma": array, ...}.axis_values (Sequence[np.ndarray]) – Tick values per axis (same as
plot_pricing_surface).fixed_indices (dict[int, int] | None) – Override slice indices for remaining axes.
cmap (str) – Colour map.
figsize (tuple[float, float]) – Figure size for the whole row.
- Returns:
(fig, axes)tuple.- Return type:
- tensorquantlib.viz.plots.plot_tt_ranks(cores, title='TT-Rank Profile', figsize=(6, 4), color='#2563eb')[source]¶
Bar chart of TT-ranks across bonds.
- tensorquantlib.viz.plots.plot_rank_profile(rank_lists, title='Rank Profiles', figsize=(7, 4))[source]¶
Overlay multiple rank profiles for comparison.
- tensorquantlib.viz.plots.plot_compression_vs_tolerance(epsilons, compression_ratios, errors=None, title='Compression vs Tolerance', figsize=(7, 4))[source]¶
Plot compression ratio and (optionally) error vs SVD tolerance.
- Parameters:
- Returns:
(fig, ax)— second y-axis isax.twinx()if errors given.- Return type:
tuple[matplotlib.figure.Figure, matplotlib.axes.Axes]