investing-algorithm-framework 9.0.0a2__tar.gz → 9.0.0a3__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 (369) hide show
  1. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/PKG-INFO +10 -10
  2. investing_algorithm_framework-9.0.0a3/investing_algorithm_framework/app/algorithm_runner.py +236 -0
  3. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/app.py +111 -15
  4. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/eventloop.py +115 -26
  5. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/charts/__init__.py +0 -2
  6. investing_algorithm_framework-9.0.0a3/investing_algorithm_framework/app/reporting/charts/_finterion_render.py +71 -0
  7. investing_algorithm_framework-9.0.0a3/investing_algorithm_framework/app/reporting/charts/entry_exist_signals.py +54 -0
  8. investing_algorithm_framework-9.0.0a3/investing_algorithm_framework/app/reporting/charts/equity_curve.py +38 -0
  9. investing_algorithm_framework-9.0.0a3/investing_algorithm_framework/app/reporting/charts/equity_curve_drawdown.py +51 -0
  10. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/charts/monthly_returns_heatmap.py +15 -35
  11. investing_algorithm_framework-9.0.0a3/investing_algorithm_framework/app/reporting/charts/ohlcv_data_completeness.py +45 -0
  12. investing_algorithm_framework-9.0.0a3/investing_algorithm_framework/app/reporting/charts/rolling_sharp_ratio.py +49 -0
  13. investing_algorithm_framework-9.0.0a3/investing_algorithm_framework/app/reporting/charts/yearly_returns_barchart.py +40 -0
  14. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/controllers/__init__.py +6 -0
  15. investing_algorithm_framework-9.0.0a3/investing_algorithm_framework/app/web/controllers/algorithm.py +155 -0
  16. investing_algorithm_framework-9.0.0a3/investing_algorithm_framework/app/web/controllers/trades.py +28 -0
  17. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/schemas/__init__.py +3 -0
  18. investing_algorithm_framework-9.0.0a3/investing_algorithm_framework/app/web/schemas/trade.py +20 -0
  19. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/cli.py +9 -3
  20. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +23 -1
  21. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +43 -0
  22. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/strategy.py.template +43 -14
  23. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/dependency_container.py +5 -0
  24. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/data/data_source.py +12 -19
  25. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/data_providers/ccxt.py +315 -260
  26. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/data_providers/csv.py +8 -1
  27. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/data_providers/ohlcv_base.py +5 -2
  28. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/services/aws/state_handler.py +12 -2
  29. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/services/azure/state_handler.py +4 -1
  30. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/services/backtesting/backtest_service.py +8 -34
  31. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/services/backtesting/event_backtest_service.py +8 -31
  32. investing_algorithm_framework-9.0.0a3/investing_algorithm_framework/infrastructure/services/backtesting/schedule_generation.py +75 -0
  33. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/data_providers/data_provider_service.py +11 -5
  34. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +6 -3
  35. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +7 -2
  36. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +13 -8
  37. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/pyproject.toml +13 -12
  38. investing_algorithm_framework-9.0.0a2/investing_algorithm_framework/app/reporting/backtest_report_old.py +0 -352
  39. investing_algorithm_framework-9.0.0a2/investing_algorithm_framework/app/reporting/charts/entry_exist_signals.py +0 -66
  40. investing_algorithm_framework-9.0.0a2/investing_algorithm_framework/app/reporting/charts/equity_curve.py +0 -37
  41. investing_algorithm_framework-9.0.0a2/investing_algorithm_framework/app/reporting/charts/equity_curve_drawdown.py +0 -74
  42. investing_algorithm_framework-9.0.0a2/investing_algorithm_framework/app/reporting/charts/line_chart.py +0 -11
  43. investing_algorithm_framework-9.0.0a2/investing_algorithm_framework/app/reporting/charts/ohlcv_data_completeness.py +0 -51
  44. investing_algorithm_framework-9.0.0a2/investing_algorithm_framework/app/reporting/charts/rolling_sharp_ratio.py +0 -79
  45. investing_algorithm_framework-9.0.0a2/investing_algorithm_framework/app/reporting/charts/yearly_returns_barchart.py +0 -55
  46. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/LICENSE +0 -0
  47. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/README.md +0 -0
  48. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/__init__.py +0 -0
  49. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/analysis/__init__.py +0 -0
  50. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/analysis/backtest_data_ranges.py +0 -0
  51. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/analysis/backtest_window_analysis.py +0 -0
  52. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/analysis/bundle_inspection.py +0 -0
  53. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/analysis/markdown.py +0 -0
  54. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/analysis/ranking.py +0 -0
  55. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/analysis/robustness.py +0 -0
  56. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/analysis/top_selection.py +0 -0
  57. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/__init__.py +0 -0
  58. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/algorithm/__init__.py +0 -0
  59. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/algorithm/algorithm.py +0 -0
  60. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/algorithm/algorithm_factory.py +0 -0
  61. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/app_hook.py +0 -0
  62. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/context.py +0 -0
  63. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/__init__.py +0 -0
  64. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/ascii.py +0 -0
  65. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/backtest_report.py +0 -0
  66. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/generate.py +0 -0
  67. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/tables/__init__.py +0 -0
  68. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/tables/key_metrics_table.py +0 -0
  69. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/tables/stop_loss_table.py +0 -0
  70. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/tables/time_metrics_table.py +0 -0
  71. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/tables/trade_metrics_table.py +0 -0
  72. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/tables/trades_table.py +0 -0
  73. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/tables/utils.py +0 -0
  74. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/templates/dashboard.css +0 -0
  75. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/templates/dashboard.js +0 -0
  76. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/templates/dashboard_template.html.j2 +0 -0
  77. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/reporting/templates/report_template.html.j2 +0 -0
  78. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/stateless/__init__.py +0 -0
  79. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/stateless/action_handlers/__init__.py +0 -0
  80. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +0 -0
  81. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +0 -0
  82. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +0 -0
  83. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/stateless/exception_handler.py +0 -0
  84. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/strategy.py +0 -0
  85. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/task.py +0 -0
  86. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/__init__.py +0 -0
  87. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/controllers/backtest_results.py +0 -0
  88. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/controllers/orders.py +0 -0
  89. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/controllers/portfolio.py +0 -0
  90. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/controllers/positions.py +0 -0
  91. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/create_app.py +0 -0
  92. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/error_handler.py +0 -0
  93. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/responses.py +0 -0
  94. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/run_strategies.py +0 -0
  95. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/schemas/backtest_result.py +0 -0
  96. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/schemas/order.py +0 -0
  97. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/schemas/portfolio.py +0 -0
  98. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/schemas/position.py +0 -0
  99. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/app/web/setup_cors.py +0 -0
  100. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/__init__.py +0 -0
  101. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/deploy_to_aws_lambda.py +0 -0
  102. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/deploy_to_azure_function.py +0 -0
  103. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/index_command.py +0 -0
  104. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/initialize_app.py +0 -0
  105. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/mcp_server.py +0 -0
  106. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/migrate_store_command.py +0 -0
  107. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/.gitignore.template +0 -0
  108. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/app.py.template +0 -0
  109. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/app_azure_function.py.template +0 -0
  110. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/app_web.py.template +0 -0
  111. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +0 -0
  112. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +0 -0
  113. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/aws_lambda_readme.md.template +0 -0
  114. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +0 -0
  115. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/azure_function_host.json.template +0 -0
  116. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +0 -0
  117. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +0 -0
  118. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/data_providers.py.template +0 -0
  119. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/env.example.template +0 -0
  120. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/env_azure_function.example.template +0 -0
  121. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/market_data_providers.py.template +0 -0
  122. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/readme.md.template +0 -0
  123. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/requirements.txt.template +0 -0
  124. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/templates/run_backtest.py.template +0 -0
  125. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/cli/validate_backtest_checkpoints.py +0 -0
  126. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/create_app.py +0 -0
  127. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/__init__.py +0 -0
  128. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/algorithm_id.py +0 -0
  129. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/__init__.py +0 -0
  130. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/backtest.py +0 -0
  131. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/backtest_date_range.py +0 -0
  132. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/backtest_engine.py +0 -0
  133. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +0 -0
  134. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/backtest_index_row.py +0 -0
  135. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/backtest_metrics.py +0 -0
  136. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/backtest_monte_carlo_test.py +0 -0
  137. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/backtest_run.py +0 -0
  138. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +0 -0
  139. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/backtest_utils.py +0 -0
  140. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/backtest_window.py +0 -0
  141. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/bundle.py +0 -0
  142. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/combine_backtests.py +0 -0
  143. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/consistency.py +0 -0
  144. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/execution_config.py +0 -0
  145. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/study.py +0 -0
  146. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/templates/backtest.html +0 -0
  147. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/templates/finterion-dark.png +0 -0
  148. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/templates/finterion-light.png +0 -0
  149. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/backtesting/universe.py +0 -0
  150. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/blotter.py +0 -0
  151. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/config.py +0 -0
  152. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/constants.py +0 -0
  153. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/data_provider.py +0 -0
  154. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/data_structures.py +0 -0
  155. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/datetime_parsing.py +0 -0
  156. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/decimal_parsing.py +0 -0
  157. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/exceptions.py +0 -0
  158. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/fx.py +0 -0
  159. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/__init__.py +0 -0
  160. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/app_mode.py +0 -0
  161. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/base_model.py +0 -0
  162. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/conflict_policy.py +0 -0
  163. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/data/__init__.py +0 -0
  164. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/data/data_type.py +0 -0
  165. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/event.py +0 -0
  166. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/market/__init__.py +0 -0
  167. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/market/market_credential.py +0 -0
  168. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/order/__init__.py +0 -0
  169. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/order/order.py +0 -0
  170. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/order/order_side.py +0 -0
  171. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/order/order_status.py +0 -0
  172. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/order/order_type.py +0 -0
  173. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/portfolio/__init__.py +0 -0
  174. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/portfolio/portfolio.py +0 -0
  175. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +0 -0
  176. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +0 -0
  177. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/portfolio/sync.py +0 -0
  178. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/position/__init__.py +0 -0
  179. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/position/position.py +0 -0
  180. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/position/position_size.py +0 -0
  181. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/position/position_snapshot.py +0 -0
  182. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/risk_rules/__init__.py +0 -0
  183. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/risk_rules/cooldown_rule.py +0 -0
  184. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/risk_rules/scaling_rule.py +0 -0
  185. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/risk_rules/stop_loss_rule.py +0 -0
  186. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/risk_rules/take_profit_rule.py +0 -0
  187. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/risk_rules/trading_cost.py +0 -0
  188. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/scheduling/__init__.py +0 -0
  189. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/scheduling/date_rule.py +0 -0
  190. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/scheduling/schedule.py +0 -0
  191. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/scheduling/scheduled_function.py +0 -0
  192. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/scheduling/time_rule.py +0 -0
  193. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/signal.py +0 -0
  194. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/signal_helpers.py +0 -0
  195. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/signal_series.py +0 -0
  196. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/snapshot_interval.py +0 -0
  197. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/strategy_profile.py +0 -0
  198. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/time_frame.py +0 -0
  199. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/time_interval.py +0 -0
  200. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/time_unit.py +0 -0
  201. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/tracing/__init__.py +0 -0
  202. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/tracing/trace.py +0 -0
  203. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/trade/__init__.py +0 -0
  204. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/trade/trade.py +0 -0
  205. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/trade/trade_status.py +0 -0
  206. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +0 -0
  207. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/models/trade/trade_take_profit.py +0 -0
  208. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/order_executor.py +0 -0
  209. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/pipeline/__init__.py +0 -0
  210. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/pipeline/custom_factor.py +0 -0
  211. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/pipeline/factor.py +0 -0
  212. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/pipeline/factors/__init__.py +0 -0
  213. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/pipeline/factors/builtin.py +0 -0
  214. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/pipeline/filter.py +0 -0
  215. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/pipeline/pipeline.py +0 -0
  216. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/portfolio_provider.py +0 -0
  217. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/services/__init__.py +0 -0
  218. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/services/market_credential_service.py +0 -0
  219. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/services/portfolios/__init__.py +0 -0
  220. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +0 -0
  221. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/services/rounding_service.py +0 -0
  222. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/services/state_handler.py +0 -0
  223. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/stateless_actions.py +0 -0
  224. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/strategy.py +0 -0
  225. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/utils/__init__.py +0 -0
  226. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/utils/csv.py +0 -0
  227. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/utils/custom_tqdm.py +0 -0
  228. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/utils/dates.py +0 -0
  229. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +0 -0
  230. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/utils/polars.py +0 -0
  231. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/utils/random.py +0 -0
  232. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/utils/signatures.py +0 -0
  233. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/utils/stoppable_thread.py +0 -0
  234. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/domain/utils/synchronized.py +0 -0
  235. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/download_data.py +0 -0
  236. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/__init__.py +0 -0
  237. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/data_providers/__init__.py +0 -0
  238. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/data_providers/alpha_vantage.py +0 -0
  239. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/data_providers/base_url.py +0 -0
  240. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/data_providers/csv_url.py +0 -0
  241. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/data_providers/json_url.py +0 -0
  242. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/data_providers/pandas.py +0 -0
  243. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/data_providers/parquet_url.py +0 -0
  244. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/data_providers/polygon.py +0 -0
  245. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/data_providers/yahoo.py +0 -0
  246. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/database/__init__.py +0 -0
  247. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/database/sql_alchemy.py +0 -0
  248. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/__init__.py +0 -0
  249. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/decimal_parser.py +0 -0
  250. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/model_extension.py +0 -0
  251. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/order/__init__.py +0 -0
  252. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/order/order.py +0 -0
  253. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/order/trade_allocation.py +0 -0
  254. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/order_trade_association.py +0 -0
  255. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +0 -0
  256. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +0 -0
  257. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/portfolio/sql_portfolio.py +0 -0
  258. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/position/__init__.py +0 -0
  259. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/position/position.py +0 -0
  260. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +0 -0
  261. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/trades/__init__.py +0 -0
  262. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/trades/trade.py +0 -0
  263. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +0 -0
  264. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +0 -0
  265. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/order_executors/__init__.py +0 -0
  266. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/order_executors/ccxt_order_executor.py +0 -0
  267. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/portfolio_providers/__init__.py +0 -0
  268. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/portfolio_providers/ccxt_portfolio_provider.py +0 -0
  269. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/repositories/__init__.py +0 -0
  270. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/repositories/order_repository.py +0 -0
  271. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +0 -0
  272. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +0 -0
  273. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/repositories/position_repository.py +0 -0
  274. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +0 -0
  275. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/repositories/repository.py +0 -0
  276. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/repositories/trade_allocation_repository.py +0 -0
  277. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/repositories/trade_repository.py +0 -0
  278. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +0 -0
  279. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +0 -0
  280. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/services/__init__.py +0 -0
  281. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/services/aws/__init__.py +0 -0
  282. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/services/azure/__init__.py +0 -0
  283. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/services/backtesting/__init__.py +0 -0
  284. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/services/backtesting/checkpoint_manifest.py +0 -0
  285. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/infrastructure/services/backtesting/vector_backtest_service.py +0 -0
  286. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/notebook/__init__.py +0 -0
  287. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/notebook/magic.py +0 -0
  288. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/__init__.py +0 -0
  289. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/backtest_index/__init__.py +0 -0
  290. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/backtest_index/sqlite_index.py +0 -0
  291. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/backtest_store/__init__.py +0 -0
  292. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/backtest_store/base.py +0 -0
  293. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/backtest_store/decompose.py +0 -0
  294. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/backtest_store/local_dir_store.py +0 -0
  295. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/backtest_store/local_tiered_store.py +0 -0
  296. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/configuration_service.py +0 -0
  297. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/data_providers/__init__.py +0 -0
  298. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/data_providers/data.py +0 -0
  299. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/executors/__init__.py +0 -0
  300. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/executors/base.py +0 -0
  301. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/executors/limit.py +0 -0
  302. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/executors/market.py +0 -0
  303. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/market_credential_service.py +0 -0
  304. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/__init__.py +0 -0
  305. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/_returns_helper.py +0 -0
  306. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/alpha.py +0 -0
  307. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/beta.py +0 -0
  308. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/cagr.py +0 -0
  309. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/calmar_ratio.py +0 -0
  310. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/consistency.py +0 -0
  311. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/drawdown.py +0 -0
  312. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/equity_curve.py +0 -0
  313. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/exposure.py +0 -0
  314. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/generate.py +0 -0
  315. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/mae_mfe.py +0 -0
  316. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/mean_daily_return.py +0 -0
  317. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/omega_ratio.py +0 -0
  318. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/price_efficiency.py +0 -0
  319. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/profit_factor.py +0 -0
  320. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/recovery.py +0 -0
  321. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/returns.py +0 -0
  322. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/risk_free_rate.py +0 -0
  323. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/sharpe_ratio.py +0 -0
  324. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/sortino_ratio.py +0 -0
  325. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/standard_deviation.py +0 -0
  326. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/trades.py +0 -0
  327. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/treynor_ratio.py +0 -0
  328. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/ulcer.py +0 -0
  329. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/value_at_risk.py +0 -0
  330. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/volatility.py +0 -0
  331. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/metrics/win_rate.py +0 -0
  332. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/order_service/__init__.py +0 -0
  333. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/order_service/order_backtest_service.py +0 -0
  334. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/order_service/order_executor_lookup.py +0 -0
  335. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/order_service/order_service.py +0 -0
  336. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/pipeline/__init__.py +0 -0
  337. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/pipeline/pipeline_engine.py +0 -0
  338. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/pipeline/vector_pipeline_engine.py +0 -0
  339. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/portfolios/__init__.py +0 -0
  340. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +0 -0
  341. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/portfolios/broker_balance_tracker.py +0 -0
  342. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/portfolios/portfolio_configuration_service.py +0 -0
  343. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +0 -0
  344. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/portfolios/portfolio_service.py +0 -0
  345. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +0 -0
  346. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +0 -0
  347. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/positions/__init__.py +0 -0
  348. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/positions/position_service.py +0 -0
  349. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/positions/position_snapshot_service.py +0 -0
  350. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/repository_service.py +0 -0
  351. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/strategy_phases/__init__.py +0 -0
  352. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/strategy_phases/apply_risk_budget.py +0 -0
  353. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/strategy_phases/attach_risk_rules.py +0 -0
  354. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/strategy_phases/base.py +0 -0
  355. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/strategy_phases/collect_signals.py +0 -0
  356. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/strategy_phases/default.py +0 -0
  357. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/strategy_phases/emit_orders.py +0 -0
  358. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/strategy_phases/evaluate_pipelines.py +0 -0
  359. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/strategy_phases/phase_state.py +0 -0
  360. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/strategy_phases/record_cooldown.py +0 -0
  361. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/strategy_phases/resolve_conflicts.py +0 -0
  362. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/strategy_phases/size_positions.py +0 -0
  363. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/trade_hooks/__init__.py +0 -0
  364. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/trade_hooks/trade_hook_dispatcher.py +0 -0
  365. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/trade_order_evaluator/__init__.py +0 -0
  366. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/trade_service/__init__.py +0 -0
  367. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/trade_service/trade_service.py +0 -0
  368. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/investing_algorithm_framework/services/trade_service/trade_stop_loss_service.py +0 -0
  369. {investing_algorithm_framework-9.0.0a2 → investing_algorithm_framework-9.0.0a3}/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: 9.0.0a2
3
+ Version: 9.0.0a3
4
4
  Summary: A framework for creating trading bots
5
5
  Author: MDUYN
6
6
  Requires-Python: >=3.10,<4.0
@@ -10,25 +10,25 @@ Classifier: Programming Language :: Python :: 3.11
10
10
  Classifier: Programming Language :: Python :: 3.12
11
11
  Provides-Extra: all
12
12
  Provides-Extra: alpha-vantage
13
+ Provides-Extra: aws
14
+ Provides-Extra: azure
13
15
  Provides-Extra: polygon
14
16
  Provides-Extra: yahoo
15
17
  Requires-Dist: Flask (>=3.1.0)
16
18
  Requires-Dist: Flask-Cors (>=3.0.9,<7.0.0)
17
- Requires-Dist: Flask-Migrate (>=2.6.0)
18
19
  Requires-Dist: SQLAlchemy (>=2.0.18)
19
20
  Requires-Dist: alpha_vantage (>=3.0.0,<4.0.0) ; extra == "alpha-vantage" or extra == "all"
20
- Requires-Dist: azure-identity (>=1.19.0,<2.0.0)
21
- Requires-Dist: azure-mgmt-resource (>=23.2.0,<24.0.0)
22
- Requires-Dist: azure-mgmt-storage (>=21.2.1,<22.0.0)
23
- Requires-Dist: azure-mgmt-web (>=7.3.1,<8.0.0)
24
- Requires-Dist: azure-storage-blob (>=12.24.0,<13.0.0)
25
- Requires-Dist: boto3 (>=1.38.41,<2.0.0)
21
+ Requires-Dist: azure-identity (>=1.19.0,<2.0.0) ; extra == "azure" or extra == "all"
22
+ Requires-Dist: azure-mgmt-resource (>=23.2.0,<24.0.0) ; extra == "azure" or extra == "all"
23
+ Requires-Dist: azure-mgmt-storage (>=21.2.1,<22.0.0) ; extra == "azure" or extra == "all"
24
+ Requires-Dist: azure-mgmt-web (>=7.3.1,<8.0.0) ; extra == "azure" or extra == "all"
25
+ Requires-Dist: azure-storage-blob (>=12.24.0,<13.0.0) ; extra == "azure" or extra == "all"
26
+ Requires-Dist: boto3 (>=1.38.41,<2.0.0) ; extra == "aws" or extra == "all"
26
27
  Requires-Dist: ccxt (>=4.2.48)
27
28
  Requires-Dist: dependency-injector (>=4.40.0)
28
- Requires-Dist: jupyter (>=1.0.0)
29
+ Requires-Dist: finterion-charts (==1.4.0)
29
30
  Requires-Dist: marshmallow (>=3.5.0)
30
31
  Requires-Dist: msgpack (>=1.0.0)
31
- Requires-Dist: plotly (>=6.1.2,<7.0.0)
32
32
  Requires-Dist: polars[numpy,pandas] (>=0.20.10)
33
33
  Requires-Dist: polygon-api-client (>=1.14.0,<2.0.0) ; extra == "polygon" or extra == "all"
34
34
  Requires-Dist: pyarrow (>=14.0.0)
@@ -0,0 +1,236 @@
1
+ import json
2
+ import logging
3
+ import os
4
+ import threading
5
+ from datetime import datetime, timezone
6
+ from typing import Optional
7
+
8
+ from investing_algorithm_framework.domain import OperationalException
9
+
10
+ logger = logging.getLogger("investing_algorithm_framework")
11
+
12
+ NOT_STARTED = "NOT_STARTED"
13
+ RUNNING = "RUNNING"
14
+ STOPPING = "STOPPING"
15
+ STOPPED = "STOPPED"
16
+
17
+ CONTROL_FILE_NAME = "algorithm_control.json"
18
+
19
+
20
+ class AlgorithmRunner:
21
+ """
22
+ Thread-safe controller that runs an ``EventLoopService`` in a
23
+ background thread so the trading algorithm can be started and
24
+ stopped on demand (e.g. from the web API) without killing the
25
+ process that hosts it.
26
+ """
27
+
28
+ def __init__(self):
29
+ self._lock = threading.Lock()
30
+ self._thread: Optional[threading.Thread] = None
31
+ self._event_loop_service = None
32
+ self._run_kwargs = {}
33
+ self._status = NOT_STARTED
34
+ self._started_at = None
35
+ self._stopped_at = None
36
+ self._error = None
37
+ self._resource_directory = None
38
+ self._state_handler = None
39
+
40
+ def bind_persistence(self, resource_directory, state_handler=None) -> None:
41
+ """
42
+ Wires where the enabled/disabled control flag is persisted.
43
+
44
+ This is what makes ``enable()``/``disable()`` meaningful for
45
+ *stateless* deployments (AWS Lambda, Azure Functions): the
46
+ flag file lives inside ``resource_directory``, the same
47
+ directory a configured ``state_handler`` already uploads/
48
+ downloads on every run. Passing the state handler here makes a
49
+ toggle take effect immediately (pushed on the spot) instead of
50
+ waiting for the next natural save.
51
+ """
52
+ with self._lock:
53
+ self._resource_directory = resource_directory
54
+ self._state_handler = state_handler
55
+
56
+ def _control_file_path(self) -> Optional[str]:
57
+ if self._resource_directory is None:
58
+ return None
59
+ os.makedirs(self._resource_directory, exist_ok=True)
60
+ return os.path.join(self._resource_directory, CONTROL_FILE_NAME)
61
+
62
+ def get_control_state(self) -> dict:
63
+ """Returns the persisted enabled/disabled control state."""
64
+ default = {"enabled": True, "reason": None, "updated_at": None}
65
+ path = self._control_file_path()
66
+
67
+ if path is None or not os.path.exists(path):
68
+ return default
69
+
70
+ try:
71
+ with open(path, "r") as f:
72
+ return {**default, **json.load(f)}
73
+ except (OSError, ValueError) as e:
74
+ logger.warning(f"Could not read algorithm control file: {e}")
75
+ return default
76
+
77
+ def is_enabled(self) -> bool:
78
+ """Enabled by default when no control file has been written yet."""
79
+ return self.get_control_state().get("enabled", True)
80
+
81
+ def _persist_enabled(
82
+ self, enabled: bool, reason: Optional[str] = None
83
+ ) -> None:
84
+ path = self._control_file_path()
85
+
86
+ if path is None:
87
+ return
88
+
89
+ state = {
90
+ "enabled": enabled,
91
+ "reason": reason,
92
+ "updated_at": datetime.now(timezone.utc).isoformat(),
93
+ }
94
+
95
+ with open(path, "w") as f:
96
+ json.dump(state, f)
97
+
98
+ if self._state_handler is not None:
99
+ try:
100
+ self._state_handler.save(self._resource_directory)
101
+ except Exception as e:
102
+ logger.warning(
103
+ "Could not push algorithm control state via the "
104
+ f"configured state handler: {e}"
105
+ )
106
+
107
+ def enable(self, reason: Optional[str] = None) -> None:
108
+ """Persists 'enabled', independent of any in-process thread."""
109
+ self._persist_enabled(True, reason=reason)
110
+
111
+ def disable(self, reason: Optional[str] = None) -> None:
112
+ """Persists 'disabled', independent of any in-process thread."""
113
+ self._persist_enabled(False, reason=reason)
114
+
115
+ def configure(self, event_loop_service, **run_kwargs) -> None:
116
+ """
117
+ Wires the event loop service (and any kwargs for its
118
+ ``start()`` method) that ``start``/``stop`` will control.
119
+ Safe to call again after a ``stop()`` to reconfigure before
120
+ the next ``start()``.
121
+ """
122
+ with self._lock:
123
+ self._event_loop_service = event_loop_service
124
+ self._run_kwargs = run_kwargs
125
+
126
+ @property
127
+ def status(self) -> str:
128
+ with self._lock:
129
+ return self._status
130
+
131
+ @property
132
+ def is_running(self) -> bool:
133
+ return self.status == RUNNING
134
+
135
+ def get_status_report(self) -> dict:
136
+ with self._lock:
137
+ return {
138
+ "status": self._status,
139
+ "started_at": self._started_at.isoformat()
140
+ if self._started_at else None,
141
+ "stopped_at": self._stopped_at.isoformat()
142
+ if self._stopped_at else None,
143
+ "error": self._error,
144
+ }
145
+
146
+ def start(self) -> bool:
147
+ """
148
+ Starts (or resumes) the algorithm loop in a background thread.
149
+
150
+ Returns:
151
+ bool: True if a new run was started, False if the
152
+ algorithm was already running.
153
+
154
+ Raises:
155
+ OperationalException: If the runner has not been
156
+ configured with an event loop service yet (i.e. the
157
+ app has never been run).
158
+ """
159
+ with self._lock:
160
+ if self._event_loop_service is None:
161
+ raise OperationalException(
162
+ "The algorithm has not been initialized yet. Run "
163
+ "the app at least once before starting it "
164
+ "through the API."
165
+ )
166
+
167
+ if self._status == RUNNING:
168
+ self.enable()
169
+ return False
170
+
171
+ self._event_loop_service.reset_stop()
172
+ self._error = None
173
+ self._started_at = datetime.now(timezone.utc)
174
+ self._stopped_at = None
175
+ self._status = RUNNING
176
+ event_loop_service = self._event_loop_service
177
+ run_kwargs = self._run_kwargs
178
+
179
+ def _run():
180
+ try:
181
+ event_loop_service.start(**run_kwargs)
182
+ except Exception as e:
183
+ logger.error(f"Algorithm loop stopped with an error: {e}")
184
+ with self._lock:
185
+ self._error = str(e)
186
+ finally:
187
+ with self._lock:
188
+ self._status = STOPPED
189
+ self._stopped_at = datetime.now(timezone.utc)
190
+
191
+ self._thread = threading.Thread(
192
+ name="Algorithm Loop", target=_run, daemon=True
193
+ )
194
+ self._thread.start()
195
+ self.enable()
196
+ return True
197
+
198
+ def stop(
199
+ self,
200
+ wait: bool = False,
201
+ timeout: float = 10,
202
+ reason: Optional[str] = None,
203
+ ) -> bool:
204
+ """
205
+ Signals the running algorithm loop to stop after its current
206
+ iteration completes, and persists 'disabled' regardless of
207
+ whether a loop is currently running in-process (this is what a
208
+ stateless/serverless deployment, e.g. AWS Lambda or Azure
209
+ Functions, checks on its next scheduled invocation).
210
+
211
+ Args:
212
+ wait: If True, blocks until the background thread has
213
+ actually exited (bounded by ``timeout`` seconds).
214
+ timeout: Max seconds to wait for the thread to exit when
215
+ ``wait`` is True.
216
+ reason: Optional human-readable reason, persisted alongside
217
+ the disabled state.
218
+
219
+ Returns:
220
+ bool: True if a running in-process loop was signaled to
221
+ stop, False if it was not running (the disabled state
222
+ is still persisted either way).
223
+ """
224
+ self.disable(reason=reason)
225
+
226
+ with self._lock:
227
+ if self._status != RUNNING:
228
+ return False
229
+ self._status = STOPPING
230
+ self._event_loop_service.request_stop()
231
+ thread = self._thread
232
+
233
+ if wait and thread is not None:
234
+ thread.join(timeout=timeout)
235
+
236
+ return True
@@ -787,6 +787,74 @@ class App:
787
787
  configuration_service.add_value(APP_MODE, AppMode.WEB.value)
788
788
  self._initialize_web()
789
789
 
790
+ def _bind_algorithm_control_persistence(self):
791
+ """
792
+ Wires the algorithm runner's enabled/disabled control file to
793
+ this app's resource directory (and state handler, if any).
794
+ Safe to call multiple times/from multiple entry points
795
+ (``run()``, ``start_algorithm()``, ``stop_algorithm()``,
796
+ ``is_algorithm_enabled()``) since it just re-binds the same
797
+ path.
798
+ """
799
+ algorithm_runner = self.container.algorithm_runner()
800
+ algorithm_runner.bind_persistence(
801
+ self.resource_directory_path, state_handler=self._state_handler
802
+ )
803
+ return algorithm_runner
804
+
805
+ def start_algorithm(self) -> bool:
806
+ """
807
+ Enables the algorithm and, if it is currently running live in
808
+ this process, resumes it. In a stateless deployment (AWS
809
+ Lambda, Azure Functions) there is no in-process loop to
810
+ resume — enabling it here is enough, since ``run()`` checks
811
+ this same persisted flag on every future invocation.
812
+
813
+ Returns:
814
+ bool: True if an in-process loop was (re)started, False
815
+ otherwise (already running, or no live loop to
816
+ resume).
817
+ """
818
+ algorithm_runner = self._bind_algorithm_control_persistence()
819
+
820
+ try:
821
+ return algorithm_runner.start()
822
+ except OperationalException:
823
+ # No live event loop configured yet (e.g. this app has
824
+ # never called `run()` in this process, or it's a
825
+ # stateless deployment) — persisting 'enabled' is enough.
826
+ algorithm_runner.enable()
827
+ return False
828
+
829
+ def stop_algorithm(self, reason: str = None, wait: bool = False) -> bool:
830
+ """
831
+ Disables the algorithm and, if it is currently running live in
832
+ this process, signals it to stop after its current iteration.
833
+ In a stateless deployment (AWS Lambda, Azure Functions), this
834
+ persists 'disabled' so the next scheduled invocation of
835
+ ``run()`` skips its iteration entirely.
836
+
837
+ Args:
838
+ reason: Optional human-readable reason to persist
839
+ alongside the disabled state.
840
+ wait: If True, blocks until the in-process loop (if any)
841
+ has actually exited.
842
+
843
+ Returns:
844
+ bool: True if an in-process loop was signaled to stop,
845
+ False otherwise (it wasn't running).
846
+ """
847
+ algorithm_runner = self._bind_algorithm_control_persistence()
848
+ return algorithm_runner.stop(reason=reason, wait=wait)
849
+
850
+ def is_algorithm_enabled(self) -> bool:
851
+ """Returns whether the algorithm is currently enabled."""
852
+ return self._bind_algorithm_control_persistence().is_enabled()
853
+
854
+ def get_algorithm_control_state(self) -> dict:
855
+ """Returns the persisted enabled/disabled control state."""
856
+ return self._bind_algorithm_control_persistence().get_control_state()
857
+
790
858
  def run(self, number_of_iterations: int = None):
791
859
  """
792
860
  Entry point to run the application. This method should be called to
@@ -834,6 +902,17 @@ class App:
834
902
  config = self.container.configuration_service().get_config()
835
903
  self._state_handler.load(config[RESOURCE_DIRECTORY])
836
904
 
905
+ algorithm_runner = self._bind_algorithm_control_persistence()
906
+
907
+ if not algorithm_runner.is_enabled():
908
+ control_state = algorithm_runner.get_control_state()
909
+ logger.info(
910
+ "Algorithm is disabled (stopped via the control API "
911
+ f"or control file, reason: {control_state.get('reason')})"
912
+ " — skipping this run."
913
+ )
914
+ return
915
+
837
916
  self.initialize_storage()
838
917
  logger.info("App initialization complete")
839
918
  event_loop_service = None
@@ -852,9 +931,12 @@ class App:
852
931
  self.initialize_services()
853
932
  self.initialize_portfolios()
854
933
 
855
- if AppMode.WEB.equals(self.config[APP_MODE]) \
856
- and not (self._flask_app and self._flask_app.testing) \
857
- and number_of_iterations is None:
934
+ is_live_web_run = AppMode.WEB.equals(self.config[APP_MODE]) \
935
+ and not (self._flask_app and self._flask_app.testing) \
936
+ and number_of_iterations is None
937
+ flask_thread = None
938
+
939
+ if is_live_web_run:
858
940
  logger.info("Running web")
859
941
  flask_thread = threading.Thread(
860
942
  name='Web App',
@@ -889,12 +971,28 @@ class App:
889
971
  algorithm, trade_order_evaluator=trade_order_evaluator
890
972
  )
891
973
 
892
- try:
893
- event_loop_service.start(
894
- number_of_iterations=number_of_iterations
895
- )
896
- except KeyboardInterrupt:
897
- exit(0)
974
+ if is_live_web_run:
975
+ # Run the event loop in its own background thread so
976
+ # the web API can start/stop it on demand (see
977
+ # `/api/algorithm/start` and `/api/algorithm/stop`)
978
+ # without killing the process. The main thread just
979
+ # keeps the process alive alongside the Flask thread.
980
+ algorithm_runner.configure(event_loop_service)
981
+ algorithm_runner.start()
982
+
983
+ try:
984
+ while flask_thread.is_alive():
985
+ flask_thread.join(timeout=1)
986
+ except KeyboardInterrupt:
987
+ algorithm_runner.stop(wait=True)
988
+ exit(0)
989
+ else:
990
+ try:
991
+ event_loop_service.start(
992
+ number_of_iterations=number_of_iterations
993
+ )
994
+ except KeyboardInterrupt:
995
+ exit(0)
898
996
  except Exception as e:
899
997
  logger.error(e)
900
998
  raise e
@@ -1547,9 +1645,8 @@ class App:
1547
1645
  ) -> Backtest:
1548
1646
  """
1549
1647
  Run vectorized backtests for a strategy. The provided
1550
- strategy needs to have its 'generate_buy_signals' and
1551
- 'generate_sell_signals' methods implemented to support vectorized
1552
- backtesting.
1648
+ strategy needs to have its 'generate_signal_series' method
1649
+ implemented to support vectorized backtesting.
1553
1650
 
1554
1651
  Args:
1555
1652
  strategy (TradingStrategy) (Optional): The strategy object
@@ -2258,9 +2355,8 @@ class App:
2258
2355
  ) -> Backtest:
2259
2356
  """
2260
2357
  Run vectorized backtests for a strategy. The provided
2261
- strategy needs to have its 'generate_buy_signals' and
2262
- 'generate_sell_signals' methods implemented to support vectorized
2263
- backtesting.
2358
+ strategy needs to have its 'generate_signal_series' method
2359
+ implemented to support vectorized backtesting.
2264
2360
 
2265
2361
  Args:
2266
2362
  strategy (TradingStrategy) (Optional): The strategy object
@@ -1,4 +1,5 @@
1
1
  from datetime import datetime, timezone
2
+ from threading import Event
2
3
  from time import sleep
3
4
  from typing import List, Set, Dict
4
5
  from logging import getLogger
@@ -81,12 +82,34 @@ class EventLoopService:
81
82
  self.data_sources = set()
82
83
  self.next_run_times = {}
83
84
  self._scheduled_function_last_runs = {}
85
+ self._task_last_runs = {}
84
86
  self.history = {}
85
87
 
86
88
  # One-shot flag: live-mode envelope validation runs once per
87
89
  # process. Reset by ``cleanup`` so a new run re-validates.
88
90
  self._pipelines_live_validated: bool = False
89
91
 
92
+ # Set by ``request_stop`` to gracefully break out of the live
93
+ # (unbounded) loop in ``start``. Cleared by ``reset_stop`` so
94
+ # the loop can be (re)started again afterwards.
95
+ self._stop_event = Event()
96
+
97
+ def request_stop(self) -> None:
98
+ """
99
+ Signals a running (unbounded) ``start()`` call to stop after
100
+ it finishes its current iteration. Safe to call from another
101
+ thread.
102
+ """
103
+ self._stop_event.set()
104
+
105
+ def reset_stop(self) -> None:
106
+ """Clears a previous stop request so ``start()`` can run again."""
107
+ self._stop_event.clear()
108
+
109
+ @property
110
+ def stop_requested(self) -> bool:
111
+ return self._stop_event.is_set()
112
+
90
113
  @staticmethod
91
114
  def _get_data_sources_for_iteration(
92
115
  strategy_data_sources
@@ -194,6 +217,52 @@ class EventLoopService:
194
217
 
195
218
  return due
196
219
 
220
+ def _get_tasks_by_ids(self, task_ids: List[str]):
221
+ """
222
+ Returns the tasks matching the given worker IDs. Unlike
223
+ ``_get_strategies``, an empty/None ``task_ids`` means "no
224
+ tasks are due" (not "all tasks") — the backtest schedule
225
+ always provides an explicit (possibly empty) list per tick.
226
+
227
+ Args:
228
+ task_ids: A list of task worker IDs to retrieve.
229
+
230
+ Returns:
231
+ List[Task]: The tasks matching the provided IDs.
232
+ """
233
+ if not task_ids:
234
+ return []
235
+
236
+ return [
237
+ self._tasks_lookup[task_id]
238
+ for task_id in task_ids
239
+ if task_id in self._tasks_lookup
240
+ ]
241
+
242
+ def _get_due_tasks(self, current_datetime=None):
243
+ """
244
+ Checks which tasks are due to run based on their Schedule.
245
+
246
+ Args:
247
+ current_datetime: Optional; the datetime to check against.
248
+ If None, uses the current datetime in UTC.
249
+
250
+ Returns:
251
+ List[Task]: A list of tasks that are due to run.
252
+ """
253
+ due = []
254
+
255
+ if current_datetime is None:
256
+ current_datetime = datetime.now(timezone.utc)
257
+
258
+ for task in self.tasks:
259
+ last_run = self._task_last_runs.get(task.worker_id)
260
+ if task.schedule.is_due(current_datetime, last_run):
261
+ due.append(task)
262
+ self._task_last_runs[task.worker_id] = current_datetime
263
+
264
+ return due
265
+
197
266
  def _get_due_scheduled_functions(self, current_datetime=None):
198
267
  """
199
268
  Returns a list of (strategy, ScheduledFunction) tuples whose
@@ -341,6 +410,10 @@ class EventLoopService:
341
410
  for strategy in self.strategies
342
411
  }
343
412
  self._scheduled_function_last_runs = {}
413
+ self._task_last_runs = {}
414
+ self._tasks_lookup = {
415
+ task.worker_id: task for task in self.tasks
416
+ }
344
417
 
345
418
  # Collect all data sources and initialize history
346
419
  for strategy in self.strategies:
@@ -419,11 +492,14 @@ class EventLoopService:
419
492
  )
420
493
  strategy_ids = schedule[current_time]["strategy_ids"]
421
494
  strategies = self._get_strategies(strategy_ids)
495
+ task_ids = schedule[current_time]["task_ids"]
496
+ tasks = self._get_tasks_by_ids(task_ids)
422
497
  sf_calls = schedule[current_time].get(
423
498
  "scheduled_function_calls", []
424
499
  )
425
500
  self._run_iteration(
426
501
  strategies=strategies,
502
+ tasks=tasks,
427
503
  scheduled_function_calls=sf_calls,
428
504
  )
429
505
 
@@ -433,34 +509,45 @@ class EventLoopService:
433
509
  INDEX_DATETIME, current_time
434
510
  )
435
511
  strategy_ids = schedule[current_time]["strategy_ids"]
436
- # task_ids = schedule[current_time]["task_ids"]
512
+ task_ids = schedule[current_time]["task_ids"]
437
513
  strategies = self._get_strategies(strategy_ids)
514
+ tasks = self._get_tasks_by_ids(task_ids)
438
515
  sf_calls = schedule[current_time].get(
439
516
  "scheduled_function_calls", []
440
517
  )
441
518
  self._run_iteration(
442
519
  strategies=strategies,
520
+ tasks=tasks,
443
521
  scheduled_function_calls=sf_calls,
444
522
  )
445
523
  else:
446
524
  if number_of_iterations is None:
447
- try:
448
- config = self._configuration_service.config
449
- current_time = config[INDEX_DATETIME]
450
- strategies = self._get_due_strategies(current_time)
451
- sf_calls = self._get_due_scheduled_functions(current_time)
452
- self._run_iteration(
453
- strategies=strategies,
454
- tasks=self.tasks,
455
- scheduled_function_calls=sf_calls,
456
- )
457
- current_time = datetime.now(timezone.utc)
458
- self._configuration_service.add_value(
459
- INDEX_DATETIME, current_time
460
- )
461
- sleep(1)
462
- except KeyboardInterrupt:
463
- exit(0)
525
+ # Unbounded live loop: keeps iterating until a stop is
526
+ # requested (e.g. via ``request_stop()`` from the web
527
+ # API) or the process receives a KeyboardInterrupt.
528
+ while not self._stop_event.is_set():
529
+ try:
530
+ config = self._configuration_service.config
531
+ current_time = config[INDEX_DATETIME]
532
+ strategies = self._get_due_strategies(current_time)
533
+ tasks = self._get_due_tasks(current_time)
534
+ sf_calls = \
535
+ self._get_due_scheduled_functions(current_time)
536
+ self._run_iteration(
537
+ strategies=strategies,
538
+ tasks=tasks,
539
+ scheduled_function_calls=sf_calls,
540
+ )
541
+ current_time = datetime.now(timezone.utc)
542
+ self._configuration_service.add_value(
543
+ INDEX_DATETIME, current_time
544
+ )
545
+ except KeyboardInterrupt:
546
+ break
547
+ # Wakes up immediately if a stop is requested
548
+ # instead of always waiting out the full second.
549
+ if self._stop_event.wait(1):
550
+ break
464
551
  else:
465
552
 
466
553
  if show_progress:
@@ -472,11 +559,12 @@ class EventLoopService:
472
559
  config = self._configuration_service.config
473
560
  current_time = config[INDEX_DATETIME]
474
561
  strategies = self._get_due_strategies(current_time)
562
+ tasks = self._get_due_tasks(current_time)
475
563
  sf_calls = \
476
564
  self._get_due_scheduled_functions(current_time)
477
565
  self._run_iteration(
478
566
  strategies=strategies,
479
- tasks=self.tasks,
567
+ tasks=tasks,
480
568
  scheduled_function_calls=sf_calls,
481
569
  )
482
570
  current_time = datetime.now(timezone.utc)
@@ -492,11 +580,12 @@ class EventLoopService:
492
580
  config = self._configuration_service.config
493
581
  current_time = config[INDEX_DATETIME]
494
582
  strategies = self._get_due_strategies(current_time)
583
+ tasks = self._get_due_tasks(current_time)
495
584
  sf_calls = \
496
585
  self._get_due_scheduled_functions(current_time)
497
586
  self._run_iteration(
498
587
  strategies=strategies,
499
- tasks=self.tasks,
588
+ tasks=tasks,
500
589
  scheduled_function_calls=sf_calls,
501
590
  )
502
591
  current_time = datetime.now(timezone.utc)
@@ -747,17 +836,17 @@ class EventLoopService:
747
836
  ohlcv_data=orders_trades_update_ohlcv_data
748
837
  )
749
838
 
750
- # Step 4: Run all tasks
751
- for task in self.tasks:
752
- task.run(data_object)
839
+ # Step 4: Run all due tasks. ``tasks`` is the caller-resolved,
840
+ # schedule-filtered list (see _get_due_tasks/_get_tasks_by_ids);
841
+ # fall back to every registered task only if no list was given.
842
+ for task in (self.tasks if tasks is None else tasks):
843
+ logger.info(f"Running task {task.worker_id}")
844
+ task.run(self.context)
753
845
 
754
846
  # Step 5: Run all strategies
755
847
  if not strategies:
756
848
  return
757
849
 
758
- for task in self.tasks:
759
- logger.info(f"Running task {task.__class__.__name__}")
760
-
761
850
  for strategy in strategies:
762
851
 
763
852
  if strategy.data_sources is not None: