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.

Files changed (256) hide show
  1. investing_algorithm_framework/__init__.py +168 -45
  2. investing_algorithm_framework/app/__init__.py +32 -1
  3. investing_algorithm_framework/app/algorithm/__init__.py +7 -0
  4. investing_algorithm_framework/app/algorithm/algorithm.py +239 -0
  5. investing_algorithm_framework/app/algorithm/algorithm_factory.py +114 -0
  6. investing_algorithm_framework/app/analysis/__init__.py +15 -0
  7. investing_algorithm_framework/app/analysis/backtest_data_ranges.py +121 -0
  8. investing_algorithm_framework/app/analysis/backtest_utils.py +107 -0
  9. investing_algorithm_framework/app/analysis/permutation.py +116 -0
  10. investing_algorithm_framework/app/analysis/ranking.py +297 -0
  11. investing_algorithm_framework/app/app.py +1933 -589
  12. investing_algorithm_framework/app/app_hook.py +28 -0
  13. investing_algorithm_framework/app/context.py +1725 -0
  14. investing_algorithm_framework/app/eventloop.py +590 -0
  15. investing_algorithm_framework/app/reporting/__init__.py +27 -0
  16. investing_algorithm_framework/app/reporting/ascii.py +921 -0
  17. investing_algorithm_framework/app/reporting/backtest_report.py +349 -0
  18. investing_algorithm_framework/app/reporting/charts/__init__.py +19 -0
  19. investing_algorithm_framework/app/reporting/charts/entry_exist_signals.py +66 -0
  20. investing_algorithm_framework/app/reporting/charts/equity_curve.py +37 -0
  21. investing_algorithm_framework/app/reporting/charts/equity_curve_drawdown.py +74 -0
  22. investing_algorithm_framework/app/reporting/charts/line_chart.py +11 -0
  23. investing_algorithm_framework/app/reporting/charts/monthly_returns_heatmap.py +70 -0
  24. investing_algorithm_framework/app/reporting/charts/ohlcv_data_completeness.py +51 -0
  25. investing_algorithm_framework/app/reporting/charts/rolling_sharp_ratio.py +79 -0
  26. investing_algorithm_framework/app/reporting/charts/yearly_returns_barchart.py +55 -0
  27. investing_algorithm_framework/app/reporting/generate.py +185 -0
  28. investing_algorithm_framework/app/reporting/tables/__init__.py +11 -0
  29. investing_algorithm_framework/app/reporting/tables/key_metrics_table.py +217 -0
  30. investing_algorithm_framework/app/reporting/tables/stop_loss_table.py +0 -0
  31. investing_algorithm_framework/app/reporting/tables/time_metrics_table.py +80 -0
  32. investing_algorithm_framework/app/reporting/tables/trade_metrics_table.py +147 -0
  33. investing_algorithm_framework/app/reporting/tables/trades_table.py +75 -0
  34. investing_algorithm_framework/app/reporting/tables/utils.py +29 -0
  35. investing_algorithm_framework/app/reporting/templates/report_template.html.j2 +154 -0
  36. investing_algorithm_framework/app/stateless/action_handlers/__init__.py +4 -2
  37. investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +1 -1
  38. investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +1 -1
  39. investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +14 -7
  40. investing_algorithm_framework/app/strategy.py +664 -84
  41. investing_algorithm_framework/app/task.py +5 -3
  42. investing_algorithm_framework/app/web/__init__.py +2 -1
  43. investing_algorithm_framework/app/web/create_app.py +4 -2
  44. investing_algorithm_framework/cli/__init__.py +0 -0
  45. investing_algorithm_framework/cli/cli.py +226 -0
  46. investing_algorithm_framework/cli/deploy_to_aws_lambda.py +501 -0
  47. investing_algorithm_framework/cli/deploy_to_azure_function.py +718 -0
  48. investing_algorithm_framework/cli/initialize_app.py +603 -0
  49. investing_algorithm_framework/cli/templates/.gitignore.template +178 -0
  50. investing_algorithm_framework/cli/templates/app.py.template +18 -0
  51. investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +48 -0
  52. investing_algorithm_framework/cli/templates/app_azure_function.py.template +14 -0
  53. investing_algorithm_framework/cli/templates/app_web.py.template +18 -0
  54. investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +22 -0
  55. investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +92 -0
  56. investing_algorithm_framework/cli/templates/aws_lambda_readme.md.template +110 -0
  57. investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +2 -0
  58. investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +65 -0
  59. investing_algorithm_framework/cli/templates/azure_function_host.json.template +15 -0
  60. investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +8 -0
  61. investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +3 -0
  62. investing_algorithm_framework/cli/templates/data_providers.py.template +17 -0
  63. investing_algorithm_framework/cli/templates/env.example.template +2 -0
  64. investing_algorithm_framework/cli/templates/env_azure_function.example.template +4 -0
  65. investing_algorithm_framework/cli/templates/market_data_providers.py.template +9 -0
  66. investing_algorithm_framework/cli/templates/readme.md.template +135 -0
  67. investing_algorithm_framework/cli/templates/requirements.txt.template +2 -0
  68. investing_algorithm_framework/cli/templates/run_backtest.py.template +20 -0
  69. investing_algorithm_framework/cli/templates/strategy.py.template +124 -0
  70. investing_algorithm_framework/create_app.py +40 -6
  71. investing_algorithm_framework/dependency_container.py +72 -56
  72. investing_algorithm_framework/domain/__init__.py +71 -47
  73. investing_algorithm_framework/domain/backtesting/__init__.py +21 -0
  74. investing_algorithm_framework/domain/backtesting/backtest.py +503 -0
  75. investing_algorithm_framework/domain/backtesting/backtest_date_range.py +96 -0
  76. investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +242 -0
  77. investing_algorithm_framework/domain/backtesting/backtest_metrics.py +459 -0
  78. investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +275 -0
  79. investing_algorithm_framework/domain/backtesting/backtest_run.py +605 -0
  80. investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +162 -0
  81. investing_algorithm_framework/domain/backtesting/combine_backtests.py +280 -0
  82. investing_algorithm_framework/domain/config.py +59 -91
  83. investing_algorithm_framework/domain/constants.py +13 -38
  84. investing_algorithm_framework/domain/data_provider.py +334 -0
  85. investing_algorithm_framework/domain/data_structures.py +3 -2
  86. investing_algorithm_framework/domain/exceptions.py +51 -1
  87. investing_algorithm_framework/domain/models/__init__.py +17 -12
  88. investing_algorithm_framework/domain/models/data/__init__.py +7 -0
  89. investing_algorithm_framework/domain/models/data/data_source.py +214 -0
  90. investing_algorithm_framework/domain/models/data/data_type.py +46 -0
  91. investing_algorithm_framework/domain/models/event.py +35 -0
  92. investing_algorithm_framework/domain/models/market/market_credential.py +55 -1
  93. investing_algorithm_framework/domain/models/order/order.py +77 -83
  94. investing_algorithm_framework/domain/models/order/order_status.py +2 -2
  95. investing_algorithm_framework/domain/models/order/order_type.py +1 -3
  96. investing_algorithm_framework/domain/models/portfolio/portfolio.py +81 -3
  97. investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +26 -3
  98. investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +108 -11
  99. investing_algorithm_framework/domain/models/position/__init__.py +2 -1
  100. investing_algorithm_framework/domain/models/position/position.py +12 -0
  101. investing_algorithm_framework/domain/models/position/position_size.py +41 -0
  102. investing_algorithm_framework/domain/models/risk_rules/__init__.py +7 -0
  103. investing_algorithm_framework/domain/models/risk_rules/stop_loss_rule.py +51 -0
  104. investing_algorithm_framework/domain/models/risk_rules/take_profit_rule.py +55 -0
  105. investing_algorithm_framework/domain/models/snapshot_interval.py +45 -0
  106. investing_algorithm_framework/domain/models/strategy_profile.py +19 -151
  107. investing_algorithm_framework/domain/models/time_frame.py +37 -0
  108. investing_algorithm_framework/domain/models/time_interval.py +33 -0
  109. investing_algorithm_framework/domain/models/time_unit.py +66 -2
  110. investing_algorithm_framework/domain/models/trade/__init__.py +8 -1
  111. investing_algorithm_framework/domain/models/trade/trade.py +295 -171
  112. investing_algorithm_framework/domain/models/trade/trade_status.py +9 -2
  113. investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +332 -0
  114. investing_algorithm_framework/domain/models/trade/trade_take_profit.py +365 -0
  115. investing_algorithm_framework/domain/order_executor.py +112 -0
  116. investing_algorithm_framework/domain/portfolio_provider.py +118 -0
  117. investing_algorithm_framework/domain/services/__init__.py +2 -9
  118. investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +0 -6
  119. investing_algorithm_framework/domain/services/state_handler.py +38 -0
  120. investing_algorithm_framework/domain/strategy.py +1 -29
  121. investing_algorithm_framework/domain/utils/__init__.py +12 -7
  122. investing_algorithm_framework/domain/utils/custom_tqdm.py +22 -0
  123. investing_algorithm_framework/domain/utils/dates.py +57 -0
  124. investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +19 -0
  125. investing_algorithm_framework/domain/utils/polars.py +53 -0
  126. investing_algorithm_framework/domain/utils/random.py +29 -0
  127. investing_algorithm_framework/download_data.py +108 -0
  128. investing_algorithm_framework/infrastructure/__init__.py +31 -18
  129. investing_algorithm_framework/infrastructure/data_providers/__init__.py +36 -0
  130. investing_algorithm_framework/infrastructure/data_providers/ccxt.py +1143 -0
  131. investing_algorithm_framework/infrastructure/data_providers/csv.py +568 -0
  132. investing_algorithm_framework/infrastructure/data_providers/pandas.py +599 -0
  133. investing_algorithm_framework/infrastructure/database/__init__.py +6 -2
  134. investing_algorithm_framework/infrastructure/database/sql_alchemy.py +86 -12
  135. investing_algorithm_framework/infrastructure/models/__init__.py +6 -11
  136. investing_algorithm_framework/infrastructure/models/order/__init__.py +2 -1
  137. investing_algorithm_framework/infrastructure/models/order/order.py +35 -49
  138. investing_algorithm_framework/infrastructure/models/order/order_metadata.py +44 -0
  139. investing_algorithm_framework/infrastructure/models/order_trade_association.py +10 -0
  140. investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +1 -1
  141. investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +8 -0
  142. investing_algorithm_framework/infrastructure/models/portfolio/{portfolio.py → sql_portfolio.py} +17 -5
  143. investing_algorithm_framework/infrastructure/models/trades/__init__.py +9 -0
  144. investing_algorithm_framework/infrastructure/models/trades/trade.py +130 -0
  145. investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +59 -0
  146. investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +55 -0
  147. investing_algorithm_framework/infrastructure/order_executors/__init__.py +21 -0
  148. investing_algorithm_framework/infrastructure/order_executors/backtest_oder_executor.py +28 -0
  149. investing_algorithm_framework/infrastructure/order_executors/ccxt_order_executor.py +200 -0
  150. investing_algorithm_framework/infrastructure/portfolio_providers/__init__.py +19 -0
  151. investing_algorithm_framework/infrastructure/portfolio_providers/ccxt_portfolio_provider.py +199 -0
  152. investing_algorithm_framework/infrastructure/repositories/__init__.py +8 -0
  153. investing_algorithm_framework/infrastructure/repositories/order_metadata_repository.py +17 -0
  154. investing_algorithm_framework/infrastructure/repositories/order_repository.py +5 -0
  155. investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +1 -1
  156. investing_algorithm_framework/infrastructure/repositories/position_repository.py +11 -0
  157. investing_algorithm_framework/infrastructure/repositories/repository.py +81 -27
  158. investing_algorithm_framework/infrastructure/repositories/trade_repository.py +71 -0
  159. investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +29 -0
  160. investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +29 -0
  161. investing_algorithm_framework/infrastructure/services/__init__.py +4 -4
  162. investing_algorithm_framework/infrastructure/services/aws/__init__.py +6 -0
  163. investing_algorithm_framework/infrastructure/services/aws/state_handler.py +113 -0
  164. investing_algorithm_framework/infrastructure/services/azure/__init__.py +5 -0
  165. investing_algorithm_framework/infrastructure/services/azure/state_handler.py +158 -0
  166. investing_algorithm_framework/services/__init__.py +113 -16
  167. investing_algorithm_framework/services/backtesting/__init__.py +0 -7
  168. investing_algorithm_framework/services/backtesting/backtest_service.py +566 -359
  169. investing_algorithm_framework/services/configuration_service.py +77 -11
  170. investing_algorithm_framework/services/data_providers/__init__.py +5 -0
  171. investing_algorithm_framework/services/data_providers/data_provider_service.py +850 -0
  172. investing_algorithm_framework/services/market_credential_service.py +16 -1
  173. investing_algorithm_framework/services/metrics/__init__.py +114 -0
  174. investing_algorithm_framework/services/metrics/alpha.py +0 -0
  175. investing_algorithm_framework/services/metrics/beta.py +0 -0
  176. investing_algorithm_framework/services/metrics/cagr.py +60 -0
  177. investing_algorithm_framework/services/metrics/calmar_ratio.py +40 -0
  178. investing_algorithm_framework/services/metrics/drawdown.py +181 -0
  179. investing_algorithm_framework/services/metrics/equity_curve.py +24 -0
  180. investing_algorithm_framework/services/metrics/exposure.py +210 -0
  181. investing_algorithm_framework/services/metrics/generate.py +358 -0
  182. investing_algorithm_framework/services/metrics/mean_daily_return.py +83 -0
  183. investing_algorithm_framework/services/metrics/profit_factor.py +165 -0
  184. investing_algorithm_framework/services/metrics/recovery.py +113 -0
  185. investing_algorithm_framework/services/metrics/returns.py +452 -0
  186. investing_algorithm_framework/services/metrics/risk_free_rate.py +28 -0
  187. investing_algorithm_framework/services/metrics/sharpe_ratio.py +137 -0
  188. investing_algorithm_framework/services/metrics/sortino_ratio.py +74 -0
  189. investing_algorithm_framework/services/metrics/standard_deviation.py +157 -0
  190. investing_algorithm_framework/services/metrics/trades.py +500 -0
  191. investing_algorithm_framework/services/metrics/treynor_ratio.py +0 -0
  192. investing_algorithm_framework/services/metrics/ulcer.py +0 -0
  193. investing_algorithm_framework/services/metrics/value_at_risk.py +0 -0
  194. investing_algorithm_framework/services/metrics/volatility.py +97 -0
  195. investing_algorithm_framework/services/metrics/win_rate.py +177 -0
  196. investing_algorithm_framework/services/order_service/__init__.py +3 -1
  197. investing_algorithm_framework/services/order_service/order_backtest_service.py +76 -89
  198. investing_algorithm_framework/services/order_service/order_executor_lookup.py +110 -0
  199. investing_algorithm_framework/services/order_service/order_service.py +407 -326
  200. investing_algorithm_framework/services/portfolios/__init__.py +3 -1
  201. investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +37 -3
  202. investing_algorithm_framework/services/portfolios/portfolio_configuration_service.py +22 -8
  203. investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +106 -0
  204. investing_algorithm_framework/services/portfolios/portfolio_service.py +96 -28
  205. investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +97 -28
  206. investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +116 -313
  207. investing_algorithm_framework/services/positions/__init__.py +7 -0
  208. investing_algorithm_framework/services/positions/position_service.py +210 -0
  209. investing_algorithm_framework/services/repository_service.py +8 -2
  210. investing_algorithm_framework/services/trade_order_evaluator/__init__.py +9 -0
  211. investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +113 -0
  212. investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +51 -0
  213. investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +80 -0
  214. investing_algorithm_framework/services/trade_service/__init__.py +7 -1
  215. investing_algorithm_framework/services/trade_service/trade_service.py +1013 -315
  216. investing_algorithm_framework/services/trade_service/trade_stop_loss_service.py +39 -0
  217. investing_algorithm_framework/services/trade_service/trade_take_profit_service.py +41 -0
  218. investing_algorithm_framework-7.19.15.dist-info/METADATA +537 -0
  219. investing_algorithm_framework-7.19.15.dist-info/RECORD +263 -0
  220. investing_algorithm_framework-7.19.15.dist-info/entry_points.txt +3 -0
  221. investing_algorithm_framework/app/algorithm.py +0 -1105
  222. investing_algorithm_framework/domain/graphs.py +0 -382
  223. investing_algorithm_framework/domain/metrics/__init__.py +0 -6
  224. investing_algorithm_framework/domain/models/backtesting/__init__.py +0 -11
  225. investing_algorithm_framework/domain/models/backtesting/backtest_date_range.py +0 -43
  226. investing_algorithm_framework/domain/models/backtesting/backtest_position.py +0 -120
  227. investing_algorithm_framework/domain/models/backtesting/backtest_report.py +0 -580
  228. investing_algorithm_framework/domain/models/backtesting/backtest_reports_evaluation.py +0 -243
  229. investing_algorithm_framework/domain/models/trading_data_types.py +0 -47
  230. investing_algorithm_framework/domain/models/trading_time_frame.py +0 -223
  231. investing_algorithm_framework/domain/services/market_data_sources.py +0 -344
  232. investing_algorithm_framework/domain/services/market_service.py +0 -153
  233. investing_algorithm_framework/domain/singleton.py +0 -9
  234. investing_algorithm_framework/domain/utils/backtesting.py +0 -472
  235. investing_algorithm_framework/infrastructure/models/market_data_sources/__init__.py +0 -12
  236. investing_algorithm_framework/infrastructure/models/market_data_sources/ccxt.py +0 -559
  237. investing_algorithm_framework/infrastructure/models/market_data_sources/csv.py +0 -254
  238. investing_algorithm_framework/infrastructure/models/market_data_sources/us_treasury_yield.py +0 -47
  239. investing_algorithm_framework/infrastructure/services/market_service/__init__.py +0 -5
  240. investing_algorithm_framework/infrastructure/services/market_service/ccxt_market_service.py +0 -455
  241. investing_algorithm_framework/infrastructure/services/performance_service/__init__.py +0 -7
  242. investing_algorithm_framework/infrastructure/services/performance_service/backtest_performance_service.py +0 -2
  243. investing_algorithm_framework/infrastructure/services/performance_service/performance_service.py +0 -350
  244. investing_algorithm_framework/services/backtesting/backtest_report_writer_service.py +0 -53
  245. investing_algorithm_framework/services/backtesting/graphs.py +0 -61
  246. investing_algorithm_framework/services/market_data_source_service/__init__.py +0 -8
  247. investing_algorithm_framework/services/market_data_source_service/backtest_market_data_source_service.py +0 -150
  248. investing_algorithm_framework/services/market_data_source_service/market_data_source_service.py +0 -189
  249. investing_algorithm_framework/services/position_service.py +0 -31
  250. investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -264
  251. investing_algorithm_framework-3.7.0.dist-info/METADATA +0 -339
  252. investing_algorithm_framework-3.7.0.dist-info/RECORD +0 -147
  253. /investing_algorithm_framework/{domain → services}/metrics/price_efficiency.py +0 -0
  254. /investing_algorithm_framework/services/{position_snapshot_service.py → positions/position_snapshot_service.py} +0 -0
  255. {investing_algorithm_framework-3.7.0.dist-info → investing_algorithm_framework-7.19.15.dist-info}/LICENSE +0 -0
  256. {investing_algorithm_framework-3.7.0.dist-info → investing_algorithm_framework-7.19.15.dist-info}/WHEEL +0 -0
@@ -1,472 +0,0 @@
1
- import os
2
- import json
3
- from datetime import datetime
4
- from typing import List, Tuple
5
-
6
- from tabulate import tabulate
7
-
8
- from investing_algorithm_framework.domain import DATETIME_FORMAT, \
9
- BacktestDateRange
10
- from investing_algorithm_framework.domain.exceptions import \
11
- OperationalException
12
- from investing_algorithm_framework.domain.models.backtesting import \
13
- BacktestReportsEvaluation, BacktestReport
14
-
15
- COLOR_RED = '\033[91m'
16
- COLOR_PURPLE = '\033[95m'
17
- COLOR_RESET = '\033[0m'
18
- COLOR_GREEN = '\033[92m'
19
- COLOR_YELLOW = '\033[93m'
20
-
21
-
22
- def is_positive(number) -> bool:
23
- """
24
- Check if a number is positive.
25
-
26
- param number: The number
27
- :return: True if the number is positive, False otherwise
28
- """
29
- number = float(number)
30
- return number > 0
31
-
32
-
33
- def pretty_print_profit_evaluation(reports, precision=4):
34
- profit_table = {}
35
- profit_table["Algorithm name"] = [
36
- report.name for report in reports
37
- ]
38
- profit_table["Profit"] = [
39
- f"{report.total_net_gain:.{precision}f} {report.trading_symbol}"
40
- for report in reports
41
- ]
42
- profit_table["Profit percentage"] = [
43
- f"{report.total_net_gain_percentage:.{precision}f}%" for report in reports
44
- ]
45
- profit_table["Date range"] = [
46
- f"{report.backtest_date_range.name} {report.backtest_date_range.start_date} - {report.backtest_date_range.end_date}"
47
- for report in reports
48
- ]
49
- profit_table["Total value"] = [
50
- f"{report.total_value:.{precision}f}" for report in reports
51
- ]
52
- print(tabulate(profit_table, headers="keys", tablefmt="rounded_grid"))
53
-
54
-
55
- def pretty_print_growth_evaluation(reports, precision=4):
56
- growth_table = {}
57
- growth_table["Algorithm name"] = [
58
- report.name for report in reports
59
- ]
60
- growth_table["Growth"] = [
61
- f"{report.growth:.{precision}f} {report.trading_symbol}" for report in reports
62
- ]
63
- growth_table["Growth percentage"] = [
64
- f"{report.growth_rate:.{precision}f}%" for report in reports
65
- ]
66
- growth_table["Date range"] = [
67
- f"{report.backtest_date_range.name} {report.backtest_date_range.start_date} - {report.backtest_date_range.end_date}"
68
- for report in reports
69
- ]
70
- growth_table["Total value"] = [
71
- f"{report.total_value:.{precision}f}" for report in reports
72
- ]
73
- print(
74
- tabulate(growth_table, headers="keys", tablefmt="rounded_grid")
75
- )
76
-
77
- def pretty_print_percentage_positive_trades_evaluation(
78
- evaluation: BacktestReportsEvaluation,
79
- backtest_date_range: BacktestDateRange,
80
- precision=0,
81
- number_of_reports=3
82
- ):
83
- order = evaluation.get_percentage_positive_trades_order(backtest_date_range=backtest_date_range)
84
- print(f"{COLOR_YELLOW}Trades:{COLOR_RESET} {COLOR_GREEN}Top {number_of_reports}{COLOR_RESET}")
85
- profit_table = {}
86
- profit_table["Algorithm name"] = [
87
- report.name for report in order[:number_of_reports]
88
- ]
89
- profit_table["Percentage positive trades"] = [
90
- f"{report.percentage_positive_trades:.{precision}f}%"
91
- for report in order[:number_of_reports]
92
- ]
93
- profit_table["Total amount of trades"] = [
94
- f"{report.number_of_trades_closed}" for report in order[:number_of_reports]
95
- ]
96
- print(
97
- tabulate(profit_table, headers="keys", tablefmt="rounded_grid")
98
- )
99
-
100
- least = order[-number_of_reports:]
101
- table = {}
102
- table["Algorithm name"] = [
103
- report.name for report in least
104
- ]
105
- table["Percentage positive trades"] = [
106
- f"{report.percentage_positive_trades:.{precision}f}%"
107
- for report in least
108
- ]
109
- table["Total amount of trades"] = [
110
- f"{report.number_of_trades_closed}" for report in
111
- least
112
- ]
113
-
114
- print(
115
- f"{COLOR_RED}Worst trades:{COLOR_RESET} {COLOR_GREEN}"
116
- f"Top {number_of_reports}{COLOR_RESET}"
117
- )
118
- print(
119
- tabulate(
120
- table, headers="keys", tablefmt="rounded_grid"
121
- )
122
- )
123
-
124
-
125
- def pretty_print_date_ranges(date_ranges: List[BacktestDateRange]) -> None:
126
- """
127
- Pretty print the date ranges to the console.
128
-
129
- param date_ranges: The date ranges
130
- """
131
- print(f"{COLOR_YELLOW}Date ranges of backtests:{COLOR_RESET}")
132
- for date_range in date_ranges:
133
- start_date = date_range.start_date
134
- end_date = date_range.end_date
135
-
136
- if isinstance(start_date, datetime):
137
- start_date = start_date.strftime(DATETIME_FORMAT)
138
-
139
- if isinstance(end_date, datetime):
140
- end_date = end_date.strftime(DATETIME_FORMAT)
141
-
142
- if date_range.name is not None:
143
- print(f"{COLOR_GREEN}{date_range.name}: {start_date} - {end_date}{COLOR_RESET}")
144
- else:
145
- print(f"{COLOR_GREEN}{start_date} - {end_date}{COLOR_RESET}")
146
-
147
-
148
- def pretty_print_price_efficiency(reports, precision=4):
149
- """
150
- Pretty print the price efficiency of the backtest reports evaluation
151
- to the console.
152
- """
153
- # Get all symbols of the reports
154
- print(f"{COLOR_YELLOW}Price noise{COLOR_RESET}")
155
- rows = []
156
-
157
- for report in reports:
158
-
159
- if report.metrics is not None and "efficiency_ratio" in report.metrics:
160
- price_efficiency = report.metrics["efficiency_ratio"]
161
-
162
- for symbol in price_efficiency:
163
- row = {}
164
- row["Symbol"] = symbol
165
- row["Efficiency ratio / Noise"] = f"{price_efficiency[symbol]:.{precision}f}"
166
- row["Date"] = f"{report.backtest_start_date} - {report.backtest_end_date}"
167
-
168
-
169
-
170
-
171
- if report.backtest_date_range.name is not None:
172
- row["Date"] = f"{report.backtest_date_range.name} " \
173
- f"{report.backtest_date_range.start_date}" \
174
- f" - {report.backtest_date_range.end_date}"
175
- else:
176
- row["Date"] = f"{report.backtest_start_date} - " \
177
- f"{report.backtest_end_date}"
178
-
179
- rows.append(row)
180
-
181
- # Remove all duplicate rows with the same symbol and date range
182
- unique_rows = []
183
-
184
- # Initialize an empty set to track unique (symbol, date) pairs
185
- seen = set()
186
- # Initialize a list to store the filtered dictionaries
187
- filtered_data = []
188
-
189
- # Iterate through each dictionary in the list
190
- for entry in rows:
191
- # Extract the (symbol, date) pair
192
- pair = (entry["Symbol"], entry["Date"])
193
- # Check if the pair is already in the set
194
- if pair not in seen:
195
- # If not, add the pair to the set and
196
- # the entry to the filtered list
197
- seen.add(pair)
198
- filtered_data.append(entry)
199
-
200
- print(
201
- tabulate(
202
- filtered_data,
203
- headers="keys",
204
- tablefmt="rounded_grid"
205
- )
206
- )
207
-
208
-
209
- def pretty_print_most_profitable(
210
- evaluation: BacktestReportsEvaluation,
211
- backtest_date_range: BacktestDateRange,
212
- precision=4,
213
- ):
214
- profits = evaluation.get_profit_order(backtest_date_range=backtest_date_range)
215
- profit = profits[0]
216
- print(f"{COLOR_YELLOW}Most profitable:{COLOR_RESET} {COLOR_GREEN}Algorithm {profit.name} {profit.total_net_gain:.{precision}f} {profit.trading_symbol} {profit.total_net_gain_percentage:.{precision}f}%{COLOR_RESET}")
217
-
218
-
219
- def pretty_print_most_growth(
220
- evaluation: BacktestReportsEvaluation,
221
- backtest_date_range: BacktestDateRange,
222
- precision=4,
223
- ):
224
- profits = evaluation.get_growth_order(backtest_date_range=backtest_date_range)
225
- profit = profits[0]
226
- print(f"{COLOR_YELLOW}Most growth:{COLOR_RESET} {COLOR_GREEN}Algorithm {profit.name} {profit.growth:.{precision}f} {profit.trading_symbol} {profit.growth_rate:.{precision}f}%{COLOR_RESET}")
227
-
228
-
229
- def pretty_print_percentage_positive_trades(
230
- evaluation: BacktestReportsEvaluation,
231
- backtest_date_range: BacktestDateRange,
232
- precision=0
233
- ):
234
- percentages = evaluation.get_percentage_positive_trades_order(backtest_date_range=backtest_date_range)
235
- percentages = percentages[0]
236
- print(f"{COLOR_YELLOW}Most positive trades:{COLOR_RESET} {COLOR_GREEN}Algorithm {percentages.name} {percentages.percentage_positive_trades:.{precision}f}%{COLOR_RESET}")
237
-
238
-
239
- def pretty_print_backtest_reports_evaluation(
240
- backtest_reports_evaluation: BacktestReportsEvaluation,
241
- precision=4,
242
- backtest_date_range: BacktestDateRange = None
243
- ) -> None:
244
- """
245
- Pretty print the backtest reports evaluation to the console.
246
- """
247
- if backtest_date_range is not None:
248
- reports = backtest_reports_evaluation.get_reports(backtest_date_range=backtest_date_range)
249
-
250
- if len(reports) == 0:
251
- print(f"No reports available for date range {backtest_date_range}")
252
- return
253
- else:
254
- reports = backtest_reports_evaluation.backtest_reports
255
-
256
- number_of_backtest_reports = len(reports)
257
- most_profitable = backtest_reports_evaluation.get_profit_order(backtest_date_range)[0]
258
- most_growth = backtest_reports_evaluation.get_growth_order(backtest_date_range)[0]
259
-
260
- ascii_art = f"""
261
- :%%%#+- .=*#%%% {COLOR_GREEN}Backtest reports evaluation{COLOR_RESET}
262
- *%%%%%%%+------=*%%%%%%%- {COLOR_GREEN}---------------------------{COLOR_RESET}
263
- *%%%%%%%%%%%%%%%%%%%%%%%- {COLOR_YELLOW}Number of reports:{COLOR_RESET} {COLOR_GREEN}{number_of_backtest_reports} backtest reports{COLOR_RESET}
264
- .%%%%%%%%%%%%%%%%%%%%%%# {COLOR_YELLOW}Largest overall profit:{COLOR_RESET}{COLOR_GREEN}{COLOR_RESET}{COLOR_GREEN} (Algorithm {most_profitable.name}) {most_profitable.total_net_gain:.{precision}f} {most_profitable.trading_symbol} {most_profitable.total_net_gain_percentage:.{precision}f}% ({most_profitable.backtest_date_range.name} {most_profitable.backtest_date_range.start_date} - {most_profitable.backtest_date_range.end_date}){COLOR_RESET}
265
- #%%%####%%%%%%%%**#%%%+ {COLOR_YELLOW}Largest overall growth:{COLOR_RESET}{COLOR_GREEN} (Algorithm {most_profitable.name}) {most_growth.growth:.{precision}f} {most_growth.trading_symbol} {most_growth.growth_rate:.{precision}f}% ({most_growth.backtest_date_range.name} {most_growth.backtest_date_range.start_date} - {most_growth.backtest_date_range.end_date}){COLOR_RESET}
266
- .:-+*%%%%- {COLOR_PURPLE}-+..#{COLOR_RESET}%%%+.{COLOR_PURPLE}+- +{COLOR_RESET}%%%#*=-:
267
- .:-=*%%%%. {COLOR_PURPLE}+={COLOR_RESET} .%%# {COLOR_PURPLE}-+.-{COLOR_RESET}%%%%=-:..
268
- .:=+#%%%%%*###%%%%#*+#%%%%%%*+-:
269
- +%%%%%%%%%%%%%%%%%%%=
270
- :++ .=#%%%%%%%%%%%%%*-
271
- :++: :+%%%%%%#-.
272
- :++: .%%%%%#=
273
- :++: .#%%%%%#*=
274
- :++- :%%%%%%%%%+=
275
- .++- -%%%%%%%%%%%+=
276
- .++- .%%%%%%%%%%%%%+=
277
- .++- *%%%%%%%%%%%%%*+:
278
- .++- %%%%%%%%%%%%%%#+=
279
- =++........:::%%%%%%%%%%%%%%*+-
280
- .=++++++++++**#%%%%%%%%%%%%%++.
281
- """
282
-
283
- if len(backtest_reports_evaluation.backtest_reports) == 0:
284
- print("No backtest reports available in your evaluation")
285
- return
286
-
287
- print(ascii_art)
288
- if backtest_date_range is None:
289
- pretty_print_date_ranges(backtest_reports_evaluation.get_date_ranges())
290
- print("")
291
-
292
- pretty_print_price_efficiency(reports, precision=precision)
293
- print(f"{COLOR_YELLOW}All profits ordered{COLOR_RESET}")
294
- pretty_print_profit_evaluation(
295
- backtest_reports_evaluation.get_profit_order(backtest_date_range), precision
296
- )
297
- print(f"{COLOR_YELLOW}All growths ordered{COLOR_RESET}")
298
- pretty_print_growth_evaluation(
299
- backtest_reports_evaluation.get_growth_order(backtest_date_range), precision
300
- )
301
-
302
-
303
- def print_number_of_runs(report):
304
-
305
- if report.number_of_runs == 1:
306
-
307
- if report.inteval > 1:
308
- print(f"Strategy ran every {report.interval} {report.time_unit} "
309
- f"for a total of {report.number_of_runs} time")
310
-
311
-
312
- def pretty_print_backtest(
313
- backtest_report, show_positions=True, show_trades=True, precision=4
314
- ):
315
- """
316
- Pretty print the backtest report to the console.
317
-
318
- :param backtest_report: The backtest report
319
- :param show_positions: Show the positions
320
- :param show_trades: Show the trades
321
- :param precision: The precision of the numbers
322
- """
323
-
324
- ascii_art = f"""
325
- :%%%#+- .=*#%%% {COLOR_GREEN}Backtest report{COLOR_RESET}
326
- *%%%%%%%+------=*%%%%%%%- {COLOR_GREEN}---------------------------{COLOR_RESET}
327
- *%%%%%%%%%%%%%%%%%%%%%%%- {COLOR_YELLOW}Start date:{COLOR_RESET}{COLOR_GREEN} {backtest_report.backtest_start_date}{COLOR_RESET}
328
- .%%%%%%%%%%%%%%%%%%%%%%# {COLOR_YELLOW}End date:{COLOR_RESET}{COLOR_GREEN} {backtest_report.backtest_end_date}{COLOR_RESET}
329
- #%%%####%%%%%%%%**#%%%+ {COLOR_YELLOW}Number of days:{COLOR_RESET}{COLOR_GREEN}{COLOR_RESET}{COLOR_GREEN} {backtest_report.number_of_days}{COLOR_RESET}
330
- .:-+*%%%%- {COLOR_PURPLE}-+..#{COLOR_RESET}%%%+.{COLOR_PURPLE}+- +{COLOR_RESET}%%%#*=-: {COLOR_YELLOW}Number of runs:{COLOR_RESET}{COLOR_GREEN} {backtest_report.number_of_runs}{COLOR_RESET}
331
- .:-=*%%%%. {COLOR_PURPLE}+={COLOR_RESET} .%%# {COLOR_PURPLE}-+.-{COLOR_RESET}%%%%=-:.. {COLOR_YELLOW}Number of orders:{COLOR_RESET}{COLOR_GREEN} {backtest_report.number_of_orders}{COLOR_RESET}
332
- .:=+#%%%%%*###%%%%#*+#%%%%%%*+-: {COLOR_YELLOW}Initial balance:{COLOR_RESET}{COLOR_GREEN} {backtest_report.initial_unallocated}{COLOR_RESET}
333
- +%%%%%%%%%%%%%%%%%%%= {COLOR_YELLOW}Final balance:{COLOR_RESET}{COLOR_GREEN} {backtest_report.total_value:.{precision}f}{COLOR_RESET}
334
- :++ .=#%%%%%%%%%%%%%*- {COLOR_YELLOW}Total net gain:{COLOR_RESET}{COLOR_GREEN} {backtest_report.total_net_gain:.{precision}f} {backtest_report.total_net_gain_percentage:.{precision}}%{COLOR_RESET}
335
- :++: :+%%%%%%#-. {COLOR_YELLOW}Growth:{COLOR_RESET}{COLOR_GREEN} {backtest_report.growth:.{precision}f} {backtest_report.growth_rate:.{precision}}%{COLOR_RESET}
336
- :++: .%%%%%#= {COLOR_YELLOW}Number of trades closed:{COLOR_RESET}{COLOR_GREEN} {backtest_report.number_of_trades_closed}{COLOR_RESET}
337
- :++: .#%%%%%#*= {COLOR_YELLOW}Number of trades open(end of backtest):{COLOR_RESET}{COLOR_GREEN} {backtest_report.number_of_trades_open}{COLOR_RESET}
338
- :++- :%%%%%%%%%+= {COLOR_YELLOW}Percentage positive trades:{COLOR_RESET}{COLOR_GREEN} {backtest_report.percentage_positive_trades}%{COLOR_RESET}
339
- .++- -%%%%%%%%%%%+= {COLOR_YELLOW}Percentage negative trades:{COLOR_RESET}{COLOR_GREEN} {backtest_report.percentage_negative_trades}%{COLOR_RESET}
340
- .++- .%%%%%%%%%%%%%+= {COLOR_YELLOW}Average trade size:{COLOR_RESET}{COLOR_GREEN} {backtest_report.average_trade_size:.{precision}f} {backtest_report.trading_symbol}{COLOR_RESET}
341
- .++- *%%%%%%%%%%%%%*+: {COLOR_YELLOW}Average trade duration:{COLOR_RESET}{COLOR_GREEN} {backtest_report.average_trade_duration} hours{COLOR_RESET}
342
- .++- %%%%%%%%%%%%%%#+=
343
- =++........:::%%%%%%%%%%%%%%*+-
344
- .=++++++++++**#%%%%%%%%%%%%%++.
345
- """
346
-
347
- print(ascii_art)
348
- pretty_print_price_efficiency([backtest_report], precision=precision)
349
-
350
- if show_positions:
351
- print(f"{COLOR_YELLOW}Positions overview{COLOR_RESET}")
352
- position_table = {}
353
- position_table["Position"] = [
354
- position.symbol for position in backtest_report.positions
355
- ]
356
- position_table["Amount"] = [
357
- f"{position.amount:.{precision}f}" for position in
358
- backtest_report.positions
359
- ]
360
- position_table["Pending buy amount"] = [
361
- f"{position.amount_pending_buy:.{precision}f}"
362
- for position in backtest_report.positions
363
- ]
364
- position_table["Pending sell amount"] = [
365
- f"{position.amount_pending_sell:.{precision}f}"
366
- for position in backtest_report.positions
367
- ]
368
- position_table[f"Cost ({backtest_report.trading_symbol})"] = [
369
- f"{position.cost:.{precision}f}"
370
- for position in backtest_report.positions
371
- ]
372
- position_table[f"Value ({backtest_report.trading_symbol})"] = [
373
- f"{position.value:.{precision}f}"
374
- for position in backtest_report.positions
375
- ]
376
- position_table["Percentage of portfolio"] = [
377
- f"{position.percentage_of_portfolio:.{precision}f}%"
378
- for position in backtest_report.positions
379
- ]
380
- position_table[f"Growth ({backtest_report.trading_symbol})"] = [
381
- f"{position.growth:.{precision}f}"
382
- for position in backtest_report.positions
383
- ]
384
- position_table["Growth_rate"] = [
385
- f"{position.growth_rate:.{precision}f}%"
386
- for position in backtest_report.positions
387
- ]
388
- print(
389
- tabulate(position_table, headers="keys", tablefmt="rounded_grid")
390
- )
391
-
392
- if show_trades:
393
- print(f"{COLOR_YELLOW}Trades overview{COLOR_RESET}")
394
- trades_table = {}
395
- trades_table["Pair"] = [
396
- f"{trade.target_symbol}-{trade.trading_symbol}"
397
- for trade in backtest_report.trades
398
- ]
399
- trades_table["Open date"] = [
400
- trade.opened_at for trade in backtest_report.trades
401
- ]
402
- trades_table["Close date"] = [
403
- trade.closed_at for trade in backtest_report.trades
404
- ]
405
- trades_table["Duration (hours)"] = [
406
- trade.duration for trade in backtest_report.trades
407
- ]
408
- trades_table[f"Size ({backtest_report.trading_symbol})"] = [
409
- f"{trade.size:.{precision}f}" for trade in backtest_report.trades
410
- ]
411
- trades_table[f"Net gain ({backtest_report.trading_symbol})"] = [
412
- f"{trade.net_gain:.{precision}f}"
413
- for trade in backtest_report.trades
414
- ]
415
- trades_table["Net gain percentage"] = [
416
- f"{trade.net_gain_percentage:.{precision}f}%"
417
- for trade in backtest_report.trades
418
- ]
419
- trades_table[f"Open price ({backtest_report.trading_symbol})"] = [
420
- trade.open_price for trade in backtest_report.trades
421
- ]
422
- trades_table[f"Close price ({backtest_report.trading_symbol})"] = [
423
- trade.closed_price for trade in backtest_report.trades
424
- ]
425
- print(tabulate(trades_table, headers="keys", tablefmt="rounded_grid"))
426
-
427
-
428
- def load_backtest_report(file_path: str) -> BacktestReport:
429
- """
430
- Load a backtest report from a file.
431
-
432
- param file_path: The file path
433
- :return: The backtest report
434
- """
435
-
436
- if not os.path.isfile(file_path):
437
- raise OperationalException("File does not exist")
438
-
439
- if not file_path.endswith(".json"):
440
- raise OperationalException("File is not a json file")
441
-
442
- with open(file_path, 'r') as json_file:
443
- data = json.load(json_file)
444
-
445
- return BacktestReport.from_dict(data)
446
-
447
-
448
- def load_backtest_reports(folder_path: str) -> List[BacktestReport]:
449
- """
450
- Load backtest reports from a folder.
451
-
452
- param folder_path: The folder path
453
- :return: The backtest reports
454
- """
455
- backtest_reports = []
456
-
457
- if not os.path.exists(folder_path):
458
- raise OperationalException(f"Folder {folder_path} does not exist")
459
-
460
- list_of_files = os.listdir(folder_path)
461
-
462
- if not list_of_files:
463
- raise OperationalException(f"Folder {folder_path} is empty")
464
-
465
- for file in list_of_files:
466
- if not file.endswith(".json"):
467
- continue
468
- file_path = os.path.join(folder_path, file)
469
- report = load_backtest_report(file_path)
470
- backtest_reports.append(report)
471
-
472
- return backtest_reports
@@ -1,12 +0,0 @@
1
- from .ccxt import CCXTOrderBookMarketDataSource, CCXTTickerMarketDataSource, \
2
- CCXTOHLCVMarketDataSource, CCXTOHLCVBacktestMarketDataSource
3
- from .csv import CSVOHLCVMarketDataSource, CSVTickerMarketDataSource
4
-
5
- __all__ = [
6
- 'CCXTOrderBookMarketDataSource',
7
- 'CCXTTickerMarketDataSource',
8
- 'CCXTOHLCVMarketDataSource',
9
- "CCXTOHLCVBacktestMarketDataSource",
10
- "CSVOHLCVMarketDataSource",
11
- "CSVTickerMarketDataSource"
12
- ]