investing-algorithm-framework 3.5.2__tar.gz → 3.6.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-3.5.2 → investing_algorithm_framework-3.6.0}/PKG-INFO +1 -1
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/__init__.py +4 -1
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/algorithm.py +47 -7
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/app.py +17 -9
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/dependency_container.py +1 -3
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/__init__.py +5 -3
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/__init__.py +4 -4
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/backtesting/__init__.py +2 -0
- investing_algorithm_framework-3.6.0/investing_algorithm_framework/domain/models/backtesting/backtest_date_range.py +26 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/backtesting/backtest_position.py +14 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/backtesting/backtest_report.py +35 -17
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/order/__init__.py +1 -2
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/order/order.py +71 -24
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/trade/trade.py +17 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/utils/__init__.py +2 -1
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/utils/backtesting.py +23 -3
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/__init__.py +2 -4
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/models/__init__.py +1 -2
- investing_algorithm_framework-3.6.0/investing_algorithm_framework/infrastructure/models/market_data_sources/us_treasury_yield.py +47 -0
- investing_algorithm_framework-3.6.0/investing_algorithm_framework/infrastructure/models/order/__init__.py +3 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/models/order/order.py +21 -8
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/repositories/__init__.py +0 -2
- investing_algorithm_framework-3.6.0/investing_algorithm_framework/services/backtesting/backtest_report_writer_service.py +75 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/backtesting/backtest_service.py +4 -1
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/order_service/order_backtest_service.py +0 -2
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/order_service/order_service.py +0 -28
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/pyproject.toml +1 -1
- investing_algorithm_framework-3.5.2/investing_algorithm_framework/domain/models/order/order_fee.py +0 -49
- investing_algorithm_framework-3.5.2/investing_algorithm_framework/infrastructure/models/order/__init__.py +0 -4
- investing_algorithm_framework-3.5.2/investing_algorithm_framework/infrastructure/models/order/order_fee.py +0 -21
- investing_algorithm_framework-3.5.2/investing_algorithm_framework/infrastructure/repositories/order_fee_repository.py +0 -15
- investing_algorithm_framework-3.5.2/investing_algorithm_framework/services/backtesting/backtest_report_writer_service.py +0 -42
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/LICENSE +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/README.md +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/stateless/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/stateless/action_handlers/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/stateless/exception_handler.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/strategy.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/task.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/web/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/web/controllers/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/web/controllers/orders.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/web/controllers/portfolio.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/web/controllers/positions.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/web/create_app.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/web/error_handler.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/web/responses.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/web/run_strategies.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/web/schemas/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/web/schemas/order.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/web/schemas/portfolio.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/web/schemas/position.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/app/web/setup_cors.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/create_app.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/config.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/constants.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/data_structures.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/decimal_parsing.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/exceptions.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/app_mode.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/backtesting/backtest_reports_evaluation.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/base_model.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/market/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/market/market_credential.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/order/order_side.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/order/order_status.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/order/order_type.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/portfolio/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/portfolio/portfolio.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/position/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/position/position.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/position/position_snapshot.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/strategy_profile.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/time_frame.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/time_interval.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/time_unit.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/trade/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/trade/trade_status.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/trading_data_types.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/models/trading_time_frame.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/services/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/services/market_credential_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/services/market_data_sources.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/services/market_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/services/portfolios/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/services/rounding_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/singleton.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/stateless_actions.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/strategy.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/utils/csv.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/utils/random.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/utils/signatures.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/utils/stoppable_thread.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/domain/utils/synchronized.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/database/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/database/sql_alchemy.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/models/decimal_parser.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/ccxt.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/csv.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/models/model_extension.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/models/portfolio/portfolio.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/models/position/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/models/position/position.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/repositories/order_repository.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/repositories/position_repository.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/repositories/repository.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/services/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/services/market_service/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/services/market_service/ccxt_market_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/services/performance_service/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/services/performance_service/backtest_performance_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/infrastructure/services/performance_service/performance_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/backtesting/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/configuration_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/market_credential_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/market_data_source_service/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/market_data_source_service/backtest_market_data_source_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/market_data_source_service/market_data_source_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/order_service/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/portfolios/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/portfolios/portfolio_configuration_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/portfolios/portfolio_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/position_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/position_snapshot_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/repository_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/trade_service/__init__.py +0 -0
- {investing_algorithm_framework-3.5.2 → investing_algorithm_framework-3.6.0}/investing_algorithm_framework/services/trade_service/trade_service.py +0 -0
|
@@ -9,7 +9,8 @@ from investing_algorithm_framework.domain import ApiException, \
|
|
|
9
9
|
Trade, OHLCVMarketDataSource, OrderBookMarketDataSource, SYMBOLS, \
|
|
10
10
|
TickerMarketDataSource, MarketService, BacktestReportsEvaluation, \
|
|
11
11
|
pretty_print_backtest_reports_evaluation, load_backtest_reports, \
|
|
12
|
-
RESERVED_BALANCES, APP_MODE, AppMode, DATETIME_FORMAT
|
|
12
|
+
RESERVED_BALANCES, APP_MODE, AppMode, DATETIME_FORMAT, \
|
|
13
|
+
load_backtest_report, BacktestDateRange
|
|
13
14
|
from investing_algorithm_framework.infrastructure import \
|
|
14
15
|
CCXTOrderBookMarketDataSource, CCXTOHLCVMarketDataSource, \
|
|
15
16
|
CCXTTickerMarketDataSource, CSVOHLCVMarketDataSource, \
|
|
@@ -61,4 +62,6 @@ __all__ = [
|
|
|
61
62
|
"APP_MODE",
|
|
62
63
|
"AppMode",
|
|
63
64
|
"DATETIME_FORMAT",
|
|
65
|
+
"load_backtest_report",
|
|
66
|
+
"BacktestDateRange",
|
|
64
67
|
]
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import inspect
|
|
2
2
|
import logging
|
|
3
|
-
from typing import List
|
|
3
|
+
from typing import List, Dict
|
|
4
4
|
|
|
5
|
-
from investing_algorithm_framework.domain import OrderStatus,
|
|
5
|
+
from investing_algorithm_framework.domain import OrderStatus, \
|
|
6
6
|
Position, Order, Portfolio, OrderType, OrderSide, \
|
|
7
7
|
BACKTESTING_FLAG, BACKTESTING_INDEX_DATETIME, MarketService, TimeUnit, \
|
|
8
8
|
OperationalException, random_string, RoundingService
|
|
@@ -16,8 +16,22 @@ logger = logging.getLogger("investing_algorithm_framework")
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class Algorithm:
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
"""
|
|
20
|
+
Class to represent an algorithm. An algorithm is a collection of
|
|
21
|
+
strategies that are executed in a specific order. The algorithm
|
|
22
|
+
class is responsible for managing the strategies and executing
|
|
23
|
+
them in the correct order.
|
|
24
|
+
|
|
25
|
+
:param name: The name of the algorithm
|
|
26
|
+
:param description: The description of the algorithm
|
|
27
|
+
:param context: The context of the algorithm, for backtest references
|
|
28
|
+
"""
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
name: str = None,
|
|
32
|
+
description: str = None,
|
|
33
|
+
context: Dict[str, str] = None
|
|
34
|
+
):
|
|
21
35
|
self._name = name
|
|
22
36
|
|
|
23
37
|
if name is None:
|
|
@@ -28,6 +42,21 @@ class Algorithm:
|
|
|
28
42
|
if description is not None:
|
|
29
43
|
self._description = description
|
|
30
44
|
|
|
45
|
+
self._context = context
|
|
46
|
+
|
|
47
|
+
if self.context is None:
|
|
48
|
+
self._context = {}
|
|
49
|
+
|
|
50
|
+
# Check if the context is a dictionary with only string,
|
|
51
|
+
# float or int values
|
|
52
|
+
for key, value in self.context.items():
|
|
53
|
+
if not isinstance(key, str) or \
|
|
54
|
+
not isinstance(value, (str, float, int)):
|
|
55
|
+
raise OperationalException(
|
|
56
|
+
"The context of the algorithm must be a dictionary with "
|
|
57
|
+
"only string, float or int values."
|
|
58
|
+
)
|
|
59
|
+
|
|
31
60
|
self._strategies = []
|
|
32
61
|
self._tasks = []
|
|
33
62
|
self.portfolio_service: PortfolioService
|
|
@@ -108,6 +137,20 @@ class Algorithm:
|
|
|
108
137
|
"""
|
|
109
138
|
return self.configuration_service.config
|
|
110
139
|
|
|
140
|
+
@property
|
|
141
|
+
def description(self):
|
|
142
|
+
"""
|
|
143
|
+
Function to get the description of the algorithm
|
|
144
|
+
"""
|
|
145
|
+
return self._description
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def context(self):
|
|
149
|
+
"""
|
|
150
|
+
Function to get the context of the algorithm
|
|
151
|
+
"""
|
|
152
|
+
return self._context
|
|
153
|
+
|
|
111
154
|
@property
|
|
112
155
|
def running(self) -> bool:
|
|
113
156
|
"""
|
|
@@ -362,9 +405,6 @@ class Algorithm:
|
|
|
362
405
|
}
|
|
363
406
|
)
|
|
364
407
|
|
|
365
|
-
def get_order_fee(self, order_id) -> OrderFee:
|
|
366
|
-
return self.order_service.get_order_fee(order_id)
|
|
367
|
-
|
|
368
408
|
def get_positions(
|
|
369
409
|
self,
|
|
370
410
|
market=None,
|
|
@@ -7,7 +7,7 @@ from abc import abstractmethod
|
|
|
7
7
|
from datetime import datetime
|
|
8
8
|
from distutils.sysconfig import get_python_lib
|
|
9
9
|
from time import sleep
|
|
10
|
-
from typing import List, Optional
|
|
10
|
+
from typing import List, Optional
|
|
11
11
|
|
|
12
12
|
from flask import Flask
|
|
13
13
|
|
|
@@ -20,7 +20,7 @@ from investing_algorithm_framework.domain import DATABASE_NAME, TimeUnit, \
|
|
|
20
20
|
SQLALCHEMY_DATABASE_URI, OperationalException, BACKTESTING_FLAG, \
|
|
21
21
|
BACKTESTING_START_DATE, BACKTESTING_END_DATE, BacktestReport, \
|
|
22
22
|
BACKTESTING_PENDING_ORDER_CHECK_INTERVAL, APP_MODE, MarketCredential, \
|
|
23
|
-
AppMode
|
|
23
|
+
AppMode, BacktestDateRange
|
|
24
24
|
from investing_algorithm_framework.infrastructure import setup_sqlalchemy, \
|
|
25
25
|
create_all_tables
|
|
26
26
|
from investing_algorithm_framework.services import OrderBacktestService, \
|
|
@@ -319,7 +319,6 @@ class App:
|
|
|
319
319
|
self.container.order_service.override(
|
|
320
320
|
OrderBacktestService(
|
|
321
321
|
order_repository=self.container.order_repository(),
|
|
322
|
-
order_fee_repository=self.container.order_fee_repository(),
|
|
323
322
|
position_repository=self.container.position_repository(),
|
|
324
323
|
portfolio_repository=self.container.portfolio_repository(),
|
|
325
324
|
portfolio_configuration_service=self.container
|
|
@@ -729,7 +728,7 @@ class App:
|
|
|
729
728
|
"backtest_reports"
|
|
730
729
|
)
|
|
731
730
|
|
|
732
|
-
backtest_report_writer_service.
|
|
731
|
+
backtest_report_writer_service.write_report_to_json(
|
|
733
732
|
report=report, output_directory=output_directory
|
|
734
733
|
)
|
|
735
734
|
|
|
@@ -740,7 +739,7 @@ class App:
|
|
|
740
739
|
algorithms,
|
|
741
740
|
start_date: Optional[datetime] = None,
|
|
742
741
|
end_date: Optional[datetime] = None,
|
|
743
|
-
date_ranges: Optional[
|
|
742
|
+
date_ranges: Optional[List[BacktestDateRange]] = None,
|
|
744
743
|
pending_order_check_interval=None,
|
|
745
744
|
output_directory=None
|
|
746
745
|
) -> List[BacktestReport]:
|
|
@@ -754,7 +753,7 @@ class App:
|
|
|
754
753
|
:param end_date: The end date of the backtest
|
|
755
754
|
:param pending_order_check_interval: The interval at which to check
|
|
756
755
|
:param date_ranges: The date ranges to run the backtests for (list of
|
|
757
|
-
|
|
756
|
+
BacktestDateRange instances representing a start and end date)
|
|
758
757
|
pending orders
|
|
759
758
|
:param output_directory: The directory to write the backtest report to
|
|
760
759
|
:return: List of BacktestReport intances
|
|
@@ -767,7 +766,9 @@ class App:
|
|
|
767
766
|
if end_date is None:
|
|
768
767
|
end_date = datetime.utcnow()
|
|
769
768
|
|
|
770
|
-
date_ranges = [
|
|
769
|
+
date_ranges = [
|
|
770
|
+
BacktestDateRange(start_date=start_date, end_date=end_date)
|
|
771
|
+
]
|
|
771
772
|
else:
|
|
772
773
|
if date_ranges is None:
|
|
773
774
|
raise OperationalException("No date ranges specified")
|
|
@@ -776,7 +777,9 @@ class App:
|
|
|
776
777
|
.get_market_data_sources()
|
|
777
778
|
|
|
778
779
|
for date_range in date_ranges:
|
|
779
|
-
|
|
780
|
+
date_range: BacktestDateRange = date_range
|
|
781
|
+
start_date = date_range.start_date
|
|
782
|
+
end_date = date_range.end_date
|
|
780
783
|
self._initialize_app_for_backtest(
|
|
781
784
|
backtest_start_date=start_date,
|
|
782
785
|
backtest_end_date=end_date,
|
|
@@ -804,6 +807,11 @@ class App:
|
|
|
804
807
|
start_date=start_date,
|
|
805
808
|
end_date=end_date
|
|
806
809
|
)
|
|
810
|
+
|
|
811
|
+
# Add date range name to report if present
|
|
812
|
+
if date_range.name is not None:
|
|
813
|
+
report.date_range_name = date_range.name
|
|
814
|
+
|
|
807
815
|
backtest_report_writer_service = self.container \
|
|
808
816
|
.backtest_report_writer_service()
|
|
809
817
|
|
|
@@ -813,7 +821,7 @@ class App:
|
|
|
813
821
|
"backtest_reports"
|
|
814
822
|
)
|
|
815
823
|
|
|
816
|
-
backtest_report_writer_service.
|
|
824
|
+
backtest_report_writer_service.write_report_to_json(
|
|
817
825
|
report=report, output_directory=output_directory
|
|
818
826
|
)
|
|
819
827
|
reports.append(report)
|
|
@@ -3,7 +3,7 @@ from dependency_injector import containers, providers
|
|
|
3
3
|
from investing_algorithm_framework.app.algorithm import Algorithm
|
|
4
4
|
from investing_algorithm_framework.infrastructure import SQLOrderRepository, \
|
|
5
5
|
SQLPositionRepository, SQLPortfolioRepository, \
|
|
6
|
-
|
|
6
|
+
SQLPortfolioSnapshotRepository, \
|
|
7
7
|
SQLPositionSnapshotRepository, PerformanceService, CCXTMarketService
|
|
8
8
|
from investing_algorithm_framework.services import OrderService, \
|
|
9
9
|
PositionService, PortfolioService, StrategyOrchestratorService, \
|
|
@@ -33,7 +33,6 @@ class DependencyContainer(containers.DeclarativeContainer):
|
|
|
33
33
|
MarketCredentialService
|
|
34
34
|
)
|
|
35
35
|
order_repository = providers.Factory(SQLOrderRepository)
|
|
36
|
-
order_fee_repository = providers.Factory(SQLOrderFeeRepository)
|
|
37
36
|
position_repository = providers.Factory(SQLPositionRepository)
|
|
38
37
|
portfolio_repository = providers.Factory(SQLPortfolioRepository)
|
|
39
38
|
position_snapshot_repository = providers.Factory(
|
|
@@ -70,7 +69,6 @@ class DependencyContainer(containers.DeclarativeContainer):
|
|
|
70
69
|
OrderService,
|
|
71
70
|
configuration_service=configuration_service,
|
|
72
71
|
order_repository=order_repository,
|
|
73
|
-
order_fee_repository=order_fee_repository,
|
|
74
72
|
portfolio_repository=portfolio_repository,
|
|
75
73
|
position_repository=position_repository,
|
|
76
74
|
market_service=market_service,
|
|
@@ -15,9 +15,9 @@ from .exceptions import OperationalException, ApiException, \
|
|
|
15
15
|
from .models import OrderStatus, OrderSide, OrderType, TimeInterval, \
|
|
16
16
|
TimeUnit, TimeFrame, TradingTimeFrame, TradingDataType, \
|
|
17
17
|
PortfolioConfiguration, Portfolio, Position, Order, TradeStatus, \
|
|
18
|
-
|
|
18
|
+
BacktestReport, PortfolioSnapshot, StrategyProfile, \
|
|
19
19
|
BacktestPosition, Trade, MarketCredential, PositionSnapshot, \
|
|
20
|
-
BacktestReportsEvaluation, AppMode
|
|
20
|
+
BacktestReportsEvaluation, AppMode, BacktestDateRange
|
|
21
21
|
from .services import TickerMarketDataSource, OrderBookMarketDataSource, \
|
|
22
22
|
OHLCVMarketDataSource, BacktestMarketDataSource, MarketDataSource, \
|
|
23
23
|
MarketService, MarketCredentialService, AbstractPortfolioSyncService, \
|
|
@@ -27,6 +27,7 @@ from .stateless_actions import StatelessActions
|
|
|
27
27
|
from .strategy import Strategy
|
|
28
28
|
from .utils import random_string, append_dict_as_row_to_csv, \
|
|
29
29
|
add_column_headers_to_csv, get_total_amount_of_rows, \
|
|
30
|
+
load_backtest_report, \
|
|
30
31
|
csv_to_list, StoppableThread, pretty_print_backtest_reports_evaluation, \
|
|
31
32
|
pretty_print_backtest, load_csv_into_dict, load_backtest_reports
|
|
32
33
|
|
|
@@ -70,7 +71,6 @@ __all__ = [
|
|
|
70
71
|
"Strategy",
|
|
71
72
|
"DATETIME_FORMAT",
|
|
72
73
|
"StatelessActions",
|
|
73
|
-
"OrderFee",
|
|
74
74
|
"parse_decimal_to_string",
|
|
75
75
|
"parse_string_to_decimal",
|
|
76
76
|
"BacktestReport",
|
|
@@ -112,4 +112,6 @@ __all__ = [
|
|
|
112
112
|
"APP_MODE",
|
|
113
113
|
"AppMode",
|
|
114
114
|
"RoundingService",
|
|
115
|
+
"BacktestDateRange",
|
|
116
|
+
"load_backtest_report",
|
|
115
117
|
]
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from .app_mode import AppMode
|
|
2
2
|
from .backtesting import BacktestReport, BacktestPosition, \
|
|
3
|
-
BacktestReportsEvaluation
|
|
3
|
+
BacktestReportsEvaluation, BacktestDateRange
|
|
4
4
|
from .market import MarketCredential
|
|
5
|
-
from .order import OrderStatus, OrderSide, OrderType, Order
|
|
5
|
+
from .order import OrderStatus, OrderSide, OrderType, Order
|
|
6
6
|
from .portfolio import PortfolioConfiguration, Portfolio, PortfolioSnapshot
|
|
7
7
|
from .position import Position, PositionSnapshot
|
|
8
8
|
from .strategy_profile import StrategyProfile
|
|
@@ -26,7 +26,6 @@ __all__ = [
|
|
|
26
26
|
"PortfolioConfiguration",
|
|
27
27
|
"Position",
|
|
28
28
|
"Portfolio",
|
|
29
|
-
"OrderFee",
|
|
30
29
|
"BacktestReport",
|
|
31
30
|
"PositionSnapshot",
|
|
32
31
|
"PortfolioSnapshot",
|
|
@@ -36,5 +35,6 @@ __all__ = [
|
|
|
36
35
|
"MarketCredential",
|
|
37
36
|
"TradeStatus",
|
|
38
37
|
"BacktestReportsEvaluation",
|
|
39
|
-
"AppMode"
|
|
38
|
+
"AppMode",
|
|
39
|
+
"BacktestDateRange"
|
|
40
40
|
]
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
from .backtest_position import BacktestPosition
|
|
2
2
|
from .backtest_report import BacktestReport
|
|
3
3
|
from .backtest_reports_evaluation import BacktestReportsEvaluation
|
|
4
|
+
from .backtest_date_range import BacktestDateRange
|
|
4
5
|
|
|
5
6
|
__all__ = [
|
|
6
7
|
"BacktestReport",
|
|
7
8
|
"BacktestPosition",
|
|
8
9
|
"BacktestReportsEvaluation",
|
|
10
|
+
"BacktestDateRange"
|
|
9
11
|
]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class BacktestDateRange:
|
|
5
|
+
"""
|
|
6
|
+
Represents a date range for a backtest
|
|
7
|
+
"""
|
|
8
|
+
def __init__(self, start_date, end_date=None, name=None):
|
|
9
|
+
self._start_date = start_date
|
|
10
|
+
self._end_date = end_date
|
|
11
|
+
self._name = name
|
|
12
|
+
|
|
13
|
+
if end_date is None:
|
|
14
|
+
self._end_date = datetime.now()
|
|
15
|
+
|
|
16
|
+
@property
|
|
17
|
+
def start_date(self):
|
|
18
|
+
return self._start_date
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def end_date(self):
|
|
22
|
+
return self._end_date
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def name(self):
|
|
26
|
+
return self._name
|
|
@@ -104,3 +104,17 @@ class BacktestPosition(BaseModel):
|
|
|
104
104
|
return 0.0
|
|
105
105
|
|
|
106
106
|
return self.value / self._total_value_portfolio * 100
|
|
107
|
+
|
|
108
|
+
def to_dict(self):
|
|
109
|
+
return {
|
|
110
|
+
"symbol": self.symbol,
|
|
111
|
+
"amount": self.amount,
|
|
112
|
+
"cost": self.cost,
|
|
113
|
+
"price": self.price,
|
|
114
|
+
"value": self.value,
|
|
115
|
+
"growth": self.growth,
|
|
116
|
+
"growth_rate": self.growth_rate,
|
|
117
|
+
"amount_pending_buy": self.amount_pending_buy,
|
|
118
|
+
"amount_pending_sell": self.amount_pending_sell,
|
|
119
|
+
"percentage_of_portfolio": self.percentage_of_portfolio
|
|
120
|
+
}
|
|
@@ -2,6 +2,7 @@ from datetime import datetime
|
|
|
2
2
|
|
|
3
3
|
from investing_algorithm_framework.domain.models.base_model import BaseModel
|
|
4
4
|
from investing_algorithm_framework.domain.models.time_unit import TimeUnit
|
|
5
|
+
from investing_algorithm_framework.domain.constants import DATETIME_FORMAT
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class BacktestReport(BaseModel):
|
|
@@ -18,7 +19,6 @@ class BacktestReport(BaseModel):
|
|
|
18
19
|
backtest_data_index_date=None,
|
|
19
20
|
backtest_start_date=None,
|
|
20
21
|
backtest_end_date=None,
|
|
21
|
-
backtest_index_date=None,
|
|
22
22
|
trading_time_frame=None,
|
|
23
23
|
trading_time_frame_start_date=None,
|
|
24
24
|
symbols=None,
|
|
@@ -42,14 +42,15 @@ class BacktestReport(BaseModel):
|
|
|
42
42
|
average_trade_duration=0,
|
|
43
43
|
average_trade_size=0.0,
|
|
44
44
|
trades=None,
|
|
45
|
-
|
|
45
|
+
orders=None,
|
|
46
|
+
created_at: datetime = None,
|
|
47
|
+
context=None,
|
|
46
48
|
):
|
|
47
49
|
self._name = name
|
|
48
50
|
self._strategy_identifiers = strategy_identifiers
|
|
49
51
|
self._backtest_start_date_data = backtest_start_date_data
|
|
50
52
|
self._backtest_start_date = backtest_start_date
|
|
51
53
|
self._backtest_end_date = backtest_end_date
|
|
52
|
-
self._backtest_index_date = backtest_index_date
|
|
53
54
|
self._number_of_runs = number_of_runs
|
|
54
55
|
self._trading_time_frame = trading_time_frame
|
|
55
56
|
self._trading_time_frame_start_date = trading_time_frame_start_date
|
|
@@ -72,13 +73,15 @@ class BacktestReport(BaseModel):
|
|
|
72
73
|
self._total_net_gain = total_net_gain
|
|
73
74
|
self._backtest_data_index_date = backtest_data_index_date
|
|
74
75
|
self._total_value = total_value
|
|
75
|
-
self.
|
|
76
|
+
self._positions = positions
|
|
77
|
+
self._orders = orders
|
|
76
78
|
self._average_trade_duration = average_trade_duration
|
|
77
79
|
self._average_trade_size = average_trade_size
|
|
78
80
|
self._trades = trades
|
|
79
81
|
self._created_at: datetime = created_at
|
|
80
82
|
self._interval = interval
|
|
81
83
|
self._time_unit = time_unit
|
|
84
|
+
self._context = context
|
|
82
85
|
|
|
83
86
|
@property
|
|
84
87
|
def name(self):
|
|
@@ -116,10 +119,6 @@ class BacktestReport(BaseModel):
|
|
|
116
119
|
def backtest_end_date(self):
|
|
117
120
|
return self._backtest_end_date
|
|
118
121
|
|
|
119
|
-
@property
|
|
120
|
-
def backtest_index_date(self):
|
|
121
|
-
return self._backtest_index_date
|
|
122
|
-
|
|
123
122
|
@property
|
|
124
123
|
def trading_time_frame(self):
|
|
125
124
|
return self._trading_time_frame
|
|
@@ -160,10 +159,6 @@ class BacktestReport(BaseModel):
|
|
|
160
159
|
def backtest_end_date(self, value):
|
|
161
160
|
self._backtest_end_date = value
|
|
162
161
|
|
|
163
|
-
@backtest_index_date.setter
|
|
164
|
-
def backtest_index_date(self, value):
|
|
165
|
-
self._backtest_index_date = value
|
|
166
|
-
|
|
167
162
|
@number_of_runs.setter
|
|
168
163
|
def number_of_runs(self, value):
|
|
169
164
|
self._number_of_runs = value
|
|
@@ -316,6 +311,14 @@ class BacktestReport(BaseModel):
|
|
|
316
311
|
def positions(self, value):
|
|
317
312
|
self._positions = value
|
|
318
313
|
|
|
314
|
+
@property
|
|
315
|
+
def orders(self):
|
|
316
|
+
return self._orders
|
|
317
|
+
|
|
318
|
+
@orders.setter
|
|
319
|
+
def orders(self, value):
|
|
320
|
+
self._orders = value
|
|
321
|
+
|
|
319
322
|
@property
|
|
320
323
|
def average_trade_duration(self):
|
|
321
324
|
return self._average_trade_duration
|
|
@@ -348,6 +351,14 @@ class BacktestReport(BaseModel):
|
|
|
348
351
|
def interval(self, value):
|
|
349
352
|
self._interval = value
|
|
350
353
|
|
|
354
|
+
@property
|
|
355
|
+
def context(self):
|
|
356
|
+
return self._context
|
|
357
|
+
|
|
358
|
+
@context.setter
|
|
359
|
+
def context(self, value):
|
|
360
|
+
self._context = value
|
|
361
|
+
|
|
351
362
|
@property
|
|
352
363
|
def time_unit(self):
|
|
353
364
|
return self._time_unit
|
|
@@ -372,7 +383,6 @@ class BacktestReport(BaseModel):
|
|
|
372
383
|
name=self.name,
|
|
373
384
|
start_date=self.backtest_start_date,
|
|
374
385
|
end_date=self.backtest_end_date,
|
|
375
|
-
backtest_index_date=self.backtest_index_date,
|
|
376
386
|
start_date_data=self.backtest_start_date_data,
|
|
377
387
|
)
|
|
378
388
|
|
|
@@ -383,9 +393,12 @@ class BacktestReport(BaseModel):
|
|
|
383
393
|
"""
|
|
384
394
|
return {
|
|
385
395
|
"name": self.name,
|
|
396
|
+
"context": self.context if self.context is not None else {},
|
|
386
397
|
"strategy_identifiers": self.strategy_identifiers,
|
|
387
|
-
"backtest_start_date": self.backtest_start_date
|
|
388
|
-
|
|
398
|
+
"backtest_start_date": self.backtest_start_date
|
|
399
|
+
.strftime(DATETIME_FORMAT),
|
|
400
|
+
"backtest_end_date": self.backtest_end_date
|
|
401
|
+
.strftime(DATETIME_FORMAT),
|
|
389
402
|
"number_of_runs": self.number_of_runs,
|
|
390
403
|
"symbols": self.symbols,
|
|
391
404
|
"market": self.market,
|
|
@@ -404,10 +417,16 @@ class BacktestReport(BaseModel):
|
|
|
404
417
|
"trading_symbol": self.trading_symbol,
|
|
405
418
|
"total_net_gain_percentage": self.total_net_gain_percentage,
|
|
406
419
|
"total_net_gain": self.total_net_gain,
|
|
407
|
-
"backtest_data_index_date": self.backtest_data_index_date,
|
|
408
420
|
"total_value": self.total_value,
|
|
409
421
|
"average_trade_duration": self.average_trade_duration,
|
|
410
422
|
"average_trade_size": self.average_trade_size,
|
|
423
|
+
"positions": [position.to_dict() for position in self.positions],
|
|
424
|
+
"trades": [trade.to_dict() for trade in self.trades],
|
|
425
|
+
"orders": [
|
|
426
|
+
order.to_dict(datetime_format=DATETIME_FORMAT)
|
|
427
|
+
for order in self.orders
|
|
428
|
+
],
|
|
429
|
+
"created_at": self.created_at.strftime(DATETIME_FORMAT),
|
|
411
430
|
}
|
|
412
431
|
|
|
413
432
|
@staticmethod
|
|
@@ -438,7 +457,6 @@ class BacktestReport(BaseModel):
|
|
|
438
457
|
trading_symbol=data["trading_symbol"],
|
|
439
458
|
total_net_gain_percentage=float(data["total_net_gain_percentage"]),
|
|
440
459
|
total_net_gain=float(data["total_net_gain"]),
|
|
441
|
-
backtest_data_index_date=data["backtest_data_index_date"],
|
|
442
460
|
total_value=float(data["total_value"]),
|
|
443
461
|
average_trade_duration=data["average_trade_duration"],
|
|
444
462
|
average_trade_size=float(data["average_trade_size"]),
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from .order import Order
|
|
2
|
-
from .order_fee import OrderFee
|
|
3
2
|
from .order_side import OrderSide
|
|
4
3
|
from .order_status import OrderStatus
|
|
5
4
|
from .order_type import OrderType
|
|
6
5
|
|
|
7
|
-
__all__ = ["OrderType", "OrderStatus", "OrderSide", "Order"
|
|
6
|
+
__all__ = ["OrderType", "OrderStatus", "OrderSide", "Order"]
|
|
@@ -5,20 +5,20 @@ from dateutil.parser import parse
|
|
|
5
5
|
from investing_algorithm_framework.domain.exceptions import \
|
|
6
6
|
OperationalException
|
|
7
7
|
from investing_algorithm_framework.domain.models.base_model import BaseModel
|
|
8
|
+
from investing_algorithm_framework.domain.models.order.order_side import \
|
|
9
|
+
OrderSide
|
|
8
10
|
from investing_algorithm_framework.domain.models.order.order_status import \
|
|
9
11
|
OrderStatus
|
|
10
12
|
from investing_algorithm_framework.domain.models.order.order_type import \
|
|
11
13
|
OrderType
|
|
12
|
-
from investing_algorithm_framework.domain.models.order.order_side import \
|
|
13
|
-
OrderSide
|
|
14
|
-
from investing_algorithm_framework.domain.models.order.order_fee import \
|
|
15
|
-
OrderFee
|
|
16
14
|
|
|
17
15
|
logger = logging.getLogger("investing_algorithm_framework")
|
|
18
16
|
|
|
19
17
|
|
|
20
18
|
class Order(BaseModel):
|
|
21
|
-
|
|
19
|
+
"""
|
|
20
|
+
Order model class to represent an order of the trading bot
|
|
21
|
+
"""
|
|
22
22
|
def __init__(
|
|
23
23
|
self,
|
|
24
24
|
order_type,
|
|
@@ -40,10 +40,9 @@ class Order(BaseModel):
|
|
|
40
40
|
cost=None,
|
|
41
41
|
fee=None,
|
|
42
42
|
position_id=None,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
trailing_stop_loss_percentage=None,
|
|
43
|
+
order_fee=None,
|
|
44
|
+
order_fee_currency=None,
|
|
45
|
+
order_fee_rate=None
|
|
47
46
|
):
|
|
48
47
|
if target_symbol is None:
|
|
49
48
|
raise OperationalException("Target symbol is not specified")
|
|
@@ -80,11 +79,10 @@ class Order(BaseModel):
|
|
|
80
79
|
self.remaining = remaining
|
|
81
80
|
self.cost = cost
|
|
82
81
|
self.fee = fee
|
|
83
|
-
self.stop_loss = stop_loss
|
|
84
|
-
self.stop_loss_percentage = stop_loss_percentage
|
|
85
|
-
self.trailing_stop_loss = trailing_stop_loss
|
|
86
|
-
self.trailing_stop_loss_percentage = trailing_stop_loss_percentage
|
|
87
82
|
self._available_amount = self.filled
|
|
83
|
+
self.order_fee = order_fee
|
|
84
|
+
self.order_fee_currency = order_fee_currency
|
|
85
|
+
self.order_fee_rate = order_fee_rate
|
|
88
86
|
|
|
89
87
|
def get_id(self):
|
|
90
88
|
return self.id
|
|
@@ -107,6 +105,24 @@ class Order(BaseModel):
|
|
|
107
105
|
def set_price(self, price):
|
|
108
106
|
self.price = price
|
|
109
107
|
|
|
108
|
+
def get_order_fee_currency(self):
|
|
109
|
+
return self.order_fee_currency
|
|
110
|
+
|
|
111
|
+
def set_order_fee_currency(self, order_fee_currency):
|
|
112
|
+
self.order_fee_currency = order_fee_currency
|
|
113
|
+
|
|
114
|
+
def get_order_fee_rate(self):
|
|
115
|
+
return self.order_fee_rate
|
|
116
|
+
|
|
117
|
+
def set_order_fee_rate(self, order_fee_rate):
|
|
118
|
+
self.order_fee_rate = order_fee_rate
|
|
119
|
+
|
|
120
|
+
def get_order_fee(self):
|
|
121
|
+
return self.order_fee
|
|
122
|
+
|
|
123
|
+
def set_order_fee(self, order_fee):
|
|
124
|
+
self.order_fee = order_fee
|
|
125
|
+
|
|
110
126
|
def get_order_size(self):
|
|
111
127
|
return self.order_side
|
|
112
128
|
|
|
@@ -232,7 +248,20 @@ class Order(BaseModel):
|
|
|
232
248
|
def available_amount(self, available_amount):
|
|
233
249
|
self.set_available_amount(available_amount)
|
|
234
250
|
|
|
235
|
-
def to_dict(self):
|
|
251
|
+
def to_dict(self, datetime_format=None):
|
|
252
|
+
|
|
253
|
+
if datetime_format is not None:
|
|
254
|
+
created_at = self.created_at.strftime(datetime_format) \
|
|
255
|
+
if self.created_at else None
|
|
256
|
+
updated_at = self.updated_at.strftime(datetime_format) \
|
|
257
|
+
if self.updated_at else None
|
|
258
|
+
trade_closed_at = self.trade_closed_at.strftime(datetime_format) \
|
|
259
|
+
if self.trade_closed_at else None
|
|
260
|
+
else:
|
|
261
|
+
created_at = self.created_at
|
|
262
|
+
updated_at = self.updated_at
|
|
263
|
+
trade_closed_at = self.trade_closed_at
|
|
264
|
+
|
|
236
265
|
return {
|
|
237
266
|
"external_id": self.external_id,
|
|
238
267
|
"target_symbol": self.target_symbol,
|
|
@@ -243,18 +272,16 @@ class Order(BaseModel):
|
|
|
243
272
|
"price": self.price,
|
|
244
273
|
"amount": self.amount,
|
|
245
274
|
"net_gain": self.net_gain,
|
|
246
|
-
"trade_closed_at":
|
|
275
|
+
"trade_closed_at": trade_closed_at,
|
|
247
276
|
"trade_closed_price": self.trade_closed_price,
|
|
248
|
-
"created_at":
|
|
249
|
-
"updated_at":
|
|
277
|
+
"created_at": created_at,
|
|
278
|
+
"updated_at": updated_at,
|
|
250
279
|
"filled": self.filled,
|
|
251
280
|
"remaining": self.remaining,
|
|
252
281
|
"cost": self.cost,
|
|
253
|
-
"
|
|
254
|
-
"
|
|
255
|
-
"
|
|
256
|
-
"trailing_stop_loss": self.trailing_stop_loss,
|
|
257
|
-
"trailing_stop_loss_percentage": self.trailing_stop_loss_percentage
|
|
282
|
+
"order_fee_currency": self.order_fee_currency,
|
|
283
|
+
"order_fee_rate": self.order_fee_rate,
|
|
284
|
+
"order_fee": self.order_fee,
|
|
258
285
|
}
|
|
259
286
|
|
|
260
287
|
@staticmethod
|
|
@@ -290,14 +317,32 @@ class Order(BaseModel):
|
|
|
290
317
|
cost=data.get("cost", None),
|
|
291
318
|
fee=data.get("fee", None),
|
|
292
319
|
created_at=created_at,
|
|
293
|
-
updated_at=updated_at
|
|
320
|
+
updated_at=updated_at,
|
|
321
|
+
order_fee=data.get("order_fee", None),
|
|
322
|
+
order_fee_currency=data.get("order_fee_currency", None),
|
|
323
|
+
order_fee_rate=data.get("order_fee_rate", None),
|
|
294
324
|
)
|
|
295
325
|
|
|
296
326
|
@staticmethod
|
|
297
327
|
def from_ccxt_order(ccxt_order):
|
|
328
|
+
"""
|
|
329
|
+
Create an Order object from a ccxt order object
|
|
330
|
+
:param ccxt_order: ccxt order object
|
|
331
|
+
:return: Order object
|
|
332
|
+
"""
|
|
298
333
|
status = OrderStatus.from_value(ccxt_order["status"])
|
|
299
334
|
target_symbol = ccxt_order.get("symbol").split("/")[0]
|
|
300
335
|
trading_symbol = ccxt_order.get("symbol").split("/")[1]
|
|
336
|
+
ccxt_fee = ccxt_order.get("fee", None)
|
|
337
|
+
order_fee = None
|
|
338
|
+
order_fee_currency = None
|
|
339
|
+
order_fee_rate = None
|
|
340
|
+
|
|
341
|
+
if ccxt_fee is not None:
|
|
342
|
+
order_fee = ccxt_fee.get("cost", None)
|
|
343
|
+
order_fee_currency = ccxt_fee.get("currency", None)
|
|
344
|
+
order_fee_rate = ccxt_fee.get("rate", None)
|
|
345
|
+
|
|
301
346
|
return Order(
|
|
302
347
|
external_id=ccxt_order.get("id", None),
|
|
303
348
|
target_symbol=target_symbol,
|
|
@@ -310,7 +355,9 @@ class Order(BaseModel):
|
|
|
310
355
|
filled=ccxt_order.get("filled", None),
|
|
311
356
|
remaining=ccxt_order.get("remaining", None),
|
|
312
357
|
cost=ccxt_order.get("cost", None),
|
|
313
|
-
|
|
358
|
+
order_fee=order_fee,
|
|
359
|
+
order_fee_currency=order_fee_currency,
|
|
360
|
+
order_fee_rate=order_fee_rate,
|
|
314
361
|
created_at=parse(ccxt_order.get("datetime", None))
|
|
315
362
|
)
|
|
316
363
|
|