quantflow 0.6.3__tar.gz → 0.8.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.
- quantflow-0.8.0/.github/copilot-instructions.md +59 -0
- quantflow-0.8.0/.github/instructions/makefile.instructions.md +5 -0
- quantflow-0.8.0/.github/instructions/tutorial.instructions.md +96 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/.github/workflows/build.yml +2 -3
- {quantflow-0.6.3 → quantflow-0.8.0}/.github/workflows/docker-multiarch.yml +6 -0
- quantflow-0.8.0/.github/workflows/release.yml +78 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/.gitignore +3 -1
- {quantflow-0.6.3 → quantflow-0.8.0}/.vscode/launch.json +1 -1
- quantflow-0.8.0/CLAUDE.md +4 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/Makefile +35 -24
- {quantflow-0.6.3 → quantflow-0.8.0}/PKG-INFO +27 -58
- {quantflow-0.6.3 → quantflow-0.8.0}/app/__main__.py +6 -3
- {quantflow-0.6.3 → quantflow-0.8.0}/app/hurst.py +23 -23
- quantflow-0.8.0/app/utils/paths.py +13 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/app/volatility_surface.py +35 -12
- quantflow-0.8.0/dev/build-examples +10 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/lint +5 -6
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/quantflow.dockerfile +10 -7
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/index.md +1 -1
- quantflow-0.8.0/docs/api/options/calibration.md +17 -0
- quantflow-0.8.0/docs/api/options/svi.md +3 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/options/vol_surface.md +2 -0
- quantflow-0.8.0/docs/api/rates/index.md +1 -0
- quantflow-0.8.0/docs/api/rates/interest_rate.md +4 -0
- quantflow-0.8.0/docs/api/rates/yield_curve.md +6 -0
- quantflow-0.8.0/docs/api/sp/bns.md +6 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/sp/heston.md +6 -0
- quantflow-0.8.0/docs/api/sp/index.md +63 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/sp/ou.md +2 -0
- quantflow-0.8.0/docs/api/sp/wiener.md +3 -0
- quantflow-0.8.0/docs/api/utils/index.md +15 -0
- quantflow-0.8.0/docs/api/utils/marginal1d.md +9 -0
- quantflow-0.8.0/docs/assets/logos/README.md +30 -0
- quantflow-0.8.0/docs/assets/logos/favicon.ico +0 -0
- quantflow-0.8.0/docs/assets/logos/head-snippet.html +12 -0
- quantflow-0.8.0/docs/assets/logos/manifest.json +42 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-app-icon-1024.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-app-icon-128.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-app-icon-256.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-app-icon-512.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-linkedin-banner.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-lockup-1200.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-lockup-dark-1200.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-lockup-dark-2400.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-lockup-tagline-dark-1600.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-lockup-tagline-light-1600.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-1024.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-128.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-16.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-256.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-32.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-48.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-512.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-64.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-dark-1024.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-dark-128.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-dark-16.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-dark-256.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-dark-32.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-dark-48.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-dark-512.png +0 -0
- quantflow-0.8.0/docs/assets/logos/png/quantflow-mark-dark-64.png +0 -0
- quantflow-0.8.0/docs/assets/logos/quantflow-app-icon.svg +16 -0
- quantflow-0.8.0/docs/assets/logos/quantflow-favicon.svg +13 -0
- quantflow-0.8.0/docs/assets/logos/quantflow-linkedin-banner.svg +18 -0
- quantflow-0.8.0/docs/assets/logos/quantflow-lockup-dark.svg +15 -0
- quantflow-0.8.0/docs/assets/logos/quantflow-lockup-tagline-dark.svg +16 -0
- quantflow-0.8.0/docs/assets/logos/quantflow-lockup-tagline-light.svg +15 -0
- quantflow-0.8.0/docs/assets/logos/quantflow-lockup.svg +14 -0
- quantflow-0.8.0/docs/assets/logos/quantflow-mark-dark.svg +14 -0
- quantflow-0.8.0/docs/assets/logos/quantflow-mark.svg +13 -0
- quantflow-0.8.0/docs/bib2md.py +195 -0
- quantflow-0.8.0/docs/bibliography.md +73 -0
- quantflow-0.8.0/docs/examples/_utils.py +43 -0
- quantflow-0.8.0/docs/examples/cir_pdf_comparison.py +100 -0
- quantflow-0.8.0/docs/examples/fft.py +22 -0
- quantflow-0.8.0/docs/examples/pricing_method_comparison.py +178 -0
- quantflow-0.8.0/docs/examples/vol_surface_bns2_calibration.py +42 -0
- quantflow-0.8.0/docs/examples/vol_surface_bns_calibration.py +34 -0
- quantflow-0.8.0/docs/examples/vol_surface_heston_calibration.py +35 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/examples/vol_surface_hestonj_calibration.py +12 -14
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/examples/vol_surface_inputs.py +6 -1
- quantflow-0.8.0/docs/examples/volsurface.json +5348 -0
- quantflow-0.6.3/docs/examples/weiner_volatility_pricer.py → quantflow-0.8.0/docs/examples/wiener_volatility_pricer.py +3 -6
- quantflow-0.8.0/docs/favicon.ico +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/glossary.md +65 -8
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/index.md +10 -56
- quantflow-0.8.0/docs/javascripts/mathjax.js +26 -0
- quantflow-0.8.0/docs/mcp.md +63 -0
- quantflow-0.8.0/docs/references.bib +152 -0
- quantflow-0.8.0/docs/release-notes.md +68 -0
- quantflow-0.8.0/docs/robots.txt +2 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/theory/characteristic.md +6 -0
- quantflow-0.8.0/docs/theory/convexity_correction.md +119 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/theory/inversion.md +9 -25
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/theory/levy.md +4 -2
- quantflow-0.8.0/docs/theory/option_pricing.md +232 -0
- quantflow-0.8.0/docs/tutorials/bns_calibration.md +143 -0
- quantflow-0.8.0/docs/tutorials/cir.md +95 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/tutorials/index.md +1 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/tutorials/option_pricing.md +3 -3
- quantflow-0.8.0/docs/tutorials/pricing_method_comparison.md +62 -0
- quantflow-0.8.0/docs/tutorials/volatility_surface.md +251 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/mkdocs.yml +20 -5
- quantflow-0.6.3/notebooks/models/weiner.md → quantflow-0.8.0/notebooks/models/wiener.md +6 -6
- {quantflow-0.6.3 → quantflow-0.8.0}/pyproject.toml +36 -2
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ai/tools/crypto.py +21 -6
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/bs.py +9 -6
- quantflow-0.8.0/quantflow/options/calibration/__init__.py +24 -0
- quantflow-0.8.0/quantflow/options/calibration/base.py +273 -0
- quantflow-0.8.0/quantflow/options/calibration/bns.py +144 -0
- quantflow-0.8.0/quantflow/options/calibration/heston.py +305 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/divfm/network.py +1 -1
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/divfm/pricer.py +4 -4
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/inputs.py +4 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/pricer.py +62 -55
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/surface.py +350 -62
- quantflow-0.8.0/quantflow/options/svi.py +144 -0
- quantflow-0.8.0/quantflow/rates/__init__.py +0 -0
- quantflow-0.8.0/quantflow/rates/interest_rate.py +110 -0
- quantflow-0.8.0/quantflow/rates/nelson_siegel.py +123 -0
- quantflow-0.8.0/quantflow/rates/yield_curve.py +37 -0
- quantflow-0.8.0/quantflow/sp/__init__.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/sp/base.py +25 -7
- quantflow-0.8.0/quantflow/sp/bns.py +246 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/sp/cir.py +88 -31
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/sp/copula.py +6 -10
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/sp/dsp.py +4 -2
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/sp/heston.py +165 -7
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/sp/jump_diffusion.py +5 -5
- quantflow-0.8.0/quantflow/sp/ou.py +333 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/sp/poisson.py +1 -1
- quantflow-0.6.3/quantflow/sp/weiner.py → quantflow-0.8.0/quantflow/sp/wiener.py +1 -1
- quantflow-0.8.0/quantflow/utils/__init__.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/utils/distributions.py +2 -2
- quantflow-0.8.0/quantflow/utils/marginal.py +744 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/utils/plot.py +8 -6
- quantflow-0.8.0/quantflow_tests/__init__.py +0 -0
- quantflow-0.8.0/quantflow_tests/conftest.py +13 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/fixtures/deribit_instruments.json +5 -5
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/test_ai.py +0 -8
- quantflow-0.8.0/quantflow_tests/test_bns.py +107 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/test_cir.py +21 -2
- quantflow-0.8.0/quantflow_tests/test_copula.py +58 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/test_data_deribit.py +16 -6
- quantflow-0.8.0/quantflow_tests/test_disable_outliers.py +215 -0
- quantflow-0.8.0/quantflow_tests/test_heston.py +104 -0
- quantflow-0.8.0/quantflow_tests/test_implied_fwd.py +175 -0
- quantflow-0.8.0/quantflow_tests/test_jump_diffusion.py +56 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/test_ohlc.py +2 -2
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/test_options.py +173 -20
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/test_options_pricer.py +3 -3
- quantflow-0.8.0/quantflow_tests/test_ou.py +110 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/test_poisson.py +17 -0
- quantflow-0.8.0/quantflow_tests/test_rates.py +220 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/test_strategies.py +2 -2
- quantflow-0.8.0/quantflow_tests/test_surface_methods.py +82 -0
- quantflow-0.8.0/quantflow_tests/test_svi.py +136 -0
- quantflow-0.6.3/quantflow_tests/test_weiner.py → quantflow-0.8.0/quantflow_tests/test_wiener.py +13 -13
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/utils.py +12 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/readme.md +10 -56
- {quantflow-0.6.3 → quantflow-0.8.0}/uv.lock +829 -786
- quantflow-0.6.3/.github/copilot-instructions.md +0 -38
- quantflow-0.6.3/CLAUDE.md +0 -2
- quantflow-0.6.3/dev/build-examples +0 -28
- quantflow-0.6.3/docs/api/options/calibration.md +0 -5
- quantflow-0.6.3/docs/api/sp/index.md +0 -9
- quantflow-0.6.3/docs/api/sp/weiner.md +0 -3
- quantflow-0.6.3/docs/api/utils/index.md +0 -3
- quantflow-0.6.3/docs/api/utils/marginal1d.md +0 -3
- 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.3/docs/assets/linkedin-banner.png +0 -0
- quantflow-0.6.3/docs/assets/quantflow-light.svg +0 -110
- quantflow-0.6.3/docs/assets/quantflow-logo.png +0 -0
- quantflow-0.6.3/docs/assets/quantflow-repo.png +0 -0
- quantflow-0.6.3/docs/assets/quantflow-repo.svg +0 -203
- quantflow-0.6.3/docs/assets/quantflow.svg +0 -252
- quantflow-0.6.3/docs/bibliography.md +0 -51
- quantflow-0.6.3/docs/examples/vol_surface_heston_calibration.py +0 -33
- quantflow-0.6.3/docs/examples_png/vol_surface_heston_plot.py +0 -35
- quantflow-0.6.3/docs/examples_png/vol_surface_hestonj_plot.py +0 -46
- quantflow-0.6.3/docs/javascripts/mathjax.js +0 -12
- quantflow-0.6.3/docs/references.bib +0 -139
- quantflow-0.6.3/docs/theory/option_pricing.md +0 -114
- quantflow-0.6.3/docs/tutorials/volatility_surface.md +0 -185
- quantflow-0.6.3/quantflow/options/calibration.py +0 -357
- quantflow-0.6.3/quantflow/sp/bns.py +0 -66
- quantflow-0.6.3/quantflow/sp/ou.py +0 -182
- quantflow-0.6.3/quantflow/utils/interest_rates.py +0 -51
- quantflow-0.6.3/quantflow/utils/marginal.py +0 -321
- quantflow-0.6.3/quantflow_tests/conftest.py +0 -3
- quantflow-0.6.3/quantflow_tests/test_copula.py +0 -30
- quantflow-0.6.3/quantflow_tests/test_heston.py +0 -39
- quantflow-0.6.3/quantflow_tests/test_jump_diffusion.py +0 -27
- quantflow-0.6.3/quantflow_tests/test_ou.py +0 -48
- quantflow-0.6.3/quantflow_tests/volsurface.json +0 -4359
- {quantflow-0.6.3 → quantflow-0.8.0}/.coveragerc +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/.dockerignore +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/.github/workflows/deploy.yml +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/.vscode/settings.json +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/.vscode/tasks.json +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/CITATION.cff +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/LICENSE +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/app/cointegration.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/app/double_exponential_sampling.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/app/gaussian_sampling.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/app/heston_divfm_fit.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/app/heston_vol_surface.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/app/poisson_sampling.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/app/scripts/__init__.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/app/scripts/heston_divfm_fit.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0/app/scripts}/test_comparison.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/app/supersmoother.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/app/utils/__init__.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/blocks/quantflow.yaml +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/charts.yaml +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/helm/.helmignore +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/helm/Chart.yaml +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/helm/templates/_helpers.tpl +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/helm/templates/_service.tpl +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/helm/templates/app.yaml +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/helm/templates/configmap.yaml +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/helm/templates/secret.yaml +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/helm/values.yaml +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/install +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/marimo +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/dev/test +0 -0
- {quantflow-0.6.3/quantflow/ai/tools → quantflow-0.8.0/docs}/__init__.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/data/deribit.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/data/fed.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/data/fmp.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/data/fred.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/data/index.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/options/black.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/options/divfm.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/options/index.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/options/pricer.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/sp/cir.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/sp/compound_poisson.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/sp/copula.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/sp/dsp.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/sp/jump_diffusion.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/sp/poisson.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/ta/ewma.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/ta/index.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/ta/kalman.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/ta/ohlc.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/ta/paths.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/ta/supersmoother.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/utils/bins.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/utils/distributions.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/utils/numbers.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/api/utils/types.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/assets/heston.gif +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/contributing.md +0 -0
- {quantflow-0.6.3/quantflow/data → quantflow-0.8.0/docs/examples}/__init__.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/examples/heston_volatility_pricer.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/docs/theory/index.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/applications/calibration.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/applications/calibration.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/applications/volatility_surface.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/data/fed.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/data/fiscal_data.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/data/fmp.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/data/timeseries.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/models/bns.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/models/cir.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/models/gousv.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/models/heston.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/models/heston_jumps.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/models/jump_diffusion.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/models/ou.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/models/overview.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/notebooks/models/poisson.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/__init__.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ai/__init__.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ai/server.py +0 -0
- {quantflow-0.6.3/quantflow/options → quantflow-0.8.0/quantflow/ai/tools}/__init__.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ai/tools/base.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ai/tools/charts.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ai/tools/fred.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ai/tools/stocks.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ai/tools/vault.py +0 -0
- {quantflow-0.6.3/quantflow/sp → quantflow-0.8.0/quantflow/data}/__init__.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/data/deribit.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/data/fed.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/data/fiscal_data.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/data/fmp.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/data/fred.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/data/vault.py +0 -0
- {quantflow-0.6.3/quantflow/utils → quantflow-0.8.0/quantflow/options}/__init__.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/divfm/__init__.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/divfm/trainer.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/divfm/weights.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/docs/butterfly.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/docs/calendar_spread.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/docs/spread.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/docs/straddle.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/docs/strangle.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/docs/terminology.md +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/strategies/__init__.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/strategies/base.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/strategies/butterfly.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/strategies/calendar_spread.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/strategies/spread.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/strategies/straddle.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/options/strategies/strangle.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/py.typed +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ta/__init__.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ta/base.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ta/ewma.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ta/kalman.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ta/ohlc.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ta/paths.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/ta/supersmoother.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/utils/bins.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/utils/dates.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/utils/functions.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/utils/numbers.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/utils/transforms.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow/utils/types.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/fixtures/deribit_futures.json +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/fixtures/deribit_options.json +0 -0
- {quantflow-0.6.3/docs/examples → quantflow-0.8.0/quantflow_tests/fixtures}/volsurface.json +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/test_data.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/test_distributions.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/test_divfm.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/test_frft.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/test_utils.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/quantflow_tests/test_vault.py +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/rops.toml +0 -0
- {quantflow-0.6.3 → quantflow-0.8.0}/taplo.toml +0 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: quantflow-instructions
|
|
3
|
+
description: 'Instructions for quantflow'
|
|
4
|
+
applyTo: '/**'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Quantflow Instructions
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## Development
|
|
12
|
+
|
|
13
|
+
* Always run `make lint` after code changes — runs taplo, isort, black, ruff, and mypy
|
|
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`
|
|
16
|
+
* To run all tests use `make test` — runs all tests in the `tests/` directory using pytest
|
|
17
|
+
* To run a specific test file, use `uv run pytest tests/path/to/test_file.py`
|
|
18
|
+
|
|
19
|
+
## Docker
|
|
20
|
+
|
|
21
|
+
* The Dockerfile is at `dev/quantflow.dockerfile`
|
|
22
|
+
* Uses `ghcr.io/astral-sh/uv:python3.14-bookworm-slim` as the base image (uv + Python bundled, no separate install needed)
|
|
23
|
+
* Multi-stage build: builder installs deps and builds docs, runtime copies the `.venv` and app code
|
|
24
|
+
* Package manager is `uv` — do not use Poetry or pip directly
|
|
25
|
+
|
|
26
|
+
## Documentation
|
|
27
|
+
|
|
28
|
+
* The documentation for quantflow is available at `https://quantflow.quantmid.com`
|
|
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.
|
|
30
|
+
* Split prose into short paragraphs (one idea per paragraph) separated by blank lines. Never write a wall-of-text paragraph that strings together mechanism, rationale, caveats and usage advice. This applies to mkdocs tutorials, theory pages and long docstrings.
|
|
31
|
+
* Do not use dashes (em dashes, en dashes, or hyphens used as dashes) in documentation files or docstrings. Use colons, parentheses, or restructure the sentence instead.
|
|
32
|
+
* Math in documentation and docstrings: always use `\begin{equation}...\end{equation}` for any formula or equation. Use `$...$` only for brief inline references to variables (e.g. $F$, $K$). Do not use `$$...$$`, `` `...` ``, or RST syntax (`.. math::`, `:math:`).
|
|
33
|
+
* Math notation convention: use $\Phi$ for the characteristic function and $\phi$ for the characteristic exponent, where $\Phi = e^{-\phi}$.
|
|
34
|
+
* Glossary entries in `docs/glossary.md` must be kept in alphabetical order.
|
|
35
|
+
* Do not repeat concept definitions inline in tutorials or docstrings — link to the glossary instead using a relative markdown link (e.g. `[moneyness](../glossary.md#moneyness)`).
|
|
36
|
+
* To rebuild doc examples run `uv run ./dev/build-examples` — runs all scripts in `docs/examples/` and writes their output to `docs/examples_output/`
|
|
37
|
+
|
|
38
|
+
## Pydantic models
|
|
39
|
+
|
|
40
|
+
* Always document Pydantic fields with `Field(description=...)` — never use a docstring below a field assignment
|
|
41
|
+
* Split long description strings across lines using implicit string concatenation rather than shortening the text
|
|
42
|
+
* When a docstring line exceeds the line length limit, split it across multiple lines rather than shortening the text
|
|
43
|
+
|
|
44
|
+
## Package structure
|
|
45
|
+
|
|
46
|
+
* 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
|
|
47
|
+
* mkdocs documentation pages live in `docs/api/options/` — do not mix these two locations
|
|
48
|
+
|
|
49
|
+
## Releasing
|
|
50
|
+
|
|
51
|
+
The release procedure is fully driven by `make release` and the `release.yml` workflow:
|
|
52
|
+
|
|
53
|
+
1. Bump `version` in `pyproject.toml` to the new release version.
|
|
54
|
+
2. Add a `## vX.Y.Z` section to `docs/release-notes.md` with the notes for the release. The header text is matched verbatim by the workflow's `awk` extractor, so it must be `## vX.Y.Z` exactly (no trailing dash, no title after the version).
|
|
55
|
+
3. Commit and merge to `main`.
|
|
56
|
+
4. From `main`, run `make release` — it reads the version from `pyproject.toml`, prompts for confirmation, then creates an annotated `vX.Y.Z` tag and pushes it.
|
|
57
|
+
5. The tag push triggers `.github/workflows/release.yml`, which runs lint and tests, publishes the package to PyPI (`make publish`), and posts the extracted `## vX.Y.Z` section as the GitHub Release body.
|
|
58
|
+
|
|
59
|
+
Do not publish to PyPI manually or via the old `head_commit.message == 'release'` flow — the tag-triggered workflow is the only supported path.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Makefile Conventions
|
|
2
|
+
|
|
3
|
+
- Keep all targets sorted alphabetically.
|
|
4
|
+
- targets should be separated by a one blank line only.
|
|
5
|
+
- Each target should have a one-line description, starting with `##`, that describes what the target does. This description is used by the `help` target to generate documentation for all targets.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: quantflow-tutorial-instructions
|
|
3
|
+
description: 'Instructions for tutorial in quantflow'
|
|
4
|
+
applyTo: '/docs/tutorials/**,/docs/examples/**'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Tutorial Instructions
|
|
10
|
+
|
|
11
|
+
## File locations
|
|
12
|
+
|
|
13
|
+
- Tutorial pages: `docs/tutorials/<name>.md`
|
|
14
|
+
- Example scripts: `docs/examples/<name>.py`
|
|
15
|
+
- Generated images: `docs/assets/examples/<name>.png`
|
|
16
|
+
- Script stdout captured to: `docs/examples/output/<name>.out`
|
|
17
|
+
- Every new tutorial must be added to the `nav` section of `mkdocs.yml` under `Tutorials`.
|
|
18
|
+
- Update `docs/tutorials/index.md` with a row in the summary table.
|
|
19
|
+
|
|
20
|
+
## Building
|
|
21
|
+
|
|
22
|
+
- Build a single example: `uv run python docs/examples/<name>.py`
|
|
23
|
+
- Build all examples and capture output: `make docs-examples`
|
|
24
|
+
- Preview the docs locally: `uv run mkdocs serve`
|
|
25
|
+
|
|
26
|
+
## Tutorial page structure
|
|
27
|
+
|
|
28
|
+
Each tutorial markdown file should follow this order:
|
|
29
|
+
|
|
30
|
+
1. **H1 title** — the subject, not "Tutorial on X".
|
|
31
|
+
2. **One-paragraph introduction** — what the tutorial demonstrates and why it is useful.
|
|
32
|
+
Link to the relevant API classes using `[ClassName][fully.qualified.path]`.
|
|
33
|
+
3. **Sections** (H2) — cover the concept first, then show usage, then show results.
|
|
34
|
+
Use H3 subsections for variants (different parameter regimes, maturities, etc.).
|
|
35
|
+
4. **Code section** — always the last H2. Embed the full example script with:
|
|
36
|
+
````
|
|
37
|
+
```python
|
|
38
|
+
--8<-- "docs/examples/<name>.py"
|
|
39
|
+
```
|
|
40
|
+
````
|
|
41
|
+
If the script prints structured output, embed it too:
|
|
42
|
+
````
|
|
43
|
+
```
|
|
44
|
+
--8<-- "docs/examples/output/<name>.out"
|
|
45
|
+
```
|
|
46
|
+
````
|
|
47
|
+
|
|
48
|
+
## Example scripts
|
|
49
|
+
|
|
50
|
+
- Each script must be self-contained and runnable with `uv run python docs/examples/<name>.py`.
|
|
51
|
+
- Place shared helpers in `docs/examples/_utils.py` — do not duplicate utility code.
|
|
52
|
+
- Use `assets_path(filename)` from `_utils.py` to get the correct path when saving images.
|
|
53
|
+
- Use `plotly` for all charts. Save to PNG with `fig.write_image(assets_path(...), width=900, height=500)`.
|
|
54
|
+
Use `width=1600, height=800` for side-by-side subplot layouts.
|
|
55
|
+
- When overlaying an analytical curve with a numerical result (e.g. PDF from characteristic
|
|
56
|
+
function), plot the analytical result as a solid line and the numerical result as circle
|
|
57
|
+
markers (`mode="markers", marker=dict(symbol="circle")`). This makes the discretization
|
|
58
|
+
points visible and the two series easy to distinguish.
|
|
59
|
+
- Do not `print` raw numbers — emit only what belongs in the captured `.out` file.
|
|
60
|
+
- Scripts must produce no warnings when run cleanly (fix the root cause, e.g. avoid `x=0`
|
|
61
|
+
in domains where the PDF is singular).
|
|
62
|
+
- The `build_examples` helper in `_utils.py` runs every non-underscore script and captures
|
|
63
|
+
stdout; keep scripts idempotent and deterministic.
|
|
64
|
+
|
|
65
|
+
## Charts
|
|
66
|
+
|
|
67
|
+
- Embed images with a clickable link that opens full-size in a new tab:
|
|
68
|
+
```markdown
|
|
69
|
+
[](../assets/examples/<name>.png){target="_blank"}
|
|
70
|
+
```
|
|
71
|
+
- Write a one-sentence caption above each image explaining what the reader should observe.
|
|
72
|
+
|
|
73
|
+
## Math
|
|
74
|
+
|
|
75
|
+
Follow the math conventions in `copilot-instructions.md`:
|
|
76
|
+
|
|
77
|
+
- Use `\begin{equation}...\end{equation}` for standalone formulas.
|
|
78
|
+
- Use `\begin{equation}\begin{aligned}...\end{aligned}\end{equation}` for multi-line systems.
|
|
79
|
+
- Use `$...$` only for brief inline variable references.
|
|
80
|
+
- Use `\Phi` for the characteristic function and `\phi` for the characteristic exponent.
|
|
81
|
+
|
|
82
|
+
## Cross-references
|
|
83
|
+
|
|
84
|
+
- Link API symbols with `[ClassName][fully.qualified.module.ClassName]`.
|
|
85
|
+
- Link to theory pages with relative markdown links: `[Option Pricing](../theory/option_pricing.md)`.
|
|
86
|
+
- Link to the glossary for concept definitions rather than re-defining them inline.
|
|
87
|
+
- Link to the bibliography for external references: `[Carr-Madan](../bibliography.md#carr_madan)`.
|
|
88
|
+
|
|
89
|
+
## What not to include
|
|
90
|
+
|
|
91
|
+
- Do not explain implementation details that belong in docstrings.
|
|
92
|
+
- Do not reproduce equations already in the API reference — link to them instead.
|
|
93
|
+
- Do not add a summary or "next steps" section unless the tutorial is part of a series.
|
|
94
|
+
- Do not use math notation (`$...$`, `\begin{equation}`, etc.) in any heading (H1–H4).
|
|
95
|
+
Math does not render in the table of contents — write headings in plain English instead
|
|
96
|
+
(e.g. "Short horizon" not "Short horizon ($t = 0.5$)").
|
|
@@ -23,6 +23,8 @@ jobs:
|
|
|
23
23
|
- uses: actions/checkout@v4
|
|
24
24
|
- name: install rops
|
|
25
25
|
uses: quantmind/rops/.github/actions/setup-rops@main
|
|
26
|
+
env:
|
|
27
|
+
GITHUB_TOKEN: ${{ secrets.TOKEN_DEPLOYMENT }}
|
|
26
28
|
- name: install taplo
|
|
27
29
|
run: rops tools update taplo
|
|
28
30
|
- name: Set up Python ${{ matrix.python-version }}
|
|
@@ -47,9 +49,6 @@ jobs:
|
|
|
47
49
|
with:
|
|
48
50
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
49
51
|
files: ./build/coverage.xml
|
|
50
|
-
- name: publish
|
|
51
|
-
if: ${{ matrix.python-version == '3.14' && github.event.head_commit.message == 'release' }}
|
|
52
|
-
run: make publish
|
|
53
52
|
|
|
54
53
|
image:
|
|
55
54
|
if: github.ref == 'refs/heads/main'
|
|
@@ -23,6 +23,8 @@ jobs:
|
|
|
23
23
|
password: ${{ github.token }}
|
|
24
24
|
- name: install rops
|
|
25
25
|
uses: quantmind/rops/.github/actions/setup-rops@main
|
|
26
|
+
env:
|
|
27
|
+
GITHUB_TOKEN: ${{ secrets.TOKEN_DEPLOYMENT }}
|
|
26
28
|
- name: build amd64
|
|
27
29
|
run: rops docker build ${{ inputs.image-name }}
|
|
28
30
|
- name: push amd64
|
|
@@ -44,6 +46,8 @@ jobs:
|
|
|
44
46
|
password: ${{ github.token }}
|
|
45
47
|
- name: install rops
|
|
46
48
|
uses: quantmind/rops/.github/actions/setup-rops@main
|
|
49
|
+
env:
|
|
50
|
+
GITHUB_TOKEN: ${{ secrets.TOKEN_DEPLOYMENT }}
|
|
47
51
|
- name: build arm64
|
|
48
52
|
run: rops docker build ${{ inputs.image-name }}
|
|
49
53
|
- name: push arm64
|
|
@@ -64,5 +68,7 @@ jobs:
|
|
|
64
68
|
password: ${{ github.token }}
|
|
65
69
|
- name: install rops
|
|
66
70
|
uses: quantmind/rops/.github/actions/setup-rops@main
|
|
71
|
+
env:
|
|
72
|
+
GITHUB_TOKEN: ${{ secrets.TOKEN_DEPLOYMENT }}
|
|
67
73
|
- name: create manifest
|
|
68
74
|
run: rops docker manifest ${{ inputs.image-name }}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# Triggered by `v*` tags. Builds and publishes the package to PyPI, then
|
|
4
|
+
# extracts the matching section from docs/release-notes.md and publishes it
|
|
5
|
+
# as the GitHub Release body. Re-runs idempotently update an existing
|
|
6
|
+
# release rather than failing.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
tags:
|
|
11
|
+
- "v*"
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: write
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
release:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
env:
|
|
20
|
+
PYTHON_ENV: ci
|
|
21
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
22
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
23
|
+
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
|
|
24
|
+
FMP_API_KEY: ${{ secrets.FMP_API_KEY }}
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v4
|
|
27
|
+
|
|
28
|
+
- name: install rops
|
|
29
|
+
uses: quantmind/rops/.github/actions/setup-rops@main
|
|
30
|
+
env:
|
|
31
|
+
GITHUB_TOKEN: ${{ secrets.TOKEN_DEPLOYMENT }}
|
|
32
|
+
|
|
33
|
+
- name: install taplo
|
|
34
|
+
run: rops tools update taplo
|
|
35
|
+
|
|
36
|
+
- name: Set up Python
|
|
37
|
+
uses: actions/setup-python@v5
|
|
38
|
+
with:
|
|
39
|
+
python-version: "3.14"
|
|
40
|
+
|
|
41
|
+
- name: Install uv
|
|
42
|
+
run: pip install -U pip uv
|
|
43
|
+
|
|
44
|
+
- name: Install dependencies
|
|
45
|
+
run: make install-dev
|
|
46
|
+
|
|
47
|
+
- name: run lint
|
|
48
|
+
run: make lint-check
|
|
49
|
+
|
|
50
|
+
- name: run tests
|
|
51
|
+
run: make tests
|
|
52
|
+
|
|
53
|
+
- name: publish to PyPI
|
|
54
|
+
run: make publish
|
|
55
|
+
|
|
56
|
+
- name: Extract release notes
|
|
57
|
+
run: |
|
|
58
|
+
TAG="${GITHUB_REF_NAME}"
|
|
59
|
+
awk -v tag="## ${TAG}" '
|
|
60
|
+
$0 == tag { in_section = 1; next }
|
|
61
|
+
/^## / && in_section { exit }
|
|
62
|
+
in_section { print }
|
|
63
|
+
' docs/release-notes.md > /tmp/notes.md
|
|
64
|
+
if [ ! -s /tmp/notes.md ]; then
|
|
65
|
+
echo "No section '## ${TAG}' found in docs/release-notes.md" >&2
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
echo "--- extracted notes for ${TAG} ---"
|
|
69
|
+
cat /tmp/notes.md
|
|
70
|
+
|
|
71
|
+
- name: Publish GitHub Release
|
|
72
|
+
run: |
|
|
73
|
+
TAG="${GITHUB_REF_NAME}"
|
|
74
|
+
if gh release view "$TAG" >/dev/null 2>&1; then
|
|
75
|
+
gh release edit "$TAG" --notes-file /tmp/notes.md
|
|
76
|
+
else
|
|
77
|
+
gh release create "$TAG" --title "$TAG" --notes-file /tmp/notes.md
|
|
78
|
+
fi
|
|
@@ -5,53 +5,64 @@ help:
|
|
|
5
5
|
@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//'
|
|
6
6
|
@echo ================================================================================
|
|
7
7
|
|
|
8
|
+
.PHONY: docs
|
|
9
|
+
docs: ## build documentation
|
|
10
|
+
@cp docs/index.md readme.md
|
|
11
|
+
@uv run ./dev/build-examples
|
|
12
|
+
@uv run mkdocs build
|
|
13
|
+
|
|
14
|
+
.PHONY: docs-bib
|
|
15
|
+
docs-bib: ## Regenerate docs bibliography
|
|
16
|
+
@uv run ./docs/bib2md.py
|
|
17
|
+
|
|
18
|
+
.PHONY: docs-examples
|
|
19
|
+
docs-examples: ## Regenerate docs examples
|
|
20
|
+
@uv run ./dev/build-examples
|
|
21
|
+
|
|
22
|
+
.PHONY: docs-serve
|
|
23
|
+
docs-serve: ## serve documentation
|
|
24
|
+
@uv run mkdocs serve --livereload --watch quantflow --watch docs
|
|
25
|
+
|
|
26
|
+
.PHONY: install-dev
|
|
27
|
+
install-dev: ## Install development dependencies
|
|
28
|
+
@./dev/install
|
|
8
29
|
|
|
9
30
|
.PHONY: lint
|
|
10
31
|
lint: ## Lint and fix
|
|
11
32
|
@uv run ./dev/lint fix
|
|
12
33
|
|
|
13
|
-
|
|
14
34
|
.PHONY: lint-check
|
|
15
35
|
lint-check: ## Lint check only
|
|
16
36
|
@uv run ./dev/lint
|
|
17
37
|
|
|
18
|
-
|
|
19
|
-
.PHONY: install-dev
|
|
20
|
-
install-dev: ## Install development dependencies
|
|
21
|
-
@./dev/install
|
|
22
|
-
|
|
23
38
|
.PHONY: marimo
|
|
24
39
|
marimo: ## Run marimo for editing notebooks
|
|
25
40
|
@./dev/marimo edit
|
|
26
41
|
|
|
27
|
-
.PHONY:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
.PHONY: docs
|
|
32
|
-
docs: ## build documentation
|
|
33
|
-
@cp docs/index.md readme.md
|
|
34
|
-
@uv run ./dev/build-examples
|
|
35
|
-
@uv run mkdocs build
|
|
36
|
-
|
|
37
|
-
.PHONY: docs-serve
|
|
38
|
-
docs-serve: ## serve documentation
|
|
39
|
-
@uv run mkdocs serve --livereload --watch quantflow --watch docs
|
|
42
|
+
.PHONY: outdated
|
|
43
|
+
outdated: ## Show outdated packages
|
|
44
|
+
uv tree --outdated
|
|
40
45
|
|
|
41
46
|
.PHONY: publish
|
|
42
47
|
publish: ## Release to pypi
|
|
43
48
|
@uv build
|
|
44
49
|
@uv publish --token $(PYPI_TOKEN)
|
|
45
50
|
|
|
51
|
+
.PHONY: release
|
|
52
|
+
release: ## Tag current version (from pyproject.toml) and push
|
|
53
|
+
$(eval VERSION := $(shell grep '^version' pyproject.toml | head -1 | sed 's/version = "\(.*\)"/\1/'))
|
|
54
|
+
@read -p "Tagging with v$(VERSION), are you sure? [Y/n] " ans; \
|
|
55
|
+
ans=$${ans:-Y}; \
|
|
56
|
+
if [ "$$ans" = "Y" ] || [ "$$ans" = "y" ]; then \
|
|
57
|
+
git tag -a v$(VERSION) -m "v$(VERSION)" && git push origin v$(VERSION); \
|
|
58
|
+
else \
|
|
59
|
+
echo "Aborted."; \
|
|
60
|
+
fi
|
|
61
|
+
|
|
46
62
|
.PHONY: tests
|
|
47
63
|
tests: ## Unit tests
|
|
48
64
|
@./dev/test
|
|
49
65
|
|
|
50
|
-
|
|
51
|
-
.PHONY: outdated
|
|
52
|
-
outdated: ## Show outdated packages
|
|
53
|
-
uv tree --outdated
|
|
54
|
-
|
|
55
66
|
.PHONY: upgrade
|
|
56
67
|
upgrade: ## Upgrade dependencies
|
|
57
68
|
uv lock --upgrade
|
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quantflow
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
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
|
|
7
|
-
Project-URL: Documentation, https://quantmind.
|
|
7
|
+
Project-URL: Documentation, https://quantflow.quantmind.com
|
|
8
|
+
Project-URL: Issues, https://github.com/quantmind/quantflow/issues
|
|
8
9
|
Author-email: Luca Sbardella <luca@quantmind.com>
|
|
9
10
|
License-Expression: BSD-3-Clause
|
|
10
11
|
License-File: LICENSE
|
|
12
|
+
Keywords: finance,options,pricing,quantitative,stochastic,volatility
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
25
|
+
Classifier: Typing :: Typed
|
|
11
26
|
Requires-Python: <3.15,>=3.11
|
|
12
27
|
Requires-Dist: ccy>=2.0.0
|
|
13
28
|
Requires-Dist: polars[pandas,pyarrow]>=1.11.0
|
|
@@ -54,7 +69,7 @@ Provides-Extra: ml
|
|
|
54
69
|
Requires-Dist: torch>=2.10.0; extra == 'ml'
|
|
55
70
|
Description-Content-Type: text/markdown
|
|
56
71
|
|
|
57
|
-
# <a href="https://quantmind.github.io/quantflow"><img src="https://raw.githubusercontent.com/quantmind/quantflow/main/docs/assets/quantflow-
|
|
72
|
+
# <a href="https://quantmind.github.io/quantflow"><img src="https://raw.githubusercontent.com/quantmind/quantflow/main/docs/assets/logos/quantflow-lockup.svg" width=300 /></a>
|
|
58
73
|
|
|
59
74
|
[](https://badge.fury.io/py/quantflow)
|
|
60
75
|
[](https://pypi.org/project/quantflow)
|
|
@@ -85,67 +100,21 @@ pip install quantflow
|
|
|
85
100
|
|
|
86
101
|
* `data` — data retrieval: `pip install quantflow[data]`
|
|
87
102
|
* `ai` — MCP server for AI clients: `pip install quantflow[ai,data]`
|
|
103
|
+
* `ml` — training the Deep Implied Volatility model: `pip install quantflow[ml]`
|
|
88
104
|
|
|
89
105
|
## MCP Server
|
|
90
106
|
|
|
91
|
-
Quantflow exposes its data tools as an [MCP](https://modelcontextprotocol.io) server
|
|
107
|
+
Quantflow exposes its data tools as an [MCP](https://modelcontextprotocol.io) server for AI clients.
|
|
108
|
+
See [MCP Server](https://quantflow.quantmind.com/mcp/) for setup and available tools.
|
|
92
109
|
|
|
93
|
-
|
|
110
|
+
## License
|
|
94
111
|
|
|
95
|
-
|
|
96
|
-
pip install quantflow[ai,data]
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### API keys
|
|
100
|
-
|
|
101
|
-
Store your API keys in `~/.quantflow/.vault`:
|
|
102
|
-
|
|
103
|
-
```
|
|
104
|
-
fmp=your-fmp-key
|
|
105
|
-
fred=your-fred-key
|
|
106
|
-
```
|
|
112
|
+
Released under the [BSD 3-Clause License](https://github.com/quantmind/quantflow/blob/main/LICENSE).
|
|
107
113
|
|
|
108
|
-
|
|
114
|
+
## Citation
|
|
109
115
|
|
|
110
|
-
|
|
116
|
+
If you use Quantflow in your research, please cite it using the metadata in [CITATION.cff](https://github.com/quantmind/quantflow/blob/main/CITATION.cff).
|
|
111
117
|
|
|
112
|
-
|
|
113
|
-
claude mcp add quantflow -- uv run qf-mcp
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### Claude Desktop
|
|
117
|
-
|
|
118
|
-
Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
|
|
119
|
-
|
|
120
|
-
```json
|
|
121
|
-
{
|
|
122
|
-
"mcpServers": {
|
|
123
|
-
"quantflow": {
|
|
124
|
-
"command": "uv",
|
|
125
|
-
"args": ["run", "qf-mcp"]
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
```
|
|
118
|
+
## License
|
|
130
119
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
| Tool | Description |
|
|
134
|
-
|---|---|
|
|
135
|
-
| `vault_keys` | List stored API keys |
|
|
136
|
-
| `vault_add` | Add or update an API key |
|
|
137
|
-
| `vault_delete` | Delete an API key |
|
|
138
|
-
| `stock_indices` | List stock market indices |
|
|
139
|
-
| `stock_search` | Search companies by name or symbol |
|
|
140
|
-
| `stock_profile` | Get company profile |
|
|
141
|
-
| `stock_prices` | Get OHLC price history |
|
|
142
|
-
| `sector_performance` | Sector performance and PE ratios |
|
|
143
|
-
| `crypto_instruments` | List Deribit instruments |
|
|
144
|
-
| `crypto_historical_volatility` | Historical volatility from Deribit |
|
|
145
|
-
| `crypto_term_structure` | Volatility term structure |
|
|
146
|
-
| `crypto_implied_volatility` | Implied volatility surface |
|
|
147
|
-
| `crypto_prices` | Crypto OHLC price history |
|
|
148
|
-
| `ascii_chart` | ASCII chart for any stock or crypto symbol |
|
|
149
|
-
| `fred_subcategories` | Browse FRED categories |
|
|
150
|
-
| `fred_series` | List series in a FRED category |
|
|
151
|
-
| `fred_data` | Fetch FRED observations |
|
|
120
|
+
Released under the [BSD 3-Clause License](https://github.com/quantmind/quantflow/blob/main/LICENSE).
|
|
@@ -2,17 +2,19 @@ import os
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
|
|
4
4
|
import marimo
|
|
5
|
-
from fastapi import
|
|
5
|
+
from fastapi import APIRouter, FastAPI
|
|
6
6
|
from fastapi.staticfiles import StaticFiles
|
|
7
7
|
|
|
8
|
-
APP_PATH
|
|
8
|
+
from app.utils.paths import APP_PATH, head_snippet
|
|
9
|
+
|
|
9
10
|
PORT = int(os.environ.get("MICRO_SERVICE_PORT", "8001"))
|
|
10
11
|
status_router = APIRouter()
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
def crate_app() -> FastAPI:
|
|
14
15
|
# Create a marimo asgi app
|
|
15
|
-
|
|
16
|
+
html_head = head_snippet(APP_PATH / "docs")
|
|
17
|
+
server = marimo.create_asgi_app(include_code=True, html_head=html_head)
|
|
16
18
|
for path in APP_PATH.glob("*.py"):
|
|
17
19
|
if path.name.startswith("_"):
|
|
18
20
|
continue
|
|
@@ -25,6 +27,7 @@ def crate_app() -> FastAPI:
|
|
|
25
27
|
app.mount("/", StaticFiles(directory=APP_PATH / "docs", html=True), name="static")
|
|
26
28
|
return app
|
|
27
29
|
|
|
30
|
+
|
|
28
31
|
@status_router.get("/status")
|
|
29
32
|
async def service_status() -> dict:
|
|
30
33
|
return {"status": "ok"}
|
|
@@ -40,9 +40,9 @@ def _(mo):
|
|
|
40
40
|
|
|
41
41
|
We want to construct a mechanism to estimate the Hurst exponent via OHLC data because it is widely available from data providers and easily constructed as an online signal during trading.
|
|
42
42
|
|
|
43
|
-
In order to evaluate results against known solutions, we consider the
|
|
43
|
+
In order to evaluate results against known solutions, we consider the Wiener process as generator of timeseries.
|
|
44
44
|
|
|
45
|
-
We use the **
|
|
45
|
+
We use the **WienerProcess** from the stochastic process library and sample one path over a time horizon of 1 (day) with a time step every second.
|
|
46
46
|
""")
|
|
47
47
|
return
|
|
48
48
|
|
|
@@ -56,24 +56,24 @@ def _(mo):
|
|
|
56
56
|
|
|
57
57
|
@app.cell
|
|
58
58
|
def _(regenerate_btn):
|
|
59
|
-
from quantflow.sp.
|
|
59
|
+
from quantflow.sp.wiener import WienerProcess
|
|
60
60
|
from quantflow.utils import plot
|
|
61
61
|
from quantflow.utils.dates import start_of_day
|
|
62
62
|
|
|
63
63
|
regenerate_btn
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
wiener = WienerProcess(sigma=2.0)
|
|
66
|
+
wiener_paths = wiener.sample(n=1, time_horizon=1, time_steps=24*60*60)
|
|
67
|
+
wiener_df = wiener_paths.as_datetime_df(start=start_of_day(), unit="d").reset_index()
|
|
68
68
|
|
|
69
69
|
plot.plot_lines(
|
|
70
|
-
|
|
71
|
-
x=
|
|
72
|
-
y=
|
|
73
|
-
title="
|
|
74
|
-
labels={"value": "Value", "variable": "Path",
|
|
70
|
+
wiener_df,
|
|
71
|
+
x=wiener_df.columns[0],
|
|
72
|
+
y=wiener_df.columns[1],
|
|
73
|
+
title="Wiener Process Path",
|
|
74
|
+
labels={"value": "Value", "variable": "Path", wiener_df.columns[0]: "Date"},
|
|
75
75
|
)
|
|
76
|
-
return plot, start_of_day,
|
|
76
|
+
return plot, start_of_day, wiener_df, wiener_paths
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
@app.cell
|
|
@@ -90,14 +90,14 @@ def _(mo):
|
|
|
90
90
|
### Realized Variance
|
|
91
91
|
|
|
92
92
|
At this point we estimate the standard deviation using the **realized variance** along the path (we use the **scaled** flag so that the standard deviation is scaled by the square-root of time step, in this way it removes the dependency on the time step size).
|
|
93
|
-
The value should be close to the **sigma** of the
|
|
93
|
+
The value should be close to the **sigma** of the WienerProcess defined above.
|
|
94
94
|
""")
|
|
95
95
|
return
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
@app.cell
|
|
99
|
-
def _(
|
|
100
|
-
float(
|
|
99
|
+
def _(wiener_paths):
|
|
100
|
+
float(wiener_paths.paths_std(scaled=True)[0])
|
|
101
101
|
return
|
|
102
102
|
|
|
103
103
|
|
|
@@ -110,15 +110,15 @@ def _(mo):
|
|
|
110
110
|
|
|
111
111
|
|
|
112
112
|
@app.cell
|
|
113
|
-
def _(
|
|
114
|
-
|
|
113
|
+
def _(wiener_paths):
|
|
114
|
+
wiener_paths.hurst_exponent()
|
|
115
115
|
return
|
|
116
116
|
|
|
117
117
|
|
|
118
118
|
@app.cell
|
|
119
119
|
def _(mo):
|
|
120
120
|
mo.md(r"""
|
|
121
|
-
As expected, the Hurst exponent should be close to 0.5, since we have calculated the exponent from the paths of a
|
|
121
|
+
As expected, the Hurst exponent should be close to 0.5, since we have calculated the exponent from the paths of a Wiener process.
|
|
122
122
|
""")
|
|
123
123
|
return
|
|
124
124
|
|
|
@@ -143,7 +143,7 @@ def _(mo):
|
|
|
143
143
|
|
|
144
144
|
|
|
145
145
|
@app.cell
|
|
146
|
-
def _(
|
|
146
|
+
def _(wiener_df):
|
|
147
147
|
import pandas as pd
|
|
148
148
|
import polars as pl
|
|
149
149
|
import math
|
|
@@ -167,7 +167,7 @@ def _(weiner_df):
|
|
|
167
167
|
results = []
|
|
168
168
|
for period in ("10s", "20s", "30s", "1m", "2m", "3m", "5m", "10m", "30m"):
|
|
169
169
|
ohlc = template.model_copy(update=dict(period=period))
|
|
170
|
-
rf = ohlc(
|
|
170
|
+
rf = ohlc(wiener_df)
|
|
171
171
|
ts = pd.to_timedelta(period).to_pytimedelta().total_seconds()
|
|
172
172
|
data = dict(period=period)
|
|
173
173
|
for name in ("pk", "gk", "rs"):
|
|
@@ -255,15 +255,15 @@ def _(OHLC, pd):
|
|
|
255
255
|
|
|
256
256
|
|
|
257
257
|
@app.cell
|
|
258
|
-
def _(ohlc_hurst_exponent,
|
|
259
|
-
ohlc_hurst_exponent(
|
|
258
|
+
def _(ohlc_hurst_exponent, wiener_df):
|
|
259
|
+
ohlc_hurst_exponent(wiener_df, series=["0"])
|
|
260
260
|
return
|
|
261
261
|
|
|
262
262
|
|
|
263
263
|
@app.cell
|
|
264
264
|
def _(mo):
|
|
265
265
|
mo.md(r"""
|
|
266
|
-
The Hurst exponent should be close to 0.5, since we have calculated the exponent from the paths of a
|
|
266
|
+
The Hurst exponent should be close to 0.5, since we have calculated the exponent from the paths of a Wiener process. But it is not exactly 0.5 because the range-based estimators are not the same as the realized variance. Interestingly, the Parkinson estimator gives a Hurst exponent closer to 0.5 than the Garman-Klass and Rogers-Satchell estimators.
|
|
267
267
|
|
|
268
268
|
## Mean Reverting Time Series
|
|
269
269
|
|