Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"args": [
"-x",
"-vvv",
"quantflow_tests/test_options_pricer.py",
"quantflow_tests/test_divfm.py",
]
},
]
Expand Down
2 changes: 1 addition & 1 deletion app/gaussian_sampling.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import marimo
import marimo

__generated_with = "0.19.7"
app = marimo.App(width="medium")
Expand Down
119 changes: 119 additions & 0 deletions app/heston_vol_surface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import marimo

__generated_with = "0.22.0"
app = marimo.App(width="medium")


@app.cell
def _():
import marimo as mo
from app.utils import nav_menu
nav_menu()
return (mo,)


@app.cell(hide_code=True)
def _(mo):
mo.md(r"""
## Jump Diffusion
""")
return


@app.cell
def _(mo):
from quantflow.sp.jump_diffusion import JumpDiffusion
from quantflow.utils.distributions import DoubleExponential

jump_fraction = mo.ui.slider(start=0.1, stop=0.9, step=0.05, value=0.5, debounce=True, label="Jump Fraction")
jump_intensity = mo.ui.slider(start=10, stop=100, step=5, debounce=True, label="Jump Intensity")
jump_asymmetry = mo.ui.slider(start=-2, stop=2, step=0.1, value=0, debounce=True, label="Jump Asymmetry")
jump_controls = mo.vstack([
jump_fraction, jump_intensity, jump_asymmetry
])
jump_controls
return (
DoubleExponential,
JumpDiffusion,
jump_asymmetry,
jump_fraction,
jump_intensity,
)


@app.cell
def _(
DoubleExponential,
JumpDiffusion,
OptionPricer,
jump_asymmetry,
jump_fraction,
jump_intensity,
):
jd = JumpDiffusion.create(
DoubleExponential,
jump_fraction=jump_fraction.value,
jump_intensity=jump_intensity.value,
jump_asymmetry=jump_asymmetry.value,
)
OptionPricer(model=jd).maturity(0.01).plot()
return (jd,)


@app.cell
def _(jd):
jd.model_dump()
return


@app.cell
def _():
return


@app.cell(hide_code=True)
def _(mo):
mo.md(r"""
## Heston Volatility Surface
""")
return


@app.cell
def _(mo):
from quantflow.options.pricer import OptionPricer
from quantflow.sp.heston import HestonJ

sigma = mo.ui.slider(start=0.1, stop=2, step=0.1, debounce=True, label="vol of vol")
sigma
return HestonJ, OptionPricer, sigma


@app.cell
def _(DoubleExponential, HestonJ, jump_asymmetry, jump_fraction, sigma):
hj = HestonJ.create(
DoubleExponential,
vol=0.5,
sigma=sigma.value,
kappa=1.0,
rho=0.0,
jump_fraction=jump_fraction.value,
jump_asymmetry=jump_asymmetry.value,
)
return (hj,)


@app.cell
def _(OptionPricer, hj):
hjp = OptionPricer(model=hj)
hjp.maturity(0.5).plot()
return


@app.cell
def _():
return


if __name__ == "__main__":
app.run()
30 changes: 30 additions & 0 deletions docs/api/options/divfm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Deep IV Factor Model

The DIVFM module implements the Deep Implied Volatility Factor Model from
Gauthier, Godin & Legros (2025). The IV surface on a given day is modelled as
a linear combination of $p$ fixed latent functions learned by a neural network:

$$\sigma_t(M, \tau; \theta) = \mathbf{f}(M, \tau, X; \theta)\,\boldsymbol{\beta}_t = \sum_{i=1}^{p} \beta_{t,i}\,f_i(M, \tau, X; \theta)$$

where $M = \frac{1}{\sqrt{\tau}}\log\!\left(\frac{K}{F_{t,\tau}}\right)$ is the
time-scaled moneyness, $\mathbf{f}$ is a feedforward neural network with fixed
weights $\theta$ shared across all days, and $\boldsymbol{\beta}_t$ are daily
coefficients fitted in closed form via OLS.

## Inference (no torch required)

::: quantflow.options.divfm.DIVFMPricer

::: quantflow.options.divfm.DIVFMWeights

::: quantflow.options.divfm.weights.SubnetWeights

::: quantflow.options.divfm.weights.LayerWeights

## Training (requires `quantflow[ml]`)

::: quantflow.options.divfm.network.DIVFMNetwork

::: quantflow.options.divfm.trainer.DIVFMTrainer

::: quantflow.options.divfm.trainer.DayData
1 change: 1 addition & 0 deletions docs/api/options/pricer.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
The option pricer module provides classes for pricing options using
different stochastic volatility models.

::: quantflow.options.pricer.OptionPricerBase

::: quantflow.options.pricer.OptionPricer

Expand Down
8 changes: 8 additions & 0 deletions docs/bibliography.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,11 @@ Peter Molnar
Master's thesis, University of Economics in Prague, 2020

---

### Gauthier

Gauthier Godin & Legros

[Deep Implied Volatility Factor Models for Stock Options](https://drive.google.com/file/d/1Rjypn1IqnhpiZz08s0hxl5ISQDC8KeWk/view?usp=sharing)

2025
18 changes: 12 additions & 6 deletions docs/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,26 @@ Moneyness, or log strike/forward ratio, is used in the context of option pricing

where $K$ is the strike and $F$ is the Forward price. A positive value implies strikes above the forward, which means put options are in the money (ITM) and call options are out of the money (OTM).

## Moneyness Time Scaled

The time to maturity scaled moneyness, is used in the context of option pricing in order to compare options with different maturities. It is defined as

\begin{equation}
\frac{1}{\sqrt{T}}\ln{\frac{K}{F}}
\end{equation}

where $K$ is the strike, $F$ is the Forward price, and $T$ is the time to maturity. It is used to compare options with different maturities by scaling the moneyness by the square root of time to maturity. This is because the price of the underlying asset is subject to random fluctuations, if these fluctuations follow a Brownian motion than the standard deviation of the price movement will increase with the square root of time.


## Moneyness Vol Adjusted

The vol-adjusted moneyness is used in the context of option pricing in order to compare options with different maturities. It is defined as
The vol-adjusted moneyness is used in the context of option pricing in order to compare options with different maturities and different levels of volatility. It is defined as

\begin{equation}
\frac{1}{\sigma\sqrt{T}}\ln\frac{K}{F}
\end{equation}

where $K$ is the strike and $F$ is the Forward price and $T$ is the time to maturity and $\sigma$ is the implied Black volatility.

The key reason for dividing by the square root of time-to-maturity is related to how volatility and price movement behave over time.
The price of the underlying asset is subject to random fluctuations, if these fluctuations follow a Brownian motion than the
standard deviation of the price movement will increase with the square root of time.
where $K$ is the strike, $F$ is the Forward price, $T$ is the time to maturity and $\sigma$ is the implied Black volatility.

## Probability Density Function (PDF)

Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ nav:
- api/options/index.md
- Black-Scholes: api/options/black.md
- Calibration: api/options/calibration.md
- Deep IV Factor Model: api/options/divfm.md
- Pricer: api/options/pricer.md
- Volatility Surface: api/options/vol_surface.md
- Stochastic Processes:
Expand Down
Loading
Loading