investing-algorithm-framework 8.7.3__tar.gz → 8.8.0__tar.gz

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 (308) hide show
  1. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/PKG-INFO +3 -2
  2. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/README.md +2 -1
  3. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/__init__.py +5 -1
  4. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/app.py +94 -0
  5. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/context.py +335 -13
  6. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/eventloop.py +89 -0
  7. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/backtest_report.py +23 -0
  8. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/templates/dashboard.js +52 -0
  9. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/dependency_container.py +7 -1
  10. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/__init__.py +7 -2
  11. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/backtest_metrics.py +23 -0
  12. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/exceptions.py +30 -0
  13. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/__init__.py +4 -1
  14. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/data/data_source.py +23 -0
  15. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/order/order.py +32 -0
  16. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/order/order_type.py +2 -0
  17. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/portfolio/__init__.py +3 -0
  18. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +6 -0
  19. investing_algorithm_framework-8.8.0/investing_algorithm_framework/domain/models/portfolio/sync.py +111 -0
  20. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/data_providers/base_url.py +32 -2
  21. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/order/order.py +4 -0
  22. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/order_executors/ccxt_order_executor.py +38 -0
  23. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/repositories/repository.py +2 -1
  24. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/services/backtesting/vector_backtest_service.py +74 -2
  25. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/__init__.py +3 -1
  26. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/__init__.py +5 -3
  27. investing_algorithm_framework-8.8.0/investing_algorithm_framework/services/metrics/_returns_helper.py +70 -0
  28. investing_algorithm_framework-8.8.0/investing_algorithm_framework/services/metrics/cagr.py +81 -0
  29. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/drawdown.py +108 -1
  30. investing_algorithm_framework-8.8.0/investing_algorithm_framework/services/metrics/equity_curve.py +77 -0
  31. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/generate.py +12 -2
  32. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/mean_daily_return.py +19 -7
  33. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/returns.py +45 -16
  34. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/sharpe_ratio.py +4 -5
  35. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/standard_deviation.py +31 -55
  36. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/value_at_risk.py +14 -8
  37. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/volatility.py +16 -35
  38. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/order_service/order_backtest_service.py +31 -0
  39. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/order_service/order_service.py +69 -0
  40. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/portfolios/__init__.py +3 -1
  41. investing_algorithm_framework-8.8.0/investing_algorithm_framework/services/portfolios/broker_balance_tracker.py +330 -0
  42. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +63 -1
  43. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/pyproject.toml +1 -1
  44. investing_algorithm_framework-8.7.3/investing_algorithm_framework/services/metrics/cagr.py +0 -60
  45. investing_algorithm_framework-8.7.3/investing_algorithm_framework/services/metrics/equity_curve.py +0 -27
  46. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/LICENSE +0 -0
  47. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/analysis/__init__.py +0 -0
  48. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/analysis/backtest_data_ranges.py +0 -0
  49. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/analysis/markdown.py +0 -0
  50. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/analysis/ranking.py +0 -0
  51. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/__init__.py +0 -0
  52. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/algorithm/__init__.py +0 -0
  53. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/algorithm/algorithm.py +0 -0
  54. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/algorithm/algorithm_factory.py +0 -0
  55. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/app_hook.py +0 -0
  56. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/__init__.py +0 -0
  57. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/ascii.py +0 -0
  58. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/backtest_report_old.py +0 -0
  59. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/charts/__init__.py +0 -0
  60. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/charts/entry_exist_signals.py +0 -0
  61. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/charts/equity_curve.py +0 -0
  62. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/charts/equity_curve_drawdown.py +0 -0
  63. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/charts/line_chart.py +0 -0
  64. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/charts/monthly_returns_heatmap.py +0 -0
  65. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/charts/ohlcv_data_completeness.py +0 -0
  66. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/charts/rolling_sharp_ratio.py +0 -0
  67. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/charts/yearly_returns_barchart.py +0 -0
  68. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/generate.py +0 -0
  69. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/tables/__init__.py +0 -0
  70. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/tables/key_metrics_table.py +0 -0
  71. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/tables/stop_loss_table.py +0 -0
  72. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/tables/time_metrics_table.py +0 -0
  73. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/tables/trade_metrics_table.py +0 -0
  74. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/tables/trades_table.py +0 -0
  75. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/tables/utils.py +0 -0
  76. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/templates/dashboard.css +0 -0
  77. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/templates/dashboard_template.html.j2 +0 -0
  78. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/reporting/templates/report_template.html.j2 +0 -0
  79. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/stateless/__init__.py +0 -0
  80. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/stateless/action_handlers/__init__.py +0 -0
  81. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +0 -0
  82. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +0 -0
  83. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +0 -0
  84. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/stateless/exception_handler.py +0 -0
  85. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/strategy.py +0 -0
  86. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/task.py +0 -0
  87. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/web/__init__.py +0 -0
  88. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/web/controllers/__init__.py +0 -0
  89. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/web/controllers/orders.py +0 -0
  90. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/web/controllers/portfolio.py +0 -0
  91. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/web/controllers/positions.py +0 -0
  92. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/web/create_app.py +0 -0
  93. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/web/error_handler.py +0 -0
  94. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/web/responses.py +0 -0
  95. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/web/run_strategies.py +0 -0
  96. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/web/schemas/__init__.py +0 -0
  97. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/web/schemas/order.py +0 -0
  98. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/web/schemas/portfolio.py +0 -0
  99. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/web/schemas/position.py +0 -0
  100. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/app/web/setup_cors.py +0 -0
  101. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/__init__.py +0 -0
  102. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/cli.py +0 -0
  103. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/deploy_to_aws_lambda.py +0 -0
  104. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/deploy_to_azure_function.py +0 -0
  105. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/initialize_app.py +0 -0
  106. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/mcp_server.py +0 -0
  107. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/.gitignore.template +0 -0
  108. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/app.py.template +0 -0
  109. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +0 -0
  110. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/app_azure_function.py.template +0 -0
  111. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/app_web.py.template +0 -0
  112. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +0 -0
  113. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +0 -0
  114. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/aws_lambda_readme.md.template +0 -0
  115. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +0 -0
  116. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +0 -0
  117. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/azure_function_host.json.template +0 -0
  118. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +0 -0
  119. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +0 -0
  120. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/data_providers.py.template +0 -0
  121. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/env.example.template +0 -0
  122. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/env_azure_function.example.template +0 -0
  123. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/market_data_providers.py.template +0 -0
  124. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/readme.md.template +0 -0
  125. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/requirements.txt.template +0 -0
  126. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/run_backtest.py.template +0 -0
  127. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/templates/strategy.py.template +0 -0
  128. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/cli/validate_backtest_checkpoints.py +0 -0
  129. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/create_app.py +0 -0
  130. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/algorithm_id.py +0 -0
  131. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/__init__.py +0 -0
  132. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/backtest.py +0 -0
  133. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/backtest_date_range.py +0 -0
  134. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +0 -0
  135. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +0 -0
  136. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/backtest_run.py +0 -0
  137. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +0 -0
  138. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/backtest_utils.py +0 -0
  139. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/bundle.py +0 -0
  140. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/combine_backtests.py +0 -0
  141. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/consistency.py +0 -0
  142. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/templates/backtest.html +0 -0
  143. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/templates/finterion-dark.png +0 -0
  144. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/backtesting/templates/finterion-light.png +0 -0
  145. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/blotter.py +0 -0
  146. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/config.py +0 -0
  147. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/constants.py +0 -0
  148. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/data_provider.py +0 -0
  149. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/data_structures.py +0 -0
  150. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/datetime_parsing.py +0 -0
  151. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/decimal_parsing.py +0 -0
  152. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/fx.py +0 -0
  153. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/app_mode.py +0 -0
  154. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/base_model.py +0 -0
  155. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/data/__init__.py +0 -0
  156. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/data/data_type.py +0 -0
  157. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/event.py +0 -0
  158. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/market/__init__.py +0 -0
  159. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/market/market_credential.py +0 -0
  160. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/order/__init__.py +0 -0
  161. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/order/order_side.py +0 -0
  162. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/order/order_status.py +0 -0
  163. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/portfolio/portfolio.py +0 -0
  164. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +0 -0
  165. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/position/__init__.py +0 -0
  166. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/position/position.py +0 -0
  167. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/position/position_size.py +0 -0
  168. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/position/position_snapshot.py +0 -0
  169. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/risk_rules/__init__.py +0 -0
  170. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/risk_rules/scaling_rule.py +0 -0
  171. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/risk_rules/stop_loss_rule.py +0 -0
  172. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/risk_rules/take_profit_rule.py +0 -0
  173. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/risk_rules/trading_cost.py +0 -0
  174. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/snapshot_interval.py +0 -0
  175. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/strategy_profile.py +0 -0
  176. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/time_frame.py +0 -0
  177. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/time_interval.py +0 -0
  178. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/time_unit.py +0 -0
  179. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/tracing/__init__.py +0 -0
  180. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/tracing/trace.py +0 -0
  181. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/trade/__init__.py +0 -0
  182. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/trade/trade.py +0 -0
  183. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/trade/trade_status.py +0 -0
  184. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +0 -0
  185. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/models/trade/trade_take_profit.py +0 -0
  186. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/order_executor.py +0 -0
  187. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/pipeline/__init__.py +0 -0
  188. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/pipeline/custom_factor.py +0 -0
  189. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/pipeline/factor.py +0 -0
  190. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/pipeline/factors/__init__.py +0 -0
  191. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/pipeline/factors/builtin.py +0 -0
  192. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/pipeline/filter.py +0 -0
  193. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/pipeline/pipeline.py +0 -0
  194. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/portfolio_provider.py +0 -0
  195. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/services/__init__.py +0 -0
  196. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/services/market_credential_service.py +0 -0
  197. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/services/portfolios/__init__.py +0 -0
  198. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +0 -0
  199. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/services/rounding_service.py +0 -0
  200. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/services/state_handler.py +0 -0
  201. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/stateless_actions.py +0 -0
  202. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/strategy.py +0 -0
  203. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/utils/__init__.py +0 -0
  204. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/utils/csv.py +0 -0
  205. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/utils/custom_tqdm.py +0 -0
  206. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/utils/dates.py +0 -0
  207. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +0 -0
  208. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/utils/polars.py +0 -0
  209. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/utils/random.py +0 -0
  210. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/utils/signatures.py +0 -0
  211. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/utils/stoppable_thread.py +0 -0
  212. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/domain/utils/synchronized.py +0 -0
  213. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/download_data.py +0 -0
  214. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/__init__.py +0 -0
  215. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/data_providers/__init__.py +0 -0
  216. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/data_providers/alpha_vantage.py +0 -0
  217. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/data_providers/ccxt.py +0 -0
  218. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/data_providers/csv.py +0 -0
  219. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/data_providers/csv_url.py +0 -0
  220. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/data_providers/json_url.py +0 -0
  221. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/data_providers/ohlcv_base.py +0 -0
  222. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/data_providers/pandas.py +0 -0
  223. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/data_providers/parquet_url.py +0 -0
  224. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/data_providers/polygon.py +0 -0
  225. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/data_providers/yahoo.py +0 -0
  226. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/database/__init__.py +0 -0
  227. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/database/sql_alchemy.py +0 -0
  228. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/__init__.py +0 -0
  229. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/decimal_parser.py +0 -0
  230. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/model_extension.py +0 -0
  231. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/order/__init__.py +0 -0
  232. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/order/trade_allocation.py +0 -0
  233. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/order_trade_association.py +0 -0
  234. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +0 -0
  235. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +0 -0
  236. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/portfolio/sql_portfolio.py +0 -0
  237. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/position/__init__.py +0 -0
  238. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/position/position.py +0 -0
  239. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +0 -0
  240. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/trades/__init__.py +0 -0
  241. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/trades/trade.py +0 -0
  242. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +0 -0
  243. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +0 -0
  244. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/order_executors/__init__.py +0 -0
  245. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/portfolio_providers/__init__.py +0 -0
  246. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/portfolio_providers/ccxt_portfolio_provider.py +0 -0
  247. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/repositories/__init__.py +0 -0
  248. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/repositories/order_repository.py +0 -0
  249. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +0 -0
  250. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +0 -0
  251. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/repositories/position_repository.py +0 -0
  252. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +0 -0
  253. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/repositories/trade_allocation_repository.py +0 -0
  254. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/repositories/trade_repository.py +0 -0
  255. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +0 -0
  256. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +0 -0
  257. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/services/__init__.py +0 -0
  258. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/services/aws/__init__.py +0 -0
  259. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/services/aws/state_handler.py +0 -0
  260. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/services/azure/__init__.py +0 -0
  261. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/services/azure/state_handler.py +0 -0
  262. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/services/backtesting/__init__.py +0 -0
  263. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/services/backtesting/backtest_service.py +0 -0
  264. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/services/backtesting/checkpoint_manifest.py +0 -0
  265. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/infrastructure/services/backtesting/event_backtest_service.py +0 -0
  266. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/notebook/__init__.py +0 -0
  267. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/notebook/magic.py +0 -0
  268. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/configuration_service.py +0 -0
  269. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/data_providers/__init__.py +0 -0
  270. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/data_providers/data.py +0 -0
  271. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/data_providers/data_provider_service.py +0 -0
  272. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/market_credential_service.py +0 -0
  273. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/alpha.py +0 -0
  274. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/beta.py +0 -0
  275. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/calmar_ratio.py +0 -0
  276. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/consistency.py +0 -0
  277. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/exposure.py +0 -0
  278. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/price_efficiency.py +0 -0
  279. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/profit_factor.py +0 -0
  280. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/recovery.py +0 -0
  281. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/risk_free_rate.py +0 -0
  282. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/sortino_ratio.py +0 -0
  283. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/trades.py +0 -0
  284. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/treynor_ratio.py +0 -0
  285. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/ulcer.py +0 -0
  286. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/metrics/win_rate.py +0 -0
  287. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/order_service/__init__.py +0 -0
  288. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/order_service/order_executor_lookup.py +0 -0
  289. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/pipeline/__init__.py +0 -0
  290. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/pipeline/pipeline_engine.py +0 -0
  291. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/pipeline/vector_pipeline_engine.py +0 -0
  292. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +0 -0
  293. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/portfolios/portfolio_configuration_service.py +0 -0
  294. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +0 -0
  295. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/portfolios/portfolio_service.py +0 -0
  296. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +0 -0
  297. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +0 -0
  298. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/positions/__init__.py +0 -0
  299. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/positions/position_service.py +0 -0
  300. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/positions/position_snapshot_service.py +0 -0
  301. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/repository_service.py +0 -0
  302. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/trade_order_evaluator/__init__.py +0 -0
  303. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +0 -0
  304. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +0 -0
  305. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/trade_service/__init__.py +0 -0
  306. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/trade_service/trade_service.py +0 -0
  307. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/trade_service/trade_stop_loss_service.py +0 -0
  308. {investing_algorithm_framework-8.7.3 → investing_algorithm_framework-8.8.0}/investing_algorithm_framework/services/trade_service/trade_take_profit_service.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: investing-algorithm-framework
3
- Version: 8.7.3
3
+ Version: 8.8.0
4
4
  Summary: A framework for creating trading bots
5
5
  Author: MDUYN
6
6
  Requires-Python: >=3.10,<4.0
@@ -129,7 +129,8 @@ This framework is built around the full loop: **create strategies → vector bac
129
129
  - 📄 **[One-Click HTML Report](https://coding-kitties.github.io/investing-algorithm-framework/Getting%20Started/backtest-reports)** — Self-contained file, no server, dark & light theme, shareable
130
130
  - 📦 **[Custom `.iafbt` Backtest Bundle Format](https://coding-kitties.github.io/investing-algorithm-framework/Data/backtest_data)** — An explicit, versioned, compressed, language-portable container (zstd + msgpack with magic-byte header) plus a separate parquet index for fast filtering without loading. ~21× smaller and ~27× fewer files than standard filebased directory layouts, with parallel I/O for fast load/save of large amounts of backtests.
131
131
  - 🌐 **[Load External Data](https://coding-kitties.github.io/investing-algorithm-framework/Data/external-data)** — Fetch CSV, JSON, or Parquet from any URL with caching and auto-refresh
132
- - 📝 **[Record Custom Variables](https://coding-kitties.github.io/investing-algorithm-framework/Advanced%20Concepts/recording-variables)** — Track any indicator or metric during backtests with `context.record()`
132
+ - � **[Per-Market Deposit Schedules & Portfolio Sync](https://coding-kitties.github.io/investing-algorithm-framework/Advanced%20Concepts/portfolio-sync)** — Declare recurring or one-shot external cash flows on a market with `deposit_schedule=` / `auto_sync=True`. Backtests simulate the deposits; live mode reconciles with the broker — same `context.sync_portfolio()` API in both modes.
133
+ - �📝 **[Record Custom Variables](https://coding-kitties.github.io/investing-algorithm-framework/Advanced%20Concepts/recording-variables)** — Track any indicator or metric during backtests with `context.record()`
133
134
  - 🚀 **[Build → Backtest → Deploy](https://coding-kitties.github.io/investing-algorithm-framework/Getting%20Started/application-setup)** — Local dev, cloud deploy (AWS / Azure), or monetize on Finterion
134
135
 
135
136
  </details>
@@ -85,7 +85,8 @@ This framework is built around the full loop: **create strategies → vector bac
85
85
  - 📄 **[One-Click HTML Report](https://coding-kitties.github.io/investing-algorithm-framework/Getting%20Started/backtest-reports)** — Self-contained file, no server, dark & light theme, shareable
86
86
  - 📦 **[Custom `.iafbt` Backtest Bundle Format](https://coding-kitties.github.io/investing-algorithm-framework/Data/backtest_data)** — An explicit, versioned, compressed, language-portable container (zstd + msgpack with magic-byte header) plus a separate parquet index for fast filtering without loading. ~21× smaller and ~27× fewer files than standard filebased directory layouts, with parallel I/O for fast load/save of large amounts of backtests.
87
87
  - 🌐 **[Load External Data](https://coding-kitties.github.io/investing-algorithm-framework/Data/external-data)** — Fetch CSV, JSON, or Parquet from any URL with caching and auto-refresh
88
- - 📝 **[Record Custom Variables](https://coding-kitties.github.io/investing-algorithm-framework/Advanced%20Concepts/recording-variables)** — Track any indicator or metric during backtests with `context.record()`
88
+ - � **[Per-Market Deposit Schedules & Portfolio Sync](https://coding-kitties.github.io/investing-algorithm-framework/Advanced%20Concepts/portfolio-sync)** — Declare recurring or one-shot external cash flows on a market with `deposit_schedule=` / `auto_sync=True`. Backtests simulate the deposits; live mode reconciles with the broker — same `context.sync_portfolio()` API in both modes.
89
+ - �📝 **[Record Custom Variables](https://coding-kitties.github.io/investing-algorithm-framework/Advanced%20Concepts/recording-variables)** — Track any indicator or metric during backtests with `context.record()`
89
90
  - 🚀 **[Build → Backtest → Deploy](https://coding-kitties.github.io/investing-algorithm-framework/Getting%20Started/application-setup)** — Local dev, cloud deploy (AWS / Azure), or monetize on Finterion
90
91
 
91
92
  </details>
@@ -35,7 +35,8 @@ from .domain import ApiException, combine_backtests, PositionSize, \
35
35
  Pipeline, Factor, CustomFactor, Filter, \
36
36
  Returns, AverageDollarVolume, AverageTradedValue, SMA, RSI, \
37
37
  Volatility, StaticPerSymbol, CrossSectionalMean, RollingBeta, \
38
- Neutralize
38
+ Neutralize, \
39
+ SyncResult, ScheduledDeposit, PortfolioOutOfSyncError
39
40
  from .infrastructure import AzureBlobStorageStateHandler, \
40
41
  CSVOHLCVDataProvider, CSVTickerDataProvider, CSVURLDataProvider, \
41
42
  JSONURLDataProvider, ParquetURLDataProvider, \
@@ -285,6 +286,9 @@ __all__ = [
285
286
  "get_normalized_stability",
286
287
  "get_consistency_score",
287
288
  "get_stability_score",
289
+ "SyncResult",
290
+ "ScheduledDeposit",
291
+ "PortfolioOutOfSyncError",
288
292
  ]
289
293
 
290
294
 
@@ -2242,6 +2242,9 @@ class App:
2242
2242
  initial_balance=None,
2243
2243
  fee_percentage=0.0,
2244
2244
  slippage_percentage=0.0,
2245
+ deposit_schedule=None,
2246
+ auto_sync=False,
2247
+ auto_sync_error_mode="raise",
2245
2248
  ):
2246
2249
  """
2247
2250
  Function to add a market to the app. This function is a utility
@@ -2260,10 +2263,28 @@ class App:
2260
2263
  slippage_percentage: Default slippage percentage for all
2261
2264
  trades on this market (e.g. 0.05 for 0.05%). Can be
2262
2265
  overridden per-symbol via TradingCost on the strategy.
2266
+ deposit_schedule: Optional list of
2267
+ :class:`ScheduledDeposit` describing simulated external
2268
+ cash flows landing on this market during a backtest
2269
+ (e.g. monthly paychecks). Ignored in live mode — for
2270
+ live deployments the broker is the source of truth and
2271
+ ``Context.sync_portfolio()`` queries it directly.
2272
+ auto_sync: When ``True``, the framework automatically calls
2273
+ ``Context.sync_portfolio(market=market)`` before every
2274
+ strategy iteration so deposits/withdrawals are absorbed
2275
+ without strategy code having to opt in. Defaults to
2276
+ ``False`` (explicit opt-in via ``context.sync_portfolio()``).
2277
+ auto_sync_error_mode: How auto-sync handles failures. One of
2278
+ ``"raise"`` (loud, default — best for development),
2279
+ ``"warn"`` (log and continue with stale state — best for
2280
+ live trading where transient broker glitches should not
2281
+ crash the bot), or ``"halt"`` (log, disable auto-sync
2282
+ for this market, and continue).
2263
2283
 
2264
2284
  Returns:
2265
2285
  None
2266
2286
  """
2287
+ deposit_schedule = self._normalize_deposit_schedule(deposit_schedule)
2267
2288
 
2268
2289
  portfolio_configuration = PortfolioConfiguration(
2269
2290
  market=market,
@@ -2271,6 +2292,7 @@ class App:
2271
2292
  initial_balance=initial_balance,
2272
2293
  fee_percentage=fee_percentage,
2273
2294
  slippage_percentage=slippage_percentage,
2295
+ deposit_schedule=deposit_schedule,
2274
2296
  )
2275
2297
 
2276
2298
  self.add_portfolio_configuration(portfolio_configuration)
@@ -2281,6 +2303,78 @@ class App:
2281
2303
  )
2282
2304
  self.add_market_credential(market_credential)
2283
2305
 
2306
+ tracker = self.container.broker_balance_tracker()
2307
+ if deposit_schedule:
2308
+ tracker.set_schedule(market, deposit_schedule)
2309
+ if auto_sync:
2310
+ tracker.set_auto_sync(market, True)
2311
+ tracker.set_auto_sync_error_mode(market, auto_sync_error_mode)
2312
+
2313
+ @staticmethod
2314
+ def _normalize_deposit_schedule(deposit_schedule):
2315
+ """Coerce a deposit_schedule argument to a validated list.
2316
+
2317
+ Accepts ``None`` (treated as no schedule), a list/tuple of
2318
+ :class:`ScheduledDeposit`, or rejects anything else with a clear
2319
+ error. Notably rejects passing a single ``ScheduledDeposit``
2320
+ directly (which would be iterable over its dataclass fields and
2321
+ produce nonsense).
2322
+ """
2323
+ from investing_algorithm_framework.domain import ScheduledDeposit
2324
+ if deposit_schedule is None:
2325
+ return []
2326
+ if isinstance(deposit_schedule, ScheduledDeposit):
2327
+ raise OperationalException(
2328
+ "deposit_schedule must be a list of ScheduledDeposit, not a "
2329
+ "single ScheduledDeposit. Wrap it: [ScheduledDeposit(...)]."
2330
+ )
2331
+ if not isinstance(deposit_schedule, (list, tuple)):
2332
+ raise OperationalException(
2333
+ "deposit_schedule must be a list of ScheduledDeposit, got "
2334
+ f"{type(deposit_schedule).__name__}."
2335
+ )
2336
+ for entry in deposit_schedule:
2337
+ if not isinstance(entry, ScheduledDeposit):
2338
+ raise OperationalException(
2339
+ "deposit_schedule entries must be ScheduledDeposit, "
2340
+ f"got {type(entry).__name__}."
2341
+ )
2342
+ return list(deposit_schedule)
2343
+
2344
+ def add_deposit_schedule(self, market, schedule):
2345
+ """Register simulated external deposits for a backtested market.
2346
+
2347
+ Equivalent to passing ``deposit_schedule=`` to :meth:`add_market`,
2348
+ but usable after the market has already been registered. Replaces
2349
+ any previously registered schedule for this market.
2350
+
2351
+ Args:
2352
+ market: Market identifier.
2353
+ schedule: Iterable of :class:`ScheduledDeposit`.
2354
+
2355
+ Returns:
2356
+ None
2357
+ """
2358
+ self.container.broker_balance_tracker().set_schedule(
2359
+ market, self._normalize_deposit_schedule(schedule)
2360
+ )
2361
+
2362
+ def set_market_auto_sync(self, market, enabled=True):
2363
+ """Toggle automatic ``sync_portfolio`` before each strategy iteration.
2364
+
2365
+ Args:
2366
+ market: Market identifier.
2367
+ enabled: When ``True`` (the default), the framework calls
2368
+ ``Context.sync_portfolio(market=market)`` immediately before
2369
+ each strategy ``run_strategy`` invocation.
2370
+
2371
+ Returns:
2372
+ None
2373
+ """
2374
+ self.container.broker_balance_tracker().set_auto_sync(
2375
+ market, enabled
2376
+ )
2377
+
2284
2378
  def set_blotter(self, blotter):
2285
2379
  """
2286
2380
  Set a blotter for order book management. The blotter sits
@@ -5,12 +5,16 @@ from typing import List
5
5
  from investing_algorithm_framework.services import ConfigurationService, \
6
6
  MarketCredentialService, OrderService, PortfolioConfigurationService, \
7
7
  PortfolioService, PositionService, TradeService, DataProviderService, \
8
- TradeStopLossService, TradeTakeProfitService
8
+ TradeStopLossService, TradeTakeProfitService, BrokerBalanceTracker
9
+ from investing_algorithm_framework.services.portfolios import (
10
+ PortfolioProviderLookup,
11
+ )
9
12
  from investing_algorithm_framework.domain import OrderStatus, OrderType, \
10
13
  OrderSide, OperationalException, Portfolio, RoundingService, \
11
14
  BACKTESTING_FLAG, INDEX_DATETIME, Order, \
12
15
  Position, Trade, TradeStatus, MarketCredential, TradeStopLoss, \
13
- TradeTakeProfit
16
+ TradeTakeProfit, SyncResult, PortfolioOutOfSyncError, Environment, \
17
+ ENVIRONMENT
14
18
 
15
19
  logger = logging.getLogger("investing_algorithm_framework")
16
20
 
@@ -33,7 +37,9 @@ class Context:
33
37
  trade_service: TradeService,
34
38
  trade_stop_loss_service: TradeStopLossService,
35
39
  trade_take_profit_service: TradeTakeProfitService,
36
- data_provider_service: DataProviderService
40
+ data_provider_service: DataProviderService,
41
+ portfolio_provider_lookup: PortfolioProviderLookup = None,
42
+ broker_balance_tracker: BrokerBalanceTracker = None,
37
43
  ):
38
44
  self.configuration_service: ConfigurationService = \
39
45
  configuration_service
@@ -50,6 +56,10 @@ class Context:
50
56
  trade_stop_loss_service
51
57
  self.trade_take_profit_service: TradeTakeProfitService = \
52
58
  trade_take_profit_service
59
+ self.portfolio_provider_lookup: PortfolioProviderLookup = \
60
+ portfolio_provider_lookup
61
+ self.broker_balance_tracker: BrokerBalanceTracker = \
62
+ broker_balance_tracker
53
63
  self._blotter = None
54
64
  self._fx_rate_provider = None
55
65
  self._base_currency = None
@@ -134,7 +144,8 @@ class Context:
134
144
  execute=True,
135
145
  validate=True,
136
146
  sync=True,
137
- validate_symbol=False
147
+ validate_symbol=False,
148
+ stop_price=None,
138
149
  ) -> Order:
139
150
  """
140
151
  Function to create an order. This function will create an order
@@ -154,6 +165,8 @@ class Context:
154
165
  with the portfolio of the algorithm.
155
166
  validate_symbol: Default False. If set to True,
156
167
  validates that target_symbol is not the trading_symbol.
168
+ stop_price: Required for STOP and STOP_LIMIT order types.
169
+ The trigger price at which the order activates.
157
170
 
158
171
  Returns:
159
172
  The order created
@@ -173,6 +186,9 @@ class Context:
173
186
  "trading_symbol": portfolio.trading_symbol,
174
187
  }
175
188
 
189
+ if stop_price is not None:
190
+ order_data["stop_price"] = stop_price
191
+
176
192
  if BACKTESTING_FLAG in self.configuration_service.config \
177
193
  and self.configuration_service.config[BACKTESTING_FLAG]:
178
194
  order_data["created_at"] = \
@@ -884,6 +900,280 @@ class Context:
884
900
  {"portfolio": portfolio.id, "symbol": trading_symbol}
885
901
  ).get_amount()
886
902
 
903
+ def sync_portfolio(
904
+ self,
905
+ market: str = None,
906
+ allow_withdrawals: bool = False,
907
+ tolerance: float = 1e-9,
908
+ ) -> SyncResult:
909
+ """Reconcile the local portfolio's unallocated balance with the broker.
910
+
911
+ This is the **canonical entry point** for "make my strategy aware of
912
+ cash that arrived (or left) my account out-of-band". The contract is
913
+ identical across live and backtest modes:
914
+
915
+ 1. Ask the broker (live: registered :class:`PortfolioProvider`;
916
+ backtest: simulated :class:`BrokerBalanceTracker`) what the
917
+ trading-symbol balance currently is.
918
+ 2. In live mode, subtract cash reserved for orders the framework
919
+ knows about but the exchange has not yet acknowledged
920
+ (``OrderStatus.CREATED``). Without this, the natural race
921
+ between local order creation and exchange acknowledgement
922
+ would surface as a phantom "deposit".
923
+ 3. Compute ``delta = adjusted_broker_available - local_unallocated``.
924
+ 4. ``abs(delta) <= tolerance`` → no-op.
925
+ 5. ``delta > 0`` → an external deposit landed; absorb it by topping
926
+ up ``unallocated``.
927
+ 6. ``delta < 0`` → the broker reports *less* than the framework
928
+ expected (an external withdrawal, an out-of-band fill, an
929
+ unrecorded fee, …). By default this raises
930
+ :class:`PortfolioOutOfSyncError` because silently shrinking
931
+ the strategy's working capital is almost always the wrong
932
+ thing to do. Pass ``allow_withdrawals=True`` to explicitly
933
+ accept the drain.
934
+
935
+ The absorbed cash flow is recorded on the
936
+ :class:`BrokerBalanceTracker` so the snapshot service can attach
937
+ it to the next portfolio snapshot's ``cash_flow`` field, which in
938
+ turn lets return metrics (CAGR, monthly/yearly returns) compute
939
+ true time-weighted returns instead of being inflated by deposits.
940
+
941
+ Args:
942
+ market: Market identifier. Defaults to the first registered
943
+ portfolio. Case-insensitive.
944
+ allow_withdrawals: When ``True``, negative deltas drain
945
+ ``unallocated`` instead of raising. The drain is still
946
+ refused if it would push ``unallocated`` below zero.
947
+ tolerance: Absolute drift below which the sync is treated as
948
+ a noop. Defaults to ``1e-9`` to swallow floating-point
949
+ dust. Useful to bump (e.g. ``1.0``) for live mode if
950
+ small fee/rounding glitches keep tripping the check.
951
+
952
+ Returns:
953
+ :class:`SyncResult` describing the outcome.
954
+
955
+ Raises:
956
+ PortfolioOutOfSyncError: On negative delta when
957
+ ``allow_withdrawals=False``, or when the resulting
958
+ ``unallocated`` would be negative.
959
+ OperationalException: When live mode is configured but no
960
+ :class:`PortfolioProvider` / :class:`MarketCredential`
961
+ is registered for the market.
962
+ """
963
+ if tolerance < 0:
964
+ raise OperationalException(
965
+ f"sync_portfolio: tolerance must be non-negative, got "
966
+ f"{tolerance}."
967
+ )
968
+ portfolio = self._resolve_portfolio_for_sync(market)
969
+ market_id = portfolio.market
970
+ previous_unallocated = float(portfolio.get_unallocated() or 0.0)
971
+
972
+ broker_available, reserved = self._fetch_broker_available(
973
+ portfolio, previous_unallocated
974
+ )
975
+
976
+ delta = broker_available - previous_unallocated
977
+
978
+ if abs(delta) <= tolerance:
979
+ return SyncResult(
980
+ market=market_id,
981
+ kind="noop",
982
+ delta=delta,
983
+ broker_available=broker_available,
984
+ previous_unallocated=previous_unallocated,
985
+ new_unallocated=previous_unallocated,
986
+ within_tolerance=delta != 0,
987
+ reserved_for_pending_orders=reserved,
988
+ )
989
+
990
+ if delta < 0 and not allow_withdrawals:
991
+ raise PortfolioOutOfSyncError(
992
+ f"Portfolio out of sync on market '{market_id}': local "
993
+ f"unallocated {previous_unallocated} > broker available "
994
+ f"{broker_available} (delta {delta}, "
995
+ f"{reserved} reserved for pending orders). This usually "
996
+ f"means an external withdrawal happened, an order filled "
997
+ f"out-of-band, or fees were charged the framework did not "
998
+ f"see. Pass allow_withdrawals=True to drain unallocated, "
999
+ f"or investigate the broker account.",
1000
+ market=market_id,
1001
+ local_unallocated=previous_unallocated,
1002
+ broker_available=broker_available,
1003
+ delta=delta,
1004
+ )
1005
+
1006
+ new_unallocated = broker_available
1007
+ if new_unallocated < 0:
1008
+ raise PortfolioOutOfSyncError(
1009
+ f"Refusing to set unallocated to a negative value on market "
1010
+ f"'{market_id}': broker reports {broker_available}, which is "
1011
+ f"below zero. Investigate the broker account.",
1012
+ market=market_id,
1013
+ local_unallocated=previous_unallocated,
1014
+ broker_available=broker_available,
1015
+ delta=delta,
1016
+ )
1017
+
1018
+ kind = "deposit" if delta > 0 else "withdrawal"
1019
+ self._apply_unallocated_change(portfolio, new_unallocated)
1020
+
1021
+ # Record the cash flow so the next portfolio snapshot gets a
1022
+ # non-zero ``cash_flow`` and TWR-aware metrics work correctly.
1023
+ if self.broker_balance_tracker is not None:
1024
+ self.broker_balance_tracker.record_cash_flow(market_id, delta)
1025
+
1026
+ logger.info(
1027
+ "sync_portfolio[%s] %s: local %.6f -> %.6f (broker reports %.6f, "
1028
+ "delta %+.6f, reserved %.6f)",
1029
+ market_id, kind, previous_unallocated, new_unallocated,
1030
+ broker_available, delta, reserved,
1031
+ )
1032
+
1033
+ return SyncResult(
1034
+ market=market_id,
1035
+ kind=kind,
1036
+ delta=delta,
1037
+ broker_available=broker_available,
1038
+ previous_unallocated=previous_unallocated,
1039
+ new_unallocated=new_unallocated,
1040
+ within_tolerance=False,
1041
+ reserved_for_pending_orders=reserved,
1042
+ )
1043
+
1044
+ def _resolve_portfolio_for_sync(self, market) -> Portfolio:
1045
+ if market is not None:
1046
+ # Portfolio.market is canonically uppercased on creation; match
1047
+ # case-insensitively so users can pass "binance" or "BINANCE".
1048
+ normalized = str(market).upper()
1049
+ portfolio = self.portfolio_service.find({"market": normalized})
1050
+ if portfolio is None:
1051
+ portfolio = self.portfolio_service.find({"market": market})
1052
+ else:
1053
+ portfolios = self.portfolio_service.get_all()
1054
+ if not portfolios:
1055
+ raise OperationalException(
1056
+ "sync_portfolio: no portfolio registered. "
1057
+ "Did you call app.add_market(...)?"
1058
+ )
1059
+ portfolio = portfolios[0]
1060
+ if portfolio is None:
1061
+ raise OperationalException(
1062
+ f"sync_portfolio: no portfolio found for market '{market}'."
1063
+ )
1064
+ return portfolio
1065
+
1066
+ def _fetch_broker_available(
1067
+ self, portfolio: Portfolio, previous_unallocated: float
1068
+ ) -> tuple:
1069
+ """Returns (broker_available, reserved_for_pending_orders)."""
1070
+ config = self.configuration_service.get_config()
1071
+ environment = config.get(ENVIRONMENT)
1072
+
1073
+ is_backtest = environment in (
1074
+ Environment.BACKTEST.value,
1075
+ Environment.BACKTEST,
1076
+ )
1077
+
1078
+ if is_backtest:
1079
+ if self.broker_balance_tracker is None:
1080
+ # No tracker wired (legacy app construction); deposits cannot
1081
+ # be simulated → broker == local.
1082
+ return previous_unallocated, 0.0
1083
+ pending = self.broker_balance_tracker.consume_pending(
1084
+ portfolio.market
1085
+ )
1086
+ return previous_unallocated + pending, 0.0
1087
+
1088
+ # Live mode
1089
+ if self.portfolio_provider_lookup is None:
1090
+ raise OperationalException(
1091
+ "sync_portfolio: no PortfolioProviderLookup wired into the "
1092
+ "context. This usually means the app was constructed without "
1093
+ "the standard dependency container."
1094
+ )
1095
+ market_credential = self.market_credential_service.get(
1096
+ portfolio.market
1097
+ )
1098
+ if market_credential is None:
1099
+ raise OperationalException(
1100
+ f"sync_portfolio: no market credential registered for "
1101
+ f"market '{portfolio.market}'. Live broker reconciliation "
1102
+ f"requires API credentials."
1103
+ )
1104
+ provider = self.portfolio_provider_lookup.get_portfolio_provider(
1105
+ portfolio.market
1106
+ )
1107
+ if provider is None:
1108
+ raise OperationalException(
1109
+ f"sync_portfolio: no PortfolioProvider registered for market "
1110
+ f"'{portfolio.market}'."
1111
+ )
1112
+ position = provider.get_position(
1113
+ portfolio, portfolio.trading_symbol, market_credential
1114
+ )
1115
+ raw = float(position.amount) if position is not None else 0.0
1116
+
1117
+ # Subtract cash reserved for orders the framework has issued but
1118
+ # the exchange has not yet acknowledged. ``free`` from the broker
1119
+ # already excludes acknowledged open orders, but not those in
1120
+ # CREATED state — without this adjustment a brief race window
1121
+ # between create_order() and the exchange ack would surface as a
1122
+ # phantom "deposit" of the order's cost.
1123
+ reserved = self._reserved_cash_for_pending_orders(portfolio)
1124
+ return raw - reserved, reserved
1125
+
1126
+ def _reserved_cash_for_pending_orders(
1127
+ self, portfolio: Portfolio
1128
+ ) -> float:
1129
+ """Sum of trading-symbol cash locked by orders the framework has
1130
+ created but the exchange has not yet filled or cancelled.
1131
+
1132
+ Buys consume cash; sells release it. Only ``CREATED`` orders are
1133
+ counted because the broker's ``free`` balance already excludes
1134
+ acknowledged open orders.
1135
+ """
1136
+ try:
1137
+ created_orders = self.order_service.get_all({
1138
+ "portfolio_id": portfolio.id,
1139
+ "status": OrderStatus.CREATED.value,
1140
+ })
1141
+ except Exception: # noqa: BLE001
1142
+ return 0.0
1143
+ reserved = 0.0
1144
+ for order in created_orders or []:
1145
+ try:
1146
+ price = float(order.get_price() or 0.0)
1147
+ amount = float(
1148
+ order.get_remaining() or order.get_amount() or 0.0
1149
+ )
1150
+ except Exception: # noqa: BLE001
1151
+ continue
1152
+ if OrderSide.BUY.equals(order.get_order_side()):
1153
+ reserved += price * amount
1154
+ # Sells release cash on fill; not counted here.
1155
+ return reserved
1156
+
1157
+ def _apply_unallocated_change(
1158
+ self, portfolio: Portfolio, new_unallocated: float
1159
+ ) -> None:
1160
+ self.portfolio_service.update(
1161
+ portfolio.id, {"unallocated": new_unallocated}
1162
+ )
1163
+ # Keep the trading-symbol position in lockstep, mirroring the
1164
+ # behaviour of PortfolioSyncService.sync_unallocated().
1165
+ try:
1166
+ trading_position = self.position_service.find({
1167
+ "portfolio": portfolio.id,
1168
+ "symbol": portfolio.trading_symbol,
1169
+ })
1170
+ except Exception: # noqa: BLE001 — repository raises on miss
1171
+ trading_position = None
1172
+ if trading_position is not None:
1173
+ self.position_service.update(
1174
+ trading_position.id, {"amount": new_unallocated}
1175
+ )
1176
+
887
1177
  def get_total_size(self):
888
1178
  """
889
1179
  Returns the total size of the portfolio.
@@ -2092,6 +2382,14 @@ class Context:
2092
2382
 
2093
2383
  return self.trade_stop_loss_service.get_all(query_params)
2094
2384
 
2385
+ def _get_url_provider_cache_key(self, url, headers):
2386
+ # Delegates to the canonical helper so the in-memory provider
2387
+ # dict and the on-disk cache filename stay in lockstep — see
2388
+ # ``url_cache_key`` for rationale.
2389
+ from investing_algorithm_framework.infrastructure \
2390
+ .data_providers.base_url import url_cache_key
2391
+ return url_cache_key(url, headers)
2392
+
2095
2393
  def fetch_csv(
2096
2394
  self,
2097
2395
  url,
@@ -2099,6 +2397,7 @@ class Context:
2099
2397
  date_format=None,
2100
2398
  cache=True,
2101
2399
  refresh_interval=None,
2400
+ headers=None,
2102
2401
  pre_process=None,
2103
2402
  post_process=None,
2104
2403
  ):
@@ -2118,6 +2417,10 @@ class Context:
2118
2417
  cache (bool): Cache fetched data locally (default: True).
2119
2418
  refresh_interval (str, optional): Re-fetch interval
2120
2419
  (e.g., "1d", "1h").
2420
+ headers (dict, optional): HTTP headers to send with the
2421
+ request. Header values are redacted (replaced
2422
+ with "***") in ``DataSource.to_dict``, so
2423
+ secrets do not leak into diagnostic payloads.
2121
2424
  pre_process (callable, optional): Transform raw CSV text
2122
2425
  before parsing.
2123
2426
  post_process (callable, optional): Transform the parsed
@@ -2141,20 +2444,23 @@ class Context:
2141
2444
  if not hasattr(self, '_csv_url_providers'):
2142
2445
  self._csv_url_providers = {}
2143
2446
 
2144
- if url not in self._csv_url_providers:
2447
+ provider_key = self._get_url_provider_cache_key(url, headers)
2448
+
2449
+ if provider_key not in self._csv_url_providers:
2145
2450
  provider = CSVURLDataProvider(
2146
2451
  url=url,
2147
2452
  date_column=date_column,
2148
2453
  date_format=date_format,
2149
2454
  cache=cache,
2150
2455
  refresh_interval=refresh_interval,
2456
+ headers=headers,
2151
2457
  pre_process=pre_process,
2152
2458
  post_process=post_process,
2153
2459
  )
2154
2460
  provider.config = self.configuration_service.get_config()
2155
- self._csv_url_providers[url] = provider
2461
+ self._csv_url_providers[provider_key] = provider
2156
2462
 
2157
- return self._csv_url_providers[url].get_data()
2463
+ return self._csv_url_providers[provider_key].get_data()
2158
2464
 
2159
2465
  def fetch_json(
2160
2466
  self,
@@ -2163,6 +2469,7 @@ class Context:
2163
2469
  date_format=None,
2164
2470
  cache=True,
2165
2471
  refresh_interval=None,
2472
+ headers=None,
2166
2473
  pre_process=None,
2167
2474
  post_process=None,
2168
2475
  ):
@@ -2185,6 +2492,10 @@ class Context:
2185
2492
  cache (bool): Cache fetched data locally (default: True).
2186
2493
  refresh_interval (str, optional): Re-fetch interval
2187
2494
  (e.g., "1d", "1h").
2495
+ headers (dict, optional): HTTP headers to send with the
2496
+ request. Header values are redacted (replaced
2497
+ with "***") in ``DataSource.to_dict``, so
2498
+ secrets do not leak into diagnostic payloads.
2188
2499
  pre_process (callable, optional): Transform raw JSON text
2189
2500
  before parsing.
2190
2501
  post_process (callable, optional): Transform the parsed
@@ -2207,20 +2518,23 @@ class Context:
2207
2518
  if not hasattr(self, '_json_url_providers'):
2208
2519
  self._json_url_providers = {}
2209
2520
 
2210
- if url not in self._json_url_providers:
2521
+ provider_key = self._get_url_provider_cache_key(url, headers)
2522
+
2523
+ if provider_key not in self._json_url_providers:
2211
2524
  provider = JSONURLDataProvider(
2212
2525
  url=url,
2213
2526
  date_column=date_column,
2214
2527
  date_format=date_format,
2215
2528
  cache=cache,
2216
2529
  refresh_interval=refresh_interval,
2530
+ headers=headers,
2217
2531
  pre_process=pre_process,
2218
2532
  post_process=post_process,
2219
2533
  )
2220
2534
  provider.config = self.configuration_service.get_config()
2221
- self._json_url_providers[url] = provider
2535
+ self._json_url_providers[provider_key] = provider
2222
2536
 
2223
- return self._json_url_providers[url].get_data()
2537
+ return self._json_url_providers[provider_key].get_data()
2224
2538
 
2225
2539
  def fetch_parquet(
2226
2540
  self,
@@ -2229,6 +2543,7 @@ class Context:
2229
2543
  date_format=None,
2230
2544
  cache=True,
2231
2545
  refresh_interval=None,
2546
+ headers=None,
2232
2547
  post_process=None,
2233
2548
  ):
2234
2549
  """
@@ -2247,6 +2562,10 @@ class Context:
2247
2562
  cache (bool): Cache fetched data locally (default: True).
2248
2563
  refresh_interval (str, optional): Re-fetch interval
2249
2564
  (e.g., "1d", "1h").
2565
+ headers (dict, optional): HTTP headers to send with the
2566
+ request. Header values are redacted (replaced
2567
+ with "***") in ``DataSource.to_dict``, so
2568
+ secrets do not leak into diagnostic payloads.
2250
2569
  post_process (callable, optional): Transform the parsed
2251
2570
  DataFrame.
2252
2571
 
@@ -2266,19 +2585,22 @@ class Context:
2266
2585
  if not hasattr(self, '_parquet_url_providers'):
2267
2586
  self._parquet_url_providers = {}
2268
2587
 
2269
- if url not in self._parquet_url_providers:
2588
+ provider_key = self._get_url_provider_cache_key(url, headers)
2589
+
2590
+ if provider_key not in self._parquet_url_providers:
2270
2591
  provider = ParquetURLDataProvider(
2271
2592
  url=url,
2272
2593
  date_column=date_column,
2273
2594
  date_format=date_format,
2274
2595
  cache=cache,
2275
2596
  refresh_interval=refresh_interval,
2597
+ headers=headers,
2276
2598
  post_process=post_process,
2277
2599
  )
2278
2600
  provider.config = self.configuration_service.get_config()
2279
- self._parquet_url_providers[url] = provider
2601
+ self._parquet_url_providers[provider_key] = provider
2280
2602
 
2281
- return self._parquet_url_providers[url].get_data()
2603
+ return self._parquet_url_providers[provider_key].get_data()
2282
2604
 
2283
2605
  def batch_order(self, orders, market=None):
2284
2606
  """