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.
- quantark/__init__.py +3 -0
- quantark/_compat.py +150 -0
- quantark/asset/__init__.py +8 -0
- quantark/asset/bond/__init__.py +2 -0
- quantark/asset/bond/engine/__init__.py +44 -0
- quantark/asset/bond/engine/analytical/__init__.py +12 -0
- quantark/asset/bond/engine/analytical/black_engine.py +583 -0
- quantark/asset/bond/engine/analytical/bond_forward_engine.py +390 -0
- quantark/asset/bond/engine/analytical/bond_futures_engine.py +569 -0
- quantark/asset/bond/engine/convertible/__init__.py +12 -0
- quantark/asset/bond/engine/convertible/convertible_bond_engine.py +800 -0
- quantark/asset/bond/engine/discount/__init__.py +10 -0
- quantark/asset/bond/engine/discount/bond_discount_engine.py +517 -0
- quantark/asset/bond/engine/discount/frn_engine.py +913 -0
- quantark/asset/bond/engine/pde/__init__.py +14 -0
- quantark/asset/bond/engine/pde/convertible/__init__.py +21 -0
- quantark/asset/bond/engine/pde/convertible/jump_diffusion_engine.py +603 -0
- quantark/asset/bond/engine/pde/convertible/pde_params.py +59 -0
- quantark/asset/bond/engine/pde/convertible/tf_engine.py +546 -0
- quantark/asset/bond/engine/tree/__init__.py +14 -0
- quantark/asset/bond/engine/tree/convertible/__init__.py +21 -0
- quantark/asset/bond/engine/tree/convertible/binomial_engine.py +488 -0
- quantark/asset/bond/engine/tree/convertible/tree_params.py +72 -0
- quantark/asset/bond/engine/tree/convertible/trinomial_engine.py +1341 -0
- quantark/asset/bond/product/__init__.py +37 -0
- quantark/asset/bond/product/base_bond_product.py +114 -0
- quantark/asset/bond/product/convertible/__init__.py +16 -0
- quantark/asset/bond/product/convertible/convertible_bond.py +595 -0
- quantark/asset/bond/product/couponbond/__init__.py +12 -0
- quantark/asset/bond/product/couponbond/fixed_bond.py +285 -0
- quantark/asset/bond/product/couponbond/frn.py +538 -0
- quantark/asset/bond/product/forward/__init__.py +9 -0
- quantark/asset/bond/product/forward/base_bond_forward.py +92 -0
- quantark/asset/bond/product/forward/bond_forward.py +335 -0
- quantark/asset/bond/product/futures/__init__.py +8 -0
- quantark/asset/bond/product/futures/bond_futures.py +532 -0
- quantark/asset/bond/product/option/__init__.py +9 -0
- quantark/asset/bond/product/option/euro_short_term_bond_option.py +231 -0
- quantark/asset/bond/riskmeasures/__init__.py +13 -0
- quantark/asset/bond/riskmeasures/bond_greeks_calculator.py +484 -0
- quantark/asset/bond/schedule/__init__.py +21 -0
- quantark/asset/bond/schedule/cashflow.py +595 -0
- quantark/asset/equity/__init__.py +11 -0
- quantark/asset/equity/analysis/__init__.py +4 -0
- quantark/asset/equity/analysis/autocallable_path_analyzer.py +257 -0
- quantark/asset/equity/engine/__init__.py +84 -0
- quantark/asset/equity/engine/analytical/__init__.py +37 -0
- quantark/asset/equity/engine/analytical/american_option_engine.py +682 -0
- quantark/asset/equity/engine/analytical/asian_option_analytical_engine.py +1102 -0
- quantark/asset/equity/engine/analytical/barrier_analytical_engine.py +455 -0
- quantark/asset/equity/engine/analytical/black_scholes_engine.py +322 -0
- quantark/asset/equity/engine/analytical/deltaone_engine.py +340 -0
- quantark/asset/equity/engine/analytical/digital_option_engine.py +168 -0
- quantark/asset/equity/engine/analytical/double_barrier_option_engine.py +481 -0
- quantark/asset/equity/engine/analytical/double_sharkfin_option_analytical_engine.py +508 -0
- quantark/asset/equity/engine/analytical/one_touch_analytical_engine.py +302 -0
- quantark/asset/equity/engine/analytical/range_accrual_analytical_engine.py +396 -0
- quantark/asset/equity/engine/analytical/single_sharkfin_option_analytical_engine.py +229 -0
- quantark/asset/equity/engine/base_engine.py +137 -0
- quantark/asset/equity/engine/event_stats.py +85 -0
- quantark/asset/equity/engine/mc/__init__.py +31 -0
- quantark/asset/equity/engine/mc/american_option_mc_engine.py +485 -0
- quantark/asset/equity/engine/mc/asian_option_mc_engine.py +678 -0
- quantark/asset/equity/engine/mc/barrier_option_mc_engine.py +726 -0
- quantark/asset/equity/engine/mc/digital_option_mc_engine.py +419 -0
- quantark/asset/equity/engine/mc/double_sharkfin_option_mc_engine.py +676 -0
- quantark/asset/equity/engine/mc/euro_mc_engine.py +423 -0
- quantark/asset/equity/engine/mc/phoenix_mc_engine.py +1206 -0
- quantark/asset/equity/engine/mc/range_accrual_mc_engine.py +738 -0
- quantark/asset/equity/engine/mc/single_sharkfin_option_mc_engine.py +549 -0
- quantark/asset/equity/engine/mc/snowball_mc_engine.py +2250 -0
- quantark/asset/equity/engine/pde/__init__.py +36 -0
- quantark/asset/equity/engine/pde/american_pde_solver.py +211 -0
- quantark/asset/equity/engine/pde/barrier_pde_solver.py +692 -0
- quantark/asset/equity/engine/pde/base_pde_solver.py +994 -0
- quantark/asset/equity/engine/pde/double_barrier_pde_solver.py +510 -0
- quantark/asset/equity/engine/pde/double_one_touch_pde_solver.py +435 -0
- quantark/asset/equity/engine/pde/european_pde_solver.py +170 -0
- quantark/asset/equity/engine/pde/ko_reset_snowball_pde_solver.py +477 -0
- quantark/asset/equity/engine/pde/one_touch_pde_solver.py +439 -0
- quantark/asset/equity/engine/pde/phoenix_pde_solver.py +613 -0
- quantark/asset/equity/engine/pde/snowball_pde_solver.py +1810 -0
- quantark/asset/equity/engine/pde/spatial_grid.py +750 -0
- quantark/asset/equity/engine/pde/time_grid.py +308 -0
- quantark/asset/equity/engine/pde_engine.py +238 -0
- quantark/asset/equity/engine/quad/__init__.py +23 -0
- quantark/asset/equity/engine/quad/discrete_quad_engine.py +106 -0
- quantark/asset/equity/engine/quad/european_quad_engine.py +325 -0
- quantark/asset/equity/engine/quad/ko_reset_snowball_quad_engine.py +362 -0
- quantark/asset/equity/engine/quad/phoenix_quad_engine.py +614 -0
- quantark/asset/equity/engine/quad/quad_adapters.py +1260 -0
- quantark/asset/equity/engine/quad/quad_core.py +513 -0
- quantark/asset/equity/engine/quad/quad_math.py +219 -0
- quantark/asset/equity/engine/quad/snowball_quad_engine.py +1137 -0
- quantark/asset/equity/engine/validation/script/benchmark_check_american_analytical.py +117 -0
- quantark/asset/equity/engine/validation/script/benchmark_check_american_pde.py +114 -0
- quantark/asset/equity/engine/validation/script/benchmark_check_asian_analytical.py +440 -0
- quantark/asset/equity/engine/validation/script/benchmark_check_barrier_analytical.py +269 -0
- quantark/asset/equity/engine/validation/script/benchmark_check_barrier_pde_solver.py +636 -0
- quantark/asset/equity/engine/validation/script/benchmark_check_digital_option.py +256 -0
- quantark/asset/equity/engine/validation/script/benchmark_check_snowball_pde_solver.py +807 -0
- quantark/asset/equity/engine/validation/script/boundary_check_american_analytical.py +290 -0
- quantark/asset/equity/engine/validation/script/boundary_check_american_pde.py +242 -0
- quantark/asset/equity/engine/validation/script/boundary_check_asian_analytical.py +612 -0
- quantark/asset/equity/engine/validation/script/boundary_check_barrier_analytical.py +434 -0
- quantark/asset/equity/engine/validation/script/boundary_check_barrier_pde_solver.py +748 -0
- quantark/asset/equity/engine/validation/script/boundary_check_digital_option.py +575 -0
- quantark/asset/equity/engine/validation/script/boundary_check_snowball_pde_solver.py +1101 -0
- quantark/asset/equity/engine/validation/script/greeks_check_digital_option.py +349 -0
- quantark/asset/equity/engine/validation/script/mc_comparison_barrier_pde.py +270 -0
- quantark/asset/equity/engine/validation/script/quick_mc_compare.py +51 -0
- quantark/asset/equity/engine/validation/script/validation_stepdown_improved.py +97 -0
- quantark/asset/equity/param/__init__.py +24 -0
- quantark/asset/equity/param/engine_param_profiles.py +325 -0
- quantark/asset/equity/param/engine_params.py +728 -0
- quantark/asset/equity/process/__init__.py +7 -0
- quantark/asset/equity/process/bsm/__init__.py +7 -0
- quantark/asset/equity/process/bsm/bsm_process.py +108 -0
- quantark/asset/equity/process/bsm/qmc_brownian_bridge.py +401 -0
- quantark/asset/equity/process/bsm/qmc_path_generator.py +694 -0
- quantark/asset/equity/process/bsm/qmc_rqmc_driver.py +163 -0
- quantark/asset/equity/process/bsm/qmc_sobol.py +195 -0
- quantark/asset/equity/process/bsm/qmc_variance_reduction.py +292 -0
- quantark/asset/equity/product/__init__.py +8 -0
- quantark/asset/equity/product/base_equity_product.py +72 -0
- quantark/asset/equity/product/deltaone/__init__.py +22 -0
- quantark/asset/equity/product/deltaone/base_deltaone_product.py +147 -0
- quantark/asset/equity/product/deltaone/futures.py +485 -0
- quantark/asset/equity/product/deltaone/spot_instrument.py +118 -0
- quantark/asset/equity/product/option/__init__.py +104 -0
- quantark/asset/equity/product/option/american_option.py +114 -0
- quantark/asset/equity/product/option/asian_option.py +531 -0
- quantark/asset/equity/product/option/barrier_option.py +289 -0
- quantark/asset/equity/product/option/base_equity_option.py +659 -0
- quantark/asset/equity/product/option/digital_option.py +102 -0
- quantark/asset/equity/product/option/double_barrier_option.py +286 -0
- quantark/asset/equity/product/option/double_one_touch_option.py +310 -0
- quantark/asset/equity/product/option/double_sharkfin_option.py +466 -0
- quantark/asset/equity/product/option/european_vanilla_option.py +103 -0
- quantark/asset/equity/product/option/ko_reset_snowball_option.py +563 -0
- quantark/asset/equity/product/option/observation_schedule.py +530 -0
- quantark/asset/equity/product/option/one_touch_option.py +287 -0
- quantark/asset/equity/product/option/phoenix_config.py +116 -0
- quantark/asset/equity/product/option/phoenix_helpers.py +576 -0
- quantark/asset/equity/product/option/phoenix_option.py +1167 -0
- quantark/asset/equity/product/option/range_accrual_config.py +288 -0
- quantark/asset/equity/product/option/range_accrual_helpers.py +608 -0
- quantark/asset/equity/product/option/range_accrual_option.py +526 -0
- quantark/asset/equity/product/option/single_sharkfin_option.py +420 -0
- quantark/asset/equity/product/option/snowball_config.py +261 -0
- quantark/asset/equity/product/option/snowball_helpers.py +977 -0
- quantark/asset/equity/product/option/snowball_option.py +1242 -0
- quantark/asset/equity/report/__init__.py +15 -0
- quantark/asset/equity/report/autocallable_risk_report.py +2118 -0
- quantark/asset/equity/report/plotting.py +87 -0
- quantark/asset/equity/report/snowball_risk_comparison_report.py +2230 -0
- quantark/asset/equity/report/surfaces.py +123 -0
- quantark/asset/equity/report/term_structure.py +126 -0
- quantark/asset/equity/riskmeasures/__init__.py +7 -0
- quantark/asset/equity/riskmeasures/greeks_calculator.py +1204 -0
- quantark/asset/rate/__init__.py +58 -0
- quantark/asset/rate/engine/__init__.py +25 -0
- quantark/asset/rate/engine/cap_floor_engine.py +514 -0
- quantark/asset/rate/engine/fra_engine.py +286 -0
- quantark/asset/rate/engine/irs_discount_engine.py +891 -0
- quantark/asset/rate/engine/swaption_engine.py +587 -0
- quantark/asset/rate/product/__init__.py +67 -0
- quantark/asset/rate/product/cap_floor.py +550 -0
- quantark/asset/rate/product/fra.py +219 -0
- quantark/asset/rate/product/irs.py +1223 -0
- quantark/asset/rate/product/swaption.py +372 -0
- quantark/backtest/__init__.py +153 -0
- quantark/backtest/base.py +263 -0
- quantark/backtest/dashboard.py +874 -0
- quantark/backtest/equity/__init__.py +35 -0
- quantark/backtest/equity/config.py +118 -0
- quantark/backtest/equity/engine.py +408 -0
- quantark/backtest/equity/hedge_executor.py +374 -0
- quantark/backtest/equity/metrics.py +396 -0
- quantark/backtest/equity/results.py +232 -0
- quantark/backtest/equity/state.py +252 -0
- quantark/backtest/examples/__init__.py +4 -0
- quantark/backtest/examples/advanced_backtest.py +345 -0
- quantark/backtest/examples/basic_delta_hedge.py +246 -0
- quantark/backtest/examples/fi_dv01_hedge.py +267 -0
- quantark/backtest/fi/__init__.py +30 -0
- quantark/backtest/fi/config.py +114 -0
- quantark/backtest/fi/engine.py +378 -0
- quantark/backtest/fi/hedge_executor.py +254 -0
- quantark/backtest/fi/metrics.py +308 -0
- quantark/backtest/fi/results.py +193 -0
- quantark/backtest/fi/state.py +212 -0
- quantark/backtest/logger.py +393 -0
- quantark/backtest/otc/__init__.py +74 -0
- quantark/backtest/otc/_replay.py +637 -0
- quantark/backtest/otc/book_engine.py +587 -0
- quantark/backtest/otc/config.py +175 -0
- quantark/backtest/otc/dashboard.py +1006 -0
- quantark/backtest/otc/engine.py +420 -0
- quantark/backtest/otc/engine_factory.py +138 -0
- quantark/backtest/otc/market.py +216 -0
- quantark/backtest/otc/results.py +107 -0
- quantark/backtest/otc/state.py +166 -0
- quantark/backtest/report_generator.py +608 -0
- quantark/backtest/strategy/__init__.py +28 -0
- quantark/backtest/strategy/base_strategy.py +235 -0
- quantark/backtest/strategy/convexity_neutral_strategy.py +247 -0
- quantark/backtest/strategy/delta_neutral_strategy.py +283 -0
- quantark/backtest/strategy/dv01_neutral_strategy.py +283 -0
- quantark/backtest/transaction_costs.py +485 -0
- quantark/backtest/visualizer.py +1019 -0
- quantark/cashleg/__init__.py +31 -0
- quantark/cashleg/accrual_leg.py +120 -0
- quantark/cashleg/base.py +48 -0
- quantark/cashleg/base_amount.py +60 -0
- quantark/cashleg/deterministic_leg.py +39 -0
- quantark/cashleg/event_distribution.py +262 -0
- quantark/cashleg/fixed_payoff_leg.py +92 -0
- quantark/cashleg/leg_schedule.py +95 -0
- quantark/cashleg/leg_valuator.py +40 -0
- quantark/dynamicscenario/__init__.py +97 -0
- quantark/dynamicscenario/base.py +297 -0
- quantark/dynamicscenario/config.py +122 -0
- quantark/dynamicscenario/engine.py +703 -0
- quantark/dynamicscenario/equity/__init__.py +14 -0
- quantark/dynamicscenario/fi/__init__.py +24 -0
- quantark/dynamicscenario/fi/config.py +149 -0
- quantark/dynamicscenario/fi/engine.py +500 -0
- quantark/dynamicscenario/fi/results.py +503 -0
- quantark/dynamicscenario/path/__init__.py +17 -0
- quantark/dynamicscenario/path/day_path.py +397 -0
- quantark/dynamicscenario/path/fi_path_library.py +488 -0
- quantark/dynamicscenario/path/path_builder.py +726 -0
- quantark/dynamicscenario/path/path_library.py +620 -0
- quantark/dynamicscenario/report/__init__.py +12 -0
- quantark/dynamicscenario/report/dynamic_report.py +1175 -0
- quantark/dynamicscenario/report/visualizer.py +1586 -0
- quantark/dynamicscenario/results/__init__.py +19 -0
- quantark/dynamicscenario/results/dynamic_results.py +579 -0
- quantark/dynamicscenario/results/result_exporter.py +438 -0
- quantark/param/__init__.py +75 -0
- quantark/param/basis/__init__.py +19 -0
- quantark/param/basis/basis_yield.py +301 -0
- quantark/param/div/__init__.py +16 -0
- quantark/param/div/dividend_yield.py +123 -0
- quantark/param/index/__init__.py +52 -0
- quantark/param/index/rate_index.py +568 -0
- quantark/param/quote/__init__.py +7 -0
- quantark/param/quote/spot_quote.py +35 -0
- quantark/param/rrf/__init__.py +22 -0
- quantark/param/rrf/rate_curve.py +436 -0
- quantark/param/vol/__init__.py +6 -0
- quantark/param/vol/vol_surface.py +118 -0
- quantark/portfolio/__init__.py +61 -0
- quantark/portfolio/base.py +203 -0
- quantark/portfolio/equity/__init__.py +17 -0
- quantark/portfolio/equity/portfolio.py +391 -0
- quantark/portfolio/equity/position.py +368 -0
- quantark/portfolio/fi/__init__.py +14 -0
- quantark/portfolio/fi/portfolio.py +424 -0
- quantark/portfolio/fi/position.py +272 -0
- quantark/portfolio/portfolio_snapshot.py +221 -0
- quantark/portfolio/portfolio_storage.py +414 -0
- quantark/priceenv/__init__.py +7 -0
- quantark/priceenv/pricing_environment.py +196 -0
- quantark/rfq/__init__.py +32 -0
- quantark/rfq/builders.py +102 -0
- quantark/rfq/models.py +214 -0
- quantark/rfq/registry.py +611 -0
- quantark/rfq/service.py +237 -0
- quantark/simm/__init__.py +155 -0
- quantark/simm/calibration/__init__.py +206 -0
- quantark/simm/calibration/accessors.py +439 -0
- quantark/simm/calibration/commodity.py +156 -0
- quantark/simm/calibration/credit_non_qualifying.py +79 -0
- quantark/simm/calibration/credit_qualifying.py +130 -0
- quantark/simm/calibration/cross_risk.py +39 -0
- quantark/simm/calibration/equity.py +125 -0
- quantark/simm/calibration/fx.py +92 -0
- quantark/simm/calibration/ir.py +152 -0
- quantark/simm/calibration/version.py +33 -0
- quantark/simm/config.py +186 -0
- quantark/simm/crif/__init__.py +35 -0
- quantark/simm/crif/models.py +230 -0
- quantark/simm/crif/parser.py +585 -0
- quantark/simm/engines/__init__.py +62 -0
- quantark/simm/engines/aggregation/__init__.py +67 -0
- quantark/simm/engines/aggregation/addon.py +141 -0
- quantark/simm/engines/aggregation/bucket_aggregator.py +298 -0
- quantark/simm/engines/aggregation/concentration.py +349 -0
- quantark/simm/engines/aggregation/product_class_aggregator.py +183 -0
- quantark/simm/engines/aggregation/risk_class_aggregator.py +403 -0
- quantark/simm/engines/aggregation/simm_calculator.py +430 -0
- quantark/simm/engines/aggregation/weighted_sensitivity.py +272 -0
- quantark/simm/engines/base.py +231 -0
- quantark/simm/engines/classification/__init__.py +10 -0
- quantark/simm/engines/classification/bucket_mapper.py +347 -0
- quantark/simm/engines/factory.py +137 -0
- quantark/simm/engines/portfolio_adapter.py +336 -0
- quantark/simm/engines/result.py +176 -0
- quantark/simm/engines/risk_class/__init__.py +18 -0
- quantark/simm/engines/risk_class/equity_engine.py +263 -0
- quantark/simm/engines/risk_class/ir_engine.py +264 -0
- quantark/simm/report/__init__.py +17 -0
- quantark/simm/report/crif_export.py +284 -0
- quantark/simm/report/excel_generator.py +401 -0
- quantark/simm/report/html_generator.py +840 -0
- quantark/simm/results/__init__.py +38 -0
- quantark/simm/results/attribution.py +313 -0
- quantark/simm/results/simm_result.py +339 -0
- quantark/simm/results/whatif.py +268 -0
- quantark/simm/sensitivity.py +533 -0
- quantark/simm/taxonomy.py +416 -0
- quantark/stresstest/__init__.py +67 -0
- quantark/stresstest/base.py +116 -0
- quantark/stresstest/config.py +5 -0
- quantark/stresstest/engine.py +5 -0
- quantark/stresstest/equity/__init__.py +17 -0
- quantark/stresstest/equity/config.py +69 -0
- quantark/stresstest/equity/engine.py +272 -0
- quantark/stresstest/equity/report/__init__.py +7 -0
- quantark/stresstest/equity/report/report_generator.py +423 -0
- quantark/stresstest/equity/report/visualizer.py +328 -0
- quantark/stresstest/equity/results.py +145 -0
- quantark/stresstest/fi/__init__.py +15 -0
- quantark/stresstest/fi/config.py +59 -0
- quantark/stresstest/fi/engine.py +213 -0
- quantark/stresstest/fi/metrics.py +60 -0
- quantark/stresstest/fi/results.py +64 -0
- quantark/stresstest/report/__init__.py +12 -0
- quantark/stresstest/report/report_generator.py +5 -0
- quantark/stresstest/report/visualizer.py +5 -0
- quantark/stresstest/results/__init__.py +16 -0
- quantark/stresstest/results/result_aggregator.py +325 -0
- quantark/stresstest/results/result_exporter.py +286 -0
- quantark/stresstest/results/stress_results.py +5 -0
- quantark/stresstest/scenario/__init__.py +13 -0
- quantark/stresstest/scenario/scenario.py +242 -0
- quantark/stresstest/scenario/scenario_builder.py +376 -0
- quantark/stresstest/scenario/scenario_library.py +435 -0
- quantark/stresstest/scenario/scenario_storage.py +224 -0
- quantark/stresstest/stress/__init__.py +13 -0
- quantark/stresstest/stress/stress_applicator.py +590 -0
- quantark/stresstest/stress/stress_types.py +142 -0
- quantark/util/__init__.py +23 -0
- quantark/util/barrier_shift.py +44 -0
- quantark/util/calendar/__init__.py +27 -0
- quantark/util/calendar/business_calendar.py +584 -0
- quantark/util/calendar/day_counter.py +517 -0
- quantark/util/calendar/holidayfile/china.csv +1920 -0
- quantark/util/calendar/holidayfile/china_sse.csv +1462 -0
- quantark/util/enum/__init__.py +81 -0
- quantark/util/enum/bond_enums.py +112 -0
- quantark/util/enum/deltaone_enums.py +16 -0
- quantark/util/enum/engine_enums.py +137 -0
- quantark/util/enum/greeks_enums.py +29 -0
- quantark/util/enum/option_enums.py +221 -0
- quantark/util/exceptions.py +66 -0
- quantark/util/marketdata/__init__.py +39 -0
- quantark/util/marketdata/adapter/base_adapter.py +203 -0
- quantark/util/marketdata/adapter/mock_adapter.py +265 -0
- quantark/util/marketdata/converter.py +289 -0
- quantark/util/marketdata/example_usage.py +314 -0
- quantark/util/marketdata/generator/__init__.py +7 -0
- quantark/util/marketdata/generator/mock_generator.py +466 -0
- quantark/util/marketdata/models.py +358 -0
- quantark/util/marketdata/storage/__init__.py +7 -0
- quantark/util/marketdata/storage/parquet_storage.py +340 -0
- quantark/util/numerical/__init__.py +98 -0
- quantark/util/numerical/comparison.py +219 -0
- quantark/util/numerical/constants.py +98 -0
- quantark/util/numerical/formatting.py +380 -0
- quantark/util/numerical/pnl.py +17 -0
- quantark/util/numerical/safe_math.py +238 -0
- quantark/util/numerical/validation.py +315 -0
- quantark/var/__init__.py +39 -0
- quantark/var/attribution.py +398 -0
- quantark/var/backtest/__init__.py +7 -0
- quantark/var/backtest/var_backtester.py +309 -0
- quantark/var/base.py +63 -0
- quantark/var/config.py +219 -0
- quantark/var/engines/__init__.py +13 -0
- quantark/var/engines/historical.py +925 -0
- quantark/var/engines/monte_carlo.py +870 -0
- quantark/var/engines/parametric.py +1199 -0
- quantark/var/results/__init__.py +16 -0
- quantark/var/results/incremental_var_result.py +131 -0
- quantark/var/results/var_report.py +346 -0
- quantark/var/results/var_result.py +134 -0
- quantark/var/risk_factors/__init__.py +22 -0
- quantark/var/risk_factors/base.py +41 -0
- quantark/var/risk_factors/equity_factors.py +158 -0
- quantark/var/risk_factors/fi_factors.py +99 -0
- quantark-0.1.0.dist-info/METADATA +351 -0
- quantark-0.1.0.dist-info/RECORD +399 -0
- quantark-0.1.0.dist-info/WHEEL +4 -0
- quantark-0.1.0.dist-info/licenses/LICENSE +202 -0
- quantark-0.1.0.dist-info/licenses/NOTICE +2 -0
- quantark_compat.pth +1 -0
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Discount-based pricing engine for bonds.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import Optional
|
|
7
|
+
import math
|
|
8
|
+
|
|
9
|
+
from quantark.asset.bond.product.base_bond_product import BaseBondProduct
|
|
10
|
+
from quantark.priceenv import PricingEnvironment
|
|
11
|
+
from quantark.util.exceptions import ValidationError, MarketDataError
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class BondDiscountEngine:
|
|
15
|
+
"""
|
|
16
|
+
Discount-based pricing engine for bonds.
|
|
17
|
+
|
|
18
|
+
This engine prices bonds by discounting future cashflows using
|
|
19
|
+
the risk-free rate curve from the pricing environment.
|
|
20
|
+
|
|
21
|
+
Supports:
|
|
22
|
+
- Clean price (without accrued interest)
|
|
23
|
+
- Dirty price (with accrued interest)
|
|
24
|
+
- Yield to maturity calculation
|
|
25
|
+
- Duration and convexity
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, pricing_env: PricingEnvironment):
|
|
29
|
+
"""
|
|
30
|
+
Initialize bond discount engine.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
pricing_env: Pricing environment with rate curve
|
|
34
|
+
"""
|
|
35
|
+
if pricing_env is None:
|
|
36
|
+
raise ValidationError("Pricing environment is required")
|
|
37
|
+
|
|
38
|
+
if pricing_env.rate_curve is None:
|
|
39
|
+
raise MarketDataError("Rate curve is required for bond pricing")
|
|
40
|
+
|
|
41
|
+
self.pricing_env = pricing_env
|
|
42
|
+
|
|
43
|
+
def price(
|
|
44
|
+
self,
|
|
45
|
+
bond: BaseBondProduct,
|
|
46
|
+
valuation_date: Optional[datetime] = None,
|
|
47
|
+
settlement_date: Optional[datetime] = None,
|
|
48
|
+
) -> float:
|
|
49
|
+
"""
|
|
50
|
+
Calculate bond dirty price (present value including accrued interest).
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
bond: Bond product to price
|
|
54
|
+
valuation_date: Date to value the bond (default: pricing env valuation date)
|
|
55
|
+
settlement_date: Settlement date for trade (default: valuation_date)
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Dirty price (present value of all future cashflows)
|
|
59
|
+
"""
|
|
60
|
+
if valuation_date is None:
|
|
61
|
+
valuation_date = self.pricing_env.valuation_date
|
|
62
|
+
|
|
63
|
+
if settlement_date is None:
|
|
64
|
+
settlement_date = valuation_date
|
|
65
|
+
|
|
66
|
+
# Check if bond has matured
|
|
67
|
+
if bond.is_expired(valuation_date):
|
|
68
|
+
return 0.0
|
|
69
|
+
|
|
70
|
+
# Get future cashflows
|
|
71
|
+
cashflows = bond.get_cashflows(settlement_date)
|
|
72
|
+
|
|
73
|
+
if not cashflows:
|
|
74
|
+
return 0.0
|
|
75
|
+
|
|
76
|
+
# Discount each cashflow
|
|
77
|
+
pv = 0.0
|
|
78
|
+
for cf in cashflows:
|
|
79
|
+
# Calculate time to payment
|
|
80
|
+
time_to_payment = (cf.payment_date - valuation_date).days / 365.0
|
|
81
|
+
|
|
82
|
+
if time_to_payment < 0:
|
|
83
|
+
continue # Skip past cashflows
|
|
84
|
+
|
|
85
|
+
# Get discount factor from rate curve
|
|
86
|
+
discount_factor = self.pricing_env.get_discount_factor(time_to_payment)
|
|
87
|
+
|
|
88
|
+
# Add discounted cashflow to present value
|
|
89
|
+
pv += cf.amount * discount_factor
|
|
90
|
+
|
|
91
|
+
return pv
|
|
92
|
+
|
|
93
|
+
def dirty_price(
|
|
94
|
+
self,
|
|
95
|
+
bond: BaseBondProduct,
|
|
96
|
+
valuation_date: Optional[datetime] = None,
|
|
97
|
+
settlement_date: Optional[datetime] = None,
|
|
98
|
+
) -> float:
|
|
99
|
+
"""
|
|
100
|
+
Calculate bond dirty price (alias for price method).
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
bond: Bond product to price
|
|
104
|
+
valuation_date: Date to value the bond
|
|
105
|
+
settlement_date: Settlement date for trade
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Dirty price
|
|
109
|
+
"""
|
|
110
|
+
return self.price(bond, valuation_date, settlement_date)
|
|
111
|
+
|
|
112
|
+
def clean_price(
|
|
113
|
+
self,
|
|
114
|
+
bond: BaseBondProduct,
|
|
115
|
+
valuation_date: Optional[datetime] = None,
|
|
116
|
+
settlement_date: Optional[datetime] = None,
|
|
117
|
+
) -> float:
|
|
118
|
+
"""
|
|
119
|
+
Calculate bond clean price (dirty price - accrued interest).
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
bond: Bond product to price
|
|
123
|
+
valuation_date: Date to value the bond
|
|
124
|
+
settlement_date: Settlement date for trade
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
Clean price
|
|
128
|
+
"""
|
|
129
|
+
if valuation_date is None:
|
|
130
|
+
valuation_date = self.pricing_env.valuation_date
|
|
131
|
+
|
|
132
|
+
if settlement_date is None:
|
|
133
|
+
settlement_date = valuation_date
|
|
134
|
+
|
|
135
|
+
# Get dirty price
|
|
136
|
+
dirty = self.dirty_price(bond, valuation_date, settlement_date)
|
|
137
|
+
|
|
138
|
+
# Calculate accrued interest
|
|
139
|
+
accrued = bond.calculate_accrued_interest(settlement_date)
|
|
140
|
+
|
|
141
|
+
# Clean price = dirty price - accrued interest
|
|
142
|
+
return dirty - accrued
|
|
143
|
+
|
|
144
|
+
def accrued_interest(
|
|
145
|
+
self, bond: BaseBondProduct, settlement_date: Optional[datetime] = None
|
|
146
|
+
) -> float:
|
|
147
|
+
"""
|
|
148
|
+
Calculate accrued interest.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
bond: Bond product
|
|
152
|
+
settlement_date: Settlement date
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
Accrued interest amount
|
|
156
|
+
"""
|
|
157
|
+
if settlement_date is None:
|
|
158
|
+
settlement_date = self.pricing_env.valuation_date
|
|
159
|
+
|
|
160
|
+
return bond.calculate_accrued_interest(settlement_date)
|
|
161
|
+
|
|
162
|
+
def price_from_yield(
|
|
163
|
+
self,
|
|
164
|
+
bond: BaseBondProduct,
|
|
165
|
+
ytm: float,
|
|
166
|
+
valuation_date: Optional[datetime] = None,
|
|
167
|
+
settlement_date: Optional[datetime] = None,
|
|
168
|
+
clean_price: bool = True,
|
|
169
|
+
) -> float:
|
|
170
|
+
"""
|
|
171
|
+
Calculate bond price given yield to maturity.
|
|
172
|
+
|
|
173
|
+
This is the inverse of yield_to_maturity - given a yield, calculate
|
|
174
|
+
the corresponding bond price by discounting all future cashflows.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
bond: Bond product
|
|
178
|
+
ytm: Yield to maturity (annualized, continuously compounded)
|
|
179
|
+
valuation_date: Valuation date
|
|
180
|
+
settlement_date: Settlement date
|
|
181
|
+
clean_price: Whether to return clean price (default: True)
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
Bond price (clean or dirty based on clean_price flag)
|
|
185
|
+
"""
|
|
186
|
+
if valuation_date is None:
|
|
187
|
+
valuation_date = self.pricing_env.valuation_date
|
|
188
|
+
|
|
189
|
+
if settlement_date is None:
|
|
190
|
+
settlement_date = valuation_date
|
|
191
|
+
|
|
192
|
+
# Check if bond has matured
|
|
193
|
+
if bond.is_expired(valuation_date):
|
|
194
|
+
return 0.0
|
|
195
|
+
|
|
196
|
+
# Get future cashflows
|
|
197
|
+
cashflows = bond.get_cashflows(settlement_date)
|
|
198
|
+
|
|
199
|
+
if not cashflows:
|
|
200
|
+
return 0.0
|
|
201
|
+
|
|
202
|
+
# Discount each cashflow using the given yield
|
|
203
|
+
dirty_price = 0.0
|
|
204
|
+
for cf in cashflows:
|
|
205
|
+
time_to_payment = (cf.payment_date - valuation_date).days / 365.0
|
|
206
|
+
|
|
207
|
+
if time_to_payment < 0:
|
|
208
|
+
continue
|
|
209
|
+
|
|
210
|
+
# Discount factor using the given yield
|
|
211
|
+
df = math.exp(-ytm * time_to_payment)
|
|
212
|
+
dirty_price += cf.amount * df
|
|
213
|
+
|
|
214
|
+
if clean_price:
|
|
215
|
+
accrued = bond.calculate_accrued_interest(settlement_date)
|
|
216
|
+
return dirty_price - accrued
|
|
217
|
+
|
|
218
|
+
return dirty_price
|
|
219
|
+
|
|
220
|
+
def dirty_price_from_yield(
|
|
221
|
+
self,
|
|
222
|
+
bond: BaseBondProduct,
|
|
223
|
+
ytm: float,
|
|
224
|
+
valuation_date: Optional[datetime] = None,
|
|
225
|
+
settlement_date: Optional[datetime] = None,
|
|
226
|
+
) -> float:
|
|
227
|
+
"""
|
|
228
|
+
Calculate dirty price given yield to maturity.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
bond: Bond product
|
|
232
|
+
ytm: Yield to maturity (annualized, continuously compounded)
|
|
233
|
+
valuation_date: Valuation date
|
|
234
|
+
settlement_date: Settlement date
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
Dirty price
|
|
238
|
+
"""
|
|
239
|
+
return self.price_from_yield(
|
|
240
|
+
bond, ytm, valuation_date, settlement_date, clean_price=False
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
def clean_price_from_yield(
|
|
244
|
+
self,
|
|
245
|
+
bond: BaseBondProduct,
|
|
246
|
+
ytm: float,
|
|
247
|
+
valuation_date: Optional[datetime] = None,
|
|
248
|
+
settlement_date: Optional[datetime] = None,
|
|
249
|
+
) -> float:
|
|
250
|
+
"""
|
|
251
|
+
Calculate clean price given yield to maturity.
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
bond: Bond product
|
|
255
|
+
ytm: Yield to maturity (annualized, continuously compounded)
|
|
256
|
+
valuation_date: Valuation date
|
|
257
|
+
settlement_date: Settlement date
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
Clean price
|
|
261
|
+
"""
|
|
262
|
+
return self.price_from_yield(
|
|
263
|
+
bond, ytm, valuation_date, settlement_date, clean_price=True
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
def yield_to_maturity(
|
|
267
|
+
self,
|
|
268
|
+
bond: BaseBondProduct,
|
|
269
|
+
price: float,
|
|
270
|
+
valuation_date: Optional[datetime] = None,
|
|
271
|
+
settlement_date: Optional[datetime] = None,
|
|
272
|
+
clean_price: bool = True,
|
|
273
|
+
max_iterations: int = 100,
|
|
274
|
+
tolerance: float = 1e-6,
|
|
275
|
+
) -> float:
|
|
276
|
+
"""
|
|
277
|
+
Calculate yield to maturity using Newton-Raphson iteration.
|
|
278
|
+
|
|
279
|
+
Args:
|
|
280
|
+
bond: Bond product
|
|
281
|
+
price: Market price (clean or dirty based on clean_price flag)
|
|
282
|
+
valuation_date: Valuation date
|
|
283
|
+
settlement_date: Settlement date
|
|
284
|
+
clean_price: Whether price is clean price (default: True)
|
|
285
|
+
max_iterations: Maximum iterations for solver
|
|
286
|
+
tolerance: Convergence tolerance
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
Yield to maturity (annualized)
|
|
290
|
+
|
|
291
|
+
Raises:
|
|
292
|
+
ValidationError: If convergence fails
|
|
293
|
+
"""
|
|
294
|
+
if valuation_date is None:
|
|
295
|
+
valuation_date = self.pricing_env.valuation_date
|
|
296
|
+
|
|
297
|
+
if settlement_date is None:
|
|
298
|
+
settlement_date = valuation_date
|
|
299
|
+
|
|
300
|
+
if price <= 0:
|
|
301
|
+
raise ValidationError(f"Price must be positive, got {price}")
|
|
302
|
+
|
|
303
|
+
# Convert clean price to dirty price if needed
|
|
304
|
+
if clean_price:
|
|
305
|
+
accrued = bond.calculate_accrued_interest(settlement_date)
|
|
306
|
+
target_price = price + accrued
|
|
307
|
+
else:
|
|
308
|
+
target_price = price
|
|
309
|
+
|
|
310
|
+
# Get cashflows
|
|
311
|
+
cashflows = bond.get_cashflows(settlement_date)
|
|
312
|
+
|
|
313
|
+
if not cashflows:
|
|
314
|
+
raise ValidationError("No future cashflows to calculate yield")
|
|
315
|
+
|
|
316
|
+
# Initial guess: use coupon rate or estimate from price
|
|
317
|
+
if hasattr(bond, "coupon_rate"):
|
|
318
|
+
ytm = bond.coupon_rate
|
|
319
|
+
else:
|
|
320
|
+
# Rough estimate from price
|
|
321
|
+
ttm = bond.time_to_maturity(valuation_date)
|
|
322
|
+
ytm = (
|
|
323
|
+
-math.log(price / bond.get_denominator()) / ttm if ttm > 0 else 0.05
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
# Newton-Raphson iteration
|
|
327
|
+
for iteration in range(max_iterations):
|
|
328
|
+
# Calculate price and duration at current yield
|
|
329
|
+
pv = 0.0
|
|
330
|
+
duration = 0.0
|
|
331
|
+
|
|
332
|
+
for cf in cashflows:
|
|
333
|
+
time_to_payment = (cf.payment_date - valuation_date).days / 365.0
|
|
334
|
+
|
|
335
|
+
if time_to_payment < 0:
|
|
336
|
+
continue
|
|
337
|
+
|
|
338
|
+
df = math.exp(-ytm * time_to_payment)
|
|
339
|
+
pv += cf.amount * df
|
|
340
|
+
duration += cf.amount * time_to_payment * df
|
|
341
|
+
|
|
342
|
+
# Check convergence
|
|
343
|
+
price_diff = pv - target_price
|
|
344
|
+
|
|
345
|
+
if abs(price_diff) < tolerance:
|
|
346
|
+
return ytm
|
|
347
|
+
|
|
348
|
+
# Newton-Raphson update
|
|
349
|
+
# f(y) = PV(y) - target_price
|
|
350
|
+
# f'(y) = -duration
|
|
351
|
+
if abs(duration) < 1e-10:
|
|
352
|
+
raise ValidationError("Duration too small for yield calculation")
|
|
353
|
+
|
|
354
|
+
ytm = ytm - price_diff / (-duration)
|
|
355
|
+
|
|
356
|
+
# Sanity check on yield
|
|
357
|
+
if ytm < -0.5 or ytm > 1.0:
|
|
358
|
+
ytm = max(-0.5, min(1.0, ytm))
|
|
359
|
+
|
|
360
|
+
raise ValidationError(
|
|
361
|
+
f"Yield to maturity did not converge after {max_iterations} iterations"
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
def modified_duration(
|
|
365
|
+
self,
|
|
366
|
+
bond: BaseBondProduct,
|
|
367
|
+
valuation_date: Optional[datetime] = None,
|
|
368
|
+
settlement_date: Optional[datetime] = None,
|
|
369
|
+
) -> float:
|
|
370
|
+
"""
|
|
371
|
+
Calculate modified duration.
|
|
372
|
+
|
|
373
|
+
Modified duration measures the price sensitivity to yield changes.
|
|
374
|
+
|
|
375
|
+
Args:
|
|
376
|
+
bond: Bond product
|
|
377
|
+
valuation_date: Valuation date
|
|
378
|
+
settlement_date: Settlement date
|
|
379
|
+
|
|
380
|
+
Returns:
|
|
381
|
+
Modified duration
|
|
382
|
+
"""
|
|
383
|
+
if valuation_date is None:
|
|
384
|
+
valuation_date = self.pricing_env.valuation_date
|
|
385
|
+
|
|
386
|
+
if settlement_date is None:
|
|
387
|
+
settlement_date = valuation_date
|
|
388
|
+
|
|
389
|
+
# Get price and cashflows
|
|
390
|
+
base_price = self.price(bond, valuation_date, settlement_date)
|
|
391
|
+
|
|
392
|
+
if base_price == 0:
|
|
393
|
+
return 0.0
|
|
394
|
+
|
|
395
|
+
cashflows = bond.get_cashflows(settlement_date)
|
|
396
|
+
|
|
397
|
+
if not cashflows:
|
|
398
|
+
return 0.0
|
|
399
|
+
|
|
400
|
+
# Calculate weighted average time to cashflows
|
|
401
|
+
weighted_time = 0.0
|
|
402
|
+
|
|
403
|
+
for cf in cashflows:
|
|
404
|
+
time_to_payment = (cf.payment_date - valuation_date).days / 365.0
|
|
405
|
+
|
|
406
|
+
if time_to_payment < 0:
|
|
407
|
+
continue
|
|
408
|
+
|
|
409
|
+
discount_factor = self.pricing_env.get_discount_factor(time_to_payment)
|
|
410
|
+
pv = cf.amount * discount_factor
|
|
411
|
+
|
|
412
|
+
weighted_time += pv * time_to_payment
|
|
413
|
+
|
|
414
|
+
# Modified duration = weighted average time / price
|
|
415
|
+
return weighted_time / base_price
|
|
416
|
+
|
|
417
|
+
def macaulay_duration(
|
|
418
|
+
self,
|
|
419
|
+
bond: BaseBondProduct,
|
|
420
|
+
valuation_date: Optional[datetime] = None,
|
|
421
|
+
settlement_date: Optional[datetime] = None,
|
|
422
|
+
) -> float:
|
|
423
|
+
"""
|
|
424
|
+
Calculate Macaulay duration.
|
|
425
|
+
|
|
426
|
+
Args:
|
|
427
|
+
bond: Bond product
|
|
428
|
+
valuation_date: Valuation date
|
|
429
|
+
settlement_date: Settlement date
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
Macaulay duration (in years)
|
|
433
|
+
"""
|
|
434
|
+
# For continuously compounded yields, Macaulay = Modified duration
|
|
435
|
+
return self.modified_duration(bond, valuation_date, settlement_date)
|
|
436
|
+
|
|
437
|
+
def convexity(
|
|
438
|
+
self,
|
|
439
|
+
bond: BaseBondProduct,
|
|
440
|
+
valuation_date: Optional[datetime] = None,
|
|
441
|
+
settlement_date: Optional[datetime] = None,
|
|
442
|
+
) -> float:
|
|
443
|
+
"""
|
|
444
|
+
Calculate convexity.
|
|
445
|
+
|
|
446
|
+
Convexity measures the curvature of the price-yield relationship.
|
|
447
|
+
|
|
448
|
+
Args:
|
|
449
|
+
bond: Bond product
|
|
450
|
+
valuation_date: Valuation date
|
|
451
|
+
settlement_date: Settlement date
|
|
452
|
+
|
|
453
|
+
Returns:
|
|
454
|
+
Convexity
|
|
455
|
+
"""
|
|
456
|
+
if valuation_date is None:
|
|
457
|
+
valuation_date = self.pricing_env.valuation_date
|
|
458
|
+
|
|
459
|
+
if settlement_date is None:
|
|
460
|
+
settlement_date = valuation_date
|
|
461
|
+
|
|
462
|
+
# Get price and cashflows
|
|
463
|
+
base_price = self.price(bond, valuation_date, settlement_date)
|
|
464
|
+
|
|
465
|
+
if base_price == 0:
|
|
466
|
+
return 0.0
|
|
467
|
+
|
|
468
|
+
cashflows = bond.get_cashflows(settlement_date)
|
|
469
|
+
|
|
470
|
+
if not cashflows:
|
|
471
|
+
return 0.0
|
|
472
|
+
|
|
473
|
+
# Calculate weighted average time squared
|
|
474
|
+
weighted_time_sq = 0.0
|
|
475
|
+
|
|
476
|
+
for cf in cashflows:
|
|
477
|
+
time_to_payment = (cf.payment_date - valuation_date).days / 365.0
|
|
478
|
+
|
|
479
|
+
if time_to_payment < 0:
|
|
480
|
+
continue
|
|
481
|
+
|
|
482
|
+
discount_factor = self.pricing_env.get_discount_factor(time_to_payment)
|
|
483
|
+
pv = cf.amount * discount_factor
|
|
484
|
+
|
|
485
|
+
weighted_time_sq += pv * time_to_payment * time_to_payment
|
|
486
|
+
|
|
487
|
+
# Convexity
|
|
488
|
+
return weighted_time_sq / base_price
|
|
489
|
+
|
|
490
|
+
def dv01(
|
|
491
|
+
self,
|
|
492
|
+
bond: BaseBondProduct,
|
|
493
|
+
valuation_date: Optional[datetime] = None,
|
|
494
|
+
settlement_date: Optional[datetime] = None,
|
|
495
|
+
) -> float:
|
|
496
|
+
"""
|
|
497
|
+
Calculate DV01 (dollar value of one basis point).
|
|
498
|
+
|
|
499
|
+
DV01 measures the change in bond price for a 1 basis point
|
|
500
|
+
change in yield.
|
|
501
|
+
|
|
502
|
+
Args:
|
|
503
|
+
bond: Bond product
|
|
504
|
+
valuation_date: Valuation date
|
|
505
|
+
settlement_date: Settlement date
|
|
506
|
+
|
|
507
|
+
Returns:
|
|
508
|
+
DV01 (price change per basis point)
|
|
509
|
+
"""
|
|
510
|
+
mod_dur = self.modified_duration(bond, valuation_date, settlement_date)
|
|
511
|
+
price = self.price(bond, valuation_date, settlement_date)
|
|
512
|
+
|
|
513
|
+
# DV01 = Modified Duration * Price * 0.0001
|
|
514
|
+
return mod_dur * price * 0.0001
|
|
515
|
+
|
|
516
|
+
def __repr__(self):
|
|
517
|
+
return f"BondDiscountEngine(valuation_date={self.pricing_env.valuation_date.date()})"
|