stochvolmodels 1.1.1__tar.gz → 1.1.2__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 (91) hide show
  1. {stochvolmodels-1.1.1/stochvolmodels.egg-info → stochvolmodels-1.1.2}/PKG-INFO +117 -12
  2. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/README.md +116 -11
  3. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/pyproject.toml +1 -1
  4. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/data/fetch_option_chain.py +11 -13
  5. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/data/test_option_chain.py +13 -15
  6. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/examples/run_lognormal_sv_pricer.py +18 -20
  7. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/analytic/tdist.py +12 -14
  8. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/gmm_pricer.py +9 -11
  9. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/hawkes_jd_pricer.py +13 -15
  10. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/heston_pricer.py +13 -15
  11. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/logsv/vol_moments_ode.py +12 -14
  12. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/logsv_pricer.py +16 -18
  13. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/tdist_pricer.py +9 -11
  14. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/tests/bsm_mgf_pricer.py +11 -13
  15. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/tests/qv_pricer.py +10 -12
  16. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2/stochvolmodels.egg-info}/PKG-INFO +117 -12
  17. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/.gitignore +0 -0
  18. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/LICENSE.txt +0 -0
  19. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/MANIFEST.in +0 -0
  20. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/forward_var/calibrate_forward_var.py +0 -0
  21. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/il_hedging/README.md +0 -0
  22. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/il_hedging/logsv_figures.py +0 -0
  23. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/il_hedging/run_logsv_for_il_payoff.py +0 -0
  24. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/inverse_options/README.md +0 -0
  25. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/inverse_options/compare_net_delta.py +0 -0
  26. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/logsv_model_wtih_quadratic_drift/README.md +0 -0
  27. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/logsv_model_wtih_quadratic_drift/article_figures.py +0 -0
  28. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/logsv_model_wtih_quadratic_drift/calibrations.py +0 -0
  29. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/logsv_model_wtih_quadratic_drift/compare_admis_reg.py +0 -0
  30. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/logsv_model_wtih_quadratic_drift/model_fit_to_options_timeseries.py +0 -0
  31. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/logsv_model_wtih_quadratic_drift/moments_vol_qvar.py +0 -0
  32. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/logsv_model_wtih_quadratic_drift/ode_sol_in_time.py +0 -0
  33. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/logsv_model_wtih_quadratic_drift/steady_state_pdf.py +0 -0
  34. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/logsv_model_wtih_quadratic_drift/vol_drift.py +0 -0
  35. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/risk_premia_gmm/check_kernel.py +0 -0
  36. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/risk_premia_gmm/gmm_slides.py +0 -0
  37. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/risk_premia_gmm/plot_gmm.py +0 -0
  38. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/risk_premia_gmm/q_kernel.py +0 -0
  39. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/risk_premia_gmm/run_gmm_fit.py +0 -0
  40. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/sv_for_factor_hjm/README.md +0 -0
  41. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/sv_for_factor_hjm/calibration_fig_5_6_7.py +0 -0
  42. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/sv_for_factor_hjm/calibration_fig_8_9.py +0 -0
  43. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/t_distribution/illustrations.py +0 -0
  44. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/t_distribution/market_data_fit.py +0 -0
  45. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/t_distribution/mc_pricer_with_kernel.py +0 -0
  46. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/volatility_models/README.md +0 -0
  47. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/volatility_models/article_figures.py +0 -0
  48. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/volatility_models/autocorr_fit.py +0 -0
  49. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/volatility_models/load_data.py +0 -0
  50. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/volatility_models/ss_distribution_fit.py +0 -0
  51. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/my_papers/volatility_models/vol_beta.py +0 -0
  52. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/requirements.txt +0 -0
  53. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/setup.cfg +0 -0
  54. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/__init__.py +0 -0
  55. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/data/__init__.py +0 -0
  56. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/data/option_chain.py +0 -0
  57. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/examples/quick_run_lognormal_sv_pricer.py +0 -0
  58. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/examples/run_heston.py +0 -0
  59. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/examples/run_heston_sv_pricer.py +0 -0
  60. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/examples/run_pricing_options_on_qvar.py +0 -0
  61. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/__init__.py +0 -0
  62. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/analytic/__init__.py +0 -0
  63. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/analytic/bachelier.py +0 -0
  64. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/analytic/bsm.py +0 -0
  65. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/factor_hjm/double_exp_pricer.py +0 -0
  66. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/factor_hjm/factor_hjm_pricer.py +0 -0
  67. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/factor_hjm/rate_affine_expansion.py +0 -0
  68. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/factor_hjm/rate_core.py +0 -0
  69. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/factor_hjm/rate_evaluate.py +0 -0
  70. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/factor_hjm/rate_factor_basis.py +0 -0
  71. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/factor_hjm/rate_logsv_ivols.py +0 -0
  72. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/factor_hjm/rate_logsv_params.py +0 -0
  73. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/factor_hjm/rate_logsv_pricer.py +0 -0
  74. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/logsv/__init__.py +0 -0
  75. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/logsv/affine_expansion.py +0 -0
  76. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/logsv/logsv_params.py +0 -0
  77. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/model_pricer.py +0 -0
  78. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/rough_logsv/RoughKernel.py +0 -0
  79. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/pricers/rough_logsv/split_simulation.py +0 -0
  80. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/tests/__init__.py +0 -0
  81. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/utils/__init__.py +0 -0
  82. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/utils/config.py +0 -0
  83. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/utils/funcs.py +0 -0
  84. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/utils/mc_payoffs.py +0 -0
  85. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/utils/mgf_pricer.py +0 -0
  86. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/utils/plots.py +0 -0
  87. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels/utils/var_swap_pricer.py +0 -0
  88. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels.egg-info/SOURCES.txt +0 -0
  89. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels.egg-info/dependency_links.txt +0 -0
  90. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels.egg-info/requires.txt +0 -0
  91. {stochvolmodels-1.1.1 → stochvolmodels-1.1.2}/stochvolmodels.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stochvolmodels
3
- Version: 1.1.1
3
+ Version: 1.1.2
4
4
  Summary: Python implementation of pricing analytics and Monte Carlo simulations for stochastic volatility models including log-normal SV model, Heston
5
5
  Author-email: Artur Sepp <artursepp@gmail.com>
6
6
  Maintainer-email: Artur Sepp <artursepp@gmail.com>, Parviz Rakhmonov <ParvizRZ@gmail.com>
@@ -779,7 +779,7 @@ Dynamic: license-file
779
779
  The StochVol package provides:
780
780
  1) Analytics for Black-Scholes and Normal vols
781
781
  2) Interfaces and implementation for stochastic volatility models,
782
- including log-normal SV model and Heston SV model
782
+ including Karasinski-Sepp log-normal SV model and Heston SV model
783
783
  using analytical method with Fourier transform and Monte Carlo simulations
784
784
  3) Visualization of model implied volatilities
785
785
 
@@ -808,17 +808,18 @@ Close using
808
808
  git clone https://github.com/ArturSepp/StochVolModels.git
809
809
  ```
810
810
 
811
- Core dependencies:
812
- python = ">=3.8",
813
- numba = ">=0.56.4",
814
- numpy = ">=1.22.4",
815
- scipy = ">=1.10",
816
- pandas = ">=2.2.0",
817
- matplotlib = ">=3.2.2",
818
- seaborn = ">=0.12.2"
811
+
812
+ ### Core Dependencies
813
+ - `python >= 3.8`
814
+ - `numba >= 0.56.4`
815
+ - `numpy >= 1.22.4`
816
+ - `scipy >= 1.10`
817
+ - `pandas >= 2.2.0`
818
+ - `matplotlib >= 3.2.2`
819
+ - `seaborn >= 0.12.2`
819
820
 
820
821
  Optional dependencies:
821
- qis ">=2.1.38" (for running code in my_papers)
822
+ qis ">=2.3.1" (for running code in my_papers)
822
823
 
823
824
 
824
825
  # Table of contents
@@ -846,7 +847,7 @@ The model interface is in stochvolmodels/pricers/model_pricer.py
846
847
 
847
848
  ### Log-normal stochastic volatility model <a name="logsv"></a>
848
849
 
849
- The analytics for the log-normal stochastic volatility model is based on the paper
850
+ The analytics for Karasinki-Sepp log-normal stochastic volatility model is based on the paper
850
851
 
851
852
  [Log-normal Stochastic Volatility Model with Quadratic Drift](https://www.worldscientific.com/doi/10.1142/S0219024924500031) by Artur Sepp and Parviz Rakhmonov
852
853
 
@@ -1039,3 +1040,107 @@ https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4646925
1039
1040
  stochvolmodels/my_papers/sv_for_factor_hjm
1040
1041
  ```
1041
1042
 
1043
+ ## Project Structure
1044
+
1045
+ ```
1046
+ StochVolModels/
1047
+ ├── stochvolmodels/
1048
+ │ ├── pricers/
1049
+ │ │ ├── model_pricer.py # Generic model interface
1050
+ │ │ ├── logsv_pricer.py # Log-normal SV implementation
1051
+ │ │ └── heston_pricer.py # Heston SV implementation
1052
+ │ ├── data/
1053
+ │ │ └── option_chain.py # Option chain data structures
1054
+ │ └── my_papers/ # Research paper implementations
1055
+ │ ├── logsv_model_with_quadratic_drift/
1056
+ │ ├── volatility_models/
1057
+ │ ├── inverse_options/
1058
+ │ ├── il_hedging/
1059
+ │ └── sv_for_factor_hjm/
1060
+ ├── examples/
1061
+ │ ├── run_lognormal_sv_pricer.py
1062
+ │ ├── run_heston_sv_pricer.py
1063
+ │ ├── run_heston.py
1064
+ │ └── plots_for_paper/
1065
+ └── README.md
1066
+ ```
1067
+
1068
+ ## Contributing
1069
+
1070
+ Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
1071
+
1072
+ ## License
1073
+
1074
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
1075
+
1076
+ ## Citation
1077
+
1078
+ If you use this package in your research, please cite the relevant papers:
1079
+
1080
+ ```bibtex
1081
+ @misc{sepp2024stochvolmodels,
1082
+ title={StochVolModels: Python Implementation of Stochastic Volatility Models},
1083
+ author={Sepp, Artur},
1084
+ year={2024},
1085
+ howpublished={\url{https://github.com/ArturSepp/StochVolModels}},
1086
+ note={Python package for pricing analytics and Monte Carlo simulations}
1087
+ }
1088
+
1089
+ @article{sepprakhmonov2023,
1090
+ title={Log-normal stochastic volatility model with quadratic drift},
1091
+ author={Sepp, Artur and Rakhmonov, Parviz},
1092
+ journal={International Journal of Theoretical and Applied Finance},
1093
+ volume={26},
1094
+ number={8},
1095
+ year={2023},
1096
+ url={https://www.worldscientific.com/doi/epdf/10.1142/S0219024924500031}
1097
+ }
1098
+
1099
+ @article{sepprakhmonov2023b,
1100
+ title={What is a robust stochastic volatility model},
1101
+ author={Sepp, Artur and Rakhmonov, Parviz},
1102
+ year={2023},
1103
+ note={Working paper},
1104
+ url={http://ssrn.com/abstract=4647027}
1105
+ }
1106
+
1107
+ @article{lucicsepp2024,
1108
+ title={Valuation and hedging of cryptocurrency inverse options},
1109
+ author={Lucic, Vladimir and Sepp, Artur},
1110
+ journal={Quantitative Finance},
1111
+ volume={24},
1112
+ number={7},
1113
+ pages={851--869},
1114
+ year={2024},
1115
+ url={https://www.tandfonline.com/doi/full/10.1080/14697688.2024.2364804}
1116
+ }
1117
+
1118
+ @article{lucicsepp2024,
1119
+ title={Valuation and hedging of cryptocurrency inverse options},
1120
+ author={Lucic, Vladimir and Sepp, Artur},
1121
+ journal={Quantitative Finance},
1122
+ volume={24},
1123
+ number={7},
1124
+ pages={851--869},
1125
+ year={2024},
1126
+ url={https://www.tandfonline.com/doi/full/10.1080/14697688.2024.2364804}
1127
+ }
1128
+
1129
+ @article{sepprakhmonov2024,
1130
+ title={Stochastic volatility for factor Heath-Jarrow-Morton framework},
1131
+ author={Sepp, Artur and Rakhmonov, Parviz},
1132
+ year={2025},
1133
+ journal={Review of Derivatives Research},
1134
+ note={Accepted},
1135
+ url={http://ssrn.com/abstract=4646925}
1136
+ }
1137
+ ```
1138
+
1139
+ ## Acknowledgments
1140
+
1141
+ Special thanks to co-authors and collaborators:
1142
+ - Parviz Rakhmonov
1143
+ - Vladimir Lucic
1144
+ - Alexander Lipton
1145
+
1146
+ For additional research and advanced analytics, see the companion modules and papers included in this package.
@@ -27,7 +27,7 @@
27
27
  The StochVol package provides:
28
28
  1) Analytics for Black-Scholes and Normal vols
29
29
  2) Interfaces and implementation for stochastic volatility models,
30
- including log-normal SV model and Heston SV model
30
+ including Karasinski-Sepp log-normal SV model and Heston SV model
31
31
  using analytical method with Fourier transform and Monte Carlo simulations
32
32
  3) Visualization of model implied volatilities
33
33
 
@@ -56,17 +56,18 @@ Close using
56
56
  git clone https://github.com/ArturSepp/StochVolModels.git
57
57
  ```
58
58
 
59
- Core dependencies:
60
- python = ">=3.8",
61
- numba = ">=0.56.4",
62
- numpy = ">=1.22.4",
63
- scipy = ">=1.10",
64
- pandas = ">=2.2.0",
65
- matplotlib = ">=3.2.2",
66
- seaborn = ">=0.12.2"
59
+
60
+ ### Core Dependencies
61
+ - `python >= 3.8`
62
+ - `numba >= 0.56.4`
63
+ - `numpy >= 1.22.4`
64
+ - `scipy >= 1.10`
65
+ - `pandas >= 2.2.0`
66
+ - `matplotlib >= 3.2.2`
67
+ - `seaborn >= 0.12.2`
67
68
 
68
69
  Optional dependencies:
69
- qis ">=2.1.38" (for running code in my_papers)
70
+ qis ">=2.3.1" (for running code in my_papers)
70
71
 
71
72
 
72
73
  # Table of contents
@@ -94,7 +95,7 @@ The model interface is in stochvolmodels/pricers/model_pricer.py
94
95
 
95
96
  ### Log-normal stochastic volatility model <a name="logsv"></a>
96
97
 
97
- The analytics for the log-normal stochastic volatility model is based on the paper
98
+ The analytics for Karasinki-Sepp log-normal stochastic volatility model is based on the paper
98
99
 
99
100
  [Log-normal Stochastic Volatility Model with Quadratic Drift](https://www.worldscientific.com/doi/10.1142/S0219024924500031) by Artur Sepp and Parviz Rakhmonov
100
101
 
@@ -287,3 +288,107 @@ https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4646925
287
288
  stochvolmodels/my_papers/sv_for_factor_hjm
288
289
  ```
289
290
 
291
+ ## Project Structure
292
+
293
+ ```
294
+ StochVolModels/
295
+ ├── stochvolmodels/
296
+ │ ├── pricers/
297
+ │ │ ├── model_pricer.py # Generic model interface
298
+ │ │ ├── logsv_pricer.py # Log-normal SV implementation
299
+ │ │ └── heston_pricer.py # Heston SV implementation
300
+ │ ├── data/
301
+ │ │ └── option_chain.py # Option chain data structures
302
+ │ └── my_papers/ # Research paper implementations
303
+ │ ├── logsv_model_with_quadratic_drift/
304
+ │ ├── volatility_models/
305
+ │ ├── inverse_options/
306
+ │ ├── il_hedging/
307
+ │ └── sv_for_factor_hjm/
308
+ ├── examples/
309
+ │ ├── run_lognormal_sv_pricer.py
310
+ │ ├── run_heston_sv_pricer.py
311
+ │ ├── run_heston.py
312
+ │ └── plots_for_paper/
313
+ └── README.md
314
+ ```
315
+
316
+ ## Contributing
317
+
318
+ Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
319
+
320
+ ## License
321
+
322
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
323
+
324
+ ## Citation
325
+
326
+ If you use this package in your research, please cite the relevant papers:
327
+
328
+ ```bibtex
329
+ @misc{sepp2024stochvolmodels,
330
+ title={StochVolModels: Python Implementation of Stochastic Volatility Models},
331
+ author={Sepp, Artur},
332
+ year={2024},
333
+ howpublished={\url{https://github.com/ArturSepp/StochVolModels}},
334
+ note={Python package for pricing analytics and Monte Carlo simulations}
335
+ }
336
+
337
+ @article{sepprakhmonov2023,
338
+ title={Log-normal stochastic volatility model with quadratic drift},
339
+ author={Sepp, Artur and Rakhmonov, Parviz},
340
+ journal={International Journal of Theoretical and Applied Finance},
341
+ volume={26},
342
+ number={8},
343
+ year={2023},
344
+ url={https://www.worldscientific.com/doi/epdf/10.1142/S0219024924500031}
345
+ }
346
+
347
+ @article{sepprakhmonov2023b,
348
+ title={What is a robust stochastic volatility model},
349
+ author={Sepp, Artur and Rakhmonov, Parviz},
350
+ year={2023},
351
+ note={Working paper},
352
+ url={http://ssrn.com/abstract=4647027}
353
+ }
354
+
355
+ @article{lucicsepp2024,
356
+ title={Valuation and hedging of cryptocurrency inverse options},
357
+ author={Lucic, Vladimir and Sepp, Artur},
358
+ journal={Quantitative Finance},
359
+ volume={24},
360
+ number={7},
361
+ pages={851--869},
362
+ year={2024},
363
+ url={https://www.tandfonline.com/doi/full/10.1080/14697688.2024.2364804}
364
+ }
365
+
366
+ @article{lucicsepp2024,
367
+ title={Valuation and hedging of cryptocurrency inverse options},
368
+ author={Lucic, Vladimir and Sepp, Artur},
369
+ journal={Quantitative Finance},
370
+ volume={24},
371
+ number={7},
372
+ pages={851--869},
373
+ year={2024},
374
+ url={https://www.tandfonline.com/doi/full/10.1080/14697688.2024.2364804}
375
+ }
376
+
377
+ @article{sepprakhmonov2024,
378
+ title={Stochastic volatility for factor Heath-Jarrow-Morton framework},
379
+ author={Sepp, Artur and Rakhmonov, Parviz},
380
+ year={2025},
381
+ journal={Review of Derivatives Research},
382
+ note={Accepted},
383
+ url={http://ssrn.com/abstract=4646925}
384
+ }
385
+ ```
386
+
387
+ ## Acknowledgments
388
+
389
+ Special thanks to co-authors and collaborators:
390
+ - Parviz Rakhmonov
391
+ - Vladimir Lucic
392
+ - Alexander Lipton
393
+
394
+ For additional research and advanced analytics, see the companion modules and papers included in this package.
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "stochvolmodels"
10
- version = "1.1.1"
10
+ version = "1.1.2"
11
11
  description = "Python implementation of pricing analytics and Monte Carlo simulations for stochastic volatility models including log-normal SV model, Heston"
12
12
  readme = "README.md"
13
13
  license = {file = "LICENSE.txt"}
@@ -117,13 +117,18 @@ def load_price_data(options_data_dfs: OptionsDataDFs,
117
117
  return spot_price
118
118
 
119
119
 
120
- class UnitTests(Enum):
120
+ class LocalTests(Enum):
121
121
  PRINT_CHAIN_DATA = 1
122
122
  GENERATE_VOL_CHAIN_NP = 2
123
123
  SAMPLE_CHAIN_AT_TIMES = 3
124
124
 
125
125
 
126
- def run_unit_test(unit_test: UnitTests):
126
+ def run_local_test(local_test: LocalTests):
127
+ """Run local tests for development and debugging purposes.
128
+
129
+ These are integration tests that download real data and generate reports.
130
+ Use for quick verification during development.
131
+ """
127
132
 
128
133
  ticker = 'BTC' # BTC, ETH
129
134
  value_time = pd.Timestamp('2021-10-21 08:00:00+00:00')
@@ -134,11 +139,11 @@ def run_unit_test(unit_test: UnitTests):
134
139
  options_data_dfs.get_start_end_date().print()
135
140
  chain = create_chain_from_from_options_dfs(options_data_dfs=options_data_dfs, value_time=value_time)
136
141
 
137
- if unit_test == UnitTests.PRINT_CHAIN_DATA:
142
+ if local_test == LocalTests.PRINT_CHAIN_DATA:
138
143
  for expiry, eslice in chain.expiry_slices.items():
139
144
  eslice.print()
140
145
 
141
- elif unit_test == UnitTests.GENERATE_VOL_CHAIN_NP:
146
+ elif local_test == LocalTests.GENERATE_VOL_CHAIN_NP:
142
147
  option_chain = generate_vol_chain_np(chain=chain,
143
148
  value_time=value_time,
144
149
  days_map={'1w': 7},
@@ -148,7 +153,7 @@ def run_unit_test(unit_test: UnitTests):
148
153
  skews = option_chain.get_chain_skews(delta=0.35)
149
154
  print(skews)
150
155
 
151
- elif unit_test == UnitTests.SAMPLE_CHAIN_AT_TIMES:
156
+ elif local_test == LocalTests.SAMPLE_CHAIN_AT_TIMES:
152
157
  time_period = qis.TimePeriod('01Jan2023', '31Jan2023', tz='UTC')
153
158
  option_chains = sample_option_chain_at_times(options_data_dfs=options_data_dfs,
154
159
  time_period=time_period,
@@ -164,11 +169,4 @@ def run_unit_test(unit_test: UnitTests):
164
169
 
165
170
  if __name__ == '__main__':
166
171
 
167
- unit_test = UnitTests.SAMPLE_CHAIN_AT_TIMES
168
-
169
- is_run_all_tests = False
170
- if is_run_all_tests:
171
- for unit_test in UnitTests:
172
- run_unit_test(unit_test=unit_test)
173
- else:
174
- run_unit_test(unit_test=unit_test)
172
+ run_local_test(local_test=LocalTests.SAMPLE_CHAIN_AT_TIMES)
@@ -871,7 +871,7 @@ def get_qv_options_test_chain_data(num_strikes: int = 21) -> OptionChain:
871
871
  return data
872
872
 
873
873
 
874
- class UnitTests(Enum):
874
+ class LocalTests(Enum):
875
875
  BTC = 1
876
876
  VIX = 2
877
877
  GLD = 3
@@ -879,36 +879,34 @@ class UnitTests(Enum):
879
879
  SPY = 5
880
880
 
881
881
 
882
- def run_unit_test(unit_test: UnitTests):
882
+ def run_local_test(local_test: LocalTests):
883
+ """Run local tests for development and debugging purposes.
883
884
 
884
- if unit_test == UnitTests.BTC:
885
+ These are integration tests that download real data and generate reports.
886
+ Use for quick verification during development.
887
+ """
888
+
889
+ if local_test == LocalTests.BTC:
885
890
  option_chain = get_btc_test_chain_data()
886
891
  print(option_chain)
887
892
 
888
- elif unit_test == UnitTests.VIX:
893
+ elif local_test == LocalTests.VIX:
889
894
  option_chain = get_vix_test_chain_data()
890
895
  print(option_chain)
891
896
 
892
- elif unit_test == UnitTests.GLD:
897
+ elif local_test == LocalTests.GLD:
893
898
  option_chain = get_gld_test_chain_data()
894
899
  print(option_chain)
895
900
 
896
- elif unit_test == UnitTests.SQQQ:
901
+ elif local_test == LocalTests.SQQQ:
897
902
  option_chain = get_sqqq_test_chain_data()
898
903
  print(option_chain)
899
904
 
900
- elif unit_test == UnitTests.SPY:
905
+ elif local_test == LocalTests.SPY:
901
906
  option_chain = get_spy_test_chain_data()
902
907
  print(option_chain)
903
908
 
904
909
 
905
910
  if __name__ == '__main__':
906
911
 
907
- unit_test = UnitTests.BTC
908
-
909
- is_run_all_tests = False
910
- if is_run_all_tests:
911
- for unit_test in UnitTests:
912
- run_unit_test(unit_test=unit_test)
913
- else:
914
- run_unit_test(unit_test=unit_test)
912
+ run_local_test(local_test=LocalTests.BTC)
@@ -9,7 +9,7 @@ import stochvolmodels as sv
9
9
  from stochvolmodels import LogSVPricer, LogSvParams, OptionChain, LogsvModelCalibrationType
10
10
 
11
11
 
12
- class UnitTests(Enum):
12
+ class LocalTests(Enum):
13
13
  COMPUTE_MODEL_PRICES = 1
14
14
  PLOT_MODEL_IMPLIED_VOLS = 2
15
15
  PLOT_MODEL_VOLS_IN_PARAMS = 3
@@ -22,7 +22,12 @@ class UnitTests(Enum):
22
22
  BENCHM_ROUGH_PRICER = 10
23
23
 
24
24
 
25
- def run_unit_test(unit_test: UnitTests):
25
+ def run_local_test(local_test: LocalTests):
26
+ """Run local tests for development and debugging purposes.
27
+
28
+ These are integration tests that download real data and generate reports.
29
+ Use for quick verification during development.
30
+ """
26
31
 
27
32
  # instance of pricer
28
33
  logsv_pricer = LogSVPricer()
@@ -30,7 +35,7 @@ def run_unit_test(unit_test: UnitTests):
30
35
  # define model params
31
36
  params = LogSvParams(sigma0=1.0, theta=1.0, kappa1=5.0, kappa2=5.0, beta=0.2, volvol=2.0)
32
37
 
33
- if unit_test == UnitTests.COMPUTE_MODEL_PRICES:
38
+ if local_test == LocalTests.COMPUTE_MODEL_PRICES:
34
39
  # 1. one price
35
40
  model_price, vol = logsv_pricer.price_vanilla(params=params,
36
41
  ttm=0.25,
@@ -55,7 +60,7 @@ def run_unit_test(unit_test: UnitTests):
55
60
  print(model_prices)
56
61
  print(vols)
57
62
 
58
- elif unit_test == UnitTests.PLOT_MODEL_IMPLIED_VOLS:
63
+ elif local_test == LocalTests.PLOT_MODEL_IMPLIED_VOLS:
59
64
  # define uniform option chain
60
65
  option_chain = OptionChain.get_uniform_chain(ttms=np.array([0.083, 0.25]),
61
66
  ids=np.array(['1m', '3m']),
@@ -63,7 +68,7 @@ def run_unit_test(unit_test: UnitTests):
63
68
  logsv_pricer.plot_model_ivols(option_chain=option_chain,
64
69
  params=params)
65
70
 
66
- elif unit_test == UnitTests.PLOT_MODEL_VOLS_IN_PARAMS:
71
+ elif local_test == LocalTests.PLOT_MODEL_VOLS_IN_PARAMS:
67
72
 
68
73
  # define uniform option chain
69
74
  option_chain = OptionChain.get_uniform_chain(ttms=np.array([0.083, 0.25]),
@@ -79,7 +84,7 @@ def run_unit_test(unit_test: UnitTests):
79
84
  logsv_pricer.plot_model_slices_in_params(option_slice=option_slice,
80
85
  params_dict=params_dict)
81
86
 
82
- elif unit_test == UnitTests.COMPARE_MODEL_VOLS_TO_MC:
87
+ elif local_test == LocalTests.COMPARE_MODEL_VOLS_TO_MC:
83
88
  btc_option_chain = sv.get_btc_test_chain_data()
84
89
  uniform_chain_data = OptionChain.to_uniform_strikes(obj=btc_option_chain, num_strikes=31)
85
90
  btc_calibrated_params = LogSvParams(sigma0=0.8327, theta=1.0139, kappa1=4.8609, kappa2=4.7940, beta=0.1988, volvol=2.3694)
@@ -92,13 +97,13 @@ def run_unit_test(unit_test: UnitTests):
92
97
  params=btc_calibrated_params,
93
98
  nb_path=100000)
94
99
 
95
- elif unit_test == UnitTests.PLOT_FIT_TO_BITCOIN_OPTION_CHAIN:
100
+ elif local_test == LocalTests.PLOT_FIT_TO_BITCOIN_OPTION_CHAIN:
96
101
  btc_option_chain = sv.get_btc_test_chain_data()
97
102
  btc_calibrated_params = LogSvParams(sigma0=0.8327, theta=1.0139, kappa1=4.8609, kappa2=4.7940, beta=0.1988, volvol=2.3694)
98
103
  logsv_pricer.plot_model_ivols_vs_bid_ask(option_chain=btc_option_chain,
99
104
  params=btc_calibrated_params)
100
105
 
101
- elif unit_test == UnitTests.MC_WITH_FIXED_RANDOMS:
106
+ elif local_test == LocalTests.MC_WITH_FIXED_RANDOMS:
102
107
  btc_option_chain = sv.get_btc_test_chain_data()
103
108
  W0s, W1s, dts = sv.get_randoms_for_chain_valuation(ttms=btc_option_chain.ttms,
104
109
  nb_path=10000,
@@ -126,7 +131,7 @@ def run_unit_test(unit_test: UnitTests):
126
131
  print(option_prices_ttm)
127
132
 
128
133
 
129
- elif unit_test == UnitTests.ROUGH_MC_WITH_FIXED_RANDOMS:
134
+ elif local_test == LocalTests.ROUGH_MC_WITH_FIXED_RANDOMS:
130
135
  btc_option_chain = sv.get_btc_test_chain_data()
131
136
  Z0, Z1, grid_ttms = sv.get_randoms_for_rough_vol_chain_valuation(ttms=btc_option_chain.ttms,
132
137
  nb_path=10000,
@@ -154,7 +159,7 @@ def run_unit_test(unit_test: UnitTests):
154
159
  timegrids=grid_ttms)
155
160
  print(option_prices_ttm)
156
161
 
157
- elif unit_test == UnitTests.BENCHM_ROUGH_PRICER:
162
+ elif local_test == LocalTests.BENCHM_ROUGH_PRICER:
158
163
  btc_option_chain = OptionChain.get_uniform_chain(ttms=np.array([0.083, 0.25]),
159
164
  ids=np.array(['1m', '3m']),
160
165
  strikes=np.linspace(0.5, 1.5, 21))
@@ -234,7 +239,7 @@ def run_unit_test(unit_test: UnitTests):
234
239
  fig.suptitle(f"Conventional LogSV model vs Rough LogSV, H={H:.2f} via {N}f Markovian approximation",
235
240
  color="darkblue")
236
241
 
237
- elif unit_test == UnitTests.CALIBRATE_MODEL_TO_BTC_OPTIONS:
242
+ elif local_test == LocalTests.CALIBRATE_MODEL_TO_BTC_OPTIONS:
238
243
  btc_option_chain = sv.get_btc_test_chain_data()
239
244
  params0 = LogSvParams(sigma0=0.8, theta=1.0, kappa1=2.21, kappa2=2.18, beta=0.15, volvol=2.0)
240
245
  btc_calibrated_params = logsv_pricer.calibrate_model_params_to_chain(option_chain=btc_option_chain,
@@ -245,7 +250,7 @@ def run_unit_test(unit_test: UnitTests):
245
250
  logsv_pricer.plot_model_ivols_vs_bid_ask(option_chain=btc_option_chain,
246
251
  params=btc_calibrated_params)
247
252
 
248
- elif unit_test == UnitTests.CALIBRATE_MODEL_TO_BTC_OPTIONS_WITH_MC:
253
+ elif local_test == LocalTests.CALIBRATE_MODEL_TO_BTC_OPTIONS_WITH_MC:
249
254
  btc_option_chain = sv.get_btc_test_chain_data()
250
255
  params0 = LogSvParams(sigma0=0.8, theta=1.0, kappa1=2.21, kappa2=0.0, beta=0.15, volvol=2.0)
251
256
  params0.H = 0.3
@@ -266,11 +271,4 @@ def run_unit_test(unit_test: UnitTests):
266
271
 
267
272
  if __name__ == '__main__':
268
273
 
269
- unit_test = UnitTests.BENCHM_ROUGH_PRICER
270
-
271
- is_run_all_tests = False
272
- if is_run_all_tests:
273
- for unit_test in UnitTests:
274
- run_unit_test(unit_test=unit_test)
275
- else:
276
- run_unit_test(unit_test=unit_test)
274
+ run_local_test(local_test=LocalTests.BENCHM_ROUGH_PRICER)
@@ -197,14 +197,19 @@ def infer_tdist_implied_vols_from_model_slice_prices(ttm: float,
197
197
  return model_vol_ttm
198
198
 
199
199
 
200
- class UnitTests(Enum):
200
+ class LocalTests(Enum):
201
201
  PLOT_PDF = 1
202
202
  PLOT_CDF = 2
203
203
  PLOT_CUM_X = 3
204
204
  PLOT_H = 4
205
205
 
206
206
 
207
- def run_unit_test(unit_test: UnitTests):
207
+ def run_local_test(local_test: LocalTests):
208
+ """Run local tests for development and debugging purposes.
209
+
210
+ These are integration tests that download real data and generate reports.
211
+ Use for quick verification during development.
212
+ """
208
213
 
209
214
  import qis as qis
210
215
 
@@ -215,7 +220,7 @@ def run_unit_test(unit_test: UnitTests):
215
220
  'mu=0.2, vol=0.2': (0.2, 0.2),
216
221
  'mu=0.2, vol=0.4': (0.2, 0.4)}
217
222
 
218
- if unit_test == UnitTests.PLOT_PDF:
223
+ if local_test == LocalTests.PLOT_PDF:
219
224
  pdfs = {}
220
225
  for key, mu_vol in mu_vols.items():
221
226
  pdf = dx * pdf_tdist(x=x, mu=mu_vol[0], vol=mu_vol[1], nu=3.0, ttm=ttm)
@@ -224,7 +229,7 @@ def run_unit_test(unit_test: UnitTests):
224
229
  pdfs = pd.DataFrame.from_dict(pdfs, orient='columns')
225
230
  qis.plot_line(df=pdfs)
226
231
 
227
- elif unit_test == UnitTests.PLOT_CDF:
232
+ elif local_test == LocalTests.PLOT_CDF:
228
233
  pdfs = {}
229
234
  cpdfs = {}
230
235
  for key, mu_vol in mu_vols.items():
@@ -238,7 +243,7 @@ def run_unit_test(unit_test: UnitTests):
238
243
  colors = qis.get_n_colors(n=len(mu_vols.keys()))
239
244
  qis.plot_line(df=df, colors=2*colors)
240
245
 
241
- elif unit_test == UnitTests.PLOT_CUM_X:
246
+ elif local_test == LocalTests.PLOT_CUM_X:
242
247
  pdfs = {}
243
248
  cpdfs = {}
244
249
  for key, mu_vol in mu_vols.items():
@@ -252,7 +257,7 @@ def run_unit_test(unit_test: UnitTests):
252
257
  colors = qis.get_n_colors(n=len(mu_vols.keys()))
253
258
  qis.plot_line(df=df, colors=2*colors)
254
259
 
255
- elif unit_test == UnitTests.PLOT_H:
260
+ elif local_test == LocalTests.PLOT_H:
256
261
  x = np.linspace(-10.0, 10.0, 2000)
257
262
  h = pd.Series(cum_mean_tdist(x=x, mu=0.5, vol=1.0, nu=3.0, ttm=1.0), index=x, name='h')
258
263
  qis.plot_line(df=h, xlabel='x')
@@ -262,11 +267,4 @@ def run_unit_test(unit_test: UnitTests):
262
267
 
263
268
  if __name__ == '__main__':
264
269
 
265
- unit_test = UnitTests.PLOT_CUM_X
266
-
267
- is_run_all_tests = False
268
- if is_run_all_tests:
269
- for unit_test in UnitTests:
270
- run_unit_test(unit_test=unit_test)
271
- else:
272
- run_unit_test(unit_test=unit_test)
270
+ run_local_test(local_test=LocalTests.PLOT_CUM_X)
@@ -259,17 +259,22 @@ def gmm_vanilla_chain_pricer(gmm_weights: np.ndarray,
259
259
  return model_prices_ttms
260
260
 
261
261
 
262
- class UnitTests(Enum):
262
+ class LocalTests(Enum):
263
263
  CALIBRATOR = 1
264
264
 
265
265
 
266
- def run_unit_test(unit_test: UnitTests):
266
+ def run_local_test(local_test: LocalTests):
267
+ """Run local tests for development and debugging purposes.
268
+
269
+ These are integration tests that download real data and generate reports.
270
+ Use for quick verification during development.
271
+ """
267
272
 
268
273
  import seaborn as sns
269
274
  from stochvolmodels.utils import plots as plot
270
275
  from stochvolmodels.data.test_option_chain import get_btc_test_chain_data
271
276
 
272
- if unit_test == UnitTests.CALIBRATOR:
277
+ if local_test == LocalTests.CALIBRATOR:
273
278
  option_chain = get_btc_test_chain_data()
274
279
  gmm_pricer = GmmPricer()
275
280
  fit_params = gmm_pricer.calibrate_model_params_to_chain(option_chain=option_chain)
@@ -288,11 +293,4 @@ def run_unit_test(unit_test: UnitTests):
288
293
 
289
294
  if __name__ == '__main__':
290
295
 
291
- unit_test = UnitTests.CALIBRATOR
292
-
293
- is_run_all_tests = False
294
- if is_run_all_tests:
295
- for unit_test in UnitTests:
296
- run_unit_test(unit_test=unit_test)
297
- else:
298
- run_unit_test(unit_test=unit_test)
296
+ run_local_test(local_test=LocalTests.CALIBRATOR)