Local-Vol
The Local Volatility Model is an extension of the Black-Scholes model, where volatility is not constant but instead is assumed to be a function of the asset's current price and time. Using Dupire's method, this function, known as local volatility, can be calibrated from the implied volatility surface observed in the market. It is used for equity options, FX options, and commodity derivatives.
Model Dynamics
In the Local Vol model the lognormal stock process \(X_t\) is given by,
Where \(\sigma_t\) is a function of \(X_t\) and \(t\).
Dataset
The model specific component in the dataset (LV
) is a dict with the following parameters:
- ASSET: the name of the asset
- VOL: the volatility \(\sigma\)
The volatility can be expressed in a number of ways as described in following examples.
Examples
Constant Vol
This is an example with constant local volatility, in which case it reduces to the Black-Scholes Model.
from finmc.models.localvol import LVMC
lv_params = {"ASSET": "SPX", "VOL": 0.015}
dataset = {
"MC": {"PATHS": 100_000, "TIMESTEP": 1 / 250},
"BASE": "USD",
"ASSETS": {
"USD": ("ZERO_RATES", np.array([[2.0, 0.05]])),
"SPX": ("FORWARD", np.array([[0.0, 5500], [1.0, 5600]])),
},
"LV": lv_params
}
model = LVMC(dataset)
model.advance(1.0)
spots = model.get_value("SPX")
Vol Interpolator
VOL
can be specified using a 2D-array, vs time and strike,
using an interpolator as below
from scipy.interpolate import RegularGridInterpolator
times = [0.01, 0.2, 1.0]
strikes = [-5.0, -0.5, -0.1, 0.0, 0.1, 0.5, 5.0]
vols = np.array([
[2.713, 0.884, 0.442, 0.222, 0.032, 0.032, 0.032],
[2.187, 0.719, 0.372, 0.209, 0.032, 0.032, 0.032],
[1.237, 0.435, 0.264, 0.200, 0.101, 0.032, 0.032]
])
volinterp = RegularGridInterpolator(
(times, strikes), vols, fill_value=None, bounds_error=False
)
lv_params = {"ASSET": "SPX", "VOL": volinterp}
Vol Function
Alternatively, VOL
can be specified as an arbitrary function, where the arg is a tuple of
time (float) and log stock (1D-array)
def volfn(points):
# t is float, x_vec is a np array
(t, x_vec) = points
at = 5.0 * t + .01
atm = 0.04 + 0.01 * np.exp(-at)
skew = -1.5 * (1 - np.exp(-at)) / at
return np.sqrt(np.maximum(0.001, atm + x_vec * skew))
lv_params = {"ASSET": "SPX", "VOL": volfn}