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.
Files changed (243) hide show
  1. {quantflow-0.6.2 → quantflow-0.6.3}/.github/copilot-instructions.md +7 -0
  2. {quantflow-0.6.2 → quantflow-0.6.3}/.vscode/launch.json +1 -1
  3. {quantflow-0.6.2 → quantflow-0.6.3}/Makefile +4 -0
  4. {quantflow-0.6.2 → quantflow-0.6.3}/PKG-INFO +2 -1
  5. {quantflow-0.6.2 → quantflow-0.6.3}/app/gaussian_sampling.py +1 -1
  6. quantflow-0.6.3/app/heston_divfm_fit.py +276 -0
  7. quantflow-0.6.3/app/heston_vol_surface.py +165 -0
  8. quantflow-0.6.3/app/scripts/heston_divfm_fit.py +208 -0
  9. {quantflow-0.6.2 → quantflow-0.6.3}/app/volatility_surface.py +21 -32
  10. quantflow-0.6.3/docs/api/data/index.md +33 -0
  11. quantflow-0.6.3/docs/api/index.md +71 -0
  12. quantflow-0.6.3/docs/api/options/divfm.md +30 -0
  13. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/options/pricer.md +1 -0
  14. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/options/vol_surface.md +3 -1
  15. quantflow-0.6.3/docs/api/sp/copula.md +10 -0
  16. quantflow-0.6.3/docs/assets/heston_calibrated_smile.png +0 -0
  17. quantflow-0.6.3/docs/assets/hestonj_calibrated_smile.png +0 -0
  18. {quantflow-0.6.2 → quantflow-0.6.3}/docs/bibliography.md +8 -0
  19. quantflow-0.6.3/docs/examples/vol_surface_heston_calibration.py +33 -0
  20. quantflow-0.6.3/docs/examples/vol_surface_hestonj_calibration.py +46 -0
  21. quantflow-0.6.3/docs/examples/vol_surface_inputs.py +24 -0
  22. quantflow-0.6.3/docs/examples_png/vol_surface_heston_plot.py +35 -0
  23. quantflow-0.6.3/docs/examples_png/vol_surface_hestonj_plot.py +46 -0
  24. quantflow-0.6.3/docs/glossary.md +110 -0
  25. quantflow-0.6.3/docs/tutorials/index.md +8 -0
  26. quantflow-0.6.3/docs/tutorials/volatility_surface.md +185 -0
  27. {quantflow-0.6.2 → quantflow-0.6.3}/mkdocs.yml +5 -0
  28. {quantflow-0.6.2 → quantflow-0.6.3}/pyproject.toml +2 -1
  29. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/data/deribit.py +25 -3
  30. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/options/calibration.py +48 -6
  31. quantflow-0.6.3/quantflow/options/divfm/__init__.py +4 -0
  32. quantflow-0.6.3/quantflow/options/divfm/network.py +210 -0
  33. quantflow-0.6.3/quantflow/options/divfm/pricer.py +137 -0
  34. quantflow-0.6.3/quantflow/options/divfm/trainer.py +181 -0
  35. quantflow-0.6.3/quantflow/options/divfm/weights.py +154 -0
  36. quantflow-0.6.3/quantflow/options/docs/butterfly.md +44 -0
  37. quantflow-0.6.3/quantflow/options/docs/calendar_spread.md +47 -0
  38. quantflow-0.6.3/quantflow/options/docs/spread.md +36 -0
  39. quantflow-0.6.3/quantflow/options/docs/straddle.md +22 -0
  40. quantflow-0.6.3/quantflow/options/docs/strangle.md +23 -0
  41. quantflow-0.6.3/quantflow/options/docs/terminology.md +5 -0
  42. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/options/pricer.py +56 -25
  43. quantflow-0.6.3/quantflow/options/strategies/__init__.py +17 -0
  44. quantflow-0.6.3/quantflow/options/strategies/base.py +111 -0
  45. quantflow-0.6.3/quantflow/options/strategies/butterfly.py +100 -0
  46. quantflow-0.6.3/quantflow/options/strategies/calendar_spread.py +75 -0
  47. quantflow-0.6.3/quantflow/options/strategies/spread.py +73 -0
  48. quantflow-0.6.3/quantflow/options/strategies/straddle.py +39 -0
  49. quantflow-0.6.3/quantflow/options/strategies/strangle.py +68 -0
  50. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/options/surface.py +10 -2
  51. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/base.py +7 -5
  52. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/copula.py +7 -6
  53. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/heston.py +6 -2
  54. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/ou.py +0 -2
  55. quantflow-0.6.3/quantflow/utils/__init__.py +0 -0
  56. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/distributions.py +8 -7
  57. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/plot.py +10 -2
  58. quantflow-0.6.3/quantflow_tests/fixtures/deribit_futures.json +23 -0
  59. quantflow-0.6.3/quantflow_tests/fixtures/deribit_instruments.json +48 -0
  60. quantflow-0.6.3/quantflow_tests/fixtures/deribit_options.json +30 -0
  61. quantflow-0.6.3/quantflow_tests/test_data_deribit.py +84 -0
  62. quantflow-0.6.3/quantflow_tests/test_divfm.py +311 -0
  63. quantflow-0.6.3/quantflow_tests/test_strategies.py +109 -0
  64. quantflow-0.6.3/quantflow_tests/volsurface.json +4359 -0
  65. {quantflow-0.6.2 → quantflow-0.6.3}/uv.lock +204 -36
  66. quantflow-0.6.2/docs/api/data/index.md +0 -8
  67. quantflow-0.6.2/docs/api/index.md +0 -3
  68. quantflow-0.6.2/notebooks/CNAME +0 -1
  69. quantflow-0.6.2/notebooks/_config.yml +0 -65
  70. quantflow-0.6.2/notebooks/_toc.yml +0 -46
  71. quantflow-0.6.2/notebooks/applications/hurst.md +0 -202
  72. quantflow-0.6.2/notebooks/applications/overview.md +0 -23
  73. quantflow-0.6.2/notebooks/applications/sampling.md +0 -35
  74. quantflow-0.6.2/notebooks/conf.py +0 -38
  75. quantflow-0.6.2/notebooks/examples/heston_vol_surface.md +0 -54
  76. quantflow-0.6.2/notebooks/index.md +0 -54
  77. quantflow-0.6.2/notebooks/reference/biblio.md +0 -18
  78. quantflow-0.6.2/notebooks/reference/contributing.md +0 -68
  79. quantflow-0.6.2/notebooks/reference/glossary.md +0 -80
  80. {quantflow-0.6.2 → quantflow-0.6.3}/.coveragerc +0 -0
  81. {quantflow-0.6.2 → quantflow-0.6.3}/.dockerignore +0 -0
  82. {quantflow-0.6.2 → quantflow-0.6.3}/.github/workflows/build.yml +0 -0
  83. {quantflow-0.6.2 → quantflow-0.6.3}/.github/workflows/deploy.yml +0 -0
  84. {quantflow-0.6.2 → quantflow-0.6.3}/.github/workflows/docker-multiarch.yml +0 -0
  85. {quantflow-0.6.2 → quantflow-0.6.3}/.gitignore +0 -0
  86. {quantflow-0.6.2 → quantflow-0.6.3}/.vscode/settings.json +0 -0
  87. {quantflow-0.6.2 → quantflow-0.6.3}/.vscode/tasks.json +0 -0
  88. {quantflow-0.6.2 → quantflow-0.6.3}/CITATION.cff +0 -0
  89. {quantflow-0.6.2 → quantflow-0.6.3}/CLAUDE.md +0 -0
  90. {quantflow-0.6.2 → quantflow-0.6.3}/LICENSE +0 -0
  91. {quantflow-0.6.2 → quantflow-0.6.3}/app/__main__.py +0 -0
  92. {quantflow-0.6.2 → quantflow-0.6.3}/app/cointegration.py +0 -0
  93. {quantflow-0.6.2 → quantflow-0.6.3}/app/double_exponential_sampling.py +0 -0
  94. {quantflow-0.6.2 → quantflow-0.6.3}/app/hurst.py +0 -0
  95. {quantflow-0.6.2 → quantflow-0.6.3}/app/poisson_sampling.py +0 -0
  96. {quantflow-0.6.2/quantflow/ai/tools → quantflow-0.6.3/app/scripts}/__init__.py +0 -0
  97. {quantflow-0.6.2 → quantflow-0.6.3}/app/supersmoother.py +0 -0
  98. {quantflow-0.6.2 → quantflow-0.6.3}/app/utils/__init__.py +0 -0
  99. {quantflow-0.6.2 → quantflow-0.6.3}/dev/blocks/quantflow.yaml +0 -0
  100. {quantflow-0.6.2 → quantflow-0.6.3}/dev/build-examples +0 -0
  101. {quantflow-0.6.2 → quantflow-0.6.3}/dev/charts.yaml +0 -0
  102. {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/.helmignore +0 -0
  103. {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/Chart.yaml +0 -0
  104. {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/templates/_helpers.tpl +0 -0
  105. {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/templates/_service.tpl +0 -0
  106. {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/templates/app.yaml +0 -0
  107. {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/templates/configmap.yaml +0 -0
  108. {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/templates/secret.yaml +0 -0
  109. {quantflow-0.6.2 → quantflow-0.6.3}/dev/helm/values.yaml +0 -0
  110. {quantflow-0.6.2 → quantflow-0.6.3}/dev/install +0 -0
  111. {quantflow-0.6.2 → quantflow-0.6.3}/dev/lint +0 -0
  112. {quantflow-0.6.2 → quantflow-0.6.3}/dev/marimo +0 -0
  113. {quantflow-0.6.2 → quantflow-0.6.3}/dev/quantflow.dockerfile +0 -0
  114. {quantflow-0.6.2 → quantflow-0.6.3}/dev/test +0 -0
  115. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/data/deribit.md +0 -0
  116. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/data/fed.md +0 -0
  117. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/data/fmp.md +0 -0
  118. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/data/fred.md +0 -0
  119. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/options/black.md +0 -0
  120. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/options/calibration.md +0 -0
  121. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/options/index.md +0 -0
  122. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/cir.md +0 -0
  123. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/compound_poisson.md +0 -0
  124. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/dsp.md +0 -0
  125. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/heston.md +0 -0
  126. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/index.md +0 -0
  127. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/jump_diffusion.md +0 -0
  128. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/ou.md +0 -0
  129. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/poisson.md +0 -0
  130. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/sp/weiner.md +0 -0
  131. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/ta/ewma.md +0 -0
  132. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/ta/index.md +0 -0
  133. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/ta/kalman.md +0 -0
  134. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/ta/ohlc.md +0 -0
  135. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/ta/paths.md +0 -0
  136. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/ta/supersmoother.md +0 -0
  137. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/utils/bins.md +0 -0
  138. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/utils/distributions.md +0 -0
  139. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/utils/index.md +0 -0
  140. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/utils/marginal1d.md +0 -0
  141. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/utils/numbers.md +0 -0
  142. {quantflow-0.6.2 → quantflow-0.6.3}/docs/api/utils/types.md +0 -0
  143. {quantflow-0.6.2 → quantflow-0.6.3}/docs/assets/heston.gif +0 -0
  144. {quantflow-0.6.2 → quantflow-0.6.3}/docs/assets/linkedin-banner.png +0 -0
  145. {quantflow-0.6.2 → quantflow-0.6.3}/docs/assets/quantflow-light.svg +0 -0
  146. {quantflow-0.6.2 → quantflow-0.6.3}/docs/assets/quantflow-logo.png +0 -0
  147. {quantflow-0.6.2 → quantflow-0.6.3}/docs/assets/quantflow-repo.png +0 -0
  148. {quantflow-0.6.2 → quantflow-0.6.3}/docs/assets/quantflow-repo.svg +0 -0
  149. {quantflow-0.6.2 → quantflow-0.6.3}/docs/assets/quantflow.svg +0 -0
  150. {quantflow-0.6.2 → quantflow-0.6.3}/docs/contributing.md +0 -0
  151. {quantflow-0.6.2 → quantflow-0.6.3}/docs/examples/heston_volatility_pricer.py +0 -0
  152. {quantflow-0.6.2/quantflow_tests → quantflow-0.6.3/docs/examples}/volsurface.json +0 -0
  153. {quantflow-0.6.2 → quantflow-0.6.3}/docs/examples/weiner_volatility_pricer.py +0 -0
  154. {quantflow-0.6.2 → quantflow-0.6.3}/docs/index.md +0 -0
  155. {quantflow-0.6.2 → quantflow-0.6.3}/docs/javascripts/mathjax.js +0 -0
  156. {quantflow-0.6.2/notebooks/reference → quantflow-0.6.3/docs}/references.bib +0 -0
  157. {quantflow-0.6.2 → quantflow-0.6.3}/docs/theory/characteristic.md +0 -0
  158. {quantflow-0.6.2 → quantflow-0.6.3}/docs/theory/index.md +0 -0
  159. {quantflow-0.6.2 → quantflow-0.6.3}/docs/theory/inversion.md +0 -0
  160. {quantflow-0.6.2 → quantflow-0.6.3}/docs/theory/levy.md +0 -0
  161. {quantflow-0.6.2 → quantflow-0.6.3}/docs/theory/option_pricing.md +0 -0
  162. {quantflow-0.6.2 → quantflow-0.6.3}/docs/tutorials/option_pricing.md +0 -0
  163. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/applications/calibration.md +0 -0
  164. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/applications/calibration.py +0 -0
  165. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/applications/volatility_surface.md +0 -0
  166. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/data/fed.md +0 -0
  167. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/data/fiscal_data.md +0 -0
  168. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/data/fmp.md +0 -0
  169. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/data/timeseries.md +0 -0
  170. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/bns.md +0 -0
  171. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/cir.md +0 -0
  172. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/gousv.md +0 -0
  173. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/heston.md +0 -0
  174. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/heston_jumps.md +0 -0
  175. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/jump_diffusion.md +0 -0
  176. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/ou.md +0 -0
  177. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/overview.md +0 -0
  178. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/poisson.md +0 -0
  179. {quantflow-0.6.2 → quantflow-0.6.3}/notebooks/models/weiner.md +0 -0
  180. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/__init__.py +0 -0
  181. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/__init__.py +0 -0
  182. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/server.py +0 -0
  183. {quantflow-0.6.2/quantflow/data → quantflow-0.6.3/quantflow/ai/tools}/__init__.py +0 -0
  184. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/tools/base.py +0 -0
  185. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/tools/charts.py +0 -0
  186. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/tools/crypto.py +0 -0
  187. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/tools/fred.py +0 -0
  188. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/tools/stocks.py +0 -0
  189. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ai/tools/vault.py +0 -0
  190. {quantflow-0.6.2/quantflow/options → quantflow-0.6.3/quantflow/data}/__init__.py +0 -0
  191. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/data/fed.py +0 -0
  192. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/data/fiscal_data.py +0 -0
  193. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/data/fmp.py +0 -0
  194. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/data/fred.py +0 -0
  195. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/data/vault.py +0 -0
  196. {quantflow-0.6.2/quantflow/sp → quantflow-0.6.3/quantflow/options}/__init__.py +0 -0
  197. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/options/bs.py +0 -0
  198. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/options/inputs.py +0 -0
  199. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/py.typed +0 -0
  200. {quantflow-0.6.2/quantflow/utils → quantflow-0.6.3/quantflow/sp}/__init__.py +0 -0
  201. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/bns.py +0 -0
  202. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/cir.py +0 -0
  203. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/dsp.py +0 -0
  204. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/jump_diffusion.py +0 -0
  205. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/poisson.py +0 -0
  206. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/sp/weiner.py +0 -0
  207. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ta/__init__.py +0 -0
  208. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ta/base.py +0 -0
  209. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ta/ewma.py +0 -0
  210. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ta/kalman.py +0 -0
  211. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ta/ohlc.py +0 -0
  212. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ta/paths.py +0 -0
  213. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/ta/supersmoother.py +0 -0
  214. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/bins.py +0 -0
  215. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/dates.py +0 -0
  216. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/functions.py +0 -0
  217. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/interest_rates.py +0 -0
  218. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/marginal.py +0 -0
  219. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/numbers.py +0 -0
  220. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/transforms.py +0 -0
  221. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow/utils/types.py +0 -0
  222. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/conftest.py +0 -0
  223. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_ai.py +0 -0
  224. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_cir.py +0 -0
  225. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_copula.py +0 -0
  226. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_data.py +0 -0
  227. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_distributions.py +0 -0
  228. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_frft.py +0 -0
  229. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_heston.py +0 -0
  230. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_jump_diffusion.py +0 -0
  231. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_ohlc.py +0 -0
  232. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_options.py +0 -0
  233. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_options_pricer.py +0 -0
  234. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_ou.py +0 -0
  235. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_poisson.py +0 -0
  236. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_utils.py +0 -0
  237. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_vault.py +0 -0
  238. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/test_weiner.py +0 -0
  239. {quantflow-0.6.2 → quantflow-0.6.3}/quantflow_tests/utils.py +0 -0
  240. {quantflow-0.6.2 → quantflow-0.6.3}/readme.md +0 -0
  241. {quantflow-0.6.2 → quantflow-0.6.3}/rops.toml +0 -0
  242. {quantflow-0.6.2 → quantflow-0.6.3}/taplo.toml +0 -0
  243. {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
@@ -14,7 +14,7 @@
14
14
  "args": [
15
15
  "-x",
16
16
  "-vvv",
17
- "quantflow_tests/test_options_pricer.py",
17
+ "quantflow_tests/test_divfm.py",
18
18
  ]
19
19
  },
20
20
  ]
@@ -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.2
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'
@@ -1,4 +1,4 @@
1
- import marimo
1
+ import marimo
2
2
 
3
3
  __generated_with = "0.19.7"
4
4
  app = marimo.App(width="medium")
@@ -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()