investing-algorithm-framework 4.1.0__tar.gz → 5.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/PKG-INFO +20 -11
  2. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/README.md +17 -9
  3. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/__init__.py +4 -2
  4. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/algorithm.py +262 -21
  5. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/app.py +271 -365
  6. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/strategy.py +76 -15
  7. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/dependency_container.py +27 -24
  8. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/__init__.py +8 -3
  9. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/constants.py +3 -3
  10. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/__init__.py +2 -0
  11. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/backtesting/backtest_report.py +4 -1
  12. investing_algorithm_framework-5.0.0/investing_algorithm_framework/domain/models/market_data_type.py +46 -0
  13. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/order/order.py +4 -66
  14. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/order/order_status.py +1 -1
  15. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/time_frame.py +21 -0
  16. investing_algorithm_framework-5.0.0/investing_algorithm_framework/domain/models/trade/trade.py +296 -0
  17. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/trade/trade_status.py +1 -0
  18. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/services/market_data_sources.py +47 -16
  19. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/services/market_service.py +1 -1
  20. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/utils/backtesting.py +61 -6
  21. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/utils/polars.py +4 -0
  22. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/indicators/trend.py +14 -2
  23. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/__init__.py +5 -3
  24. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/__init__.py +2 -0
  25. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/ccxt.py +54 -105
  26. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/csv.py +69 -62
  27. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/pandas.py +6 -44
  28. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/order/order.py +19 -30
  29. investing_algorithm_framework-5.0.0/investing_algorithm_framework/infrastructure/models/order_trade_association.py +10 -0
  30. investing_algorithm_framework-5.0.0/investing_algorithm_framework/infrastructure/models/trade.py +106 -0
  31. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/repositories/__init__.py +2 -0
  32. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/repositories/position_repository.py +7 -0
  33. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/repositories/repository.py +3 -0
  34. investing_algorithm_framework-5.0.0/investing_algorithm_framework/infrastructure/repositories/trade_repository.py +71 -0
  35. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/services/performance_service/performance_service.py +35 -67
  36. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/__init__.py +1 -5
  37. investing_algorithm_framework-5.0.0/investing_algorithm_framework/services/backtesting/__init__.py +5 -0
  38. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/backtesting/backtest_service.py +129 -12
  39. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/configuration_service.py +8 -3
  40. investing_algorithm_framework-5.0.0/investing_algorithm_framework/services/market_data_source_service/backtest_market_data_source_service.py +207 -0
  41. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/market_data_source_service/market_data_source_service.py +149 -17
  42. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/order_service/order_backtest_service.py +26 -56
  43. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/order_service/order_service.py +42 -115
  44. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +8 -39
  45. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/strategy_orchestrator_service.py +31 -18
  46. investing_algorithm_framework-5.0.0/investing_algorithm_framework/services/trade_service/trade_service.py +347 -0
  47. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/pyproject.toml +2 -2
  48. investing_algorithm_framework-4.1.0/investing_algorithm_framework/domain/models/trade/trade.py +0 -287
  49. investing_algorithm_framework-4.1.0/investing_algorithm_framework/services/backtesting/__init__.py +0 -12
  50. investing_algorithm_framework-4.1.0/investing_algorithm_framework/services/backtesting/backtest_report_writer_service.py +0 -91
  51. investing_algorithm_framework-4.1.0/investing_algorithm_framework/services/backtesting/graphs.py +0 -61
  52. investing_algorithm_framework-4.1.0/investing_algorithm_framework/services/market_data_source_service/backtest_market_data_source_service.py +0 -149
  53. investing_algorithm_framework-4.1.0/investing_algorithm_framework/services/trade_service/trade_service.py +0 -401
  54. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/LICENSE +0 -0
  55. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/__init__.py +0 -0
  56. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/stateless/__init__.py +0 -0
  57. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/stateless/action_handlers/__init__.py +0 -0
  58. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +0 -0
  59. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +0 -0
  60. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +0 -0
  61. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/stateless/exception_handler.py +0 -0
  62. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/task.py +0 -0
  63. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/web/__init__.py +0 -0
  64. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/web/controllers/__init__.py +0 -0
  65. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/web/controllers/orders.py +0 -0
  66. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/web/controllers/portfolio.py +0 -0
  67. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/web/controllers/positions.py +0 -0
  68. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/web/create_app.py +0 -0
  69. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/web/error_handler.py +0 -0
  70. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/web/responses.py +0 -0
  71. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/web/run_strategies.py +0 -0
  72. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/web/schemas/__init__.py +0 -0
  73. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/web/schemas/order.py +0 -0
  74. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/web/schemas/portfolio.py +0 -0
  75. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/web/schemas/position.py +0 -0
  76. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/app/web/setup_cors.py +0 -0
  77. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/cli/__init__.py +0 -0
  78. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/cli/create_azure_function_app_skeleton.py +0 -0
  79. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/cli/deploy_to_azure_function.py +0 -0
  80. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/cli/templates/azure_function_framework_app.py.template +0 -0
  81. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +0 -0
  82. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/cli/templates/azure_function_host.json.template +0 -0
  83. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +0 -0
  84. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +0 -0
  85. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/create_app.py +0 -0
  86. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/config.py +0 -0
  87. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/data_structures.py +0 -0
  88. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/decimal_parsing.py +0 -0
  89. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/exceptions.py +0 -0
  90. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/metrics/__init__.py +0 -0
  91. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/metrics/price_efficiency.py +0 -0
  92. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/app_mode.py +0 -0
  93. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/backtesting/__init__.py +0 -0
  94. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/backtesting/backtest_date_range.py +0 -0
  95. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/backtesting/backtest_position.py +0 -0
  96. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/backtesting/backtest_reports_evaluation.py +0 -0
  97. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/base_model.py +0 -0
  98. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/date_range.py +0 -0
  99. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/market/__init__.py +0 -0
  100. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/market/market_credential.py +0 -0
  101. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/order/__init__.py +0 -0
  102. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/order/order_side.py +0 -0
  103. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/order/order_type.py +0 -0
  104. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/portfolio/__init__.py +0 -0
  105. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/portfolio/portfolio.py +0 -0
  106. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +0 -0
  107. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +0 -0
  108. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/position/__init__.py +0 -0
  109. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/position/position.py +0 -0
  110. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/position/position_snapshot.py +0 -0
  111. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/strategy_profile.py +0 -0
  112. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/time_interval.py +0 -0
  113. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/time_unit.py +0 -0
  114. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/tracing/__init__.py +0 -0
  115. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/tracing/trace.py +0 -0
  116. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/trade/__init__.py +0 -0
  117. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/trading_data_types.py +0 -0
  118. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/models/trading_time_frame.py +0 -0
  119. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/services/__init__.py +0 -0
  120. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/services/market_credential_service.py +0 -0
  121. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/services/portfolios/__init__.py +0 -0
  122. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +0 -0
  123. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/services/rounding_service.py +0 -0
  124. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/singleton.py +0 -0
  125. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/stateless_actions.py +0 -0
  126. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/strategy.py +0 -0
  127. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/utils/__init__.py +0 -0
  128. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/utils/csv.py +0 -0
  129. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/utils/random.py +0 -0
  130. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/utils/signatures.py +0 -0
  131. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/utils/stoppable_thread.py +0 -0
  132. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/domain/utils/synchronized.py +0 -0
  133. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/indicators/__init__.py +0 -0
  134. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/indicators/advanced.py +0 -0
  135. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/indicators/momentum.py +0 -0
  136. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/indicators/utils.py +0 -0
  137. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/database/__init__.py +0 -0
  138. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/database/sql_alchemy.py +0 -0
  139. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/decimal_parser.py +0 -0
  140. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/__init__.py +0 -0
  141. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/us_treasury_yield.py +0 -0
  142. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/model_extension.py +0 -0
  143. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/order/__init__.py +0 -0
  144. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +0 -0
  145. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +0 -0
  146. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/portfolio/sql_portfolio.py +0 -0
  147. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/position/__init__.py +0 -0
  148. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/position/position.py +0 -0
  149. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +0 -0
  150. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/repositories/order_repository.py +0 -0
  151. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +0 -0
  152. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +0 -0
  153. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +0 -0
  154. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/services/__init__.py +0 -0
  155. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/services/azure/__init__.py +0 -0
  156. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/services/azure/state_handler.py +0 -0
  157. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/services/market_service/__init__.py +0 -0
  158. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/services/market_service/ccxt_market_service.py +0 -0
  159. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/services/performance_service/__init__.py +0 -0
  160. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/infrastructure/services/performance_service/backtest_performance_service.py +0 -0
  161. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/market_credential_service.py +0 -0
  162. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/market_data_source_service/__init__.py +0 -0
  163. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/order_service/__init__.py +0 -0
  164. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/portfolios/__init__.py +0 -0
  165. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +0 -0
  166. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/portfolios/portfolio_configuration_service.py +0 -0
  167. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/portfolios/portfolio_service.py +0 -0
  168. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +0 -0
  169. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/position_service.py +0 -0
  170. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/position_snapshot_service.py +0 -0
  171. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/repository_service.py +0 -0
  172. {investing_algorithm_framework-4.1.0 → investing_algorithm_framework-5.0.0}/investing_algorithm_framework/services/trade_service/__init__.py +0 -0
@@ -1,10 +1,11 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: investing-algorithm-framework
3
- Version: 4.1.0
3
+ Version: 5.0.0
4
4
  Summary: A framework for creating trading bots
5
5
  Author: MDUYN
6
- Requires-Python: >=3.10
6
+ Requires-Python: >=3.9
7
7
  Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.9
8
9
  Classifier: Programming Language :: Python :: 3.10
9
10
  Classifier: Programming Language :: Python :: 3.11
10
11
  Classifier: Programming Language :: Python :: 3.12
@@ -74,7 +75,8 @@ Features:
74
75
  The following algorithm connects to binance and buys BTC every 5 seconds. It also exposes an REST API that allows you to interact with the algorithm.
75
76
 
76
77
  ```python
77
- import logging
78
+ import logging.config
79
+
78
80
  from investing_algorithm_framework import create_app, PortfolioConfiguration, \
79
81
  TimeUnit, CCXTOHLCVMarketDataSource, Algorithm, \
80
82
  CCXTTickerMarketDataSource, MarketCredential, DEFAULT_LOGGING_CONFIG
@@ -96,7 +98,6 @@ bitvavo_btc_eur_ticker = CCXTTickerMarketDataSource(
96
98
  symbol="BTC/EUR",
97
99
  )
98
100
  app = create_app()
99
- algorithm = Algorithm()
100
101
  # Bitvavo market credentials are read from .env file
101
102
  app.add_market_credential(MarketCredential(market="bitvavo"))
102
103
  app.add_portfolio_configuration(
@@ -106,10 +107,9 @@ app.add_portfolio_configuration(
106
107
  initial_balance=400
107
108
  )
108
109
  )
109
- app.add_algorithm(algorithm)
110
110
 
111
111
  # Run every two hours and register the data sources
112
- @algorithm.strategy(
112
+ @app.strategy(
113
113
  time_unit=TimeUnit.HOUR,
114
114
  interval=2,
115
115
  market_data_sources=[bitvavo_btc_eur_ticker, bitvavo_btc_eur_ohlcv_2h]
@@ -117,7 +117,6 @@ app.add_algorithm(algorithm)
117
117
  def perform_strategy(algorithm: Algorithm, market_data: dict):
118
118
  # Access the data sources with the indentifier
119
119
  polars_df = market_data["BTC-ohlcv"]
120
-
121
120
  # Convert the polars dataframe to a pandas dataframe
122
121
  pandas_df = polars_df.to_pandas()
123
122
  ticker_data = market_data["BTC-ticker"]
@@ -128,18 +127,21 @@ def perform_strategy(algorithm: Algorithm, market_data: dict):
128
127
  closed_trades = algorithm.get_closed_trades()
129
128
 
130
129
  # Create a buy oder
131
- algorithm.create_limit_order(
130
+ order = algorithm.create_limit_order(
132
131
  target_symbol="BTC/EUR",
133
132
  order_side="buy",
134
133
  amount=0.01,
135
134
  price=ticker_data["ask"],
136
135
  )
136
+ trade = algorithm.get_trade(order_id=order.id)
137
+ algorithm.add_trailing_stop_loss(trade=trade, percentage=5)
137
138
 
138
139
  # Close a trade
139
- algorithm.close_trade(trades[0].id)
140
+ algorithm.close_trade(trade=trade)
140
141
 
141
142
  # Close a position
142
- algorithm.close_position(positions[0].get_symbol())
143
+ position = algorithm.get_position(symbol="BTC/EUR")
144
+ algorithm.close_position(position)
143
145
 
144
146
  if __name__ == "__main__":
145
147
  app.run()
@@ -151,7 +153,14 @@ if __name__ == "__main__":
151
153
 
152
154
  The framework also supports backtesting and performing backtest experiments. After a backtest, you can print a report that shows the performance of your trading bot.
153
155
 
154
- To run a single backtest you can use the example code that can be found [here](./examples/backtest).
156
+ To run a single backtest you can use the example code that can be found [here](./examples/backtest_example). Simply run:
157
+
158
+ > Its assumed here that you have cloned the repository, installed the framework and
159
+ > are in the root of the project.
160
+
161
+ ```bash
162
+ python examples/backtest_example/run_backtest.py
163
+ ```
155
164
 
156
165
  ### Backtesting report
157
166
 
@@ -37,7 +37,8 @@ Features:
37
37
  The following algorithm connects to binance and buys BTC every 5 seconds. It also exposes an REST API that allows you to interact with the algorithm.
38
38
 
39
39
  ```python
40
- import logging
40
+ import logging.config
41
+
41
42
  from investing_algorithm_framework import create_app, PortfolioConfiguration, \
42
43
  TimeUnit, CCXTOHLCVMarketDataSource, Algorithm, \
43
44
  CCXTTickerMarketDataSource, MarketCredential, DEFAULT_LOGGING_CONFIG
@@ -59,7 +60,6 @@ bitvavo_btc_eur_ticker = CCXTTickerMarketDataSource(
59
60
  symbol="BTC/EUR",
60
61
  )
61
62
  app = create_app()
62
- algorithm = Algorithm()
63
63
  # Bitvavo market credentials are read from .env file
64
64
  app.add_market_credential(MarketCredential(market="bitvavo"))
65
65
  app.add_portfolio_configuration(
@@ -69,10 +69,9 @@ app.add_portfolio_configuration(
69
69
  initial_balance=400
70
70
  )
71
71
  )
72
- app.add_algorithm(algorithm)
73
72
 
74
73
  # Run every two hours and register the data sources
75
- @algorithm.strategy(
74
+ @app.strategy(
76
75
  time_unit=TimeUnit.HOUR,
77
76
  interval=2,
78
77
  market_data_sources=[bitvavo_btc_eur_ticker, bitvavo_btc_eur_ohlcv_2h]
@@ -80,7 +79,6 @@ app.add_algorithm(algorithm)
80
79
  def perform_strategy(algorithm: Algorithm, market_data: dict):
81
80
  # Access the data sources with the indentifier
82
81
  polars_df = market_data["BTC-ohlcv"]
83
-
84
82
  # Convert the polars dataframe to a pandas dataframe
85
83
  pandas_df = polars_df.to_pandas()
86
84
  ticker_data = market_data["BTC-ticker"]
@@ -91,18 +89,21 @@ def perform_strategy(algorithm: Algorithm, market_data: dict):
91
89
  closed_trades = algorithm.get_closed_trades()
92
90
 
93
91
  # Create a buy oder
94
- algorithm.create_limit_order(
92
+ order = algorithm.create_limit_order(
95
93
  target_symbol="BTC/EUR",
96
94
  order_side="buy",
97
95
  amount=0.01,
98
96
  price=ticker_data["ask"],
99
97
  )
98
+ trade = algorithm.get_trade(order_id=order.id)
99
+ algorithm.add_trailing_stop_loss(trade=trade, percentage=5)
100
100
 
101
101
  # Close a trade
102
- algorithm.close_trade(trades[0].id)
102
+ algorithm.close_trade(trade=trade)
103
103
 
104
104
  # Close a position
105
- algorithm.close_position(positions[0].get_symbol())
105
+ position = algorithm.get_position(symbol="BTC/EUR")
106
+ algorithm.close_position(position)
106
107
 
107
108
  if __name__ == "__main__":
108
109
  app.run()
@@ -114,7 +115,14 @@ if __name__ == "__main__":
114
115
 
115
116
  The framework also supports backtesting and performing backtest experiments. After a backtest, you can print a report that shows the performance of your trading bot.
116
117
 
117
- To run a single backtest you can use the example code that can be found [here](./examples/backtest).
118
+ To run a single backtest you can use the example code that can be found [here](./examples/backtest_example). Simply run:
119
+
120
+ > Its assumed here that you have cloned the repository, installed the framework and
121
+ > are in the root of the project.
122
+
123
+ ```bash
124
+ python examples/backtest_example/run_backtest.py
125
+ ```
118
126
 
119
127
  ### Backtesting report
120
128
 
@@ -12,7 +12,7 @@ from investing_algorithm_framework.domain import ApiException, \
12
12
  RESERVED_BALANCES, APP_MODE, AppMode, DATETIME_FORMAT, \
13
13
  load_backtest_report, BacktestDateRange, convert_polars_to_pandas, \
14
14
  DateRange, get_backtest_report, DEFAULT_LOGGING_CONFIG, \
15
- BacktestReport
15
+ BacktestReport, TradeStatus, MarketDataType
16
16
  from investing_algorithm_framework.infrastructure import \
17
17
  CCXTOrderBookMarketDataSource, CCXTOHLCVMarketDataSource, \
18
18
  CCXTTickerMarketDataSource, CSVOHLCVMarketDataSource, \
@@ -90,5 +90,7 @@ __all__ = [
90
90
  "get_backtest_report",
91
91
  "AzureBlobStorageStateHandler",
92
92
  "DEFAULT_LOGGING_CONFIG",
93
- "BacktestReport"
93
+ "BacktestReport",
94
+ "TradeStatus",
95
+ "MarketDataType"
94
96
  ]
@@ -4,7 +4,7 @@ from typing import List, Dict
4
4
  import re
5
5
 
6
6
  from investing_algorithm_framework.domain import OrderStatus, \
7
- Position, Order, Portfolio, OrderType, OrderSide, \
7
+ Position, Order, Portfolio, OrderType, OrderSide, TradeStatus, \
8
8
  BACKTESTING_FLAG, BACKTESTING_INDEX_DATETIME, MarketService, TimeUnit, \
9
9
  OperationalException, random_string, RoundingService, Trade
10
10
  from investing_algorithm_framework.services import MarketCredentialService, \
@@ -61,7 +61,7 @@ class Algorithm:
61
61
  self.market_service: MarketService
62
62
  self.configuration_service: ConfigurationService
63
63
  self.portfolio_configuration_service: PortfolioConfigurationService
64
- self.strategy_orchestrator_service: StrategyOrchestratorService
64
+ self.strategy_orchestrator_service: StrategyOrchestratorService = None
65
65
  self._data_sources = {}
66
66
  self._strategies = []
67
67
  self._market_credential_service: MarketCredentialService
@@ -94,12 +94,21 @@ class Algorithm:
94
94
  )
95
95
 
96
96
  pattern = re.compile(r"^[a-zA-Z0-9]*$")
97
+
97
98
  if not pattern.match(name):
98
99
  raise OperationalException(
99
100
  "The name of the algorithm can only contain" +
100
101
  " letters and numbers"
101
102
  )
102
103
 
104
+ illegal_chars = r"[\/:*?\"<>|]"
105
+
106
+ if re.search(illegal_chars, name):
107
+ raise OperationalException(
108
+ f"Illegal characters detected in algorithm: {name}. "
109
+ f"Illegal characters: / \\ : * ? \" < > |"
110
+ )
111
+
103
112
  def initialize_services(
104
113
  self,
105
114
  configuration_service,
@@ -155,10 +164,28 @@ class Algorithm:
155
164
  number_of_iterations=number_of_iterations
156
165
  )
157
166
 
167
+ def stop(self) -> None:
168
+ """
169
+ Function to stop the algorithm. This function will stop the
170
+ algorithm by stopping all jobs in the strategy orchestrator
171
+ service.
172
+
173
+ Returns:
174
+ None
175
+ """
176
+
177
+ if self.strategy_orchestrator_service is not None:
178
+ self.strategy_orchestrator_service.stop()
179
+
158
180
  @property
159
181
  def name(self):
160
182
  return self._name
161
183
 
184
+ @name.setter
185
+ def name(self, name):
186
+ self._validate_name(name)
187
+ self._name = name
188
+
162
189
  @property
163
190
  def data_sources(self):
164
191
  return self._data_sources
@@ -172,6 +199,14 @@ class Algorithm:
172
199
  """
173
200
  return self.configuration_service.get_config()
174
201
 
202
+ def get_config(self):
203
+ """
204
+ Function to get a config instance. This allows users when
205
+ having access to the algorithm instance also to read the
206
+ configs of the app.
207
+ """
208
+ return self.configuration_service.get_config()
209
+
175
210
  @property
176
211
  def description(self):
177
212
  """
@@ -315,7 +350,7 @@ class Algorithm:
315
350
  order and execute it if the execute parameter is set to True. If the
316
351
  validate parameter is set to True, the order will be validated
317
352
 
318
- Parameters:
353
+ Args:
319
354
  target_symbol: The symbol of the asset to trade
320
355
  price: The price of the asset
321
356
  order_side: The side of the order
@@ -476,7 +511,7 @@ class Algorithm:
476
511
  """
477
512
 
478
513
  if market is None:
479
- return self.portfolio_service.find({})
514
+ return self.portfolio_service.get_all()[0]
480
515
 
481
516
  return self.portfolio_service.find({{"market": market}})
482
517
 
@@ -497,7 +532,7 @@ class Algorithm:
497
532
  If the market parameter is specified, the unallocated balance
498
533
  of the specified market will be returned.
499
534
 
500
- Parameters:
535
+ Args:
501
536
  market: The market of the portfolio
502
537
 
503
538
  Returns:
@@ -507,7 +542,7 @@ class Algorithm:
507
542
  if market:
508
543
  portfolio = self.portfolio_service.find({{"market": market}})
509
544
  else:
510
- portfolio = self.portfolio_service.find({})
545
+ portfolio = self.portfolio_service.get_all()[0]
511
546
 
512
547
  trading_symbol = portfolio.trading_symbol
513
548
  return self.position_service.find(
@@ -539,6 +574,19 @@ class Algorithm:
539
574
  order_side=None,
540
575
  order_type=None
541
576
  ) -> Order:
577
+ """
578
+ Function to retrieve an order.
579
+
580
+ Exception is thrown when no param has been provided.
581
+
582
+ Args:
583
+ reference_id [optional] (int): id given by the external
584
+ market or exchange.
585
+ market [optional] (str): the market that the order was
586
+ executed on.
587
+ target_symbol [optional] (str): the symbol of the asset
588
+ that the order was executed
589
+ """
542
590
  query_params = {}
543
591
 
544
592
  if reference_id:
@@ -563,6 +611,11 @@ class Algorithm:
563
611
  )
564
612
  query_params["position"] = [position.id for position in positions]
565
613
 
614
+ if not query_params:
615
+ raise OperationalException(
616
+ "No parameters provided to get order."
617
+ )
618
+
566
619
  return self.order_service.find(query_params)
567
620
 
568
621
  def get_orders(
@@ -1169,25 +1222,95 @@ class Algorithm:
1169
1222
  query_params["status"] = OrderStatus.OPEN.value
1170
1223
  return self.order_service.exists(query_params)
1171
1224
 
1172
- def check_pending_orders(self):
1225
+ def get_trade(
1226
+ self,
1227
+ target_symbol=None,
1228
+ trading_symbol=None,
1229
+ market=None,
1230
+ portfolio=None,
1231
+ status=None,
1232
+ order_id=None
1233
+ ) -> List[Trade]:
1173
1234
  """
1174
- Function to check pending orders
1235
+ Function to get all trades. This function will return all trades
1236
+ that match the specified query parameters. If the market parameter
1237
+ is specified, the trades with the specified market will be returned.
1238
+
1239
+ Args:
1240
+ market: The market of the asset
1241
+ portfolio: The portfolio of the asset
1242
+ status: The status of the trade
1243
+ order_id: The order id of the trade
1244
+ target_symbol: The symbol of the asset
1245
+ trading_symbol: The trading symbol of the asset
1246
+
1247
+ Returns:
1248
+ List[Trade]: A list of trades that match the query parameters
1175
1249
  """
1176
- self.order_service.check_pending_orders()
1250
+ query_params = {}
1251
+
1252
+ if market is not None:
1253
+ query_params["market"] = market
1254
+
1255
+ if portfolio is not None:
1256
+ query_params["portfolio"] = portfolio
1257
+
1258
+ if status is not None:
1259
+ query_params["status"] = status
1260
+
1261
+ if order_id is not None:
1262
+ query_params["order_id"] = order_id
1263
+
1264
+ if target_symbol is not None:
1265
+ query_params["target_symbol"] = target_symbol
1266
+
1267
+ if trading_symbol is not None:
1268
+ query_params["trading_symbol"] = trading_symbol
1269
+
1270
+ return self.trade_service.find(query_params)
1177
1271
 
1178
- def get_trades(self, market=None) -> List[Trade]:
1272
+ def get_trades(
1273
+ self,
1274
+ target_symbol=None,
1275
+ trading_symbol=None,
1276
+ market=None,
1277
+ portfolio=None,
1278
+ status=None,
1279
+ ) -> List[Trade]:
1179
1280
  """
1180
1281
  Function to get all trades. This function will return all trades
1181
1282
  that match the specified query parameters. If the market parameter
1182
1283
  is specified, the trades with the specified market will be returned.
1183
1284
 
1184
- Parameters:
1285
+ Args:
1185
1286
  market: The market of the asset
1287
+ portfolio: The portfolio of the asset
1288
+ status: The status of the trade
1289
+ target_symbol: The symbol of the asset
1290
+ trading_symbol: The trading symbol of the asset
1186
1291
 
1187
1292
  Returns:
1188
1293
  List[Trade]: A list of trades that match the query parameters
1189
1294
  """
1190
- return self.trade_service.get_trades(market)
1295
+
1296
+ query_params = {}
1297
+
1298
+ if market is not None:
1299
+ query_params["market"] = market
1300
+
1301
+ if portfolio is not None:
1302
+ query_params["portfolio"] = portfolio
1303
+
1304
+ if status is not None:
1305
+ query_params["status"] = status
1306
+
1307
+ if target_symbol is not None:
1308
+ query_params["target_symbol"] = target_symbol
1309
+
1310
+ if trading_symbol is not None:
1311
+ query_params["trading_symbol"] = trading_symbol
1312
+
1313
+ return self.trade_service.get_all({"market": market})
1191
1314
 
1192
1315
  def get_closed_trades(self) -> List[Trade]:
1193
1316
  """
@@ -1197,7 +1320,44 @@ class Algorithm:
1197
1320
  Returns:
1198
1321
  List[Trade]: A list of closed trades
1199
1322
  """
1200
- return self.trade_service.get_closed_trades()
1323
+ return self.trade_service.get_all({"status": TradeStatus.CLOSED.value})
1324
+
1325
+ def count_trades(
1326
+ self,
1327
+ target_symbol=None,
1328
+ trading_symbol=None,
1329
+ market=None,
1330
+ portfolio=None
1331
+ ) -> int:
1332
+ """
1333
+ Function to count trades. This function will return the number of
1334
+ trades that match the specified query parameters.
1335
+
1336
+ Args:
1337
+ target_symbol: The symbol of the asset
1338
+ trading_symbol: The trading symbol of the asset
1339
+ market: The market of the asset
1340
+ portfolio: The portfolio of the asset
1341
+
1342
+ Returns:
1343
+ int: The number of trades that match the query parameters
1344
+ """
1345
+
1346
+ query_params = {}
1347
+
1348
+ if market is not None:
1349
+ query_params["market"] = market
1350
+
1351
+ if portfolio is not None:
1352
+ query_params["portfolio"] = portfolio
1353
+
1354
+ if target_symbol is not None:
1355
+ query_params["target_symbol"] = target_symbol
1356
+
1357
+ if trading_symbol is not None:
1358
+ query_params["trading_symbol"] = trading_symbol
1359
+
1360
+ return self.trade_service.count(query_params)
1201
1361
 
1202
1362
  def get_open_trades(self, target_symbol=None, market=None) -> List[Trade]:
1203
1363
  """
@@ -1208,32 +1368,107 @@ class Algorithm:
1208
1368
  is specified, the open trades with the specified market will be
1209
1369
  returned.
1210
1370
 
1211
- Parameters:
1371
+ Args:
1212
1372
  target_symbol: The symbol of the asset
1213
1373
  market: The market of the asset
1214
1374
 
1215
1375
  Returns:
1216
1376
  List[Trade]: A list of open trades that match the query parameters
1217
1377
  """
1218
- return self.trade_service.get_open_trades(target_symbol, market)
1378
+ return self.trade_service.get_all(
1379
+ {
1380
+ "status": TradeStatus.OPEN.value,
1381
+ "target_symbol": target_symbol,
1382
+ "market": market
1383
+ }
1384
+ )
1219
1385
 
1220
- def close_trade(self, trade, market=None, precision=None) -> None:
1386
+ def add_stop_loss(self, trade, percentage: int) -> None:
1387
+ """
1388
+ Function to add a stop loss to a trade. This function will add a
1389
+ stop loss to the specified trade. If the stop loss is triggered,
1390
+ the trade will be closed.
1391
+
1392
+ Args:
1393
+ trade: Trade - The trade to add the stop loss to
1394
+ percentage: int - The stop loss of the trade
1395
+
1396
+ Returns:
1397
+ None
1398
+ """
1399
+ self.trade_service.add_stop_loss(trade, percentage=percentage)
1400
+
1401
+ def add_trailing_stop_loss(self, trade, percentage: int) -> None:
1402
+ """
1403
+ Function to add a trailing stop loss to a trade. This function will
1404
+ add a trailing stop loss to the specified trade. If the trailing
1405
+ stop loss is triggered, the trade will be closed.
1406
+
1407
+ Args:
1408
+ trade: Trade - The trade to add the trailing stop loss to
1409
+ trailing_stop_loss: float - The trailing stop loss of the trade
1410
+
1411
+ Returns:
1412
+ None
1413
+ """
1414
+ self.trade_service.add_trailing_stop_loss(trade, percentage=percentage)
1415
+
1416
+ def close_trade(self, trade, precision=None) -> None:
1221
1417
  """
1222
1418
  Function to close a trade. This function will close a trade by
1223
1419
  creating a market order to sell the position. If the precision
1224
1420
  parameter is specified, the amount of the order will be rounded
1225
1421
  down to the specified precision.
1226
1422
 
1227
- Parameters:
1423
+ Args:
1228
1424
  trade: Trade - The trade to close
1229
- market: str - The market of the trade
1230
- precision: float - The precision of the amount
1425
+ precision: int - The precision of the amount
1231
1426
 
1232
1427
  Returns:
1233
1428
  None
1234
1429
  """
1235
- self.trade_service.close_trade(
1236
- trade=trade, market=market, precision=precision
1430
+
1431
+ trade = self.trade_service.get(trade.id)
1432
+
1433
+ if TradeStatus.CLOSED.equals(trade.status):
1434
+ raise OperationalException("Trade already closed.")
1435
+
1436
+ if trade.remaining <= 0:
1437
+ raise OperationalException("Trade has no amount to close.")
1438
+
1439
+ position_id = trade.orders[0].position_id
1440
+ portfolio = self.portfolio_service.find({"position": position_id})
1441
+ position = self.position_service.find(
1442
+ {"portfolio": portfolio.id, "symbol": trade.target_symbol}
1443
+ )
1444
+ amount = trade.remaining
1445
+
1446
+ if precision is not None:
1447
+ amount = RoundingService.round_down(amount, precision)
1448
+
1449
+ if position.get_amount() < amount:
1450
+ logger.warning(
1451
+ f"Order amount {amount} is larger then amount "
1452
+ f"of available {position.symbol} "
1453
+ f"position: {position.get_amount()}, "
1454
+ f"changing order amount to size of position"
1455
+ )
1456
+ amount = position.get_amount()
1457
+
1458
+ ticker = self._market_data_source_service.get_ticker(
1459
+ symbol=trade.symbol, market=portfolio.market
1460
+ )
1461
+
1462
+ self.order_service.create(
1463
+ {
1464
+ "portfolio_id": portfolio.id,
1465
+ "trading_symbol": trade.trading_symbol,
1466
+ "target_symbol": trade.target_symbol,
1467
+ "amount": amount,
1468
+ "order_side": OrderSide.SELL.value,
1469
+ "order_type": OrderType.LIMIT.value,
1470
+ "price": ticker["bid"],
1471
+ }
1237
1472
  )
1238
1473
 
1239
1474
  def get_number_of_positions(self):
@@ -1386,3 +1621,9 @@ class Algorithm:
1386
1621
  [order.get_amount() * order.get_price()
1387
1622
  for order in pending_orders]
1388
1623
  )
1624
+
1625
+ def get_trade_service(self):
1626
+ return self.trade_service
1627
+
1628
+ def get_market_data_source_service(self):
1629
+ return self._market_data_source_service