investing-algorithm-framework 4.0.0__tar.gz → 4.1.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-4.0.0 → investing_algorithm_framework-4.1.0}/PKG-INFO +23 -2
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/README.md +22 -1
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/__init__.py +4 -3
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/algorithm.py +12 -11
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/app.py +19 -21
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/dependency_container.py +2 -1
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/backtesting/backtest_report.py +4 -10
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/portfolio/portfolio.py +31 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +22 -3
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +1 -1
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/repositories/repository.py +1 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/services/performance_service/performance_service.py +4 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/backtesting/backtest_service.py +66 -19
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/market_data_source_service/backtest_market_data_source_service.py +0 -1
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/market_data_source_service/market_data_source_service.py +20 -20
- investing_algorithm_framework-4.1.0/investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +46 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/portfolios/portfolio_configuration_service.py +9 -6
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/portfolios/portfolio_service.py +6 -1
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/pyproject.toml +3 -2
- investing_algorithm_framework-4.0.0/investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +0 -21
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/LICENSE +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/stateless/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/stateless/action_handlers/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/stateless/exception_handler.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/strategy.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/task.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/web/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/web/controllers/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/web/controllers/orders.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/web/controllers/portfolio.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/web/controllers/positions.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/web/create_app.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/web/error_handler.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/web/responses.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/web/run_strategies.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/web/schemas/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/web/schemas/order.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/web/schemas/portfolio.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/web/schemas/position.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/app/web/setup_cors.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/cli/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/cli/create_azure_function_app_skeleton.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/cli/deploy_to_azure_function.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/cli/templates/azure_function_framework_app.py.template +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/cli/templates/azure_function_host.json.template +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/create_app.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/config.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/constants.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/data_structures.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/decimal_parsing.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/exceptions.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/metrics/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/metrics/price_efficiency.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/app_mode.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/backtesting/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/backtesting/backtest_date_range.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/backtesting/backtest_position.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/backtesting/backtest_reports_evaluation.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/base_model.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/date_range.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/market/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/market/market_credential.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/order/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/order/order.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/order/order_side.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/order/order_status.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/order/order_type.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/portfolio/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/position/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/position/position.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/position/position_snapshot.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/strategy_profile.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/time_frame.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/time_interval.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/time_unit.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/tracing/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/tracing/trace.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/trade/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/trade/trade.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/trade/trade_status.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/trading_data_types.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/models/trading_time_frame.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/services/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/services/market_credential_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/services/market_data_sources.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/services/market_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/services/portfolios/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/services/rounding_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/singleton.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/stateless_actions.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/strategy.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/utils/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/utils/backtesting.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/utils/csv.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/utils/polars.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/utils/random.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/utils/signatures.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/utils/stoppable_thread.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/domain/utils/synchronized.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/indicators/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/indicators/advanced.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/indicators/momentum.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/indicators/trend.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/indicators/utils.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/database/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/database/sql_alchemy.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/decimal_parser.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/ccxt.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/csv.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/pandas.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/market_data_sources/us_treasury_yield.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/model_extension.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/order/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/order/order.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/portfolio/sql_portfolio.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/position/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/position/position.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/repositories/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/repositories/order_repository.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/repositories/position_repository.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/services/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/services/azure/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/services/azure/state_handler.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/services/market_service/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/services/market_service/ccxt_market_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/services/performance_service/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/infrastructure/services/performance_service/backtest_performance_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/backtesting/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/backtesting/backtest_report_writer_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/backtesting/graphs.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/configuration_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/market_credential_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/market_data_source_service/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/order_service/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/order_service/order_backtest_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/order_service/order_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/portfolios/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/position_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/position_snapshot_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/repository_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/trade_service/__init__.py +0 -0
- {investing_algorithm_framework-4.0.0 → investing_algorithm_framework-4.1.0}/investing_algorithm_framework/services/trade_service/trade_service.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: investing-algorithm-framework
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.1.0
|
|
4
4
|
Summary: A framework for creating trading bots
|
|
5
5
|
Author: MDUYN
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -278,7 +278,7 @@ app.add_portfolio_configuration(
|
|
|
278
278
|
We are continuously working on improving the performance of the framework. If
|
|
279
279
|
you have any suggestions, please let us know.
|
|
280
280
|
|
|
281
|
-
##
|
|
281
|
+
## How to install
|
|
282
282
|
|
|
283
283
|
You can download the framework with pypi.
|
|
284
284
|
|
|
@@ -286,6 +286,27 @@ You can download the framework with pypi.
|
|
|
286
286
|
pip install investing-algorithm-framework
|
|
287
287
|
```
|
|
288
288
|
|
|
289
|
+
## Installation for local development
|
|
290
|
+
|
|
291
|
+
The framework is built with poetry. To install the framework for local development, you can run the following commands:
|
|
292
|
+
|
|
293
|
+
> Make sure you have poetry installed. If you don't have poetry installed, you can find installation instructions [here](https://python-poetry.org/docs/#installation)
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
git clone http
|
|
297
|
+
cd investing-algorithm-framework
|
|
298
|
+
poetry install
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Running tests
|
|
302
|
+
|
|
303
|
+
To run the tests, you can run the following command:
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
# In the root of the project
|
|
307
|
+
python -m unittest discover -s tests
|
|
308
|
+
```
|
|
309
|
+
|
|
289
310
|
## Disclaimer
|
|
290
311
|
|
|
291
312
|
If you use this framework for your investments, do not risk money
|
|
@@ -241,7 +241,7 @@ app.add_portfolio_configuration(
|
|
|
241
241
|
We are continuously working on improving the performance of the framework. If
|
|
242
242
|
you have any suggestions, please let us know.
|
|
243
243
|
|
|
244
|
-
##
|
|
244
|
+
## How to install
|
|
245
245
|
|
|
246
246
|
You can download the framework with pypi.
|
|
247
247
|
|
|
@@ -249,6 +249,27 @@ You can download the framework with pypi.
|
|
|
249
249
|
pip install investing-algorithm-framework
|
|
250
250
|
```
|
|
251
251
|
|
|
252
|
+
## Installation for local development
|
|
253
|
+
|
|
254
|
+
The framework is built with poetry. To install the framework for local development, you can run the following commands:
|
|
255
|
+
|
|
256
|
+
> Make sure you have poetry installed. If you don't have poetry installed, you can find installation instructions [here](https://python-poetry.org/docs/#installation)
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
git clone http
|
|
260
|
+
cd investing-algorithm-framework
|
|
261
|
+
poetry install
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Running tests
|
|
265
|
+
|
|
266
|
+
To run the tests, you can run the following command:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
# In the root of the project
|
|
270
|
+
python -m unittest discover -s tests
|
|
271
|
+
```
|
|
272
|
+
|
|
252
273
|
## Disclaimer
|
|
253
274
|
|
|
254
275
|
If you use this framework for your investments, do not risk money
|
|
@@ -11,7 +11,8 @@ from investing_algorithm_framework.domain import ApiException, \
|
|
|
11
11
|
pretty_print_backtest_reports_evaluation, load_backtest_reports, \
|
|
12
12
|
RESERVED_BALANCES, APP_MODE, AppMode, DATETIME_FORMAT, \
|
|
13
13
|
load_backtest_report, BacktestDateRange, convert_polars_to_pandas, \
|
|
14
|
-
DateRange, get_backtest_report, DEFAULT_LOGGING_CONFIG
|
|
14
|
+
DateRange, get_backtest_report, DEFAULT_LOGGING_CONFIG, \
|
|
15
|
+
BacktestReport
|
|
15
16
|
from investing_algorithm_framework.infrastructure import \
|
|
16
17
|
CCXTOrderBookMarketDataSource, CCXTOHLCVMarketDataSource, \
|
|
17
18
|
CCXTTickerMarketDataSource, CSVOHLCVMarketDataSource, \
|
|
@@ -70,7 +71,6 @@ __all__ = [
|
|
|
70
71
|
"BacktestDateRange",
|
|
71
72
|
"convert_polars_to_pandas",
|
|
72
73
|
"DateRange",
|
|
73
|
-
"get_rsi",
|
|
74
74
|
"get_peaks",
|
|
75
75
|
"is_uptrend",
|
|
76
76
|
"is_downtrend",
|
|
@@ -89,5 +89,6 @@ __all__ = [
|
|
|
89
89
|
"is_divergence",
|
|
90
90
|
"get_backtest_report",
|
|
91
91
|
"AzureBlobStorageStateHandler",
|
|
92
|
-
"DEFAULT_LOGGING_CONFIG"
|
|
92
|
+
"DEFAULT_LOGGING_CONFIG",
|
|
93
|
+
"BacktestReport"
|
|
93
94
|
]
|
|
@@ -163,15 +163,6 @@ class Algorithm:
|
|
|
163
163
|
def data_sources(self):
|
|
164
164
|
return self._data_sources
|
|
165
165
|
|
|
166
|
-
@property
|
|
167
|
-
def identifier(self):
|
|
168
|
-
"""
|
|
169
|
-
Function to get a config instance. This allows users when
|
|
170
|
-
having access to the algorithm instance also to read the
|
|
171
|
-
configs of the app.
|
|
172
|
-
"""
|
|
173
|
-
return self.configuration_service.config
|
|
174
|
-
|
|
175
166
|
@property
|
|
176
167
|
def config(self):
|
|
177
168
|
"""
|
|
@@ -179,7 +170,7 @@ class Algorithm:
|
|
|
179
170
|
having access to the algorithm instance also to read the
|
|
180
171
|
configs of the app.
|
|
181
172
|
"""
|
|
182
|
-
return self.configuration_service.
|
|
173
|
+
return self.configuration_service.get_config()
|
|
183
174
|
|
|
184
175
|
@property
|
|
185
176
|
def description(self):
|
|
@@ -489,6 +480,16 @@ class Algorithm:
|
|
|
489
480
|
|
|
490
481
|
return self.portfolio_service.find({{"market": market}})
|
|
491
482
|
|
|
483
|
+
def get_portfolios(self):
|
|
484
|
+
"""
|
|
485
|
+
Function to get all portfolios of the algorithm. This function
|
|
486
|
+
will return all portfolios of the algorithm.
|
|
487
|
+
|
|
488
|
+
Returns:
|
|
489
|
+
List[Portfolio]: A list of all portfolios of the algorithm
|
|
490
|
+
"""
|
|
491
|
+
return self.portfolio_service.get_all()
|
|
492
|
+
|
|
492
493
|
def get_unallocated(self, market=None) -> float:
|
|
493
494
|
"""
|
|
494
495
|
Function to get the unallocated balance of the portfolio. This
|
|
@@ -834,7 +835,7 @@ class Algorithm:
|
|
|
834
835
|
return (position.amount * ticker["bid"] / total) * 100
|
|
835
836
|
|
|
836
837
|
def get_position_percentage_of_portfolio_by_net_size(
|
|
837
|
-
|
|
838
|
+
self, symbol, market=None, identifier=None
|
|
838
839
|
) -> float:
|
|
839
840
|
"""
|
|
840
841
|
Returns the percentage of the portfolio that is allocated to a
|
|
@@ -518,17 +518,6 @@ class App:
|
|
|
518
518
|
trade_service=self.container.trade_service(),
|
|
519
519
|
)
|
|
520
520
|
|
|
521
|
-
# Create all portfolios
|
|
522
|
-
portfolio_configuration_service = self.container \
|
|
523
|
-
.portfolio_configuration_service()
|
|
524
|
-
portfolio_configurations = portfolio_configuration_service.get_all()
|
|
525
|
-
portfolio_service = self.container.portfolio_service()
|
|
526
|
-
|
|
527
|
-
for portfolio_configuration in portfolio_configurations:
|
|
528
|
-
portfolio_service.create_portfolio_from_configuration(
|
|
529
|
-
portfolio_configuration
|
|
530
|
-
)
|
|
531
|
-
|
|
532
521
|
def run(
|
|
533
522
|
self,
|
|
534
523
|
payload: dict = None,
|
|
@@ -774,20 +763,24 @@ class App:
|
|
|
774
763
|
|
|
775
764
|
def run_backtest(
|
|
776
765
|
self,
|
|
777
|
-
algorithm,
|
|
778
766
|
backtest_date_range: BacktestDateRange,
|
|
767
|
+
initial_amount=None,
|
|
779
768
|
pending_order_check_interval=None,
|
|
780
|
-
output_directory=None
|
|
769
|
+
output_directory=None,
|
|
770
|
+
algorithm: Algorithm = None
|
|
781
771
|
) -> BacktestReport:
|
|
782
772
|
"""
|
|
783
773
|
Run a backtest for an algorithm. This method should be called when
|
|
784
774
|
running a backtest.
|
|
785
775
|
|
|
786
776
|
Parameters:
|
|
787
|
-
algorithm: The algorithm to run a backtest for (instance of
|
|
788
|
-
Algorithm)
|
|
789
777
|
backtest_date_range: The date range to run the backtest for
|
|
790
778
|
(instance of BacktestDateRange)
|
|
779
|
+
initial_amount: The initial amount to start the backtest with.
|
|
780
|
+
This will be the amount of trading currency that the backtest
|
|
781
|
+
portfolio will start with.
|
|
782
|
+
algorithm: The algorithm to run a backtest for (instance of
|
|
783
|
+
Algorithm)
|
|
791
784
|
pending_order_check_interval: str - pending_order_check_interval:
|
|
792
785
|
The interval at which to check pending orders (e.g. 1h, 1d, 1w)
|
|
793
786
|
output_directory: str - The directory to
|
|
@@ -796,8 +789,11 @@ class App:
|
|
|
796
789
|
Returns:
|
|
797
790
|
Instance of BacktestReport
|
|
798
791
|
"""
|
|
799
|
-
|
|
800
|
-
|
|
792
|
+
if algorithm is not None:
|
|
793
|
+
self.algorithm = algorithm
|
|
794
|
+
|
|
795
|
+
if self.algorithm is None:
|
|
796
|
+
raise OperationalException("No algorithm registered")
|
|
801
797
|
|
|
802
798
|
self._initialize_app_for_backtest(
|
|
803
799
|
backtest_date_range=backtest_date_range,
|
|
@@ -807,18 +803,20 @@ class App:
|
|
|
807
803
|
self._initialize_algorithm_for_backtest(
|
|
808
804
|
algorithm=self.algorithm
|
|
809
805
|
)
|
|
806
|
+
|
|
810
807
|
backtest_service = self.container.backtest_service()
|
|
811
|
-
configuration_service = self.container.configuration_service()
|
|
812
|
-
config = configuration_service.get_config()
|
|
813
|
-
backtest_service.resource_directory = config[RESOURCE_DIRECTORY]
|
|
814
808
|
|
|
815
809
|
# Run the backtest with the backtest_service and collect the report
|
|
816
810
|
report = backtest_service.run_backtest(
|
|
817
|
-
algorithm=self.algorithm,
|
|
811
|
+
algorithm=self.algorithm,
|
|
812
|
+
initial_amount=initial_amount,
|
|
813
|
+
backtest_date_range=backtest_date_range
|
|
818
814
|
)
|
|
819
815
|
backtest_report_writer_service = self.container \
|
|
820
816
|
.backtest_report_writer_service()
|
|
821
817
|
|
|
818
|
+
config = self.container.configuration_service().get_config()
|
|
819
|
+
|
|
822
820
|
if output_directory is None:
|
|
823
821
|
output_directory = os.path.join(
|
|
824
822
|
config[RESOURCE_DIRECTORY], "backtest_reports"
|
|
@@ -126,10 +126,11 @@ class DependencyContainer(containers.DeclarativeContainer):
|
|
|
126
126
|
BacktestService,
|
|
127
127
|
configuration_service=configuration_service,
|
|
128
128
|
order_service=order_service,
|
|
129
|
-
|
|
129
|
+
portfolio_service=portfolio_service,
|
|
130
130
|
performance_service=performance_service,
|
|
131
131
|
position_repository=position_repository,
|
|
132
132
|
market_data_source_service=market_data_source_service,
|
|
133
|
+
portfolio_configuration_service=portfolio_configuration_service,
|
|
133
134
|
)
|
|
134
135
|
backtest_report_writer_service = providers.Factory(
|
|
135
136
|
BacktestReportWriterService,
|
|
@@ -9,7 +9,6 @@ from investing_algorithm_framework.domain.metrics import \
|
|
|
9
9
|
from investing_algorithm_framework.domain.models \
|
|
10
10
|
.backtesting.backtest_date_range import BacktestDateRange
|
|
11
11
|
from investing_algorithm_framework.domain.models.base_model import BaseModel
|
|
12
|
-
from investing_algorithm_framework.domain.models.time_unit import TimeUnit
|
|
13
12
|
from investing_algorithm_framework.domain.models.position import Position
|
|
14
13
|
from investing_algorithm_framework.domain.models.trade import Trade
|
|
15
14
|
from investing_algorithm_framework.domain.models.order import Order
|
|
@@ -358,15 +357,7 @@ class BacktestReport(BaseModel):
|
|
|
358
357
|
self._time_unit = value
|
|
359
358
|
|
|
360
359
|
def get_runs_per_day(self):
|
|
361
|
-
|
|
362
|
-
if self.time_unit is None:
|
|
363
|
-
return 0
|
|
364
|
-
elif TimeUnit.SECOND.equals(self.time_unit):
|
|
365
|
-
return 86400 / self.interval
|
|
366
|
-
elif TimeUnit.MINUTE.equals(self.time_unit):
|
|
367
|
-
return 1440 / self.interval
|
|
368
|
-
else:
|
|
369
|
-
return 24 / self.interval
|
|
360
|
+
return self.number_of_runs / self.number_of_days
|
|
370
361
|
|
|
371
362
|
@property
|
|
372
363
|
def backtest_start_date(self):
|
|
@@ -525,6 +516,9 @@ class BacktestReport(BaseModel):
|
|
|
525
516
|
def get_trading_symbol(self) -> str:
|
|
526
517
|
return self.trading_symbol
|
|
527
518
|
|
|
519
|
+
def get_initial_unallocated(self) -> float:
|
|
520
|
+
return self.initial_unallocated
|
|
521
|
+
|
|
528
522
|
def add_symbol(self, symbol):
|
|
529
523
|
|
|
530
524
|
if symbol not in self.symbols:
|
|
@@ -2,6 +2,37 @@ from investing_algorithm_framework.domain.models.base_model import BaseModel
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class Portfolio(BaseModel):
|
|
5
|
+
"""
|
|
6
|
+
Portfolio base class.
|
|
7
|
+
|
|
8
|
+
A portfolio is a collection of positions that are managed by an algorithm.
|
|
9
|
+
|
|
10
|
+
Attributes:
|
|
11
|
+
* identifier: str, unique identifier of the portfolio
|
|
12
|
+
* trading_symbol: str, trading symbol of the portfolio
|
|
13
|
+
* unallocated: float, the size of the trading symbol that is not
|
|
14
|
+
allocated. For example, if the trading symbol is USDT and the unallocated
|
|
15
|
+
is 1000, it means that the portfolio has 1000 USDT that is not
|
|
16
|
+
allocated to any position.
|
|
17
|
+
* net_size: float, net size of the portfolio is the initial balance of the
|
|
18
|
+
portfolio plus the all the net gains of the trades. The
|
|
19
|
+
* realized: float, the realized gain of the portfolio is the sum of all the
|
|
20
|
+
realized gains of the trades.
|
|
21
|
+
* total_revenue: float, the total revenue of the portfolio is the sum
|
|
22
|
+
of all the orders (price * size)
|
|
23
|
+
* total_cost: float, the total cost of the portfolio is the sum of all the
|
|
24
|
+
costs of the trades (price * size (for buy orders)
|
|
25
|
+
or -price * size (for sell orders))
|
|
26
|
+
* total_net_gain: float, the total net gain of the portfolio is the sum of
|
|
27
|
+
all the net gains of the trades
|
|
28
|
+
* total_trade_volume: float, the total trade volume of the
|
|
29
|
+
portfolio is the sum of all the sizes of the trades
|
|
30
|
+
* market: str, the market of the portfolio (e.g. BITVAVO, BINANCE)
|
|
31
|
+
* created_at: datetime, the datetime when the portfolio was created
|
|
32
|
+
* updated_at: datetime, the datetime when the portfolio was last updated
|
|
33
|
+
* initialized: bool, whether the portfolio is initialized or not
|
|
34
|
+
* initial_balance: float, the initial balance of the portfolio
|
|
35
|
+
"""
|
|
5
36
|
|
|
6
37
|
def __init__(
|
|
7
38
|
self,
|
|
@@ -6,6 +6,23 @@ from investing_algorithm_framework.domain.models.base_model import BaseModel
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class PortfolioConfiguration(BaseModel):
|
|
9
|
+
"""
|
|
10
|
+
This class represents a portfolio configuration. It is used to
|
|
11
|
+
configure the portfolio that the user wants to create.
|
|
12
|
+
|
|
13
|
+
The portfolio configuration will have the following attributes:
|
|
14
|
+
- market: The market where the portfolio will be created
|
|
15
|
+
- trading_symbol: The trading symbol of the portfolio
|
|
16
|
+
- track_from: The date from which the portfolio will be tracked
|
|
17
|
+
- identifier: The identifier of the portfolio
|
|
18
|
+
- initial_balance: The initial balance of the portfolio
|
|
19
|
+
|
|
20
|
+
For backtesting, a portfolio configuration is used to create a
|
|
21
|
+
portfolio that will be used to simulate the trading of the algorithm. if
|
|
22
|
+
the user does not provide an initial balance, the portfolio will be created
|
|
23
|
+
with a balance of according to the initial balanace of
|
|
24
|
+
the PortfolioConfiguration class.
|
|
25
|
+
"""
|
|
9
26
|
|
|
10
27
|
def __init__(
|
|
11
28
|
self,
|
|
@@ -22,7 +39,9 @@ class PortfolioConfiguration(BaseModel):
|
|
|
22
39
|
self._initial_balance = initial_balance
|
|
23
40
|
|
|
24
41
|
if self.identifier is None:
|
|
25
|
-
self._identifier = market.
|
|
42
|
+
self._identifier = market.upper()
|
|
43
|
+
else:
|
|
44
|
+
self._identifier = identifier.upper()
|
|
26
45
|
|
|
27
46
|
if track_from:
|
|
28
47
|
self._track_from = parse(track_from)
|
|
@@ -35,8 +54,8 @@ class PortfolioConfiguration(BaseModel):
|
|
|
35
54
|
@property
|
|
36
55
|
def market(self):
|
|
37
56
|
|
|
38
|
-
if hasattr(self._market, "
|
|
39
|
-
return self._market.
|
|
57
|
+
if hasattr(self._market, "upper"):
|
|
58
|
+
return self._market.upper()
|
|
40
59
|
|
|
41
60
|
return self._market
|
|
42
61
|
|
|
@@ -20,7 +20,7 @@ class SQLPortfolioRepository(Repository):
|
|
|
20
20
|
query = query.filter_by(market=market_query_param.upper())
|
|
21
21
|
|
|
22
22
|
if identifier_query_param:
|
|
23
|
-
query = query.filter_by(identifier=identifier_query_param.
|
|
23
|
+
query = query.filter_by(identifier=identifier_query_param.upper())
|
|
24
24
|
|
|
25
25
|
if position_query_param:
|
|
26
26
|
position = db.query(SQLPosition)\
|
|
@@ -193,6 +193,10 @@ class PerformanceService:
|
|
|
193
193
|
return: The total net gain percentage of the backtest
|
|
194
194
|
"""
|
|
195
195
|
portfolio = self.portfolio_repository.find({"id": portfolio_id})
|
|
196
|
+
|
|
197
|
+
if portfolio.total_net_gain == 0:
|
|
198
|
+
return 0
|
|
199
|
+
|
|
196
200
|
return portfolio.total_net_gain \
|
|
197
201
|
/ backtest_profile.initial_unallocated * 100
|
|
198
202
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
from datetime import datetime, timedelta
|
|
2
|
-
|
|
3
2
|
import re
|
|
4
3
|
import os
|
|
5
4
|
import json
|
|
6
5
|
import pandas as pd
|
|
7
6
|
from dateutil import parser
|
|
8
7
|
from tqdm import tqdm
|
|
8
|
+
import logging
|
|
9
9
|
|
|
10
10
|
from investing_algorithm_framework.domain import BacktestReport, \
|
|
11
11
|
BACKTESTING_INDEX_DATETIME, TimeUnit, BacktestPosition, \
|
|
@@ -15,6 +15,7 @@ from investing_algorithm_framework.services.market_data_source_service import \
|
|
|
15
15
|
MarketDataSourceService
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
18
19
|
BACKTEST_REPORT_FILE_NAME_PATTERN = (
|
|
19
20
|
r"^report_\w+_backtest-start-date_\d{4}-\d{2}-\d{2}:\d{2}:\d{2}_"
|
|
20
21
|
r"backtest-end-date_\d{4}-\d{2}-\d{2}:\d{2}:\d{2}_"
|
|
@@ -28,17 +29,18 @@ class BacktestService:
|
|
|
28
29
|
"""
|
|
29
30
|
|
|
30
31
|
def __init__(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
self,
|
|
33
|
+
market_data_source_service: MarketDataSourceService,
|
|
34
|
+
order_service,
|
|
35
|
+
portfolio_service,
|
|
36
|
+
position_repository,
|
|
37
|
+
performance_service,
|
|
38
|
+
configuration_service,
|
|
39
|
+
portfolio_configuration_service
|
|
38
40
|
):
|
|
39
41
|
self._resource_directory = None
|
|
40
42
|
self._order_service = order_service
|
|
41
|
-
self.
|
|
43
|
+
self._portfolio_service = portfolio_service
|
|
42
44
|
self._data_index = {
|
|
43
45
|
TradingDataType.OHLCV: {},
|
|
44
46
|
TradingDataType.TICKER: {}
|
|
@@ -49,6 +51,7 @@ class BacktestService:
|
|
|
49
51
|
= market_data_source_service
|
|
50
52
|
self._backtest_market_data_sources = []
|
|
51
53
|
self._configuration_service = configuration_service
|
|
54
|
+
self._portfolio_configuration_service = portfolio_configuration_service
|
|
52
55
|
|
|
53
56
|
@property
|
|
54
57
|
def resource_directory(self):
|
|
@@ -59,7 +62,10 @@ class BacktestService:
|
|
|
59
62
|
self._resource_directory = resource_directory
|
|
60
63
|
|
|
61
64
|
def run_backtest(
|
|
62
|
-
self,
|
|
65
|
+
self,
|
|
66
|
+
algorithm,
|
|
67
|
+
backtest_date_range: BacktestDateRange,
|
|
68
|
+
initial_amount=None
|
|
63
69
|
) -> BacktestReport:
|
|
64
70
|
"""
|
|
65
71
|
Run a backtest for the given algorithm. This function will run
|
|
@@ -73,15 +79,40 @@ class BacktestService:
|
|
|
73
79
|
|
|
74
80
|
At the end of the run all traces
|
|
75
81
|
|
|
76
|
-
|
|
82
|
+
Args:
|
|
77
83
|
algorithm: The algorithm to run the backtest for
|
|
78
84
|
backtest_date_range: The backtest date range
|
|
85
|
+
initial_amount: The initial amount of the backtest portfolio
|
|
79
86
|
|
|
80
87
|
Returns:
|
|
81
88
|
BacktestReport - The backtest report
|
|
82
89
|
"""
|
|
90
|
+
logging.info(
|
|
91
|
+
f"Running backtest for algorithm with name {algorithm.name}"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Create backtest portfolio
|
|
95
|
+
portfolio_configurations = \
|
|
96
|
+
self._portfolio_configuration_service.get_all()
|
|
97
|
+
|
|
98
|
+
for portfolio_configuration in portfolio_configurations:
|
|
99
|
+
|
|
100
|
+
if self._portfolio_service.exists(
|
|
101
|
+
{"identifier": portfolio_configuration.identifier}
|
|
102
|
+
):
|
|
103
|
+
# Delete existing portfolio
|
|
104
|
+
portfolio = self._portfolio_service.find(
|
|
105
|
+
{"identifier": portfolio_configuration.identifier}
|
|
106
|
+
)
|
|
107
|
+
self._portfolio_service.delete(portfolio.id)
|
|
108
|
+
|
|
109
|
+
# Check if the portfolio configuration has a initial balance
|
|
110
|
+
self._portfolio_service.create_portfolio_from_configuration(
|
|
111
|
+
portfolio_configuration, initial_amount=initial_amount
|
|
112
|
+
)
|
|
113
|
+
|
|
83
114
|
strategy_profiles = []
|
|
84
|
-
portfolios = self.
|
|
115
|
+
portfolios = self._portfolio_service.get_all()
|
|
85
116
|
initial_unallocated = 0
|
|
86
117
|
|
|
87
118
|
for portfolio in portfolios:
|
|
@@ -114,10 +145,23 @@ class BacktestService:
|
|
|
114
145
|
strategy=algorithm.get_strategy(strategy_profile.strategy_id),
|
|
115
146
|
index_date=index_date,
|
|
116
147
|
)
|
|
117
|
-
|
|
148
|
+
|
|
149
|
+
report = self.create_backtest_report(
|
|
118
150
|
algorithm, len(schedule), backtest_date_range, initial_unallocated
|
|
119
151
|
)
|
|
120
152
|
|
|
153
|
+
# Cleanup backtest portfolio
|
|
154
|
+
portfolio_configurations = \
|
|
155
|
+
self._portfolio_configuration_service.get_all()
|
|
156
|
+
|
|
157
|
+
for portfolio_configuration in portfolio_configurations:
|
|
158
|
+
portfolio = self._portfolio_service.find(
|
|
159
|
+
{"identifier": portfolio_configuration.identifier}
|
|
160
|
+
)
|
|
161
|
+
self._portfolio_service.delete(portfolio.id)
|
|
162
|
+
|
|
163
|
+
return report
|
|
164
|
+
|
|
121
165
|
def run_backtests(
|
|
122
166
|
self, algorithms, backtest_date_range: BacktestDateRange
|
|
123
167
|
):
|
|
@@ -126,9 +170,9 @@ class BacktestService:
|
|
|
126
170
|
backtests for the given algorithms and return a list of backtest
|
|
127
171
|
reports.
|
|
128
172
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
173
|
+
Args:
|
|
174
|
+
algorithms: The algorithms to run the backtests for
|
|
175
|
+
backtest_date_range: The backtest date range of the backtests
|
|
132
176
|
|
|
133
177
|
Returns:
|
|
134
178
|
List - A list of backtest reports
|
|
@@ -146,6 +190,9 @@ class BacktestService:
|
|
|
146
190
|
return backtest_reports
|
|
147
191
|
|
|
148
192
|
def run_backtest_for_profile(self, algorithm, strategy, index_date):
|
|
193
|
+
self._configuration_service.add_value(
|
|
194
|
+
BACKTESTING_INDEX_DATETIME, index_date
|
|
195
|
+
)
|
|
149
196
|
algorithm.config[BACKTESTING_INDEX_DATETIME] = index_date
|
|
150
197
|
market_data = {}
|
|
151
198
|
|
|
@@ -173,7 +220,7 @@ class BacktestService:
|
|
|
173
220
|
calculate when the strategies should run based on the given start
|
|
174
221
|
and end date. The schedule will be stored in a pandas DataFrame.
|
|
175
222
|
|
|
176
|
-
|
|
223
|
+
Args:
|
|
177
224
|
strategies: The strategies to generate the schedule for
|
|
178
225
|
start_date: The start date of the schedule
|
|
179
226
|
end_date: The end date of the schedule
|
|
@@ -207,6 +254,7 @@ class BacktestService:
|
|
|
207
254
|
raise ValueError(f"Unsupported time unit: {time_unit}")
|
|
208
255
|
|
|
209
256
|
schedule_df = pd.DataFrame(data)
|
|
257
|
+
|
|
210
258
|
if schedule_df.empty:
|
|
211
259
|
raise OperationalException(
|
|
212
260
|
"Could not generate schedule "
|
|
@@ -253,7 +301,7 @@ class BacktestService:
|
|
|
253
301
|
BacktestReport: The backtest report instance of BacktestReport
|
|
254
302
|
"""
|
|
255
303
|
|
|
256
|
-
for portfolio in self.
|
|
304
|
+
for portfolio in self._portfolio_service.get_all():
|
|
257
305
|
ids = [strategy.strategy_id for strategy in algorithm.strategies]
|
|
258
306
|
|
|
259
307
|
# Check if strategy_id is None
|
|
@@ -440,7 +488,6 @@ class BacktestService:
|
|
|
440
488
|
if a ticker market data source is registered for the symbol and market.
|
|
441
489
|
"""
|
|
442
490
|
symbols = self._configuration_service.config[SYMBOLS]
|
|
443
|
-
print(symbols)
|
|
444
491
|
|
|
445
492
|
if symbols is not None:
|
|
446
493
|
|
|
@@ -61,7 +61,6 @@ class BacktestMarketDataSourceService(MarketDataSourceService):
|
|
|
61
61
|
.get_config()[BACKTESTING_START_DATE],
|
|
62
62
|
backtest_end_date=configuration_service
|
|
63
63
|
.get_config()[BACKTESTING_END_DATE],
|
|
64
|
-
market_credential_service=self._market_credential_service
|
|
65
64
|
)
|
|
66
65
|
|
|
67
66
|
def get_data(self, identifier):
|