investing-algorithm-framework 3.3.0__tar.gz → 3.4.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 (142) hide show
  1. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/PKG-INFO +1 -1
  2. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/algorithm.py +11 -24
  3. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/app.py +7 -0
  4. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/dependency_container.py +2 -0
  5. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/__init__.py +4 -2
  6. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/config.py +1 -0
  7. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/order/order.py +1 -5
  8. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/services/__init__.py +3 -1
  9. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/services/market_data_sources.py +21 -7
  10. investing_algorithm_framework-3.4.0/investing_algorithm_framework/domain/services/rounding_service.py +27 -0
  11. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/ccxt.py +36 -15
  12. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/services/market_service/ccxt_market_service.py +26 -12
  13. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/backtesting/backtest_service.py +5 -2
  14. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/market_data_source_service/backtest_market_data_source_service.py +1 -0
  15. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/order_service/order_backtest_service.py +0 -3
  16. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/order_service/order_service.py +2 -0
  17. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/trade_service/trade_service.py +9 -5
  18. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/pyproject.toml +1 -1
  19. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/LICENSE +0 -0
  20. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/README.md +0 -0
  21. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/__init__.py +0 -0
  22. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/__init__.py +0 -0
  23. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/stateless/__init__.py +0 -0
  24. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/stateless/action_handlers/__init__.py +0 -0
  25. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +0 -0
  26. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +0 -0
  27. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +0 -0
  28. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/stateless/exception_handler.py +0 -0
  29. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/strategy.py +0 -0
  30. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/task.py +0 -0
  31. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/web/__init__.py +0 -0
  32. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/web/controllers/__init__.py +0 -0
  33. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/web/controllers/orders.py +0 -0
  34. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/web/controllers/portfolio.py +0 -0
  35. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/web/controllers/positions.py +0 -0
  36. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/web/create_app.py +0 -0
  37. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/web/error_handler.py +0 -0
  38. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/web/responses.py +0 -0
  39. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/web/run_strategies.py +0 -0
  40. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/web/schemas/__init__.py +0 -0
  41. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/web/schemas/order.py +0 -0
  42. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/web/schemas/portfolio.py +0 -0
  43. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/web/schemas/position.py +0 -0
  44. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/app/web/setup_cors.py +0 -0
  45. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/create_app.py +0 -0
  46. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/constants.py +0 -0
  47. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/data_structures.py +0 -0
  48. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/decimal_parsing.py +0 -0
  49. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/exceptions.py +0 -0
  50. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/__init__.py +0 -0
  51. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/app_mode.py +0 -0
  52. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/backtesting/__init__.py +0 -0
  53. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/backtesting/backtest_position.py +0 -0
  54. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/backtesting/backtest_report.py +0 -0
  55. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/backtesting/backtest_reports_evaluation.py +0 -0
  56. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/base_model.py +0 -0
  57. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/market/__init__.py +0 -0
  58. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/market/market_credential.py +0 -0
  59. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/order/__init__.py +0 -0
  60. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/order/order_fee.py +0 -0
  61. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/order/order_side.py +0 -0
  62. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/order/order_status.py +0 -0
  63. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/order/order_type.py +0 -0
  64. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/portfolio/__init__.py +0 -0
  65. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/portfolio/portfolio.py +0 -0
  66. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +0 -0
  67. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +0 -0
  68. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/position/__init__.py +0 -0
  69. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/position/position.py +0 -0
  70. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/position/position_snapshot.py +0 -0
  71. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/strategy_profile.py +0 -0
  72. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/time_frame.py +0 -0
  73. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/time_interval.py +0 -0
  74. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/time_unit.py +0 -0
  75. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/trade/__init__.py +0 -0
  76. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/trade/trade.py +0 -0
  77. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/trade/trade_status.py +0 -0
  78. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/trading_data_types.py +0 -0
  79. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/models/trading_time_frame.py +0 -0
  80. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/services/market_credential_service.py +0 -0
  81. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/services/market_service.py +0 -0
  82. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/services/portfolios/__init__.py +0 -0
  83. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +0 -0
  84. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/singleton.py +0 -0
  85. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/stateless_actions.py +0 -0
  86. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/strategy.py +0 -0
  87. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/utils/__init__.py +0 -0
  88. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/utils/backtesting.py +0 -0
  89. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/utils/csv.py +0 -0
  90. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/utils/random.py +0 -0
  91. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/utils/signatures.py +0 -0
  92. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/utils/stoppable_thread.py +0 -0
  93. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/domain/utils/synchronized.py +0 -0
  94. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/__init__.py +0 -0
  95. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/database/__init__.py +0 -0
  96. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/database/sql_alchemy.py +0 -0
  97. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/__init__.py +0 -0
  98. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/decimal_parser.py +0 -0
  99. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/__init__.py +0 -0
  100. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/csv.py +0 -0
  101. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/model_extension.py +0 -0
  102. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/order/__init__.py +0 -0
  103. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/order/order.py +0 -0
  104. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/order/order_fee.py +0 -0
  105. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +0 -0
  106. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/portfolio/portfolio.py +0 -0
  107. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +0 -0
  108. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/position/__init__.py +0 -0
  109. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/position/position.py +0 -0
  110. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +0 -0
  111. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/repositories/__init__.py +0 -0
  112. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/repositories/order_fee_repository.py +0 -0
  113. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/repositories/order_repository.py +0 -0
  114. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +0 -0
  115. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +0 -0
  116. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/repositories/position_repository.py +0 -0
  117. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +0 -0
  118. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/repositories/repository.py +0 -0
  119. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/services/__init__.py +0 -0
  120. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/services/market_service/__init__.py +0 -0
  121. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/services/performance_service/__init__.py +0 -0
  122. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/services/performance_service/backtest_performance_service.py +0 -0
  123. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/infrastructure/services/performance_service/performance_service.py +0 -0
  124. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/__init__.py +0 -0
  125. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/backtesting/__init__.py +0 -0
  126. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/backtesting/backtest_report_writer_service.py +0 -0
  127. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/configuration_service.py +0 -0
  128. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/market_credential_service.py +0 -0
  129. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/market_data_source_service/__init__.py +0 -0
  130. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/market_data_source_service/market_data_source_service.py +0 -0
  131. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/order_service/__init__.py +0 -0
  132. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/portfolios/__init__.py +0 -0
  133. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +0 -0
  134. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/portfolios/portfolio_configuration_service.py +0 -0
  135. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/portfolios/portfolio_service.py +0 -0
  136. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +0 -0
  137. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +0 -0
  138. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/position_service.py +0 -0
  139. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/position_snapshot_service.py +0 -0
  140. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/repository_service.py +0 -0
  141. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -0
  142. {investing_algorithm_framework-3.3.0 → investing_algorithm_framework-3.4.0}/investing_algorithm_framework/services/trade_service/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: investing-algorithm-framework
3
- Version: 3.3.0
3
+ Version: 3.4.0
4
4
  Summary: A framework for creating trading bots
5
5
  Author: MDUYN
6
6
  Requires-Python: >=3.8.1,<4.0.0
@@ -1,12 +1,11 @@
1
- import decimal
1
+ import inspect
2
2
  import logging
3
3
  from typing import List
4
- import inspect
5
4
 
6
5
  from investing_algorithm_framework.domain import OrderStatus, OrderFee, \
7
6
  Position, Order, Portfolio, OrderType, OrderSide, \
8
7
  BACKTESTING_FLAG, BACKTESTING_INDEX_DATETIME, MarketService, TimeUnit, \
9
- OperationalException, random_string
8
+ OperationalException, random_string, RoundingService
10
9
  from investing_algorithm_framework.services import MarketCredentialService, \
11
10
  MarketDataSourceService, PortfolioService, PositionService, TradeService, \
12
11
  OrderService, ConfigurationService, StrategyOrchestratorService, \
@@ -218,7 +217,7 @@ class Algorithm:
218
217
  amount = position.get_amount() * (percentage_of_position / 100)
219
218
 
220
219
  if precision is not None:
221
- amount = self.round_down(amount, precision)
220
+ amount = RoundingService.round_down(amount, precision)
222
221
 
223
222
  order_data = {
224
223
  "target_symbol": target_symbol,
@@ -594,7 +593,9 @@ class Algorithm:
594
593
  net_size = portfolio.get_net_size()
595
594
  return (position.cost / net_size) * 100
596
595
 
597
- def close_position(self, symbol, market=None, identifier=None):
596
+ def close_position(
597
+ self, symbol, market=None, identifier=None, precision=None
598
+ ):
598
599
  portfolio = self.portfolio_service.find(
599
600
  {"market": market, "identifier": identifier}
600
601
  )
@@ -623,6 +624,7 @@ class Algorithm:
623
624
  amount=position.get_amount(),
624
625
  order_side=OrderSide.SELL.value,
625
626
  price=ticker["bid"],
627
+ precision=precision,
626
628
  )
627
629
 
628
630
  def add_strategies(self, strategies):
@@ -886,28 +888,13 @@ class Algorithm:
886
888
  def get_closed_trades(self):
887
889
  return self.trade_service.get_closed_trades()
888
890
 
889
- def round_down(self, value, amount_of_decimals):
890
-
891
- if self.count_decimals(value) <= amount_of_decimals:
892
- return value
893
-
894
- with decimal.localcontext() as ctx:
895
- d = decimal.Decimal(value)
896
- ctx.rounding = decimal.ROUND_DOWN
897
- return float(round(d, amount_of_decimals))
898
-
899
- def count_decimals(self, number):
900
- decimal_str = str(number)
901
- if '.' in decimal_str:
902
- return len(decimal_str.split('.')[1])
903
- else:
904
- return 0
905
-
906
891
  def get_open_trades(self, target_symbol=None, market=None):
907
892
  return self.trade_service.get_open_trades(target_symbol, market)
908
893
 
909
- def close_trade(self, trade, market=None):
910
- self.trade_service.close_trade(trade, market)
894
+ def close_trade(self, trade, market=None, precision=None) -> None:
895
+ self.trade_service.close_trade(
896
+ trade=trade, market=market, precision=precision
897
+ )
911
898
 
912
899
  def get_number_of_positions(self):
913
900
  """
@@ -278,7 +278,13 @@ class App:
278
278
  backtest_market_data_sources = [
279
279
  market_data_source.to_backtest_market_data_source()
280
280
  for market_data_source in market_data_sources
281
+ if market_data_source is not None
281
282
  ]
283
+
284
+ for market_data_source in backtest_market_data_sources:
285
+ if market_data_source is not None:
286
+ market_data_source.config = self.config
287
+
282
288
  self.container.market_data_source_service.override(
283
289
  BacktestMarketDataSourceService(
284
290
  market_data_sources=backtest_market_data_sources,
@@ -787,6 +793,7 @@ class App:
787
793
  return reports
788
794
 
789
795
  def add_market_data_source(self, market_data_source):
796
+ market_data_source.config = self.config
790
797
  self._market_data_source_service.add(market_data_source)
791
798
 
792
799
  def add_market_credential(self, market_credential: MarketCredential):
@@ -68,6 +68,7 @@ class DependencyContainer(containers.DeclarativeContainer):
68
68
  )
69
69
  order_service = providers.Factory(
70
70
  OrderService,
71
+ configuration_service=configuration_service,
71
72
  order_repository=order_repository,
72
73
  order_fee_repository=order_fee_repository,
73
74
  portfolio_repository=portfolio_repository,
@@ -125,6 +126,7 @@ class DependencyContainer(containers.DeclarativeContainer):
125
126
  )
126
127
  backtest_service = providers.Factory(
127
128
  BacktestService,
129
+ configuration_service=configuration_service,
128
130
  order_service=order_service,
129
131
  portfolio_repository=portfolio_repository,
130
132
  performance_service=performance_service,
@@ -26,7 +26,8 @@ from .stateless_actions import StatelessActions
26
26
  from .decimal_parsing import parse_decimal_to_string, parse_string_to_decimal
27
27
  from .services import TickerMarketDataSource, OrderBookMarketDataSource, \
28
28
  OHLCVMarketDataSource, BacktestMarketDataSource, MarketDataSource, \
29
- MarketService, MarketCredentialService, AbstractPortfolioSyncService
29
+ MarketService, MarketCredentialService, AbstractPortfolioSyncService, \
30
+ RoundingService
30
31
  from .data_structures import PeekableQueue
31
32
 
32
33
  __all__ = [
@@ -109,5 +110,6 @@ __all__ = [
109
110
  "RESERVED_BALANCES",
110
111
  "AbstractPortfolioSyncService",
111
112
  "APP_MODE",
112
- "AppMode"
113
+ "AppMode",
114
+ "RoundingService",
113
115
  ]
@@ -77,6 +77,7 @@ class Config(dict):
77
77
  SQLITE_INITIALIZED = False
78
78
  BACKTEST_DATA_DIRECTORY_NAME = "backtest_data"
79
79
  SYMBOLS = None
80
+ DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
80
81
 
81
82
  def __init__(self, resource_directory=None):
82
83
  super().__init__()
@@ -1,7 +1,6 @@
1
1
  import logging
2
2
 
3
3
  from dateutil.parser import parse
4
- from dateutil.tz import gettz
5
4
 
6
5
  from investing_algorithm_framework.domain.exceptions import \
7
6
  OperationalException
@@ -308,10 +307,7 @@ class Order(BaseModel):
308
307
  remaining=ccxt_order.get("remaining", None),
309
308
  cost=ccxt_order.get("cost", None),
310
309
  fee=OrderFee.from_ccxt_fee(ccxt_order.get("fee", None)),
311
- created_at=parse(
312
- ccxt_order.get("datetime", None),
313
- tzinfos={"UTC": gettz("UTC")}
314
- )
310
+ created_at=parse(ccxt_order.get("datetime", None))
315
311
  )
316
312
 
317
313
  def __repr__(self):
@@ -3,6 +3,7 @@ from .market_data_sources import MarketDataSource, TickerMarketDataSource, \
3
3
  from .market_service import MarketService
4
4
  from .market_credential_service import MarketCredentialService
5
5
  from .portfolios import AbstractPortfolioSyncService
6
+ from .rounding_service import RoundingService
6
7
 
7
8
  __all__ = [
8
9
  "MarketDataSource",
@@ -12,5 +13,6 @@ __all__ = [
12
13
  "BacktestMarketDataSource",
13
14
  "MarketService",
14
15
  "MarketCredentialService",
15
- "AbstractPortfolioSyncService"
16
+ "AbstractPortfolioSyncService",
17
+ "RoundingService",
16
18
  ]
@@ -34,6 +34,14 @@ class BacktestMarketDataSource(ABC):
34
34
  self._backtest_data_start_date = backtest_data_start_date
35
35
  self._backtest_data_index_date = backtest_data_index_date
36
36
 
37
+ @property
38
+ def config(self):
39
+ return self._config
40
+
41
+ @config.setter
42
+ def config(self, value):
43
+ self._config = value
44
+
37
45
  def _data_source_exists(self, file_path):
38
46
  """
39
47
  Function to check if the data source exists.
@@ -60,9 +68,7 @@ class BacktestMarketDataSource(ABC):
60
68
  return False
61
69
 
62
70
  return True
63
- except Exception as e:
64
- logger.error(f"Error reading {file_path}")
65
- logger.error(e)
71
+ except Exception:
66
72
  return False
67
73
 
68
74
  def write_data_to_file_path(self, data_file, data):
@@ -151,10 +157,10 @@ class BacktestMarketDataSource(ABC):
151
157
  class MarketDataSource(ABC):
152
158
 
153
159
  def __init__(
154
- self,
155
- identifier,
156
- market,
157
- symbol,
160
+ self,
161
+ identifier,
162
+ market,
163
+ symbol,
158
164
  ):
159
165
  self._identifier = identifier
160
166
  self._market = market
@@ -168,6 +174,14 @@ class MarketDataSource(ABC):
168
174
  def identifier(self):
169
175
  return self._identifier
170
176
 
177
+ @property
178
+ def config(self):
179
+ return self._config
180
+
181
+ @config.setter
182
+ def config(self, value):
183
+ self._config = value
184
+
171
185
  def get_identifier(self):
172
186
  return self.identifier
173
187
 
@@ -0,0 +1,27 @@
1
+ import decimal
2
+
3
+
4
+ class RoundingService:
5
+ """
6
+ Service to round numbers to a certain amount of decimals.
7
+ It will always round down.
8
+ """
9
+
10
+ @staticmethod
11
+ def round_down(value, amount_of_decimals):
12
+
13
+ if RoundingService.count_decimals(value) <= amount_of_decimals:
14
+ return value
15
+
16
+ with decimal.localcontext() as ctx:
17
+ d = decimal.Decimal(value)
18
+ ctx.rounding = decimal.ROUND_DOWN
19
+ return float(round(d, amount_of_decimals))
20
+
21
+ @staticmethod
22
+ def count_decimals(number):
23
+ decimal_str = str(number)
24
+ if '.' in decimal_str:
25
+ return len(decimal_str.split('.')[1])
26
+ else:
27
+ return 0
@@ -3,6 +3,7 @@ import os
3
3
  from datetime import timedelta
4
4
 
5
5
  import polars
6
+ from dateutil import parser
6
7
 
7
8
  from investing_algorithm_framework.domain import RESOURCE_DIRECTORY, \
8
9
  BACKTEST_DATA_DIRECTORY_NAME, DATETIME_FORMAT_BACKTESTING, \
@@ -59,7 +60,7 @@ class CCXTOHLCVBacktestMarketDataSource(
59
60
  start_date_func=start_date_func,
60
61
  end_date=end_date,
61
62
  end_date_func=end_date_func,
62
- window_size=window_size
63
+ window_size=window_size,
63
64
  )
64
65
 
65
66
  def prepare_data(
@@ -80,7 +81,6 @@ class CCXTOHLCVBacktestMarketDataSource(
80
81
  When downloading the data it will use the ccxt library.
81
82
  """
82
83
  # Calculating the backtest data start date
83
-
84
84
  difference = self.end_date - self.start_date
85
85
  total_minutes = 0
86
86
 
@@ -127,7 +127,10 @@ class CCXTOHLCVBacktestMarketDataSource(
127
127
  )
128
128
 
129
129
  # Get the OHLCV data from the ccxt market service
130
- market_service = CCXTMarketService(self.market_credential_service)
130
+ market_service = CCXTMarketService(
131
+ market_credential_service=self.market_credential_service,
132
+ )
133
+ market_service.config = config
131
134
  ohlcv = market_service.get_ohlcv(
132
135
  symbol=self.symbol,
133
136
  time_frame=self.timeframe,
@@ -171,6 +174,7 @@ class CCXTOHLCVBacktestMarketDataSource(
171
174
  from_timestamp = backtest_index_date - timedelta(
172
175
  minutes=self.total_minutes_timeframe
173
176
  )
177
+ datetime_format = self._config["DATETIME_FORMAT"]
174
178
  self.backtest_data_index_date = backtest_index_date\
175
179
  .replace(microsecond=0)
176
180
  from_timestamp = from_timestamp.replace(microsecond=0)
@@ -193,8 +197,8 @@ class CCXTOHLCVBacktestMarketDataSource(
193
197
  file_path, columns=self.column_names, separator=","
194
198
  )
195
199
  df = df.filter(
196
- (df['Datetime'] >= from_timestamp.strftime(DATETIME_FORMAT))
197
- & (df['Datetime'] <= to_timestamp.strftime(DATETIME_FORMAT))
200
+ (df['Datetime'] >= from_timestamp.strftime(datetime_format))
201
+ & (df['Datetime'] <= to_timestamp.strftime(datetime_format))
198
202
  )
199
203
  return df
200
204
 
@@ -209,6 +213,9 @@ class CCXTOHLCVBacktestMarketDataSource(
209
213
  def file_name(self):
210
214
  return self._create_file_path().split("/")[-1]
211
215
 
216
+ def write_data_to_file_path(self, data_file, data: polars.DataFrame):
217
+ data.write_csv(data_file)
218
+
212
219
 
213
220
  class CCXTTickerBacktestMarketDataSource(
214
221
  TickerMarketDataSource, BacktestMarketDataSource
@@ -304,7 +311,10 @@ class CCXTTickerBacktestMarketDataSource(
304
311
  )
305
312
 
306
313
  # Get the OHLCV data from the ccxt market service
307
- market_service = CCXTMarketService(self.market_credential_service)
314
+ market_service = CCXTMarketService(
315
+ market_credential_service=self.market_credential_service
316
+ )
317
+ market_service.config = config
308
318
  ohlcv = market_service.get_ohlcv(
309
319
  symbol=self.symbol,
310
320
  time_frame=self.timeframe,
@@ -363,13 +373,12 @@ class CCXTTickerBacktestMarketDataSource(
363
373
  # Filter the data based on the backtest index date and the end date
364
374
  df = polars.read_csv(file_path)
365
375
  df = df.filter(
366
- (df['Datetime'] >= backtest_index_date
367
- .strftime(DATETIME_FORMAT))
376
+ (df['Datetime'] >= backtest_index_date.strftime(DATETIME_FORMAT))
368
377
  )
369
-
370
378
  first_row = df.head(1)[0]
379
+ first_row_datetime = parser.parse(first_row["Datetime"][0])
371
380
 
372
- if first_row["Datetime"][0] > end_date.strftime(DATETIME_FORMAT):
381
+ if first_row_datetime > end_date:
373
382
  logger.warning(
374
383
  f"No ticker data available for the given backtest "
375
384
  f"index date {backtest_index_date} and symbol {self.symbol} "
@@ -386,12 +395,17 @@ class CCXTTickerBacktestMarketDataSource(
386
395
  "datetime": first_row["Datetime"][0],
387
396
  }
388
397
 
398
+ def write_data_to_file_path(self, data_file, data: polars.DataFrame):
399
+ data.write_csv(data_file)
400
+
389
401
 
390
402
  class CCXTOHLCVMarketDataSource(OHLCVMarketDataSource):
391
403
 
392
404
  def get_data(self, **kwargs):
393
- market_service = CCXTMarketService(self.market_credential_service)
394
-
405
+ market_service = CCXTMarketService(
406
+ market_credential_service=self.market_credential_service,
407
+ )
408
+ market_service.config = self.config
395
409
  if self.start_date is None:
396
410
  raise OperationalException(
397
411
  "Either start_date or start_date_func should be set "
@@ -422,7 +436,10 @@ class CCXTOHLCVMarketDataSource(OHLCVMarketDataSource):
422
436
  class CCXTOrderBookMarketDataSource(OrderBookMarketDataSource):
423
437
 
424
438
  def get_data(self, **kwargs):
425
- market_service = CCXTMarketService(self.market_credential_service)
439
+ market_service = CCXTMarketService(
440
+ market_credential_service=self.market_credential_service
441
+ )
442
+ market_service.config = self.config
426
443
  return market_service.get_order_book(
427
444
  symbol=self.symbol, market=self.market
428
445
  )
@@ -438,7 +455,8 @@ class CCXTTickerMarketDataSource(TickerMarketDataSource):
438
455
  identifier,
439
456
  market,
440
457
  symbol=None,
441
- backtest_timeframe=None
458
+ backtest_timeframe=None,
459
+
442
460
  ):
443
461
  super().__init__(
444
462
  identifier=identifier,
@@ -448,7 +466,10 @@ class CCXTTickerMarketDataSource(TickerMarketDataSource):
448
466
  self._backtest_timeframe = backtest_timeframe
449
467
 
450
468
  def get_data(self, **kwargs):
451
- market_service = CCXTMarketService(self.market_credential_service)
469
+ market_service = CCXTMarketService(
470
+ market_credential_service=self.market_credential_service
471
+ )
472
+ market_service.config = self.config
452
473
 
453
474
  if self.market is None:
454
475
 
@@ -1,14 +1,14 @@
1
1
  import logging
2
- from typing import Dict
3
2
  from datetime import datetime
4
3
  from time import sleep
5
- import polars as pl
4
+ from typing import Dict
5
+
6
6
  import ccxt
7
+ import polars as pl
7
8
  from dateutil import parser
8
- from dateutil.tz import gettz
9
9
 
10
10
  from investing_algorithm_framework.domain import OperationalException, Order, \
11
- CCXT_DATETIME_FORMAT, MarketService
11
+ MarketService
12
12
 
13
13
  logger = logging.getLogger(__name__)
14
14
 
@@ -20,6 +20,19 @@ class CCXTMarketService(MarketService):
20
20
  msec = 1000
21
21
  minute = 60 * msec
22
22
 
23
+ def __init__(self, market_credential_service):
24
+ super(CCXTMarketService, self).__init__(
25
+ market_credential_service=market_credential_service,
26
+ )
27
+
28
+ @property
29
+ def config(self):
30
+ return self._config
31
+
32
+ @config.setter
33
+ def config(self, config):
34
+ self._config = config
35
+
23
36
  def initialize_exchange(self, market, market_credential):
24
37
  market = market.lower()
25
38
  if not hasattr(ccxt, market):
@@ -149,6 +162,7 @@ class CCXTMarketService(MarketService):
149
162
  def get_orders(self, symbol, market, since: datetime = None):
150
163
  market_credential = self.get_market_credential(market)
151
164
  exchange = self.initialize_exchange(market, market_credential)
165
+ datetime_format = self.config["DATETIME_FORMAT"]
152
166
 
153
167
  if not exchange.has['fetchOrders']:
154
168
  raise OperationalException(
@@ -157,7 +171,7 @@ class CCXTMarketService(MarketService):
157
171
  )
158
172
 
159
173
  if since is not None:
160
- since = exchange.parse8601(since.strftime(":%Y-%m-%d %H:%M:%S"))
174
+ since = exchange.parse8601(datetime_format)
161
175
 
162
176
  try:
163
177
  ccxt_orders = exchange.fetchOrders(symbol, since=since)
@@ -343,6 +357,7 @@ class CCXTMarketService(MarketService):
343
357
  def get_ohlcv(
344
358
  self, symbol, time_frame, from_timestamp, market, to_timestamp=None
345
359
  ) -> pl.DataFrame:
360
+ datetime_format = self.config["DATETIME_FORMAT"]
346
361
  market_credential = self.get_market_credential(market)
347
362
  exchange = self.initialize_exchange(market, market_credential)
348
363
 
@@ -353,14 +368,14 @@ class CCXTMarketService(MarketService):
353
368
  )
354
369
 
355
370
  from_time_stamp = exchange.parse8601(
356
- from_timestamp.strftime(CCXT_DATETIME_FORMAT)
371
+ from_timestamp.strftime(datetime_format)
357
372
  )
358
373
 
359
374
  if to_timestamp is None:
360
375
  to_timestamp = exchange.milliseconds()
361
376
  else:
362
377
  to_timestamp = exchange.parse8601(
363
- to_timestamp.strftime(CCXT_DATETIME_FORMAT)
378
+ to_timestamp.strftime(datetime_format)
364
379
  )
365
380
  data = []
366
381
 
@@ -374,17 +389,16 @@ class CCXTMarketService(MarketService):
374
389
  from_time_stamp = to_timestamp
375
390
 
376
391
  for candle in ohlcv:
377
- datetime_stamp = parser.parse(
378
- exchange.iso8601(candle[0]),
379
- tzinfos={"UTC": gettz("UTC")}
392
+ datetime_stamp = parser.parse(exchange.iso8601(candle[0]))
380
393
 
381
- )
382
394
  to_timestamp_datetime = parser.parse(
383
395
  exchange.iso8601(to_timestamp),
384
- tzinfos={"UTC": gettz("UTC")}
385
396
  )
386
397
 
387
398
  if datetime_stamp <= to_timestamp_datetime:
399
+ datetime_stamp = datetime_stamp\
400
+ .strftime(datetime_format)
401
+
388
402
  data.append([datetime_stamp] + candle[1:])
389
403
 
390
404
  sleep(exchange.rateLimit / 1000)
@@ -1,5 +1,5 @@
1
1
  from datetime import datetime, timedelta
2
-
2
+ from dateutil import parser
3
3
  import pandas as pd
4
4
  from tqdm import tqdm
5
5
 
@@ -22,6 +22,7 @@ class BacktestService:
22
22
  portfolio_repository,
23
23
  position_repository,
24
24
  performance_service,
25
+ configuration_service
25
26
  ):
26
27
  self._resource_directory = None
27
28
  self._order_service = order_service
@@ -35,6 +36,7 @@ class BacktestService:
35
36
  self._market_data_source_service: MarketDataSourceService \
36
37
  = market_data_source_service
37
38
  self._backtest_market_data_sources = []
39
+ self._configuration_service = configuration_service
38
40
 
39
41
  @property
40
42
  def resource_directory(self):
@@ -96,10 +98,11 @@ class BacktestService:
96
98
  strategy_profile = self.get_strategy_from_strategy_profiles(
97
99
  strategy_profiles, row['id']
98
100
  )
101
+ index_date = parser.parse(str(index))
99
102
  self.run_backtest_for_profile(
100
103
  algorithm=algorithm,
101
104
  strategy=algorithm.get_strategy(strategy_profile.strategy_id),
102
- index_date=index,
105
+ index_date=index_date,
103
106
  )
104
107
  return self.create_backtest_report(
105
108
  algorithm, len(schedule), start_date, end_date, initial_unallocated
@@ -49,6 +49,7 @@ class BacktestMarketDataSourceService(MarketDataSourceService):
49
49
  if backtest_market_data_source is not None:
50
50
  backtest_market_data_source.market_credentials_service = \
51
51
  self._market_credential_service
52
+
52
53
  backtest_market_data_source.prepare_data(
53
54
  config=configuration_service.get_config(),
54
55
  backtest_start_date=configuration_service
@@ -161,9 +161,6 @@ class OrderBacktestService(OrderService):
161
161
  order_side = order.get_order_side()
162
162
  order_price = order.get_price()
163
163
 
164
- # Convert 'created_at' to pandas Timestamp for easier comparison
165
- created_at = pd.Timestamp(created_at, tz='UTC')
166
-
167
164
  # Filter OHLCV data after the order creation time
168
165
  ohlcv_data_after_order = ohlcv_data_frame.loc[created_at:]
169
166
 
@@ -15,6 +15,7 @@ class OrderService(RepositoryService):
15
15
 
16
16
  def __init__(
17
17
  self,
18
+ configuration_service,
18
19
  order_repository,
19
20
  order_fee_repository,
20
21
  market_service: MarketService,
@@ -25,6 +26,7 @@ class OrderService(RepositoryService):
25
26
  market_credential_service
26
27
  ):
27
28
  super(OrderService, self).__init__(order_repository)
29
+ self.configuration_service = configuration_service
28
30
  self.order_repository = order_repository
29
31
  self.order_fee_repository = order_fee_repository
30
32
  self.market_service: MarketService = market_service
@@ -1,14 +1,14 @@
1
1
  import logging
2
- from typing import List
3
2
  from queue import PriorityQueue
3
+ from typing import List
4
4
 
5
5
  from investing_algorithm_framework.domain import OrderStatus, OrderSide, \
6
6
  Trade, PeekableQueue, OrderType, TradeStatus, \
7
- OperationalException, Order
8
- from investing_algorithm_framework.services.position_service import \
9
- PositionService
7
+ OperationalException, Order, RoundingService
10
8
  from investing_algorithm_framework.services.market_data_source_service import \
11
9
  MarketDataSourceService
10
+ from investing_algorithm_framework.services.position_service import \
11
+ PositionService
12
12
 
13
13
  logger = logging.getLogger(__name__)
14
14
 
@@ -199,7 +199,7 @@ class TradeService:
199
199
  if order.get_trade_closed_at() is not None
200
200
  ]
201
201
 
202
- def close_trade(self, trade, market=None) -> None:
202
+ def close_trade(self, trade, market=None, precision=None) -> None:
203
203
  """
204
204
  Close trade method
205
205
 
@@ -210,6 +210,7 @@ class TradeService:
210
210
 
211
211
  return: None
212
212
  """
213
+
213
214
  if trade.closed_at is not None:
214
215
  raise OperationalException("Trade already closed.")
215
216
 
@@ -227,6 +228,9 @@ class TradeService:
227
228
  )
228
229
  amount = order.get_amount()
229
230
 
231
+ if precision is not None:
232
+ amount = RoundingService.round_down(amount, precision)
233
+
230
234
  if position.get_amount() < amount:
231
235
  logger.warning(
232
236
  f"Order amount {amount} is larger then amount "
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "investing-algorithm-framework"
3
- version = "v3.3.0"
3
+ version = "v3.4.0"
4
4
  description = "A framework for creating trading bots"
5
5
  authors = ["MDUYN"]
6
6
  readme = "README.md"