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,287 @@
1
+ """
2
+ One-touch option implementation.
3
+
4
+ One-touch options are binary/digital options that pay a fixed rebate
5
+ if the underlying price touches a barrier at any point before expiry.
6
+ """
7
+
8
+ from dataclasses import dataclass
9
+ from typing import Optional, List
10
+ from datetime import datetime
11
+ from ..base_equity_product import BaseEquityProduct
12
+ from .observation_schedule import ObservationRecord, ObservationSchedule
13
+ from quantark.util.enum import (
14
+ BarrierDirection,
15
+ ObservationType,
16
+ ObservationAggregation,
17
+ TouchType,
18
+ )
19
+ from quantark.util.exceptions import ValidationError
20
+
21
+
22
+ @dataclass
23
+ class OneTouchOption(BaseEquityProduct):
24
+ """
25
+ One-touch (or no-touch) digital option.
26
+
27
+ One-touch options pay a fixed rebate if the underlying price touches
28
+ the barrier at any point during the option's life.
29
+
30
+ No-touch options pay a fixed rebate if the barrier is NOT touched.
31
+
32
+ Attributes:
33
+ barrier: Barrier price level
34
+ barrier_direction: UP (barrier above spot) or DOWN (barrier below spot)
35
+ rebate: Amount paid when condition is satisfied (default: 1.0)
36
+ maturity: Time to maturity in years
37
+ payment_at_hit: If True, rebate paid immediately on touch;
38
+ If False, rebate paid at expiry
39
+ touch_type: ONE_TOUCH or NO_TOUCH
40
+ observation_type: CONTINUOUS or DISCRETE monitoring
41
+ observation_dates: For discrete, list of observation times
42
+ """
43
+
44
+ barrier: float = 0.0
45
+ barrier_direction: BarrierDirection = BarrierDirection.UP
46
+ rebate: float = 1.0
47
+ maturity: float = 0.0
48
+ payment_at_hit: bool = True
49
+ touch_type: TouchType = TouchType.ONE_TOUCH
50
+ observation_type: ObservationType = ObservationType.CONTINUOUS
51
+ observation_dates: Optional[List[float]] = None
52
+ observation_schedule: Optional[ObservationSchedule] = None
53
+ exercise_date: Optional[datetime] = None
54
+ settlement_date: Optional[datetime] = None
55
+
56
+ def __init__(
57
+ self,
58
+ barrier: float,
59
+ barrier_direction: BarrierDirection,
60
+ maturity: Optional[float] = None,
61
+ exercise_date: Optional[datetime] = None,
62
+ settlement_date: Optional[datetime] = None,
63
+ rebate: float = 1.0,
64
+ payment_at_hit: bool = True,
65
+ touch_type: TouchType = TouchType.ONE_TOUCH,
66
+ observation_type: ObservationType = ObservationType.CONTINUOUS,
67
+ observation_dates: Optional[List[float]] = None,
68
+ observation_schedule: Optional[ObservationSchedule] = None,
69
+ ):
70
+ """
71
+ Initialize one-touch option.
72
+
73
+ Args:
74
+ barrier: Barrier price level
75
+ barrier_direction: UP or DOWN
76
+ maturity: Time to maturity in years (optional if exercise_date provided)
77
+ exercise_date: Expiration date (optional if maturity provided)
78
+ settlement_date: Settlement date (optional)
79
+ rebate: Payment amount on touch (default: 1.0)
80
+ payment_at_hit: If True, pay on touch; if False, pay at expiry
81
+ touch_type: ONE_TOUCH (pay if touched) or NO_TOUCH (pay if not touched)
82
+ observation_type: CONTINUOUS or DISCRETE
83
+ observation_dates: For discrete, list of observation times
84
+
85
+ Raises:
86
+ ValidationError: If parameters are invalid
87
+ """
88
+ # Handle maturity vs exercise_date
89
+ if maturity is None and exercise_date is None:
90
+ maturity = 0.0
91
+ elif maturity is None:
92
+ maturity = 0.0
93
+
94
+ self.barrier = barrier
95
+ self.barrier_direction = barrier_direction
96
+ self.rebate = rebate
97
+ self.maturity = maturity
98
+ self.payment_at_hit = payment_at_hit
99
+ self.touch_type = touch_type
100
+ self.observation_type = observation_type
101
+ self.observation_dates = observation_dates
102
+ self.observation_schedule = observation_schedule
103
+ self.exercise_date = exercise_date
104
+ self.settlement_date = settlement_date
105
+
106
+ self.validate()
107
+
108
+ def validate(self) -> None:
109
+ """
110
+ Validate one-touch option parameters.
111
+
112
+ Raises:
113
+ ValidationError: If parameters are invalid
114
+ """
115
+ if self.barrier <= 0:
116
+ raise ValidationError(f"Barrier must be positive, got {self.barrier}")
117
+
118
+ if self.rebate < 0:
119
+ raise ValidationError(f"Rebate must be non-negative, got {self.rebate}")
120
+
121
+ if not isinstance(self.barrier_direction, BarrierDirection):
122
+ raise ValidationError(
123
+ f"Invalid barrier direction: {self.barrier_direction}"
124
+ )
125
+
126
+ if not isinstance(self.touch_type, TouchType):
127
+ raise ValidationError(f"Invalid touch type: {self.touch_type}")
128
+
129
+ # Validate maturity
130
+ has_dates = self.exercise_date is not None
131
+ has_maturity = self.maturity is not None and self.maturity > 0
132
+
133
+ if not has_dates and not has_maturity:
134
+ raise ValidationError("Either maturity or exercise_date must be provided")
135
+
136
+ # For discrete observation, must have observation dates
137
+ if (
138
+ self.observation_type == ObservationType.DISCRETE
139
+ and self.observation_schedule is None
140
+ and (self.observation_dates is None or len(self.observation_dates) == 0)
141
+ ):
142
+ raise ValidationError(
143
+ "Observation dates required for discrete barrier monitoring"
144
+ )
145
+
146
+ # Normalize observation schedule (preferred) or legacy dates for discrete monitoring
147
+ if self.observation_schedule is not None:
148
+ if self.observation_type == ObservationType.CONTINUOUS:
149
+ raise ValidationError("ObservationSchedule requires DISCRETE observation_type.")
150
+ normalized_schedule = ObservationSchedule(
151
+ records=[
152
+ ObservationRecord(
153
+ observation_time=rec.observation_time,
154
+ observation_date=rec.observation_date,
155
+ barrier=rec.barrier if rec.barrier is not None else self.barrier,
156
+ payoff=rec.payoff if rec.payoff is not None else self.rebate,
157
+ return_rate=rec.return_rate,
158
+ )
159
+ for rec in self.observation_schedule.records
160
+ ],
161
+ aggregation_mode=self.observation_schedule.aggregation_mode,
162
+ frequency=self.observation_schedule.frequency,
163
+ )
164
+ normalized_schedule.validate(require_single=True)
165
+ self.observation_schedule = normalized_schedule
166
+ if self.observation_schedule.times:
167
+ self.observation_dates = self.observation_schedule.times
168
+ self.observation_type = ObservationType.DISCRETE
169
+ elif self.observation_type == ObservationType.DISCRETE:
170
+ self.observation_schedule = ObservationSchedule.from_legacy(
171
+ observation_dates=self.observation_dates or [],
172
+ default_barrier=self.barrier,
173
+ default_payoff=self.rebate,
174
+ aggregation_mode=ObservationAggregation.STOP_FIRST_HIT,
175
+ )
176
+ self.observation_dates = self.observation_schedule.times
177
+
178
+ def get_maturity(self, pricing_env=None) -> float:
179
+ """
180
+ Get time to maturity in years.
181
+
182
+ Args:
183
+ pricing_env: Pricing environment (required if using dates)
184
+
185
+ Returns:
186
+ Time to maturity in years
187
+ """
188
+ if self.exercise_date is not None:
189
+ if pricing_env is None:
190
+ raise ValidationError(
191
+ "PricingEnvironment required for date-based maturity calculation"
192
+ )
193
+ from quantark.util.calendar import calculate_year_fraction
194
+
195
+ return calculate_year_fraction(
196
+ pricing_env.valuation_date,
197
+ self.exercise_date,
198
+ pricing_env.day_count_convention,
199
+ pricing_env.bus_days_in_year,
200
+ calendar=getattr(pricing_env, "calendar", None),
201
+ )
202
+ else:
203
+ return self.maturity
204
+
205
+ def time_shift(self, time_bump: float, bumped_date: datetime, pricing_env) -> bool:
206
+ """Shift observation schedule and maturity for theta bumping."""
207
+ schedule = getattr(self, "observation_schedule", None)
208
+ if schedule is not None:
209
+ if schedule.uses_dates():
210
+ pricing_env.valuation_date = bumped_date
211
+ bumped_schedule = schedule.time_shift(time_bump, bumped_date)
212
+ if bumped_schedule is None:
213
+ return True
214
+ self.observation_schedule = bumped_schedule
215
+ if hasattr(self, "observation_dates") and bumped_schedule.uses_times():
216
+ self.observation_dates = bumped_schedule.times
217
+
218
+ if getattr(self, "exercise_date", None) is None:
219
+ if getattr(self, "maturity", None) is not None:
220
+ self.maturity -= time_bump
221
+ else:
222
+ pricing_env.valuation_date = bumped_date
223
+
224
+ return False
225
+
226
+ def get_payoff(self, spot: float, touched: bool = False) -> float:
227
+ """
228
+ Calculate the option payoff.
229
+
230
+ For one-touch: pays rebate if touched
231
+ For no-touch: pays rebate if NOT touched
232
+
233
+ Args:
234
+ spot: Spot price (not used for one-touch, kept for interface)
235
+ touched: Whether the barrier was touched
236
+
237
+ Returns:
238
+ Option payoff
239
+ """
240
+ if self.touch_type == TouchType.ONE_TOUCH:
241
+ return self.rebate if touched else 0.0
242
+ else: # NO_TOUCH
243
+ return self.rebate if not touched else 0.0
244
+
245
+ @property
246
+ def is_one_touch(self) -> bool:
247
+ """Check if this is a one-touch option."""
248
+ return self.touch_type == TouchType.ONE_TOUCH
249
+
250
+ @property
251
+ def is_no_touch(self) -> bool:
252
+ """Check if this is a no-touch option."""
253
+ return self.touch_type == TouchType.NO_TOUCH
254
+
255
+ @property
256
+ def is_up_barrier(self) -> bool:
257
+ """Check if barrier is above spot."""
258
+ return self.barrier_direction == BarrierDirection.UP
259
+
260
+ @property
261
+ def is_down_barrier(self) -> bool:
262
+ """Check if barrier is below spot."""
263
+ return self.barrier_direction == BarrierDirection.DOWN
264
+
265
+ def is_barrier_hit(self, spot: float) -> bool:
266
+ """
267
+ Check if the barrier would be hit at a given spot price.
268
+
269
+ Args:
270
+ spot: Spot price to check
271
+
272
+ Returns:
273
+ True if barrier is hit
274
+ """
275
+ if self.is_up_barrier:
276
+ return spot >= self.barrier
277
+ else:
278
+ return spot <= self.barrier
279
+
280
+ def __repr__(self):
281
+ touch_str = "OneTouch" if self.is_one_touch else "NoTouch"
282
+ dir_str = "Up" if self.is_up_barrier else "Down"
283
+ return (
284
+ f"{touch_str}Option("
285
+ f"B={self.barrier:.2f}, {dir_str}, "
286
+ f"rebate={self.rebate:.2f}, T={self.maturity:.4f})"
287
+ )
@@ -0,0 +1,116 @@
1
+ """
2
+ Configuration classes for Phoenix options.
3
+
4
+ Phoenix options are autocallable structured products with periodic coupon payments
5
+ when spot exceeds a coupon barrier at observation dates.
6
+ """
7
+
8
+ from dataclasses import dataclass
9
+ from typing import List, Optional, Union
10
+
11
+ from quantark.util.enum import CouponPayType
12
+ from quantark.util.calendar.day_counter import DayCountConvention
13
+ from quantark.util.exceptions import ValidationError
14
+
15
+
16
+ @dataclass(frozen=True)
17
+ class CouponBarrierConfig:
18
+ """
19
+ Configuration for coupon barrier settings (Phoenix-specific).
20
+
21
+ The coupon barrier determines when periodic coupons are paid. At each observation
22
+ date, if the spot price is above (or below for reverse) the coupon barrier, a
23
+ coupon is paid based on the coupon_rate and day count convention.
24
+
25
+ Attributes:
26
+ coupon_barrier: Coupon barrier level(s). Can be scalar or time-varying (list).
27
+ For standard Phoenix: pays coupon when spot >= coupon_barrier.
28
+ For reverse Phoenix: pays coupon when spot <= coupon_barrier.
29
+ coupon_rate: Per-period coupon rate (e.g., 0.01 for 1% per period).
30
+ coupon_pay_type: INSTANT (pay at observation) or EXPIRY (accumulate to maturity).
31
+ day_count_convention: Day count convention for year fraction calculation.
32
+ Supported: ACT_365, THIRTY_360_US, THIRTY_360_EUROPEAN, etc.
33
+ memory_coupon: If True, missed coupons accumulate and are paid when barrier
34
+ is hit later. If False, only current period coupon is paid.
35
+ fixed_coupon_year_fraction: Optional fixed year fraction used for each coupon
36
+ period (e.g., 1/12 for equal monthly coupons). If None, engines
37
+ use observation-time differences.
38
+ """
39
+
40
+ # Coupon barrier level(s)
41
+ coupon_barrier: Union[float, List[float]]
42
+
43
+ # Coupon rate per period
44
+ coupon_rate: float = 0.01
45
+
46
+ # Payment timing
47
+ coupon_pay_type: CouponPayType = CouponPayType.INSTANT
48
+
49
+ # Day count convention for year fraction calculation
50
+ day_count_convention: DayCountConvention = DayCountConvention.ACT_365
51
+
52
+ # Memory coupon feature
53
+ memory_coupon: bool = True
54
+
55
+ # Optional fixed accrual per coupon period (e.g. 1/12)
56
+ fixed_coupon_year_fraction: Optional[float] = None
57
+
58
+ def __post_init__(self):
59
+ """Validate configuration after initialization."""
60
+ # Validate coupon_barrier is positive
61
+ self._validate_barrier_positive(self.coupon_barrier, "coupon_barrier")
62
+
63
+ # Validate coupon_rate is non-negative
64
+ if not isinstance(self.coupon_rate, (int, float)):
65
+ raise ValidationError(
66
+ f"coupon_rate must be a number, got {type(self.coupon_rate)}"
67
+ )
68
+ if self.coupon_rate < 0:
69
+ raise ValidationError(f"coupon_rate must be non-negative, got {self.coupon_rate}")
70
+
71
+ # Validate coupon_pay_type is enum
72
+ if not isinstance(self.coupon_pay_type, CouponPayType):
73
+ raise ValidationError(
74
+ f"coupon_pay_type must be CouponPayType, got {type(self.coupon_pay_type)}"
75
+ )
76
+
77
+ # Validate day_count_convention is enum
78
+ if not isinstance(self.day_count_convention, DayCountConvention):
79
+ raise ValidationError(
80
+ f"day_count_convention must be DayCountConvention, "
81
+ f"got {type(self.day_count_convention)}"
82
+ )
83
+
84
+ # Validate memory_coupon is boolean
85
+ if not isinstance(self.memory_coupon, bool):
86
+ raise ValidationError(
87
+ f"memory_coupon must be boolean, got {type(self.memory_coupon)}"
88
+ )
89
+
90
+ # Validate fixed coupon accrual if provided
91
+ if self.fixed_coupon_year_fraction is not None:
92
+ if not isinstance(self.fixed_coupon_year_fraction, (int, float)):
93
+ raise ValidationError(
94
+ "fixed_coupon_year_fraction must be numeric when provided, "
95
+ f"got {type(self.fixed_coupon_year_fraction)}"
96
+ )
97
+ if self.fixed_coupon_year_fraction <= 0:
98
+ raise ValidationError(
99
+ "fixed_coupon_year_fraction must be positive, "
100
+ f"got {self.fixed_coupon_year_fraction}"
101
+ )
102
+
103
+ @staticmethod
104
+ def _validate_barrier_positive(
105
+ barrier: Union[float, List[float]], name: str
106
+ ) -> None:
107
+ """Validate that barrier level(s) are positive."""
108
+ if isinstance(barrier, list):
109
+ if not barrier:
110
+ raise ValidationError(f"{name} list cannot be empty")
111
+ for i, b in enumerate(barrier):
112
+ if not isinstance(b, (int, float)) or b <= 0:
113
+ raise ValidationError(f"{name}[{i}] must be positive number, got {b}")
114
+ else:
115
+ if not isinstance(barrier, (int, float)) or barrier <= 0:
116
+ raise ValidationError(f"{name} must be positive number, got {barrier}")