stochvolmodels 1.0.21__tar.gz → 1.0.22__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.
Files changed (68) hide show
  1. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/PKG-INFO +1 -1
  2. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/pyproject.toml +1 -1
  3. stochvolmodels-1.0.21/stochvolmodels/my_papers/forward_var/calibrate_forward_var.py +0 -115
  4. stochvolmodels-1.0.21/stochvolmodels/my_papers/il_hedging/README.md +0 -8
  5. stochvolmodels-1.0.21/stochvolmodels/my_papers/il_hedging/logsv_figures.py +0 -61
  6. stochvolmodels-1.0.21/stochvolmodels/my_papers/il_hedging/run_logsv_for_il_payoff.py +0 -150
  7. stochvolmodels-1.0.21/stochvolmodels/my_papers/inverse_options/README.md +0 -10
  8. stochvolmodels-1.0.21/stochvolmodels/my_papers/inverse_options/compare_net_delta.py +0 -168
  9. stochvolmodels-1.0.21/stochvolmodels/my_papers/logsv_model_wtih_quadratic_drift/README.md +0 -13
  10. stochvolmodels-1.0.21/stochvolmodels/my_papers/logsv_model_wtih_quadratic_drift/article_figures.py +0 -325
  11. stochvolmodels-1.0.21/stochvolmodels/my_papers/logsv_model_wtih_quadratic_drift/calibrations.py +0 -198
  12. stochvolmodels-1.0.21/stochvolmodels/my_papers/logsv_model_wtih_quadratic_drift/compare_admis_reg.py +0 -128
  13. stochvolmodels-1.0.21/stochvolmodels/my_papers/logsv_model_wtih_quadratic_drift/model_fit_to_options_timeseries.py +0 -253
  14. stochvolmodels-1.0.21/stochvolmodels/my_papers/logsv_model_wtih_quadratic_drift/moments_vol_qvar.py +0 -240
  15. stochvolmodels-1.0.21/stochvolmodels/my_papers/logsv_model_wtih_quadratic_drift/ode_sol_in_time.py +0 -308
  16. stochvolmodels-1.0.21/stochvolmodels/my_papers/logsv_model_wtih_quadratic_drift/steady_state_pdf.py +0 -251
  17. stochvolmodels-1.0.21/stochvolmodels/my_papers/logsv_model_wtih_quadratic_drift/vol_drift.py +0 -82
  18. stochvolmodels-1.0.21/stochvolmodels/my_papers/risk_premia/check_kernel.py +0 -20
  19. stochvolmodels-1.0.21/stochvolmodels/my_papers/risk_premia/gmm_slides.py +0 -501
  20. stochvolmodels-1.0.21/stochvolmodels/my_papers/risk_premia/q_kernel.py +0 -53
  21. stochvolmodels-1.0.21/stochvolmodels/my_papers/t_distribution/illustrations.py +0 -197
  22. stochvolmodels-1.0.21/stochvolmodels/my_papers/t_distribution/market_data_fit.py +0 -66
  23. stochvolmodels-1.0.21/stochvolmodels/my_papers/t_distribution/mc_pricer_with_kernel.py +0 -97
  24. stochvolmodels-1.0.21/stochvolmodels/my_papers/volatility_models/README.md +0 -10
  25. stochvolmodels-1.0.21/stochvolmodels/my_papers/volatility_models/article_figures.py +0 -216
  26. stochvolmodels-1.0.21/stochvolmodels/my_papers/volatility_models/autocorr_fit.py +0 -236
  27. stochvolmodels-1.0.21/stochvolmodels/my_papers/volatility_models/load_data.py +0 -64
  28. stochvolmodels-1.0.21/stochvolmodels/my_papers/volatility_models/ss_distribution_fit.py +0 -327
  29. stochvolmodels-1.0.21/stochvolmodels/my_papers/volatility_models/vol_beta.py +0 -60
  30. stochvolmodels-1.0.21/stochvolmodels/utils/__init__.py +0 -0
  31. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/LICENSE.txt +0 -0
  32. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/README.md +0 -0
  33. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/__init__.py +0 -0
  34. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/data/__init__.py +0 -0
  35. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/data/fetch_option_chain.py +0 -0
  36. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/data/option_chain.py +0 -0
  37. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/data/test_option_chain.py +0 -0
  38. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/examples/quick_run_lognormal_sv_pricer.py +0 -0
  39. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/examples/run_gmm_fit.py +0 -0
  40. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/examples/run_heston.py +0 -0
  41. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/examples/run_heston_sv_pricer.py +0 -0
  42. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/examples/run_lognormal_sv_pricer.py +0 -0
  43. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/examples/run_pricing_options_on_qvar.py +0 -0
  44. {stochvolmodels-1.0.21/stochvolmodels/my_papers → stochvolmodels-1.0.22/stochvolmodels/pricers}/__init__.py +0 -0
  45. {stochvolmodels-1.0.21/stochvolmodels/pricers → stochvolmodels-1.0.22/stochvolmodels/pricers/analytic}/__init__.py +0 -0
  46. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/pricers/analytic/bachelier.py +0 -0
  47. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/pricers/analytic/bsm.py +0 -0
  48. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/pricers/analytic/tdist.py +0 -0
  49. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/pricers/gmm_pricer.py +0 -0
  50. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/pricers/hawkes_jd_pricer.py +0 -0
  51. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/pricers/heston_pricer.py +0 -0
  52. {stochvolmodels-1.0.21/stochvolmodels/pricers/analytic → stochvolmodels-1.0.22/stochvolmodels/pricers/logsv}/__init__.py +0 -0
  53. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/pricers/logsv/affine_expansion.py +0 -0
  54. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/pricers/logsv/logsv_params.py +0 -0
  55. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/pricers/logsv/vol_moments_ode.py +0 -0
  56. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/pricers/logsv_pricer.py +0 -0
  57. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/pricers/model_pricer.py +0 -0
  58. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/pricers/tdist_pricer.py +0 -0
  59. {stochvolmodels-1.0.21/stochvolmodels/pricers/logsv → stochvolmodels-1.0.22/stochvolmodels/tests}/__init__.py +0 -0
  60. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/tests/bsm_mgf_pricer.py +0 -0
  61. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/tests/qv_pricer.py +0 -0
  62. {stochvolmodels-1.0.21/stochvolmodels/tests → stochvolmodels-1.0.22/stochvolmodels/utils}/__init__.py +0 -0
  63. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/utils/config.py +0 -0
  64. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/utils/funcs.py +0 -0
  65. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/utils/mc_payoffs.py +0 -0
  66. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/utils/mgf_pricer.py +0 -0
  67. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/utils/plots.py +0 -0
  68. {stochvolmodels-1.0.21 → stochvolmodels-1.0.22}/stochvolmodels/utils/var_swap_pricer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: stochvolmodels
3
- Version: 1.0.21
3
+ Version: 1.0.22
4
4
  Summary: Implementation of stochastic volatility models for option pricing
5
5
  Home-page: https://github.com/ArturSepp/StochVolModels
6
6
  License: LICENSE.txt
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "stochvolmodels"
3
- version = "1.0.21"
3
+ version = "1.0.22"
4
4
  description = "Implementation of stochastic volatility models for option pricing"
5
5
  license = "LICENSE.txt"
6
6
  authors = ["Artur Sepp <artursepp@gmail.com>"]
@@ -1,115 +0,0 @@
1
- # packages
2
- import numpy as np
3
- import pandas as pd
4
- import matplotlib.pyplot as plt
5
- from enum import Enum
6
-
7
- import qis
8
-
9
- # project
10
- import stochvolmodels as sv
11
- from stochvolmodels.pricers.logsv_pricer import LogSVPricer, LogsvModelCalibrationType
12
- from stochvolmodels.pricers.logsv.vol_moments_ode import fit_model_vol_backbone_to_varswaps
13
- from stochvolmodels import LogSvParams
14
- from stochvolmodels.utils.funcs import set_seed
15
-
16
-
17
- class UnitTests(Enum):
18
- VARSWAP_FIT = 1
19
- CALIBRATE_4PARAM_MODEL = 2
20
- CALIBRATE_VARSWAP_PARAM_MODEL = 3
21
- COMPARE_MODEL_VOLS_TO_MC = 4
22
-
23
-
24
- def run_unit_test(unit_test: UnitTests):
25
-
26
- set_seed(24)
27
-
28
- logsv_pricer = LogSVPricer()
29
- option_chain = sv.get_btc_test_chain_data()
30
-
31
- local_path = "C://Users//artur//OneDrive//My Papers//MyPresentations//Crypto Vols Tartu. Zurich. Aug 2022//figures//"
32
-
33
- if unit_test == UnitTests.VARSWAP_FIT:
34
- btc_log_params = LogSvParams(sigma0=0.7118361434192538, theta=0.7118361434192538,
35
- kappa1=2.214702576955766, kappa2=2.18028273418397, beta=0.0,
36
- volvol=0.921487415907961)
37
- btc_log_params = LogSvParams(sigma0=0.88, theta=0.88,
38
- kappa1=2.214702576955766, kappa2=2.18028273418397, beta=0.0,
39
- volvol=0.921487415907961)
40
-
41
- vars_swaps = option_chain.get_slice_varswap_strikes()
42
- vars_swaps1 = pd.Series(np.square(option_chain.get_chain_atm_vols()), index=option_chain.ttms)
43
- vars_swaps = np.maximum(vars_swaps, vars_swaps1)
44
-
45
- vol_backbone = fit_model_vol_backbone_to_varswaps(log_sv_params=btc_log_params,
46
- varswap_strikes=vars_swaps,
47
- verbose=True)
48
- btc_log_params.set_vol_backbone(vol_backbone=vol_backbone)
49
-
50
- logsv_pricer = LogSVPricer()
51
- logsv_pricer.plot_model_ivols_vs_bid_ask(option_chain=option_chain,
52
- params=btc_log_params)
53
-
54
- elif unit_test == UnitTests.CALIBRATE_4PARAM_MODEL:
55
- params0 = LogSvParams(sigma0=0.8, theta=1.0, kappa1=2.21, kappa2=2.18, beta=0.15, volvol=2.0)
56
- fitted_params = LogSvParams(sigma0=0.8626, theta=1.0417, kappa1=2.21, kappa2=2.18, beta=0.13, volvol=1.6286)
57
- btc_calibrated_params = fitted_params
58
- """
59
- btc_calibrated_params = logsv_pricer.calibrate_model_params_to_chain(option_chain=option_chain,
60
- params0=params0,
61
- model_calibration_type=LogsvModelCalibrationType.PARAMS4,
62
- constraints_type=sv.ConstraintsType.INVERSE_MARTINGALE)
63
- """
64
- print(btc_calibrated_params)
65
- fig = logsv_pricer.plot_model_ivols_vs_bid_ask(option_chain=option_chain,
66
- params=btc_calibrated_params)
67
- qis.save_fig(fig=fig, file_name='four_param_model_fit', local_path=local_path)
68
-
69
- elif unit_test == UnitTests.CALIBRATE_VARSWAP_PARAM_MODEL:
70
- params0 = LogSvParams(sigma0=0.85, theta=0.85, kappa1=2.21, kappa2=2.18, beta=0.15, volvol=1.5)
71
- fitted_params = LogSvParams(sigma0=0.85, theta=1.0, kappa1=2.21, kappa2=2.18, beta=0.24, volvol=1.14)
72
- btc_calibrated_params = logsv_pricer.calibrate_model_params_to_chain(
73
- option_chain=option_chain,
74
- params0=params0,
75
- params_min=LogSvParams(sigma0=0.1, theta=0.1, kappa1=0.25, kappa2=0.25, beta=0.0, volvol=1.5),
76
- model_calibration_type=LogsvModelCalibrationType.PARAMS_WITH_VARSWAP_FIT,
77
- constraints_type=sv.ConstraintsType.INVERSE_MARTINGALE)
78
- print(btc_calibrated_params)
79
-
80
- fig = logsv_pricer.plot_model_ivols_vs_bid_ask(option_chain=option_chain,
81
- params=btc_calibrated_params)
82
- qis.save_fig(fig=fig, file_name='backbone_model_fit', local_path=local_path)
83
-
84
- elif unit_test == UnitTests.COMPARE_MODEL_VOLS_TO_MC:
85
- uniform_chain_data = sv.OptionChain.to_uniform_strikes(obj=option_chain, num_strikes=31)
86
- is_varswap = True
87
- if is_varswap:
88
- fitted_params = LogSvParams(sigma0=0.85, theta=.85, kappa1=2.21, kappa2=2.18, beta=0.24, volvol=1.14)
89
- varswap_strikes = option_chain.get_slice_varswap_strikes(floor_with_atm_vols=True)
90
- fitted_params.set_vol_backbone(vol_backbone=fit_model_vol_backbone_to_varswaps(log_sv_params=fitted_params,
91
- varswap_strikes=varswap_strikes))
92
- else:
93
- fitted_params = LogSvParams(sigma0=0.8626, theta=1.0417, kappa1=2.21, kappa2=2.18, beta=0.13, volvol=1.6286)
94
-
95
- logsv_pricer.plot_model_ivols_vs_mc(option_chain=uniform_chain_data,
96
- params=fitted_params,
97
- nb_path=100000)
98
-
99
- logsv_pricer.plot_comp_mma_inverse_options_with_mc(option_chain=uniform_chain_data,
100
- params=fitted_params,
101
- nb_path=100000)
102
-
103
- plt.show()
104
-
105
-
106
- if __name__ == '__main__':
107
-
108
- unit_test = UnitTests.CALIBRATE_VARSWAP_PARAM_MODEL
109
-
110
- is_run_all_tests = False
111
- if is_run_all_tests:
112
- for unit_test in UnitTests:
113
- run_unit_test(unit_test=unit_test)
114
- else:
115
- run_unit_test(unit_test=unit_test)
@@ -1,8 +0,0 @@
1
- This module contains analysis for paper
2
- [Unified Approach for Hedging Impermanent Loss of Liquidity Provision](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4887298)
3
- by Artur Sepp, Alexander Lipton, and Vladimir Lucic
4
-
5
- All figures in the paper are produced by unittests in
6
- https://github.com/ArturSepp/StochVolModels/blob/main/my_papers/il_hedging/run_logsv_for_il_payoff.py
7
-
8
- See the description of data and analysis in the paper.
@@ -1,61 +0,0 @@
1
- """
2
- run few unit test to illustrate implementation of log-normal sv model analytics
3
- """
4
-
5
- import numpy as np
6
- import matplotlib.pyplot as plt
7
- import seaborn as sns
8
- from enum import Enum
9
-
10
- from stochvolmodels import LogSVPricer, LogSvParams, OptionChain
11
-
12
-
13
- def plot_skews():
14
- logsv_pricer = LogSVPricer()
15
- option_chain = OptionChain.get_uniform_chain(ttms=np.array([14.0/365.0]),
16
- ids=np.array(['2w']),
17
- strikes=np.linspace(0.6, 1.4, 21))
18
-
19
- # define parameters for bootstrap
20
- sigma0 = 0.5
21
- params_dict = {'beta=-1': LogSvParams(sigma0=sigma0, theta=sigma0, kappa1=5.0, kappa2=5.0, beta=-1, volvol=1.0),
22
- 'beta=0': LogSvParams(sigma0=sigma0, theta=sigma0, kappa1=5.0, kappa2=5.0, beta=0.0, volvol=1.4),
23
- 'beta=1': LogSvParams(sigma0=sigma0, theta=sigma0, kappa1=5.0, kappa2=5.0, beta=1.0, volvol=1.0)}
24
-
25
- params_dict = {
26
- 'volvol=1.0': LogSvParams(sigma0=sigma0, theta=sigma0, kappa1=2.21, kappa2=2.18, beta=0.0, volvol=1.0),
27
- 'volvol=2.0': LogSvParams(sigma0=sigma0 - 0.005, theta=sigma0 - 0.005, kappa1=2.21, kappa2=2.18, beta=0.0,
28
- volvol=2.0),
29
- 'volvol=3.0': LogSvParams(sigma0=sigma0 - 0.01, theta=sigma0 - 0.01, kappa1=2.21, kappa2=2.18, beta=0.0,
30
- volvol=3.0)}
31
-
32
- # get slice for illustration
33
- option_slice = option_chain.get_slice(id='2w')
34
- logsv_pricer.plot_model_slices_in_params(option_slice=option_slice,
35
- params_dict=params_dict)
36
-
37
-
38
- class UnitTests(Enum):
39
- PLOT_SKEWS = 1
40
-
41
-
42
- def run_unit_test(unit_test: UnitTests):
43
-
44
- if unit_test == UnitTests.PLOT_SKEWS:
45
- with sns.axes_style("darkgrid"):
46
- fig, axs = plt.subplots(3, 1, figsize=(10, 7))
47
- plot_skews()
48
-
49
- plt.show()
50
-
51
-
52
- if __name__ == '__main__':
53
-
54
- unit_test = UnitTests.PLOT_SKEWS
55
-
56
- is_run_all_tests = False
57
- if is_run_all_tests:
58
- for unit_test in UnitTests:
59
- run_unit_test(unit_test=unit_test)
60
- else:
61
- run_unit_test(unit_test=unit_test)
@@ -1,150 +0,0 @@
1
- """
2
- computation of il payoff under log sv
3
- """
4
- import numpy as np
5
- import matplotlib.pyplot as plt
6
- from numba import njit
7
- from enum import Enum
8
-
9
- # stochvolmodels pricers
10
- from stochvolmodels import (get_transform_var_grid,
11
- vanilla_slice_pricer_with_mgf_grid,
12
- digital_slice_pricer_with_mgf_grid,
13
- compute_integration_weights,
14
- ExpansionOrder,
15
- get_expansion_n,
16
- compute_logsv_a_mgf_grid,
17
- LogSvParams)
18
-
19
-
20
- def logsv_il_pricer(params: LogSvParams,
21
- ttm: float,
22
- p1: float, # can price on range of forwards
23
- p0: float,
24
- pa: float,
25
- pb: float,
26
- is_stiff_solver: bool = False,
27
- expansion_order: ExpansionOrder = ExpansionOrder.SECOND,
28
- vol_scaler: float = None,
29
- notional: float = 1000000
30
- ) -> float:
31
- """
32
- price il using bsm mgf
33
- """
34
- # starting values
35
- if vol_scaler is None: # for calibrations we fix one vol_scaler so the grid is not affected by v0
36
- vol_scaler = params.sigma0 * np.sqrt(np.minimum(np.min(ttm), 0.5 / 12.0))
37
-
38
- # for vanilla call and put
39
- phi_grid, psi_grid, theta_grid = get_transform_var_grid(vol_scaler=vol_scaler,
40
- real_phi=-0.4)
41
- a_t0 = np.zeros((phi_grid.shape[0], get_expansion_n(expansion_order)), dtype=np.complex128)
42
-
43
- a_t0, log_mgf_grid = compute_logsv_a_mgf_grid(ttm=ttm,
44
- phi_grid=phi_grid,
45
- psi_grid=psi_grid,
46
- theta_grid=theta_grid,
47
- a_t0=a_t0,
48
- expansion_order=expansion_order,
49
- is_stiff_solver=is_stiff_solver,
50
- **params.to_dict())
51
-
52
- vanilla_option_prices = vanilla_slice_pricer_with_mgf_grid(log_mgf_grid=log_mgf_grid,
53
- phi_grid=phi_grid,
54
- forward=p1,
55
- strikes=np.array([pa, pb]),
56
- optiontypes=np.array(['P', 'C']),
57
- discfactor=1.0)
58
- bsm_put, bsm_call = vanilla_option_prices[0], vanilla_option_prices[1]
59
-
60
- digital_options = digital_slice_pricer_with_mgf_grid(log_mgf_grid=log_mgf_grid,
61
- phi_grid=phi_grid,
62
- forward=p1,
63
- strikes=np.array([pa, pb]),
64
- optiontypes=np.array(['P', 'C']),
65
- discfactor=1.0)
66
- digital_put, digital_call = digital_options[0], digital_options[1]
67
-
68
- square_root = square_root_payoff_pricer_with_mgf_grid(log_mgf_grid=log_mgf_grid,
69
- phi_grid=phi_grid,
70
- forward=p1,
71
- pa=pa,
72
- pb=pb,
73
- discfactor=1.0)
74
-
75
- sp0 = np.sqrt(p0)
76
- spa = np.sqrt(pa)
77
- spb = np.sqrt(pb)
78
-
79
- linear = sp0*(p1/p0+1.0)
80
-
81
- payoff = -2.0*square_root + linear + \
82
- (1.0 / spa) * bsm_put - (1.0 / spb) * bsm_call \
83
- -2.0 * spa * digital_put -2.0 * spb * digital_call
84
-
85
- notional0 = 1.0 / (2.0*sp0-p0/spb-spa)
86
- payoff = - (notional0*notional)*payoff
87
- return payoff
88
-
89
-
90
- logsv_il_pricer_vector = np.vectorize(logsv_il_pricer, doc='Vectorized `logsv_il_pricer`')
91
-
92
-
93
- @njit(cache=False, fastmath=True)
94
- def square_root_payoff_pricer_with_mgf_grid(log_mgf_grid: np.ndarray,
95
- phi_grid: np.ndarray,
96
- forward: float,
97
- pa: float,
98
- pb: float,
99
- discfactor: float = 1.0,
100
- is_simpson: bool = True
101
- ) -> np.ndarray:
102
- """
103
- generic function for pricing digital options on the spot given the mgf grid
104
- mgf in x is function defined on log-price transform phi grids
105
- transform variable is phi_grid = real_phi + i*p
106
- grid can be non-uniform
107
- we can use either positive or negative phi_real but not
108
- """
109
- dp = compute_integration_weights(var_grid=phi_grid, is_simpson=is_simpson)
110
-
111
- x = np.log(forward)
112
- xa = np.log(pa)
113
- xb = np.log(pb)
114
- p_payoff = (np.exp( (phi_grid+0.5)*xb - phi_grid*x) - np.exp((phi_grid+0.5)*xa - phi_grid*x))
115
- p_payoff = (dp / np.pi) * p_payoff / (phi_grid+0.5)
116
- option_price = discfactor * np.nansum(np.real(p_payoff*np.exp(log_mgf_grid)))
117
- return option_price
118
-
119
-
120
- class UnitTests(Enum):
121
- COMPUTE_MODEL_PRICES = 1
122
-
123
-
124
- def run_unit_test(unit_test: UnitTests):
125
-
126
- # define model params
127
- params = LogSvParams(sigma0=0.4861785891939535, theta=0.6176006871606874, kappa1=1.955809653686808, kappa2=1.978367101612294, beta=-0.26916969112829325, volvol=3.265815229306317)
128
-
129
- if unit_test == UnitTests.COMPUTE_MODEL_PRICES:
130
- payoff = logsv_il_pricer(params=params,
131
- ttm=10.0/365.0,
132
- p1=2200.0,
133
- p0=2200.0,
134
- pa=2000.0,
135
- pb=2400.0)
136
- print(payoff)
137
-
138
- plt.show()
139
-
140
-
141
- if __name__ == '__main__':
142
-
143
- unit_test = UnitTests.COMPUTE_MODEL_PRICES
144
-
145
- is_run_all_tests = False
146
- if is_run_all_tests:
147
- for unit_test in UnitTests:
148
- run_unit_test(unit_test=unit_test)
149
- else:
150
- run_unit_test(unit_test=unit_test)
@@ -1,10 +0,0 @@
1
- This module contains analysis for paper
2
- [Valuation and Hedging of Cryptocurrency Inverse Options](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4606748) by Artur Sepp and Vladimir Lucic
3
-
4
- Comparision of net deltas in the paper are generated using
5
- ```python
6
- compare_net_delta.py
7
- ```
8
- https://github.com/ArturSepp/StochVolModels/tree/main/my_papers/inverse_options
9
-
10
- See the description of data and analysis in the paper.
@@ -1,168 +0,0 @@
1
- import numpy as np
2
- import pandas as pd
3
- import matplotlib.pyplot as plt
4
- import seaborn as sns
5
- import qis as qis
6
- from enum import Enum
7
-
8
-
9
- from stochvolmodels import (compute_bsm_vanilla_grid_deltas,
10
- compute_bsm_forward_grid_prices,
11
- compute_bsm_vanilla_price,
12
- compute_bsm_vanilla_delta)
13
-
14
-
15
- def compare_net_deltas(ttm: float,
16
- forward: float,
17
- vol: float,
18
- strike_level: float = 1.0,
19
- optiontype: str = 'C',
20
- ax: plt.Subplot = None,
21
- **kwargs
22
- ):
23
-
24
- spot_drid = np.linspace(0.7*forward, 1.3*forward, 1000)
25
- strike = strike_level * forward
26
-
27
- option_prices = compute_bsm_forward_grid_prices(ttm=ttm, forwards=spot_drid, strike=strike, vol=vol, optiontype=optiontype)
28
- option_deltas = compute_bsm_vanilla_grid_deltas(ttm=ttm, forwards=spot_drid, strike=strike, vol=vol, optiontype=optiontype)
29
- option_net_delta = option_deltas - option_prices / spot_drid
30
- option_deltas = pd.Series(option_deltas, index=spot_drid, name='Black Delta')
31
- option_net_delta = pd.Series(option_net_delta, index=spot_drid, name='Net Delta')
32
- deltas = pd.concat([option_deltas, option_net_delta], axis=1)
33
-
34
- qis.plot_line(df=deltas,
35
- xvar_format='{:,.0f}',
36
- ylabel='BTC price',
37
- ax=ax,
38
- **kwargs)
39
-
40
-
41
- def compare_pnl(ttm: float,
42
- forward: float,
43
- vol: float,
44
- strike_level: float = 1.0,
45
- optiontype: str = 'C',
46
- is_btc_pnl: bool = True,
47
- ax: plt.Subplot = None,
48
- **kwargs
49
- ):
50
-
51
- spot_drid = np.linspace(0.7*forward, 1.3*forward, 10000)
52
- returns_grid = spot_drid / forward - 1.0
53
- strike = strike_level*forward
54
-
55
- option_price0 = compute_bsm_vanilla_price(ttm=ttm, forward=forward, strike=strike, vol=vol, optiontype=optiontype)
56
- option_delta0 = compute_bsm_vanilla_delta(ttm=ttm, forward=forward, strike=strike, vol=vol, optiontype=optiontype)
57
- option_net_delta0 = option_delta0 - option_price0 / forward
58
-
59
- # price return
60
- inverse_price_return = (spot_drid-forward) / spot_drid
61
- dt = 1.0 / 365.0
62
- option_prices = compute_bsm_forward_grid_prices(ttm=ttm-dt, forwards=spot_drid, strike=strike, vol=vol, optiontype=optiontype)
63
- option_pnl_btc = (option_price0/forward - option_prices/spot_drid)
64
-
65
- # black p&l
66
- pnl_btc = option_pnl_btc + option_delta0 * inverse_price_return
67
- if not is_btc_pnl:
68
- pnl_btc = pnl_btc * spot_drid
69
- pnl_btc_positive = spot_drid[pnl_btc >= 0.0]
70
- lower_be = pnl_btc_positive[0] / forward - 1.0
71
- upper_be = pnl_btc_positive[-1] / forward - 1.0
72
- pnl_btc = pd.Series(pnl_btc, index=returns_grid, name=f"Black Delta: breakevens=({lower_be:0.2%}, {upper_be:0.2%})")
73
-
74
- # net p&l
75
- pnl_btc_net_delta = option_pnl_btc + option_net_delta0 * inverse_price_return
76
- if not is_btc_pnl:
77
- pnl_btc_net_delta = pnl_btc_net_delta * spot_drid
78
- pnl_btc_net_delta_positive = spot_drid[pnl_btc_net_delta >= 0.0]
79
- lower_be = pnl_btc_net_delta_positive[0] / forward - 1.0
80
- upper_be = pnl_btc_net_delta_positive[-1] / forward - 1.0
81
- pnl_btc_net_delta = pd.Series(pnl_btc_net_delta, index=returns_grid, name=f"Net Delta : breakevens=({lower_be:0.2%}, {upper_be:0.2%})")
82
-
83
- pnls = pd.concat([pnl_btc, pnl_btc_net_delta], axis=1)
84
-
85
- if is_btc_pnl:
86
- ylabel = 'BTC P&L'
87
- yvar_format = '{:,.2f}'
88
- else:
89
- ylabel = 'USD P&L'
90
- yvar_format = '{:,.0f}'
91
-
92
- qis.plot_line(df=pnls,
93
- xvar_format='{:,.1%}',
94
- yvar_format=yvar_format,
95
- ylabel=ylabel,
96
- xlabel='BTC % change',
97
- ax=ax,
98
- **kwargs)
99
-
100
-
101
- class UnitTests(Enum):
102
- DELTA_COMP = 1
103
- PNL_COMP = 2
104
-
105
-
106
- def run_unit_test(unit_test: UnitTests):
107
-
108
- LOCAL_PATH = "C://Users//artur//OneDrive//My Papers//Working Papers//Crypto Options. Zurich. Oct 2022//FinalFigures//"
109
-
110
- kwargs = dict(fontsize=14, framealpha=0.9)
111
-
112
- ttm = 7.0 / 365.0
113
-
114
- if unit_test == UnitTests.DELTA_COMP:
115
-
116
- with sns.axes_style("darkgrid"):
117
- fig, axs = plt.subplots(1, 2, figsize=(14, 7), tight_layout=True)
118
- compare_net_deltas(ttm=ttm, forward=50000, vol=0.6, optiontype='C',
119
- strike_level=1.0,
120
- title='(A) Call Delta for K=100%*S_0',
121
- ax=axs[0],
122
- **kwargs)
123
- compare_net_deltas(ttm=ttm, forward=50000, vol=0.6, optiontype='P',
124
- strike_level=1.0,
125
- title='(B) Put Delta for K=100%*S_0',
126
- ax=axs[1],
127
- **kwargs)
128
-
129
- is_save = True
130
- if is_save:
131
- qis.save_fig(fig, file_name='delta_comp', local_path=LOCAL_PATH)
132
- qis.save_fig(fig, file_name='delta_comp', file_type=qis.FileTypes.EPS, dpi=1200, local_path=LOCAL_PATH)
133
-
134
- elif unit_test == UnitTests.PNL_COMP:
135
-
136
- with sns.axes_style("darkgrid"):
137
- fig, axs = plt.subplots(1, 2, figsize=(14, 7), tight_layout=True)
138
- compare_pnl(ttm=ttm, forward=50000, vol=0.6, optiontype='C',
139
- title='(A) ATM Call K=100%*F_0',
140
- y_limits=(-0.3, 0.05),
141
- ax=axs[0],
142
- **kwargs)
143
- compare_pnl(ttm=ttm, forward=50000, vol=0.6, optiontype='C',
144
- title='(B) ITM Call K=90%*F_0',
145
- strike_level=0.9,
146
- is_btc_pnl=True,
147
- y_limits=(-0.3, 0.05),
148
- ax=axs[1],
149
- **kwargs)
150
-
151
- is_save = True
152
- if is_save:
153
- qis.save_fig(fig, file_name='pnl_comp', local_path=LOCAL_PATH)
154
- qis.save_fig(fig, file_name='pnl_comp', file_type=qis.FileTypes.EPS, dpi=1200, local_path=LOCAL_PATH)
155
-
156
- plt.show()
157
-
158
-
159
- if __name__ == '__main__':
160
-
161
- unit_test = UnitTests.DELTA_COMP
162
-
163
- is_run_all_tests = False
164
- if is_run_all_tests:
165
- for unit_test in UnitTests:
166
- run_unit_test(unit_test=unit_test)
167
- else:
168
- run_unit_test(unit_test=unit_test)
@@ -1,13 +0,0 @@
1
- This module contains analysis for paper
2
- [Log-normal Stochastic Volatility Model with Quadratic Drift](https://www.worldscientific.com/doi/10.1142/S0219024924500031)
3
- by Artur Sepp and Parviz Rakhmonov
4
-
5
- See the description of data and analysis in the paper.
6
-
7
- Figures in the paper are generated using unittests in
8
- ```python
9
- article_figures.py
10
- ```
11
- https://github.com/ArturSepp/StochVolModels/blob/main/my_papers/logsv_model_wtih_quadratic_drift/article_figures.py
12
-
13
- See the description of data and analysis in the paper.