investing-algorithm-framework 3.7.0__py3-none-any.whl → 7.19.15__py3-none-any.whl
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.
Potentially problematic release.
This version of investing-algorithm-framework might be problematic. Click here for more details.
- investing_algorithm_framework/__init__.py +168 -45
- investing_algorithm_framework/app/__init__.py +32 -1
- investing_algorithm_framework/app/algorithm/__init__.py +7 -0
- investing_algorithm_framework/app/algorithm/algorithm.py +239 -0
- investing_algorithm_framework/app/algorithm/algorithm_factory.py +114 -0
- investing_algorithm_framework/app/analysis/__init__.py +15 -0
- investing_algorithm_framework/app/analysis/backtest_data_ranges.py +121 -0
- investing_algorithm_framework/app/analysis/backtest_utils.py +107 -0
- investing_algorithm_framework/app/analysis/permutation.py +116 -0
- investing_algorithm_framework/app/analysis/ranking.py +297 -0
- investing_algorithm_framework/app/app.py +1933 -589
- investing_algorithm_framework/app/app_hook.py +28 -0
- investing_algorithm_framework/app/context.py +1725 -0
- investing_algorithm_framework/app/eventloop.py +590 -0
- investing_algorithm_framework/app/reporting/__init__.py +27 -0
- investing_algorithm_framework/app/reporting/ascii.py +921 -0
- investing_algorithm_framework/app/reporting/backtest_report.py +349 -0
- investing_algorithm_framework/app/reporting/charts/__init__.py +19 -0
- investing_algorithm_framework/app/reporting/charts/entry_exist_signals.py +66 -0
- investing_algorithm_framework/app/reporting/charts/equity_curve.py +37 -0
- investing_algorithm_framework/app/reporting/charts/equity_curve_drawdown.py +74 -0
- investing_algorithm_framework/app/reporting/charts/line_chart.py +11 -0
- investing_algorithm_framework/app/reporting/charts/monthly_returns_heatmap.py +70 -0
- investing_algorithm_framework/app/reporting/charts/ohlcv_data_completeness.py +51 -0
- investing_algorithm_framework/app/reporting/charts/rolling_sharp_ratio.py +79 -0
- investing_algorithm_framework/app/reporting/charts/yearly_returns_barchart.py +55 -0
- investing_algorithm_framework/app/reporting/generate.py +185 -0
- investing_algorithm_framework/app/reporting/tables/__init__.py +11 -0
- investing_algorithm_framework/app/reporting/tables/key_metrics_table.py +217 -0
- investing_algorithm_framework/app/reporting/tables/stop_loss_table.py +0 -0
- investing_algorithm_framework/app/reporting/tables/time_metrics_table.py +80 -0
- investing_algorithm_framework/app/reporting/tables/trade_metrics_table.py +147 -0
- investing_algorithm_framework/app/reporting/tables/trades_table.py +75 -0
- investing_algorithm_framework/app/reporting/tables/utils.py +29 -0
- investing_algorithm_framework/app/reporting/templates/report_template.html.j2 +154 -0
- investing_algorithm_framework/app/stateless/action_handlers/__init__.py +4 -2
- investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +1 -1
- investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +1 -1
- investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +14 -7
- investing_algorithm_framework/app/strategy.py +664 -84
- investing_algorithm_framework/app/task.py +5 -3
- investing_algorithm_framework/app/web/__init__.py +2 -1
- investing_algorithm_framework/app/web/create_app.py +4 -2
- investing_algorithm_framework/cli/__init__.py +0 -0
- investing_algorithm_framework/cli/cli.py +226 -0
- investing_algorithm_framework/cli/deploy_to_aws_lambda.py +501 -0
- investing_algorithm_framework/cli/deploy_to_azure_function.py +718 -0
- investing_algorithm_framework/cli/initialize_app.py +603 -0
- investing_algorithm_framework/cli/templates/.gitignore.template +178 -0
- investing_algorithm_framework/cli/templates/app.py.template +18 -0
- investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +48 -0
- investing_algorithm_framework/cli/templates/app_azure_function.py.template +14 -0
- investing_algorithm_framework/cli/templates/app_web.py.template +18 -0
- investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +22 -0
- investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +92 -0
- investing_algorithm_framework/cli/templates/aws_lambda_readme.md.template +110 -0
- investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +2 -0
- investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +65 -0
- investing_algorithm_framework/cli/templates/azure_function_host.json.template +15 -0
- investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +8 -0
- investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +3 -0
- investing_algorithm_framework/cli/templates/data_providers.py.template +17 -0
- investing_algorithm_framework/cli/templates/env.example.template +2 -0
- investing_algorithm_framework/cli/templates/env_azure_function.example.template +4 -0
- investing_algorithm_framework/cli/templates/market_data_providers.py.template +9 -0
- investing_algorithm_framework/cli/templates/readme.md.template +135 -0
- investing_algorithm_framework/cli/templates/requirements.txt.template +2 -0
- investing_algorithm_framework/cli/templates/run_backtest.py.template +20 -0
- investing_algorithm_framework/cli/templates/strategy.py.template +124 -0
- investing_algorithm_framework/create_app.py +40 -6
- investing_algorithm_framework/dependency_container.py +72 -56
- investing_algorithm_framework/domain/__init__.py +71 -47
- investing_algorithm_framework/domain/backtesting/__init__.py +21 -0
- investing_algorithm_framework/domain/backtesting/backtest.py +503 -0
- investing_algorithm_framework/domain/backtesting/backtest_date_range.py +96 -0
- investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +242 -0
- investing_algorithm_framework/domain/backtesting/backtest_metrics.py +459 -0
- investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +275 -0
- investing_algorithm_framework/domain/backtesting/backtest_run.py +605 -0
- investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +162 -0
- investing_algorithm_framework/domain/backtesting/combine_backtests.py +280 -0
- investing_algorithm_framework/domain/config.py +59 -91
- investing_algorithm_framework/domain/constants.py +13 -38
- investing_algorithm_framework/domain/data_provider.py +334 -0
- investing_algorithm_framework/domain/data_structures.py +3 -2
- investing_algorithm_framework/domain/exceptions.py +51 -1
- investing_algorithm_framework/domain/models/__init__.py +17 -12
- investing_algorithm_framework/domain/models/data/__init__.py +7 -0
- investing_algorithm_framework/domain/models/data/data_source.py +214 -0
- investing_algorithm_framework/domain/models/data/data_type.py +46 -0
- investing_algorithm_framework/domain/models/event.py +35 -0
- investing_algorithm_framework/domain/models/market/market_credential.py +55 -1
- investing_algorithm_framework/domain/models/order/order.py +77 -83
- investing_algorithm_framework/domain/models/order/order_status.py +2 -2
- investing_algorithm_framework/domain/models/order/order_type.py +1 -3
- investing_algorithm_framework/domain/models/portfolio/portfolio.py +81 -3
- investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +26 -3
- investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +108 -11
- investing_algorithm_framework/domain/models/position/__init__.py +2 -1
- investing_algorithm_framework/domain/models/position/position.py +12 -0
- investing_algorithm_framework/domain/models/position/position_size.py +41 -0
- investing_algorithm_framework/domain/models/risk_rules/__init__.py +7 -0
- investing_algorithm_framework/domain/models/risk_rules/stop_loss_rule.py +51 -0
- investing_algorithm_framework/domain/models/risk_rules/take_profit_rule.py +55 -0
- investing_algorithm_framework/domain/models/snapshot_interval.py +45 -0
- investing_algorithm_framework/domain/models/strategy_profile.py +19 -151
- investing_algorithm_framework/domain/models/time_frame.py +37 -0
- investing_algorithm_framework/domain/models/time_interval.py +33 -0
- investing_algorithm_framework/domain/models/time_unit.py +66 -2
- investing_algorithm_framework/domain/models/trade/__init__.py +8 -1
- investing_algorithm_framework/domain/models/trade/trade.py +295 -171
- investing_algorithm_framework/domain/models/trade/trade_status.py +9 -2
- investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +332 -0
- investing_algorithm_framework/domain/models/trade/trade_take_profit.py +365 -0
- investing_algorithm_framework/domain/order_executor.py +112 -0
- investing_algorithm_framework/domain/portfolio_provider.py +118 -0
- investing_algorithm_framework/domain/services/__init__.py +2 -9
- investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +0 -6
- investing_algorithm_framework/domain/services/state_handler.py +38 -0
- investing_algorithm_framework/domain/strategy.py +1 -29
- investing_algorithm_framework/domain/utils/__init__.py +12 -7
- investing_algorithm_framework/domain/utils/custom_tqdm.py +22 -0
- investing_algorithm_framework/domain/utils/dates.py +57 -0
- investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +19 -0
- investing_algorithm_framework/domain/utils/polars.py +53 -0
- investing_algorithm_framework/domain/utils/random.py +29 -0
- investing_algorithm_framework/download_data.py +108 -0
- investing_algorithm_framework/infrastructure/__init__.py +31 -18
- investing_algorithm_framework/infrastructure/data_providers/__init__.py +36 -0
- investing_algorithm_framework/infrastructure/data_providers/ccxt.py +1143 -0
- investing_algorithm_framework/infrastructure/data_providers/csv.py +568 -0
- investing_algorithm_framework/infrastructure/data_providers/pandas.py +599 -0
- investing_algorithm_framework/infrastructure/database/__init__.py +6 -2
- investing_algorithm_framework/infrastructure/database/sql_alchemy.py +86 -12
- investing_algorithm_framework/infrastructure/models/__init__.py +6 -11
- investing_algorithm_framework/infrastructure/models/order/__init__.py +2 -1
- investing_algorithm_framework/infrastructure/models/order/order.py +35 -49
- investing_algorithm_framework/infrastructure/models/order/order_metadata.py +44 -0
- investing_algorithm_framework/infrastructure/models/order_trade_association.py +10 -0
- investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +1 -1
- investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +8 -0
- investing_algorithm_framework/infrastructure/models/portfolio/{portfolio.py → sql_portfolio.py} +17 -5
- investing_algorithm_framework/infrastructure/models/trades/__init__.py +9 -0
- investing_algorithm_framework/infrastructure/models/trades/trade.py +130 -0
- investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +59 -0
- investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +55 -0
- investing_algorithm_framework/infrastructure/order_executors/__init__.py +21 -0
- investing_algorithm_framework/infrastructure/order_executors/backtest_oder_executor.py +28 -0
- investing_algorithm_framework/infrastructure/order_executors/ccxt_order_executor.py +200 -0
- investing_algorithm_framework/infrastructure/portfolio_providers/__init__.py +19 -0
- investing_algorithm_framework/infrastructure/portfolio_providers/ccxt_portfolio_provider.py +199 -0
- investing_algorithm_framework/infrastructure/repositories/__init__.py +8 -0
- investing_algorithm_framework/infrastructure/repositories/order_metadata_repository.py +17 -0
- investing_algorithm_framework/infrastructure/repositories/order_repository.py +5 -0
- investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +1 -1
- investing_algorithm_framework/infrastructure/repositories/position_repository.py +11 -0
- investing_algorithm_framework/infrastructure/repositories/repository.py +81 -27
- investing_algorithm_framework/infrastructure/repositories/trade_repository.py +71 -0
- investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +29 -0
- investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +29 -0
- investing_algorithm_framework/infrastructure/services/__init__.py +4 -4
- investing_algorithm_framework/infrastructure/services/aws/__init__.py +6 -0
- investing_algorithm_framework/infrastructure/services/aws/state_handler.py +113 -0
- investing_algorithm_framework/infrastructure/services/azure/__init__.py +5 -0
- investing_algorithm_framework/infrastructure/services/azure/state_handler.py +158 -0
- investing_algorithm_framework/services/__init__.py +113 -16
- investing_algorithm_framework/services/backtesting/__init__.py +0 -7
- investing_algorithm_framework/services/backtesting/backtest_service.py +566 -359
- investing_algorithm_framework/services/configuration_service.py +77 -11
- investing_algorithm_framework/services/data_providers/__init__.py +5 -0
- investing_algorithm_framework/services/data_providers/data_provider_service.py +850 -0
- investing_algorithm_framework/services/market_credential_service.py +16 -1
- investing_algorithm_framework/services/metrics/__init__.py +114 -0
- investing_algorithm_framework/services/metrics/alpha.py +0 -0
- investing_algorithm_framework/services/metrics/beta.py +0 -0
- investing_algorithm_framework/services/metrics/cagr.py +60 -0
- investing_algorithm_framework/services/metrics/calmar_ratio.py +40 -0
- investing_algorithm_framework/services/metrics/drawdown.py +181 -0
- investing_algorithm_framework/services/metrics/equity_curve.py +24 -0
- investing_algorithm_framework/services/metrics/exposure.py +210 -0
- investing_algorithm_framework/services/metrics/generate.py +358 -0
- investing_algorithm_framework/services/metrics/mean_daily_return.py +83 -0
- investing_algorithm_framework/services/metrics/profit_factor.py +165 -0
- investing_algorithm_framework/services/metrics/recovery.py +113 -0
- investing_algorithm_framework/services/metrics/returns.py +452 -0
- investing_algorithm_framework/services/metrics/risk_free_rate.py +28 -0
- investing_algorithm_framework/services/metrics/sharpe_ratio.py +137 -0
- investing_algorithm_framework/services/metrics/sortino_ratio.py +74 -0
- investing_algorithm_framework/services/metrics/standard_deviation.py +157 -0
- investing_algorithm_framework/services/metrics/trades.py +500 -0
- investing_algorithm_framework/services/metrics/treynor_ratio.py +0 -0
- investing_algorithm_framework/services/metrics/ulcer.py +0 -0
- investing_algorithm_framework/services/metrics/value_at_risk.py +0 -0
- investing_algorithm_framework/services/metrics/volatility.py +97 -0
- investing_algorithm_framework/services/metrics/win_rate.py +177 -0
- investing_algorithm_framework/services/order_service/__init__.py +3 -1
- investing_algorithm_framework/services/order_service/order_backtest_service.py +76 -89
- investing_algorithm_framework/services/order_service/order_executor_lookup.py +110 -0
- investing_algorithm_framework/services/order_service/order_service.py +407 -326
- investing_algorithm_framework/services/portfolios/__init__.py +3 -1
- investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +37 -3
- investing_algorithm_framework/services/portfolios/portfolio_configuration_service.py +22 -8
- investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +106 -0
- investing_algorithm_framework/services/portfolios/portfolio_service.py +96 -28
- investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +97 -28
- investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +116 -313
- investing_algorithm_framework/services/positions/__init__.py +7 -0
- investing_algorithm_framework/services/positions/position_service.py +210 -0
- investing_algorithm_framework/services/repository_service.py +8 -2
- investing_algorithm_framework/services/trade_order_evaluator/__init__.py +9 -0
- investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +113 -0
- investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +51 -0
- investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +80 -0
- investing_algorithm_framework/services/trade_service/__init__.py +7 -1
- investing_algorithm_framework/services/trade_service/trade_service.py +1013 -315
- investing_algorithm_framework/services/trade_service/trade_stop_loss_service.py +39 -0
- investing_algorithm_framework/services/trade_service/trade_take_profit_service.py +41 -0
- investing_algorithm_framework-7.19.15.dist-info/METADATA +537 -0
- investing_algorithm_framework-7.19.15.dist-info/RECORD +263 -0
- investing_algorithm_framework-7.19.15.dist-info/entry_points.txt +3 -0
- investing_algorithm_framework/app/algorithm.py +0 -1105
- investing_algorithm_framework/domain/graphs.py +0 -382
- investing_algorithm_framework/domain/metrics/__init__.py +0 -6
- investing_algorithm_framework/domain/models/backtesting/__init__.py +0 -11
- investing_algorithm_framework/domain/models/backtesting/backtest_date_range.py +0 -43
- investing_algorithm_framework/domain/models/backtesting/backtest_position.py +0 -120
- investing_algorithm_framework/domain/models/backtesting/backtest_report.py +0 -580
- investing_algorithm_framework/domain/models/backtesting/backtest_reports_evaluation.py +0 -243
- investing_algorithm_framework/domain/models/trading_data_types.py +0 -47
- investing_algorithm_framework/domain/models/trading_time_frame.py +0 -223
- investing_algorithm_framework/domain/services/market_data_sources.py +0 -344
- investing_algorithm_framework/domain/services/market_service.py +0 -153
- investing_algorithm_framework/domain/singleton.py +0 -9
- investing_algorithm_framework/domain/utils/backtesting.py +0 -472
- investing_algorithm_framework/infrastructure/models/market_data_sources/__init__.py +0 -12
- investing_algorithm_framework/infrastructure/models/market_data_sources/ccxt.py +0 -559
- investing_algorithm_framework/infrastructure/models/market_data_sources/csv.py +0 -254
- investing_algorithm_framework/infrastructure/models/market_data_sources/us_treasury_yield.py +0 -47
- investing_algorithm_framework/infrastructure/services/market_service/__init__.py +0 -5
- investing_algorithm_framework/infrastructure/services/market_service/ccxt_market_service.py +0 -455
- investing_algorithm_framework/infrastructure/services/performance_service/__init__.py +0 -7
- investing_algorithm_framework/infrastructure/services/performance_service/backtest_performance_service.py +0 -2
- investing_algorithm_framework/infrastructure/services/performance_service/performance_service.py +0 -350
- investing_algorithm_framework/services/backtesting/backtest_report_writer_service.py +0 -53
- investing_algorithm_framework/services/backtesting/graphs.py +0 -61
- investing_algorithm_framework/services/market_data_source_service/__init__.py +0 -8
- investing_algorithm_framework/services/market_data_source_service/backtest_market_data_source_service.py +0 -150
- investing_algorithm_framework/services/market_data_source_service/market_data_source_service.py +0 -189
- investing_algorithm_framework/services/position_service.py +0 -31
- investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -264
- investing_algorithm_framework-3.7.0.dist-info/METADATA +0 -339
- investing_algorithm_framework-3.7.0.dist-info/RECORD +0 -147
- /investing_algorithm_framework/{domain → services}/metrics/price_efficiency.py +0 -0
- /investing_algorithm_framework/services/{position_snapshot_service.py → positions/position_snapshot_service.py} +0 -0
- {investing_algorithm_framework-3.7.0.dist-info → investing_algorithm_framework-7.19.15.dist-info}/LICENSE +0 -0
- {investing_algorithm_framework-3.7.0.dist-info → investing_algorithm_framework-7.19.15.dist-info}/WHEEL +0 -0
|
@@ -1,580 +0,0 @@
|
|
|
1
|
-
from datetime import datetime
|
|
2
|
-
from logging import getLogger
|
|
3
|
-
|
|
4
|
-
from pandas import DataFrame
|
|
5
|
-
|
|
6
|
-
from investing_algorithm_framework.domain.constants import DATETIME_FORMAT
|
|
7
|
-
from investing_algorithm_framework.domain.metrics import \
|
|
8
|
-
get_price_efficiency_ratio
|
|
9
|
-
from investing_algorithm_framework.domain.models \
|
|
10
|
-
.backtesting.backtest_date_range import BacktestDateRange
|
|
11
|
-
from investing_algorithm_framework.domain.models.base_model import BaseModel
|
|
12
|
-
from investing_algorithm_framework.domain.models.time_unit import TimeUnit
|
|
13
|
-
|
|
14
|
-
logger = getLogger(__name__)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class BacktestReport(BaseModel):
|
|
18
|
-
"""
|
|
19
|
-
Class that represents a backtest report. The backtest report
|
|
20
|
-
contains information about the backtest.
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
def __init__(
|
|
24
|
-
self,
|
|
25
|
-
backtest_date_range: BacktestDateRange,
|
|
26
|
-
name=None,
|
|
27
|
-
time_unit=None,
|
|
28
|
-
interval=0,
|
|
29
|
-
strategy_identifiers=None,
|
|
30
|
-
initial_unallocated=0.0,
|
|
31
|
-
number_of_runs=0,
|
|
32
|
-
trading_time_frame=None,
|
|
33
|
-
trading_time_frame_start_date=None,
|
|
34
|
-
symbols=None,
|
|
35
|
-
market=None,
|
|
36
|
-
number_of_orders=0,
|
|
37
|
-
number_of_positions=0,
|
|
38
|
-
market_data_file=None,
|
|
39
|
-
number_of_trades_closed=0,
|
|
40
|
-
number_of_trades_open=0,
|
|
41
|
-
percentage_positive_trades=0.0,
|
|
42
|
-
percentage_negative_trades=0.0,
|
|
43
|
-
total_cost=0.0,
|
|
44
|
-
trading_symbol=None,
|
|
45
|
-
total_net_gain_percentage=0.0,
|
|
46
|
-
total_net_gain=0.0,
|
|
47
|
-
growth_rate=0.0,
|
|
48
|
-
growth=0.0,
|
|
49
|
-
total_value=0.0,
|
|
50
|
-
positions=None,
|
|
51
|
-
average_trade_duration=0,
|
|
52
|
-
average_trade_size=0.0,
|
|
53
|
-
trades=None,
|
|
54
|
-
orders=None,
|
|
55
|
-
created_at: datetime = None,
|
|
56
|
-
context=None,
|
|
57
|
-
):
|
|
58
|
-
self._traces = {}
|
|
59
|
-
self.metrics = {}
|
|
60
|
-
self._name = name
|
|
61
|
-
self._strategy_identifiers = strategy_identifiers
|
|
62
|
-
self.backtest_date_range = backtest_date_range
|
|
63
|
-
self._number_of_runs = number_of_runs
|
|
64
|
-
self._trading_time_frame = trading_time_frame
|
|
65
|
-
self._trading_time_frame_start_date = trading_time_frame_start_date
|
|
66
|
-
self._market = market
|
|
67
|
-
self._number_of_orders = number_of_orders
|
|
68
|
-
self._number_of_positions = number_of_positions
|
|
69
|
-
self._market_data_file = market_data_file
|
|
70
|
-
self._percentage_positive_trades = percentage_positive_trades
|
|
71
|
-
self._percentage_negative_trades = percentage_negative_trades
|
|
72
|
-
self._number_of_trades_closed = number_of_trades_closed
|
|
73
|
-
self._number_of_trades_open = number_of_trades_open
|
|
74
|
-
self._total_cost = total_cost
|
|
75
|
-
self._growth_rate = growth_rate
|
|
76
|
-
self._growth = growth
|
|
77
|
-
self._initial_unallocated = initial_unallocated
|
|
78
|
-
self._trading_symbol = trading_symbol
|
|
79
|
-
self._total_net_gain_percentage = total_net_gain_percentage
|
|
80
|
-
self._total_net_gain = total_net_gain
|
|
81
|
-
self._total_value = total_value
|
|
82
|
-
self._positions = positions
|
|
83
|
-
self._orders = orders
|
|
84
|
-
self._average_trade_duration = average_trade_duration
|
|
85
|
-
self._average_trade_size = average_trade_size
|
|
86
|
-
self._trades = trades
|
|
87
|
-
self._created_at: datetime = created_at
|
|
88
|
-
self._interval = interval
|
|
89
|
-
self._time_unit = time_unit
|
|
90
|
-
self._context = context
|
|
91
|
-
|
|
92
|
-
self._symbols = symbols
|
|
93
|
-
|
|
94
|
-
if self._symbols is None:
|
|
95
|
-
self._symbols = []
|
|
96
|
-
|
|
97
|
-
self._number_of_days = \
|
|
98
|
-
(self.backtest_date_range.end_date
|
|
99
|
-
- self.backtest_date_range.start_date).days
|
|
100
|
-
|
|
101
|
-
@property
|
|
102
|
-
def name(self):
|
|
103
|
-
return self._name
|
|
104
|
-
|
|
105
|
-
@property
|
|
106
|
-
def strategy_identifiers(self):
|
|
107
|
-
return self._strategy_identifiers
|
|
108
|
-
|
|
109
|
-
@property
|
|
110
|
-
def created_at(self):
|
|
111
|
-
return self._created_at
|
|
112
|
-
|
|
113
|
-
@property
|
|
114
|
-
def portfolio_id(self):
|
|
115
|
-
return self._portfolio_id
|
|
116
|
-
|
|
117
|
-
@portfolio_id.setter
|
|
118
|
-
def portfolio_id(self, portfolio_id):
|
|
119
|
-
self._portfolio_id = portfolio_id
|
|
120
|
-
|
|
121
|
-
@property
|
|
122
|
-
def symbols(self):
|
|
123
|
-
return self._symbols
|
|
124
|
-
|
|
125
|
-
@property
|
|
126
|
-
def trading_time_frame(self):
|
|
127
|
-
return self._trading_time_frame
|
|
128
|
-
|
|
129
|
-
@property
|
|
130
|
-
def trading_time_frame_start_date(self):
|
|
131
|
-
return self._trading_time_frame_start_date
|
|
132
|
-
|
|
133
|
-
@property
|
|
134
|
-
def number_of_runs(self):
|
|
135
|
-
return self._number_of_runs
|
|
136
|
-
|
|
137
|
-
@property
|
|
138
|
-
def market(self):
|
|
139
|
-
return self._market
|
|
140
|
-
|
|
141
|
-
@property
|
|
142
|
-
def number_of_days(self):
|
|
143
|
-
return self._number_of_days
|
|
144
|
-
|
|
145
|
-
@symbols.setter
|
|
146
|
-
def symbols(self, value):
|
|
147
|
-
self._symbols = value
|
|
148
|
-
|
|
149
|
-
@market.setter
|
|
150
|
-
def market(self, value):
|
|
151
|
-
self._market = value
|
|
152
|
-
|
|
153
|
-
@number_of_runs.setter
|
|
154
|
-
def number_of_runs(self, value):
|
|
155
|
-
self._number_of_runs = value
|
|
156
|
-
|
|
157
|
-
@trading_time_frame.setter
|
|
158
|
-
def trading_time_frame(self, value):
|
|
159
|
-
self._trading_time_frame = value
|
|
160
|
-
|
|
161
|
-
@trading_time_frame_start_date.setter
|
|
162
|
-
def trading_time_frame_start_date(self, value):
|
|
163
|
-
self._trading_time_frame_start_date = value
|
|
164
|
-
|
|
165
|
-
@property
|
|
166
|
-
def number_of_orders(self):
|
|
167
|
-
return self._number_of_orders
|
|
168
|
-
|
|
169
|
-
@number_of_orders.setter
|
|
170
|
-
def number_of_orders(self, value):
|
|
171
|
-
self._number_of_orders = value
|
|
172
|
-
|
|
173
|
-
@property
|
|
174
|
-
def number_of_positions(self):
|
|
175
|
-
return self._number_of_positions
|
|
176
|
-
|
|
177
|
-
@number_of_positions.setter
|
|
178
|
-
def number_of_positions(self, value):
|
|
179
|
-
self._number_of_positions = value
|
|
180
|
-
|
|
181
|
-
@property
|
|
182
|
-
def backtest_data_index_date(self):
|
|
183
|
-
return self._backtest_data_index_date
|
|
184
|
-
|
|
185
|
-
@backtest_data_index_date.setter
|
|
186
|
-
def backtest_data_index_date(self, value):
|
|
187
|
-
self._backtest_data_index_date = value
|
|
188
|
-
|
|
189
|
-
@property
|
|
190
|
-
def market_data_file(self):
|
|
191
|
-
return self._market_data_file
|
|
192
|
-
|
|
193
|
-
@market_data_file.setter
|
|
194
|
-
def market_data_file(self, value):
|
|
195
|
-
self._market_data_file = value
|
|
196
|
-
|
|
197
|
-
@property
|
|
198
|
-
def percentage_positive_trades(self):
|
|
199
|
-
return float(self._percentage_positive_trades)
|
|
200
|
-
|
|
201
|
-
@percentage_positive_trades.setter
|
|
202
|
-
def percentage_positive_trades(self, value):
|
|
203
|
-
self._percentage_positive_trades = value
|
|
204
|
-
|
|
205
|
-
@property
|
|
206
|
-
def percentage_negative_trades(self):
|
|
207
|
-
return float(self._percentage_negative_trades)
|
|
208
|
-
|
|
209
|
-
@percentage_negative_trades.setter
|
|
210
|
-
def percentage_negative_trades(self, value):
|
|
211
|
-
self._percentage_negative_trades = value
|
|
212
|
-
|
|
213
|
-
@property
|
|
214
|
-
def number_of_trades_closed(self):
|
|
215
|
-
return self._number_of_trades_closed
|
|
216
|
-
|
|
217
|
-
@number_of_trades_closed.setter
|
|
218
|
-
def number_of_trades_closed(self, value):
|
|
219
|
-
self._number_of_trades_closed = value
|
|
220
|
-
|
|
221
|
-
@property
|
|
222
|
-
def number_of_trades_open(self):
|
|
223
|
-
return self._number_of_trades_open
|
|
224
|
-
|
|
225
|
-
@number_of_trades_open.setter
|
|
226
|
-
def number_of_trades_open(self, value):
|
|
227
|
-
self._number_of_trades_open = value
|
|
228
|
-
|
|
229
|
-
@property
|
|
230
|
-
def total_cost(self):
|
|
231
|
-
return self._total_cost
|
|
232
|
-
|
|
233
|
-
@total_cost.setter
|
|
234
|
-
def total_cost(self, value):
|
|
235
|
-
self._total_cost = value
|
|
236
|
-
|
|
237
|
-
@property
|
|
238
|
-
def growth_rate(self):
|
|
239
|
-
return self._growth_rate
|
|
240
|
-
|
|
241
|
-
@growth_rate.setter
|
|
242
|
-
def growth_rate(self, value):
|
|
243
|
-
self._growth_rate = value
|
|
244
|
-
|
|
245
|
-
@property
|
|
246
|
-
def growth(self):
|
|
247
|
-
return self._growth
|
|
248
|
-
|
|
249
|
-
@growth.setter
|
|
250
|
-
def growth(self, value):
|
|
251
|
-
self._growth = value
|
|
252
|
-
|
|
253
|
-
@property
|
|
254
|
-
def initial_unallocated(self):
|
|
255
|
-
return self._initial_unallocated
|
|
256
|
-
|
|
257
|
-
@initial_unallocated.setter
|
|
258
|
-
def initial_unallocated(self, value):
|
|
259
|
-
self._initial_unallocated = value
|
|
260
|
-
|
|
261
|
-
@property
|
|
262
|
-
def trading_symbol(self):
|
|
263
|
-
return self._trading_symbol
|
|
264
|
-
|
|
265
|
-
@trading_symbol.setter
|
|
266
|
-
def trading_symbol(self, value):
|
|
267
|
-
self._trading_symbol = value
|
|
268
|
-
|
|
269
|
-
@property
|
|
270
|
-
def total_net_gain_percentage(self):
|
|
271
|
-
return self._total_net_gain_percentage
|
|
272
|
-
|
|
273
|
-
@total_net_gain_percentage.setter
|
|
274
|
-
def total_net_gain_percentage(self, value):
|
|
275
|
-
self._total_net_gain_percentage = value
|
|
276
|
-
|
|
277
|
-
@property
|
|
278
|
-
def total_net_gain(self):
|
|
279
|
-
return self._total_net_gain
|
|
280
|
-
|
|
281
|
-
@total_net_gain.setter
|
|
282
|
-
def total_net_gain(self, value):
|
|
283
|
-
self._total_net_gain = value
|
|
284
|
-
|
|
285
|
-
@property
|
|
286
|
-
def total_value(self):
|
|
287
|
-
return self._total_value
|
|
288
|
-
|
|
289
|
-
@total_value.setter
|
|
290
|
-
def total_value(self, value):
|
|
291
|
-
self._total_value = value
|
|
292
|
-
|
|
293
|
-
@property
|
|
294
|
-
def positions(self):
|
|
295
|
-
return self._positions
|
|
296
|
-
|
|
297
|
-
@positions.setter
|
|
298
|
-
def positions(self, value):
|
|
299
|
-
self._positions = value
|
|
300
|
-
|
|
301
|
-
@property
|
|
302
|
-
def orders(self):
|
|
303
|
-
return self._orders
|
|
304
|
-
|
|
305
|
-
@orders.setter
|
|
306
|
-
def orders(self, value):
|
|
307
|
-
self._orders = value
|
|
308
|
-
|
|
309
|
-
@property
|
|
310
|
-
def average_trade_duration(self):
|
|
311
|
-
return self._average_trade_duration
|
|
312
|
-
|
|
313
|
-
@average_trade_duration.setter
|
|
314
|
-
def average_trade_duration(self, value):
|
|
315
|
-
self._average_trade_duration = value
|
|
316
|
-
|
|
317
|
-
@property
|
|
318
|
-
def average_trade_size(self):
|
|
319
|
-
return self._average_trade_size
|
|
320
|
-
|
|
321
|
-
@average_trade_size.setter
|
|
322
|
-
def average_trade_size(self, value):
|
|
323
|
-
self._average_trade_size = value
|
|
324
|
-
|
|
325
|
-
@property
|
|
326
|
-
def trades(self):
|
|
327
|
-
return self._trades
|
|
328
|
-
|
|
329
|
-
@trades.setter
|
|
330
|
-
def trades(self, value):
|
|
331
|
-
self._trades = value
|
|
332
|
-
|
|
333
|
-
@property
|
|
334
|
-
def interval(self):
|
|
335
|
-
return self._interval
|
|
336
|
-
|
|
337
|
-
@interval.setter
|
|
338
|
-
def interval(self, value):
|
|
339
|
-
self._interval = value
|
|
340
|
-
|
|
341
|
-
@property
|
|
342
|
-
def context(self):
|
|
343
|
-
return self._context
|
|
344
|
-
|
|
345
|
-
@context.setter
|
|
346
|
-
def context(self, value):
|
|
347
|
-
self._context = value
|
|
348
|
-
|
|
349
|
-
@property
|
|
350
|
-
def time_unit(self):
|
|
351
|
-
return self._time_unit
|
|
352
|
-
|
|
353
|
-
@time_unit.setter
|
|
354
|
-
def time_unit(self, value):
|
|
355
|
-
self._time_unit = value
|
|
356
|
-
|
|
357
|
-
def get_runs_per_day(self):
|
|
358
|
-
|
|
359
|
-
if self.time_unit is None:
|
|
360
|
-
return 0
|
|
361
|
-
elif TimeUnit.SECOND.equals(self.time_unit):
|
|
362
|
-
return 86400 / self.interval
|
|
363
|
-
elif TimeUnit.MINUTE.equals(self.time_unit):
|
|
364
|
-
return 1440 / self.interval
|
|
365
|
-
else:
|
|
366
|
-
return 24 / self.interval
|
|
367
|
-
|
|
368
|
-
@property
|
|
369
|
-
def backtest_start_date(self):
|
|
370
|
-
return self.backtest_date_range.start_date
|
|
371
|
-
|
|
372
|
-
@property
|
|
373
|
-
def backtest_end_date(self):
|
|
374
|
-
return self.backtest_date_range.end_date
|
|
375
|
-
|
|
376
|
-
def __repr__(self):
|
|
377
|
-
return self.repr(
|
|
378
|
-
name=self.name,
|
|
379
|
-
backtest_date_range=self.backtest_date_range,
|
|
380
|
-
profit=self.get_profit(),
|
|
381
|
-
profit_percentage=self.get_profit_percentage(),
|
|
382
|
-
growth=self.get_growth(),
|
|
383
|
-
growth_percentage=self.get_growth_percentage(),
|
|
384
|
-
)
|
|
385
|
-
|
|
386
|
-
def to_dict(self):
|
|
387
|
-
"""
|
|
388
|
-
Convert the backtest report to a dictionary. So it can be
|
|
389
|
-
saved to a file.
|
|
390
|
-
"""
|
|
391
|
-
|
|
392
|
-
# Convert context to a dictionary
|
|
393
|
-
if self.context is not None:
|
|
394
|
-
|
|
395
|
-
for key, value in self.context.items():
|
|
396
|
-
if isinstance(value, datetime):
|
|
397
|
-
self.context[key] = value.strftime(DATETIME_FORMAT)
|
|
398
|
-
|
|
399
|
-
if isinstance(value, DataFrame):
|
|
400
|
-
self.context[key] = value.to_json()
|
|
401
|
-
|
|
402
|
-
return {
|
|
403
|
-
"name": self.name,
|
|
404
|
-
"context": self.context if self.context is not None else {},
|
|
405
|
-
"strategy_identifiers": self.strategy_identifiers,
|
|
406
|
-
"backtest_date_range_identifier": self.backtest_date_range.name,
|
|
407
|
-
"backtest_start_date": self.backtest_date_range.start_date
|
|
408
|
-
.strftime(DATETIME_FORMAT),
|
|
409
|
-
"backtest_end_date": self.backtest_date_range.end_date
|
|
410
|
-
.strftime(DATETIME_FORMAT),
|
|
411
|
-
"number_of_runs": self.number_of_runs,
|
|
412
|
-
"symbols": self.symbols,
|
|
413
|
-
"market": self.market,
|
|
414
|
-
"number_of_days": self.number_of_days,
|
|
415
|
-
"number_of_orders": self.number_of_orders,
|
|
416
|
-
"number_of_positions": self.number_of_positions,
|
|
417
|
-
"market_data_file": self.market_data_file,
|
|
418
|
-
"percentage_positive_trades": self.percentage_positive_trades,
|
|
419
|
-
"percentage_negative_trades": self.percentage_negative_trades,
|
|
420
|
-
"number_of_trades_closed": self.number_of_trades_closed,
|
|
421
|
-
"number_of_trades_open": self.number_of_trades_open,
|
|
422
|
-
"total_cost": self.total_cost,
|
|
423
|
-
"growth_rate": self.growth_rate,
|
|
424
|
-
"growth": self.growth,
|
|
425
|
-
"initial_unallocated": self.initial_unallocated,
|
|
426
|
-
"trading_symbol": self.trading_symbol,
|
|
427
|
-
"total_net_gain_percentage": self.total_net_gain_percentage,
|
|
428
|
-
"total_net_gain": self.total_net_gain,
|
|
429
|
-
"total_value": self.total_value,
|
|
430
|
-
"average_trade_duration": self.average_trade_duration,
|
|
431
|
-
"average_trade_size": self.average_trade_size,
|
|
432
|
-
"positions": [position.to_dict() for position in self.positions],
|
|
433
|
-
"trades": [trade.to_dict() for trade in self.trades],
|
|
434
|
-
"orders": [
|
|
435
|
-
order.to_dict(datetime_format=DATETIME_FORMAT)
|
|
436
|
-
for order in self.orders
|
|
437
|
-
],
|
|
438
|
-
"created_at": self.created_at.strftime(DATETIME_FORMAT),
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
@staticmethod
|
|
442
|
-
def from_dict(data):
|
|
443
|
-
"""
|
|
444
|
-
Factory method to create a backtest report from a dictionary.
|
|
445
|
-
"""
|
|
446
|
-
|
|
447
|
-
backtest_date_range = BacktestDateRange(
|
|
448
|
-
start_date=datetime.strptime(
|
|
449
|
-
data["backtest_start_date"], DATETIME_FORMAT),
|
|
450
|
-
end_date=datetime.strptime(
|
|
451
|
-
data["backtest_end_date"], DATETIME_FORMAT)
|
|
452
|
-
)
|
|
453
|
-
|
|
454
|
-
return BacktestReport(
|
|
455
|
-
name=data["name"],
|
|
456
|
-
strategy_identifiers=data["strategy_identifiers"],
|
|
457
|
-
number_of_runs=data["number_of_runs"],
|
|
458
|
-
backtest_date_range=backtest_date_range,
|
|
459
|
-
symbols=data["symbols"],
|
|
460
|
-
market=data["market"],
|
|
461
|
-
number_of_orders=data["number_of_orders"],
|
|
462
|
-
number_of_positions=data["number_of_positions"],
|
|
463
|
-
market_data_file=data["market_data_file"],
|
|
464
|
-
percentage_positive_trades=data["percentage_positive_trades"],
|
|
465
|
-
percentage_negative_trades=data["percentage_negative_trades"],
|
|
466
|
-
number_of_trades_closed=data["number_of_trades_closed"],
|
|
467
|
-
number_of_trades_open=data["number_of_trades_open"],
|
|
468
|
-
total_cost=float(data["total_cost"]),
|
|
469
|
-
growth_rate=float(data["growth_rate"]),
|
|
470
|
-
growth=float(data["growth"]),
|
|
471
|
-
initial_unallocated=float(data["initial_unallocated"]),
|
|
472
|
-
trading_symbol=data["trading_symbol"],
|
|
473
|
-
total_net_gain_percentage=float(data["total_net_gain_percentage"]),
|
|
474
|
-
total_net_gain=float(data["total_net_gain"]),
|
|
475
|
-
total_value=float(data["total_value"]),
|
|
476
|
-
average_trade_duration=data["average_trade_duration"],
|
|
477
|
-
average_trade_size=float(data["average_trade_size"]),
|
|
478
|
-
)
|
|
479
|
-
|
|
480
|
-
def get_trades(self, symbol=None):
|
|
481
|
-
"""
|
|
482
|
-
Function to get trades. If a symbol is provided, it will
|
|
483
|
-
return the trades for that symbol. If no symbol is provided,
|
|
484
|
-
it will return all the trades.
|
|
485
|
-
"""
|
|
486
|
-
if symbol is None:
|
|
487
|
-
return self.trades
|
|
488
|
-
|
|
489
|
-
return [trade for trade in self.trades if trade.symbol == symbol]
|
|
490
|
-
|
|
491
|
-
def get_profit(self) -> float:
|
|
492
|
-
return self._total_net_gain
|
|
493
|
-
|
|
494
|
-
def get_profit_percentage(self) -> float:
|
|
495
|
-
return self._total_net_gain_percentage
|
|
496
|
-
|
|
497
|
-
def get_growth(self) -> float:
|
|
498
|
-
return self._growth
|
|
499
|
-
|
|
500
|
-
def get_growth_percentage(self) -> float:
|
|
501
|
-
return self._growth_rate
|
|
502
|
-
|
|
503
|
-
def get_trading_symbol(self) -> str:
|
|
504
|
-
return self.trading_symbol
|
|
505
|
-
|
|
506
|
-
def add_symbol(self, symbol):
|
|
507
|
-
|
|
508
|
-
if symbol not in self.symbols:
|
|
509
|
-
self.symbols.append(symbol)
|
|
510
|
-
|
|
511
|
-
def calculate_metrics(self):
|
|
512
|
-
"""
|
|
513
|
-
Parent method to calculate all metrics.
|
|
514
|
-
|
|
515
|
-
returns:
|
|
516
|
-
None
|
|
517
|
-
"""
|
|
518
|
-
if self.traces is not None:
|
|
519
|
-
self.metrics['efficiency_ratio'] = {}
|
|
520
|
-
|
|
521
|
-
for strategy_id in self.traces:
|
|
522
|
-
entries = self.traces[strategy_id]
|
|
523
|
-
|
|
524
|
-
if entries is None:
|
|
525
|
-
continue
|
|
526
|
-
|
|
527
|
-
for symbol in entries:
|
|
528
|
-
|
|
529
|
-
self.metrics['efficiency_ratio'][symbol] = \
|
|
530
|
-
get_price_efficiency_ratio(
|
|
531
|
-
self.traces[strategy_id][symbol]
|
|
532
|
-
)
|
|
533
|
-
|
|
534
|
-
@property
|
|
535
|
-
def traces(self):
|
|
536
|
-
"""
|
|
537
|
-
Get the traces of the backtest report.
|
|
538
|
-
"""
|
|
539
|
-
return self._traces
|
|
540
|
-
|
|
541
|
-
@traces.setter
|
|
542
|
-
def traces(self, value):
|
|
543
|
-
"""
|
|
544
|
-
Set the traces of the backtest report.
|
|
545
|
-
|
|
546
|
-
Args:
|
|
547
|
-
value (dict): The traces of the backtest report.
|
|
548
|
-
|
|
549
|
-
returns:
|
|
550
|
-
None
|
|
551
|
-
"""
|
|
552
|
-
self._traces = value
|
|
553
|
-
|
|
554
|
-
def get_trace(self, symbol, strategy_id=None):
|
|
555
|
-
"""
|
|
556
|
-
Get the trace for a given symbol. If a strategy_id is provided,
|
|
557
|
-
it will return the trace for that strategy.
|
|
558
|
-
|
|
559
|
-
Args:
|
|
560
|
-
symbol (str): The symbol
|
|
561
|
-
strategy_id (str): The
|
|
562
|
-
"""
|
|
563
|
-
|
|
564
|
-
if strategy_id is None:
|
|
565
|
-
|
|
566
|
-
for strategy_id, trace in self.traces.items():
|
|
567
|
-
|
|
568
|
-
if symbol in trace:
|
|
569
|
-
return trace[symbol]
|
|
570
|
-
|
|
571
|
-
else:
|
|
572
|
-
if strategy_id in self.traces:
|
|
573
|
-
return self.traces[strategy_id][symbol]
|
|
574
|
-
|
|
575
|
-
else:
|
|
576
|
-
raise ValueError(
|
|
577
|
-
f"Trace {symbol} for strategy {strategy_id} not found"
|
|
578
|
-
)
|
|
579
|
-
|
|
580
|
-
return None
|