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
investing_algorithm_framework/infrastructure/services/performance_service/performance_service.py
DELETED
|
@@ -1,350 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
|
|
3
|
-
from investing_algorithm_framework.domain import OrderStatus, OrderSide
|
|
4
|
-
|
|
5
|
-
logger = logging.getLogger(__name__)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class PerformanceService:
|
|
9
|
-
"""
|
|
10
|
-
Service to calculate the performance of a portfolio.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
def __init__(
|
|
14
|
-
self,
|
|
15
|
-
order_repository,
|
|
16
|
-
position_repository,
|
|
17
|
-
portfolio_repository,
|
|
18
|
-
):
|
|
19
|
-
self.order_repository = order_repository
|
|
20
|
-
self.position_repository = position_repository
|
|
21
|
-
self.portfolio_repository = portfolio_repository
|
|
22
|
-
|
|
23
|
-
def get_total_net_gain(self, portfolio_id):
|
|
24
|
-
pass
|
|
25
|
-
|
|
26
|
-
def get_total_size(self, portfolio_id):
|
|
27
|
-
pass
|
|
28
|
-
|
|
29
|
-
def get_percentage_change(self, portfolio_id, time_frame):
|
|
30
|
-
pass
|
|
31
|
-
|
|
32
|
-
def get_total_cost(self, portfolio_id):
|
|
33
|
-
pass
|
|
34
|
-
|
|
35
|
-
def get_number_of_trades_closed(self, portfolio_id):
|
|
36
|
-
""""
|
|
37
|
-
Get the number of trades closed. This function will
|
|
38
|
-
return the number of trades that are already closed.
|
|
39
|
-
|
|
40
|
-
param portfolio_id: The id of the portfolio
|
|
41
|
-
type portfolio_id: str
|
|
42
|
-
|
|
43
|
-
return: The number of trades closed
|
|
44
|
-
"""
|
|
45
|
-
portfolio = self.portfolio_repository.find({"id": portfolio_id})
|
|
46
|
-
number_of_trades_closed = 0
|
|
47
|
-
orders = self.order_repository.get_all(
|
|
48
|
-
{
|
|
49
|
-
"portfolio_id": portfolio.id,
|
|
50
|
-
"order_side": OrderSide.BUY.value,
|
|
51
|
-
}
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
for order in orders:
|
|
55
|
-
if order.get_trade_closed_at() is not None:
|
|
56
|
-
number_of_trades_closed += 1
|
|
57
|
-
|
|
58
|
-
return number_of_trades_closed
|
|
59
|
-
|
|
60
|
-
def get_number_of_trades_open(self, portfolio_id):
|
|
61
|
-
"""
|
|
62
|
-
Get the number of trades open. This function will
|
|
63
|
-
return the number of trades that are still open.
|
|
64
|
-
|
|
65
|
-
param portfolio_id: The id of the portfolio
|
|
66
|
-
type portfolio_id: str
|
|
67
|
-
|
|
68
|
-
return: The number of trades open
|
|
69
|
-
"""
|
|
70
|
-
portfolio = self.portfolio_repository.find({"id": portfolio_id})
|
|
71
|
-
number_of_trades_open = 0
|
|
72
|
-
orders = self.order_repository.get_all(
|
|
73
|
-
{
|
|
74
|
-
"portfolio_id": portfolio.id,
|
|
75
|
-
"order_side": OrderSide.BUY.value,
|
|
76
|
-
}
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
for order in orders:
|
|
80
|
-
if order.get_trade_closed_at() is None:
|
|
81
|
-
number_of_trades_open += 1
|
|
82
|
-
|
|
83
|
-
return number_of_trades_open
|
|
84
|
-
|
|
85
|
-
def get_percentage_positive_trades(self, portfolio_id):
|
|
86
|
-
"""
|
|
87
|
-
Get the percentage of positive trades. This function will
|
|
88
|
-
calculate the percentage of positive trades by dividing the
|
|
89
|
-
total number of positive trades by the total number of trades
|
|
90
|
-
and then multiplying it by 100.
|
|
91
|
-
|
|
92
|
-
param portfolio_id: The id of the portfolio
|
|
93
|
-
type portfolio_id: str
|
|
94
|
-
|
|
95
|
-
return: The percentage of positive trades
|
|
96
|
-
"""
|
|
97
|
-
portfolio = self.portfolio_repository.find({"id": portfolio_id})
|
|
98
|
-
orders = self.order_repository.get_all(
|
|
99
|
-
{"portfolio_id": portfolio.id, "status": OrderStatus.CLOSED.value}
|
|
100
|
-
)
|
|
101
|
-
total_number_of_orders = len(orders)
|
|
102
|
-
|
|
103
|
-
if total_number_of_orders == 0:
|
|
104
|
-
return 0.0
|
|
105
|
-
|
|
106
|
-
positive_orders = [
|
|
107
|
-
order for order in orders if order.get_net_gain() > 0
|
|
108
|
-
]
|
|
109
|
-
total_number_of_positive_orders = len(positive_orders)
|
|
110
|
-
return total_number_of_positive_orders / total_number_of_orders * 100
|
|
111
|
-
|
|
112
|
-
def get_percentage_negative_trades(self, portfolio_id):
|
|
113
|
-
"""
|
|
114
|
-
Get the percentage of negative trades. This function will
|
|
115
|
-
calculate the percentage of negative trades by dividing the
|
|
116
|
-
total number of negative trades by the total number of trades
|
|
117
|
-
and then multiplying it by 100.
|
|
118
|
-
|
|
119
|
-
param portfolio_id: The id of the portfolio
|
|
120
|
-
type portfolio_id: str
|
|
121
|
-
|
|
122
|
-
return: The percentage of negative trades
|
|
123
|
-
"""
|
|
124
|
-
|
|
125
|
-
portfolio = self.portfolio_repository.find({"id": portfolio_id})
|
|
126
|
-
orders = self.order_repository.get_all(
|
|
127
|
-
{"portfolio_id": portfolio.id, "status": OrderStatus.CLOSED.value}
|
|
128
|
-
)
|
|
129
|
-
total_number_of_orders = len(orders)
|
|
130
|
-
|
|
131
|
-
if total_number_of_orders == 0:
|
|
132
|
-
return 0.0
|
|
133
|
-
|
|
134
|
-
negative_orders = [
|
|
135
|
-
order for order in orders if order.get_net_gain() < 0
|
|
136
|
-
]
|
|
137
|
-
total_number_of_negative_orders = len(negative_orders)
|
|
138
|
-
return total_number_of_negative_orders / total_number_of_orders * 100
|
|
139
|
-
|
|
140
|
-
def get_growth_rate_of_backtest(
|
|
141
|
-
self, portfolio_id, tickers, backtest_profile
|
|
142
|
-
):
|
|
143
|
-
"""
|
|
144
|
-
Get the growth rate of the backtest. This function will
|
|
145
|
-
calculate the total value of the portfolio and then
|
|
146
|
-
calculate the growth rate of the portfolio.
|
|
147
|
-
|
|
148
|
-
param portfolio_id: The id of the portfolio
|
|
149
|
-
type portfolio_id: str
|
|
150
|
-
param tickers: list of tickers of all the used symbols
|
|
151
|
-
type tickers: dict
|
|
152
|
-
|
|
153
|
-
return: The growth rate of the backtest
|
|
154
|
-
"""
|
|
155
|
-
total_value = self.get_total_value(
|
|
156
|
-
portfolio_id, tickers, backtest_profile
|
|
157
|
-
)
|
|
158
|
-
gain = total_value - backtest_profile.initial_unallocated
|
|
159
|
-
return gain / backtest_profile.initial_unallocated * 100
|
|
160
|
-
|
|
161
|
-
def get_growth_of_backtest(self, portfolio_id, tickers, backtest_profile):
|
|
162
|
-
"""
|
|
163
|
-
Get the growth of the backtest. This function will
|
|
164
|
-
calculate the total value of the portfolio and then
|
|
165
|
-
calculate the growth of the portfolio.
|
|
166
|
-
|
|
167
|
-
param portfolio_id: The id of the portfolio
|
|
168
|
-
type portfolio_id: str
|
|
169
|
-
param tickers: The tickers of the market
|
|
170
|
-
type tickers: dict
|
|
171
|
-
|
|
172
|
-
return: The growth of the backtest
|
|
173
|
-
"""
|
|
174
|
-
total_value = self.get_total_value(
|
|
175
|
-
portfolio_id, tickers, backtest_profile
|
|
176
|
-
)
|
|
177
|
-
return total_value - backtest_profile.initial_unallocated
|
|
178
|
-
|
|
179
|
-
def get_total_net_gain_percentage_of_backtest(
|
|
180
|
-
self, portfolio_id, backtest_profile
|
|
181
|
-
):
|
|
182
|
-
"""
|
|
183
|
-
Get the total net gain percentage of the backtest. This function
|
|
184
|
-
will calculate the total net gain percentage of the portfolio
|
|
185
|
-
by dividing the total net gain by the initial unallocated value
|
|
186
|
-
of the portfolio and then multiplying it by 100.
|
|
187
|
-
|
|
188
|
-
param portfolio_id: The id of the portfolio
|
|
189
|
-
type portfolio_id: str
|
|
190
|
-
param backtest_profile: The backtest profile
|
|
191
|
-
type backtest_profile: BacktestProfile
|
|
192
|
-
|
|
193
|
-
return: The total net gain percentage of the backtest
|
|
194
|
-
"""
|
|
195
|
-
portfolio = self.portfolio_repository.find({"id": portfolio_id})
|
|
196
|
-
return portfolio.total_net_gain \
|
|
197
|
-
/ backtest_profile.initial_unallocated * 100
|
|
198
|
-
|
|
199
|
-
def get_total_value(self, portfolio_id, tickers, backtest_profile):
|
|
200
|
-
"""
|
|
201
|
-
Get the total value of the portfolio. This functions
|
|
202
|
-
will calculate the allocated value, pending buy value,
|
|
203
|
-
pending sell value and unallocated value.
|
|
204
|
-
|
|
205
|
-
At the end, it will sum all these values and return the
|
|
206
|
-
total value of the portfolio.
|
|
207
|
-
|
|
208
|
-
param portfolio_id: The id of the portfolio
|
|
209
|
-
type portfolio_id: str
|
|
210
|
-
param tickers: The tickers of the market
|
|
211
|
-
type tickers: dict
|
|
212
|
-
param backtest_profile: The backtest profile
|
|
213
|
-
type backtest_profile: BacktestProfile
|
|
214
|
-
|
|
215
|
-
return: The total value of the portfolio
|
|
216
|
-
rtype: float
|
|
217
|
-
"""
|
|
218
|
-
portfolio = self.portfolio_repository.find({"id": portfolio_id})
|
|
219
|
-
positions = self.position_repository.get_all(
|
|
220
|
-
{"portfolio_id": portfolio.id}
|
|
221
|
-
)
|
|
222
|
-
allocated = 0
|
|
223
|
-
|
|
224
|
-
for position in positions:
|
|
225
|
-
|
|
226
|
-
if position.symbol == portfolio.trading_symbol:
|
|
227
|
-
continue
|
|
228
|
-
|
|
229
|
-
ticker_symbol = f"{position.symbol.upper()}" \
|
|
230
|
-
f"/{portfolio.trading_symbol.upper()}"
|
|
231
|
-
if ticker_symbol not in tickers:
|
|
232
|
-
logger.warning(
|
|
233
|
-
f"Symbol {position.symbol} not found in tickers, "
|
|
234
|
-
f"cannot calculate the total value of the position"
|
|
235
|
-
)
|
|
236
|
-
continue
|
|
237
|
-
|
|
238
|
-
allocated += position.amount * tickers[ticker_symbol]["bid"]
|
|
239
|
-
|
|
240
|
-
# Calculate the pending sell value
|
|
241
|
-
pending_sell_orders = self.order_repository.get_all(
|
|
242
|
-
{
|
|
243
|
-
"portfolio_id": portfolio.id,
|
|
244
|
-
"status": OrderStatus.OPEN.value,
|
|
245
|
-
"order_side": OrderSide.SELL.value,
|
|
246
|
-
}
|
|
247
|
-
)
|
|
248
|
-
|
|
249
|
-
for order in pending_sell_orders:
|
|
250
|
-
|
|
251
|
-
if order.get_symbol() in tickers:
|
|
252
|
-
allocated += order.get_amount() \
|
|
253
|
-
* tickers[order.get_symbol()]["bid"]
|
|
254
|
-
else:
|
|
255
|
-
logger.warning(
|
|
256
|
-
f"Symbol {order.get_symbol()} not found in tickers, "
|
|
257
|
-
f"cannot calculate the total value of sell orders"
|
|
258
|
-
)
|
|
259
|
-
|
|
260
|
-
# Calculate the unallocated value by summing the unallocated and
|
|
261
|
-
# pending buy value
|
|
262
|
-
unallocated = portfolio.unallocated
|
|
263
|
-
pending_buy_orders = self.order_repository.get_all(
|
|
264
|
-
{
|
|
265
|
-
"portfolio_id": portfolio.id,
|
|
266
|
-
"status": OrderStatus.OPEN.value,
|
|
267
|
-
"order_side": OrderSide.BUY.value,
|
|
268
|
-
}
|
|
269
|
-
)
|
|
270
|
-
|
|
271
|
-
for order in pending_buy_orders:
|
|
272
|
-
if order.get_symbol() in tickers:
|
|
273
|
-
unallocated += order.get_amount() \
|
|
274
|
-
* tickers[order.get_symbol()]["ask"]
|
|
275
|
-
else:
|
|
276
|
-
logger.warning(
|
|
277
|
-
f"Symbol {order.get_symbol()} not found in tickers, "
|
|
278
|
-
f"cannot calculate the total value of buy orders"
|
|
279
|
-
)
|
|
280
|
-
|
|
281
|
-
# Add everything together
|
|
282
|
-
return allocated + unallocated
|
|
283
|
-
|
|
284
|
-
def get_average_trade_duration(self, portfolio_id):
|
|
285
|
-
"""
|
|
286
|
-
Get the average trade duration. This function will
|
|
287
|
-
calculate the average trade duration by summing the
|
|
288
|
-
duration of all the trades and then dividing it by the
|
|
289
|
-
total number of trades.
|
|
290
|
-
|
|
291
|
-
param portfolio_id: The id of the portfolio
|
|
292
|
-
type portfolio_id: str
|
|
293
|
-
|
|
294
|
-
return: The average trade duration
|
|
295
|
-
"""
|
|
296
|
-
portfolio = self.portfolio_repository.find({"id": portfolio_id})
|
|
297
|
-
buy_orders = self.order_repository.get_all(
|
|
298
|
-
{
|
|
299
|
-
"portfolio_id": portfolio.id,
|
|
300
|
-
"order_side": OrderSide.BUY.value,
|
|
301
|
-
}
|
|
302
|
-
)
|
|
303
|
-
buy_orders_with_trade_closed = [
|
|
304
|
-
order for order in buy_orders
|
|
305
|
-
if order.get_trade_closed_at() is not None
|
|
306
|
-
]
|
|
307
|
-
|
|
308
|
-
if len(buy_orders_with_trade_closed) == 0:
|
|
309
|
-
return 0
|
|
310
|
-
|
|
311
|
-
total_duration = 0
|
|
312
|
-
|
|
313
|
-
for order in buy_orders_with_trade_closed:
|
|
314
|
-
duration = order.get_trade_closed_at() - order.get_created_at()
|
|
315
|
-
total_duration += duration.total_seconds() / 3600
|
|
316
|
-
|
|
317
|
-
return total_duration / len(buy_orders_with_trade_closed)
|
|
318
|
-
|
|
319
|
-
def get_average_trade_size(self, portfolio_id):
|
|
320
|
-
"""
|
|
321
|
-
Get the average trade size. This function will calculate
|
|
322
|
-
the average trade size by summing the size of all the trades
|
|
323
|
-
and then dividing it by the total number of trades.
|
|
324
|
-
|
|
325
|
-
param portfolio_id: The id of the portfolio
|
|
326
|
-
type portfolio_id: str
|
|
327
|
-
|
|
328
|
-
return: The average trade size
|
|
329
|
-
"""
|
|
330
|
-
portfolio = self.portfolio_repository.find({"id": portfolio_id})
|
|
331
|
-
buy_orders = self.order_repository.get_all(
|
|
332
|
-
{
|
|
333
|
-
"portfolio_id": portfolio.id,
|
|
334
|
-
"order_side": OrderSide.BUY.value,
|
|
335
|
-
}
|
|
336
|
-
)
|
|
337
|
-
closed_buy_orders = [
|
|
338
|
-
order for order in buy_orders
|
|
339
|
-
if order.get_trade_closed_at() is not None
|
|
340
|
-
]
|
|
341
|
-
|
|
342
|
-
if len(closed_buy_orders) == 0:
|
|
343
|
-
return 0
|
|
344
|
-
|
|
345
|
-
total_size = 0
|
|
346
|
-
|
|
347
|
-
for order in closed_buy_orders:
|
|
348
|
-
total_size += order.get_amount() * order.get_price()
|
|
349
|
-
|
|
350
|
-
return total_size / len(closed_buy_orders)
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import os
|
|
3
|
-
|
|
4
|
-
from investing_algorithm_framework.domain import BacktestReport, \
|
|
5
|
-
DATETIME_FORMAT_BACKTESTING
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class BacktestReportWriterService:
|
|
9
|
-
"""
|
|
10
|
-
Service to write backtest reports to a file.
|
|
11
|
-
|
|
12
|
-
Service supports writing backtest reports to the following formats:
|
|
13
|
-
- JSON
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
def write_report_to_json(
|
|
17
|
-
self, report: BacktestReport, output_directory: str
|
|
18
|
-
):
|
|
19
|
-
if not os.path.exists(output_directory):
|
|
20
|
-
os.makedirs(output_directory)
|
|
21
|
-
backtest_start_date = report.backtest_date_range.start_date\
|
|
22
|
-
.strftime(DATETIME_FORMAT_BACKTESTING)
|
|
23
|
-
backtest_end_date = report.backtest_date_range.end_date\
|
|
24
|
-
.strftime(DATETIME_FORMAT_BACKTESTING)
|
|
25
|
-
created_at = report.created_at.strftime(DATETIME_FORMAT_BACKTESTING)
|
|
26
|
-
json_file_path = os.path.join(
|
|
27
|
-
output_directory,
|
|
28
|
-
f"report_{report.name}_backtest_start_date_"
|
|
29
|
-
f"{backtest_start_date}_backtest_end_date_"
|
|
30
|
-
f"{backtest_end_date}_created_at_{created_at}.json"
|
|
31
|
-
)
|
|
32
|
-
report_dict = report.to_dict()
|
|
33
|
-
# Convert dictionary to JSON
|
|
34
|
-
json_data = json.dumps(report_dict, indent=4)
|
|
35
|
-
|
|
36
|
-
# Write JSON data to a .json file
|
|
37
|
-
with open(json_file_path, "w") as json_file:
|
|
38
|
-
json_file.write(json_data)
|
|
39
|
-
|
|
40
|
-
@staticmethod
|
|
41
|
-
def create_report_name(report, output_directory, extension=".json"):
|
|
42
|
-
backtest_start_date = report.backtest_start_date \
|
|
43
|
-
.strftime(DATETIME_FORMAT_BACKTESTING)
|
|
44
|
-
backtest_end_date = report.backtest_end_date \
|
|
45
|
-
.strftime(DATETIME_FORMAT_BACKTESTING)
|
|
46
|
-
created_at = report.created_at.strftime(DATETIME_FORMAT_BACKTESTING)
|
|
47
|
-
file_path = os.path.join(
|
|
48
|
-
output_directory,
|
|
49
|
-
f"report_{report.name}_backtest_start_date_"
|
|
50
|
-
f"{backtest_start_date}_backtest_end_date_"
|
|
51
|
-
f"{backtest_end_date}_created_at_{created_at}{extension}"
|
|
52
|
-
)
|
|
53
|
-
return file_path
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
from typing import List
|
|
2
|
-
|
|
3
|
-
import pandas as pd
|
|
4
|
-
from plotly import graph_objects as go
|
|
5
|
-
|
|
6
|
-
from investing_algorithm_framework.domain import Trade
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def create_prices_chart(df, column="Close"):
|
|
10
|
-
"""
|
|
11
|
-
Function to create a prices chart.
|
|
12
|
-
"""
|
|
13
|
-
return go.Scatter(
|
|
14
|
-
x=df.index,
|
|
15
|
-
y=df[column],
|
|
16
|
-
mode='lines',
|
|
17
|
-
line=dict(color="blue", width=1),
|
|
18
|
-
name="Close"
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def create_trade_entry_markers_chart(df, trades: List[Trade]):
|
|
23
|
-
df['entry_prices'] = None
|
|
24
|
-
|
|
25
|
-
for trade in trades:
|
|
26
|
-
opened_index = df.index.get_indexer(
|
|
27
|
-
[pd.to_datetime(trade.opened_at)], method='nearest'
|
|
28
|
-
)
|
|
29
|
-
df.at[df.index[opened_index[0]], 'entry_prices'] = df.at[
|
|
30
|
-
df.index[opened_index[0]], 'Close']
|
|
31
|
-
|
|
32
|
-
return go.Scatter(
|
|
33
|
-
x=df.index,
|
|
34
|
-
y=df["entry_prices"],
|
|
35
|
-
marker_symbol="arrow-up",
|
|
36
|
-
marker=dict(color='green'),
|
|
37
|
-
mode='markers',
|
|
38
|
-
name='Buy'
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def create_trade_exit_markers_chart(df, trades: List[Trade]):
|
|
43
|
-
df['exit_prices'] = None
|
|
44
|
-
|
|
45
|
-
for trade in trades:
|
|
46
|
-
|
|
47
|
-
if trade.closed_at is not None:
|
|
48
|
-
closed_index = df.index.get_indexer(
|
|
49
|
-
[pd.to_datetime(trade.closed_at)], method='nearest'
|
|
50
|
-
)
|
|
51
|
-
df.at[df.index[closed_index[0]], 'exit_prices'] = df.at[
|
|
52
|
-
df.index[closed_index[0]], 'Close']
|
|
53
|
-
|
|
54
|
-
return go.Scatter(
|
|
55
|
-
x=df.index,
|
|
56
|
-
y=df["exit_prices"],
|
|
57
|
-
marker_symbol="arrow-down",
|
|
58
|
-
marker=dict(color='red'),
|
|
59
|
-
mode='markers',
|
|
60
|
-
name='Sell'
|
|
61
|
-
)
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
from typing import List
|
|
2
|
-
|
|
3
|
-
from tqdm import tqdm
|
|
4
|
-
|
|
5
|
-
from investing_algorithm_framework.domain import MarketService, \
|
|
6
|
-
BacktestMarketDataSource, BACKTESTING_END_DATE, BACKTESTING_START_DATE, \
|
|
7
|
-
BACKTESTING_INDEX_DATETIME, OperationalException
|
|
8
|
-
from investing_algorithm_framework.services.configuration_service import \
|
|
9
|
-
ConfigurationService
|
|
10
|
-
from investing_algorithm_framework.services.market_credential_service \
|
|
11
|
-
import MarketCredentialService
|
|
12
|
-
from .market_data_source_service import MarketDataSourceService
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class BacktestMarketDataSourceService(MarketDataSourceService):
|
|
16
|
-
"""
|
|
17
|
-
BacktestMarketDataSourceService is a subclass of MarketDataSourceService.
|
|
18
|
-
It is used to create market data sources for backtesting.
|
|
19
|
-
|
|
20
|
-
In the constructor, it takes a list of BacktestMarketDataSource objects.
|
|
21
|
-
These objects are used to prepare the data for backtesting.
|
|
22
|
-
|
|
23
|
-
The prepare_data method of BacktestMarketDataSource is called in the
|
|
24
|
-
constructor.
|
|
25
|
-
"""
|
|
26
|
-
def __init__(
|
|
27
|
-
self,
|
|
28
|
-
market_data_sources: List[BacktestMarketDataSource],
|
|
29
|
-
market_service: MarketService,
|
|
30
|
-
market_credential_service: MarketCredentialService,
|
|
31
|
-
configuration_service: ConfigurationService,
|
|
32
|
-
):
|
|
33
|
-
super().__init__(
|
|
34
|
-
market_service=market_service,
|
|
35
|
-
market_data_sources=None,
|
|
36
|
-
market_credential_service=market_credential_service,
|
|
37
|
-
)
|
|
38
|
-
self.market_data_sources = []
|
|
39
|
-
|
|
40
|
-
# Add all market data sources to the list
|
|
41
|
-
if market_data_sources is not None:
|
|
42
|
-
for market_data_source in market_data_sources:
|
|
43
|
-
self.add(market_data_source)
|
|
44
|
-
|
|
45
|
-
self._configuration_service: ConfigurationService = \
|
|
46
|
-
configuration_service
|
|
47
|
-
|
|
48
|
-
for backtest_market_data_source in tqdm(
|
|
49
|
-
market_data_sources,
|
|
50
|
-
total=len(self._market_data_sources),
|
|
51
|
-
desc="Preparing backtest market data",
|
|
52
|
-
colour="GREEN"
|
|
53
|
-
):
|
|
54
|
-
|
|
55
|
-
if backtest_market_data_source is not None:
|
|
56
|
-
backtest_market_data_source.market_credentials_service = \
|
|
57
|
-
self._market_credential_service
|
|
58
|
-
backtest_market_data_source.prepare_data(
|
|
59
|
-
config=configuration_service.get_config(),
|
|
60
|
-
backtest_start_date=configuration_service
|
|
61
|
-
.get_config()[BACKTESTING_START_DATE],
|
|
62
|
-
backtest_end_date=configuration_service
|
|
63
|
-
.get_config()[BACKTESTING_END_DATE],
|
|
64
|
-
market_credential_service=self._market_credential_service
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
def get_data(self, identifier):
|
|
68
|
-
"""
|
|
69
|
-
This method is used to get the data for backtesting. It loops
|
|
70
|
-
over all the backtest market data sources and returns the data
|
|
71
|
-
for the given identifier (If there is a match).
|
|
72
|
-
"""
|
|
73
|
-
for backtest_market_data_source in self._market_data_sources:
|
|
74
|
-
if backtest_market_data_source.identifier == identifier:
|
|
75
|
-
backtest_market_data_source.market_credentials_service = \
|
|
76
|
-
self._market_credential_service
|
|
77
|
-
return backtest_market_data_source.get_data(
|
|
78
|
-
backtest_index_date=self._configuration_service
|
|
79
|
-
.config[BACKTESTING_INDEX_DATETIME],
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
raise OperationalException(
|
|
83
|
-
f"Backtest market data source not found for {identifier}"
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
def get_ticker(self, symbol, market):
|
|
87
|
-
market_data_source = self.get_ticker_market_data_source(
|
|
88
|
-
symbol=symbol, market=market
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
if market_data_source is None:
|
|
92
|
-
raise OperationalException(
|
|
93
|
-
f"Backtest ticker data source "
|
|
94
|
-
f"not found for {symbol} and market {market}"
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
market_data_source.market_credentials_service = \
|
|
98
|
-
self._market_credential_service
|
|
99
|
-
return market_data_source.get_data(
|
|
100
|
-
backtest_index_date=self._configuration_service
|
|
101
|
-
.config[BACKTESTING_INDEX_DATETIME],
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
def get_order_book(self, symbol, market):
|
|
105
|
-
market_data_source = self.get_order_book_market_data_source(
|
|
106
|
-
symbol=symbol, market=market
|
|
107
|
-
)
|
|
108
|
-
market_data_source.market_credential_service = \
|
|
109
|
-
self._market_credential_service
|
|
110
|
-
return market_data_source.get_data(
|
|
111
|
-
backtest_index_date=self._configuration_service
|
|
112
|
-
.config[BACKTESTING_INDEX_DATETIME],
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
def get_ohlcv(
|
|
116
|
-
self,
|
|
117
|
-
symbol,
|
|
118
|
-
from_timestamp,
|
|
119
|
-
time_frame=None,
|
|
120
|
-
market=None,
|
|
121
|
-
to_timestamp=None
|
|
122
|
-
):
|
|
123
|
-
market_data_source = self.get_ohlcv_market_data_source(
|
|
124
|
-
symbol=symbol, market=market, time_frame=time_frame
|
|
125
|
-
)
|
|
126
|
-
market_data_source.market_credential_service = \
|
|
127
|
-
self._market_credential_service
|
|
128
|
-
return market_data_source.get_data(
|
|
129
|
-
from_timestamp=from_timestamp,
|
|
130
|
-
to_timestamp=to_timestamp,
|
|
131
|
-
backtest_index_date=self._configuration_service
|
|
132
|
-
.config[BACKTESTING_INDEX_DATETIME],
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
def is_ohlcv_data_source_present(self, symbol, time_frame, market):
|
|
136
|
-
market_data_source = self.get_ohlcv_market_data_source(
|
|
137
|
-
symbol=symbol, market=market, time_frame=time_frame
|
|
138
|
-
)
|
|
139
|
-
return market_data_source is not None
|
|
140
|
-
|
|
141
|
-
def add(self, market_data_source):
|
|
142
|
-
|
|
143
|
-
# Check if there is already a market data source with the same
|
|
144
|
-
# identifier
|
|
145
|
-
for existing_market_data_source in self._market_data_sources:
|
|
146
|
-
if existing_market_data_source.get_identifier() == \
|
|
147
|
-
market_data_source.get_identifier():
|
|
148
|
-
return
|
|
149
|
-
|
|
150
|
-
self._market_data_sources.append(market_data_source)
|