Skip to content

Commit

Permalink
remove dependence on qis from stochvolmodels
Browse files Browse the repository at this point in the history
  • Loading branch information
ArturSepp committed Jan 14, 2025
1 parent 215c25a commit 498e66f
Show file tree
Hide file tree
Showing 28 changed files with 143 additions and 112 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ Close using
git clone https://github.com/ArturSepp/StochVolModels.git
```

Core dependencies:
python = ">=3.8",
numba = ">=0.56.4",
numpy = ">=1.22.4",
scipy = ">=1.10",
pandas = ">=2.2.0",
matplotlib = ">=3.2.2",
seaborn = ">=0.12.2"

Optional dependencies:
qis ">=2.1.38" (for running code in my_papers and volatility_book)


# Table of contents
1. [Model Interface](#introduction)
1. [Log-normal stochastic volatility model](#logsv)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,14 @@
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import qis
from qis import TimePeriod
from typing import Dict, Tuple, Optional, Literal
from numba.typed import List
from enum import Enum

import qis as qis
# chain
from option_chain_analytics import OptionsDataDFs, create_chain_from_from_options_dfs
from option_chain_analytics.option_chain import SliceColumn, SlicesChain

# analytics
from stochvolmodels.data.option_chain import OptionChain

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# analytics
from stochvolmodels import OptionChain, LogSvParams, LogSVPricer, VariableType, ExpansionOrder
from stochvolmodels.pricers.logsv.vol_moments_ode import compute_analytic_qvar
from stochvolmodels.data.fetch_option_chain import generate_vol_chain_np
from my_papers.fetch_option_chain import generate_vol_chain_np
import stochvolmodels.data.test_option_chain as chains
from stochvolmodels.utils.funcs import set_seed, compute_histogram_data
import stochvolmodels.utils.plots as plot
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@
from enum import Enum

# analytics
from stochvolmodels.data.fetch_option_chain import (generate_vol_chain_np,
load_option_chain,
sample_option_chain_at_times,
load_price_data)
from my_papers.fetch_option_chain import (generate_vol_chain_np,
sample_option_chain_at_times)
from stochvolmodels import (OptionChain, LogSvParams, LogSVPricer, ConstraintsType, LogsvModelCalibrationType)

# chain data
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from option_chain_analytics import OptionsDataDFs, create_chain_from_from_options_dfs
from option_chain_analytics.ts_loaders import ts_data_loader_wrapper

from stochvolmodels.pricers.gmm_pricer import plot_gmm_pdfs
from my_papers.risk_premia.plot_gmm import plot_gmm_pdfs

FIGSIZE = (16, 4.5)

Expand Down
60 changes: 60 additions & 0 deletions my_papers/risk_premia_gmm/plot_gmm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""
illustrations of gmm vols
"""
import numpy as np
import pandas as pd
import qis as qis
import seaborn as sns
import matplotlib.pyplot as plt
from typing import List
from stochvolmodels import GmmParams, OptionChain, GmmPricer


def plot_gmm_pdfs(params: GmmParams,
option_chain0: OptionChain,
nstdev: float = 10.0,
titles: List[str] = None,
axs: List[plt.Subplot] = None
) -> plt.Figure:
"""
plot gmm pdf and model fit
"""
stdev = nstdev * params.get_get_avg_vol() * np.sqrt(params.ttm)
x = np.linspace(-stdev, stdev, 3000)
state_pdfs, agg_pdf = params.compute_state_pdfs(x=x)

columns = []
for idx in range(len(params.gmm_weights)):
columns.append(
f"state-{idx + 1}: mean={params.gmm_mus[idx]:0.2f}, vol={params.gmm_vols[idx]:0.2f}, weight={params.gmm_weights[idx]:0.2f}")

state_pdfs = pd.DataFrame(state_pdfs, index=x, columns=columns)
agg_pdf = pd.Series(agg_pdf, index=x, name='Aggregate PDF')
df = pd.concat([agg_pdf, state_pdfs], axis=1)

kwargs = dict(fontsize=14, framealpha=0.80)

if axs is None:
with sns.axes_style("darkgrid"):
fig, axs = plt.subplots(1, 2, figsize=(16, 4.5))
else:
fig = None

qis.plot_line(df=df,
linestyles=['--'] + ['-'] * len(params.gmm_weights),
y_limits=(0.0, None),
xvar_format='{:,.2f}',
xlabel='log-price',
first_color_fixed=True,
ax=axs[0],
**kwargs)
axs[0].get_lines()[0].set_linewidth(4.0)
axs[0].get_legend().get_lines()[0].set_linewidth(4.0)
qis.set_title(ax=axs[0], title='(A) State PDF and Aggregate Risk-Neutral PDF', **kwargs)

gmm_pricer = GmmPricer()
gmm_pricer.plot_model_ivols_vs_bid_ask(option_chain=option_chain0, params=params,
is_log_strike_xaxis=True,
axs=[axs[1]],
**kwargs)
return fig
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
import qis as qis
from stochvolmodels import (get_btc_test_chain_data,
get_spy_test_chain_data,
OptionChain, GmmPricer,
plot_gmm_pdfs)
OptionChain, GmmPricer)
from my_papers.risk_premia_gmm.plot_gmm import plot_gmm_pdfs

# get test option chain data
# option_chain = get_btc_test_chain_data()
Expand Down
2 changes: 1 addition & 1 deletion my_papers/volatility_models/autocorr_fit.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import qis
import qis as qis
from typing import Tuple
from scipy.optimize import minimize
from enum import Enum
Expand Down
2 changes: 1 addition & 1 deletion my_papers/volatility_models/ss_distribution_fit.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from scipy.stats import norm
from typing import Optional
from enum import Enum
import qis
import qis as qis

from my_papers.volatility_models.load_data import fetch_ohlc_vol
from stochvolmodels import LogSvParams, HestonParams
Expand Down
2 changes: 1 addition & 1 deletion my_papers/volatility_models/vol_beta.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import matplotlib.pyplot as plt
import seaborn as sns
from enum import Enum
import qis
import qis as qis

from my_papers.volatility_models.load_data import fetch_ohlc_vol

Expand Down
5 changes: 1 addition & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "stochvolmodels"
version = "1.0.24"
version = "1.0.26"
description = "Implementation of stochastic volatility models for option pricing"
license = "LICENSE.txt"
authors = ["Artur Sepp <[email protected]>"]
Expand Down Expand Up @@ -37,13 +37,10 @@ python = ">=3.8"
numba = ">=0.55"
numpy = ">=1.22.4"
scipy = ">=1.3"
statsmodels = ">=0.13.0"
pandas = ">=0.19"
matplotlib = ">=3.5.2"
seaborn = ">=0.11.2"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"


Binary file modified requirements.txt
Binary file not shown.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def read_file(file):

setup(
name='stochvolmodels',
version='1.0.24',
version='1.0.26',
author='Artur Sepp, Parviz Rakhmonov',
author_email='[email protected], [email protected]',
url='https://github.com/ArturSepp/StochVolModels',
Expand Down
6 changes: 3 additions & 3 deletions stochvolmodels/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
to_flat_np_array,
update_kwargs,
ncdf,
npdf
npdf,
find_nearest
)

from stochvolmodels.pricers.analytic.bsm import (
Expand Down Expand Up @@ -111,8 +112,7 @@

from stochvolmodels.pricers.gmm_pricer import (
GmmParams,
GmmPricer,
plot_gmm_pdfs
GmmPricer
)

from stochvolmodels.pricers.tdist_pricer import (
Expand Down
7 changes: 3 additions & 4 deletions stochvolmodels/data/option_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@
from __future__ import annotations

import numpy as np
import pandas as pd
from dataclasses import dataclass
from typing import Tuple, Optional

import pandas as pd
from numba.typed import List

import stochvolmodels.pricers.analytic.bsm as bsm
from stochvolmodels.utils.var_swap_pricer import compute_var_swap_strike
from stochvolmodels.pricers.factor_hjm.rate_core import get_default_swap_term_structure, swap_rate
import stochvolmodels.pricers.analytic.bachelier as bachel
from stochvolmodels.utils.var_swap_pricer import compute_var_swap_strike
from stochvolmodels.pricers.factor_hjm.rate_core import get_default_swap_term_structure, swap_rate


@dataclass
Expand Down
2 changes: 0 additions & 2 deletions stochvolmodels/examples/run_heston_sv_pricer.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@

import numpy as np
import matplotlib.pyplot as plt
from enum import Enum

import stochvolmodels as sv
from stochvolmodels import HestonPricer, HestonParams, OptionChain, BTC_HESTON_PARAMS

Expand Down
5 changes: 2 additions & 3 deletions stochvolmodels/examples/run_pricing_options_on_qvar.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"""
import numpy as np
import matplotlib.pyplot as plt
import qis as qis
import stochvolmodels.data.test_option_chain as chains
from numba.typed import List
from stochvolmodels import (LogSVPricer, LogSvParams, compute_analytic_qvar, OptionChain,
Expand Down Expand Up @@ -37,15 +36,15 @@
params=LOGSV_BTC_PARAMS,
variable_type=VariableType.Q_VAR,
nb_path=nb_path)
qis.set_suptitle(fig1, title='Implied variance skew by Log-Normal SV model')
fig1.suptitle('Implied variance skew by Log-Normal SV model')

# run Heston prices
heston_pricer = HestonPricer()
fig2 = heston_pricer.plot_model_ivols_vs_mc(option_chain=option_chain,
params=BTC_HESTON_PARAMS,
variable_type=VariableType.Q_VAR,
nb_path=nb_path)
qis.set_suptitle(fig2, title='Implied variance skew by Heston SV model')
fig2.suptitle('Implied variance skew by Heston SV model')


plt.show()
56 changes: 1 addition & 55 deletions stochvolmodels/pricers/gmm_pricer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,12 @@
import numpy as np
import matplotlib.pyplot as plt
from dataclasses import dataclass

import pandas as pd
import qis as qis
import seaborn as sns
from scipy.optimize import minimize
from numba import njit
from numba.typed import List
from typing import Tuple
from enum import Enum

# project
import stochvolmodels.pricers.analytic.bsm as bsm
from stochvolmodels.utils.funcs import to_flat_np_array, timer, npdf
from stochvolmodels.pricers.model_pricer import ModelParams, ModelPricer
Expand Down Expand Up @@ -263,56 +259,6 @@ def gmm_vanilla_chain_pricer(gmm_weights: np.ndarray,
return model_prices_ttms


def plot_gmm_pdfs(params: GmmParams,
option_chain0: OptionChain,
nstdev: float = 10.0,
titles: List[str] = None,
axs: List[plt.Subplot] = None
) -> plt.Figure:
"""
plot gmm pdf and model fit
"""
stdev = nstdev * params.get_get_avg_vol() * np.sqrt(params.ttm)
x = np.linspace(-stdev, stdev, 3000)
state_pdfs, agg_pdf = params.compute_state_pdfs(x=x)

columns = []
for idx in range(len(params.gmm_weights)):
columns.append(
f"state-{idx + 1}: mean={params.gmm_mus[idx]:0.2f}, vol={params.gmm_vols[idx]:0.2f}, weight={params.gmm_weights[idx]:0.2f}")

state_pdfs = pd.DataFrame(state_pdfs, index=x, columns=columns)
agg_pdf = pd.Series(agg_pdf, index=x, name='Aggregate PDF')
df = pd.concat([agg_pdf, state_pdfs], axis=1)

kwargs = dict(fontsize=14, framealpha=0.80)

if axs is None:
with sns.axes_style("darkgrid"):
fig, axs = plt.subplots(1, 2, figsize=(16, 4.5))
else:
fig = None

qis.plot_line(df=df,
linestyles=['--'] + ['-'] * len(params.gmm_weights),
y_limits=(0.0, None),
xvar_format='{:,.2f}',
xlabel='log-price',
first_color_fixed=True,
ax=axs[0],
**kwargs)
axs[0].get_lines()[0].set_linewidth(4.0)
axs[0].get_legend().get_lines()[0].set_linewidth(4.0)
qis.set_title(ax=axs[0], title='(A) State PDF and Aggregate Risk-Neutral PDF', **kwargs)

gmm_pricer = GmmPricer()
gmm_pricer.plot_model_ivols_vs_bid_ask(option_chain=option_chain0, params=params,
is_log_strike_xaxis=True,
axs=[axs[1]],
**kwargs)
return fig


class UnitTests(Enum):
CALIBRATOR = 1

Expand Down
1 change: 1 addition & 0 deletions stochvolmodels/pricers/heston_pricer.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ class UnitTests(Enum):
MC_COMPARISION = 4
MC_COMPARISION_QVAR = 5


def run_unit_test(unit_test: UnitTests):

import stochvolmodels.data.test_option_chain as chains
Expand Down
11 changes: 6 additions & 5 deletions stochvolmodels/pricers/logsv/logsv_params.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from dataclasses import dataclass, asdict
from typing import Optional, Dict, Any

"""
implementation of log sv params
"""
import numpy as np
import pandas as pd
from numpy import linalg as la
from qis import find_nearest
from dataclasses import dataclass, asdict
from typing import Optional, Dict, Any

from stochvolmodels import VariableType
from stochvolmodels import VariableType, find_nearest
from stochvolmodels.pricers.model_pricer import ModelParams


Expand Down
2 changes: 1 addition & 1 deletion stochvolmodels/tests/bsm_mgf_pricer.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from typing import Tuple
from enum import Enum

from stochvolmodels.pricers.analytic import mgf_pricer as mgfp
import stochvolmodels.utils.mgf_pricer as mgfp
from stochvolmodels.pricers.analytic.bsm import infer_bsm_ivols_from_model_chain_prices
from stochvolmodels.utils.config import VariableType

Expand Down
Loading

0 comments on commit 498e66f

Please sign in to comment.