investing-algorithm-framework 2.4.0__tar.gz → 2.5.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.
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/PKG-INFO +2 -2
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/README.md +1 -1
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/algorithm.py +58 -227
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/app.py +19 -4
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/strategy.py +13 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/dependency_container.py +14 -3
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/__init__.py +2 -2
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/__init__.py +2 -2
- investing_algorithm_framework-2.5.0/investing_algorithm_framework/domain/models/backtesting/__init__.py +6 -0
- investing_algorithm_framework-2.4.0/investing_algorithm_framework/domain/models/backtest_profile.py → investing_algorithm_framework-2.5.0/investing_algorithm_framework/domain/models/backtesting/backtest_report.py +53 -4
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/order/order.py +36 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +1 -1
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/__init__.py +6 -3
- investing_algorithm_framework-2.5.0/investing_algorithm_framework/services/backtesting/__init__.py +8 -0
- investing_algorithm_framework-2.5.0/investing_algorithm_framework/services/backtesting/backtest_report_writer_service.py +37 -0
- {investing_algorithm_framework-2.4.0/investing_algorithm_framework/services → investing_algorithm_framework-2.5.0/investing_algorithm_framework/services/backtesting}/backtest_service.py +43 -20
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/market_data_source_service/backtest_market_data_source_service.py +16 -14
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/order_service/order_service.py +5 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/portfolio_service/portfolio_service.py +3 -1
- investing_algorithm_framework-2.5.0/investing_algorithm_framework/services/trade_service/__init__.py +3 -0
- investing_algorithm_framework-2.5.0/investing_algorithm_framework/services/trade_service/trade_service.py +283 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/pyproject.toml +1 -1
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/LICENSE +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/stateless/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/stateless/action_handlers/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/stateless/exception_handler.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/task.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/web/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/web/controllers/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/web/controllers/orders.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/web/controllers/portfolio.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/web/controllers/positions.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/web/create_app.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/web/error_handler.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/web/responses.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/web/run_strategies.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/web/schemas/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/web/schemas/order.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/web/schemas/portfolio.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/web/schemas/position.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/app/web/setup_cors.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/create_app.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/config.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/constants.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/data_structures.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/decimal_parsing.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/exceptions.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/base_model.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/market/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/market/market_credential.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/order/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/order/order_fee.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/order/order_side.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/order/order_status.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/order/order_type.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/portfolio/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/portfolio/portfolio.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/position/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/position/position.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/position/position_snapshot.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/strategy_profile.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/time_frame.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/time_interval.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/time_unit.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/trade.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/trading_data_types.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/models/trading_time_frame.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/services/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/services/market_data_sources.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/services/market_service.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/singleton.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/stateless_actions.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/strategy.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/utils/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/utils/backtesting.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/utils/csv.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/utils/random.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/utils/signatures.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/utils/stoppable_thread.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/domain/utils/synchronized.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/database/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/database/sql_alchemy.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/decimal_parser.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/ccxt.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/csv.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/model_extension.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/order/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/order/order.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/order/order_fee.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/portfolio/portfolio.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/position/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/position/position.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/repositories/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/repositories/order_fee_repository.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/repositories/order_repository.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/repositories/position_repository.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/repositories/repository.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/services/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/services/market_service/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/services/market_service/ccxt_market_service.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/services/performance_service/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/services/performance_service/backtest_performance_service.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/infrastructure/services/performance_service/performance_service.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/configuration_service.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/market_credential_service.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/market_data_source_service/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/market_data_source_service/market_data_source_service.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/order_service/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/order_service/order_backtest_service.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/portfolio_configuration_service.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/portfolio_service/__init__.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/portfolio_service/backtest_portfolio_service.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/portfolio_snapshot_service.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/position_service.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/position_snapshot_service.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/repository_service.py +0 -0
- {investing_algorithm_framework-2.4.0 → investing_algorithm_framework-2.5.0}/investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: investing-algorithm-framework
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
4
4
|
Summary: A framework for creating trading bots
|
|
5
5
|
Author: MDUYN
|
|
6
6
|
Requires-Python: >=3.8.1,<4.0.0
|
|
@@ -36,7 +36,7 @@ Description-Content-Type: text/markdown
|
|
|
36
36
|
###### Sponsors
|
|
37
37
|
<p align="left">
|
|
38
38
|
<a href="https://finterion.com">
|
|
39
|
-
<img alt="Finterion" src="
|
|
39
|
+
<img alt="Finterion" src="static/sponsors/finterion.png" width="200px" />
|
|
40
40
|
</a>
|
|
41
41
|
</p>
|
|
42
42
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
###### Sponsors
|
|
10
10
|
<p align="left">
|
|
11
11
|
<a href="https://finterion.com">
|
|
12
|
-
<img alt="Finterion" src="
|
|
12
|
+
<img alt="Finterion" src="static/sponsors/finterion.png" width="200px" />
|
|
13
13
|
</a>
|
|
14
14
|
</p>
|
|
15
15
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
import decimal
|
|
2
|
+
import logging
|
|
3
3
|
from typing import List
|
|
4
4
|
|
|
5
5
|
from investing_algorithm_framework.domain import OrderStatus, OrderFee, \
|
|
6
6
|
Position, Order, Portfolio, OrderType, OrderSide, ApiException, \
|
|
7
|
-
BACKTESTING_FLAG, BACKTESTING_INDEX_DATETIME,
|
|
8
|
-
MarketService
|
|
7
|
+
BACKTESTING_FLAG, BACKTESTING_INDEX_DATETIME, MarketService
|
|
9
8
|
from investing_algorithm_framework.services import MarketCredentialService, \
|
|
10
|
-
MarketDataSourceService
|
|
9
|
+
MarketDataSourceService, PortfolioService, PositionService, TradeService, \
|
|
10
|
+
OrderService, ConfigurationService, StrategyOrchestratorService, \
|
|
11
|
+
PortfolioConfigurationService
|
|
11
12
|
|
|
12
13
|
logger = logging.getLogger("investing_algorithm_framework")
|
|
13
14
|
|
|
@@ -24,21 +25,26 @@ class Algorithm:
|
|
|
24
25
|
market_service,
|
|
25
26
|
strategy_orchestrator_service,
|
|
26
27
|
market_credential_service,
|
|
27
|
-
market_data_source_service
|
|
28
|
+
market_data_source_service,
|
|
29
|
+
trade_service
|
|
28
30
|
):
|
|
29
|
-
self.portfolio_service = portfolio_service
|
|
30
|
-
self.position_service = position_service
|
|
31
|
-
self.order_service = order_service
|
|
32
|
-
self.
|
|
33
|
-
self.configuration_service
|
|
34
|
-
|
|
35
|
-
self.
|
|
31
|
+
self.portfolio_service: PortfolioService = portfolio_service
|
|
32
|
+
self.position_service: PositionService = position_service
|
|
33
|
+
self.order_service: OrderService = order_service
|
|
34
|
+
self.market_service: MarketService = market_service
|
|
35
|
+
self.configuration_service: ConfigurationService \
|
|
36
|
+
= configuration_service
|
|
37
|
+
self.portfolio_configuration_service: PortfolioConfigurationService \
|
|
38
|
+
= portfolio_configuration_service
|
|
39
|
+
self.strategy_orchestrator_service: StrategyOrchestratorService \
|
|
40
|
+
= strategy_orchestrator_service
|
|
36
41
|
self._market_data_sources = {}
|
|
37
42
|
self._strategies = []
|
|
38
43
|
self._market_credential_service: MarketCredentialService \
|
|
39
44
|
= market_credential_service
|
|
40
45
|
self._market_data_source_service: MarketDataSourceService \
|
|
41
46
|
= market_data_source_service
|
|
47
|
+
self.trade_service: TradeService = trade_service
|
|
42
48
|
|
|
43
49
|
def start(self, number_of_iterations=None, stateless=False):
|
|
44
50
|
|
|
@@ -158,14 +164,14 @@ class Algorithm:
|
|
|
158
164
|
)
|
|
159
165
|
|
|
160
166
|
def create_market_order(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
self,
|
|
168
|
+
target_symbol,
|
|
169
|
+
order_side,
|
|
170
|
+
amount,
|
|
171
|
+
market=None,
|
|
172
|
+
execute=False,
|
|
173
|
+
validate=False,
|
|
174
|
+
sync=True
|
|
169
175
|
):
|
|
170
176
|
|
|
171
177
|
if market is None:
|
|
@@ -221,13 +227,13 @@ class Algorithm:
|
|
|
221
227
|
self._running_workers = []
|
|
222
228
|
|
|
223
229
|
def get_order(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
230
|
+
self,
|
|
231
|
+
reference_id=None,
|
|
232
|
+
market=None,
|
|
233
|
+
target_symbol=None,
|
|
234
|
+
trading_symbol=None,
|
|
235
|
+
order_side=None,
|
|
236
|
+
order_type=None
|
|
231
237
|
) -> Order:
|
|
232
238
|
query_params = {}
|
|
233
239
|
|
|
@@ -256,12 +262,12 @@ class Algorithm:
|
|
|
256
262
|
return self.order_service.find(query_params)
|
|
257
263
|
|
|
258
264
|
def get_orders(
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
+
self,
|
|
266
|
+
target_symbol=None,
|
|
267
|
+
status=None,
|
|
268
|
+
order_type=None,
|
|
269
|
+
order_side=None,
|
|
270
|
+
market=None
|
|
265
271
|
) -> List[Order]:
|
|
266
272
|
|
|
267
273
|
if market is None:
|
|
@@ -284,13 +290,13 @@ class Algorithm:
|
|
|
284
290
|
return self.order_service.get_order_fee(order_id)
|
|
285
291
|
|
|
286
292
|
def get_positions(
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
293
|
+
self,
|
|
294
|
+
market=None,
|
|
295
|
+
identifier=None,
|
|
296
|
+
amount_gt=None,
|
|
297
|
+
amount_gte=None,
|
|
298
|
+
amount_lt=None,
|
|
299
|
+
amount_lte=None
|
|
294
300
|
) -> List[Position]:
|
|
295
301
|
query_params = {}
|
|
296
302
|
|
|
@@ -346,14 +352,14 @@ class Algorithm:
|
|
|
346
352
|
return None
|
|
347
353
|
|
|
348
354
|
def has_position(
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
355
|
+
self,
|
|
356
|
+
symbol,
|
|
357
|
+
market=None,
|
|
358
|
+
identifier=None,
|
|
359
|
+
amount_gt=0,
|
|
360
|
+
amount_gte=None,
|
|
361
|
+
amount_lt=None,
|
|
362
|
+
amount_lte=None
|
|
357
363
|
):
|
|
358
364
|
return self.position_exists(
|
|
359
365
|
symbol,
|
|
@@ -675,55 +681,10 @@ class Algorithm:
|
|
|
675
681
|
self.order_service.check_pending_orders()
|
|
676
682
|
|
|
677
683
|
def get_trades(self, market=None):
|
|
678
|
-
|
|
679
|
-
trades = []
|
|
680
|
-
|
|
681
|
-
for portfolio in portfolios:
|
|
682
|
-
buy_orders = self.order_service.get_all({
|
|
683
|
-
"status": OrderStatus.CLOSED.value,
|
|
684
|
-
"order_side": OrderSide.BUY.value,
|
|
685
|
-
"portfolio_id": portfolio.id
|
|
686
|
-
})
|
|
687
|
-
|
|
688
|
-
for buy_order in buy_orders:
|
|
689
|
-
symbol = buy_order.get_symbol()
|
|
690
|
-
ticker = self._market_data_source_service.get_ticker(
|
|
691
|
-
symbol=symbol, market=market
|
|
692
|
-
)
|
|
693
|
-
trades.append(
|
|
694
|
-
Trade(
|
|
695
|
-
buy_order_id=buy_order.id,
|
|
696
|
-
target_symbol=buy_order.get_target_symbol(),
|
|
697
|
-
trading_symbol=buy_order.get_trading_symbol(),
|
|
698
|
-
amount=buy_order.get_amount(),
|
|
699
|
-
open_price=buy_order.get_price(),
|
|
700
|
-
closed_price=buy_order.get_trade_closed_price(),
|
|
701
|
-
closed_at=buy_order.get_trade_closed_at(),
|
|
702
|
-
opened_at=buy_order.get_created_at(),
|
|
703
|
-
current_price=ticker["bid"]
|
|
704
|
-
)
|
|
705
|
-
)
|
|
706
|
-
|
|
707
|
-
return trades
|
|
684
|
+
return self.trade_service.get_trades(market)
|
|
708
685
|
|
|
709
686
|
def get_closed_trades(self):
|
|
710
|
-
|
|
711
|
-
"status": OrderStatus.CLOSED.value,
|
|
712
|
-
"order_side": OrderSide.BUY.value
|
|
713
|
-
})
|
|
714
|
-
return [
|
|
715
|
-
Trade(
|
|
716
|
-
buy_order_id=order.id,
|
|
717
|
-
target_symbol=order.get_target_symbol(),
|
|
718
|
-
trading_symbol=order.get_trading_symbol(),
|
|
719
|
-
amount=order.get_amount(),
|
|
720
|
-
open_price=order.get_price(),
|
|
721
|
-
closed_price=order.get_trade_closed_price(),
|
|
722
|
-
closed_at=order.get_trade_closed_at(),
|
|
723
|
-
opened_at=order.get_created_at()
|
|
724
|
-
) for order in buy_orders
|
|
725
|
-
if order.get_trade_closed_at() is not None
|
|
726
|
-
]
|
|
687
|
+
return self.trade_service.get_closed_trades()
|
|
727
688
|
|
|
728
689
|
def round_down(self, value, amount_of_decimals):
|
|
729
690
|
|
|
@@ -743,140 +704,10 @@ class Algorithm:
|
|
|
743
704
|
return 0
|
|
744
705
|
|
|
745
706
|
def get_open_trades(self, target_symbol=None, market=None):
|
|
746
|
-
|
|
747
|
-
trades = []
|
|
748
|
-
|
|
749
|
-
for portfolio in portfolios:
|
|
750
|
-
|
|
751
|
-
if target_symbol is not None:
|
|
752
|
-
buy_orders = self.order_service.get_all({
|
|
753
|
-
"status": OrderStatus.CLOSED.value,
|
|
754
|
-
"order_side": OrderSide.BUY.value,
|
|
755
|
-
"portfolio_id": portfolio.id,
|
|
756
|
-
"target_symbol": target_symbol
|
|
757
|
-
})
|
|
758
|
-
sell_orders = self.order_service.get_all({
|
|
759
|
-
"status": OrderStatus.OPEN.value,
|
|
760
|
-
"order_side": OrderSide.SELL.value,
|
|
761
|
-
"portfolio_id": portfolio.id,
|
|
762
|
-
"target_symbol": target_symbol
|
|
763
|
-
})
|
|
764
|
-
else:
|
|
765
|
-
buy_orders = self.order_service.get_all({
|
|
766
|
-
"status": OrderStatus.CLOSED.value,
|
|
767
|
-
"order_side": OrderSide.BUY.value,
|
|
768
|
-
"portfolio_id": portfolio.id
|
|
769
|
-
})
|
|
770
|
-
sell_orders = self.order_service.get_all({
|
|
771
|
-
"status": OrderStatus.OPEN.value,
|
|
772
|
-
"order_side": OrderSide.SELL.value,
|
|
773
|
-
"portfolio_id": portfolio.id
|
|
774
|
-
})
|
|
775
|
-
|
|
776
|
-
buy_orders = [
|
|
777
|
-
buy_order for buy_order in buy_orders
|
|
778
|
-
if buy_order.get_trade_closed_at() is None
|
|
779
|
-
]
|
|
780
|
-
sell_amount = sum([order.amount for order in sell_orders])
|
|
781
|
-
|
|
782
|
-
# Subtract the amount of the open sell orders
|
|
783
|
-
# from the amount of the buy orders
|
|
784
|
-
buy_orders_queue = PeekableQueue()
|
|
785
|
-
|
|
786
|
-
for buy_order in buy_orders:
|
|
787
|
-
buy_orders_queue.enqueue(buy_order)
|
|
788
|
-
|
|
789
|
-
while sell_amount > 0 and not buy_orders_queue.is_empty():
|
|
790
|
-
first_buy_order = buy_orders_queue.peek()
|
|
791
|
-
available = first_buy_order.get_filled() \
|
|
792
|
-
- first_buy_order.get_trade_closed_amount()
|
|
793
|
-
|
|
794
|
-
if available > sell_amount:
|
|
795
|
-
remaining = available - sell_amount
|
|
796
|
-
sell_amount = 0
|
|
797
|
-
first_buy_order.set_filled(remaining)
|
|
798
|
-
else:
|
|
799
|
-
sell_amount = sell_amount - available
|
|
800
|
-
buy_orders_queue.dequeue()
|
|
801
|
-
|
|
802
|
-
for buy_order in buy_orders_queue:
|
|
803
|
-
symbol = buy_order.get_symbol()
|
|
804
|
-
|
|
805
|
-
try:
|
|
806
|
-
ticker = self._market_data_source_service.get_ticker(
|
|
807
|
-
symbol=symbol, market=market
|
|
808
|
-
)
|
|
809
|
-
except Exception as e:
|
|
810
|
-
logger.error(e)
|
|
811
|
-
raise ApiException(
|
|
812
|
-
f"Error getting ticker data for "
|
|
813
|
-
f"trade {buy_order.get_target_symbol()}"
|
|
814
|
-
f"-{buy_order.get_trading_symbol()}. Make sure you "
|
|
815
|
-
f"have registered a ticker market data source for "
|
|
816
|
-
f"{buy_order.get_target_symbol()}"
|
|
817
|
-
f"-{buy_order.get_trading_symbol()} "
|
|
818
|
-
f"for market {portfolio.market}"
|
|
819
|
-
)
|
|
820
|
-
|
|
821
|
-
amount = buy_order.get_filled()
|
|
822
|
-
closed_amount = buy_order.get_trade_closed_amount()
|
|
823
|
-
|
|
824
|
-
if closed_amount is not None:
|
|
825
|
-
amount = amount - closed_amount
|
|
826
|
-
|
|
827
|
-
trades.append(
|
|
828
|
-
Trade(
|
|
829
|
-
buy_order_id=buy_order.id,
|
|
830
|
-
target_symbol=buy_order.get_target_symbol(),
|
|
831
|
-
trading_symbol=buy_order.get_trading_symbol(),
|
|
832
|
-
amount=amount,
|
|
833
|
-
open_price=buy_order.get_price(),
|
|
834
|
-
opened_at=buy_order.get_created_at(),
|
|
835
|
-
current_price=ticker["bid"]
|
|
836
|
-
)
|
|
837
|
-
)
|
|
838
|
-
|
|
839
|
-
return trades
|
|
707
|
+
return self.trade_service.get_open_trades(target_symbol, market)
|
|
840
708
|
|
|
841
709
|
def close_trade(self, trade, market=None):
|
|
842
|
-
|
|
843
|
-
if trade.closed_at is not None:
|
|
844
|
-
raise ApiException("Trade already closed.")
|
|
845
|
-
|
|
846
|
-
order = self.order_service.get(trade.buy_order_id)
|
|
847
|
-
|
|
848
|
-
if order.get_filled() <= 0:
|
|
849
|
-
raise ApiException(
|
|
850
|
-
"Buy order belonging to the trade has no amount."
|
|
851
|
-
)
|
|
852
|
-
|
|
853
|
-
portfolio = self.portfolio_service\
|
|
854
|
-
.find({"position": order.position_id})
|
|
855
|
-
position = self.position_service.find(
|
|
856
|
-
{"portfolio": portfolio.id, "symbol": order.get_target_symbol()}
|
|
857
|
-
)
|
|
858
|
-
amount = order.get_amount()
|
|
859
|
-
|
|
860
|
-
if position.get_amount() < amount:
|
|
861
|
-
logger.warning(
|
|
862
|
-
f"Order amount {amount} is larger then amount "
|
|
863
|
-
f"of available {position.symbol} "
|
|
864
|
-
f"position: {position.get_amount()}, "
|
|
865
|
-
f"changing order amount to size of position"
|
|
866
|
-
)
|
|
867
|
-
amount = position.get_amount()
|
|
868
|
-
|
|
869
|
-
symbol = f"{order.get_target_symbol().upper()}" \
|
|
870
|
-
f"/{order.get_trading_symbol().upper()}"
|
|
871
|
-
ticker = self._market_data_source_service.get_ticker(
|
|
872
|
-
symbol=symbol, market=market
|
|
873
|
-
)
|
|
874
|
-
self.create_limit_order(
|
|
875
|
-
target_symbol=order.target_symbol,
|
|
876
|
-
amount=amount,
|
|
877
|
-
order_side=OrderSide.SELL.value,
|
|
878
|
-
price=ticker["bid"],
|
|
879
|
-
)
|
|
710
|
+
self.trade_service.close_trade(trade, market)
|
|
880
711
|
|
|
881
712
|
def get_number_of_positions(self):
|
|
882
713
|
"""
|
|
@@ -17,7 +17,7 @@ from investing_algorithm_framework.app.web import create_flask_app
|
|
|
17
17
|
from investing_algorithm_framework.domain import DATABASE_NAME, TimeUnit, \
|
|
18
18
|
DATABASE_DIRECTORY_PATH, RESOURCE_DIRECTORY, ENVIRONMENT, Environment, \
|
|
19
19
|
SQLALCHEMY_DATABASE_URI, OperationalException, BACKTESTING_FLAG, \
|
|
20
|
-
BACKTESTING_START_DATE,
|
|
20
|
+
BACKTESTING_START_DATE, BACKTESTING_END_DATE, \
|
|
21
21
|
BACKTESTING_PENDING_ORDER_CHECK_INTERVAL
|
|
22
22
|
from investing_algorithm_framework.infrastructure import setup_sqlalchemy, \
|
|
23
23
|
create_all_tables
|
|
@@ -40,7 +40,6 @@ class App:
|
|
|
40
40
|
self._strategies = []
|
|
41
41
|
self._tasks = []
|
|
42
42
|
self._configuration_service = None
|
|
43
|
-
self._market_service: MarketService = None
|
|
44
43
|
self._market_data_source_service: MarketDataSourceService = None
|
|
45
44
|
self._market_credential_service: MarketCredentialService = None
|
|
46
45
|
|
|
@@ -50,7 +49,6 @@ class App:
|
|
|
50
49
|
|
|
51
50
|
def initialize_services(self):
|
|
52
51
|
self._configuration_service = self.container.configuration_service()
|
|
53
|
-
self._market_service = self.container.market_service()
|
|
54
52
|
self._market_data_source_service = \
|
|
55
53
|
self.container.market_data_source_service()
|
|
56
54
|
self._market_credential_service = \
|
|
@@ -559,7 +557,11 @@ class App:
|
|
|
559
557
|
return self.algorithm.get_portfolio_configurations()
|
|
560
558
|
|
|
561
559
|
def backtest(
|
|
562
|
-
self,
|
|
560
|
+
self,
|
|
561
|
+
start_date,
|
|
562
|
+
end_date,
|
|
563
|
+
pending_order_check_interval='1h',
|
|
564
|
+
output_directory=None
|
|
563
565
|
):
|
|
564
566
|
logger.info("Initializing backtest")
|
|
565
567
|
|
|
@@ -578,6 +580,19 @@ class App:
|
|
|
578
580
|
report = backtest_service.backtest(
|
|
579
581
|
self.algorithm, start_date, end_date
|
|
580
582
|
)
|
|
583
|
+
backtest_report_writer_service = self.container\
|
|
584
|
+
.backtest_report_writer_service()
|
|
585
|
+
|
|
586
|
+
if output_directory is None:
|
|
587
|
+
output_directory = os.path.join(
|
|
588
|
+
self.config.get(RESOURCE_DIRECTORY),
|
|
589
|
+
"backtest_reports"
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
backtest_report_writer_service.write_report_to_csv(
|
|
593
|
+
report=report, output_directory=output_directory
|
|
594
|
+
)
|
|
595
|
+
|
|
581
596
|
return report
|
|
582
597
|
|
|
583
598
|
def add_market_data_source(self, market_data_source):
|
|
@@ -7,11 +7,13 @@ class TradingStrategy:
|
|
|
7
7
|
time_unit: str = None
|
|
8
8
|
interval: int = None
|
|
9
9
|
worker_id: str = None
|
|
10
|
+
strategy_id: str = None
|
|
10
11
|
decorated = None
|
|
11
12
|
market_data_sources = None
|
|
12
13
|
|
|
13
14
|
def __init__(
|
|
14
15
|
self,
|
|
16
|
+
strategy_id=None,
|
|
15
17
|
time_unit=None,
|
|
16
18
|
interval=None,
|
|
17
19
|
market_data_sources=None,
|
|
@@ -41,6 +43,9 @@ class TradingStrategy:
|
|
|
41
43
|
else:
|
|
42
44
|
self.worker_id = self.__class__.__name__
|
|
43
45
|
|
|
46
|
+
if strategy_id is not None:
|
|
47
|
+
self.strategy_id = strategy_id
|
|
48
|
+
|
|
44
49
|
def run_strategy(self, algorithm, market_data):
|
|
45
50
|
self.apply_strategy(algorithm=algorithm, market_data=market_data)
|
|
46
51
|
|
|
@@ -105,3 +110,11 @@ class TradingStrategy:
|
|
|
105
110
|
|
|
106
111
|
def on_trade_take_profit_created(self, algorithm: Algorithm, trade: Trade):
|
|
107
112
|
pass
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def strategy_identifier(self):
|
|
116
|
+
|
|
117
|
+
if self.strategy_id is not None:
|
|
118
|
+
return self.strategy_id
|
|
119
|
+
|
|
120
|
+
return self.worker_id
|
|
@@ -7,9 +7,9 @@ from investing_algorithm_framework.infrastructure import SQLOrderRepository, \
|
|
|
7
7
|
SQLPositionSnapshotRepository, PerformanceService, CCXTMarketService
|
|
8
8
|
from investing_algorithm_framework.services import OrderService, \
|
|
9
9
|
PositionService, PortfolioService, StrategyOrchestratorService, \
|
|
10
|
-
PortfolioConfigurationService, MarketDataSourceService,
|
|
10
|
+
PortfolioConfigurationService, MarketDataSourceService, BacktestService, \
|
|
11
11
|
ConfigurationService, PortfolioSnapshotService, PositionSnapshotService, \
|
|
12
|
-
MarketCredentialService
|
|
12
|
+
MarketCredentialService, TradeService, BacktestReportWriterService
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def setup_dependency_container(app, modules=None, packages=None):
|
|
@@ -88,6 +88,13 @@ class DependencyContainer(containers.DeclarativeContainer):
|
|
|
88
88
|
portfolio_configuration_service=portfolio_configuration_service,
|
|
89
89
|
portfolio_snapshot_service=portfolio_snapshot_service,
|
|
90
90
|
)
|
|
91
|
+
trade_service = providers.Factory(
|
|
92
|
+
TradeService,
|
|
93
|
+
portfolio_service=portfolio_service,
|
|
94
|
+
order_service=order_service,
|
|
95
|
+
market_data_source_service=market_data_source_service,
|
|
96
|
+
position_service=position_service,
|
|
97
|
+
)
|
|
91
98
|
strategy_orchestrator_service = providers.Factory(
|
|
92
99
|
StrategyOrchestratorService,
|
|
93
100
|
market_data_source_service=market_data_source_service
|
|
@@ -99,13 +106,16 @@ class DependencyContainer(containers.DeclarativeContainer):
|
|
|
99
106
|
portfolio_repository=portfolio_repository
|
|
100
107
|
)
|
|
101
108
|
backtest_service = providers.Factory(
|
|
102
|
-
|
|
109
|
+
BacktestService,
|
|
103
110
|
order_service=order_service,
|
|
104
111
|
portfolio_repository=portfolio_repository,
|
|
105
112
|
performance_service=performance_service,
|
|
106
113
|
position_repository=position_repository,
|
|
107
114
|
market_data_source_service=market_data_source_service,
|
|
108
115
|
)
|
|
116
|
+
backtest_report_writer_service = providers.Factory(
|
|
117
|
+
BacktestReportWriterService,
|
|
118
|
+
)
|
|
109
119
|
algorithm = providers.Factory(
|
|
110
120
|
Algorithm,
|
|
111
121
|
configuration_service=configuration_service,
|
|
@@ -117,4 +127,5 @@ class DependencyContainer(containers.DeclarativeContainer):
|
|
|
117
127
|
market_credential_service=market_credential_service,
|
|
118
128
|
market_data_source_service=market_data_source_service,
|
|
119
129
|
market_service=market_service,
|
|
130
|
+
trade_service=trade_service,
|
|
120
131
|
)
|
|
@@ -2,7 +2,7 @@ from .config import Config, Environment
|
|
|
2
2
|
from .models import OrderStatus, OrderSide, OrderType, TimeInterval, \
|
|
3
3
|
TimeUnit, TimeFrame, TradingTimeFrame, TradingDataType, \
|
|
4
4
|
PortfolioConfiguration, Portfolio, Position, Order, \
|
|
5
|
-
OrderFee,
|
|
5
|
+
OrderFee, BacktestReport, PortfolioSnapshot, StrategyProfile, \
|
|
6
6
|
BacktestPosition, Trade, MarketCredential, PositionSnapshot
|
|
7
7
|
from .exceptions import OperationalException, ApiException, \
|
|
8
8
|
PermissionDeniedApiException, ImproperlyConfigured
|
|
@@ -70,7 +70,7 @@ __all__ = [
|
|
|
70
70
|
"OrderFee",
|
|
71
71
|
"parse_decimal_to_string",
|
|
72
72
|
"parse_string_to_decimal",
|
|
73
|
-
"
|
|
73
|
+
"BacktestReport",
|
|
74
74
|
"pretty_print_backtest",
|
|
75
75
|
"DATETIME_FORMAT_BACKTESTING",
|
|
76
76
|
"BACKTESTING_FLAG",
|
|
@@ -7,7 +7,7 @@ from .trading_data_types import TradingDataType
|
|
|
7
7
|
from .trading_time_frame import TradingTimeFrame
|
|
8
8
|
from .portfolio import PortfolioConfiguration, Portfolio, PortfolioSnapshot
|
|
9
9
|
from .position import Position, PositionSnapshot
|
|
10
|
-
from .
|
|
10
|
+
from .backtesting import BacktestReport, BacktestPosition
|
|
11
11
|
from .strategy_profile import StrategyProfile
|
|
12
12
|
from .trade import Trade
|
|
13
13
|
|
|
@@ -25,7 +25,7 @@ __all__ = [
|
|
|
25
25
|
"Position",
|
|
26
26
|
"Portfolio",
|
|
27
27
|
"OrderFee",
|
|
28
|
-
"
|
|
28
|
+
"BacktestReport",
|
|
29
29
|
"PositionSnapshot",
|
|
30
30
|
"PortfolioSnapshot",
|
|
31
31
|
"StrategyProfile",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
from
|
|
2
|
-
from .
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from investing_algorithm_framework.domain.models.base_model import BaseModel
|
|
3
|
+
from investing_algorithm_framework.domain.models.time_unit import TimeUnit
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
class BacktestPosition(BaseModel):
|
|
@@ -97,10 +98,11 @@ class BacktestPosition(BaseModel):
|
|
|
97
98
|
return self.value / self._total_value_portfolio * 100
|
|
98
99
|
|
|
99
100
|
|
|
100
|
-
class
|
|
101
|
+
class BacktestReport(BaseModel):
|
|
101
102
|
|
|
102
103
|
def __init__(
|
|
103
104
|
self,
|
|
105
|
+
identifier=None,
|
|
104
106
|
portfolio_id=None,
|
|
105
107
|
initial_unallocated=0.0,
|
|
106
108
|
interval=None,
|
|
@@ -132,8 +134,10 @@ class BacktestProfile(BaseModel):
|
|
|
132
134
|
positions=None,
|
|
133
135
|
average_trade_duration=0,
|
|
134
136
|
average_trade_size=0.0,
|
|
135
|
-
trades=None
|
|
137
|
+
trades=None,
|
|
138
|
+
created_at: datetime = None
|
|
136
139
|
):
|
|
140
|
+
self._identifier = identifier
|
|
137
141
|
self._portfolio_id = portfolio_id
|
|
138
142
|
self._interval = interval
|
|
139
143
|
self._time_unit = time_unit
|
|
@@ -169,6 +173,15 @@ class BacktestProfile(BaseModel):
|
|
|
169
173
|
self._average_trade_duration = average_trade_duration
|
|
170
174
|
self._average_trade_size = average_trade_size
|
|
171
175
|
self._trades = trades
|
|
176
|
+
self._created_at: datetime = created_at
|
|
177
|
+
|
|
178
|
+
@property
|
|
179
|
+
def identifier(self):
|
|
180
|
+
return self._identifier
|
|
181
|
+
|
|
182
|
+
@property
|
|
183
|
+
def created_at(self):
|
|
184
|
+
return self._created_at
|
|
172
185
|
|
|
173
186
|
@property
|
|
174
187
|
def portfolio_id(self):
|
|
@@ -454,3 +467,39 @@ class BacktestProfile(BaseModel):
|
|
|
454
467
|
time_unit=self.time_unit,
|
|
455
468
|
interval=self.interval
|
|
456
469
|
)
|
|
470
|
+
|
|
471
|
+
def to_dict(self):
|
|
472
|
+
return {
|
|
473
|
+
"portfolio_id": self.portfolio_id,
|
|
474
|
+
"interval": self.interval,
|
|
475
|
+
"time_unit": self.time_unit,
|
|
476
|
+
"backtest_start_date_data": self.backtest_start_date_data,
|
|
477
|
+
"backtest_start_date": self.backtest_start_date,
|
|
478
|
+
"backtest_end_date": self.backtest_end_date,
|
|
479
|
+
"backtest_index_date": self.backtest_index_date,
|
|
480
|
+
"number_of_runs": self.number_of_runs,
|
|
481
|
+
"trading_time_frame": self.trading_time_frame,
|
|
482
|
+
"trading_time_frame_start_date":
|
|
483
|
+
self.trading_time_frame_start_date,
|
|
484
|
+
"symbols": self.symbols,
|
|
485
|
+
"market": self.market,
|
|
486
|
+
"number_of_days": self.number_of_days,
|
|
487
|
+
"number_of_orders": self.number_of_orders,
|
|
488
|
+
"number_of_positions": self.number_of_positions,
|
|
489
|
+
"market_data_file": self.market_data_file,
|
|
490
|
+
"percentage_positive_trades": self.percentage_positive_trades,
|
|
491
|
+
"percentage_negative_trades": self.percentage_negative_trades,
|
|
492
|
+
"number_of_trades_closed": self.number_of_trades_closed,
|
|
493
|
+
"number_of_trades_open": self.number_of_trades_open,
|
|
494
|
+
"total_cost": self.total_cost,
|
|
495
|
+
"growth_rate": self.growth_rate,
|
|
496
|
+
"growth": self.growth,
|
|
497
|
+
"initial_unallocated": self.initial_unallocated,
|
|
498
|
+
"trading_symbol": self.trading_symbol,
|
|
499
|
+
"total_net_gain_percentage": self.total_net_gain_percentage,
|
|
500
|
+
"total_net_gain": self.total_net_gain,
|
|
501
|
+
"backtest_data_index_date": self.backtest_data_index_date,
|
|
502
|
+
"total_value": self.total_value,
|
|
503
|
+
"average_trade_duration": self.average_trade_duration,
|
|
504
|
+
"average_trade_size": self.average_trade_size,
|
|
505
|
+
}
|