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,485 @@
1
+ """
2
+ Futures contract implementation with basis handling.
3
+ """
4
+
5
+ import math
6
+ from dataclasses import dataclass
7
+ from typing import Optional
8
+ from datetime import datetime
9
+ from .base_deltaone_product import BaseDeltaOneProduct
10
+ from quantark.util.enum.deltaone_enums import DeltaOneType
11
+ from quantark.util.exceptions import ValidationError
12
+
13
+
14
+ @dataclass
15
+ class Futures(BaseDeltaOneProduct):
16
+ """
17
+ Futures contract with basis handling and mark-to-market support.
18
+
19
+ A futures contract is an agreement to buy/sell an asset at a future date
20
+ at a predetermined price. The contract has a multiplier and optional
21
+ observed market price for mark-to-market valuation.
22
+
23
+ Theoretical forward pricing with basis:
24
+ F(t,T) = S(t) * exp((r - q) * (T - t)) + basis(t) * exp(-λ * (T - t))
25
+
26
+ Where:
27
+ - S(t): Current spot price
28
+ - r: Risk-free rate
29
+ - q: Dividend yield
30
+ - basis(t): Current basis (difference from theoretical forward)
31
+ - λ: Basis decay rate (how fast basis converges to 0 at maturity)
32
+
33
+ Attributes:
34
+ underlying: Identifier for the underlying asset
35
+ multiplier: Contract multiplier (e.g., 50 for E-mini S&P)
36
+ maturity: Time to maturity in years (optional if maturity_date provided)
37
+ maturity_date: Date when futures contract expires
38
+ basis: Current basis (futures_price - theoretical_forward)
39
+ basis_decay_rate: Rate at which basis converges to zero (default: 1.0)
40
+ market_price: Optional observed futures price for mark-to-market valuation
41
+
42
+ Example:
43
+ >>> # E-mini S&P 500 futures
44
+ >>> future = Futures(
45
+ ... underlying="ES",
46
+ ... multiplier=50.0,
47
+ ... maturity=0.25, # 3 months
48
+ ... basis=2.5,
49
+ ... basis_decay_rate=2.0
50
+ ... )
51
+ >>>
52
+ >>> # With market price for mark-to-market
53
+ >>> future_mtm = Futures(
54
+ ... underlying="ES",
55
+ ... multiplier=50.0,
56
+ ... maturity=0.25,
57
+ ... basis=2.5,
58
+ ... market_price=4525.0 # Observed market price
59
+ ... )
60
+ """
61
+
62
+ multiplier: float = 1.0
63
+ basis: float = 0.0
64
+ basis_decay_rate: float = 1.0
65
+ market_price: Optional[float] = None
66
+
67
+ def __init__(
68
+ self,
69
+ underlying: str,
70
+ multiplier: float = 1.0,
71
+ maturity: Optional[float] = None,
72
+ maturity_date: Optional[datetime] = None,
73
+ basis: float = 0.0,
74
+ basis_decay_rate: float = 1.0,
75
+ market_price: Optional[float] = None,
76
+ ):
77
+ """
78
+ Initialize futures contract.
79
+
80
+ Args:
81
+ underlying: Identifier for the underlying asset
82
+ multiplier: Contract multiplier (must be positive)
83
+ maturity: Time to maturity in years (optional if maturity_date provided)
84
+ maturity_date: Date when contract expires (optional if maturity provided)
85
+ basis: Current basis (futures_price - theoretical_forward)
86
+ basis_decay_rate: Rate at which basis converges to zero (default: 1.0)
87
+ market_price: Optional observed futures price for mark-to-market
88
+
89
+ Raises:
90
+ ValidationError: If parameters are invalid
91
+
92
+ Note:
93
+ Either maturity OR maturity_date must be provided (not both).
94
+ """
95
+ # Initialize parent with futures type
96
+ super().__init__(
97
+ underlying=underlying,
98
+ deltaone_type=DeltaOneType.FUTURES,
99
+ maturity=maturity,
100
+ maturity_date=maturity_date,
101
+ )
102
+
103
+ self.multiplier = multiplier
104
+ self.basis = basis
105
+ self.basis_decay_rate = basis_decay_rate
106
+ self.market_price = market_price
107
+
108
+ # Validate futures-specific parameters
109
+ self._validate_futures_params()
110
+
111
+ def _validate_futures_params(self) -> None:
112
+ """
113
+ Validate futures-specific parameters.
114
+
115
+ Raises:
116
+ ValidationError: If parameters are invalid
117
+ """
118
+ if self.multiplier <= 0:
119
+ raise ValidationError(f"Multiplier must be positive, got {self.multiplier}")
120
+
121
+ # Validate basis-specific parameters
122
+ if not math.isfinite(self.basis):
123
+ raise ValidationError(f"Basis must be finite, got {self.basis}")
124
+
125
+ if self.basis_decay_rate <= 0:
126
+ raise ValidationError(f"Basis decay rate must be positive, got {self.basis_decay_rate}")
127
+
128
+ if self.market_price is not None and self.market_price <= 0:
129
+ raise ValidationError(f"Market price must be positive if provided, got {self.market_price}")
130
+
131
+ # Futures must have a maturity
132
+ if self.maturity is None and self.maturity_date is None:
133
+ raise ValidationError("Futures contract must have a maturity or maturity_date")
134
+
135
+ @property
136
+ def is_linear(self) -> bool:
137
+ return True
138
+
139
+ def get_forward_price(
140
+ self,
141
+ spot: float,
142
+ rate: float,
143
+ div_yield: float,
144
+ time_to_maturity: float
145
+ ) -> float:
146
+ """
147
+ Calculate the theoretical forward price with basis.
148
+
149
+ Forward price with basis:
150
+ F(t,T) = S(t) * exp((r - q) * (T - t)) + basis(t) * exp(-λ * (T - t))
151
+
152
+ The basis decays exponentially to zero as the contract approaches maturity,
153
+ ensuring convergence to the spot price at expiration.
154
+
155
+ Args:
156
+ spot: Current spot price
157
+ rate: Risk-free rate (continuously compounded)
158
+ div_yield: Dividend yield (continuously compounded)
159
+ time_to_maturity: Time to maturity in years
160
+
161
+ Returns:
162
+ Theoretical forward price with basis
163
+
164
+ Raises:
165
+ ValidationError: If inputs are invalid
166
+ """
167
+ if spot <= 0:
168
+ raise ValidationError(f"Spot price must be positive, got {spot}")
169
+ if time_to_maturity < 0:
170
+ raise ValidationError(f"Time to maturity must be non-negative, got {time_to_maturity}")
171
+
172
+ # Theoretical forward price (cost-of-carry)
173
+ carry_cost = (rate - div_yield) * time_to_maturity
174
+ theoretical_forward = spot * math.exp(carry_cost)
175
+
176
+ # Add decaying basis
177
+ basis_decay = math.exp(-self.basis_decay_rate * time_to_maturity)
178
+ forward_price = theoretical_forward + self.basis * basis_decay
179
+
180
+ return forward_price
181
+
182
+ def get_theoretical_price(
183
+ self,
184
+ spot: float,
185
+ rate: float,
186
+ div_yield: float,
187
+ time_to_maturity: float
188
+ ) -> float:
189
+ """
190
+ Get theoretical futures contract value (per contract, not notional).
191
+
192
+ For futures contracts, the value is the forward price times multiplier.
193
+
194
+ Args:
195
+ spot: Current spot price
196
+ rate: Risk-free rate
197
+ div_yield: Dividend yield
198
+ time_to_maturity: Time to maturity in years
199
+
200
+ Returns:
201
+ Theoretical contract value
202
+ """
203
+ forward_price = self.get_forward_price(spot, rate, div_yield, time_to_maturity)
204
+ return forward_price * self.multiplier
205
+
206
+ def get_mark_to_market_price(self) -> Optional[float]:
207
+ """
208
+ Get mark-to-market price based on observed market price.
209
+
210
+ If market_price is set, returns the contract value based on observed
211
+ market price. Otherwise returns None.
212
+
213
+ Returns:
214
+ Mark-to-market contract value, or None if no market price available
215
+ """
216
+ if self.market_price is None:
217
+ return None
218
+ return self.market_price * self.multiplier
219
+
220
+ def get_notional_value(self, price: float) -> float:
221
+ """
222
+ Calculate notional value of the futures contract.
223
+
224
+ Notional value = price * multiplier
225
+
226
+ Args:
227
+ price: Futures price (per unit)
228
+
229
+ Returns:
230
+ Notional value
231
+ """
232
+ return price * self.multiplier
233
+
234
+ def update_market_price(self, new_market_price: float) -> None:
235
+ """
236
+ Update the observed market price for mark-to-market.
237
+
238
+ Args:
239
+ new_market_price: New observed market price
240
+
241
+ Raises:
242
+ ValidationError: If price is invalid
243
+ """
244
+ if new_market_price <= 0:
245
+ raise ValidationError(f"Market price must be positive, got {new_market_price}")
246
+ self.market_price = new_market_price
247
+
248
+ def get_basis(
249
+ self,
250
+ spot: float,
251
+ rate: float,
252
+ div_yield: float,
253
+ time_to_maturity: float,
254
+ observed_futures_price: Optional[float] = None
255
+ ) -> float:
256
+ """
257
+ Calculate or update the basis.
258
+
259
+ If observed_futures_price is provided, calculates the basis as:
260
+ basis = observed_futures_price - theoretical_forward
261
+
262
+ Otherwise returns the current basis attribute.
263
+
264
+ Args:
265
+ spot: Current spot price
266
+ rate: Risk-free rate
267
+ div_yield: Dividend yield
268
+ time_to_maturity: Time to maturity in years
269
+ observed_futures_price: Optional observed market price
270
+
271
+ Returns:
272
+ Basis value (in price units, not annualized)
273
+ """
274
+ if observed_futures_price is not None:
275
+ # Calculate theoretical forward without basis
276
+ carry_cost = (rate - div_yield) * time_to_maturity
277
+ theoretical_forward = spot * math.exp(carry_cost)
278
+
279
+ # Basis is the difference
280
+ return observed_futures_price - theoretical_forward
281
+ else:
282
+ return self.basis
283
+
284
+ def calculate_implied_basis(
285
+ self,
286
+ spot: float,
287
+ rate: float,
288
+ div_yield: float,
289
+ time_to_maturity: float,
290
+ observed_futures_price: float,
291
+ ) -> float:
292
+ """
293
+ Calculate the implied basis from an observed futures price.
294
+
295
+ The basis is defined as the difference between the observed futures
296
+ price and the theoretical forward price (cost-of-carry model):
297
+
298
+ basis = F_observed - S * exp((r - d) * T)
299
+
300
+ Args:
301
+ spot: Current spot price
302
+ rate: Risk-free rate (continuously compounded)
303
+ div_yield: Dividend yield (continuously compounded)
304
+ time_to_maturity: Time to maturity in years
305
+ observed_futures_price: Observed market futures price
306
+
307
+ Returns:
308
+ Implied basis in price units (points)
309
+
310
+ Raises:
311
+ ValidationError: If inputs are invalid
312
+ """
313
+ if spot <= 0:
314
+ raise ValidationError(f"Spot must be positive, got {spot}")
315
+ if observed_futures_price <= 0:
316
+ raise ValidationError(f"Futures price must be positive, got {observed_futures_price}")
317
+ if time_to_maturity <= 0:
318
+ raise ValidationError(f"Time to maturity must be positive, got {time_to_maturity}")
319
+
320
+ # Theoretical forward from cost-of-carry model
321
+ theoretical_forward = spot * math.exp((rate - div_yield) * time_to_maturity)
322
+
323
+ # Implied basis
324
+ return observed_futures_price - theoretical_forward
325
+
326
+ def calculate_annualized_basis(
327
+ self,
328
+ spot: float,
329
+ rate: float,
330
+ div_yield: float,
331
+ time_to_maturity: float,
332
+ observed_futures_price: Optional[float] = None,
333
+ ) -> float:
334
+ """
335
+ Calculate the annualized basis rate.
336
+
337
+ The annualized basis represents the basis as an annual continuously
338
+ compounded rate. This allows direct comparison with dividend yields
339
+ and interest rates.
340
+
341
+ Derivation:
342
+ F = S * exp((r - d + b_annual) * T)
343
+
344
+ Solving for b_annual:
345
+ b_annual = (1/T) * ln(F/S) - r + d
346
+
347
+ Or equivalently, using the points basis:
348
+ b_annual = (1/T) * ln(1 + basis/S) (for small basis)
349
+
350
+ Args:
351
+ spot: Current spot price
352
+ rate: Risk-free rate (continuously compounded)
353
+ div_yield: Dividend yield (continuously compounded)
354
+ time_to_maturity: Time to maturity in years
355
+ observed_futures_price: Optional observed futures price.
356
+ If not provided, uses self.basis attribute.
357
+
358
+ Returns:
359
+ Annualized basis rate (as a decimal, e.g., 0.02 = 2%)
360
+
361
+ Raises:
362
+ ValidationError: If inputs are invalid or time_to_maturity is zero
363
+
364
+ Examples:
365
+ >>> # ES futures at 4500, spot at 4480, T=0.25 years
366
+ >>> future = Futures(underlying="ES", multiplier=50)
367
+ >>> b_annual = future.calculate_annualized_basis(
368
+ ... spot=4480, rate=0.05, div_yield=0.015,
369
+ ... time_to_maturity=0.25, observed_futures_price=4500
370
+ ... )
371
+ """
372
+ if spot <= 0:
373
+ raise ValidationError(f"Spot must be positive, got {spot}")
374
+ if time_to_maturity <= 0:
375
+ raise ValidationError(f"Time to maturity must be positive, got {time_to_maturity}")
376
+
377
+ if observed_futures_price is not None:
378
+ if observed_futures_price <= 0:
379
+ raise ValidationError(f"Futures price must be positive, got {observed_futures_price}")
380
+
381
+ # Calculate annualized basis rate directly from futures price
382
+ # F = S * exp((r - d + b) * T)
383
+ # b = (1/T) * ln(F/S) - r + d
384
+ futures_ratio = observed_futures_price / spot
385
+ return (math.log(futures_ratio) / time_to_maturity) - rate + div_yield
386
+ else:
387
+ # Use stored basis attribute
388
+ # For small basis relative to spot: b_annual ≈ basis / (spot * T)
389
+ # More precisely: b_annual = (1/T) * ln(1 + basis/S)
390
+ basis_relative_to_spot = self.basis / spot
391
+ # Ensure we don't take log of negative number (basis can be negative)
392
+ # When basis is small relative to spot, ln(1 + x) ≈ x
393
+ if abs(basis_relative_to_spot) < 0.01:
394
+ # Use approximation for small basis
395
+ return basis_relative_to_spot / time_to_maturity
396
+ else:
397
+ # Use exact formula
398
+ if 1 + basis_relative_to_spot <= 0:
399
+ raise ValidationError(
400
+ f"Basis too negative relative to spot: {basis_relative_to_spot}"
401
+ )
402
+ return math.log(1 + basis_relative_to_spot) / time_to_maturity
403
+
404
+ def calculate_basis_in_bps(
405
+ self,
406
+ spot: float,
407
+ rate: float,
408
+ div_yield: float,
409
+ time_to_maturity: float,
410
+ observed_futures_price: Optional[float] = None,
411
+ ) -> float:
412
+ """
413
+ Calculate the basis in basis points (bps).
414
+
415
+ This is a convenience method that returns the annualized basis
416
+ rate converted to basis points (1 bp = 0.01%).
417
+
418
+ Args:
419
+ spot: Current spot price
420
+ rate: Risk-free rate
421
+ div_yield: Dividend yield
422
+ time_to_maturity: Time to maturity in years
423
+ observed_futures_price: Optional observed futures price
424
+
425
+ Returns:
426
+ Basis in basis points (e.g., 25.0 = 25 bps)
427
+
428
+ Examples:
429
+ >>> bps = future.calculate_basis_in_bps(
430
+ ... spot=4480, rate=0.05, div_yield=0.015,
431
+ ... time_to_maturity=0.25, observed_futures_price=4500
432
+ ... )
433
+ >>> print(f"Basis: {bps:.1f} bps")
434
+ """
435
+ annualized = self.calculate_annualized_basis(
436
+ spot, rate, div_yield, time_to_maturity, observed_futures_price
437
+ )
438
+ return annualized * 10000 # Convert to bps
439
+
440
+ def get_implied_dividend_from_basis(
441
+ self,
442
+ spot: float,
443
+ rate: float,
444
+ time_to_maturity: float,
445
+ observed_futures_price: float,
446
+ ) -> float:
447
+ """
448
+ Calculate the implied dividend yield from the observed futures price.
449
+
450
+ Using the cost-of-carry model and assuming zero basis:
451
+ F = S * exp((r - d) * T)
452
+
453
+ Solving for d:
454
+ d = r - (1/T) * ln(F/S)
455
+
456
+ Args:
457
+ spot: Current spot price
458
+ rate: Risk-free rate (continuously compounded)
459
+ time_to_maturity: Time to maturity in years
460
+ observed_futures_price: Observed market futures price
461
+
462
+ Returns:
463
+ Implied dividend yield (as a decimal)
464
+
465
+ Raises:
466
+ ValidationError: If inputs are invalid
467
+ """
468
+ if spot <= 0:
469
+ raise ValidationError(f"Spot must be positive, got {spot}")
470
+ if observed_futures_price <= 0:
471
+ raise ValidationError(f"Futures price must be positive, got {observed_futures_price}")
472
+ if time_to_maturity <= 0:
473
+ raise ValidationError(f"Time to maturity must be positive, got {time_to_maturity}")
474
+
475
+ futures_ratio = observed_futures_price / spot
476
+ return rate - (math.log(futures_ratio) / time_to_maturity)
477
+
478
+ def __repr__(self):
479
+ mtm_str = f", mtm=${self.market_price:.2f}" if self.market_price else ""
480
+ if self.maturity_date:
481
+ return (f"Futures({self.underlying}, mult={self.multiplier:.1f}, "
482
+ f"maturity_date={self.maturity_date.date()}, basis={self.basis:.4f}{mtm_str})")
483
+ else:
484
+ return (f"Futures({self.underlying}, mult={self.multiplier:.1f}, "
485
+ f"T={self.maturity:.4f}, basis={self.basis:.4f}{mtm_str})")
@@ -0,0 +1,118 @@
1
+ """
2
+ Spot instrument implementation for stocks, indices, and ETFs.
3
+ """
4
+
5
+ import math
6
+ from dataclasses import dataclass
7
+ from typing import Optional
8
+ from datetime import datetime
9
+ from .base_deltaone_product import BaseDeltaOneProduct
10
+ from quantark.util.enum.deltaone_enums import DeltaOneType
11
+ from quantark.util.exceptions import ValidationError
12
+
13
+
14
+ @dataclass
15
+ class SpotInstrument(BaseDeltaOneProduct):
16
+ """
17
+ Spot instrument (Stock, Index, or ETF).
18
+
19
+ Spot instruments are perpetual holdings with no maturity date.
20
+ Their value follows the underlying asset price with delta = 1.
21
+
22
+ Forward pricing follows cost-of-carry model:
23
+ F(t,T) = S(t) * exp((r - q) * (T - t))
24
+
25
+ Attributes:
26
+ underlying: Identifier for the underlying asset (e.g., ticker symbol)
27
+ deltaone_type: Type of spot instrument (STOCK, INDEX, or ETF)
28
+
29
+ Example:
30
+ >>> stock = SpotInstrument(underlying="AAPL", deltaone_type=DeltaOneType.STOCK)
31
+ >>> etf = SpotInstrument(underlying="SPY", deltaone_type=DeltaOneType.ETF)
32
+ """
33
+
34
+ def __init__(
35
+ self,
36
+ underlying: str,
37
+ deltaone_type: DeltaOneType,
38
+ ):
39
+ """
40
+ Initialize spot instrument.
41
+
42
+ Args:
43
+ underlying: Identifier for the underlying asset
44
+ deltaone_type: Type of instrument (STOCK, INDEX, or ETF)
45
+
46
+ Raises:
47
+ ValidationError: If deltaone_type is FUTURES (use Futures class instead)
48
+ """
49
+ if deltaone_type == DeltaOneType.FUTURES:
50
+ raise ValidationError(
51
+ "Use Futures class for futures products, not SpotInstrument"
52
+ )
53
+
54
+ # Spot instruments are perpetual (no maturity)
55
+ super().__init__(
56
+ underlying=underlying,
57
+ deltaone_type=deltaone_type,
58
+ maturity=None,
59
+ maturity_date=None,
60
+ )
61
+
62
+ def get_forward_price(
63
+ self,
64
+ spot: float,
65
+ rate: float,
66
+ div_yield: float,
67
+ time_to_maturity: float
68
+ ) -> float:
69
+ """
70
+ Calculate the forward price using cost-of-carry model.
71
+
72
+ Forward price: F(t,T) = S(t) * exp((r - q) * (T - t))
73
+
74
+ Args:
75
+ spot: Current spot price
76
+ rate: Risk-free rate (continuously compounded)
77
+ div_yield: Dividend yield (continuously compounded)
78
+ time_to_maturity: Time to forward date in years
79
+
80
+ Returns:
81
+ Forward price
82
+
83
+ Raises:
84
+ ValidationError: If inputs are invalid
85
+ """
86
+ if spot <= 0:
87
+ raise ValidationError(f"Spot price must be positive, got {spot}")
88
+ if time_to_maturity < 0:
89
+ raise ValidationError(f"Time to maturity must be non-negative, got {time_to_maturity}")
90
+
91
+ # Cost-of-carry forward pricing
92
+ carry_cost = (rate - div_yield) * time_to_maturity
93
+ forward_price = spot * math.exp(carry_cost)
94
+
95
+ return forward_price
96
+
97
+ def get_current_value(self, spot: float) -> float:
98
+ """
99
+ Get the current value of the spot instrument.
100
+
101
+ For spot instruments, current value equals spot price.
102
+
103
+ Args:
104
+ spot: Current spot price
105
+
106
+ Returns:
107
+ Current value (equals spot)
108
+ """
109
+ if spot < 0:
110
+ raise ValidationError(f"Spot price must be non-negative, got {spot}")
111
+ return spot
112
+
113
+ @property
114
+ def is_linear(self) -> bool:
115
+ return True
116
+
117
+ def __repr__(self):
118
+ return f"SpotInstrument({self.underlying}, {self.deltaone_type})"
@@ -0,0 +1,104 @@
1
+ """
2
+ Equity option products.
3
+ """
4
+
5
+ from .base_equity_option import BaseEquityOption
6
+ from .european_vanilla_option import EuropeanVanillaOption
7
+ from .american_option import AmericanOption
8
+ from .asian_option import AsianOption, AsianObservationRecord
9
+ from .digital_option import CashOrNothingDigitalOption
10
+ from .barrier_option import BarrierOption
11
+ from .double_barrier_option import DoubleBarrierOption
12
+ from .one_touch_option import OneTouchOption
13
+ from .double_one_touch_option import DoubleOneTouchOption
14
+ from .observation_schedule import (
15
+ ObservationRecord,
16
+ ObservationSchedule,
17
+ ResolvedObservationRecord,
18
+ )
19
+ from .snowball_option import SnowballOption
20
+ from .ko_reset_snowball_option import KnockOutResetSnowballOption
21
+ from .snowball_config import BarrierConfig, PayoffConfig, AccrualConfig
22
+ from .snowball_helpers import (
23
+ create_standard_snowball,
24
+ create_stepdown_snowball,
25
+ create_european_ki_snowball,
26
+ create_parachute_snowball,
27
+ create_airbag_snowball,
28
+ create_ko_reset_snowball,
29
+ generate_ko_observation_dates,
30
+ generate_stepdown_barriers,
31
+ )
32
+ from .phoenix_option import PhoenixOption
33
+ from .phoenix_config import CouponBarrierConfig
34
+ from .phoenix_helpers import (
35
+ create_standard_phoenix,
36
+ create_stepdown_phoenix,
37
+ create_reverse_phoenix,
38
+ create_memory_phoenix,
39
+ create_non_memory_phoenix,
40
+ )
41
+ from .range_accrual_option import RangeAccrualOption
42
+ from .range_accrual_config import RangeAccrualConfig, RangeAccrualObservationRecord
43
+ from .range_accrual_helpers import (
44
+ create_standard_range_accrual,
45
+ create_reverse_range_accrual,
46
+ create_stepdown_range_accrual,
47
+ generate_range_observation_records,
48
+ assign_calendar_day_weights,
49
+ )
50
+ from .single_sharkfin_option import SingleSharkfinOption
51
+ from .double_sharkfin_option import DoubleSharkfinOption
52
+
53
+ __all__ = [
54
+ "BaseEquityOption",
55
+ "EuropeanVanillaOption",
56
+ "AmericanOption",
57
+ "AsianOption",
58
+ "AsianObservationRecord",
59
+ "CashOrNothingDigitalOption",
60
+ "BarrierOption",
61
+ "DoubleBarrierOption",
62
+ "OneTouchOption",
63
+ "DoubleOneTouchOption",
64
+ "ObservationRecord",
65
+ "ObservationSchedule",
66
+ "ResolvedObservationRecord",
67
+ "SnowballOption",
68
+ "KnockOutResetSnowballOption",
69
+ "BarrierConfig",
70
+ "PayoffConfig",
71
+ "AccrualConfig",
72
+ # Snowball helpers
73
+ "create_standard_snowball",
74
+ "create_stepdown_snowball",
75
+ "create_european_ki_snowball",
76
+ "create_parachute_snowball",
77
+ "create_airbag_snowball",
78
+ "create_ko_reset_snowball",
79
+ "generate_ko_observation_dates",
80
+ "generate_stepdown_barriers",
81
+ # Phoenix option
82
+ "PhoenixOption",
83
+ "CouponBarrierConfig",
84
+ # Phoenix helpers
85
+ "create_standard_phoenix",
86
+ "create_stepdown_phoenix",
87
+ "create_reverse_phoenix",
88
+ "create_memory_phoenix",
89
+ "create_non_memory_phoenix",
90
+ # Range Accrual option
91
+ "RangeAccrualOption",
92
+ "RangeAccrualConfig",
93
+ "RangeAccrualObservationRecord",
94
+ # Range Accrual helpers
95
+ "create_standard_range_accrual",
96
+ "create_reverse_range_accrual",
97
+ "create_stepdown_range_accrual",
98
+ "generate_range_observation_records",
99
+ "assign_calendar_day_weights",
100
+ # Single Sharkfin option
101
+ "SingleSharkfinOption",
102
+ # Double Sharkfin option
103
+ "DoubleSharkfinOption",
104
+ ]