stochvolmodels 2.2.0__tar.gz → 2.3.0__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 (94) hide show
  1. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/CHANGELOG.md +32 -0
  2. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/MANIFEST.in +0 -1
  3. {stochvolmodels-2.2.0/src/stochvolmodels.egg-info → stochvolmodels-2.3.0}/PKG-INFO +17 -20
  4. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/README.md +13 -13
  5. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/pyproject.toml +9 -9
  6. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/data/fetch_option_chain.py +61 -106
  7. stochvolmodels-2.3.0/src/stochvolmodels/estimation/__init__.py +71 -0
  8. stochvolmodels-2.3.0/src/stochvolmodels/estimation/forecasting/__init__.py +63 -0
  9. stochvolmodels-2.3.0/src/stochvolmodels/estimation/forecasting/features.py +202 -0
  10. stochvolmodels-2.3.0/src/stochvolmodels/estimation/forecasting/horizons.py +55 -0
  11. stochvolmodels-2.3.0/src/stochvolmodels/estimation/forecasting/models.py +283 -0
  12. stochvolmodels-2.3.0/src/stochvolmodels/estimation/forecasting/results.py +437 -0
  13. stochvolmodels-2.3.0/src/stochvolmodels/estimation/forecasting/walk_forward.py +255 -0
  14. stochvolmodels-2.3.0/src/stochvolmodels/estimation/ohlc.py +246 -0
  15. stochvolmodels-2.3.0/src/stochvolmodels/estimation/realized_volatility.py +126 -0
  16. stochvolmodels-2.3.0/src/stochvolmodels/fitters/adapters/__init__.py +5 -0
  17. stochvolmodels-2.3.0/src/stochvolmodels/fitters/adapters/oca.py +129 -0
  18. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_oca_option_chain_adapter.py +67 -4
  19. stochvolmodels-2.3.0/src/stochvolmodels/tests/test_ohlc_estimation.py +114 -0
  20. stochvolmodels-2.3.0/src/stochvolmodels/tests/test_volatility_features.py +221 -0
  21. stochvolmodels-2.3.0/src/stochvolmodels/tests/test_volatility_forecasting_models.py +347 -0
  22. stochvolmodels-2.3.0/src/stochvolmodels/tests/test_volatility_targets.py +184 -0
  23. stochvolmodels-2.3.0/src/stochvolmodels/tests/test_volatility_walk_forward.py +380 -0
  24. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0/src/stochvolmodels.egg-info}/PKG-INFO +17 -20
  25. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels.egg-info/SOURCES.txt +16 -0
  26. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels.egg-info/requires.txt +2 -7
  27. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/LICENSE.txt +0 -0
  28. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/setup.cfg +0 -0
  29. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/__init__.py +0 -0
  30. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/data/__init__.py +0 -0
  31. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/data/option_chain.py +0 -0
  32. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/data/sample_option_chains.py +0 -0
  33. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/fitters/__init__.py +0 -0
  34. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/fitters/logsv_smile.py +0 -0
  35. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/fitters/tdist.py +0 -0
  36. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/local_path.py +0 -0
  37. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/__init__.py +0 -0
  38. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/factor_hjm/__init__.py +0 -0
  39. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/factor_hjm/double_exp_pricer.py +0 -0
  40. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/factor_hjm/factor_hjm_pricer.py +0 -0
  41. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/factor_hjm/rate_affine_expansion.py +0 -0
  42. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/factor_hjm/rate_evaluate.py +0 -0
  43. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/factor_hjm/rate_factor_basis.py +0 -0
  44. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/factor_hjm/rate_logsv_ivols.py +0 -0
  45. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/factor_hjm/rate_logsv_params.py +0 -0
  46. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/factor_hjm/rate_logsv_pricer.py +0 -0
  47. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/gmm_pricer.py +0 -0
  48. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/hawkes_jd_pricer.py +0 -0
  49. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/heston_pricer.py +0 -0
  50. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/logsv/__init__.py +0 -0
  51. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/logsv/affine_expansion.py +0 -0
  52. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/logsv/logsv_params.py +0 -0
  53. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/logsv/vol_moments_ode.py +0 -0
  54. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/logsv_pricer.py +0 -0
  55. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/model_pricer.py +0 -0
  56. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/rough_logsv/__init__.py +0 -0
  57. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/rough_logsv/expm.py +0 -0
  58. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/rough_logsv/rough_kernel.py +0 -0
  59. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/rough_logsv/split_simulation.py +0 -0
  60. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/pricers/tdist_pricer.py +0 -0
  61. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/settings.yaml.example +0 -0
  62. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/__init__.py +0 -0
  63. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/conftest.py +0 -0
  64. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_analytic_bachelier.py +0 -0
  65. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_analytic_bsm.py +0 -0
  66. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_cboe_option_data_optional.py +0 -0
  67. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_distribution_pricer_contracts.py +0 -0
  68. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_factor_hjm_characterization.py +0 -0
  69. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_heston_characterization.py +0 -0
  70. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_import_contracts.py +0 -0
  71. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_joss_evidence.py +0 -0
  72. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_local_path.py +0 -0
  73. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_logsv_characterization.py +0 -0
  74. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_logsv_smile_fitter.py +0 -0
  75. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_mgf_pricer_identities.py +0 -0
  76. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_model_calibration_contracts.py +0 -0
  77. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_module_layout.py +0 -0
  78. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_numerical_utilities.py +0 -0
  79. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_option_chain_characterization.py +0 -0
  80. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_public_api_contracts.py +0 -0
  81. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_repository_contracts.py +0 -0
  82. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_rough_logsv_characterization.py +0 -0
  83. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_rough_logsv_pricer_regression/test_rough_logsv_pricer_pricing_regression.npz +0 -0
  84. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/tests/test_rough_logsv_pricer_regression.py +0 -0
  85. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/utils/__init__.py +0 -0
  86. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/utils/config.py +0 -0
  87. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/utils/funcs.py +0 -0
  88. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/utils/mc_payoffs.py +0 -0
  89. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/utils/mgf_pricer.py +0 -0
  90. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/utils/plots.py +0 -0
  91. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/utils/rate_core.py +0 -0
  92. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels/utils/var_swap_pricer.py +0 -0
  93. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels.egg-info/dependency_links.txt +0 -0
  94. {stochvolmodels-2.2.0 → stochvolmodels-2.3.0}/src/stochvolmodels.egg-info/top_level.txt +0 -0
@@ -4,6 +4,38 @@ Entries start at 1.2.0. For earlier releases see the git log.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [2.3.0] - 2026-08-24
8
+
9
+ ### Added
10
+ - `stochvolmodels.estimation` now owns the Parkinson, Garman-Klass,
11
+ Rogers-Satchell, and close-to-close OHLC volatility estimators formerly maintained by `qis`.
12
+ - `ForecastHorizon`, trading/calendar horizon presets, and the forward variance and volatility
13
+ target builders define point-in-time 1-day, 1-week, and 1-month forecast intervals without
14
+ including the information-time observation.
15
+ - `estimate_ohlc_variances` and `build_volatility_features` provide a pooled OHLC variance panel
16
+ and append-only current, lagged, rolling-mean, LWMA, and downside-return forecast features.
17
+ - `fit_volatility_forecaster` provides expanding-mean, persistence, fixed-decay EWMA, HAR, and
18
+ pooled OHLC level-NNLS fits with immutable diagnostics and non-negative predictions.
19
+ - `walk_forward_volatility_forecast` adds expanding or rolling horizon-purged refits, immutable
20
+ per-origin and per-refit diagnostics, forecast losses, and common-sample benchmark comparisons.
21
+ - `stochvolmodels.fitters.adapters.oca.option_chain_from_oca` is the reusable conversion from
22
+ one OCA point-in-time `SlicesChain` to SVM calibration inputs.
23
+ - `plot_vix_1m_atm_vol.py` extracts and plots a same-session, constant-maturity VIX ATM
24
+ implied-volatility history from a partitioned OCA EOD cache without committing provider data.
25
+
26
+ ### Changed
27
+ - `sample_option_chain_at_times` now delegates observation schedules and point-in-time selection
28
+ to OCA's `create_chain_timeseries`; `generate_vol_chain_np` remains a deprecated compatibility
29
+ wrapper around the fitter adapter.
30
+ - `load_price_data` now delegates to the OCA chain object's linked underlying-data loader and is
31
+ retained only as a deprecated compatibility wrapper.
32
+ - The `research` extra now requires `option-chain-analytics[cboe]>=5.2.0` and `qis>=5.11.0`,
33
+ including PyArrow support required by the local Parquet-backed option-data examples.
34
+
35
+ ### Removed
36
+ - The legacy `dev` extra has been retired; contributor test dependencies now live in the
37
+ PEP 735 `test` dependency group.
38
+
7
39
  ## [2.2.0] - 2026-08-22
8
40
 
9
41
  ### Added
@@ -25,7 +25,6 @@ recursive-exclude examples *
25
25
  recursive-exclude papers *
26
26
  recursive-exclude docs *
27
27
  recursive-exclude resources *
28
- recursive-exclude volatility_book *
29
28
  recursive-exclude src/stochvolmodels/pde_solvers *
30
29
 
31
30
  global-exclude *.png
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stochvolmodels
3
- Version: 2.2.0
3
+ Version: 2.3.0
4
4
  Summary: Fourier-transform pricing, Monte Carlo validation, and calibration of European options under stochastic-volatility models in Python.
5
5
  Author-email: Artur Sepp <artursepp@gmail.com>
6
6
  Maintainer-email: Artur Sepp <artursepp@gmail.com>, Parviz Rakhmonov <ParvizRZ@gmail.com>
@@ -23,6 +23,7 @@ Classifier: Programming Language :: Python :: 3.10
23
23
  Classifier: Programming Language :: Python :: 3.11
24
24
  Classifier: Programming Language :: Python :: 3.12
25
25
  Classifier: Programming Language :: Python :: 3.13
26
+ Classifier: Programming Language :: Python :: 3.14
26
27
  Classifier: Topic :: Office/Business :: Financial :: Investment
27
28
  Classifier: Topic :: Scientific/Engineering :: Mathematics
28
29
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
@@ -37,8 +38,8 @@ Requires-Dist: pandas>=2.2.0
37
38
  Requires-Dist: matplotlib>=3.8.0
38
39
  Requires-Dist: seaborn>=0.13.0
39
40
  Provides-Extra: research
40
- Requires-Dist: option-chain-analytics>=5.0.0; extra == "research"
41
- Requires-Dist: qis>=3.5.7; extra == "research"
41
+ Requires-Dist: option-chain-analytics[cboe]>=5.2.0; extra == "research"
42
+ Requires-Dist: qis>=5.11.0; extra == "research"
42
43
  Provides-Extra: visualization
43
44
  Requires-Dist: plotly>=5.0.0; extra == "visualization"
44
45
  Provides-Extra: numerical
@@ -50,10 +51,6 @@ Requires-Dist: notebook>=6.5.0; extra == "jupyter"
50
51
  Requires-Dist: jupyterlab>=3.0.0; extra == "jupyter"
51
52
  Requires-Dist: ipykernel>=6.0.0; extra == "jupyter"
52
53
  Requires-Dist: ipywidgets>=8.0.0; extra == "jupyter"
53
- Provides-Extra: dev
54
- Requires-Dist: pytest>=7.0.0; extra == "dev"
55
- Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
56
- Requires-Dist: pytest-regressions>=2.8.3; extra == "dev"
57
54
  Provides-Extra: docs
58
55
  Requires-Dist: sphinx<10.0,>=8.0; extra == "docs"
59
56
  Requires-Dist: furo>=2024.8.6; extra == "docs"
@@ -64,22 +61,22 @@ Dynamic: license-file
64
61
 
65
62
  # StochVolModels (`stochvolmodels`)
66
63
 
67
- `stochvolmodels` provides Fourier-transform pricing, Monte Carlo validation, and calibration of
68
- European options under stochastic-volatility models in Python.
69
-
70
- It is a focused research and practitioner library, not a general derivatives platform: the stable
71
- workflows cover European vanilla and related variance analytics under Heston and the
72
- Karasinski-Sepp log-normal stochastic-volatility model.
73
-
74
64
  [![PyPI](https://img.shields.io/pypi/v/stochvolmodels?style=flat-square)](https://pypi.org/project/stochvolmodels/)
75
65
  [![Python](https://img.shields.io/pypi/pyversions/stochvolmodels?style=flat-square)](https://pypi.org/project/stochvolmodels/)
76
66
  [![License](https://img.shields.io/github/license/ArturSepp/StochVolModels.svg?style=flat-square)](LICENSE.txt)
77
- [![CI](https://github.com/ArturSepp/StochVolModels/actions/workflows/ci.yml/badge.svg)](https://github.com/ArturSepp/StochVolModels/actions)
78
- [![Documentation](https://readthedocs.org/projects/stochvolmodels/badge/?version=latest)](https://stochvolmodels.readthedocs.io/en/latest/)
67
+ [![CI](https://github.com/ArturSepp/StochVolModels/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/ArturSepp/StochVolModels/actions/workflows/ci.yml)
68
+ [![Docs](https://readthedocs.org/projects/stochvolmodels/badge/?version=latest)](https://stochvolmodels.readthedocs.io/en/latest/)
79
69
  [![Downloads](https://static.pepy.tech/badge/stochvolmodels)](https://pepy.tech/project/stochvolmodels)
80
70
  [![Monthly](https://static.pepy.tech/badge/stochvolmodels/month)](https://pepy.tech/project/stochvolmodels)
81
71
  [![Open LogSV quickstart in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/ArturSepp/StochVolModels/blob/main/examples/getting_started/quickstart_colab.ipynb)
82
72
 
73
+ `stochvolmodels` provides Fourier-transform pricing, Monte Carlo validation, and calibration of
74
+ European options under stochastic-volatility models in Python.
75
+
76
+ It is a focused research and practitioner library, not a general derivatives platform: the stable
77
+ workflows cover European vanilla and related variance analytics under Heston and the
78
+ Karasinski-Sepp log-normal stochastic-volatility model.
79
+
83
80
  **Paper:** Sepp, A. and Rakhmonov, P. (2023), *Log-normal stochastic volatility model with quadratic drift*, [International Journal of Theoretical and Applied Finance, 26(8)](https://www.worldscientific.com/doi/10.1142/S0219024924500031). See [Citation](#citation) for the full BibTeX list.
84
81
 
85
82
  **Documentation:** [stochvolmodels.readthedocs.io](https://stochvolmodels.readthedocs.io/en/latest/) ·
@@ -145,7 +142,7 @@ python -m build
145
142
  python scripts/check_wheel_contents.py dist/*.whl
146
143
  ```
147
144
 
148
- The v2.2.0 quickstart prints two five-strike slices and deterministic reference values including
145
+ The v2.3.0 quickstart prints two five-strike slices and deterministic reference values including
149
146
  `vanilla_price=0.197331` and `six_month_atm_price=0.275202`. The first call normally takes seconds
150
147
  because Numba compiles the numerical kernels. See the
151
148
  [full verification guide](https://stochvolmodels.readthedocs.io/en/latest/getting_started.html) and
@@ -166,7 +163,7 @@ because Numba compiles the numerical kernels. See the
166
163
 
167
164
  | Extra | Installs | Needed for |
168
165
  |---|---|---|
169
- | `research` | `qis >= 3.5.7`, `option-chain-analytics >= 5.0.0` | option-chain calibration and scripts in `papers/` |
166
+ | `research` | `qis >= 5.11.0`, `option-chain-analytics[cboe] >= 5.2.0` | option-chain calibration, local Parquet data, and scripts in `papers/` |
170
167
  | `visualization` | `plotly >= 5.0.0` | interactive figures |
171
168
  | `numerical` | `scikit-learn >= 1.3.0`, `statsmodels >= 0.14.0` | statistical fits |
172
169
  | `jupyter` | `jupyter`, `notebook`, `jupyterlab`, `ipykernel`, `ipywidgets` | notebooks |
@@ -340,7 +337,7 @@ normalized cache under its `cboe_options/` subdirectory, and request only the ob
340
337
  needed by the experiment:
341
338
 
342
339
  ```bash
343
- pip install "stochvolmodels[research]" "option-chain-analytics[cboe]>=5.0.0"
340
+ pip install "stochvolmodels[research]"
344
341
  ```
345
342
 
346
343
  ```python
@@ -676,7 +673,7 @@ If you use this package in your research, please cite the relevant papers:
676
673
  title={StochVolModels: Python Implementation of Stochastic Volatility Models},
677
674
  author={Sepp, Artur},
678
675
  year={2026},
679
- version={2.2.0},
676
+ version={2.3.0},
680
677
  howpublished={\url{https://github.com/ArturSepp/StochVolModels}},
681
678
  note={Python package for pricing analytics and Monte Carlo simulations}
682
679
  }
@@ -1,21 +1,21 @@
1
1
  # StochVolModels (`stochvolmodels`)
2
2
 
3
- `stochvolmodels` provides Fourier-transform pricing, Monte Carlo validation, and calibration of
4
- European options under stochastic-volatility models in Python.
5
-
6
- It is a focused research and practitioner library, not a general derivatives platform: the stable
7
- workflows cover European vanilla and related variance analytics under Heston and the
8
- Karasinski-Sepp log-normal stochastic-volatility model.
9
-
10
3
  [![PyPI](https://img.shields.io/pypi/v/stochvolmodels?style=flat-square)](https://pypi.org/project/stochvolmodels/)
11
4
  [![Python](https://img.shields.io/pypi/pyversions/stochvolmodels?style=flat-square)](https://pypi.org/project/stochvolmodels/)
12
5
  [![License](https://img.shields.io/github/license/ArturSepp/StochVolModels.svg?style=flat-square)](LICENSE.txt)
13
- [![CI](https://github.com/ArturSepp/StochVolModels/actions/workflows/ci.yml/badge.svg)](https://github.com/ArturSepp/StochVolModels/actions)
14
- [![Documentation](https://readthedocs.org/projects/stochvolmodels/badge/?version=latest)](https://stochvolmodels.readthedocs.io/en/latest/)
6
+ [![CI](https://github.com/ArturSepp/StochVolModels/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/ArturSepp/StochVolModels/actions/workflows/ci.yml)
7
+ [![Docs](https://readthedocs.org/projects/stochvolmodels/badge/?version=latest)](https://stochvolmodels.readthedocs.io/en/latest/)
15
8
  [![Downloads](https://static.pepy.tech/badge/stochvolmodels)](https://pepy.tech/project/stochvolmodels)
16
9
  [![Monthly](https://static.pepy.tech/badge/stochvolmodels/month)](https://pepy.tech/project/stochvolmodels)
17
10
  [![Open LogSV quickstart in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/ArturSepp/StochVolModels/blob/main/examples/getting_started/quickstart_colab.ipynb)
18
11
 
12
+ `stochvolmodels` provides Fourier-transform pricing, Monte Carlo validation, and calibration of
13
+ European options under stochastic-volatility models in Python.
14
+
15
+ It is a focused research and practitioner library, not a general derivatives platform: the stable
16
+ workflows cover European vanilla and related variance analytics under Heston and the
17
+ Karasinski-Sepp log-normal stochastic-volatility model.
18
+
19
19
  **Paper:** Sepp, A. and Rakhmonov, P. (2023), *Log-normal stochastic volatility model with quadratic drift*, [International Journal of Theoretical and Applied Finance, 26(8)](https://www.worldscientific.com/doi/10.1142/S0219024924500031). See [Citation](#citation) for the full BibTeX list.
20
20
 
21
21
  **Documentation:** [stochvolmodels.readthedocs.io](https://stochvolmodels.readthedocs.io/en/latest/) ·
@@ -81,7 +81,7 @@ python -m build
81
81
  python scripts/check_wheel_contents.py dist/*.whl
82
82
  ```
83
83
 
84
- The v2.2.0 quickstart prints two five-strike slices and deterministic reference values including
84
+ The v2.3.0 quickstart prints two five-strike slices and deterministic reference values including
85
85
  `vanilla_price=0.197331` and `six_month_atm_price=0.275202`. The first call normally takes seconds
86
86
  because Numba compiles the numerical kernels. See the
87
87
  [full verification guide](https://stochvolmodels.readthedocs.io/en/latest/getting_started.html) and
@@ -102,7 +102,7 @@ because Numba compiles the numerical kernels. See the
102
102
 
103
103
  | Extra | Installs | Needed for |
104
104
  |---|---|---|
105
- | `research` | `qis >= 3.5.7`, `option-chain-analytics >= 5.0.0` | option-chain calibration and scripts in `papers/` |
105
+ | `research` | `qis >= 5.11.0`, `option-chain-analytics[cboe] >= 5.2.0` | option-chain calibration, local Parquet data, and scripts in `papers/` |
106
106
  | `visualization` | `plotly >= 5.0.0` | interactive figures |
107
107
  | `numerical` | `scikit-learn >= 1.3.0`, `statsmodels >= 0.14.0` | statistical fits |
108
108
  | `jupyter` | `jupyter`, `notebook`, `jupyterlab`, `ipykernel`, `ipywidgets` | notebooks |
@@ -276,7 +276,7 @@ normalized cache under its `cboe_options/` subdirectory, and request only the ob
276
276
  needed by the experiment:
277
277
 
278
278
  ```bash
279
- pip install "stochvolmodels[research]" "option-chain-analytics[cboe]>=5.0.0"
279
+ pip install "stochvolmodels[research]"
280
280
  ```
281
281
 
282
282
  ```python
@@ -612,7 +612,7 @@ If you use this package in your research, please cite the relevant papers:
612
612
  title={StochVolModels: Python Implementation of Stochastic Volatility Models},
613
613
  author={Sepp, Artur},
614
614
  year={2026},
615
- version={2.2.0},
615
+ version={2.3.0},
616
616
  howpublished={\url{https://github.com/ArturSepp/StochVolModels}},
617
617
  note={Python package for pricing analytics and Monte Carlo simulations}
618
618
  }
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "stochvolmodels"
7
- version = "2.2.0"
7
+ version = "2.3.0"
8
8
  description = "Fourier-transform pricing, Monte Carlo validation, and calibration of European options under stochastic-volatility models in Python."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -40,6 +40,7 @@ classifiers = [
40
40
  "Programming Language :: Python :: 3.11",
41
41
  "Programming Language :: Python :: 3.12",
42
42
  "Programming Language :: Python :: 3.13",
43
+ "Programming Language :: Python :: 3.14",
43
44
  "Topic :: Office/Business :: Financial :: Investment",
44
45
  "Topic :: Scientific/Engineering :: Mathematics",
45
46
  "Topic :: Software Development :: Libraries :: Python Modules",
@@ -58,8 +59,8 @@ dependencies = [
58
59
 
59
60
  [project.optional-dependencies]
60
61
  research = [
61
- "option-chain-analytics>=5.0.0",
62
- "qis>=3.5.7",
62
+ "option-chain-analytics[cboe]>=5.2.0",
63
+ "qis>=5.11.0",
63
64
  ]
64
65
 
65
66
  visualization = [
@@ -79,12 +80,6 @@ jupyter = [
79
80
  "ipywidgets>=8.0.0",
80
81
  ]
81
82
 
82
- dev = [
83
- "pytest>=7.0.0",
84
- "pytest-cov>=4.0.0",
85
- "pytest-regressions>=2.8.3",
86
- ]
87
-
88
83
  docs = [
89
84
  "sphinx>=8.0,<10.0",
90
85
  "furo>=2024.8.6",
@@ -97,6 +92,11 @@ all = [
97
92
 
98
93
  [dependency-groups]
99
94
  # Contributor-only tools are exact so local and CI verdicts are reproducible.
95
+ test = [
96
+ "pytest>=7.0.0",
97
+ "pytest-cov>=4.0.0",
98
+ "pytest-regressions>=2.8.3",
99
+ ]
100
100
  lint = [
101
101
  "ruff==0.16.2",
102
102
  "interrogate==1.7.0",
@@ -12,32 +12,31 @@ import warnings
12
12
  from pathlib import Path
13
13
  from typing import Dict, Literal, Optional, Tuple
14
14
 
15
- import numpy as np
16
15
  import pandas as pd
17
- from numba.typed import List
18
16
 
19
17
  try:
20
- import qis as qis
21
18
  from option_chain_analytics import (
22
19
  OptionsDataDFs,
20
+ SlicesChain,
23
21
  create_chain_at_time,
22
+ create_chain_timeseries,
24
23
  )
25
24
  from option_chain_analytics.data.cboe import load_local_cboe_options_data
26
25
  from option_chain_analytics.data.tardis import (
27
26
  load_local_tardis_contract_ts_data,
28
27
  load_local_tardis_eod_options_data,
29
28
  )
30
- from option_chain_analytics.option_chain import SliceColumn, SlicesChain
31
29
  from qis import TimePeriod
32
30
  except ImportError as error:
33
31
  raise ImportError(
34
32
  "stochvolmodels.data.fetch_option_chain needs qis and option-chain-analytics: "
35
- 'pip install "stochvolmodels[research]" "option-chain-analytics[cboe]>=5.0.0"'
33
+ 'pip install "stochvolmodels[research]" "option-chain-analytics[cboe]>=5.2.0"'
36
34
  ) from error
37
35
 
38
36
  # stochvolmodels
39
37
  from stochvolmodels import local_path as lp
40
38
  from stochvolmodels.data.option_chain import OptionChain
39
+ from stochvolmodels.fitters.adapters.oca import option_chain_from_oca
41
40
 
42
41
 
43
42
  def _resolve_tardis_hourly_path(
@@ -345,74 +344,19 @@ def generate_vol_chain_np(chain: SlicesChain,
345
344
  delta_bounds: Tuple[Optional[float], Optional[float]] = (-0.1, 0.1),
346
345
  is_filtered: bool = True
347
346
  ) -> OptionChain:
348
- """Convert an OCA slices chain into SVM calibration inputs.
349
-
350
- Normalized OCA panels supply positive fitted discount factors. Historical
351
- hourly Tardis panels predate that column and retain their original unit-
352
- discount convention.
353
- """
354
-
355
- records = []
356
- seen_expiries = set()
357
- for label, day in days_map.items():
358
- next_date = value_time + pd.DateOffset(days=day)
359
- slice_date = chain.get_next_slice_after_date(mat_date=next_date)
360
- if slice_date in seen_expiries:
361
- continue
362
- slice_t = chain.expiry_slices[slice_date]
363
- df = slice_t.get_joint_slice(delta_bounds=delta_bounds, is_filtered=is_filtered)
364
- if not df.empty:
365
- if SliceColumn.DISCOUNT.value in df.columns:
366
- discounts = pd.to_numeric(
367
- df[SliceColumn.DISCOUNT.value], errors='coerce'
368
- ).to_numpy()
369
- discounts = discounts[np.isfinite(discounts) & (discounts > 0.0)]
370
- if discounts.size == 0:
371
- raise ValueError(f"missing positive discount factor for {slice_t.expiry_id}")
372
- discfactor = float(np.median(discounts))
373
- else:
374
- discfactor = 1.0
375
- records.append(
376
- {
377
- 'id': f"{label}: {slice_t.expiry_id}",
378
- 'ttm': slice_t.get_ttm(),
379
- 'forward': slice_t.get_future_price(),
380
- 'discfactor': discfactor,
381
- 'strikes': df.index.to_numpy(),
382
- 'optiontypes': df[SliceColumn.OPTION_TYPE].to_numpy(dtype=str),
383
- 'bid_ivs': df[SliceColumn.BID_IV].to_numpy(),
384
- 'ask_ivs': df[SliceColumn.ASK_IV].to_numpy(),
385
- 'bid_prices': df[SliceColumn.BID_PRICE].to_numpy(),
386
- 'ask_prices': df[SliceColumn.ASK_PRICE].to_numpy(),
387
- }
388
- )
389
- seen_expiries.add(slice_date)
390
-
391
- if not records:
392
- raise ValueError("no non-empty OCA maturity slices matched days_map")
393
- records.sort(key=lambda record: record['ttm'])
394
- strikes_ttms, optiontypes_ttms = List(), List()
395
- bid_ivs, ask_ivs = List(), List()
396
- bid_prices, ask_prices = List(), List()
397
- for record in records:
398
- strikes_ttms.append(record['strikes'])
399
- optiontypes_ttms.append(record['optiontypes'])
400
- bid_ivs.append(record['bid_ivs'])
401
- ask_ivs.append(record['ask_ivs'])
402
- bid_prices.append(record['bid_prices'])
403
- ask_prices.append(record['ask_prices'])
404
-
405
- return OptionChain(
406
- ttms=np.array([record['ttm'] for record in records]),
407
- forwards=np.array([record['forward'] for record in records]),
408
- discfactors=np.array([record['discfactor'] for record in records]),
409
- ids=np.array([record['id'] for record in records]),
410
- strikes_ttms=strikes_ttms,
411
- optiontypes_ttms=optiontypes_ttms,
412
- bid_ivs=bid_ivs,
413
- ask_ivs=ask_ivs,
414
- bid_prices=bid_prices,
415
- ask_prices=ask_prices,
347
+ """Compatibility wrapper for :func:`option_chain_from_oca`."""
348
+ warnings.warn(
349
+ 'generate_vol_chain_np moved to '
350
+ 'stochvolmodels.fitters.adapters.oca.option_chain_from_oca',
351
+ DeprecationWarning,
352
+ stacklevel=2,
353
+ )
354
+ return option_chain_from_oca(
355
+ chain=chain,
356
+ value_time=value_time,
357
+ days_map=days_map,
358
+ delta_bounds=delta_bounds,
359
+ is_filtered=is_filtered,
416
360
  )
417
361
 
418
362
 
@@ -430,16 +374,14 @@ def load_option_chain(options_data_dfs: OptionsDataDFs,
430
374
  value_time=value_time,
431
375
  time_selection='previous',
432
376
  )
433
- if chain is not None:
434
- option_chain = generate_vol_chain_np(chain=chain,
435
- value_time=chain.value_time,
436
- days_map=days_map,
437
- delta_bounds=delta_bounds,
438
- is_filtered=is_filtered)
439
- else:
440
- option_chain = None
441
-
442
- return option_chain
377
+ if chain is None:
378
+ return None
379
+ return option_chain_from_oca(
380
+ chain=chain,
381
+ days_map=days_map,
382
+ delta_bounds=delta_bounds,
383
+ is_filtered=is_filtered,
384
+ )
443
385
 
444
386
 
445
387
  def sample_option_chain_at_times(options_data_dfs: OptionsDataDFs,
@@ -452,32 +394,45 @@ def sample_option_chain_at_times(options_data_dfs: OptionsDataDFs,
452
394
  ),
453
395
  hour_offset: int = 8
454
396
  ) -> Dict[pd.Timestamp, OptionChain]:
455
- """
456
- extract chains at a sequence of observation times, for time series calibration.
457
- """
458
- value_times = qis.generate_dates_schedule(time_period=time_period,
459
- freq=freq,
460
- hour_offset=hour_offset)
461
- option_chains = {}
462
- for value_time in value_times:
463
- option_chains[value_time] = load_option_chain(options_data_dfs=options_data_dfs,
464
- value_time=value_time,
465
- days_map=days_map,
466
- delta_bounds=delta_bounds,
467
- is_filtered=True)
468
- return option_chains
397
+ """Compatibility workflow using OCA-owned observation-frequency sampling."""
398
+ warnings.warn(
399
+ 'frequency sampling is owned by OptionChainAnalytics.create_chain_timeseries; '
400
+ 'map its results with stochvolmodels.fitters.adapters.oca.option_chain_from_oca',
401
+ DeprecationWarning,
402
+ stacklevel=2,
403
+ )
404
+ chains = create_chain_timeseries(
405
+ options_data=options_data_dfs,
406
+ time_period=time_period,
407
+ freq=freq,
408
+ hour_offset=hour_offset,
409
+ time_selection='previous',
410
+ )
411
+ return {
412
+ value_time: option_chain_from_oca(
413
+ chain=chain,
414
+ days_map=days_map,
415
+ delta_bounds=delta_bounds,
416
+ is_filtered=True,
417
+ )
418
+ for value_time, chain in chains.items()
419
+ }
469
420
 
470
421
 
471
422
  def load_price_data(options_data_dfs: OptionsDataDFs,
472
423
  time_period: TimePeriod = None,
473
424
  data: Literal['close', 'perp', 'funding_rate'] = 'close',
474
- freq: Optional[str] = 'D' # to do
425
+ freq: Optional[str] = 'D'
475
426
  ) -> pd.Series:
476
- # options_data_dfs can also come from ts_data_loader_wrapper for legacy local sources.
477
- """load the underlying price series accompanying the options data."""
478
- spot_price = options_data_dfs.get_spot_data()[data]
479
- if freq is not None:
480
- spot_price = spot_price.resample(freq).last()
481
- if time_period is not None:
482
- spot_price = time_period.locate(spot_price)
483
- return spot_price
427
+ """Compatibility wrapper for OCA's chain-linked underlying-data loader."""
428
+ warnings.warn(
429
+ 'load_price_data moved to OptionChainAnalytics chain data: '
430
+ 'options_data_dfs.load_price_data(...)',
431
+ DeprecationWarning,
432
+ stacklevel=2,
433
+ )
434
+ return options_data_dfs.load_price_data(
435
+ time_period=time_period,
436
+ data=data,
437
+ freq=freq,
438
+ )
@@ -0,0 +1,71 @@
1
+ """Statistical estimators used with stochastic-volatility models."""
2
+
3
+ from stochvolmodels.estimation.forecasting import (
4
+ CALENDAR_1D,
5
+ CALENDAR_1M,
6
+ CALENDAR_1W,
7
+ CALENDAR_HORIZONS,
8
+ TRADING_1D,
9
+ TRADING_1M,
10
+ TRADING_1W,
11
+ TRADING_HORIZONS,
12
+ FeatureSpace,
13
+ ForecastHorizon,
14
+ ForecastSpace,
15
+ VolatilityForecastModel,
16
+ VolForecastComparison,
17
+ VolForecastConfig,
18
+ VolForecastEvaluation,
19
+ VolForecastFit,
20
+ VolForecastPrediction,
21
+ VolForecastResult,
22
+ build_volatility_features,
23
+ compare_volatility_forecasts,
24
+ evaluate_volatility_forecast,
25
+ fit_volatility_forecaster,
26
+ predict_volatility_forecaster,
27
+ walk_forward_volatility_forecast,
28
+ )
29
+ from stochvolmodels.estimation.ohlc import (
30
+ OhlcEstimatorType,
31
+ estimate_hf_ohlc_vol,
32
+ estimate_ohlc_var,
33
+ estimate_ohlc_variances,
34
+ )
35
+ from stochvolmodels.estimation.realized_volatility import (
36
+ make_forward_variance_target,
37
+ make_forward_volatility_target,
38
+ )
39
+
40
+ __all__ = [
41
+ "CALENDAR_1D",
42
+ "CALENDAR_1M",
43
+ "CALENDAR_1W",
44
+ "CALENDAR_HORIZONS",
45
+ "FeatureSpace",
46
+ "ForecastSpace",
47
+ "ForecastHorizon",
48
+ "OhlcEstimatorType",
49
+ "TRADING_1D",
50
+ "TRADING_1M",
51
+ "TRADING_1W",
52
+ "TRADING_HORIZONS",
53
+ "VolForecastConfig",
54
+ "VolForecastComparison",
55
+ "VolForecastEvaluation",
56
+ "VolForecastFit",
57
+ "VolForecastPrediction",
58
+ "VolForecastResult",
59
+ "VolatilityForecastModel",
60
+ "build_volatility_features",
61
+ "compare_volatility_forecasts",
62
+ "estimate_hf_ohlc_vol",
63
+ "estimate_ohlc_var",
64
+ "estimate_ohlc_variances",
65
+ "evaluate_volatility_forecast",
66
+ "fit_volatility_forecaster",
67
+ "make_forward_variance_target",
68
+ "make_forward_volatility_target",
69
+ "predict_volatility_forecaster",
70
+ "walk_forward_volatility_forecast",
71
+ ]
@@ -0,0 +1,63 @@
1
+ """Point-in-time feature construction and volatility forecasting contracts."""
2
+
3
+ from stochvolmodels.estimation.forecasting.features import (
4
+ FeatureSpace,
5
+ build_volatility_features,
6
+ )
7
+ from stochvolmodels.estimation.forecasting.horizons import (
8
+ CALENDAR_1D,
9
+ CALENDAR_1M,
10
+ CALENDAR_1W,
11
+ CALENDAR_HORIZONS,
12
+ TRADING_1D,
13
+ TRADING_1M,
14
+ TRADING_1W,
15
+ TRADING_HORIZONS,
16
+ ForecastHorizon,
17
+ )
18
+ from stochvolmodels.estimation.forecasting.models import (
19
+ fit_volatility_forecaster,
20
+ predict_volatility_forecaster,
21
+ )
22
+ from stochvolmodels.estimation.forecasting.results import (
23
+ ForecastSpace,
24
+ VolatilityForecastModel,
25
+ VolForecastComparison,
26
+ VolForecastConfig,
27
+ VolForecastEvaluation,
28
+ VolForecastFit,
29
+ VolForecastPrediction,
30
+ VolForecastResult,
31
+ compare_volatility_forecasts,
32
+ evaluate_volatility_forecast,
33
+ )
34
+ from stochvolmodels.estimation.forecasting.walk_forward import (
35
+ walk_forward_volatility_forecast,
36
+ )
37
+
38
+ __all__ = [
39
+ "CALENDAR_1D",
40
+ "CALENDAR_1M",
41
+ "CALENDAR_1W",
42
+ "CALENDAR_HORIZONS",
43
+ "FeatureSpace",
44
+ "ForecastSpace",
45
+ "ForecastHorizon",
46
+ "TRADING_1D",
47
+ "TRADING_1M",
48
+ "TRADING_1W",
49
+ "TRADING_HORIZONS",
50
+ "VolForecastConfig",
51
+ "VolForecastComparison",
52
+ "VolForecastEvaluation",
53
+ "VolForecastFit",
54
+ "VolForecastPrediction",
55
+ "VolForecastResult",
56
+ "VolatilityForecastModel",
57
+ "build_volatility_features",
58
+ "fit_volatility_forecaster",
59
+ "predict_volatility_forecaster",
60
+ "compare_volatility_forecasts",
61
+ "evaluate_volatility_forecast",
62
+ "walk_forward_volatility_forecast",
63
+ ]