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,576 @@
1
+ """
2
+ Factory functions for creating common Phoenix option structures.
3
+
4
+ This module provides helper functions that simplify the creation of Phoenix options
5
+ by providing sensible defaults for common market structures. Each helper accepts
6
+ minimal required parameters and allows full customization via **kwargs.
7
+
8
+ Available helpers:
9
+ - create_standard_phoenix(): Basic phoenix with flat barriers, non-memory by default
10
+ - create_stepdown_phoenix(): KO and coupon barriers decrease each observation period
11
+ - create_reverse_phoenix(): Reverse direction (down KO, up KI)
12
+ - create_memory_phoenix(): Explicit memory coupon enabled
13
+ - create_non_memory_phoenix(): Memory coupon disabled (explicit)
14
+
15
+ Utilities (reused from snowball_helpers):
16
+ - generate_ko_observation_dates(): Create evenly spaced observation dates
17
+ - generate_stepdown_barriers(): Generate decreasing barrier levels
18
+
19
+ Example:
20
+ >>> from asset.equity.product.option import create_standard_phoenix
21
+ >>> phoenix = create_standard_phoenix(
22
+ ... initial_price=100.0,
23
+ ... strike=100.0,
24
+ ... maturity=1.0,
25
+ ... contract_multiplier=1.0,
26
+ ... )
27
+ """
28
+
29
+ from dataclasses import fields
30
+ from typing import List, Optional
31
+
32
+ from quantark.util.calendar.day_counter import DayCountConvention
33
+ from quantark.util.enum import CouponPayType, ObservationType
34
+ from quantark.util.exceptions import ValidationError
35
+
36
+ from .phoenix_config import CouponBarrierConfig
37
+ from .phoenix_option import PhoenixOption
38
+ from .snowball_config import AccrualConfig, AirbagConfig, BarrierConfig, PayoffConfig
39
+ from .snowball_helpers import (
40
+ generate_ko_observation_dates,
41
+ generate_stepdown_barriers,
42
+ )
43
+
44
+
45
+ # =============================================================================
46
+ # Internal Helper Functions
47
+ # =============================================================================
48
+
49
+
50
+ def _validate_core_params(
51
+ initial_price: float,
52
+ strike: float,
53
+ maturity: float,
54
+ contract_multiplier: float,
55
+ func_name: str,
56
+ num_observations: Optional[int] = None,
57
+ ) -> None:
58
+ """Validate core parameters common to all helpers."""
59
+ if initial_price <= 0:
60
+ raise ValidationError(
61
+ f"{func_name}: initial_price must be positive, got {initial_price}"
62
+ )
63
+ if strike <= 0:
64
+ raise ValidationError(f"{func_name}: strike must be positive, got {strike}")
65
+ if maturity <= 0:
66
+ raise ValidationError(f"{func_name}: maturity must be positive, got {maturity}")
67
+ if contract_multiplier <= 0:
68
+ raise ValidationError(
69
+ f"{func_name}: contract_multiplier must be positive, got {contract_multiplier}"
70
+ )
71
+ if num_observations is not None:
72
+ if not isinstance(num_observations, int):
73
+ raise ValidationError(
74
+ f"{func_name}: num_observations must be an integer, got {type(num_observations)}"
75
+ )
76
+ if num_observations < 1:
77
+ raise ValidationError(
78
+ f"{func_name}: num_observations must be at least 1, got {num_observations}"
79
+ )
80
+
81
+
82
+ def _extract_config_kwargs(kwargs: dict) -> tuple:
83
+ """
84
+ Extract kwargs for each config class using introspection.
85
+
86
+ Returns:
87
+ (barrier_kwargs, coupon_kwargs, payoff_kwargs, accrual_kwargs, airbag_kwargs)
88
+ """
89
+ barrier_fields = {f.name for f in fields(BarrierConfig)}
90
+ coupon_fields = {f.name for f in fields(CouponBarrierConfig)}
91
+ payoff_fields = {f.name for f in fields(PayoffConfig)}
92
+ accrual_fields = {f.name for f in fields(AccrualConfig)}
93
+ airbag_fields = {f.name for f in fields(AirbagConfig)}
94
+
95
+ barrier_kwargs = {}
96
+ coupon_kwargs = {}
97
+ payoff_kwargs = {}
98
+ accrual_kwargs = {}
99
+ airbag_kwargs = {}
100
+ unknown_kwargs = []
101
+
102
+ for key, value in kwargs.items():
103
+ if key in barrier_fields:
104
+ barrier_kwargs[key] = value
105
+ elif key in coupon_fields:
106
+ coupon_kwargs[key] = value
107
+ elif key in payoff_fields:
108
+ payoff_kwargs[key] = value
109
+ elif key in accrual_fields:
110
+ accrual_kwargs[key] = value
111
+ elif key in airbag_fields:
112
+ airbag_kwargs[key] = value
113
+ else:
114
+ unknown_kwargs.append(key)
115
+
116
+ if unknown_kwargs:
117
+ raise ValidationError(
118
+ f"Unknown parameters provided: {', '.join(unknown_kwargs)}. "
119
+ "Please check spelling or valid configuration fields."
120
+ )
121
+
122
+ return barrier_kwargs, coupon_kwargs, payoff_kwargs, accrual_kwargs, airbag_kwargs
123
+
124
+
125
+ # =============================================================================
126
+ # Factory Functions
127
+ # =============================================================================
128
+
129
+
130
+ def create_standard_phoenix(
131
+ initial_price: float,
132
+ strike: float,
133
+ maturity: float,
134
+ contract_multiplier: float = 1.0,
135
+ ko_barrier: Optional[float] = None,
136
+ ko_rate: float = 0.0,
137
+ ki_barrier: Optional[float] = None,
138
+ coupon_barrier: Optional[float] = None,
139
+ coupon_rate: float = 0.01,
140
+ num_observations: int = 12,
141
+ memory_coupon: bool = True,
142
+ day_count_convention: DayCountConvention = DayCountConvention.ACT_365,
143
+ coupon_pay_type: CouponPayType = CouponPayType.INSTANT,
144
+ is_reverse: bool = False,
145
+ **kwargs,
146
+ ) -> PhoenixOption:
147
+ """
148
+ Create a standard phoenix with flat barriers and optional memory coupon.
149
+
150
+ This is the most common phoenix structure with:
151
+ - Discrete KO observations (monthly by default)
152
+ - Continuous KI monitoring
153
+ - Flat (constant) KO and coupon barriers
154
+ - Memory coupon disabled by default
155
+ - Day count convention for coupon calculation
156
+
157
+ Args:
158
+ initial_price: Reference price for payoff calculations
159
+ strike: Strike price for embedded option
160
+ maturity: Time to maturity in years
161
+ contract_multiplier: Underlying units represented by one contract
162
+ ko_barrier: Knock-out barrier (default: 103% of initial_price)
163
+ ko_rate: Annualized knock-out rate (default: 0%)
164
+ ki_barrier: Knock-in barrier (default: 75% of initial_price)
165
+ coupon_barrier: Coupon barrier (default: 85% of initial_price)
166
+ coupon_rate: Per-period coupon rate (default: 1%)
167
+ num_observations: Number of observations (default: 12 for monthly)
168
+ memory_coupon: If True, accumulate missed coupons (default: True)
169
+ day_count_convention: Day count for coupon calculation (default: ACT/365)
170
+ coupon_pay_type: INSTANT or EXPIRY (default: INSTANT)
171
+ is_reverse: If True, create reverse phoenix (default: False)
172
+ **kwargs: Additional parameters passed to config objects
173
+
174
+ Returns:
175
+ Configured PhoenixOption instance
176
+
177
+ Example:
178
+ >>> phoenix = create_standard_phoenix(
179
+ ... initial_price=100.0,
180
+ ... strike=100.0,
181
+ ... maturity=1.0,
182
+ ... )
183
+ >>> phoenix.coupon_config.coupon_barrier
184
+ 85.0
185
+ """
186
+ _validate_core_params(
187
+ initial_price,
188
+ strike,
189
+ maturity,
190
+ contract_multiplier,
191
+ "create_standard_phoenix",
192
+ num_observations
193
+ )
194
+
195
+ # Apply defaults
196
+ if ko_barrier is None:
197
+ ko_barrier = 1.03 * initial_price
198
+ if ki_barrier is None:
199
+ ki_barrier = 0.75 * initial_price
200
+ if coupon_barrier is None:
201
+ coupon_barrier = 0.85 * initial_price
202
+
203
+ # Generate observation dates
204
+ ko_observation_dates = [
205
+ (i + 1) / num_observations * maturity for i in range(num_observations)
206
+ ]
207
+
208
+ # Extract config-specific kwargs
209
+ (
210
+ barrier_kwargs,
211
+ coupon_kwargs,
212
+ payoff_kwargs,
213
+ accrual_kwargs,
214
+ airbag_kwargs,
215
+ ) = _extract_config_kwargs(kwargs)
216
+
217
+ # Build configs
218
+ barrier_config = BarrierConfig(
219
+ ko_barrier=ko_barrier,
220
+ ko_rate=ko_rate,
221
+ ko_observation_type=barrier_kwargs.pop(
222
+ "ko_observation_type", ObservationType.DISCRETE
223
+ ),
224
+ ko_observation_dates=barrier_kwargs.pop(
225
+ "ko_observation_dates", ko_observation_dates
226
+ ),
227
+ ki_barrier=ki_barrier,
228
+ ki_observation_type=barrier_kwargs.pop(
229
+ "ki_observation_type", ObservationType.CONTINUOUS
230
+ ),
231
+ ki_continuous=barrier_kwargs.pop("ki_continuous", True),
232
+ **barrier_kwargs,
233
+ )
234
+
235
+ coupon_config = CouponBarrierConfig(
236
+ coupon_barrier=coupon_kwargs.pop("coupon_barrier", coupon_barrier),
237
+ coupon_rate=coupon_kwargs.pop("coupon_rate", coupon_rate),
238
+ coupon_pay_type=coupon_kwargs.pop("coupon_pay_type", coupon_pay_type),
239
+ day_count_convention=coupon_kwargs.pop(
240
+ "day_count_convention", day_count_convention
241
+ ),
242
+ memory_coupon=coupon_kwargs.pop("memory_coupon", memory_coupon),
243
+ )
244
+
245
+ payoff_config = PayoffConfig(
246
+ rebate_rate=payoff_kwargs.pop("rebate_rate", ko_rate),
247
+ include_principal=payoff_kwargs.pop("include_principal", False),
248
+ **payoff_kwargs,
249
+ )
250
+
251
+ accrual_config = AccrualConfig(
252
+ coupon_pay_type=accrual_kwargs.pop("coupon_pay_type", CouponPayType.INSTANT),
253
+ is_annualized=accrual_kwargs.pop("is_annualized", True),
254
+ **accrual_kwargs,
255
+ )
256
+
257
+ airbag_config = AirbagConfig(**airbag_kwargs)
258
+
259
+ return PhoenixOption(
260
+ initial_price=initial_price,
261
+ strike=strike,
262
+ maturity=maturity,
263
+ contract_multiplier=contract_multiplier,
264
+ barrier_config=barrier_config,
265
+ coupon_config=coupon_config,
266
+ payoff_config=payoff_config,
267
+ accrual_config=accrual_config,
268
+ airbag_config=airbag_config,
269
+ is_reverse=is_reverse,
270
+ )
271
+
272
+
273
+ def create_stepdown_phoenix(
274
+ initial_price: float,
275
+ strike: float,
276
+ maturity: float,
277
+ contract_multiplier: float = 1.0,
278
+ initial_ko_barrier: Optional[float] = None,
279
+ initial_coupon_barrier: Optional[float] = None,
280
+ ko_stepdown_rate: float = 0.005,
281
+ coupon_stepdown_rate: float = 0.005,
282
+ ko_rate: float = 0.0,
283
+ ki_barrier: Optional[float] = None,
284
+ coupon_rate: float = 0.01,
285
+ num_observations: int = 12,
286
+ memory_coupon: bool = True,
287
+ day_count_convention: DayCountConvention = DayCountConvention.ACT_365,
288
+ coupon_pay_type: CouponPayType = CouponPayType.INSTANT,
289
+ is_reverse: bool = False,
290
+ **kwargs,
291
+ ) -> PhoenixOption:
292
+ """
293
+ Create a step-down phoenix where KO and coupon barriers decrease each observation.
294
+
295
+ The barriers start high and decrease each observation period, making
296
+ knock-out and coupon payments progressively easier to achieve.
297
+
298
+ Args:
299
+ initial_price: Reference price for payoff calculations
300
+ strike: Strike price for embedded option
301
+ maturity: Time to maturity in years
302
+ contract_multiplier: Underlying units represented by one contract
303
+ initial_ko_barrier: Starting KO barrier (default: 103% of initial_price)
304
+ initial_coupon_barrier: Starting coupon barrier (default: 85% of initial_price)
305
+ ko_stepdown_rate: KO barrier decrease per period as % of initial_price (default: 0.5%)
306
+ coupon_stepdown_rate: Coupon barrier decrease per period (default: 0.5%)
307
+ ko_rate: Annualized knock-out rate (default: 0%)
308
+ ki_barrier: Knock-in barrier (default: 75% of initial_price)
309
+ coupon_rate: Per-period coupon rate (default: 1%)
310
+ num_observations: Number of observations (default: 12)
311
+ memory_coupon: If True, accumulate missed coupons (default: True)
312
+ day_count_convention: Day count for coupon calculation (default: ACT/365)
313
+ coupon_pay_type: INSTANT or EXPIRY (default: INSTANT)
314
+ is_reverse: If True, create reverse phoenix (default: False)
315
+ **kwargs: Additional parameters passed to config objects
316
+
317
+ Returns:
318
+ Configured PhoenixOption instance with step-down barriers
319
+
320
+ Example:
321
+ >>> phoenix = create_stepdown_phoenix(
322
+ ... initial_price=100.0,
323
+ ... strike=100.0,
324
+ ... maturity=1.0,
325
+ ... ko_stepdown_rate=0.01,
326
+ ... )
327
+ >>> phoenix.barrier_config.ko_barrier # List of decreasing barriers
328
+ [103.0, 102.0, 101.0, ...]
329
+ """
330
+ _validate_core_params(
331
+ initial_price,
332
+ strike,
333
+ maturity,
334
+ contract_multiplier,
335
+ "create_stepdown_phoenix",
336
+ num_observations
337
+ )
338
+
339
+ # Apply defaults
340
+ if initial_ko_barrier is None:
341
+ initial_ko_barrier = 1.03 * initial_price
342
+ if initial_coupon_barrier is None:
343
+ initial_coupon_barrier = 0.85 * initial_price
344
+ if ki_barrier is None:
345
+ ki_barrier = 0.75 * initial_price
346
+
347
+ # Generate step-down barriers
348
+ ko_barriers = generate_stepdown_barriers(
349
+ initial_barrier=initial_ko_barrier,
350
+ stepdown_amount=ko_stepdown_rate * initial_price,
351
+ num_observations=num_observations,
352
+ min_barrier=ki_barrier, # Don't go below KI barrier
353
+ )
354
+
355
+ coupon_barriers = generate_stepdown_barriers(
356
+ initial_barrier=initial_coupon_barrier,
357
+ stepdown_amount=coupon_stepdown_rate * initial_price,
358
+ num_observations=num_observations,
359
+ min_barrier=ki_barrier, # Don't go below KI barrier
360
+ )
361
+
362
+ # Generate observation dates
363
+ ko_observation_dates = [
364
+ (i + 1) / num_observations * maturity for i in range(num_observations)
365
+ ]
366
+
367
+ # Extract config-specific kwargs
368
+ (
369
+ barrier_kwargs,
370
+ coupon_kwargs,
371
+ payoff_kwargs,
372
+ accrual_kwargs,
373
+ airbag_kwargs,
374
+ ) = _extract_config_kwargs(kwargs)
375
+
376
+ # Build configs
377
+ barrier_config = BarrierConfig(
378
+ ko_barrier=ko_barriers,
379
+ ko_rate=ko_rate,
380
+ ko_observation_type=barrier_kwargs.pop(
381
+ "ko_observation_type", ObservationType.DISCRETE
382
+ ),
383
+ ko_observation_dates=barrier_kwargs.pop(
384
+ "ko_observation_dates", ko_observation_dates
385
+ ),
386
+ ki_barrier=ki_barrier,
387
+ ki_observation_type=barrier_kwargs.pop(
388
+ "ki_observation_type", ObservationType.CONTINUOUS
389
+ ),
390
+ ki_continuous=barrier_kwargs.pop("ki_continuous", True),
391
+ **barrier_kwargs,
392
+ )
393
+
394
+ coupon_config = CouponBarrierConfig(
395
+ coupon_barrier=coupon_barriers,
396
+ coupon_rate=coupon_kwargs.pop("coupon_rate", coupon_rate),
397
+ coupon_pay_type=coupon_kwargs.pop("coupon_pay_type", coupon_pay_type),
398
+ day_count_convention=coupon_kwargs.pop(
399
+ "day_count_convention", day_count_convention
400
+ ),
401
+ memory_coupon=coupon_kwargs.pop("memory_coupon", memory_coupon),
402
+ )
403
+
404
+ payoff_config = PayoffConfig(
405
+ rebate_rate=payoff_kwargs.pop("rebate_rate", ko_rate),
406
+ include_principal=payoff_kwargs.pop("include_principal", False),
407
+ **payoff_kwargs,
408
+ )
409
+
410
+ accrual_config = AccrualConfig(
411
+ coupon_pay_type=accrual_kwargs.pop("coupon_pay_type", CouponPayType.INSTANT),
412
+ is_annualized=accrual_kwargs.pop("is_annualized", True),
413
+ **accrual_kwargs,
414
+ )
415
+
416
+ airbag_config = AirbagConfig(**airbag_kwargs)
417
+
418
+ return PhoenixOption(
419
+ initial_price=initial_price,
420
+ strike=strike,
421
+ maturity=maturity,
422
+ contract_multiplier=contract_multiplier,
423
+ barrier_config=barrier_config,
424
+ coupon_config=coupon_config,
425
+ payoff_config=payoff_config,
426
+ accrual_config=accrual_config,
427
+ airbag_config=airbag_config,
428
+ is_reverse=is_reverse,
429
+ )
430
+
431
+
432
+ def create_reverse_phoenix(
433
+ initial_price: float,
434
+ strike: float,
435
+ maturity: float,
436
+ contract_multiplier: float = 1.0,
437
+ ko_barrier: Optional[float] = None,
438
+ ko_rate: float = 0.0,
439
+ ki_barrier: Optional[float] = None,
440
+ coupon_barrier: Optional[float] = None,
441
+ coupon_rate: float = 0.01,
442
+ num_observations: int = 12,
443
+ memory_coupon: bool = True,
444
+ day_count_convention: DayCountConvention = DayCountConvention.ACT_365,
445
+ coupon_pay_type: CouponPayType = CouponPayType.INSTANT,
446
+ **kwargs,
447
+ ) -> PhoenixOption:
448
+ """
449
+ Create a reverse phoenix with down KO barrier and up KI barrier.
450
+
451
+ Reverse phoenix:
452
+ - KO barrier: DOWN (below initial price) - KO triggers when spot <= ko_barrier
453
+ - KI barrier: UP (above initial price) - KI triggers when spot >= ki_barrier
454
+ - Coupon barrier: UP - Coupon pays when spot <= coupon_barrier
455
+ - Embedded option: CALL (investor is short call on KI)
456
+
457
+ Args:
458
+ initial_price: Reference price for payoff calculations
459
+ strike: Strike price for embedded option
460
+ maturity: Time to maturity in years
461
+ contract_multiplier: Underlying units represented by one contract
462
+ ko_barrier: Knock-out barrier (default: 97% of initial_price)
463
+ ko_rate: Annualized knock-out rate (default: 0%)
464
+ ki_barrier: Knock-in barrier (default: 125% of initial_price)
465
+ coupon_barrier: Coupon barrier (default: 115% of initial_price)
466
+ coupon_rate: Per-period coupon rate (default: 1%)
467
+ num_observations: Number of observations (default: 12)
468
+ memory_coupon: If True, accumulate missed coupons (default: True)
469
+ day_count_convention: Day count for coupon calculation (default: ACT/365)
470
+ coupon_pay_type: INSTANT or EXPIRY (default: INSTANT)
471
+ **kwargs: Additional parameters passed to config objects
472
+
473
+ Returns:
474
+ Configured PhoenixOption instance with reverse direction
475
+ """
476
+ _validate_core_params(
477
+ initial_price,
478
+ strike,
479
+ maturity,
480
+ contract_multiplier,
481
+ "create_reverse_phoenix",
482
+ num_observations
483
+ )
484
+
485
+ # Reverse phoenix defaults
486
+ if ko_barrier is None:
487
+ ko_barrier = 0.97 * initial_price
488
+ if ki_barrier is None:
489
+ ki_barrier = 1.25 * initial_price
490
+ if coupon_barrier is None:
491
+ coupon_barrier = 1.15 * initial_price
492
+
493
+ return create_standard_phoenix(
494
+ initial_price=initial_price,
495
+ strike=strike,
496
+ maturity=maturity,
497
+ contract_multiplier=contract_multiplier,
498
+ ko_barrier=ko_barrier,
499
+ ko_rate=ko_rate,
500
+ ki_barrier=ki_barrier,
501
+ coupon_barrier=coupon_barrier,
502
+ coupon_rate=coupon_rate,
503
+ num_observations=num_observations,
504
+ memory_coupon=memory_coupon,
505
+ day_count_convention=day_count_convention,
506
+ coupon_pay_type=coupon_pay_type,
507
+ is_reverse=True,
508
+ **kwargs,
509
+ )
510
+
511
+
512
+ def create_memory_phoenix(
513
+ initial_price: float,
514
+ strike: float,
515
+ maturity: float,
516
+ contract_multiplier: float = 1.0,
517
+ **kwargs,
518
+ ) -> PhoenixOption:
519
+ """
520
+ Create a phoenix with memory coupon explicitly enabled.
521
+
522
+ Memory coupon: When coupon barrier is not hit at an observation, the
523
+ coupon is accumulated and paid when the barrier is hit at a later
524
+ observation (or at maturity if never knocked out).
525
+
526
+ Args:
527
+ initial_price: Reference price for payoff calculations
528
+ strike: Strike price for embedded option
529
+ maturity: Time to maturity in years
530
+ contract_multiplier: Underlying units represented by one contract
531
+ **kwargs: Additional parameters passed to create_standard_phoenix
532
+
533
+ Returns:
534
+ PhoenixOption with memory_coupon=True
535
+ """
536
+ return create_standard_phoenix(
537
+ initial_price=initial_price,
538
+ strike=strike,
539
+ maturity=maturity,
540
+ contract_multiplier=contract_multiplier,
541
+ memory_coupon=True,
542
+ **kwargs,
543
+ )
544
+
545
+
546
+ def create_non_memory_phoenix(
547
+ initial_price: float,
548
+ strike: float,
549
+ maturity: float,
550
+ contract_multiplier: float = 1.0,
551
+ **kwargs,
552
+ ) -> PhoenixOption:
553
+ """
554
+ Create a phoenix with memory coupon disabled.
555
+
556
+ Non-memory coupon: Each observation is independent. If coupon barrier
557
+ is not hit, that period's coupon is forfeited.
558
+
559
+ Args:
560
+ initial_price: Reference price for payoff calculations
561
+ strike: Strike price for embedded option
562
+ maturity: Time to maturity in years
563
+ contract_multiplier: Underlying units represented by one contract
564
+ **kwargs: Additional parameters passed to create_standard_phoenix
565
+
566
+ Returns:
567
+ PhoenixOption with memory_coupon=False
568
+ """
569
+ return create_standard_phoenix(
570
+ initial_price=initial_price,
571
+ strike=strike,
572
+ maturity=maturity,
573
+ contract_multiplier=contract_multiplier,
574
+ memory_coupon=False,
575
+ **kwargs,
576
+ )