quantark 0.1.0__py3-none-any.whl

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 (399) hide show
  1. quantark/__init__.py +3 -0
  2. quantark/_compat.py +150 -0
  3. quantark/asset/__init__.py +8 -0
  4. quantark/asset/bond/__init__.py +2 -0
  5. quantark/asset/bond/engine/__init__.py +44 -0
  6. quantark/asset/bond/engine/analytical/__init__.py +12 -0
  7. quantark/asset/bond/engine/analytical/black_engine.py +583 -0
  8. quantark/asset/bond/engine/analytical/bond_forward_engine.py +390 -0
  9. quantark/asset/bond/engine/analytical/bond_futures_engine.py +569 -0
  10. quantark/asset/bond/engine/convertible/__init__.py +12 -0
  11. quantark/asset/bond/engine/convertible/convertible_bond_engine.py +800 -0
  12. quantark/asset/bond/engine/discount/__init__.py +10 -0
  13. quantark/asset/bond/engine/discount/bond_discount_engine.py +517 -0
  14. quantark/asset/bond/engine/discount/frn_engine.py +913 -0
  15. quantark/asset/bond/engine/pde/__init__.py +14 -0
  16. quantark/asset/bond/engine/pde/convertible/__init__.py +21 -0
  17. quantark/asset/bond/engine/pde/convertible/jump_diffusion_engine.py +603 -0
  18. quantark/asset/bond/engine/pde/convertible/pde_params.py +59 -0
  19. quantark/asset/bond/engine/pde/convertible/tf_engine.py +546 -0
  20. quantark/asset/bond/engine/tree/__init__.py +14 -0
  21. quantark/asset/bond/engine/tree/convertible/__init__.py +21 -0
  22. quantark/asset/bond/engine/tree/convertible/binomial_engine.py +488 -0
  23. quantark/asset/bond/engine/tree/convertible/tree_params.py +72 -0
  24. quantark/asset/bond/engine/tree/convertible/trinomial_engine.py +1341 -0
  25. quantark/asset/bond/product/__init__.py +37 -0
  26. quantark/asset/bond/product/base_bond_product.py +114 -0
  27. quantark/asset/bond/product/convertible/__init__.py +16 -0
  28. quantark/asset/bond/product/convertible/convertible_bond.py +595 -0
  29. quantark/asset/bond/product/couponbond/__init__.py +12 -0
  30. quantark/asset/bond/product/couponbond/fixed_bond.py +285 -0
  31. quantark/asset/bond/product/couponbond/frn.py +538 -0
  32. quantark/asset/bond/product/forward/__init__.py +9 -0
  33. quantark/asset/bond/product/forward/base_bond_forward.py +92 -0
  34. quantark/asset/bond/product/forward/bond_forward.py +335 -0
  35. quantark/asset/bond/product/futures/__init__.py +8 -0
  36. quantark/asset/bond/product/futures/bond_futures.py +532 -0
  37. quantark/asset/bond/product/option/__init__.py +9 -0
  38. quantark/asset/bond/product/option/euro_short_term_bond_option.py +231 -0
  39. quantark/asset/bond/riskmeasures/__init__.py +13 -0
  40. quantark/asset/bond/riskmeasures/bond_greeks_calculator.py +484 -0
  41. quantark/asset/bond/schedule/__init__.py +21 -0
  42. quantark/asset/bond/schedule/cashflow.py +595 -0
  43. quantark/asset/equity/__init__.py +11 -0
  44. quantark/asset/equity/analysis/__init__.py +4 -0
  45. quantark/asset/equity/analysis/autocallable_path_analyzer.py +257 -0
  46. quantark/asset/equity/engine/__init__.py +84 -0
  47. quantark/asset/equity/engine/analytical/__init__.py +37 -0
  48. quantark/asset/equity/engine/analytical/american_option_engine.py +682 -0
  49. quantark/asset/equity/engine/analytical/asian_option_analytical_engine.py +1102 -0
  50. quantark/asset/equity/engine/analytical/barrier_analytical_engine.py +455 -0
  51. quantark/asset/equity/engine/analytical/black_scholes_engine.py +322 -0
  52. quantark/asset/equity/engine/analytical/deltaone_engine.py +340 -0
  53. quantark/asset/equity/engine/analytical/digital_option_engine.py +168 -0
  54. quantark/asset/equity/engine/analytical/double_barrier_option_engine.py +481 -0
  55. quantark/asset/equity/engine/analytical/double_sharkfin_option_analytical_engine.py +508 -0
  56. quantark/asset/equity/engine/analytical/one_touch_analytical_engine.py +302 -0
  57. quantark/asset/equity/engine/analytical/range_accrual_analytical_engine.py +396 -0
  58. quantark/asset/equity/engine/analytical/single_sharkfin_option_analytical_engine.py +229 -0
  59. quantark/asset/equity/engine/base_engine.py +137 -0
  60. quantark/asset/equity/engine/event_stats.py +85 -0
  61. quantark/asset/equity/engine/mc/__init__.py +31 -0
  62. quantark/asset/equity/engine/mc/american_option_mc_engine.py +485 -0
  63. quantark/asset/equity/engine/mc/asian_option_mc_engine.py +678 -0
  64. quantark/asset/equity/engine/mc/barrier_option_mc_engine.py +726 -0
  65. quantark/asset/equity/engine/mc/digital_option_mc_engine.py +419 -0
  66. quantark/asset/equity/engine/mc/double_sharkfin_option_mc_engine.py +676 -0
  67. quantark/asset/equity/engine/mc/euro_mc_engine.py +423 -0
  68. quantark/asset/equity/engine/mc/phoenix_mc_engine.py +1206 -0
  69. quantark/asset/equity/engine/mc/range_accrual_mc_engine.py +738 -0
  70. quantark/asset/equity/engine/mc/single_sharkfin_option_mc_engine.py +549 -0
  71. quantark/asset/equity/engine/mc/snowball_mc_engine.py +2250 -0
  72. quantark/asset/equity/engine/pde/__init__.py +36 -0
  73. quantark/asset/equity/engine/pde/american_pde_solver.py +211 -0
  74. quantark/asset/equity/engine/pde/barrier_pde_solver.py +692 -0
  75. quantark/asset/equity/engine/pde/base_pde_solver.py +994 -0
  76. quantark/asset/equity/engine/pde/double_barrier_pde_solver.py +510 -0
  77. quantark/asset/equity/engine/pde/double_one_touch_pde_solver.py +435 -0
  78. quantark/asset/equity/engine/pde/european_pde_solver.py +170 -0
  79. quantark/asset/equity/engine/pde/ko_reset_snowball_pde_solver.py +477 -0
  80. quantark/asset/equity/engine/pde/one_touch_pde_solver.py +439 -0
  81. quantark/asset/equity/engine/pde/phoenix_pde_solver.py +613 -0
  82. quantark/asset/equity/engine/pde/snowball_pde_solver.py +1810 -0
  83. quantark/asset/equity/engine/pde/spatial_grid.py +750 -0
  84. quantark/asset/equity/engine/pde/time_grid.py +308 -0
  85. quantark/asset/equity/engine/pde_engine.py +238 -0
  86. quantark/asset/equity/engine/quad/__init__.py +23 -0
  87. quantark/asset/equity/engine/quad/discrete_quad_engine.py +106 -0
  88. quantark/asset/equity/engine/quad/european_quad_engine.py +325 -0
  89. quantark/asset/equity/engine/quad/ko_reset_snowball_quad_engine.py +362 -0
  90. quantark/asset/equity/engine/quad/phoenix_quad_engine.py +614 -0
  91. quantark/asset/equity/engine/quad/quad_adapters.py +1260 -0
  92. quantark/asset/equity/engine/quad/quad_core.py +513 -0
  93. quantark/asset/equity/engine/quad/quad_math.py +219 -0
  94. quantark/asset/equity/engine/quad/snowball_quad_engine.py +1137 -0
  95. quantark/asset/equity/engine/validation/script/benchmark_check_american_analytical.py +117 -0
  96. quantark/asset/equity/engine/validation/script/benchmark_check_american_pde.py +114 -0
  97. quantark/asset/equity/engine/validation/script/benchmark_check_asian_analytical.py +440 -0
  98. quantark/asset/equity/engine/validation/script/benchmark_check_barrier_analytical.py +269 -0
  99. quantark/asset/equity/engine/validation/script/benchmark_check_barrier_pde_solver.py +636 -0
  100. quantark/asset/equity/engine/validation/script/benchmark_check_digital_option.py +256 -0
  101. quantark/asset/equity/engine/validation/script/benchmark_check_snowball_pde_solver.py +807 -0
  102. quantark/asset/equity/engine/validation/script/boundary_check_american_analytical.py +290 -0
  103. quantark/asset/equity/engine/validation/script/boundary_check_american_pde.py +242 -0
  104. quantark/asset/equity/engine/validation/script/boundary_check_asian_analytical.py +612 -0
  105. quantark/asset/equity/engine/validation/script/boundary_check_barrier_analytical.py +434 -0
  106. quantark/asset/equity/engine/validation/script/boundary_check_barrier_pde_solver.py +748 -0
  107. quantark/asset/equity/engine/validation/script/boundary_check_digital_option.py +575 -0
  108. quantark/asset/equity/engine/validation/script/boundary_check_snowball_pde_solver.py +1101 -0
  109. quantark/asset/equity/engine/validation/script/greeks_check_digital_option.py +349 -0
  110. quantark/asset/equity/engine/validation/script/mc_comparison_barrier_pde.py +270 -0
  111. quantark/asset/equity/engine/validation/script/quick_mc_compare.py +51 -0
  112. quantark/asset/equity/engine/validation/script/validation_stepdown_improved.py +97 -0
  113. quantark/asset/equity/param/__init__.py +24 -0
  114. quantark/asset/equity/param/engine_param_profiles.py +325 -0
  115. quantark/asset/equity/param/engine_params.py +728 -0
  116. quantark/asset/equity/process/__init__.py +7 -0
  117. quantark/asset/equity/process/bsm/__init__.py +7 -0
  118. quantark/asset/equity/process/bsm/bsm_process.py +108 -0
  119. quantark/asset/equity/process/bsm/qmc_brownian_bridge.py +401 -0
  120. quantark/asset/equity/process/bsm/qmc_path_generator.py +694 -0
  121. quantark/asset/equity/process/bsm/qmc_rqmc_driver.py +163 -0
  122. quantark/asset/equity/process/bsm/qmc_sobol.py +195 -0
  123. quantark/asset/equity/process/bsm/qmc_variance_reduction.py +292 -0
  124. quantark/asset/equity/product/__init__.py +8 -0
  125. quantark/asset/equity/product/base_equity_product.py +72 -0
  126. quantark/asset/equity/product/deltaone/__init__.py +22 -0
  127. quantark/asset/equity/product/deltaone/base_deltaone_product.py +147 -0
  128. quantark/asset/equity/product/deltaone/futures.py +485 -0
  129. quantark/asset/equity/product/deltaone/spot_instrument.py +118 -0
  130. quantark/asset/equity/product/option/__init__.py +104 -0
  131. quantark/asset/equity/product/option/american_option.py +114 -0
  132. quantark/asset/equity/product/option/asian_option.py +531 -0
  133. quantark/asset/equity/product/option/barrier_option.py +289 -0
  134. quantark/asset/equity/product/option/base_equity_option.py +659 -0
  135. quantark/asset/equity/product/option/digital_option.py +102 -0
  136. quantark/asset/equity/product/option/double_barrier_option.py +286 -0
  137. quantark/asset/equity/product/option/double_one_touch_option.py +310 -0
  138. quantark/asset/equity/product/option/double_sharkfin_option.py +466 -0
  139. quantark/asset/equity/product/option/european_vanilla_option.py +103 -0
  140. quantark/asset/equity/product/option/ko_reset_snowball_option.py +563 -0
  141. quantark/asset/equity/product/option/observation_schedule.py +530 -0
  142. quantark/asset/equity/product/option/one_touch_option.py +287 -0
  143. quantark/asset/equity/product/option/phoenix_config.py +116 -0
  144. quantark/asset/equity/product/option/phoenix_helpers.py +576 -0
  145. quantark/asset/equity/product/option/phoenix_option.py +1167 -0
  146. quantark/asset/equity/product/option/range_accrual_config.py +288 -0
  147. quantark/asset/equity/product/option/range_accrual_helpers.py +608 -0
  148. quantark/asset/equity/product/option/range_accrual_option.py +526 -0
  149. quantark/asset/equity/product/option/single_sharkfin_option.py +420 -0
  150. quantark/asset/equity/product/option/snowball_config.py +261 -0
  151. quantark/asset/equity/product/option/snowball_helpers.py +977 -0
  152. quantark/asset/equity/product/option/snowball_option.py +1242 -0
  153. quantark/asset/equity/report/__init__.py +15 -0
  154. quantark/asset/equity/report/autocallable_risk_report.py +2118 -0
  155. quantark/asset/equity/report/plotting.py +87 -0
  156. quantark/asset/equity/report/snowball_risk_comparison_report.py +2230 -0
  157. quantark/asset/equity/report/surfaces.py +123 -0
  158. quantark/asset/equity/report/term_structure.py +126 -0
  159. quantark/asset/equity/riskmeasures/__init__.py +7 -0
  160. quantark/asset/equity/riskmeasures/greeks_calculator.py +1204 -0
  161. quantark/asset/rate/__init__.py +58 -0
  162. quantark/asset/rate/engine/__init__.py +25 -0
  163. quantark/asset/rate/engine/cap_floor_engine.py +514 -0
  164. quantark/asset/rate/engine/fra_engine.py +286 -0
  165. quantark/asset/rate/engine/irs_discount_engine.py +891 -0
  166. quantark/asset/rate/engine/swaption_engine.py +587 -0
  167. quantark/asset/rate/product/__init__.py +67 -0
  168. quantark/asset/rate/product/cap_floor.py +550 -0
  169. quantark/asset/rate/product/fra.py +219 -0
  170. quantark/asset/rate/product/irs.py +1223 -0
  171. quantark/asset/rate/product/swaption.py +372 -0
  172. quantark/backtest/__init__.py +153 -0
  173. quantark/backtest/base.py +263 -0
  174. quantark/backtest/dashboard.py +874 -0
  175. quantark/backtest/equity/__init__.py +35 -0
  176. quantark/backtest/equity/config.py +118 -0
  177. quantark/backtest/equity/engine.py +408 -0
  178. quantark/backtest/equity/hedge_executor.py +374 -0
  179. quantark/backtest/equity/metrics.py +396 -0
  180. quantark/backtest/equity/results.py +232 -0
  181. quantark/backtest/equity/state.py +252 -0
  182. quantark/backtest/examples/__init__.py +4 -0
  183. quantark/backtest/examples/advanced_backtest.py +345 -0
  184. quantark/backtest/examples/basic_delta_hedge.py +246 -0
  185. quantark/backtest/examples/fi_dv01_hedge.py +267 -0
  186. quantark/backtest/fi/__init__.py +30 -0
  187. quantark/backtest/fi/config.py +114 -0
  188. quantark/backtest/fi/engine.py +378 -0
  189. quantark/backtest/fi/hedge_executor.py +254 -0
  190. quantark/backtest/fi/metrics.py +308 -0
  191. quantark/backtest/fi/results.py +193 -0
  192. quantark/backtest/fi/state.py +212 -0
  193. quantark/backtest/logger.py +393 -0
  194. quantark/backtest/otc/__init__.py +74 -0
  195. quantark/backtest/otc/_replay.py +637 -0
  196. quantark/backtest/otc/book_engine.py +587 -0
  197. quantark/backtest/otc/config.py +175 -0
  198. quantark/backtest/otc/dashboard.py +1006 -0
  199. quantark/backtest/otc/engine.py +420 -0
  200. quantark/backtest/otc/engine_factory.py +138 -0
  201. quantark/backtest/otc/market.py +216 -0
  202. quantark/backtest/otc/results.py +107 -0
  203. quantark/backtest/otc/state.py +166 -0
  204. quantark/backtest/report_generator.py +608 -0
  205. quantark/backtest/strategy/__init__.py +28 -0
  206. quantark/backtest/strategy/base_strategy.py +235 -0
  207. quantark/backtest/strategy/convexity_neutral_strategy.py +247 -0
  208. quantark/backtest/strategy/delta_neutral_strategy.py +283 -0
  209. quantark/backtest/strategy/dv01_neutral_strategy.py +283 -0
  210. quantark/backtest/transaction_costs.py +485 -0
  211. quantark/backtest/visualizer.py +1019 -0
  212. quantark/cashleg/__init__.py +31 -0
  213. quantark/cashleg/accrual_leg.py +120 -0
  214. quantark/cashleg/base.py +48 -0
  215. quantark/cashleg/base_amount.py +60 -0
  216. quantark/cashleg/deterministic_leg.py +39 -0
  217. quantark/cashleg/event_distribution.py +262 -0
  218. quantark/cashleg/fixed_payoff_leg.py +92 -0
  219. quantark/cashleg/leg_schedule.py +95 -0
  220. quantark/cashleg/leg_valuator.py +40 -0
  221. quantark/dynamicscenario/__init__.py +97 -0
  222. quantark/dynamicscenario/base.py +297 -0
  223. quantark/dynamicscenario/config.py +122 -0
  224. quantark/dynamicscenario/engine.py +703 -0
  225. quantark/dynamicscenario/equity/__init__.py +14 -0
  226. quantark/dynamicscenario/fi/__init__.py +24 -0
  227. quantark/dynamicscenario/fi/config.py +149 -0
  228. quantark/dynamicscenario/fi/engine.py +500 -0
  229. quantark/dynamicscenario/fi/results.py +503 -0
  230. quantark/dynamicscenario/path/__init__.py +17 -0
  231. quantark/dynamicscenario/path/day_path.py +397 -0
  232. quantark/dynamicscenario/path/fi_path_library.py +488 -0
  233. quantark/dynamicscenario/path/path_builder.py +726 -0
  234. quantark/dynamicscenario/path/path_library.py +620 -0
  235. quantark/dynamicscenario/report/__init__.py +12 -0
  236. quantark/dynamicscenario/report/dynamic_report.py +1175 -0
  237. quantark/dynamicscenario/report/visualizer.py +1586 -0
  238. quantark/dynamicscenario/results/__init__.py +19 -0
  239. quantark/dynamicscenario/results/dynamic_results.py +579 -0
  240. quantark/dynamicscenario/results/result_exporter.py +438 -0
  241. quantark/param/__init__.py +75 -0
  242. quantark/param/basis/__init__.py +19 -0
  243. quantark/param/basis/basis_yield.py +301 -0
  244. quantark/param/div/__init__.py +16 -0
  245. quantark/param/div/dividend_yield.py +123 -0
  246. quantark/param/index/__init__.py +52 -0
  247. quantark/param/index/rate_index.py +568 -0
  248. quantark/param/quote/__init__.py +7 -0
  249. quantark/param/quote/spot_quote.py +35 -0
  250. quantark/param/rrf/__init__.py +22 -0
  251. quantark/param/rrf/rate_curve.py +436 -0
  252. quantark/param/vol/__init__.py +6 -0
  253. quantark/param/vol/vol_surface.py +118 -0
  254. quantark/portfolio/__init__.py +61 -0
  255. quantark/portfolio/base.py +203 -0
  256. quantark/portfolio/equity/__init__.py +17 -0
  257. quantark/portfolio/equity/portfolio.py +391 -0
  258. quantark/portfolio/equity/position.py +368 -0
  259. quantark/portfolio/fi/__init__.py +14 -0
  260. quantark/portfolio/fi/portfolio.py +424 -0
  261. quantark/portfolio/fi/position.py +272 -0
  262. quantark/portfolio/portfolio_snapshot.py +221 -0
  263. quantark/portfolio/portfolio_storage.py +414 -0
  264. quantark/priceenv/__init__.py +7 -0
  265. quantark/priceenv/pricing_environment.py +196 -0
  266. quantark/rfq/__init__.py +32 -0
  267. quantark/rfq/builders.py +102 -0
  268. quantark/rfq/models.py +214 -0
  269. quantark/rfq/registry.py +611 -0
  270. quantark/rfq/service.py +237 -0
  271. quantark/simm/__init__.py +155 -0
  272. quantark/simm/calibration/__init__.py +206 -0
  273. quantark/simm/calibration/accessors.py +439 -0
  274. quantark/simm/calibration/commodity.py +156 -0
  275. quantark/simm/calibration/credit_non_qualifying.py +79 -0
  276. quantark/simm/calibration/credit_qualifying.py +130 -0
  277. quantark/simm/calibration/cross_risk.py +39 -0
  278. quantark/simm/calibration/equity.py +125 -0
  279. quantark/simm/calibration/fx.py +92 -0
  280. quantark/simm/calibration/ir.py +152 -0
  281. quantark/simm/calibration/version.py +33 -0
  282. quantark/simm/config.py +186 -0
  283. quantark/simm/crif/__init__.py +35 -0
  284. quantark/simm/crif/models.py +230 -0
  285. quantark/simm/crif/parser.py +585 -0
  286. quantark/simm/engines/__init__.py +62 -0
  287. quantark/simm/engines/aggregation/__init__.py +67 -0
  288. quantark/simm/engines/aggregation/addon.py +141 -0
  289. quantark/simm/engines/aggregation/bucket_aggregator.py +298 -0
  290. quantark/simm/engines/aggregation/concentration.py +349 -0
  291. quantark/simm/engines/aggregation/product_class_aggregator.py +183 -0
  292. quantark/simm/engines/aggregation/risk_class_aggregator.py +403 -0
  293. quantark/simm/engines/aggregation/simm_calculator.py +430 -0
  294. quantark/simm/engines/aggregation/weighted_sensitivity.py +272 -0
  295. quantark/simm/engines/base.py +231 -0
  296. quantark/simm/engines/classification/__init__.py +10 -0
  297. quantark/simm/engines/classification/bucket_mapper.py +347 -0
  298. quantark/simm/engines/factory.py +137 -0
  299. quantark/simm/engines/portfolio_adapter.py +336 -0
  300. quantark/simm/engines/result.py +176 -0
  301. quantark/simm/engines/risk_class/__init__.py +18 -0
  302. quantark/simm/engines/risk_class/equity_engine.py +263 -0
  303. quantark/simm/engines/risk_class/ir_engine.py +264 -0
  304. quantark/simm/report/__init__.py +17 -0
  305. quantark/simm/report/crif_export.py +284 -0
  306. quantark/simm/report/excel_generator.py +401 -0
  307. quantark/simm/report/html_generator.py +840 -0
  308. quantark/simm/results/__init__.py +38 -0
  309. quantark/simm/results/attribution.py +313 -0
  310. quantark/simm/results/simm_result.py +339 -0
  311. quantark/simm/results/whatif.py +268 -0
  312. quantark/simm/sensitivity.py +533 -0
  313. quantark/simm/taxonomy.py +416 -0
  314. quantark/stresstest/__init__.py +67 -0
  315. quantark/stresstest/base.py +116 -0
  316. quantark/stresstest/config.py +5 -0
  317. quantark/stresstest/engine.py +5 -0
  318. quantark/stresstest/equity/__init__.py +17 -0
  319. quantark/stresstest/equity/config.py +69 -0
  320. quantark/stresstest/equity/engine.py +272 -0
  321. quantark/stresstest/equity/report/__init__.py +7 -0
  322. quantark/stresstest/equity/report/report_generator.py +423 -0
  323. quantark/stresstest/equity/report/visualizer.py +328 -0
  324. quantark/stresstest/equity/results.py +145 -0
  325. quantark/stresstest/fi/__init__.py +15 -0
  326. quantark/stresstest/fi/config.py +59 -0
  327. quantark/stresstest/fi/engine.py +213 -0
  328. quantark/stresstest/fi/metrics.py +60 -0
  329. quantark/stresstest/fi/results.py +64 -0
  330. quantark/stresstest/report/__init__.py +12 -0
  331. quantark/stresstest/report/report_generator.py +5 -0
  332. quantark/stresstest/report/visualizer.py +5 -0
  333. quantark/stresstest/results/__init__.py +16 -0
  334. quantark/stresstest/results/result_aggregator.py +325 -0
  335. quantark/stresstest/results/result_exporter.py +286 -0
  336. quantark/stresstest/results/stress_results.py +5 -0
  337. quantark/stresstest/scenario/__init__.py +13 -0
  338. quantark/stresstest/scenario/scenario.py +242 -0
  339. quantark/stresstest/scenario/scenario_builder.py +376 -0
  340. quantark/stresstest/scenario/scenario_library.py +435 -0
  341. quantark/stresstest/scenario/scenario_storage.py +224 -0
  342. quantark/stresstest/stress/__init__.py +13 -0
  343. quantark/stresstest/stress/stress_applicator.py +590 -0
  344. quantark/stresstest/stress/stress_types.py +142 -0
  345. quantark/util/__init__.py +23 -0
  346. quantark/util/barrier_shift.py +44 -0
  347. quantark/util/calendar/__init__.py +27 -0
  348. quantark/util/calendar/business_calendar.py +584 -0
  349. quantark/util/calendar/day_counter.py +517 -0
  350. quantark/util/calendar/holidayfile/china.csv +1920 -0
  351. quantark/util/calendar/holidayfile/china_sse.csv +1462 -0
  352. quantark/util/enum/__init__.py +81 -0
  353. quantark/util/enum/bond_enums.py +112 -0
  354. quantark/util/enum/deltaone_enums.py +16 -0
  355. quantark/util/enum/engine_enums.py +137 -0
  356. quantark/util/enum/greeks_enums.py +29 -0
  357. quantark/util/enum/option_enums.py +221 -0
  358. quantark/util/exceptions.py +66 -0
  359. quantark/util/marketdata/__init__.py +39 -0
  360. quantark/util/marketdata/adapter/base_adapter.py +203 -0
  361. quantark/util/marketdata/adapter/mock_adapter.py +265 -0
  362. quantark/util/marketdata/converter.py +289 -0
  363. quantark/util/marketdata/example_usage.py +314 -0
  364. quantark/util/marketdata/generator/__init__.py +7 -0
  365. quantark/util/marketdata/generator/mock_generator.py +466 -0
  366. quantark/util/marketdata/models.py +358 -0
  367. quantark/util/marketdata/storage/__init__.py +7 -0
  368. quantark/util/marketdata/storage/parquet_storage.py +340 -0
  369. quantark/util/numerical/__init__.py +98 -0
  370. quantark/util/numerical/comparison.py +219 -0
  371. quantark/util/numerical/constants.py +98 -0
  372. quantark/util/numerical/formatting.py +380 -0
  373. quantark/util/numerical/pnl.py +17 -0
  374. quantark/util/numerical/safe_math.py +238 -0
  375. quantark/util/numerical/validation.py +315 -0
  376. quantark/var/__init__.py +39 -0
  377. quantark/var/attribution.py +398 -0
  378. quantark/var/backtest/__init__.py +7 -0
  379. quantark/var/backtest/var_backtester.py +309 -0
  380. quantark/var/base.py +63 -0
  381. quantark/var/config.py +219 -0
  382. quantark/var/engines/__init__.py +13 -0
  383. quantark/var/engines/historical.py +925 -0
  384. quantark/var/engines/monte_carlo.py +870 -0
  385. quantark/var/engines/parametric.py +1199 -0
  386. quantark/var/results/__init__.py +16 -0
  387. quantark/var/results/incremental_var_result.py +131 -0
  388. quantark/var/results/var_report.py +346 -0
  389. quantark/var/results/var_result.py +134 -0
  390. quantark/var/risk_factors/__init__.py +22 -0
  391. quantark/var/risk_factors/base.py +41 -0
  392. quantark/var/risk_factors/equity_factors.py +158 -0
  393. quantark/var/risk_factors/fi_factors.py +99 -0
  394. quantark-0.1.0.dist-info/METADATA +351 -0
  395. quantark-0.1.0.dist-info/RECORD +399 -0
  396. quantark-0.1.0.dist-info/WHEEL +4 -0
  397. quantark-0.1.0.dist-info/licenses/LICENSE +202 -0
  398. quantark-0.1.0.dist-info/licenses/NOTICE +2 -0
  399. quantark_compat.pth +1 -0
@@ -0,0 +1,435 @@
1
+ """
2
+ PDE solver for double one-touch (and double no-touch) options.
3
+
4
+ Implements the finite difference method for digital barrier options
5
+ with two barriers (upper and lower).
6
+ """
7
+
8
+ from typing import Dict, Optional, List, Set
9
+ import numpy as np
10
+
11
+ from quantark.asset.equity.product.base_equity_product import BaseEquityProduct
12
+ from quantark.asset.equity.product.option.double_one_touch_option import DoubleOneTouchOption
13
+ from quantark.asset.equity.param import PDEParams
14
+ from quantark.priceenv import PricingEnvironment
15
+ from quantark.util.enum import ObservationType, ObservationAggregation, TouchType
16
+ from quantark.util.exceptions import PricingError
17
+
18
+ from .base_pde_solver import BasePDESolver
19
+ from .spatial_grid import SpatialGrid
20
+ from .time_grid import TimeGrid
21
+
22
+
23
+ class DoubleOneTouchPDESolver(BasePDESolver):
24
+ """
25
+ PDE solver for double one-touch and double no-touch options.
26
+
27
+ Double one-touch options pay a fixed rebate if EITHER barrier is touched.
28
+ Double no-touch options pay a fixed rebate if NEITHER barrier is touched.
29
+
30
+ For double one-touch:
31
+ - Boundary conditions: rebate at both barriers
32
+ - Terminal condition: 0 (didn't touch either barrier yet)
33
+
34
+ For double no-touch:
35
+ - Boundary conditions: 0 at both barriers (touched = failed)
36
+ - Terminal condition: rebate inside corridor
37
+ """
38
+
39
+ def __init__(self, params: Optional[PDEParams] = None):
40
+ """
41
+ Initialize double one-touch option PDE solver.
42
+
43
+ Args:
44
+ params: PDE engine configuration parameters
45
+ """
46
+ super().__init__(params)
47
+ self._observation_indices: Set[int] = set()
48
+ self._schedule_records: Dict[int, List] = {}
49
+ self._schedule_aggregation: ObservationAggregation = (
50
+ ObservationAggregation.STOP_FIRST_HIT
51
+ )
52
+
53
+ def price(
54
+ self, product: BaseEquityProduct, pricing_env: PricingEnvironment
55
+ ) -> float:
56
+ """
57
+ Price a double one-touch or double no-touch option.
58
+
59
+ Args:
60
+ product: Double one-touch option
61
+ pricing_env: Pricing environment
62
+
63
+ Returns:
64
+ Option price
65
+
66
+ Raises:
67
+ PricingError: If product is not a double one-touch option
68
+ """
69
+ if not isinstance(product, DoubleOneTouchOption):
70
+ raise PricingError(
71
+ f"DoubleOneTouchPDESolver only supports DoubleOneTouchOption, "
72
+ f"got {type(product).__name__}"
73
+ )
74
+
75
+ # Check if barrier already hit (outside corridor)
76
+ spot = pricing_env.spot
77
+ if product.is_barrier_hit(spot):
78
+ if product.is_double_one_touch:
79
+ # Already touched, immediate rebate
80
+ return product.rebate
81
+ else:
82
+ # No-touch already failed
83
+ return 0.0
84
+
85
+ return super().price(product, pricing_env)
86
+
87
+ def calculate_greeks(
88
+ self, product: BaseEquityProduct, pricing_env: PricingEnvironment
89
+ ) -> Dict[str, float]:
90
+ """
91
+ Calculate Greeks for a double one-touch or double no-touch option.
92
+
93
+ Args:
94
+ product: Double one-touch option
95
+ pricing_env: Pricing environment
96
+
97
+ Returns:
98
+ Dictionary with price, delta, gamma
99
+
100
+ Raises:
101
+ PricingError: If product is not a double one-touch option
102
+ """
103
+ if not isinstance(product, DoubleOneTouchOption):
104
+ raise PricingError(
105
+ f"DoubleOneTouchPDESolver only supports DoubleOneTouchOption, "
106
+ f"got {type(product).__name__}"
107
+ )
108
+
109
+ spot = pricing_env.spot
110
+ tau = product.get_maturity(pricing_env)
111
+
112
+ # Handle expired case
113
+ if tau <= 0:
114
+ return {
115
+ "price": self._calculate_intrinsic(product, spot),
116
+ "delta": self._intrinsic_delta(product, spot),
117
+ "gamma": 0.0,
118
+ }
119
+
120
+ # Check if barrier already hit (outside corridor)
121
+ if product.is_barrier_hit(spot):
122
+ if product.is_double_one_touch:
123
+ # Already touched, fixed rebate (delta=gamma=0)
124
+ return {"price": product.rebate, "delta": 0.0, "gamma": 0.0}
125
+ else:
126
+ # No-touch already failed
127
+ return {"price": 0.0, "delta": 0.0, "gamma": 0.0}
128
+
129
+ return super().calculate_greeks(product, pricing_env)
130
+
131
+ def set_terminal_condition(
132
+ self,
133
+ grid: np.ndarray,
134
+ x_vec: np.ndarray,
135
+ s_vec: np.ndarray,
136
+ product: BaseEquityProduct,
137
+ pricing_env: PricingEnvironment,
138
+ ) -> None:
139
+ """
140
+ Set the terminal condition at maturity.
141
+
142
+ For double one-touch:
143
+ - At maturity, if neither barrier touched, value = 0
144
+ - At barriers and beyond, value = rebate
145
+
146
+ For double no-touch:
147
+ - At maturity, if neither barrier touched, value = rebate
148
+ - At barriers and beyond, value = 0
149
+
150
+ Args:
151
+ grid: Solution grid [num_x, num_t]
152
+ x_vec: Log-price grid points
153
+ s_vec: Price grid points
154
+ product: Double one-touch option
155
+ pricing_env: Pricing environment
156
+ """
157
+ upper = product.upper_barrier
158
+ lower = product.lower_barrier
159
+ rebate = product.rebate
160
+
161
+ # Use tolerance for floating-point comparisons
162
+ tol = 1e-10
163
+ at_or_above_upper = s_vec >= upper - tol * upper
164
+ at_or_below_lower = s_vec <= lower + tol * lower
165
+
166
+ if product.is_double_one_touch:
167
+ # One-touch: at maturity, inside corridor = 0, at/beyond barriers = rebate
168
+ grid[:, -1] = 0.0
169
+ grid[at_or_above_upper, -1] = rebate
170
+ grid[at_or_below_lower, -1] = rebate
171
+ else:
172
+ # No-touch: at maturity, inside corridor = rebate, at/beyond barriers = 0
173
+ grid[:, -1] = rebate
174
+ grid[at_or_above_upper, -1] = 0.0
175
+ grid[at_or_below_lower, -1] = 0.0
176
+
177
+ def set_boundary_conditions(
178
+ self,
179
+ grid: np.ndarray,
180
+ x_vec: np.ndarray,
181
+ s_vec: np.ndarray,
182
+ t_idx: int,
183
+ tau: float,
184
+ product: BaseEquityProduct,
185
+ pricing_env: PricingEnvironment,
186
+ ) -> None:
187
+ """
188
+ Set boundary conditions at spatial edges.
189
+
190
+ For double one-touch:
191
+ - Both barriers: rebate (possibly discounted)
192
+
193
+ For double no-touch:
194
+ - Both barriers: 0
195
+
196
+ Args:
197
+ grid: Solution grid [num_x, num_t]
198
+ x_vec: Log-price grid points
199
+ s_vec: Price grid points
200
+ t_idx: Current time index
201
+ tau: Time remaining to maturity
202
+ product: Double one-touch option
203
+ pricing_env: Pricing environment
204
+ """
205
+ rebate = product.rebate
206
+ r = pricing_env.get_rate(tau) if tau > 0 else 0.0
207
+ df = np.exp(-r * tau) if tau > 0 else 1.0
208
+
209
+ if product.is_double_one_touch:
210
+ if product.payment_at_hit:
211
+ barrier_value = rebate
212
+ else:
213
+ barrier_value = rebate * df
214
+
215
+ # Both boundaries are barriers
216
+ grid[0, t_idx] = barrier_value # Lower barrier
217
+ grid[-1, t_idx] = barrier_value # Upper barrier
218
+ else:
219
+ # No-touch: barriers are absorbing at zero
220
+ grid[0, t_idx] = 0.0
221
+ grid[-1, t_idx] = 0.0
222
+
223
+ def _apply_step_modifications(
224
+ self,
225
+ grid: np.ndarray,
226
+ x_vec: np.ndarray,
227
+ s_vec: np.ndarray,
228
+ t_idx: int,
229
+ tau: float,
230
+ product: BaseEquityProduct,
231
+ pricing_env: PricingEnvironment,
232
+ ) -> None:
233
+ """
234
+ Apply barrier checks at each time step.
235
+
236
+ For discrete monitoring, only check at observation times.
237
+ For continuous monitoring, check at every step.
238
+
239
+ Args:
240
+ grid: Solution grid
241
+ x_vec: Log-price grid points
242
+ s_vec: Price grid points
243
+ t_idx: Current time index
244
+ tau: Time remaining to maturity
245
+ product: Double one-touch option
246
+ pricing_env: Pricing environment
247
+ """
248
+ # For discrete monitoring, only check at observation times
249
+ if product.observation_type == ObservationType.DISCRETE:
250
+ if t_idx not in self._observation_indices:
251
+ return
252
+
253
+ schedule_records = self._schedule_records.get(t_idx)
254
+ upper = product.upper_barrier
255
+ lower = product.lower_barrier
256
+ rebate = product.rebate
257
+ r = pricing_env.get_rate(tau) if tau > 0 else 0.0
258
+ df = np.exp(-r * tau) if tau > 0 else 1.0
259
+
260
+ if schedule_records:
261
+ for rec in schedule_records:
262
+ upper = (
263
+ rec.upper_barrier
264
+ if rec.upper_barrier is not None
265
+ else product.upper_barrier
266
+ )
267
+ lower = (
268
+ rec.lower_barrier
269
+ if rec.lower_barrier is not None
270
+ else product.lower_barrier
271
+ )
272
+ payoff = rec.payoff
273
+ if product.is_double_one_touch:
274
+ barrier_value = payoff if product.payment_at_hit else payoff * df
275
+ else:
276
+ barrier_value = 0.0
277
+ at_or_above_upper = s_vec >= upper
278
+ at_or_below_lower = s_vec <= lower
279
+ outside_corridor = at_or_above_upper | at_or_below_lower
280
+ if self._schedule_aggregation == ObservationAggregation.ACCUMULATE:
281
+ grid[outside_corridor, t_idx] += barrier_value
282
+ else:
283
+ grid[outside_corridor, t_idx] = barrier_value
284
+ return
285
+ return
286
+
287
+ if product.is_double_one_touch:
288
+ if product.payment_at_hit:
289
+ barrier_value = rebate
290
+ else:
291
+ barrier_value = rebate * df
292
+ else:
293
+ barrier_value = 0.0
294
+
295
+ # Apply barrier values at/beyond barriers
296
+ at_or_above_upper = s_vec >= upper
297
+ at_or_below_lower = s_vec <= lower
298
+ outside_corridor = at_or_above_upper | at_or_below_lower
299
+ grid[outside_corridor, t_idx] = barrier_value
300
+
301
+ def _get_barriers(self, product: BaseEquityProduct) -> List[float]:
302
+ """Include schedule-specific barriers when building spatial bounds."""
303
+ barriers = super()._get_barriers(product)
304
+ schedule = getattr(product, "observation_schedule", None)
305
+ if schedule is not None:
306
+ for rec in schedule.records:
307
+ if rec.lower_barrier is not None:
308
+ barriers.append(rec.lower_barrier)
309
+ if rec.upper_barrier is not None:
310
+ barriers.append(rec.upper_barrier)
311
+ return barriers
312
+
313
+ def _build_grids(
314
+ self,
315
+ product: BaseEquityProduct,
316
+ pricing_env: PricingEnvironment,
317
+ spot: float,
318
+ sigma: float,
319
+ tau: float,
320
+ r: float,
321
+ q: float,
322
+ ):
323
+ """Build grids for double barrier options.
324
+
325
+ Uses a small buffer beyond the barriers to ensure proper PDE
326
+ diffusion from barrier values into the interior. The barriers
327
+ are included as interior points so their values propagate.
328
+ """
329
+ params: PDEParams = self.params
330
+
331
+ lower = product.lower_barrier
332
+ upper = product.upper_barrier
333
+
334
+ s_min, s_max = SpatialGrid.calculate_auto_bounds(
335
+ spot,
336
+ sigma,
337
+ tau,
338
+ r,
339
+ q,
340
+ barriers=[lower, upper],
341
+ num_std=5.0, # Wider range for barrier options
342
+ )
343
+
344
+ # Critical points: both barriers and spot for grid concentration
345
+ critical_points = [lower, upper]
346
+ if s_min < spot < s_max:
347
+ critical_points.append(spot)
348
+
349
+ # Build spatial grid with concentration at barriers
350
+ x_vec, s_vec, dx_vec = SpatialGrid.build(
351
+ s_min,
352
+ s_max,
353
+ params.grid_size,
354
+ critical_points=critical_points,
355
+ use_adaptive=params.adaptive_grid,
356
+ )
357
+
358
+ # Get event times
359
+ event_times = self._get_event_times(product, tau)
360
+
361
+ # Build time grid
362
+ t_vec, dt_vec = TimeGrid.build(
363
+ tau,
364
+ params.time_steps,
365
+ method=params.time_grid_type,
366
+ event_times=event_times,
367
+ grade_exponent=params.grade_exponent,
368
+ )
369
+
370
+ # Setup observation indices for discrete monitoring
371
+ self._observation_indices.clear()
372
+ self._schedule_records.clear()
373
+ self._schedule_aggregation = ObservationAggregation.STOP_FIRST_HIT
374
+ schedule = getattr(product, "observation_schedule", None)
375
+ if schedule is not None:
376
+ resolved_records = schedule.resolve(
377
+ pricing_env=pricing_env,
378
+ default_upper=product.upper_barrier,
379
+ default_lower=product.lower_barrier,
380
+ default_payoff=product.rebate,
381
+ require_double=True,
382
+ )
383
+ self._schedule_aggregation = schedule.aggregation_mode
384
+ if self._schedule_aggregation in (
385
+ ObservationAggregation.BEST,
386
+ ObservationAggregation.WORST,
387
+ ):
388
+ raise PricingError(
389
+ f"PDE solver does not support aggregation mode {self._schedule_aggregation.value}"
390
+ )
391
+ for rec in resolved_records:
392
+ if 0 < rec.observation_time < tau:
393
+ idx = np.argmin(np.abs(t_vec - rec.observation_time))
394
+ self._observation_indices.add(idx)
395
+ self._schedule_records.setdefault(idx, []).append(rec)
396
+ elif (
397
+ product.observation_type == ObservationType.DISCRETE
398
+ and product.observation_dates is not None
399
+ ):
400
+ for obs_time in product.observation_dates:
401
+ if 0 < obs_time < tau:
402
+ idx = np.argmin(np.abs(t_vec - obs_time))
403
+ self._observation_indices.add(idx)
404
+
405
+ return x_vec, s_vec, dx_vec, t_vec, dt_vec
406
+
407
+ def get_critical_points(
408
+ self, product: BaseEquityProduct, pricing_env: PricingEnvironment
409
+ ) -> List[float]:
410
+ """
411
+ Get critical prices for grid concentration.
412
+
413
+ For double one-touch, both barriers are critical.
414
+
415
+ Args:
416
+ product: Double one-touch option
417
+ pricing_env: Pricing environment
418
+
419
+ Returns:
420
+ List containing both barriers
421
+ """
422
+ points = [product.lower_barrier, product.upper_barrier]
423
+ schedule = getattr(product, "observation_schedule", None)
424
+ if schedule is not None:
425
+ for rec in schedule.records:
426
+ if rec.lower_barrier is not None:
427
+ points.append(rec.lower_barrier)
428
+ if rec.upper_barrier is not None:
429
+ points.append(rec.upper_barrier)
430
+ # sort and make unique before return
431
+ points = sorted(set(points))
432
+ return points
433
+
434
+ def __repr__(self):
435
+ return "DoubleOneTouchPDESolver()"
@@ -0,0 +1,170 @@
1
+ """
2
+ PDE solver for European vanilla options.
3
+
4
+ Implements the simplest case of PDE pricing: European calls and puts
5
+ with standard Black-Scholes boundary conditions.
6
+ """
7
+
8
+ from typing import Optional, List
9
+ import numpy as np
10
+
11
+ from quantark.asset.equity.product.base_equity_product import BaseEquityProduct
12
+ from quantark.asset.equity.product.option import EuropeanVanillaOption
13
+ from quantark.asset.equity.param import PDEParams
14
+ from quantark.priceenv import PricingEnvironment
15
+ from quantark.util.exceptions import PricingError
16
+
17
+ from .base_pde_solver import BasePDESolver
18
+
19
+
20
+ class EuropeanPDESolver(BasePDESolver):
21
+ """
22
+ PDE solver for European vanilla options.
23
+
24
+ Uses finite difference method to solve the Black-Scholes PDE
25
+ for European call and put options.
26
+
27
+ Terminal condition:
28
+ Call: max(S - K, 0)
29
+ Put: max(K - S, 0)
30
+
31
+ Boundary conditions:
32
+ Call: V(0) = 0, V(Smax) ≈ Smax - K*exp(-r*tau)
33
+ Put: V(0) ≈ K*exp(-r*tau), V(Smax) = 0
34
+ """
35
+
36
+ def __init__(self, params: Optional[PDEParams] = None):
37
+ """
38
+ Initialize European option PDE solver.
39
+
40
+ Args:
41
+ params: PDE engine configuration parameters
42
+ """
43
+ super().__init__(params)
44
+
45
+ def price(
46
+ self,
47
+ product: BaseEquityProduct,
48
+ pricing_env: PricingEnvironment
49
+ ) -> float:
50
+ """
51
+ Price a European vanilla option using PDE method.
52
+
53
+ Args:
54
+ product: European vanilla option
55
+ pricing_env: Pricing environment
56
+
57
+ Returns:
58
+ Option price
59
+
60
+ Raises:
61
+ PricingError: If product is not a European vanilla option
62
+ """
63
+ if not isinstance(product, EuropeanVanillaOption):
64
+ raise PricingError(
65
+ f"EuropeanPDESolver only supports EuropeanVanillaOption, "
66
+ f"got {type(product).__name__}"
67
+ )
68
+
69
+ return super().price(product, pricing_env)
70
+
71
+ def set_terminal_condition(
72
+ self,
73
+ grid: np.ndarray,
74
+ x_vec: np.ndarray,
75
+ s_vec: np.ndarray,
76
+ product: BaseEquityProduct,
77
+ pricing_env: PricingEnvironment
78
+ ) -> None:
79
+ """
80
+ Set the terminal condition (payoff at maturity).
81
+
82
+ For European options:
83
+ Call: max(S - K, 0)
84
+ Put: max(K - S, 0)
85
+
86
+ Args:
87
+ grid: Solution grid [num_x, num_t]
88
+ x_vec: Log-price grid points
89
+ s_vec: Price grid points
90
+ product: European vanilla option
91
+ pricing_env: Pricing environment
92
+ """
93
+ K = product.strike
94
+
95
+ if product.is_call():
96
+ grid[:, -1] = np.maximum(s_vec - K, 0.0)
97
+ else: # put
98
+ grid[:, -1] = np.maximum(K - s_vec, 0.0)
99
+
100
+ def set_boundary_conditions(
101
+ self,
102
+ grid: np.ndarray,
103
+ x_vec: np.ndarray,
104
+ s_vec: np.ndarray,
105
+ t_idx: int,
106
+ tau: float,
107
+ product: BaseEquityProduct,
108
+ pricing_env: PricingEnvironment
109
+ ) -> None:
110
+ """
111
+ Set boundary conditions at spatial edges.
112
+
113
+ For European options:
114
+ Lower boundary (S → 0):
115
+ Call: V → 0
116
+ Put: V → K * exp(-r*tau)
117
+
118
+ Upper boundary (S → ∞):
119
+ Call: V → S - K * exp(-r*tau)
120
+ Put: V → 0
121
+
122
+ Args:
123
+ grid: Solution grid [num_x, num_t]
124
+ x_vec: Log-price grid points
125
+ s_vec: Price grid points
126
+ t_idx: Current time index
127
+ tau: Time remaining to maturity
128
+ product: European vanilla option
129
+ pricing_env: Pricing environment
130
+ """
131
+ K = product.strike
132
+ r = pricing_env.get_rate(tau) if tau > 0 else 0.0
133
+ q = pricing_env.get_div_yield(tau) if tau > 0 else 0.0
134
+
135
+ df = np.exp(-r * tau) if tau > 0 else 1.0
136
+ df_div = np.exp(-q * tau) if tau > 0 else 1.0
137
+
138
+ if product.is_call():
139
+ # Lower boundary: call worth 0 when S = 0
140
+ grid[0, t_idx] = 0.0
141
+ # Upper boundary: call worth approximately S*exp(-q*tau) - K*exp(-r*tau)
142
+ grid[-1, t_idx] = max(s_vec[-1] * df_div - K * df, 0.0)
143
+ else: # put
144
+ # Lower boundary: put worth K*exp(-r*tau) when S = 0
145
+ grid[0, t_idx] = K * df
146
+ # Upper boundary: put worth 0 when S is very large
147
+ grid[-1, t_idx] = 0.0
148
+
149
+ def get_critical_points(
150
+ self,
151
+ product: BaseEquityProduct,
152
+ pricing_env: PricingEnvironment
153
+ ) -> List[float]:
154
+ """
155
+ Get critical prices for grid concentration.
156
+
157
+ For European options, the strike is the critical point.
158
+
159
+ Args:
160
+ product: European vanilla option
161
+ pricing_env: Pricing environment
162
+
163
+ Returns:
164
+ List containing the strike price
165
+ """
166
+ return [product.strike]
167
+
168
+ def __repr__(self):
169
+ return "EuropeanPDESolver()"
170
+