investing-algorithm-framework 7.16.18__tar.gz → 7.19.1__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.

Potentially problematic release.


This version of investing-algorithm-framework might be problematic. Click here for more details.

Files changed (259) hide show
  1. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/PKG-INFO +1 -1
  2. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/__init__.py +7 -4
  3. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/__init__.py +4 -2
  4. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/analysis/__init__.py +5 -1
  5. investing_algorithm_framework-7.19.1/investing_algorithm_framework/app/analysis/backtest_utils.py +80 -0
  6. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/app.py +106 -16
  7. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/__init__.py +3 -2
  8. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/backtesting/backtest.py +58 -14
  9. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/backtesting/backtest_metrics.py +8 -0
  10. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/backtesting/backtest_run.py +31 -7
  11. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +6 -0
  12. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/backtesting/combine_backtests.py +13 -4
  13. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/data_provider.py +5 -0
  14. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/exceptions.py +17 -0
  15. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/data_providers/ccxt.py +35 -1
  16. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/data_providers/csv.py +42 -4
  17. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/data_providers/pandas.py +37 -3
  18. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/data_providers/data_provider_service.py +1 -1
  19. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/pyproject.toml +1 -1
  20. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/LICENSE +0 -0
  21. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/README.md +0 -0
  22. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/algorithm/__init__.py +0 -0
  23. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/algorithm/algorithm.py +0 -0
  24. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/algorithm/algorithm_factory.py +0 -0
  25. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/analysis/backtest_data_ranges.py +0 -0
  26. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/analysis/permutation.py +0 -0
  27. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/analysis/ranking.py +0 -0
  28. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/app_hook.py +0 -0
  29. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/context.py +0 -0
  30. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/eventloop.py +0 -0
  31. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/__init__.py +0 -0
  32. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/ascii.py +0 -0
  33. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/backtest_report.py +0 -0
  34. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/charts/__init__.py +0 -0
  35. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/charts/entry_exist_signals.py +0 -0
  36. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/charts/equity_curve.py +0 -0
  37. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/charts/equity_curve_drawdown.py +0 -0
  38. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/charts/line_chart.py +0 -0
  39. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/charts/monthly_returns_heatmap.py +0 -0
  40. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/charts/ohlcv_data_completeness.py +0 -0
  41. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/charts/rolling_sharp_ratio.py +0 -0
  42. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/charts/yearly_returns_barchart.py +0 -0
  43. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/generate.py +0 -0
  44. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/tables/__init__.py +0 -0
  45. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/tables/key_metrics_table.py +0 -0
  46. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/tables/stop_loss_table.py +0 -0
  47. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/tables/time_metrics_table.py +0 -0
  48. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/tables/trade_metrics_table.py +0 -0
  49. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/tables/trades_table.py +0 -0
  50. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/tables/utils.py +0 -0
  51. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/reporting/templates/report_template.html.j2 +0 -0
  52. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/stateless/__init__.py +0 -0
  53. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/stateless/action_handlers/__init__.py +0 -0
  54. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +0 -0
  55. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +0 -0
  56. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +0 -0
  57. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/stateless/exception_handler.py +0 -0
  58. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/strategy.py +0 -0
  59. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/task.py +0 -0
  60. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/web/__init__.py +0 -0
  61. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/web/controllers/__init__.py +0 -0
  62. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/web/controllers/orders.py +0 -0
  63. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/web/controllers/portfolio.py +0 -0
  64. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/web/controllers/positions.py +0 -0
  65. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/web/create_app.py +0 -0
  66. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/web/error_handler.py +0 -0
  67. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/web/responses.py +0 -0
  68. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/web/run_strategies.py +0 -0
  69. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/web/schemas/__init__.py +0 -0
  70. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/web/schemas/order.py +0 -0
  71. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/web/schemas/portfolio.py +0 -0
  72. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/web/schemas/position.py +0 -0
  73. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/app/web/setup_cors.py +0 -0
  74. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/__init__.py +0 -0
  75. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/cli.py +0 -0
  76. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/deploy_to_aws_lambda.py +0 -0
  77. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/deploy_to_azure_function.py +0 -0
  78. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/initialize_app.py +0 -0
  79. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/.gitignore.template +0 -0
  80. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/app.py.template +0 -0
  81. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +0 -0
  82. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/app_azure_function.py.template +0 -0
  83. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/app_web.py.template +0 -0
  84. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +0 -0
  85. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +0 -0
  86. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/aws_lambda_readme.md.template +0 -0
  87. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +0 -0
  88. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +0 -0
  89. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/azure_function_host.json.template +0 -0
  90. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +0 -0
  91. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +0 -0
  92. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/data_providers.py.template +0 -0
  93. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/env.example.template +0 -0
  94. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/env_azure_function.example.template +0 -0
  95. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/market_data_providers.py.template +0 -0
  96. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/readme.md.template +0 -0
  97. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/requirements.txt.template +0 -0
  98. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/run_backtest.py.template +0 -0
  99. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/cli/templates/strategy.py.template +0 -0
  100. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/create_app.py +0 -0
  101. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/dependency_container.py +0 -0
  102. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/backtesting/__init__.py +0 -0
  103. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/backtesting/backtest_date_range.py +0 -0
  104. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +0 -0
  105. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +0 -0
  106. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/config.py +0 -0
  107. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/constants.py +0 -0
  108. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/data_structures.py +0 -0
  109. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/decimal_parsing.py +0 -0
  110. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/__init__.py +0 -0
  111. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/app_mode.py +0 -0
  112. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/base_model.py +0 -0
  113. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/data/__init__.py +0 -0
  114. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/data/data_source.py +0 -0
  115. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/data/data_type.py +0 -0
  116. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/event.py +0 -0
  117. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/market/__init__.py +0 -0
  118. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/market/market_credential.py +0 -0
  119. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/order/__init__.py +0 -0
  120. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/order/order.py +0 -0
  121. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/order/order_side.py +0 -0
  122. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/order/order_status.py +0 -0
  123. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/order/order_type.py +0 -0
  124. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/portfolio/__init__.py +0 -0
  125. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/portfolio/portfolio.py +0 -0
  126. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +0 -0
  127. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +0 -0
  128. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/position/__init__.py +0 -0
  129. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/position/position.py +0 -0
  130. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/position/position_snapshot.py +0 -0
  131. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/snapshot_interval.py +0 -0
  132. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/strategy_profile.py +0 -0
  133. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/time_frame.py +0 -0
  134. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/time_interval.py +0 -0
  135. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/time_unit.py +0 -0
  136. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/tracing/__init__.py +0 -0
  137. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/tracing/trace.py +0 -0
  138. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/trade/__init__.py +0 -0
  139. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/trade/trade.py +0 -0
  140. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/trade/trade_risk_type.py +0 -0
  141. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/trade/trade_status.py +0 -0
  142. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +0 -0
  143. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/models/trade/trade_take_profit.py +0 -0
  144. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/order_executor.py +0 -0
  145. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/portfolio_provider.py +0 -0
  146. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/positions/__init__.py +0 -0
  147. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/positions/position_size.py +0 -0
  148. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/services/__init__.py +0 -0
  149. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/services/market_credential_service.py +0 -0
  150. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/services/portfolios/__init__.py +0 -0
  151. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +0 -0
  152. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/services/rounding_service.py +0 -0
  153. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/services/state_handler.py +0 -0
  154. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/stateless_actions.py +0 -0
  155. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/strategy.py +0 -0
  156. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/utils/__init__.py +0 -0
  157. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/utils/csv.py +0 -0
  158. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/utils/custom_tqdm.py +0 -0
  159. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/utils/dates.py +0 -0
  160. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +0 -0
  161. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/utils/polars.py +0 -0
  162. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/utils/random.py +0 -0
  163. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/utils/signatures.py +0 -0
  164. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/utils/stoppable_thread.py +0 -0
  165. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/domain/utils/synchronized.py +0 -0
  166. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/download_data.py +0 -0
  167. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/__init__.py +0 -0
  168. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/data_providers/__init__.py +0 -0
  169. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/database/__init__.py +0 -0
  170. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/database/sql_alchemy.py +0 -0
  171. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/__init__.py +0 -0
  172. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/decimal_parser.py +0 -0
  173. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/model_extension.py +0 -0
  174. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/order/__init__.py +0 -0
  175. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/order/order.py +0 -0
  176. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/order/order_metadata.py +0 -0
  177. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/order_trade_association.py +0 -0
  178. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +0 -0
  179. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +0 -0
  180. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/portfolio/sql_portfolio.py +0 -0
  181. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/position/__init__.py +0 -0
  182. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/position/position.py +0 -0
  183. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +0 -0
  184. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/trades/__init__.py +0 -0
  185. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/trades/trade.py +0 -0
  186. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +0 -0
  187. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +0 -0
  188. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/order_executors/__init__.py +0 -0
  189. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/order_executors/backtest_oder_executor.py +0 -0
  190. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/order_executors/ccxt_order_executor.py +0 -0
  191. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/portfolio_providers/__init__.py +0 -0
  192. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/portfolio_providers/ccxt_portfolio_provider.py +0 -0
  193. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/repositories/__init__.py +0 -0
  194. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/repositories/order_metadata_repository.py +0 -0
  195. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/repositories/order_repository.py +0 -0
  196. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +0 -0
  197. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +0 -0
  198. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/repositories/position_repository.py +0 -0
  199. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +0 -0
  200. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/repositories/repository.py +0 -0
  201. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/repositories/trade_repository.py +0 -0
  202. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +0 -0
  203. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +0 -0
  204. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/services/__init__.py +0 -0
  205. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/services/aws/__init__.py +0 -0
  206. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/services/aws/state_handler.py +0 -0
  207. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/services/azure/__init__.py +0 -0
  208. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/infrastructure/services/azure/state_handler.py +0 -0
  209. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/__init__.py +0 -0
  210. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/backtesting/__init__.py +0 -0
  211. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/backtesting/backtest_service.py +0 -0
  212. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/configuration_service.py +0 -0
  213. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/data_providers/__init__.py +0 -0
  214. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/market_credential_service.py +0 -0
  215. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/__init__.py +0 -0
  216. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/alpha.py +0 -0
  217. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/beta.py +0 -0
  218. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/cagr.py +0 -0
  219. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/calmar_ratio.py +0 -0
  220. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/drawdown.py +0 -0
  221. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/equity_curve.py +0 -0
  222. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/exposure.py +0 -0
  223. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/generate.py +0 -0
  224. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/mean_daily_return.py +0 -0
  225. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/price_efficiency.py +0 -0
  226. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/profit_factor.py +0 -0
  227. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/recovery.py +0 -0
  228. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/returns.py +0 -0
  229. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/risk_free_rate.py +0 -0
  230. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/sharpe_ratio.py +0 -0
  231. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/sortino_ratio.py +0 -0
  232. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/standard_deviation.py +0 -0
  233. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/trades.py +0 -0
  234. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/treynor_ratio.py +0 -0
  235. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/ulcer.py +0 -0
  236. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/value_at_risk.py +0 -0
  237. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/volatility.py +0 -0
  238. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/metrics/win_rate.py +0 -0
  239. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/order_service/__init__.py +0 -0
  240. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/order_service/order_backtest_service.py +0 -0
  241. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/order_service/order_executor_lookup.py +0 -0
  242. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/order_service/order_service.py +0 -0
  243. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/portfolios/__init__.py +0 -0
  244. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +0 -0
  245. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/portfolios/portfolio_configuration_service.py +0 -0
  246. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +0 -0
  247. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/portfolios/portfolio_service.py +0 -0
  248. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +0 -0
  249. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +0 -0
  250. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/positions/__init__.py +0 -0
  251. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/positions/position_service.py +0 -0
  252. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/positions/position_snapshot_service.py +0 -0
  253. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/repository_service.py +0 -0
  254. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/trade_order_evaluator/__init__.py +0 -0
  255. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +0 -0
  256. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +0 -0
  257. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +0 -0
  258. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/trade_service/__init__.py +0 -0
  259. {investing_algorithm_framework-7.16.18 → investing_algorithm_framework-7.19.1}/investing_algorithm_framework/services/trade_service/trade_service.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: investing-algorithm-framework
3
- Version: 7.16.18
3
+ Version: 7.19.1
4
4
  Summary: A framework for creating trading bots
5
5
  Author: MDUYN
6
6
  Requires-Python: >=3.10
@@ -1,16 +1,16 @@
1
1
  from .app import App, Algorithm, \
2
2
  TradingStrategy, StatelessAction, Task, AppHook, Context, \
3
- add_html_report, BacktestReport, \
3
+ add_html_report, BacktestReport, save_backtests_to_directory, \
4
4
  pretty_print_trades, pretty_print_positions, \
5
5
  pretty_print_orders, pretty_print_backtest, select_backtest_date_ranges, \
6
- get_equity_curve_with_drawdown_chart, \
6
+ get_equity_curve_with_drawdown_chart, load_backtests_from_directory, \
7
7
  get_rolling_sharpe_ratio_chart, rank_results, \
8
8
  get_monthly_returns_heatmap_chart, create_weights, \
9
9
  get_yearly_returns_bar_chart, get_entry_and_exit_signals, \
10
10
  get_ohlcv_data_completeness_chart, get_equity_curve_chart
11
11
  from .domain import ApiException, combine_backtests, PositionSize, \
12
12
  OrderType, OperationalException, OrderStatus, OrderSide, \
13
- TimeUnit, TimeInterval, Order, Portfolio, Backtest, \
13
+ TimeUnit, TimeInterval, Order, Portfolio, Backtest, DataError, \
14
14
  Position, TimeFrame, INDEX_DATETIME, MarketCredential, \
15
15
  PortfolioConfiguration, RESOURCE_DIRECTORY, AWS_LAMBDA_LOGGING_CONFIG, \
16
16
  Trade, SYMBOLS, RESERVED_BALANCES, APP_MODE, AppMode, DATETIME_FORMAT, \
@@ -189,5 +189,8 @@ __all__ = [
189
189
  "get_negative_trades",
190
190
  "get_positive_trades",
191
191
  "get_number_of_trades",
192
- "BacktestRun"
192
+ "BacktestRun",
193
+ "load_backtests_from_directory",
194
+ "save_backtests_to_directory",
195
+ "DataError"
193
196
  ]
@@ -14,7 +14,7 @@ from .reporting import add_html_report, \
14
14
  get_yearly_returns_bar_chart, get_equity_curve_chart, \
15
15
  get_ohlcv_data_completeness_chart, get_entry_and_exit_signals
16
16
  from .analysis import select_backtest_date_ranges, rank_results, \
17
- create_weights
17
+ create_weights, load_backtests_from_directory, save_backtests_to_directory
18
18
 
19
19
 
20
20
  __all__ = [
@@ -41,5 +41,7 @@ __all__ = [
41
41
  "rank_results",
42
42
  "create_weights",
43
43
  "get_entry_and_exit_signals",
44
- "get_equity_curve_chart"
44
+ "get_equity_curve_chart",
45
+ "load_backtests_from_directory",
46
+ "save_backtests_to_directory"
45
47
  ]
@@ -1,11 +1,15 @@
1
1
  from .backtest_data_ranges import select_backtest_date_ranges
2
2
  from .ranking import rank_results, create_weights, combine_backtest_metrics
3
3
  from .permutation import create_ohlcv_permutation
4
+ from .backtest_utils import load_backtests_from_directory, \
5
+ save_backtests_to_directory
4
6
 
5
7
  __all__ = [
6
8
  "select_backtest_date_ranges",
7
9
  "rank_results",
8
10
  "create_weights",
9
11
  "create_ohlcv_permutation",
10
- "combine_backtest_metrics"
12
+ "combine_backtest_metrics",
13
+ "load_backtests_from_directory",
14
+ "save_backtests_to_directory"
11
15
  ]
@@ -0,0 +1,80 @@
1
+ import os
2
+ from pathlib import Path
3
+ from typing import List, Union
4
+ from logging import getLogger
5
+ from random import Random
6
+
7
+ from investing_algorithm_framework.domain import Backtest
8
+
9
+
10
+ logger = getLogger("investing_algorithm_framework")
11
+
12
+
13
+ def save_backtests_to_directory(
14
+ backtests: List[Backtest],
15
+ directory_path: Union[str, Path]
16
+ ) -> None:
17
+ """
18
+ Saves a list of Backtest objects to the specified directory.
19
+
20
+ Args:
21
+ backtests (List[Backtest]): List of Backtest objects to save.
22
+ directory_path (str): Path to the directory where backtests
23
+ will be saved.
24
+
25
+ Returns:
26
+ None
27
+ """
28
+
29
+ if not os.path.exists(directory_path):
30
+ os.makedirs(directory_path)
31
+
32
+ for backtest in backtests:
33
+ # Check if there is an ID in the backtest metadata
34
+ backtest_id = backtest.metadata.get('id')
35
+
36
+ if backtest_id is None:
37
+ logger.warning(
38
+ "Backtest is missing 'id' in metadata. "
39
+ "Generating a random ID as name for backtest file."
40
+ )
41
+ backtest_id = str(Random().randint(100000, 999999))
42
+
43
+ backtest.save(os.path.join(directory_path, backtest_id))
44
+
45
+
46
+ def load_backtests_from_directory(
47
+ directory_path: Union[str, Path]
48
+ ) -> List[Backtest]:
49
+ """
50
+ Loads Backtest objects from the specified directory.
51
+
52
+ Args:
53
+ directory_path (str): Path to the directory from which backtests
54
+ will be loaded.
55
+
56
+ Returns:
57
+ List[Backtest]: List of loaded Backtest objects.
58
+ """
59
+
60
+ backtests = []
61
+
62
+ if not os.path.exists(directory_path):
63
+ logger.warning(
64
+ f"Directory {directory_path} does not exist. "
65
+ "No backtests loaded."
66
+ )
67
+ return backtests
68
+
69
+ for file_name in os.listdir(directory_path):
70
+ file_path = os.path.join(directory_path, file_name)
71
+
72
+ try:
73
+ backtest = Backtest.open(file_path)
74
+ backtests.append(backtest)
75
+ except Exception as e:
76
+ logger.error(
77
+ f"Failed to load backtest from {file_path}: {e}"
78
+ )
79
+
80
+ return backtests
@@ -5,6 +5,7 @@ import threading
5
5
  from datetime import datetime, timezone
6
6
  from typing import List, Optional, Any, Dict, Tuple
7
7
 
8
+ import pandas as pd
8
9
  from flask import Flask
9
10
 
10
11
  from investing_algorithm_framework.app.algorithm import Algorithm
@@ -16,7 +17,7 @@ from investing_algorithm_framework.domain import DATABASE_NAME, TimeUnit, \
16
17
  SQLALCHEMY_DATABASE_URI, OperationalException, StateHandler, \
17
18
  BACKTESTING_START_DATE, BACKTESTING_END_DATE, APP_MODE, MarketCredential, \
18
19
  AppMode, BacktestDateRange, DATABASE_DIRECTORY_NAME, DataSource, \
19
- BACKTESTING_INITIAL_AMOUNT, SNAPSHOT_INTERVAL, Backtest, \
20
+ BACKTESTING_INITIAL_AMOUNT, SNAPSHOT_INTERVAL, Backtest, DataError, \
20
21
  PortfolioConfiguration, SnapshotInterval, DataType, combine_backtests, \
21
22
  PortfolioProvider, OrderExecutor, ImproperlyConfigured, \
22
23
  DataProvider, INDEX_DATETIME, tqdm, BacktestPermutationTest, \
@@ -32,6 +33,7 @@ from .app_hook import AppHook
32
33
  from .eventloop import EventLoopService
33
34
  from .analysis import create_ohlcv_permutation
34
35
 
36
+
35
37
  logger = logging.getLogger("investing_algorithm_framework")
36
38
  COLOR_RESET = '\033[0m'
37
39
  COLOR_GREEN = '\033[92m'
@@ -789,6 +791,70 @@ class App:
789
791
  .market_credential_service()
790
792
  return market_credential_service.get_all()
791
793
 
794
+ def check_data_completeness(
795
+ self,
796
+ strategies: List[TradingStrategy],
797
+ backtest_date_range: BacktestDateRange
798
+ ) -> None:
799
+ """
800
+ Function to check the data completeness for a set of strategies
801
+ over a given backtest date range. This method checks if all data
802
+ sources required by the strategies have complete data for the
803
+ specified date range.
804
+
805
+ Args:
806
+ strategies (List[TradingStrategy]): List of strategy objects
807
+ to check data completeness for.
808
+ backtest_date_range (BacktestDateRange): The date range to
809
+ check data completeness for.
810
+ Returns:
811
+ None
812
+ """
813
+ data_sources = []
814
+
815
+ for strategy in strategies:
816
+ data_sources.extend(strategy.data_sources)
817
+
818
+ self.initialize_data_sources_backtest(
819
+ data_sources,
820
+ backtest_date_range,
821
+ show_progress=True
822
+ )
823
+ data_provider_service = self.container.data_provider_service()
824
+
825
+ for strategy in strategies:
826
+
827
+ for data_source in strategy.data_sources:
828
+
829
+ if DataType.OHLCV.equals(data_source.data_type):
830
+ df = data_provider_service.get_ohlcv_data(
831
+ symbol=data_source.symbol,
832
+ start_date=backtest_date_range.start_date,
833
+ end_date=backtest_date_range.end_date,
834
+ pandas=True
835
+ )
836
+ df = df.copy()
837
+ df['Datetime'] = pd.to_datetime(df['Datetime'])
838
+ df = df.sort_values('Datetime')\
839
+ .tail(data_source.window_size)
840
+ start = df['Datetime'].iloc[0]
841
+ end = df['Datetime'].iloc[-1]
842
+ freq = pd.to_timedelta(data_source.time_frame.value)
843
+ expected = pd.date_range(start, end, freq=freq)
844
+ actual = df['Datetime']
845
+ missing = expected.difference(actual)
846
+
847
+ # Calculate the percentage completeness
848
+ completeness = len(actual) / len(expected) * 100
849
+
850
+ if completeness < 100:
851
+ raise DataError(
852
+ f"Data completeness for data source "
853
+ f"{data_source.identifier} "
854
+ f"({data_source.symbol}) is {completeness:.2f}% "
855
+ f"complete. Missing data points: {len(missing)}"
856
+ )
857
+
792
858
  def run_vector_backtests(
793
859
  self,
794
860
  initial_amount,
@@ -801,6 +867,7 @@ class App:
801
867
  show_progress: bool = True,
802
868
  market: Optional[str] = None,
803
869
  trading_symbol: Optional[str] = None,
870
+ continue_on_error: bool = False,
804
871
  ) -> List[Backtest]:
805
872
  """
806
873
  Run vectorized backtests for a set of strategies. The provided
@@ -848,6 +915,10 @@ class App:
848
915
  trading_symbol (str): The trading symbol to use for the backtest.
849
916
  This is used to create a portfolio configuration if no
850
917
  portfolio configuration is provided in the strategy.
918
+ continue_on_error (bool): Whether to continue running other
919
+ backtests if an error occurs in one of the backtests. If set
920
+ to True, the backtest will return an empty Backtest instance
921
+ in case of an error. If set to False, the error will be raised.
851
922
 
852
923
  Returns:
853
924
  List[Backtest]: List of Backtest instances for each strategy
@@ -956,7 +1027,8 @@ class App:
956
1027
  show_data_initialization_progress: bool = True,
957
1028
  initial_amount: float = None,
958
1029
  market: str = None,
959
- trading_symbol: str = None
1030
+ trading_symbol: str = None,
1031
+ continue_on_error: bool = False,
960
1032
  ) -> Backtest:
961
1033
  """
962
1034
  Run vectorized backtests for a strategy. The provided
@@ -1008,6 +1080,10 @@ class App:
1008
1080
  that the portfolio will start with. If not provided,
1009
1081
  the initial amount from the portfolio configuration will
1010
1082
  be used.
1083
+ continue_on_error (bool): Whether to continue running other
1084
+ backtests if an error occurs in one of the backtests. If set
1085
+ to True, the backtest will return an empty Backtest instance
1086
+ in case of an error. If set to False, the error will be raised.
1011
1087
 
1012
1088
  Returns:
1013
1089
  Backtest: Instance of Backtest
@@ -1040,21 +1116,35 @@ class App:
1040
1116
 
1041
1117
  backtest_service = self.container.backtest_service()
1042
1118
  backtest_service.validate_strategy_for_vector_backtest(strategy)
1043
- run = backtest_service.create_vector_backtest(
1044
- strategy=strategy,
1045
- backtest_date_range=backtest_date_range,
1046
- risk_free_rate=risk_free_rate,
1047
- market=market,
1048
- trading_symbol=trading_symbol,
1049
- initial_amount=initial_amount
1050
- )
1051
- backtest = Backtest(
1052
- backtest_runs=[run],
1053
- risk_free_rate=risk_free_rate,
1054
- backtest_summary=generate_backtest_summary_metrics(
1055
- [run.backtest_metrics]
1119
+
1120
+ try:
1121
+ run = backtest_service.create_vector_backtest(
1122
+ strategy=strategy,
1123
+ backtest_date_range=backtest_date_range,
1124
+ risk_free_rate=risk_free_rate,
1125
+ market=market,
1126
+ trading_symbol=trading_symbol,
1127
+ initial_amount=initial_amount
1056
1128
  )
1057
- )
1129
+ backtest = Backtest(
1130
+ backtest_runs=[run],
1131
+ risk_free_rate=risk_free_rate,
1132
+ backtest_summary=generate_backtest_summary_metrics(
1133
+ [run.backtest_metrics]
1134
+ )
1135
+ )
1136
+ except Exception as e:
1137
+ logger.error(
1138
+ f"Error occurred during vector backtest for strategy "
1139
+ f"{strategy.strategy_id}: {str(e)}"
1140
+ )
1141
+ if continue_on_error:
1142
+ backtest = Backtest(
1143
+ backtest_runs=[],
1144
+ risk_free_rate=risk_free_rate,
1145
+ )
1146
+ else:
1147
+ raise e
1058
1148
 
1059
1149
  # Add the metadata to the backtest
1060
1150
  if metadata is None:
@@ -15,7 +15,7 @@ from .constants import ITEMIZE, ITEMIZED, PER_PAGE, PAGE, ENVIRONMENT, \
15
15
  from .data_provider import DataProvider
16
16
  from .data_structures import PeekableQueue
17
17
  from .decimal_parsing import parse_decimal_to_string, parse_string_to_decimal
18
- from .exceptions import OperationalException, ApiException, \
18
+ from .exceptions import OperationalException, ApiException, DataError, \
19
19
  PermissionDeniedApiException, ImproperlyConfigured, NetworkError
20
20
  from .models import OrderStatus, OrderSide, OrderType, TimeInterval, \
21
21
  TimeUnit, TimeFrame, PortfolioConfiguration, Portfolio, Position, \
@@ -143,5 +143,6 @@ __all__ = [
143
143
  "BacktestEvaluationFocus",
144
144
  'combine_backtests',
145
145
  'PositionSize',
146
- 'generate_backtest_summary_metrics'
146
+ 'generate_backtest_summary_metrics',
147
+ 'DataError'
147
148
  ]
@@ -14,6 +14,7 @@ from .backtest_run import BacktestRun
14
14
  from .backtest_permutation_test import BacktestPermutationTest
15
15
  from .backtest_date_range import BacktestDateRange
16
16
  from .backtest_summary_metrics import BacktestSummaryMetrics
17
+ from .combine_backtests import generate_backtest_summary_metrics
17
18
 
18
19
 
19
20
  logger = getLogger(__name__)
@@ -177,13 +178,19 @@ class Backtest:
177
178
  }
178
179
 
179
180
  @staticmethod
180
- def open(directory_path: Union[str, Path]) -> 'Backtest':
181
+ def open(
182
+ directory_path: Union[str, Path],
183
+ backtest_date_ranges: List[BacktestDateRange] = None
184
+ ) -> 'Backtest':
181
185
  """
182
186
  Open a backtest report from a directory and return a Backtest instance.
183
187
 
184
188
  Args:
185
189
  directory_path (str): The path to the directory containing the
186
190
  backtest report files.
191
+ backtest_date_ranges (List[BacktestDateRange], optional): A list of
192
+ date ranges to filter the backtest runs. If provided, only
193
+ backtest runs matching these date ranges will be loaded.
187
194
 
188
195
  Returns:
189
196
  Backtest: An instance of Backtest with the loaded metrics
@@ -214,13 +221,59 @@ class Backtest:
214
221
  except json.JSONDecodeError as e:
215
222
  logger.error(f"Error decoding id JSON: {e}")
216
223
  id = None
217
- # Load combined backtest metrics if available
218
224
 
219
- summary_file = os.path.join(directory_path, "summary.json")
225
+ # Load all backtest runs
226
+ runs_dir = os.path.join(directory_path, "runs")
227
+
228
+ if os.path.isdir(runs_dir):
229
+ for dir_name in os.listdir(runs_dir):
230
+ run_path = os.path.join(runs_dir, dir_name)
231
+ if os.path.isdir(run_path):
232
+
233
+ if backtest_date_ranges is not None:
234
+ temp_run = BacktestRun.open(run_path)
235
+ match_found = False
236
+
237
+ for date_range in backtest_date_ranges:
238
+ if (
239
+ temp_run.backtest_start_date ==
240
+ date_range.start_date and
241
+ temp_run.backtest_end_date ==
242
+ date_range.end_date
243
+ ):
244
+
245
+ if date_range.name is not None:
246
+ if (
247
+ temp_run.backtest_date_range_name ==
248
+ date_range.name
249
+ ):
250
+ match_found = True
251
+ break
252
+ else:
253
+ match_found = True
254
+ break
255
+
256
+ if not match_found:
257
+ continue
258
+
259
+ backtest_runs.append(BacktestRun.open(run_path))
260
+
261
+ # Load combined backtests summary
262
+ if backtest_date_ranges is not None:
263
+ summary_file = os.path.join(directory_path, "summary.json")
264
+
265
+ if os.path.isfile(summary_file):
266
+ backtest_summary_metrics = \
267
+ BacktestSummaryMetrics.open(summary_file)
268
+ else:
269
+ # Generate new summary from loaded backtest runs
270
+ temp_metrics = []
271
+ for br in backtest_runs:
272
+ if br.backtest_metrics:
273
+ temp_metrics.append(br.backtest_metrics)
220
274
 
221
- if os.path.isfile(summary_file):
222
275
  backtest_summary_metrics = \
223
- BacktestSummaryMetrics.open(summary_file)
276
+ generate_backtest_summary_metrics(temp_metrics)
224
277
 
225
278
  # Load backtest permutation test metrics
226
279
  perm_test_dir = os.path.join(directory_path, "permutation_tests")
@@ -233,15 +286,6 @@ class Backtest:
233
286
  BacktestPermutationTest.open(perm_test_file)
234
287
  )
235
288
 
236
- # Load all backtest runs
237
- runs_dir = os.path.join(directory_path, "runs")
238
-
239
- if os.path.isdir(runs_dir):
240
- for dir_name in os.listdir(runs_dir):
241
- run_path = os.path.join(runs_dir, dir_name)
242
- if os.path.isdir(run_path):
243
- backtest_runs.append(BacktestRun.open(run_path))
244
-
245
289
  # Load metadata if available
246
290
  meta_file = os.path.join(directory_path, "metadata.json")
247
291
 
@@ -104,8 +104,12 @@ class BacktestMetrics:
104
104
  still open at the end of the backtest.
105
105
  win_rate (float): The win rate of the trades, expressed
106
106
  as a percentage.
107
+ current_win_rate (float): The current win rate of the trades,
108
+ including open trades.
107
109
  win_loss_ratio (float): The ratio of winning trades
108
110
  to losing trades.
111
+ current_win_loss_ratio (float): The current ratio of winning
112
+ trades to losing trades, including open trades.
109
113
  percentage_winning_months (float): The percentage of months
110
114
  with positive returns.
111
115
  percentage_winning_years (float): The percentage of years with
@@ -193,7 +197,9 @@ class BacktestMetrics:
193
197
  number_of_trades_opened: int = 0
194
198
  number_of_trades_open_at_end: int = 0
195
199
  win_rate: float = 0.0
200
+ current_win_rate: float = 0.0
196
201
  win_loss_ratio: float = 0.0
202
+ current_win_loss_ratio: float = 0.0
197
203
  percentage_winning_months: float = 0.0
198
204
  percentage_winning_years: float = 0.0
199
205
  average_monthly_return: float = 0.0
@@ -289,7 +295,9 @@ class BacktestMetrics:
289
295
  "number_of_trades_closed": self.number_of_trades_closed,
290
296
  "number_of_trades_opened": self.number_of_trades_opened,
291
297
  "win_rate": self.win_rate,
298
+ "current_win_rate": self.current_win_rate,
292
299
  "win_loss_ratio": self.win_loss_ratio,
300
+ "current_win_loss_ratio": self.current_win_loss_ratio,
293
301
  "percentage_winning_months": self.percentage_winning_months,
294
302
  "percentage_winning_years": self.percentage_winning_years,
295
303
  "average_monthly_return": self.average_monthly_return,
@@ -251,17 +251,41 @@ class BacktestRun:
251
251
  # Remove backtest_metrics to avoid redundancy
252
252
  data.pop("backtest_metrics", None)
253
253
 
254
- data["backtest_start_date"] = self.backtest_start_date.strftime(
254
+ # Ensure datetime objects are in UTC before formatting
255
+ backtest_start_date = self.backtest_start_date
256
+
257
+ if backtest_start_date.tzinfo is None:
258
+ # Naive datetime - treat as UTC
259
+ backtest_start_date = backtest_start_date.replace(
260
+ tzinfo=timezone.utc
261
+ )
262
+ else:
263
+ # Timezone-aware - convert to UTC
264
+ backtest_start_date = backtest_start_date.astimezone(
265
+ timezone.utc
266
+ )
267
+
268
+ backtest_end_date = self.backtest_end_date
269
+ if backtest_end_date.tzinfo is None:
270
+ backtest_end_date = backtest_end_date.replace(
271
+ tzinfo=timezone.utc
272
+ )
273
+ else:
274
+ backtest_end_date = backtest_end_date.astimezone(timezone.utc)
275
+
276
+ created_at = self.created_at
277
+ if created_at.tzinfo is None:
278
+ created_at = created_at.replace(tzinfo=timezone.utc)
279
+ else:
280
+ created_at = created_at.astimezone(timezone.utc)
281
+
282
+ data["backtest_start_date"] = backtest_start_date.strftime(
255
283
  "%Y-%m-%d %H:%M:%S"
256
284
  )
257
- data["backtest_end_date"] = self.backtest_end_date.strftime(
285
+ data["backtest_end_date"] = backtest_end_date.strftime(
258
286
  "%Y-%m-%d %H:%M:%S"
259
287
  )
260
-
261
- if self.created_at.tzinfo is None:
262
- self.created_at = self.created_at.replace(tzinfo=timezone.utc)
263
-
264
- data["created_at"] = self.created_at.strftime(
288
+ data["created_at"] = created_at.strftime(
265
289
  "%Y-%m-%d %H:%M:%S"
266
290
  )
267
291
  json.dump(data, f, default=str)
@@ -48,7 +48,9 @@ class BacktestSummaryMetrics:
48
48
  max_drawdown_duration (int): Duration of the maximum drawdown.
49
49
  trades_per_year (float): Average trades executed per year.
50
50
  win_rate (float): Percentage of winning trades.
51
+ current_win_rate (float): Win rate over recent trades.
51
52
  win_loss_ratio (float): Ratio of average win to average loss.
53
+ current_win_loss_ratio (float): Win/loss ratio over recent trades.
52
54
  number_of_trades (int): Total number of trades executed.
53
55
  cumulative_exposure (float): Total exposure over the backtest period.
54
56
  exposure_ratio (float): Ratio of exposure to available capital.
@@ -81,7 +83,9 @@ class BacktestSummaryMetrics:
81
83
  max_drawdown_duration: int = None
82
84
  trades_per_year: float = None
83
85
  win_rate: float = None
86
+ current_win_rate: float = None
84
87
  win_loss_ratio: float = None
88
+ current_win_loss_ratio: float = None
85
89
  number_of_trades: int = None
86
90
  number_of_trades_closed: int = None
87
91
  cumulative_exposure: float = None
@@ -123,7 +127,9 @@ class BacktestSummaryMetrics:
123
127
  "max_drawdown_duration": self.max_drawdown_duration,
124
128
  "trades_per_year": self.trades_per_year,
125
129
  "win_rate": self.win_rate,
130
+ "current_win_rate": self.current_win_rate,
126
131
  "win_loss_ratio": self.win_loss_ratio,
132
+ "current_win_loss_ratio": self.current_win_loss_ratio,
127
133
  "number_of_trades": self.number_of_trades,
128
134
  "number_of_trades_closed": self.number_of_trades_closed,
129
135
  "cumulative_exposure": self.cumulative_exposure,
@@ -1,6 +1,5 @@
1
1
  from typing import List
2
2
 
3
- from .backtest import Backtest
4
3
  from .backtest_summary_metrics import BacktestSummaryMetrics
5
4
  from .backtest_metrics import BacktestMetrics
6
5
 
@@ -27,9 +26,7 @@ def safe_weighted_mean(values, weights):
27
26
  ) / total_weight if total_weight > 0 else None
28
27
 
29
28
 
30
- def combine_backtests(
31
- backtests: List[Backtest],
32
- ) -> Backtest:
29
+ def combine_backtests(backtests):
33
30
  """
34
31
  Combine multiple backtests into a single backtest by aggregating
35
32
  their results.
@@ -72,6 +69,8 @@ def combine_backtests(
72
69
  risk_free_rate = backtest.risk_free_rate
73
70
  break
74
71
 
72
+ from .backtest import Backtest
73
+
75
74
  backtest = Backtest(
76
75
  backtest_summary=summary,
77
76
  metadata=metadata,
@@ -184,10 +183,18 @@ def generate_backtest_summary_metrics(
184
183
  [b.win_rate for b in backtest_metrics],
185
184
  [b.total_number_of_days for b in backtest_metrics]
186
185
  )
186
+ current_win_rate = safe_weighted_mean(
187
+ [b.current_win_rate for b in backtest_metrics],
188
+ [b.total_number_of_days for b in backtest_metrics]
189
+ )
187
190
  win_loss_ratio = safe_weighted_mean(
188
191
  [b.win_loss_ratio for b in backtest_metrics],
189
192
  [b.total_number_of_days for b in backtest_metrics]
190
193
  )
194
+ current_win_loss_ratio = safe_weighted_mean(
195
+ [b.current_win_loss_ratio for b in backtest_metrics],
196
+ [b.total_number_of_days for b in backtest_metrics]
197
+ )
191
198
  number_of_trades = sum(
192
199
  b.number_of_trades for b in backtest_metrics
193
200
  if b.number_of_trades is not None
@@ -251,7 +258,9 @@ def generate_backtest_summary_metrics(
251
258
  max_drawdown_duration=max_drawdown_duration,
252
259
  trades_per_year=trades_per_year,
253
260
  win_rate=win_rate,
261
+ current_win_rate=current_win_rate,
254
262
  win_loss_ratio=win_loss_ratio,
263
+ current_win_loss_ratio=current_win_loss_ratio,
255
264
  number_of_trades=number_of_trades,
256
265
  number_of_trades_closed=number_of_trades_closed,
257
266
  cumulative_exposure=cumulative_exposure,
@@ -240,6 +240,7 @@ class DataProvider(ABC):
240
240
  backtest_index_date: datetime,
241
241
  backtest_start_date: datetime = None,
242
242
  backtest_end_date: datetime = None,
243
+ data_source: DataSource = None,
243
244
  ) -> Any:
244
245
  """
245
246
  Fetches backtest data for a given datasource
@@ -251,6 +252,10 @@ class DataProvider(ABC):
251
252
  backtest data.
252
253
  backtest_end_date (datetime): The end date for the
253
254
  backtest data.
255
+ data_source (Optional[DataSource]): The data source
256
+ specification that is used to fetch the data.
257
+ This param is optional and can be used to
258
+ help identify errors in data fetching.
254
259
 
255
260
  Returns:
256
261
  Any: The data for the given symbol and date range.
@@ -84,3 +84,20 @@ class NetworkError(Exception):
84
84
  "status": "error",
85
85
  "message": self.error_message
86
86
  }
87
+
88
+
89
+ class DataError(Exception):
90
+ """
91
+ Class DataError: Exception class indicating a problem occurred
92
+ during data retrieval or processing
93
+ """
94
+
95
+ def __init__(self, message) -> None:
96
+ super(DataError, self).__init__(message)
97
+ self.error_message = message
98
+
99
+ def to_response(self):
100
+ return {
101
+ "status": "error",
102
+ "message": self.error_message
103
+ }