quantflow 0.6.2__tar.gz → 0.6.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.
- {quantflow-0.6.2 → quantflow-0.6.3}/.github/copilot-instructions.md +7 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/.vscode/launch.json +1 -1
- {quantflow-0.6.2 → quantflow-0.6.3}/Makefile +4 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/PKG-INFO +2 -1
- {quantflow-0.6.2 → quantflow-0.6.3}/app/gaussian_sampling.py +1 -1
- quantflow-0.6.3/app/heston_divfm_fit.py +276 -0
- quantflow-0.6.3/app/heston_vol_surface.py +165 -0
- quantflow-0.6.3/app/scripts/heston_divfm_fit.py +208 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/app/volatility_surface.py +21 -32
- quantflow-0.6.3/docs/api/data/index.md +33 -0
- quantflow-0.6.3/docs/api/index.md +71 -0
- quantflow-0.6.3/docs/api/options/divfm.md +30 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/options/pricer.md +1 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/options/vol_surface.md +3 -1
- quantflow-0.6.3/docs/api/sp/copula.md +10 -0
- quantflow-0.6.3/docs/assets/heston_calibrated_smile.png +0 -0
- quantflow-0.6.3/docs/assets/hestonj_calibrated_smile.png +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/bibliography.md +8 -0
- quantflow-0.6.3/docs/examples/vol_surface_heston_calibration.py +33 -0
- quantflow-0.6.3/docs/examples/vol_surface_hestonj_calibration.py +46 -0
- quantflow-0.6.3/docs/examples/vol_surface_inputs.py +24 -0
- quantflow-0.6.3/docs/examples_png/vol_surface_heston_plot.py +35 -0
- quantflow-0.6.3/docs/examples_png/vol_surface_hestonj_plot.py +46 -0
- quantflow-0.6.3/docs/glossary.md +110 -0
- quantflow-0.6.3/docs/tutorials/index.md +8 -0
- quantflow-0.6.3/docs/tutorials/volatility_surface.md +185 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/mkdocs.yml +5 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/pyproject.toml +2 -1
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/data/deribit.py +25 -3
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/options/calibration.py +48 -6
- quantflow-0.6.3/quantflow/options/divfm/__init__.py +4 -0
- quantflow-0.6.3/quantflow/options/divfm/network.py +210 -0
- quantflow-0.6.3/quantflow/options/divfm/pricer.py +137 -0
- quantflow-0.6.3/quantflow/options/divfm/trainer.py +181 -0
- quantflow-0.6.3/quantflow/options/divfm/weights.py +154 -0
- quantflow-0.6.3/quantflow/options/docs/butterfly.md +44 -0
- quantflow-0.6.3/quantflow/options/docs/calendar_spread.md +47 -0
- quantflow-0.6.3/quantflow/options/docs/spread.md +36 -0
- quantflow-0.6.3/quantflow/options/docs/straddle.md +22 -0
- quantflow-0.6.3/quantflow/options/docs/strangle.md +23 -0
- quantflow-0.6.3/quantflow/options/docs/terminology.md +5 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/options/pricer.py +56 -25
- quantflow-0.6.3/quantflow/options/strategies/__init__.py +17 -0
- quantflow-0.6.3/quantflow/options/strategies/base.py +111 -0
- quantflow-0.6.3/quantflow/options/strategies/butterfly.py +100 -0
- quantflow-0.6.3/quantflow/options/strategies/calendar_spread.py +75 -0
- quantflow-0.6.3/quantflow/options/strategies/spread.py +73 -0
- quantflow-0.6.3/quantflow/options/strategies/straddle.py +39 -0
- quantflow-0.6.3/quantflow/options/strategies/strangle.py +68 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/options/surface.py +10 -2
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/base.py +7 -5
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/copula.py +7 -6
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/heston.py +6 -2
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/ou.py +0 -2
- quantflow-0.6.3/quantflow/utils/__init__.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/distributions.py +8 -7
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/plot.py +10 -2
- quantflow-0.6.3/quantflow_tests/fixtures/deribit_futures.json +23 -0
- quantflow-0.6.3/quantflow_tests/fixtures/deribit_instruments.json +48 -0
- quantflow-0.6.3/quantflow_tests/fixtures/deribit_options.json +30 -0
- quantflow-0.6.3/quantflow_tests/test_data_deribit.py +84 -0
- quantflow-0.6.3/quantflow_tests/test_divfm.py +311 -0
- quantflow-0.6.3/quantflow_tests/test_strategies.py +109 -0
- quantflow-0.6.3/quantflow_tests/volsurface.json +4359 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/uv.lock +204 -36
- quantflow-0.6.2/docs/api/data/index.md +0 -8
- quantflow-0.6.2/docs/api/index.md +0 -3
- quantflow-0.6.2/notebooks/CNAME +0 -1
- quantflow-0.6.2/notebooks/_config.yml +0 -65
- quantflow-0.6.2/notebooks/_toc.yml +0 -46
- quantflow-0.6.2/notebooks/applications/hurst.md +0 -202
- quantflow-0.6.2/notebooks/applications/overview.md +0 -23
- quantflow-0.6.2/notebooks/applications/sampling.md +0 -35
- quantflow-0.6.2/notebooks/conf.py +0 -38
- quantflow-0.6.2/notebooks/examples/heston_vol_surface.md +0 -54
- quantflow-0.6.2/notebooks/index.md +0 -54
- quantflow-0.6.2/notebooks/reference/biblio.md +0 -18
- quantflow-0.6.2/notebooks/reference/contributing.md +0 -68
- quantflow-0.6.2/notebooks/reference/glossary.md +0 -80
- {quantflow-0.6.2 → quantflow-0.6.3}/.coveragerc +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/.dockerignore +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/.github/workflows/build.yml +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/.github/workflows/deploy.yml +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/.github/workflows/docker-multiarch.yml +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/.gitignore +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/.vscode/settings.json +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/.vscode/tasks.json +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/CITATION.cff +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/CLAUDE.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/LICENSE +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/app/__main__.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/app/cointegration.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/app/double_exponential_sampling.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/app/hurst.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/app/poisson_sampling.py +0 -0
- {quantflow-0.6.2/quantflow/ai/tools → quantflow-0.6.3/app/scripts}/__init__.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/app/supersmoother.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/app/utils/__init__.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/blocks/quantflow.yaml +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/build-examples +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/charts.yaml +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/.helmignore +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/Chart.yaml +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/templates/_helpers.tpl +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/templates/_service.tpl +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/templates/app.yaml +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/templates/configmap.yaml +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/templates/secret.yaml +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/values.yaml +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/install +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/lint +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/marimo +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/quantflow.dockerfile +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/dev/test +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/data/deribit.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/data/fed.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/data/fmp.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/data/fred.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/options/black.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/options/calibration.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/options/index.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/cir.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/compound_poisson.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/dsp.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/heston.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/index.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/jump_diffusion.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/ou.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/poisson.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/weiner.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/ta/ewma.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/ta/index.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/ta/kalman.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/ta/ohlc.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/ta/paths.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/ta/supersmoother.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/utils/bins.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/utils/distributions.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/utils/index.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/utils/marginal1d.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/utils/numbers.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/utils/types.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/assets/heston.gif +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/assets/linkedin-banner.png +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/assets/quantflow-light.svg +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/assets/quantflow-logo.png +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/assets/quantflow-repo.png +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/assets/quantflow-repo.svg +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/assets/quantflow.svg +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/contributing.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/examples/heston_volatility_pricer.py +0 -0
- {quantflow-0.6.2/quantflow_tests → quantflow-0.6.3/docs/examples}/volsurface.json +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/examples/weiner_volatility_pricer.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/index.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/javascripts/mathjax.js +0 -0
- {quantflow-0.6.2/notebooks/reference → quantflow-0.6.3/docs}/references.bib +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/theory/characteristic.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/theory/index.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/theory/inversion.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/theory/levy.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/theory/option_pricing.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/docs/tutorials/option_pricing.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/applications/calibration.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/applications/calibration.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/applications/volatility_surface.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/data/fed.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/data/fiscal_data.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/data/fmp.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/data/timeseries.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/bns.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/cir.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/gousv.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/heston.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/heston_jumps.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/jump_diffusion.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/ou.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/overview.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/poisson.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/weiner.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/__init__.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/__init__.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/server.py +0 -0
- {quantflow-0.6.2/quantflow/data → quantflow-0.6.3/quantflow/ai/tools}/__init__.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/tools/base.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/tools/charts.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/tools/crypto.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/tools/fred.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/tools/stocks.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/tools/vault.py +0 -0
- {quantflow-0.6.2/quantflow/options → quantflow-0.6.3/quantflow/data}/__init__.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/data/fed.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/data/fiscal_data.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/data/fmp.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/data/fred.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/data/vault.py +0 -0
- {quantflow-0.6.2/quantflow/sp → quantflow-0.6.3/quantflow/options}/__init__.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/options/bs.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/options/inputs.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/py.typed +0 -0
- {quantflow-0.6.2/quantflow/utils → quantflow-0.6.3/quantflow/sp}/__init__.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/bns.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/cir.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/dsp.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/jump_diffusion.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/poisson.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/weiner.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ta/__init__.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ta/base.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ta/ewma.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ta/kalman.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ta/ohlc.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ta/paths.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ta/supersmoother.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/bins.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/dates.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/functions.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/interest_rates.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/marginal.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/numbers.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/transforms.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/types.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/conftest.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_ai.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_cir.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_copula.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_data.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_distributions.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_frft.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_heston.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_jump_diffusion.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_ohlc.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_options.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_options_pricer.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_ou.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_poisson.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_utils.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_vault.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_weiner.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/utils.py +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/readme.md +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/rops.toml +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/taplo.toml +0 -0
- {quantflow-0.6.2 → quantflow-0.6.3}/test_comparison.py +0 -0
|
@@ -12,6 +12,7 @@ applyTo: '/**'
|
|
|
12
12
|
|
|
13
13
|
* Always run `make lint` after code changes — runs taplo, isort, black, ruff, and mypy
|
|
14
14
|
* Never edit `readme.md` directly — it is generated from `docs/index.md` via `make docs`
|
|
15
|
+
* To install all dependencies (including all optional extras) run `make install-dev` — runs `uv sync --all-extras`
|
|
15
16
|
* To run all tests use `make test` — runs all tests in the `tests/` directory using pytest
|
|
16
17
|
* To run a specific test file, use `uv run pytest tests/path/to/test_file.py`
|
|
17
18
|
|
|
@@ -28,4 +29,10 @@ applyTo: '/**'
|
|
|
28
29
|
* Documentation is built using [mkdocs](https://www.mkdocs.org/) and stored in the `docs/` directory. The documentation source files are written in markdown format.
|
|
29
30
|
* Do not use em dashes (—) in documentation files or docstrings. Use colons, parentheses, or restructure the sentence instead.
|
|
30
31
|
* Math in documentation and docstrings uses `$...$` for inline and `$$...$$` or `\begin{equation}...\end{equation}` for block equations. Do not use `.. math::` or `:math:` (RST syntax).
|
|
32
|
+
* Glossary entries in `docs/glossary.md` must be kept in alphabetical order.
|
|
31
33
|
* To rebuild doc examples run `uv run ./dev/build-examples` — runs all scripts in `docs/examples/` and writes their output to `docs/examples_output/`
|
|
34
|
+
|
|
35
|
+
## Package structure
|
|
36
|
+
|
|
37
|
+
* Strategy runtime markdown descriptions (read by `load_description()` at runtime) live inside the package at `quantflow/options/strategies/docs/` — they must be inside the package to be accessible when the library is installed
|
|
38
|
+
* mkdocs documentation pages live in `docs/api/options/` — do not mix these two locations
|
|
@@ -24,6 +24,10 @@ install-dev: ## Install development dependencies
|
|
|
24
24
|
marimo: ## Run marimo for editing notebooks
|
|
25
25
|
@./dev/marimo edit
|
|
26
26
|
|
|
27
|
+
.PHONY: docs-png
|
|
28
|
+
docs-png: ## Regenerate PNG assets in docs/assets/ (requires Chrome via kaleido)
|
|
29
|
+
@for f in docs/examples_png/*.py; do uv run python $$f; done
|
|
30
|
+
|
|
27
31
|
.PHONY: docs
|
|
28
32
|
docs: ## build documentation
|
|
29
33
|
@cp docs/index.md readme.md
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quantflow
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
4
4
|
Summary: quantitative analysis
|
|
5
5
|
Project-URL: Homepage, https://github.com/quantmind/quantflow
|
|
6
6
|
Project-URL: Repository, https://github.com/quantmind/quantflow
|
|
@@ -45,6 +45,7 @@ Requires-Dist: types-python-dateutil>=2.9.0.20251115; extra == 'dev'
|
|
|
45
45
|
Provides-Extra: docs
|
|
46
46
|
Requires-Dist: griffe-pydantic>=1.1.0; extra == 'docs'
|
|
47
47
|
Requires-Dist: griffe-typingdoc>=0.2.7; extra == 'docs'
|
|
48
|
+
Requires-Dist: kaleido>=1.2.0; extra == 'docs'
|
|
48
49
|
Requires-Dist: mkdocs-macros-plugin>=1.3.7; extra == 'docs'
|
|
49
50
|
Requires-Dist: mkdocs-material>=9.7.0; extra == 'docs'
|
|
50
51
|
Requires-Dist: mkdocs-redirects>=1.2.1; extra == 'docs'
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import marimo
|
|
2
|
+
|
|
3
|
+
__generated_with = "0.22.0"
|
|
4
|
+
app = marimo.App(width="medium")
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@app.cell
|
|
8
|
+
def _():
|
|
9
|
+
import marimo as mo
|
|
10
|
+
from app.utils import nav_menu
|
|
11
|
+
nav_menu()
|
|
12
|
+
return (mo,)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@app.cell(hide_code=True)
|
|
16
|
+
def _(mo):
|
|
17
|
+
mo.md(r"""
|
|
18
|
+
# Deep Implied Volatility Factor Model
|
|
19
|
+
""")
|
|
20
|
+
return
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@app.cell
|
|
24
|
+
def _():
|
|
25
|
+
import numpy as np
|
|
26
|
+
import torch
|
|
27
|
+
|
|
28
|
+
from quantflow.options.divfm.network import DIVFMNetwork
|
|
29
|
+
from quantflow.options.divfm.trainer import DayData, DIVFMTrainer
|
|
30
|
+
from quantflow.options.pricer import OptionPricer
|
|
31
|
+
from quantflow.sp.heston import HestonJ
|
|
32
|
+
from quantflow.utils.distributions import DoubleExponential
|
|
33
|
+
|
|
34
|
+
# ---------------------------------------------------------------------------
|
|
35
|
+
# Grid settings
|
|
36
|
+
# ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
TTM_GRID = [0.1, 0.25, 0.5, 1.0, 2.0]
|
|
39
|
+
MAX_MONEYNESS_TTM = 1.5 # moneyness_ttm range for sampling and pricing
|
|
40
|
+
N_PER_TTM = 20 # random options sampled per TTM per day
|
|
41
|
+
|
|
42
|
+
# ---------------------------------------------------------------------------
|
|
43
|
+
# HestonJ parameter ranges (uniform sampling)
|
|
44
|
+
# ---------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
PARAM_RANGES = {
|
|
47
|
+
"vol": (0.10, 0.70),
|
|
48
|
+
"rho": (-0.80, 0.10),
|
|
49
|
+
"kappa": (0.50, 5.00),
|
|
50
|
+
"sigma": (0.20, 1.50),
|
|
51
|
+
"jump_fraction": (0.1, 0.50),
|
|
52
|
+
"jump_asymmetry": (-0.50, 0.50),
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# ---------------------------------------------------------------------------
|
|
57
|
+
# Fixture generation
|
|
58
|
+
# ---------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _make_pricer(rng: np.random.Generator) -> OptionPricer:
|
|
62
|
+
"""Sample a random HestonJ parameter set and return a ready pricer."""
|
|
63
|
+
vol = float(rng.uniform(*PARAM_RANGES["vol"]))
|
|
64
|
+
rho = float(rng.uniform(*PARAM_RANGES["rho"]))
|
|
65
|
+
kappa = float(rng.uniform(*PARAM_RANGES["kappa"]))
|
|
66
|
+
sigma = float(rng.uniform(*PARAM_RANGES["sigma"]))
|
|
67
|
+
jump_fraction = float(rng.uniform(*PARAM_RANGES["jump_fraction"]))
|
|
68
|
+
jump_asymmetry = float(rng.uniform(*PARAM_RANGES["jump_asymmetry"]))
|
|
69
|
+
sv = sigma/vol
|
|
70
|
+
kappa = max(kappa, 0.6*sv*sv)
|
|
71
|
+
|
|
72
|
+
model = HestonJ.create(
|
|
73
|
+
DoubleExponential,
|
|
74
|
+
vol=vol,
|
|
75
|
+
kappa=kappa,
|
|
76
|
+
rho=rho,
|
|
77
|
+
sigma=sigma,
|
|
78
|
+
jump_fraction=jump_fraction,
|
|
79
|
+
jump_asymmetry=jump_asymmetry,
|
|
80
|
+
)
|
|
81
|
+
return OptionPricer(model=model, max_moneyness_ttm=MAX_MONEYNESS_TTM)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _sample_day(rng: np.random.Generator, pricer: OptionPricer) -> DayData | None:
|
|
85
|
+
"""Price options at random (moneyness_ttm, ttm) points and return DayData.
|
|
86
|
+
|
|
87
|
+
Returns None if all points are invalid (e.g. numerical pricing failure).
|
|
88
|
+
"""
|
|
89
|
+
m_list: list[np.ndarray] = []
|
|
90
|
+
t_list: list[np.ndarray] = []
|
|
91
|
+
iv_list: list[np.ndarray] = []
|
|
92
|
+
|
|
93
|
+
for ttm in TTM_GRID:
|
|
94
|
+
mat = pricer.maturity(ttm)
|
|
95
|
+
m_ttm = rng.uniform(-MAX_MONEYNESS_TTM, MAX_MONEYNESS_TTM, N_PER_TTM).astype(
|
|
96
|
+
np.float32
|
|
97
|
+
)
|
|
98
|
+
moneyness = m_ttm * np.sqrt(ttm)
|
|
99
|
+
ivs = np.interp(moneyness, mat.moneyness, mat.implied_vols)
|
|
100
|
+
|
|
101
|
+
# drop any degenerate points (NaN / non-positive IV)
|
|
102
|
+
valid = np.isfinite(ivs) & (ivs > 0)
|
|
103
|
+
if not valid.any():
|
|
104
|
+
continue
|
|
105
|
+
|
|
106
|
+
m_list.append(m_ttm[valid])
|
|
107
|
+
t_list.append(np.full(valid.sum(), ttm, dtype=np.float32))
|
|
108
|
+
iv_list.append(ivs[valid].astype(np.float64))
|
|
109
|
+
|
|
110
|
+
if not m_list:
|
|
111
|
+
return None
|
|
112
|
+
|
|
113
|
+
return DayData(
|
|
114
|
+
moneyness_ttm=np.concatenate(m_list),
|
|
115
|
+
ttm=np.concatenate(t_list),
|
|
116
|
+
implied_vols=np.concatenate(iv_list),
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def generate_fixtures(
|
|
121
|
+
num_days: int = 300,
|
|
122
|
+
seed: int = 42,
|
|
123
|
+
verbose: bool = True,
|
|
124
|
+
) -> list[DayData]:
|
|
125
|
+
"""Generate *num_days* synthetic IV days from random HestonJ parameters.
|
|
126
|
+
|
|
127
|
+
Each day is a different random parameter set, giving the DIVFM model a
|
|
128
|
+
diverse training distribution that covers varying vol levels, skews, and
|
|
129
|
+
term structures.
|
|
130
|
+
"""
|
|
131
|
+
rng = np.random.default_rng(seed)
|
|
132
|
+
days: list[DayData] = []
|
|
133
|
+
skipped = 0
|
|
134
|
+
|
|
135
|
+
for i in range(num_days):
|
|
136
|
+
pricer = _make_pricer(rng)
|
|
137
|
+
day = _sample_day(rng, pricer)
|
|
138
|
+
if day is None:
|
|
139
|
+
skipped += 1
|
|
140
|
+
else:
|
|
141
|
+
days.append(day)
|
|
142
|
+
|
|
143
|
+
if verbose and (i + 1) % 50 == 0:
|
|
144
|
+
print(f" generated {i + 1}/{num_days} parameter sets ({len(days)} valid)")
|
|
145
|
+
|
|
146
|
+
if verbose:
|
|
147
|
+
print(f"Fixture generation done: {len(days)} valid days, {skipped} skipped")
|
|
148
|
+
|
|
149
|
+
return days
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def fit_divfm(
|
|
153
|
+
days: list[DayData],
|
|
154
|
+
num_factors: int = 5,
|
|
155
|
+
hidden_size: int = 32,
|
|
156
|
+
num_hidden_layers: int = 3,
|
|
157
|
+
lr: float = 1e-3,
|
|
158
|
+
batch_days: int = 32,
|
|
159
|
+
num_steps: int = 500,
|
|
160
|
+
val_fraction: float = 0.1,
|
|
161
|
+
seed: int = 0,
|
|
162
|
+
log_every: int = 50,
|
|
163
|
+
) -> tuple[DIVFMNetwork, list[float]]:
|
|
164
|
+
"""Train a DIVFMNetwork on the given days.
|
|
165
|
+
|
|
166
|
+
Splits days into train/val, trains the network, and returns the trained
|
|
167
|
+
network together with the per-step training losses.
|
|
168
|
+
"""
|
|
169
|
+
torch.manual_seed(seed)
|
|
170
|
+
|
|
171
|
+
n_val = max(1, int(len(days) * val_fraction))
|
|
172
|
+
train_days = days[n_val:]
|
|
173
|
+
val_days = days[:n_val]
|
|
174
|
+
|
|
175
|
+
net = DIVFMNetwork(
|
|
176
|
+
num_factors=num_factors,
|
|
177
|
+
hidden_size=hidden_size,
|
|
178
|
+
num_hidden_layers=num_hidden_layers,
|
|
179
|
+
)
|
|
180
|
+
trainer = DIVFMTrainer(net, lr=lr, batch_days=batch_days)
|
|
181
|
+
|
|
182
|
+
print(
|
|
183
|
+
f"Training DIVFM factors={num_factors} hidden={hidden_size}"
|
|
184
|
+
f" layers={num_hidden_layers} lr={lr}"
|
|
185
|
+
f" batch_days={batch_days} steps={num_steps}"
|
|
186
|
+
)
|
|
187
|
+
print(f" train days: {len(train_days)} val days: {len(val_days)}")
|
|
188
|
+
|
|
189
|
+
losses = trainer.fit(
|
|
190
|
+
train_days,
|
|
191
|
+
num_steps=num_steps,
|
|
192
|
+
val_days=val_days,
|
|
193
|
+
log_every=log_every,
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
val_loss = trainer.evaluate(val_days)
|
|
197
|
+
print(f"Final val loss: {val_loss:.6f}")
|
|
198
|
+
|
|
199
|
+
return net, losses
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
return fit_divfm, generate_fixtures, np, torch
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
@app.cell
|
|
206
|
+
def _(generate_fixtures):
|
|
207
|
+
days = generate_fixtures(num_days=300, seed=42)
|
|
208
|
+
return (days,)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
@app.cell
|
|
212
|
+
def _(days, fit_divfm):
|
|
213
|
+
net, losses = fit_divfm(days, num_steps=500, log_every=50)
|
|
214
|
+
return (net,)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
@app.cell
|
|
218
|
+
def _():
|
|
219
|
+
return
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@app.cell
|
|
223
|
+
def _(mo, net, np, torch):
|
|
224
|
+
import plotly.graph_objects as go
|
|
225
|
+
|
|
226
|
+
# 1. Create the coordinate grid
|
|
227
|
+
m_range = np.linspace(-1.5, 1.5, 40) # moneyness_ttm
|
|
228
|
+
t_range = np.linspace(0.1, 2.0, 40) # ttm
|
|
229
|
+
M, T = np.meshgrid(m_range, t_range)
|
|
230
|
+
|
|
231
|
+
# Flatten the grid to feed into the neural network
|
|
232
|
+
M_flat = M.flatten()
|
|
233
|
+
T_flat = T.flatten()
|
|
234
|
+
|
|
235
|
+
# Prepare inputs for the network
|
|
236
|
+
M_tensor = torch.tensor(M_flat, dtype=torch.float32)
|
|
237
|
+
T_tensor = torch.tensor(T_flat, dtype=torch.float32)
|
|
238
|
+
|
|
239
|
+
# 2. Evaluate the network to get the factors
|
|
240
|
+
with torch.no_grad():
|
|
241
|
+
factors_pred = net(M_tensor, T_tensor).numpy()
|
|
242
|
+
|
|
243
|
+
# 3. Create a Plotly figure for factors 1, 2, 3, and 4
|
|
244
|
+
tabs_dict = {}
|
|
245
|
+
for i in range(1, 5):
|
|
246
|
+
# Reshape the 1D factor output back into the 2D grid shape
|
|
247
|
+
Z = factors_pred[:, i].reshape(M.shape)
|
|
248
|
+
|
|
249
|
+
fig = go.Figure(data=[go.Surface(x=M, y=T, z=Z, colorscale='Viridis')])
|
|
250
|
+
|
|
251
|
+
fig.update_layout(
|
|
252
|
+
title=f"DIVFM Learned Factor {i}",
|
|
253
|
+
scene=dict(
|
|
254
|
+
xaxis_title='Moneyness / √TTM',
|
|
255
|
+
yaxis_title='Time to Maturity',
|
|
256
|
+
zaxis_title=f'Factor {i} Value',
|
|
257
|
+
camera=dict(eye=dict(x=1.8, y=1.8, z=0.8)),
|
|
258
|
+
dragmode="turntable"
|
|
259
|
+
),
|
|
260
|
+
margin=dict(l=0, r=0, b=0, t=40)
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
tabs_dict[f"Factor {i}"] = fig
|
|
264
|
+
|
|
265
|
+
# 4. Display them in an interactive tabbed interface
|
|
266
|
+
mo.ui.tabs(tabs_dict)
|
|
267
|
+
return
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
@app.cell
|
|
271
|
+
def _():
|
|
272
|
+
return
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
if __name__ == "__main__":
|
|
276
|
+
app.run()
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import marimo
|
|
2
|
+
|
|
3
|
+
__generated_with = "0.22.0"
|
|
4
|
+
app = marimo.App(width="medium")
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@app.cell
|
|
8
|
+
def _():
|
|
9
|
+
import marimo as mo
|
|
10
|
+
from app.utils import nav_menu
|
|
11
|
+
nav_menu()
|
|
12
|
+
return (mo,)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@app.cell(hide_code=True)
|
|
16
|
+
def _(mo):
|
|
17
|
+
mo.md(r"""
|
|
18
|
+
## Jump Diffusion
|
|
19
|
+
|
|
20
|
+
We conside a Jump Diffuxion volatility surface and compare it with a more powerful Hest Stochastioc volatility with Jumps.
|
|
21
|
+
""")
|
|
22
|
+
return
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@app.cell
|
|
26
|
+
def _(mo):
|
|
27
|
+
from quantflow.sp.jump_diffusion import JumpDiffusion
|
|
28
|
+
from quantflow.sp.heston import HestonJ
|
|
29
|
+
from quantflow.utils.distributions import DoubleExponential
|
|
30
|
+
from quantflow.options.pricer import OptionPricer
|
|
31
|
+
import numpy as np
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
models = dict(jd="Jump Diffusion", hj="Heston with Jumps")
|
|
35
|
+
model = mo.ui.dropdown({v: n for n, v in models.items()}, value="Jump Diffusion", label="model")
|
|
36
|
+
vol = mo.ui.slider(start=0.1, stop=0.8, value=0.4, debounce=True, label="Long term volatility")
|
|
37
|
+
sigma = mo.ui.slider(start=0.1, stop=2, step=0.1, value=0.5, debounce=True, label="vol of vol")
|
|
38
|
+
kappa = mo.ui.slider(start=0.1, stop=2, step=0.5, value=0.5, debounce=True, label="Variance mean reversion")
|
|
39
|
+
rho = mo.ui.slider(start=-0.6, stop=0.6, step=0.1, value=0, debounce=True, label="Correlation")
|
|
40
|
+
r = mo.ui.slider(start=0.6, stop=1.6, step=0.1, value=1, debounce=True, label="Initial vol")
|
|
41
|
+
jump_fraction = mo.ui.slider(start=0.1, stop=0.9, step=0.05, value=0.5, debounce=True, label="Jump Fraction")
|
|
42
|
+
jump_intensity = mo.ui.slider(start=10, stop=100, step=5, debounce=True, label="Jump Intensity")
|
|
43
|
+
jump_asymmetry = mo.ui.slider(start=-2, stop=2, step=0.1, value=0, debounce=True, label="Jump Asymmetry")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Surface:
|
|
47
|
+
|
|
48
|
+
def __init__(self):
|
|
49
|
+
self.fig = None
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def scene_camera(self):
|
|
53
|
+
return self.fig.layout["scene"]["camera"] if self.fig is not None else None
|
|
54
|
+
|
|
55
|
+
def plot(self, model, pr):
|
|
56
|
+
name = models[model]
|
|
57
|
+
self.fig = pr.plot3d(
|
|
58
|
+
ttm=np.linspace(start=0.1, stop=1.0, num=10),
|
|
59
|
+
title=f"Implied Volatility Surface: {name}",
|
|
60
|
+
scene_camera=self.scene_camera
|
|
61
|
+
)
|
|
62
|
+
return self.fig
|
|
63
|
+
|
|
64
|
+
surface = Surface()
|
|
65
|
+
return (
|
|
66
|
+
DoubleExponential,
|
|
67
|
+
HestonJ,
|
|
68
|
+
JumpDiffusion,
|
|
69
|
+
OptionPricer,
|
|
70
|
+
jump_asymmetry,
|
|
71
|
+
jump_fraction,
|
|
72
|
+
jump_intensity,
|
|
73
|
+
kappa,
|
|
74
|
+
model,
|
|
75
|
+
r,
|
|
76
|
+
rho,
|
|
77
|
+
sigma,
|
|
78
|
+
surface,
|
|
79
|
+
vol,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@app.cell
|
|
84
|
+
def _(
|
|
85
|
+
DoubleExponential,
|
|
86
|
+
HestonJ,
|
|
87
|
+
JumpDiffusion,
|
|
88
|
+
OptionPricer,
|
|
89
|
+
jump_asymmetry,
|
|
90
|
+
jump_fraction,
|
|
91
|
+
jump_intensity,
|
|
92
|
+
kappa,
|
|
93
|
+
model,
|
|
94
|
+
r,
|
|
95
|
+
rho,
|
|
96
|
+
sigma,
|
|
97
|
+
vol,
|
|
98
|
+
):
|
|
99
|
+
def get_model(value: str):
|
|
100
|
+
match value:
|
|
101
|
+
case "jd":
|
|
102
|
+
return JumpDiffusion.create(
|
|
103
|
+
DoubleExponential,
|
|
104
|
+
vol=vol.value,
|
|
105
|
+
jump_fraction=jump_fraction.value,
|
|
106
|
+
jump_intensity=jump_intensity.value,
|
|
107
|
+
jump_asymmetry=jump_asymmetry.value,
|
|
108
|
+
)
|
|
109
|
+
case "hj":
|
|
110
|
+
st = sigma.value/vol.value
|
|
111
|
+
k = max((kappa.value, 0.5*st*st))
|
|
112
|
+
return HestonJ.create(
|
|
113
|
+
DoubleExponential,
|
|
114
|
+
rate=r.value,
|
|
115
|
+
vol=vol.value,
|
|
116
|
+
sigma=sigma.value,
|
|
117
|
+
kappa=k,
|
|
118
|
+
rho=rho.value,
|
|
119
|
+
jump_fraction=jump_fraction.value,
|
|
120
|
+
jump_intensity=jump_intensity.value,
|
|
121
|
+
jump_asymmetry=jump_asymmetry.value,
|
|
122
|
+
)
|
|
123
|
+
case _:
|
|
124
|
+
raise ValueError(f"Mode {value} not supported")
|
|
125
|
+
|
|
126
|
+
vm = get_model(model.value)
|
|
127
|
+
pricer = OptionPricer(model=vm)
|
|
128
|
+
return (pricer,)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@app.cell
|
|
132
|
+
def _(
|
|
133
|
+
jump_asymmetry,
|
|
134
|
+
jump_fraction,
|
|
135
|
+
jump_intensity,
|
|
136
|
+
kappa,
|
|
137
|
+
mo,
|
|
138
|
+
model,
|
|
139
|
+
r,
|
|
140
|
+
rho,
|
|
141
|
+
sigma,
|
|
142
|
+
vol,
|
|
143
|
+
):
|
|
144
|
+
mo.vstack([
|
|
145
|
+
mo.hstack([jump_fraction, jump_intensity, jump_asymmetry]),
|
|
146
|
+
mo.hstack([vol, sigma, kappa]),
|
|
147
|
+
mo.hstack([rho, r, model]),
|
|
148
|
+
])
|
|
149
|
+
return
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@app.cell
|
|
153
|
+
def _(model, pricer, surface):
|
|
154
|
+
fig = surface.plot(model.value, pricer)
|
|
155
|
+
fig
|
|
156
|
+
return
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@app.cell
|
|
160
|
+
def _():
|
|
161
|
+
return
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
if __name__ == "__main__":
|
|
165
|
+
app.run()
|