stochvolmodels 1.0.7__tar.gz → 1.0.8__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.7 → stochvolmodels-1.0.8}/PKG-INFO +1 -1
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/pyproject.toml +1 -1
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/__init__.py +1 -1
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/data/option_chain.py +1 -1
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/logsv_pricer.py +49 -13
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/LICENSE.txt +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/README.md +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/data/__init__.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/data/test_option_chain.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/__init__.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/core/__init__.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/core/bsm_pricer.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/core/config.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/core/mc_payoffs.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/core/mgf_pricer.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/core/normal_pricer.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/hawkes_jd_pricer.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/heston_pricer.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/logsv/__init__.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/logsv/affine_expansion.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/logsv/vol_moments_ode.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/model_pricer.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/tests/__init__.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/tests/bsm_mgf_pricer.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/tests/qv_pricer.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/utils/__init__.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/utils/funcs.py +0 -0
- {stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/utils/plots.py +0 -0
|
@@ -272,4 +272,4 @@ class OptionChain:
|
|
|
272
272
|
strikes_ttms=List([strikes for _ in ttms]),
|
|
273
273
|
bid_ivs=List([flat_vol*np.ones_like(strikes) for _ in ttms]),
|
|
274
274
|
ask_ivs=List([flat_vol*np.ones_like(strikes) for _ in ttms]),
|
|
275
|
-
optiontypes_ttms=List([np.where(strikes >= forward, 'C', 'P') for forward in forwards]))
|
|
275
|
+
optiontypes_ttms=List([np.where(strikes >= forward, 'C', 'P') for forward in forwards]))
|
|
@@ -29,9 +29,10 @@ from stochvolmodels.data.option_chain import OptionChain
|
|
|
29
29
|
from stochvolmodels.data.test_option_chain import get_btc_test_chain_data
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
class
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
class LogsvModelCalibrationType(Enum):
|
|
33
|
+
PARAMS4 = 1 # v0, theta, beta, volvol; kappa1, kappa2 are set externally
|
|
34
|
+
PARAMS5 = 2 # v0, theta, kappa1, beta, volvol
|
|
35
|
+
PARAMS6 = 3 # v0, theta, kappa1, kappa2, beta, volvol
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
class ConstraintsType(Enum):
|
|
@@ -59,8 +60,8 @@ class LogSvParams(ModelParams):
|
|
|
59
60
|
self.kappa2 = self.kappa1 / self.theta
|
|
60
61
|
|
|
61
62
|
def to_dict(self) -> Dict[str, Any]:
|
|
62
|
-
# return dict(sigma0=self.sigma0, theta=self.theta, kappa1=self.kappa1, kappa2=self.kappa2, beta=self.beta, volvol=self.volvol)
|
|
63
63
|
return asdict(self)
|
|
64
|
+
|
|
64
65
|
@property
|
|
65
66
|
def kappa(self) -> float:
|
|
66
67
|
return self.kappa1+self.kappa2*self.theta
|
|
@@ -220,10 +221,10 @@ class LogSVPricer(ModelPricer):
|
|
|
220
221
|
@timer
|
|
221
222
|
def calibrate_model_params_to_chain(self,
|
|
222
223
|
option_chain: OptionChain,
|
|
223
|
-
params0: LogSvParams
|
|
224
|
+
params0: LogSvParams,
|
|
224
225
|
is_vega_weighted: bool = True,
|
|
225
226
|
is_unit_ttm_vega: bool = False,
|
|
226
|
-
model_calibration_type:
|
|
227
|
+
model_calibration_type: LogsvModelCalibrationType = LogsvModelCalibrationType.PARAMS5,
|
|
227
228
|
constraints_type: ConstraintsType = ConstraintsType.UNCONSTRAINT,
|
|
228
229
|
**kwargs
|
|
229
230
|
) -> LogSvParams:
|
|
@@ -245,7 +246,39 @@ class LogSVPricer(ModelPricer):
|
|
|
245
246
|
else:
|
|
246
247
|
weights = np.ones_like(market_vols)
|
|
247
248
|
|
|
248
|
-
|
|
249
|
+
# implement different calibrato types
|
|
250
|
+
if model_calibration_type == LogsvModelCalibrationType.PARAMS4:
|
|
251
|
+
# fit: v0, theta, beta, volvol; kappa1, kappa2 is given with params0
|
|
252
|
+
if params0 is not None:
|
|
253
|
+
p0 = np.array([params0.sigma0, params0.theta, params0.beta, params0.volvol])
|
|
254
|
+
else:
|
|
255
|
+
p0 = np.array([0.8, 0.8, -0.2, 2.0])
|
|
256
|
+
bounds = ((0.01, 2.0), (0.01, 2.0), (-5.0, 3.0), (0.1, 10.0))
|
|
257
|
+
|
|
258
|
+
def objective(pars: np.ndarray, args: np.ndarray) -> float:
|
|
259
|
+
v0, theta, beta, volvol = pars[0], pars[1], pars[2], pars[3]
|
|
260
|
+
params = LogSvParams(sigma0=v0, theta=theta, kappa1=params0.kappa1,
|
|
261
|
+
kappa2=params0.kappa2, beta=beta, volvol=volvol)
|
|
262
|
+
model_vols = self.compute_model_ivols_for_chain(option_chain=option_chain, params=params,
|
|
263
|
+
vol_scaler=vol_scaler)
|
|
264
|
+
resid = np.nansum(weights * np.square(to_flat_np_array(model_vols) - market_vols))
|
|
265
|
+
return resid
|
|
266
|
+
|
|
267
|
+
def martingale_measure(pars: np.ndarray) -> float:
|
|
268
|
+
v0, theta, beta, volvol = pars[0], pars[1], pars[2], pars[3]
|
|
269
|
+
return params0.kappa2 - beta
|
|
270
|
+
|
|
271
|
+
def inverse_measure(pars: np.ndarray) -> float:
|
|
272
|
+
v0, theta, beta, volvol = pars[0], pars[1], pars[2], pars[3]
|
|
273
|
+
return params0.kappa2 - 2.0 * beta
|
|
274
|
+
|
|
275
|
+
def vol_4thmoment_finite(pars: np.ndarray) -> float:
|
|
276
|
+
v0, theta, beta, volvol = pars[0], pars[1], pars[2], pars[3]
|
|
277
|
+
vartheta2 = beta * beta + volvol * volvol
|
|
278
|
+
kappa = params0.kappa1 + params0.kappa2 * theta
|
|
279
|
+
return kappa - 1.5 * vartheta2
|
|
280
|
+
|
|
281
|
+
elif model_calibration_type == LogsvModelCalibrationType.PARAMS5:
|
|
249
282
|
# fit: v0, theta, kappa1, beta, volvol; kappa2 is mapped as kappa1 / theta
|
|
250
283
|
if params0 is not None:
|
|
251
284
|
p0 = np.array([params0.sigma0, params0.theta, params0.kappa1, params0.beta, params0.volvol])
|
|
@@ -275,11 +308,6 @@ class LogSVPricer(ModelPricer):
|
|
|
275
308
|
kappa = kappa1 + kappa2 * theta
|
|
276
309
|
return kappa - 1.5*vartheta2
|
|
277
310
|
|
|
278
|
-
def kurtosis_finite(pars: np.ndarray) -> float:
|
|
279
|
-
v0, theta, kappa1, beta, volvol = pars[0], pars[1], pars[2], pars[3], pars[4]
|
|
280
|
-
vartheta2 = beta*beta + volvol*volvol
|
|
281
|
-
return kappa1 - 1.5*vartheta2
|
|
282
|
-
|
|
283
311
|
else:
|
|
284
312
|
raise NotImplementedError(f"{model_calibration_type}")
|
|
285
313
|
|
|
@@ -320,7 +348,15 @@ class LogSVPricer(ModelPricer):
|
|
|
320
348
|
|
|
321
349
|
popt = res.x
|
|
322
350
|
|
|
323
|
-
if model_calibration_type ==
|
|
351
|
+
if model_calibration_type == LogsvModelCalibrationType.PARAMS4:
|
|
352
|
+
fit_params = LogSvParams(sigma0=popt[0],
|
|
353
|
+
theta=popt[1],
|
|
354
|
+
kappa1=params0.kappa1,
|
|
355
|
+
kappa2=params0.kappa2,
|
|
356
|
+
beta=popt[2],
|
|
357
|
+
volvol=popt[3])
|
|
358
|
+
|
|
359
|
+
elif model_calibration_type == LogsvModelCalibrationType.PARAMS5:
|
|
324
360
|
fit_params = LogSvParams(sigma0=popt[0],
|
|
325
361
|
theta=popt[1],
|
|
326
362
|
kappa1=popt[2],
|
|
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
|
|
File without changes
|
|
File without changes
|
{stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/stochvolmodels/pricers/logsv/affine_expansion.py
RENAMED
|
File without changes
|
{stochvolmodels-1.0.7 → stochvolmodels-1.0.8}/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
|