stochvolmodels 1.1.1__tar.gz → 1.1.3__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 (92) hide show
  1. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/.gitignore +2 -0
  2. {stochvolmodels-1.1.1/stochvolmodels.egg-info → stochvolmodels-1.1.3}/PKG-INFO +131 -12
  3. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/README.md +130 -11
  4. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/pyproject.toml +1 -1
  5. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/data/fetch_option_chain.py +11 -13
  6. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/data/test_option_chain.py +13 -15
  7. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/examples/run_lognormal_sv_pricer.py +50 -35
  8. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/analytic/tdist.py +12 -14
  9. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/gmm_pricer.py +9 -11
  10. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/hawkes_jd_pricer.py +13 -15
  11. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/heston_pricer.py +13 -15
  12. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/logsv/logsv_params.py +4 -1
  13. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/logsv/vol_moments_ode.py +12 -14
  14. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/logsv_pricer.py +23 -25
  15. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/rough_logsv/split_simulation.py +57 -38
  16. stochvolmodels-1.1.3/stochvolmodels/pricers/rough_logsv/test_kernel_approx.py +16 -0
  17. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/tdist_pricer.py +9 -11
  18. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/tests/bsm_mgf_pricer.py +11 -13
  19. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/tests/qv_pricer.py +10 -12
  20. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3/stochvolmodels.egg-info}/PKG-INFO +131 -12
  21. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels.egg-info/SOURCES.txt +1 -0
  22. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/LICENSE.txt +0 -0
  23. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/MANIFEST.in +0 -0
  24. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/forward_var/calibrate_forward_var.py +0 -0
  25. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/il_hedging/README.md +0 -0
  26. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/il_hedging/logsv_figures.py +0 -0
  27. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/il_hedging/run_logsv_for_il_payoff.py +0 -0
  28. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/inverse_options/README.md +0 -0
  29. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/inverse_options/compare_net_delta.py +0 -0
  30. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/logsv_model_wtih_quadratic_drift/README.md +0 -0
  31. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/logsv_model_wtih_quadratic_drift/article_figures.py +0 -0
  32. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/logsv_model_wtih_quadratic_drift/calibrations.py +0 -0
  33. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/logsv_model_wtih_quadratic_drift/compare_admis_reg.py +0 -0
  34. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/logsv_model_wtih_quadratic_drift/model_fit_to_options_timeseries.py +0 -0
  35. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/logsv_model_wtih_quadratic_drift/moments_vol_qvar.py +0 -0
  36. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/logsv_model_wtih_quadratic_drift/ode_sol_in_time.py +0 -0
  37. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/logsv_model_wtih_quadratic_drift/steady_state_pdf.py +0 -0
  38. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/logsv_model_wtih_quadratic_drift/vol_drift.py +0 -0
  39. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/risk_premia_gmm/check_kernel.py +0 -0
  40. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/risk_premia_gmm/gmm_slides.py +0 -0
  41. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/risk_premia_gmm/plot_gmm.py +0 -0
  42. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/risk_premia_gmm/q_kernel.py +0 -0
  43. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/risk_premia_gmm/run_gmm_fit.py +0 -0
  44. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/sv_for_factor_hjm/README.md +0 -0
  45. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/sv_for_factor_hjm/calibration_fig_5_6_7.py +0 -0
  46. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/sv_for_factor_hjm/calibration_fig_8_9.py +0 -0
  47. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/t_distribution/illustrations.py +0 -0
  48. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/t_distribution/market_data_fit.py +0 -0
  49. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/t_distribution/mc_pricer_with_kernel.py +0 -0
  50. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/volatility_models/README.md +0 -0
  51. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/volatility_models/article_figures.py +0 -0
  52. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/volatility_models/autocorr_fit.py +0 -0
  53. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/volatility_models/load_data.py +0 -0
  54. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/volatility_models/ss_distribution_fit.py +0 -0
  55. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/my_papers/volatility_models/vol_beta.py +0 -0
  56. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/requirements.txt +0 -0
  57. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/setup.cfg +0 -0
  58. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/__init__.py +0 -0
  59. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/data/__init__.py +0 -0
  60. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/data/option_chain.py +0 -0
  61. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/examples/quick_run_lognormal_sv_pricer.py +0 -0
  62. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/examples/run_heston.py +0 -0
  63. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/examples/run_heston_sv_pricer.py +0 -0
  64. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/examples/run_pricing_options_on_qvar.py +0 -0
  65. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/__init__.py +0 -0
  66. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/analytic/__init__.py +0 -0
  67. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/analytic/bachelier.py +0 -0
  68. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/analytic/bsm.py +0 -0
  69. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/factor_hjm/double_exp_pricer.py +0 -0
  70. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/factor_hjm/factor_hjm_pricer.py +0 -0
  71. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/factor_hjm/rate_affine_expansion.py +0 -0
  72. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/factor_hjm/rate_core.py +0 -0
  73. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/factor_hjm/rate_evaluate.py +0 -0
  74. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/factor_hjm/rate_factor_basis.py +0 -0
  75. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/factor_hjm/rate_logsv_ivols.py +0 -0
  76. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/factor_hjm/rate_logsv_params.py +0 -0
  77. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/factor_hjm/rate_logsv_pricer.py +0 -0
  78. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/logsv/__init__.py +0 -0
  79. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/logsv/affine_expansion.py +0 -0
  80. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/model_pricer.py +0 -0
  81. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/pricers/rough_logsv/RoughKernel.py +0 -0
  82. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/tests/__init__.py +0 -0
  83. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/utils/__init__.py +0 -0
  84. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/utils/config.py +0 -0
  85. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/utils/funcs.py +0 -0
  86. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/utils/mc_payoffs.py +0 -0
  87. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/utils/mgf_pricer.py +0 -0
  88. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/utils/plots.py +0 -0
  89. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels/utils/var_swap_pricer.py +0 -0
  90. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels.egg-info/dependency_links.txt +0 -0
  91. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels.egg-info/requires.txt +0 -0
  92. {stochvolmodels-1.1.1 → stochvolmodels-1.1.3}/stochvolmodels.egg-info/top_level.txt +0 -0
@@ -131,3 +131,5 @@ dmypy.json
131
131
 
132
132
  # Pyre type checker
133
133
  .pyre/
134
+ /resources
135
+ /volatility_book
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stochvolmodels
3
- Version: 1.1.1
3
+ Version: 1.1.3
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,121 @@ 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.
1147
+
1148
+ ## BibTeX Citations for StochVolModels (Stochastic Volatility Models) Package
1149
+
1150
+ If you use StochVolModels in your research, please cite it as:
1151
+
1152
+ ```bibtex
1153
+ @software{stochvolmodels2024,
1154
+ author={Sepp, Artur},
1155
+ title={StochVolModels: Python implementation of pricing analytics and Monte Carlo simulations for stochastic volatility models},
1156
+ year={2024},
1157
+ url={https://github.com/ArturSepp/StochVolModels},
1158
+ }
1159
+ ```
1160
+
@@ -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,121 @@ 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.
395
+
396
+ ## BibTeX Citations for StochVolModels (Stochastic Volatility Models) Package
397
+
398
+ If you use StochVolModels in your research, please cite it as:
399
+
400
+ ```bibtex
401
+ @software{stochvolmodels2024,
402
+ author={Sepp, Artur},
403
+ title={StochVolModels: Python implementation of pricing analytics and Monte Carlo simulations for stochastic volatility models},
404
+ year={2024},
405
+ url={https://github.com/ArturSepp/StochVolModels},
406
+ }
407
+ ```
408
+
@@ -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.3"
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)
@@ -4,12 +4,16 @@ run few unit test to illustrate implementation of log-normal sv model analytics
4
4
 
5
5
  import numpy as np
6
6
  import matplotlib.pyplot as plt
7
+ import seaborn as sns
8
+ import pandas as pd
9
+ import matplotlib.ticker as mticker
7
10
  from enum import Enum
8
11
  import stochvolmodels as sv
12
+ from stochvolmodels.utils import plots as plot
9
13
  from stochvolmodels import LogSVPricer, LogSvParams, OptionChain, LogsvModelCalibrationType
10
14
 
11
15
 
12
- class UnitTests(Enum):
16
+ class LocalTests(Enum):
13
17
  COMPUTE_MODEL_PRICES = 1
14
18
  PLOT_MODEL_IMPLIED_VOLS = 2
15
19
  PLOT_MODEL_VOLS_IN_PARAMS = 3
@@ -22,7 +26,13 @@ class UnitTests(Enum):
22
26
  BENCHM_ROUGH_PRICER = 10
23
27
 
24
28
 
25
- def run_unit_test(unit_test: UnitTests):
29
+
30
+ def run_local_test(local_test: LocalTests):
31
+ """Run local tests for development and debugging purposes.
32
+
33
+ These are integration tests that download real data and generate reports.
34
+ Use for quick verification during development.
35
+ """
26
36
 
27
37
  # instance of pricer
28
38
  logsv_pricer = LogSVPricer()
@@ -30,7 +40,7 @@ def run_unit_test(unit_test: UnitTests):
30
40
  # define model params
31
41
  params = LogSvParams(sigma0=1.0, theta=1.0, kappa1=5.0, kappa2=5.0, beta=0.2, volvol=2.0)
32
42
 
33
- if unit_test == UnitTests.COMPUTE_MODEL_PRICES:
43
+ if local_test == LocalTests.COMPUTE_MODEL_PRICES:
34
44
  # 1. one price
35
45
  model_price, vol = logsv_pricer.price_vanilla(params=params,
36
46
  ttm=0.25,
@@ -55,7 +65,7 @@ def run_unit_test(unit_test: UnitTests):
55
65
  print(model_prices)
56
66
  print(vols)
57
67
 
58
- elif unit_test == UnitTests.PLOT_MODEL_IMPLIED_VOLS:
68
+ elif local_test == LocalTests.PLOT_MODEL_IMPLIED_VOLS:
59
69
  # define uniform option chain
60
70
  option_chain = OptionChain.get_uniform_chain(ttms=np.array([0.083, 0.25]),
61
71
  ids=np.array(['1m', '3m']),
@@ -63,7 +73,7 @@ def run_unit_test(unit_test: UnitTests):
63
73
  logsv_pricer.plot_model_ivols(option_chain=option_chain,
64
74
  params=params)
65
75
 
66
- elif unit_test == UnitTests.PLOT_MODEL_VOLS_IN_PARAMS:
76
+ elif local_test == LocalTests.PLOT_MODEL_VOLS_IN_PARAMS:
67
77
 
68
78
  # define uniform option chain
69
79
  option_chain = OptionChain.get_uniform_chain(ttms=np.array([0.083, 0.25]),
@@ -79,7 +89,7 @@ def run_unit_test(unit_test: UnitTests):
79
89
  logsv_pricer.plot_model_slices_in_params(option_slice=option_slice,
80
90
  params_dict=params_dict)
81
91
 
82
- elif unit_test == UnitTests.COMPARE_MODEL_VOLS_TO_MC:
92
+ elif local_test == LocalTests.COMPARE_MODEL_VOLS_TO_MC:
83
93
  btc_option_chain = sv.get_btc_test_chain_data()
84
94
  uniform_chain_data = OptionChain.to_uniform_strikes(obj=btc_option_chain, num_strikes=31)
85
95
  btc_calibrated_params = LogSvParams(sigma0=0.8327, theta=1.0139, kappa1=4.8609, kappa2=4.7940, beta=0.1988, volvol=2.3694)
@@ -92,13 +102,13 @@ def run_unit_test(unit_test: UnitTests):
92
102
  params=btc_calibrated_params,
93
103
  nb_path=100000)
94
104
 
95
- elif unit_test == UnitTests.PLOT_FIT_TO_BITCOIN_OPTION_CHAIN:
105
+ elif local_test == LocalTests.PLOT_FIT_TO_BITCOIN_OPTION_CHAIN:
96
106
  btc_option_chain = sv.get_btc_test_chain_data()
97
107
  btc_calibrated_params = LogSvParams(sigma0=0.8327, theta=1.0139, kappa1=4.8609, kappa2=4.7940, beta=0.1988, volvol=2.3694)
98
108
  logsv_pricer.plot_model_ivols_vs_bid_ask(option_chain=btc_option_chain,
99
109
  params=btc_calibrated_params)
100
110
 
101
- elif unit_test == UnitTests.MC_WITH_FIXED_RANDOMS:
111
+ elif local_test == LocalTests.MC_WITH_FIXED_RANDOMS:
102
112
  btc_option_chain = sv.get_btc_test_chain_data()
103
113
  W0s, W1s, dts = sv.get_randoms_for_chain_valuation(ttms=btc_option_chain.ttms,
104
114
  nb_path=10000,
@@ -126,7 +136,7 @@ def run_unit_test(unit_test: UnitTests):
126
136
  print(option_prices_ttm)
127
137
 
128
138
 
129
- elif unit_test == UnitTests.ROUGH_MC_WITH_FIXED_RANDOMS:
139
+ elif local_test == LocalTests.ROUGH_MC_WITH_FIXED_RANDOMS:
130
140
  btc_option_chain = sv.get_btc_test_chain_data()
131
141
  Z0, Z1, grid_ttms = sv.get_randoms_for_rough_vol_chain_valuation(ttms=btc_option_chain.ttms,
132
142
  nb_path=10000,
@@ -154,24 +164,24 @@ def run_unit_test(unit_test: UnitTests):
154
164
  timegrids=grid_ttms)
155
165
  print(option_prices_ttm)
156
166
 
157
- elif unit_test == UnitTests.BENCHM_ROUGH_PRICER:
158
- btc_option_chain = OptionChain.get_uniform_chain(ttms=np.array([0.083, 0.25]),
159
- ids=np.array(['1m', '3m']),
160
- strikes=np.linspace(0.5, 1.5, 21))
161
- params0 = LogSvParams(sigma0=0.8, theta=1.0, kappa1=2.21, kappa2=0.0, beta=0.15, volvol=2.0)
162
- nb_path = 100000
163
- H = 0.3
164
- N = 3
167
+ elif local_test == LocalTests.BENCHM_ROUGH_PRICER:
168
+ btc_option_chain = sv.get_btc_test_chain_data()
169
+ # params0 = LogSvParams(sigma0=0.8, theta=1.0, kappa1=2.21, kappa2=1.0, beta=0.15, volvol=1.0)
170
+ params0 = LogSvParams(sigma0=1.32, theta=0.47, kappa1=9.98, kappa2=2.0, beta=0.45, volvol=0.83)
171
+ nb_path = 1000000
172
+ H = 0.4
173
+ N = 2
174
+ seed = 1
165
175
 
166
176
  def rough_vol():
167
177
  params1 = LogSvParams.copy(params0)
168
- params1.H = 0.3
178
+ params1.H = H
169
179
  params1.approximate_kernel(T=btc_option_chain.ttms[-1], N=N)
170
180
 
171
181
  Z0, Z1, grid_ttms = sv.get_randoms_for_rough_vol_chain_valuation(ttms=btc_option_chain.ttms,
172
182
  nb_path=nb_path,
173
183
  nb_steps_per_year=360,
174
- seed=10)
184
+ seed=seed)
175
185
 
176
186
 
177
187
  option_prices_ttm, option_std_ttm = sv.rough_logsv_mc_chain_pricer_fixed_randoms(ttms=btc_option_chain.ttms,
@@ -223,18 +233,30 @@ def run_unit_test(unit_test: UnitTests):
223
233
  ivols_logsv = regular_vol()
224
234
 
225
235
  nb_slices = btc_option_chain.ttms.size
226
- fig, axs = plt.subplots(1, nb_slices, figsize=(4*nb_slices, 3), tight_layout=True)
236
+ assert nb_slices == 4
237
+
238
+ with sns.axes_style('darkgrid'):
239
+ fig, axs = plt.subplots(2, 2, figsize=(15, 9), tight_layout=True)
240
+ axs = plot.to_flat_list(axs)
227
241
 
228
242
  for i in range(nb_slices):
229
- ax = axs[i] if nb_slices>1 else axs
230
- ax.plot(btc_option_chain.strikes_ttms[i], ivols_logsv[i], label="LOG_SV", marker="*")
231
- ax.plot(btc_option_chain.strikes_ttms[i], ivols_rough_logsv[i], label="ROUGH_LOG_SV", marker="o")
243
+ data = pd.DataFrame({"Rough Log-SV": ivols_rough_logsv[i],
244
+ "Log-SV": ivols_logsv[i]},
245
+ index=np.log(
246
+ btc_option_chain.strikes_ttms[i] / btc_option_chain.forwards[i]))
247
+ ax = axs[i]
248
+ sns.lineplot(data, ax=ax, markers=["o"])
232
249
  ax.set_title("Expiry: " + btc_option_chain.ids[i])
250
+ ax.yaxis.set_major_formatter(mticker.FuncFormatter(lambda z, _: '{:.0%}'.format(z)))
251
+ ax.xaxis.set_major_formatter(mticker.FuncFormatter(lambda z, _: '{:.2f}'.format(z)))
233
252
  ax.legend()
234
- fig.suptitle(f"Conventional LogSV model vs Rough LogSV, H={H:.2f} via {N}f Markovian approximation",
235
- color="darkblue")
253
+ fig.suptitle(f"Conventional LogSV model vs Rough LogSV, H={H:.2f} via {N}f Markovian approximation\n"
254
+ f"{params0.to_str()}",
255
+ color = "darkblue", fontsize = 14)
236
256
 
237
- elif unit_test == UnitTests.CALIBRATE_MODEL_TO_BTC_OPTIONS:
257
+ # fig.savefig("c:/temp/rough_vs_conven_vol.pdf")
258
+
259
+ elif local_test == LocalTests.CALIBRATE_MODEL_TO_BTC_OPTIONS:
238
260
  btc_option_chain = sv.get_btc_test_chain_data()
239
261
  params0 = LogSvParams(sigma0=0.8, theta=1.0, kappa1=2.21, kappa2=2.18, beta=0.15, volvol=2.0)
240
262
  btc_calibrated_params = logsv_pricer.calibrate_model_params_to_chain(option_chain=btc_option_chain,
@@ -245,7 +267,7 @@ def run_unit_test(unit_test: UnitTests):
245
267
  logsv_pricer.plot_model_ivols_vs_bid_ask(option_chain=btc_option_chain,
246
268
  params=btc_calibrated_params)
247
269
 
248
- elif unit_test == UnitTests.CALIBRATE_MODEL_TO_BTC_OPTIONS_WITH_MC:
270
+ elif local_test == LocalTests.CALIBRATE_MODEL_TO_BTC_OPTIONS_WITH_MC:
249
271
  btc_option_chain = sv.get_btc_test_chain_data()
250
272
  params0 = LogSvParams(sigma0=0.8, theta=1.0, kappa1=2.21, kappa2=0.0, beta=0.15, volvol=2.0)
251
273
  params0.H = 0.3
@@ -266,11 +288,4 @@ def run_unit_test(unit_test: UnitTests):
266
288
 
267
289
  if __name__ == '__main__':
268
290
 
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)
291
+ run_local_test(local_test=LocalTests.BENCHM_ROUGH_PRICER)