stochvolmodels 1.0.15__tar.gz → 1.0.17__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/PKG-INFO +1 -1
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/pyproject.toml +1 -1
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/__init__.py +3 -3
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/analytic/bsm.py +3 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/analytic/tdist.py +2 -1
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/gmm_pricer.py +57 -3
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/utils/funcs.py +3 -9
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/LICENSE.txt +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/README.md +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/data/__init__.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/data/fetch_option_chain.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/data/option_chain.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/data/test_option_chain.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/__init__.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/analytic/__init__.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/analytic/bachelier.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/hawkes_jd_pricer.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/heston_pricer.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/logsv/__init__.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/logsv/affine_expansion.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/logsv/vol_moments_ode.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/logsv_pricer.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/model_pricer.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/tdist_pricer.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/tests/__init__.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/tests/bsm_mgf_pricer.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/tests/qv_pricer.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/utils/__init__.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/utils/config.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/utils/mc_payoffs.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/utils/mgf_pricer.py +0 -0
- {stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/utils/plots.py +0 -0
|
@@ -22,8 +22,7 @@ from stochvolmodels.utils.funcs import (
|
|
|
22
22
|
to_flat_np_array,
|
|
23
23
|
update_kwargs,
|
|
24
24
|
ncdf,
|
|
25
|
-
npdf
|
|
26
|
-
npdf1
|
|
25
|
+
npdf
|
|
27
26
|
)
|
|
28
27
|
|
|
29
28
|
from stochvolmodels.pricers.analytic.bsm import (
|
|
@@ -112,7 +111,8 @@ from stochvolmodels.pricers.logsv_pricer import (
|
|
|
112
111
|
|
|
113
112
|
from stochvolmodels.pricers.gmm_pricer import (
|
|
114
113
|
GmmParams,
|
|
115
|
-
GmmPricer
|
|
114
|
+
GmmPricer,
|
|
115
|
+
plot_gmm_pdfs
|
|
116
116
|
)
|
|
117
117
|
|
|
118
118
|
from stochvolmodels.pricers.tdist_pricer import (
|
|
@@ -249,6 +249,8 @@ def compute_bsm_strike_from_delta(ttm: float,
|
|
|
249
249
|
Vega
|
|
250
250
|
****************************
|
|
251
251
|
"""
|
|
252
|
+
|
|
253
|
+
|
|
252
254
|
@njit
|
|
253
255
|
def compute_bsm_vanilla_vega(ttm: float,
|
|
254
256
|
forward: float,
|
|
@@ -308,6 +310,7 @@ Gamma
|
|
|
308
310
|
****************************
|
|
309
311
|
"""
|
|
310
312
|
|
|
313
|
+
|
|
311
314
|
@njit
|
|
312
315
|
def compute_bsm_vanilla_gamma(ttm: float,
|
|
313
316
|
forward: float,
|
|
@@ -33,7 +33,8 @@ def cdf_tdist(x: Union[np.ndarray, float], mu: float, vol: float, nu: float, ttm
|
|
|
33
33
|
return cdf
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
def cum_mean_tdist(x: Union[np.ndarray, float], mu: float = 0, vol: float = 0.2, nu: float = 3.0, ttm: float = 0.25
|
|
36
|
+
def cum_mean_tdist(x: Union[np.ndarray, float], mu: float = 0, vol: float = 0.2, nu: float = 3.0, ttm: float = 0.25
|
|
37
|
+
) -> Union[float, np.ndarray]:
|
|
37
38
|
"""
|
|
38
39
|
cumulative expected value
|
|
39
40
|
h = int^{x}_{-\infty} u f(u)du
|
|
@@ -4,14 +4,18 @@ implementation of gaussian mixture pricer and calibration
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
import matplotlib.pyplot as plt
|
|
6
6
|
from dataclasses import dataclass
|
|
7
|
+
|
|
8
|
+
import pandas as pd
|
|
9
|
+
import qis as qis
|
|
10
|
+
import seaborn as sns
|
|
7
11
|
from scipy.optimize import minimize
|
|
8
12
|
from numba import njit
|
|
9
13
|
from numba.typed import List
|
|
10
14
|
from typing import Tuple
|
|
11
15
|
from enum import Enum
|
|
12
16
|
|
|
13
|
-
from stochvolmodels.utils.funcs import to_flat_np_array, timer, npdf1
|
|
14
17
|
import stochvolmodels.pricers.analytic.bsm as bsm
|
|
18
|
+
from stochvolmodels.utils.funcs import to_flat_np_array, timer, npdf
|
|
15
19
|
from stochvolmodels.pricers.model_pricer import ModelParams, ModelPricer
|
|
16
20
|
from stochvolmodels.utils.config import VariableType
|
|
17
21
|
from stochvolmodels.data.option_chain import OptionChain
|
|
@@ -37,7 +41,7 @@ class GmmParams(ModelParams):
|
|
|
37
41
|
state_pdfs = np.zeros((len(x), len(self.gmm_weights)))
|
|
38
42
|
agg_pdf = np.zeros_like(x)
|
|
39
43
|
for idx, (gmm_weight, mu, vol) in enumerate(zip(self.gmm_weights, self.gmm_mus, self.gmm_vols)):
|
|
40
|
-
state_pdf =
|
|
44
|
+
state_pdf = npdf(x, mu=mu*self.ttm, vol=vol*np.sqrt(self.ttm))
|
|
41
45
|
state_pdfs[:, idx] = state_pdf
|
|
42
46
|
agg_pdf += gmm_weight*state_pdf
|
|
43
47
|
return state_pdfs, agg_pdf
|
|
@@ -45,7 +49,7 @@ class GmmParams(ModelParams):
|
|
|
45
49
|
def compute_pdf(self, x: np.ndarray):
|
|
46
50
|
pdfs = np.zeros_like(x)
|
|
47
51
|
for gmm_weight, mu, vol in zip(self.gmm_weights, self.gmm_mus, self.gmm_vols):
|
|
48
|
-
pdfs = pdfs + gmm_weight*
|
|
52
|
+
pdfs = pdfs + gmm_weight*npdf(x, mu=mu*self.ttm, vol=vol*np.sqrt(self.ttm))
|
|
49
53
|
return pdfs
|
|
50
54
|
|
|
51
55
|
|
|
@@ -259,6 +263,56 @@ def gmm_vanilla_chain_pricer(gmm_weights: np.ndarray,
|
|
|
259
263
|
return model_prices_ttms
|
|
260
264
|
|
|
261
265
|
|
|
266
|
+
def plot_gmm_pdfs(params: GmmParams,
|
|
267
|
+
option_chain0: OptionChain,
|
|
268
|
+
nstdev: float = 10.0,
|
|
269
|
+
titles: List[str] = None,
|
|
270
|
+
axs: List[plt.Subplot] = None
|
|
271
|
+
) -> plt.Figure:
|
|
272
|
+
"""
|
|
273
|
+
plot gmm pdf and model fit
|
|
274
|
+
"""
|
|
275
|
+
stdev = nstdev * params.get_get_avg_vol() * np.sqrt(params.ttm)
|
|
276
|
+
x = np.linspace(-stdev, stdev, 3000)
|
|
277
|
+
state_pdfs, agg_pdf = params.compute_state_pdfs(x=x)
|
|
278
|
+
|
|
279
|
+
columns = []
|
|
280
|
+
for idx in range(len(params.gmm_weights)):
|
|
281
|
+
columns.append(
|
|
282
|
+
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}")
|
|
283
|
+
|
|
284
|
+
state_pdfs = pd.DataFrame(state_pdfs, index=x, columns=columns)
|
|
285
|
+
agg_pdf = pd.Series(agg_pdf, index=x, name='Aggregate PDF')
|
|
286
|
+
df = pd.concat([agg_pdf, state_pdfs], axis=1)
|
|
287
|
+
|
|
288
|
+
kwargs = dict(fontsize=14, framealpha=0.80)
|
|
289
|
+
|
|
290
|
+
if axs is None:
|
|
291
|
+
with sns.axes_style("darkgrid"):
|
|
292
|
+
fig, axs = plt.subplots(1, 2, figsize=(16, 4.5))
|
|
293
|
+
else:
|
|
294
|
+
fig = None
|
|
295
|
+
|
|
296
|
+
qis.plot_line(df=df,
|
|
297
|
+
linestyles=['--'] + ['-'] * len(params.gmm_weights),
|
|
298
|
+
y_limits=(0.0, None),
|
|
299
|
+
xvar_format='{:,.2f}',
|
|
300
|
+
xlabel='log-price',
|
|
301
|
+
first_color_fixed=True,
|
|
302
|
+
ax=axs[0],
|
|
303
|
+
**kwargs)
|
|
304
|
+
axs[0].get_lines()[0].set_linewidth(4.0)
|
|
305
|
+
axs[0].get_legend().get_lines()[0].set_linewidth(4.0)
|
|
306
|
+
qis.set_title(ax=axs[0], title='(A) State PDF and Aggregate Risk-Neutral PDF', **kwargs)
|
|
307
|
+
|
|
308
|
+
gmm_pricer = GmmPricer()
|
|
309
|
+
gmm_pricer.plot_model_ivols_vs_bid_ask(option_chain=option_chain0, params=params,
|
|
310
|
+
is_log_strike_xaxis=True,
|
|
311
|
+
axs=[axs[1]],
|
|
312
|
+
**kwargs)
|
|
313
|
+
return fig
|
|
314
|
+
|
|
315
|
+
|
|
262
316
|
class UnitTests(Enum):
|
|
263
317
|
CALIBRATOR = 1
|
|
264
318
|
|
|
@@ -5,7 +5,7 @@ import functools
|
|
|
5
5
|
import time
|
|
6
6
|
import numpy as np
|
|
7
7
|
import pandas as pd
|
|
8
|
-
from numba import njit
|
|
8
|
+
from numba import njit
|
|
9
9
|
from numba.typed import List
|
|
10
10
|
from typing import Tuple, Dict, Any, Optional, Union
|
|
11
11
|
|
|
@@ -92,11 +92,5 @@ def ncdf(x: Union[float, np.ndarray]) -> Union[float, np.ndarray]:
|
|
|
92
92
|
|
|
93
93
|
|
|
94
94
|
@njit(cache=False, fastmath=True)
|
|
95
|
-
def npdf(x: Union[float, np.ndarray]) -> Union[float, np.ndarray]:
|
|
96
|
-
return np.exp(-0.5*np.square(x))/np.sqrt(2.0*np.pi)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
@njit(cache=False, fastmath=True)
|
|
100
|
-
def npdf1(x: Union[float, np.ndarray], mu: float, vol: float) -> Union[float, np.ndarray]:
|
|
101
|
-
vol2 = vol*vol
|
|
102
|
-
return np.exp(-0.5*np.square(x-mu)/vol2)/np.sqrt(2.0*np.pi*vol2)
|
|
95
|
+
def npdf(x: Union[float, np.ndarray], mu: float = 0.0, vol: float = 1.0) -> Union[float, np.ndarray]:
|
|
96
|
+
return np.exp(-0.5*np.square((x-mu)/vol))/(vol*np.sqrt(2.0*np.pi))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/analytic/bachelier.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/logsv/affine_expansion.py
RENAMED
|
File without changes
|
{stochvolmodels-1.0.15 → stochvolmodels-1.0.17}/stochvolmodels/pricers/logsv/vol_moments_ode.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|