investing-algorithm-framework 6.9.1__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 (192) hide show
  1. investing_algorithm_framework/__init__.py +147 -44
  2. investing_algorithm_framework/app/__init__.py +23 -6
  3. investing_algorithm_framework/app/algorithm/algorithm.py +5 -41
  4. investing_algorithm_framework/app/algorithm/algorithm_factory.py +17 -10
  5. investing_algorithm_framework/app/analysis/__init__.py +15 -0
  6. investing_algorithm_framework/app/analysis/backtest_data_ranges.py +121 -0
  7. investing_algorithm_framework/app/analysis/backtest_utils.py +107 -0
  8. investing_algorithm_framework/app/analysis/permutation.py +116 -0
  9. investing_algorithm_framework/app/analysis/ranking.py +297 -0
  10. investing_algorithm_framework/app/app.py +1322 -707
  11. investing_algorithm_framework/app/context.py +196 -88
  12. investing_algorithm_framework/app/eventloop.py +590 -0
  13. investing_algorithm_framework/app/reporting/__init__.py +16 -5
  14. investing_algorithm_framework/app/reporting/ascii.py +57 -202
  15. investing_algorithm_framework/app/reporting/backtest_report.py +284 -170
  16. investing_algorithm_framework/app/reporting/charts/__init__.py +10 -2
  17. investing_algorithm_framework/app/reporting/charts/entry_exist_signals.py +66 -0
  18. investing_algorithm_framework/app/reporting/charts/equity_curve.py +37 -0
  19. investing_algorithm_framework/app/reporting/charts/equity_curve_drawdown.py +11 -26
  20. investing_algorithm_framework/app/reporting/charts/line_chart.py +11 -0
  21. investing_algorithm_framework/app/reporting/charts/ohlcv_data_completeness.py +51 -0
  22. investing_algorithm_framework/app/reporting/charts/rolling_sharp_ratio.py +1 -1
  23. investing_algorithm_framework/app/reporting/generate.py +100 -114
  24. investing_algorithm_framework/app/reporting/tables/key_metrics_table.py +40 -32
  25. investing_algorithm_framework/app/reporting/tables/time_metrics_table.py +34 -27
  26. investing_algorithm_framework/app/reporting/tables/trade_metrics_table.py +23 -19
  27. investing_algorithm_framework/app/reporting/tables/trades_table.py +1 -1
  28. investing_algorithm_framework/app/reporting/tables/utils.py +1 -0
  29. investing_algorithm_framework/app/reporting/templates/report_template.html.j2 +10 -16
  30. investing_algorithm_framework/app/strategy.py +315 -175
  31. investing_algorithm_framework/app/task.py +5 -3
  32. investing_algorithm_framework/cli/cli.py +30 -12
  33. investing_algorithm_framework/cli/deploy_to_aws_lambda.py +131 -34
  34. investing_algorithm_framework/cli/initialize_app.py +20 -1
  35. investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +18 -6
  36. investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +22 -0
  37. investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +92 -0
  38. investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +2 -2
  39. investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +1 -1
  40. investing_algorithm_framework/create_app.py +3 -5
  41. investing_algorithm_framework/dependency_container.py +25 -39
  42. investing_algorithm_framework/domain/__init__.py +45 -38
  43. investing_algorithm_framework/domain/backtesting/__init__.py +21 -0
  44. investing_algorithm_framework/domain/backtesting/backtest.py +503 -0
  45. investing_algorithm_framework/domain/backtesting/backtest_date_range.py +96 -0
  46. investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +242 -0
  47. investing_algorithm_framework/domain/backtesting/backtest_metrics.py +459 -0
  48. investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +275 -0
  49. investing_algorithm_framework/domain/backtesting/backtest_run.py +605 -0
  50. investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +162 -0
  51. investing_algorithm_framework/domain/backtesting/combine_backtests.py +280 -0
  52. investing_algorithm_framework/domain/config.py +27 -0
  53. investing_algorithm_framework/domain/constants.py +6 -34
  54. investing_algorithm_framework/domain/data_provider.py +200 -56
  55. investing_algorithm_framework/domain/exceptions.py +34 -1
  56. investing_algorithm_framework/domain/models/__init__.py +10 -19
  57. investing_algorithm_framework/domain/models/base_model.py +0 -6
  58. investing_algorithm_framework/domain/models/data/__init__.py +7 -0
  59. investing_algorithm_framework/domain/models/data/data_source.py +214 -0
  60. investing_algorithm_framework/domain/models/{market_data_type.py → data/data_type.py} +7 -7
  61. investing_algorithm_framework/domain/models/market/market_credential.py +6 -0
  62. investing_algorithm_framework/domain/models/order/order.py +34 -13
  63. investing_algorithm_framework/domain/models/order/order_status.py +1 -1
  64. investing_algorithm_framework/domain/models/order/order_type.py +1 -1
  65. investing_algorithm_framework/domain/models/portfolio/portfolio.py +14 -1
  66. investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +5 -1
  67. investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +51 -11
  68. investing_algorithm_framework/domain/models/position/__init__.py +2 -1
  69. investing_algorithm_framework/domain/models/position/position.py +9 -0
  70. investing_algorithm_framework/domain/models/position/position_size.py +41 -0
  71. investing_algorithm_framework/domain/models/risk_rules/__init__.py +7 -0
  72. investing_algorithm_framework/domain/models/risk_rules/stop_loss_rule.py +51 -0
  73. investing_algorithm_framework/domain/models/risk_rules/take_profit_rule.py +55 -0
  74. investing_algorithm_framework/domain/models/snapshot_interval.py +0 -1
  75. investing_algorithm_framework/domain/models/strategy_profile.py +19 -151
  76. investing_algorithm_framework/domain/models/time_frame.py +7 -0
  77. investing_algorithm_framework/domain/models/time_interval.py +33 -0
  78. investing_algorithm_framework/domain/models/time_unit.py +63 -1
  79. investing_algorithm_framework/domain/models/trade/__init__.py +0 -2
  80. investing_algorithm_framework/domain/models/trade/trade.py +56 -32
  81. investing_algorithm_framework/domain/models/trade/trade_status.py +8 -2
  82. investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +106 -41
  83. investing_algorithm_framework/domain/models/trade/trade_take_profit.py +161 -99
  84. investing_algorithm_framework/domain/order_executor.py +19 -0
  85. investing_algorithm_framework/domain/portfolio_provider.py +20 -1
  86. investing_algorithm_framework/domain/services/__init__.py +0 -13
  87. investing_algorithm_framework/domain/strategy.py +1 -29
  88. investing_algorithm_framework/domain/utils/__init__.py +5 -1
  89. investing_algorithm_framework/domain/utils/custom_tqdm.py +22 -0
  90. investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +19 -0
  91. investing_algorithm_framework/domain/utils/polars.py +17 -14
  92. investing_algorithm_framework/download_data.py +40 -10
  93. investing_algorithm_framework/infrastructure/__init__.py +13 -25
  94. investing_algorithm_framework/infrastructure/data_providers/__init__.py +7 -4
  95. investing_algorithm_framework/infrastructure/data_providers/ccxt.py +811 -546
  96. investing_algorithm_framework/infrastructure/data_providers/csv.py +433 -122
  97. investing_algorithm_framework/infrastructure/data_providers/pandas.py +599 -0
  98. investing_algorithm_framework/infrastructure/database/__init__.py +6 -2
  99. investing_algorithm_framework/infrastructure/database/sql_alchemy.py +81 -0
  100. investing_algorithm_framework/infrastructure/models/__init__.py +0 -13
  101. investing_algorithm_framework/infrastructure/models/order/order.py +9 -3
  102. investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +27 -8
  103. investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +21 -7
  104. investing_algorithm_framework/infrastructure/order_executors/__init__.py +2 -0
  105. investing_algorithm_framework/infrastructure/order_executors/backtest_oder_executor.py +28 -0
  106. investing_algorithm_framework/infrastructure/repositories/repository.py +16 -2
  107. investing_algorithm_framework/infrastructure/repositories/trade_repository.py +2 -2
  108. investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +6 -0
  109. investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +6 -0
  110. investing_algorithm_framework/infrastructure/services/__init__.py +0 -4
  111. investing_algorithm_framework/services/__init__.py +105 -8
  112. investing_algorithm_framework/services/backtesting/backtest_service.py +536 -476
  113. investing_algorithm_framework/services/configuration_service.py +14 -4
  114. investing_algorithm_framework/services/data_providers/__init__.py +5 -0
  115. investing_algorithm_framework/services/data_providers/data_provider_service.py +850 -0
  116. investing_algorithm_framework/{app/reporting → services}/metrics/__init__.py +48 -17
  117. investing_algorithm_framework/{app/reporting → services}/metrics/drawdown.py +10 -10
  118. investing_algorithm_framework/{app/reporting → services}/metrics/equity_curve.py +2 -2
  119. investing_algorithm_framework/{app/reporting → services}/metrics/exposure.py +60 -2
  120. investing_algorithm_framework/services/metrics/generate.py +358 -0
  121. investing_algorithm_framework/{app/reporting → services}/metrics/profit_factor.py +36 -0
  122. investing_algorithm_framework/{app/reporting → services}/metrics/recovery.py +2 -2
  123. investing_algorithm_framework/{app/reporting → services}/metrics/returns.py +146 -147
  124. investing_algorithm_framework/services/metrics/risk_free_rate.py +28 -0
  125. investing_algorithm_framework/{app/reporting/metrics/sharp_ratio.py → services/metrics/sharpe_ratio.py} +6 -10
  126. investing_algorithm_framework/{app/reporting → services}/metrics/sortino_ratio.py +3 -7
  127. investing_algorithm_framework/services/metrics/trades.py +500 -0
  128. investing_algorithm_framework/services/metrics/volatility.py +97 -0
  129. investing_algorithm_framework/{app/reporting → services}/metrics/win_rate.py +70 -3
  130. investing_algorithm_framework/services/order_service/order_backtest_service.py +21 -31
  131. investing_algorithm_framework/services/order_service/order_service.py +9 -71
  132. investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +0 -2
  133. investing_algorithm_framework/services/portfolios/portfolio_service.py +3 -13
  134. investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +62 -96
  135. investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +0 -3
  136. investing_algorithm_framework/services/repository_service.py +5 -2
  137. investing_algorithm_framework/services/trade_order_evaluator/__init__.py +9 -0
  138. investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +113 -0
  139. investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +51 -0
  140. investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +80 -0
  141. investing_algorithm_framework/services/trade_service/__init__.py +7 -1
  142. investing_algorithm_framework/services/trade_service/trade_service.py +51 -29
  143. investing_algorithm_framework/services/trade_service/trade_stop_loss_service.py +39 -0
  144. investing_algorithm_framework/services/trade_service/trade_take_profit_service.py +41 -0
  145. investing_algorithm_framework-7.19.15.dist-info/METADATA +537 -0
  146. {investing_algorithm_framework-6.9.1.dist-info → investing_algorithm_framework-7.19.15.dist-info}/RECORD +159 -148
  147. investing_algorithm_framework/app/reporting/evaluation.py +0 -243
  148. investing_algorithm_framework/app/reporting/metrics/risk_free_rate.py +0 -8
  149. investing_algorithm_framework/app/reporting/metrics/volatility.py +0 -69
  150. investing_algorithm_framework/cli/templates/requirements_azure_function.txt.template +0 -3
  151. investing_algorithm_framework/domain/models/backtesting/__init__.py +0 -9
  152. investing_algorithm_framework/domain/models/backtesting/backtest_date_range.py +0 -47
  153. investing_algorithm_framework/domain/models/backtesting/backtest_position.py +0 -120
  154. investing_algorithm_framework/domain/models/backtesting/backtest_reports_evaluation.py +0 -0
  155. investing_algorithm_framework/domain/models/backtesting/backtest_results.py +0 -440
  156. investing_algorithm_framework/domain/models/data_source.py +0 -21
  157. investing_algorithm_framework/domain/models/date_range.py +0 -64
  158. investing_algorithm_framework/domain/models/trade/trade_risk_type.py +0 -34
  159. investing_algorithm_framework/domain/models/trading_data_types.py +0 -48
  160. investing_algorithm_framework/domain/models/trading_time_frame.py +0 -223
  161. investing_algorithm_framework/domain/services/market_data_sources.py +0 -543
  162. investing_algorithm_framework/domain/services/market_service.py +0 -153
  163. investing_algorithm_framework/domain/services/observable.py +0 -51
  164. investing_algorithm_framework/domain/services/observer.py +0 -19
  165. investing_algorithm_framework/infrastructure/models/market_data_sources/__init__.py +0 -16
  166. investing_algorithm_framework/infrastructure/models/market_data_sources/ccxt.py +0 -746
  167. investing_algorithm_framework/infrastructure/models/market_data_sources/csv.py +0 -270
  168. investing_algorithm_framework/infrastructure/models/market_data_sources/pandas.py +0 -312
  169. investing_algorithm_framework/infrastructure/services/market_service/__init__.py +0 -5
  170. investing_algorithm_framework/infrastructure/services/market_service/ccxt_market_service.py +0 -471
  171. investing_algorithm_framework/infrastructure/services/performance_service/__init__.py +0 -7
  172. investing_algorithm_framework/infrastructure/services/performance_service/backtest_performance_service.py +0 -2
  173. investing_algorithm_framework/infrastructure/services/performance_service/performance_service.py +0 -322
  174. investing_algorithm_framework/services/market_data_source_service/__init__.py +0 -10
  175. investing_algorithm_framework/services/market_data_source_service/backtest_market_data_source_service.py +0 -269
  176. investing_algorithm_framework/services/market_data_source_service/data_provider_service.py +0 -350
  177. investing_algorithm_framework/services/market_data_source_service/market_data_source_service.py +0 -377
  178. investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -296
  179. investing_algorithm_framework-6.9.1.dist-info/METADATA +0 -440
  180. /investing_algorithm_framework/{app/reporting → services}/metrics/alpha.py +0 -0
  181. /investing_algorithm_framework/{app/reporting → services}/metrics/beta.py +0 -0
  182. /investing_algorithm_framework/{app/reporting → services}/metrics/cagr.py +0 -0
  183. /investing_algorithm_framework/{app/reporting → services}/metrics/calmar_ratio.py +0 -0
  184. /investing_algorithm_framework/{app/reporting → services}/metrics/mean_daily_return.py +0 -0
  185. /investing_algorithm_framework/{app/reporting → services}/metrics/price_efficiency.py +0 -0
  186. /investing_algorithm_framework/{app/reporting → services}/metrics/standard_deviation.py +0 -0
  187. /investing_algorithm_framework/{app/reporting → services}/metrics/treynor_ratio.py +0 -0
  188. /investing_algorithm_framework/{app/reporting → services}/metrics/ulcer.py +0 -0
  189. /investing_algorithm_framework/{app/reporting → services}/metrics/value_at_risk.py +0 -0
  190. {investing_algorithm_framework-6.9.1.dist-info → investing_algorithm_framework-7.19.15.dist-info}/LICENSE +0 -0
  191. {investing_algorithm_framework-6.9.1.dist-info → investing_algorithm_framework-7.19.15.dist-info}/WHEEL +0 -0
  192. {investing_algorithm_framework-6.9.1.dist-info → investing_algorithm_framework-7.19.15.dist-info}/entry_points.txt +0 -0
@@ -4,11 +4,10 @@ from typing import List
4
4
 
5
5
  from tabulate import tabulate
6
6
 
7
- from investing_algorithm_framework.domain import DATETIME_FORMAT, \
8
- BacktestDateRange, TradeStatus, OrderSide, TradeRiskType
7
+ from investing_algorithm_framework.domain import DATETIME_FORMAT, Backtest, \
8
+ BacktestDateRange, TradeStatus, OrderSide
9
9
  from investing_algorithm_framework.domain.constants import \
10
10
  DATETIME_FORMAT_BACKTESTING
11
- from .evaluation import BacktestReportsEvaluation
12
11
 
13
12
  COLOR_RED = '\033[91m'
14
13
  COLOR_PURPLE = '\033[95m'
@@ -106,7 +105,8 @@ def pretty_print_growth_evaluation(
106
105
  )
107
106
 
108
107
  def pretty_print_stop_losses(
109
- backtest_report,
108
+ backtest,
109
+ backtest_date_range: BacktestDateRange = None,
110
110
  triggered_only=False,
111
111
  amount_precision=4,
112
112
  price_precision=2,
@@ -115,8 +115,8 @@ def pretty_print_stop_losses(
115
115
  ):
116
116
  print(f"{COLOR_YELLOW}Stop losses overview{COLOR_RESET}")
117
117
  stop_loss_table = {}
118
- results = backtest_report.results
119
- trades = results.trades
118
+ results = backtest.get_backtest_run(backtest_date_range)
119
+ trades = results.get_trades()
120
120
  selection = []
121
121
 
122
122
  def get_sold_amount(stop_loss):
@@ -144,7 +144,7 @@ def pretty_print_stop_losses(
144
144
 
145
145
  def get_stop_loss_price(take_profit):
146
146
 
147
- if TradeRiskType.TRAILING.equals(take_profit["trade_risk_type"]):
147
+ if take_profit["trailing"]:
148
148
  initial_price = take_profit["open_price"]
149
149
  percentage = take_profit["percentage"]
150
150
  initial_stop_loss_price = \
@@ -164,7 +164,7 @@ def pretty_print_stop_losses(
164
164
  "trading_symbol": trade.trading_symbol,
165
165
  "status": get_status(stop_loss),
166
166
  "trade_id": stop_loss.trade_id,
167
- "trade_risk_type": stop_loss.trade_risk_type,
167
+ "trailing": stop_loss.trailing,
168
168
  "percentage": stop_loss.percentage,
169
169
  "open_price": stop_loss.open_price,
170
170
  "sell_percentage": stop_loss.sell_percentage,
@@ -188,7 +188,7 @@ def pretty_print_stop_losses(
188
188
  "trading_symbol": trade.trading_symbol,
189
189
  "status": get_status(stop_loss),
190
190
  "trade_id": stop_loss.trade_id,
191
- "trade_risk_type": stop_loss.trade_risk_type,
191
+ "trailing": stop_loss.trailing,
192
192
  "percentage": stop_loss.percentage,
193
193
  "open_price": stop_loss.open_price,
194
194
  "sell_percentage": stop_loss.sell_percentage,
@@ -229,7 +229,7 @@ def pretty_print_stop_losses(
229
229
  for stop_loss in selection
230
230
  ]
231
231
  stop_loss_table["Type"] = [
232
- f"{stop_loss['trade_risk_type']}" for stop_loss in selection
232
+ f"{stop_loss['trailing']}" for stop_loss in selection
233
233
  ]
234
234
  stop_loss_table["Stop Loss (Initial Stop Loss)"] = [
235
235
  get_stop_loss_price(stop_loss) for stop_loss in selection
@@ -256,7 +256,8 @@ def pretty_print_stop_losses(
256
256
 
257
257
 
258
258
  def pretty_print_take_profits(
259
- backtest_report,
259
+ backtest: Backtest,
260
+ backtest_date_range: BacktestDateRange = None,
260
261
  triggered_only=False,
261
262
  amount_precision=4,
262
263
  price_precision=2,
@@ -265,8 +266,8 @@ def pretty_print_take_profits(
265
266
  ):
266
267
  print(f"{COLOR_YELLOW}Take profits overview{COLOR_RESET}")
267
268
  take_profit_table = {}
268
- results = backtest_report.results
269
- trades = results.trades
269
+ results = backtest.get_backtest_run(backtest_date_range)
270
+ trades = results.get_trades()
270
271
  selection = []
271
272
 
272
273
  def get_high_water_mark(take_profit):
@@ -283,7 +284,7 @@ def pretty_print_take_profits(
283
284
 
284
285
  def get_take_profit_price(take_profit):
285
286
 
286
- if TradeRiskType.TRAILING.equals(take_profit["trade_risk_type"]):
287
+ if take_profit["trailing"]:
287
288
  initial_price = take_profit["open_price"]
288
289
  percentage = take_profit["percentage"]
289
290
  initial_take_profit_price = \
@@ -314,7 +315,7 @@ def pretty_print_take_profits(
314
315
  "trading_symbol": trade.trading_symbol,
315
316
  "status": get_status(take_profit),
316
317
  "trade_id": take_profit.trade_id,
317
- "trade_risk_type": take_profit.trade_risk_type,
318
+ "trailing": take_profit.trailing,
318
319
  "percentage": take_profit.percentage,
319
320
  "open_price": take_profit.open_price,
320
321
  "sell_percentage": take_profit.sell_percentage,
@@ -340,7 +341,7 @@ def pretty_print_take_profits(
340
341
  "trading_symbol": trade.trading_symbol,
341
342
  "status": get_status(take_profit),
342
343
  "trade_id": take_profit.trade_id,
343
- "trade_risk_type": take_profit.trade_risk_type,
344
+ "trailing": take_profit.trailing,
344
345
  "percentage": take_profit.percentage,
345
346
  "open_price": take_profit.open_price,
346
347
  "sell_percentage": take_profit.sell_percentage,
@@ -382,7 +383,7 @@ def pretty_print_take_profits(
382
383
  for stop_loss in selection
383
384
  ]
384
385
  take_profit_table["Type"] = [
385
- f"{stop_loss['trade_risk_type']}" for stop_loss
386
+ f"{take_profit['trailing']}" for take_profit
386
387
  in selection
387
388
  ]
388
389
  take_profit_table["Take profit (Initial Take Profit)"] = [
@@ -410,54 +411,6 @@ def pretty_print_take_profits(
410
411
  print(tabulate(take_profit_table, headers="keys", tablefmt="rounded_grid"))
411
412
 
412
413
 
413
- def pretty_print_percentage_positive_trades_evaluation(
414
- evaluation: BacktestReportsEvaluation,
415
- backtest_date_range: BacktestDateRange,
416
- precision=0,
417
- number_of_reports=3
418
- ):
419
- order = evaluation.get_percentage_positive_trades_order(backtest_date_range=backtest_date_range)
420
- print(f"{COLOR_YELLOW}Trades:{COLOR_RESET} {COLOR_GREEN}Top {number_of_reports}{COLOR_RESET}")
421
- profit_table = {}
422
- profit_table["Algorithm name"] = [
423
- report.name for report in order[:number_of_reports]
424
- ]
425
- profit_table["Percentage positive trades"] = [
426
- f"{float(report.percentage_positive_trades):.{precision}f}%"
427
- for report in order[:number_of_reports]
428
- ]
429
- profit_table["Total amount of trades"] = [
430
- f"{report.number_of_trades_closed}" for report in order[:number_of_reports]
431
- ]
432
- print(
433
- tabulate(profit_table, headers="keys", tablefmt="rounded_grid")
434
- )
435
-
436
- least = order[-number_of_reports:]
437
- table = {}
438
- table["Algorithm name"] = [
439
- report.name for report in least
440
- ]
441
- table["Percentage positive trades"] = [
442
- f"{float(report.percentage_positive_trades):.{precision}f}%"
443
- for report in least
444
- ]
445
- table["Total amount of trades"] = [
446
- f"{report.number_of_trades_closed}" for report in
447
- least
448
- ]
449
-
450
- print(
451
- f"{COLOR_RED}Worst trades:{COLOR_RESET} {COLOR_GREEN}"
452
- f"Top {number_of_reports}{COLOR_RESET}"
453
- )
454
- print(
455
- tabulate(
456
- table, headers="keys", tablefmt="rounded_grid"
457
- )
458
- )
459
-
460
-
461
414
  def pretty_print_date_ranges(date_ranges: List[BacktestDateRange]) -> None:
462
415
  """
463
416
  Pretty print the date ranges to the console.
@@ -501,9 +454,6 @@ def pretty_print_price_efficiency(reports, precision=4):
501
454
  row["Efficiency ratio / Noise"] = f"{float(price_efficiency[symbol]):.{precision}f}"
502
455
  row["Date"] = f"{report.backtest_start_date} - {report.backtest_end_date}"
503
456
 
504
-
505
-
506
-
507
457
  if report.backtest_date_range.name is not None:
508
458
  row["Date"] = f"{report.backtest_date_range.name} " \
509
459
  f"{report.backtest_date_range.start_date}" \
@@ -542,38 +492,9 @@ def pretty_print_price_efficiency(reports, precision=4):
542
492
  )
543
493
 
544
494
 
545
- def pretty_print_most_profitable(
546
- evaluation: BacktestReportsEvaluation,
547
- backtest_date_range: BacktestDateRange,
548
- precision=4,
549
- ):
550
- profits = evaluation.get_profit_order(backtest_date_range=backtest_date_range)
551
- profit = profits[0]
552
- print(f"{COLOR_YELLOW}Most profitable:{COLOR_RESET} {COLOR_GREEN}Algorithm {profit.name} {float(profit.total_net_gain):.{precision}f} {profit.trading_symbol} {float(profit.total_net_gain_percentage):.{precision}f}%{COLOR_RESET}")
553
-
554
-
555
- def pretty_print_most_growth(
556
- evaluation: BacktestReportsEvaluation,
557
- backtest_date_range: BacktestDateRange,
558
- precision=4,
559
- ):
560
- profits = evaluation.get_growth_order(backtest_date_range=backtest_date_range)
561
- profit = profits[0]
562
- print(f"{COLOR_YELLOW}Most growth:{COLOR_RESET} {COLOR_GREEN}Algorithm {profit.name} {float(profit.growth):.{precision}f} {profit.trading_symbol} {float(profit.growth_percentage):.{precision}f}%{COLOR_RESET}")
563
-
564
-
565
- def pretty_print_percentage_positive_trades(
566
- evaluation: BacktestReportsEvaluation,
567
- backtest_date_range: BacktestDateRange,
568
- precision=0
569
- ):
570
- percentages = evaluation.get_percentage_positive_trades_order(backtest_date_range=backtest_date_range)
571
- percentages = percentages[0]
572
- print(f"{COLOR_YELLOW}Most positive trades:{COLOR_RESET} {COLOR_GREEN}Algorithm {percentages.name} {float(percentages.percentage_positive_trades):.{precision}f}%{COLOR_RESET}")
573
-
574
-
575
495
  def pretty_print_orders(
576
- backtest_report,
496
+ backtest: Backtest,
497
+ backtest_date_range: BacktestDateRange = None,
577
498
  target_symbol = None,
578
499
  order_status = None,
579
500
  amount_precesion=4,
@@ -585,7 +506,8 @@ def pretty_print_orders(
585
506
  Pretty print the orders of the backtest report to the console.
586
507
 
587
508
  Args:
588
- backtest_report: The backtest report
509
+ backtest: The backtest
510
+ backtest_date_range: The date range of the backtest
589
511
  target_symbol: The target symbol of the orders
590
512
  order_status: The status of the orders
591
513
  amount_precesion: The precision of the amount
@@ -596,8 +518,8 @@ def pretty_print_orders(
596
518
  Returns:
597
519
  None
598
520
  """
599
-
600
- selection = backtest_report.get_orders(
521
+ run = backtest.get_backtest_run(backtest_date_range)
522
+ selection = run.get_orders(
601
523
  target_symbol=target_symbol,
602
524
  order_status=order_status
603
525
  )
@@ -637,7 +559,8 @@ def pretty_print_orders(
637
559
 
638
560
 
639
561
  def pretty_print_positions(
640
- backtest_report,
562
+ backtest,
563
+ backtest_date_range: BacktestDateRange = None,
641
564
  symbol = None,
642
565
  amount_precision=4,
643
566
  price_precision=2,
@@ -648,9 +571,8 @@ def pretty_print_positions(
648
571
  Pretty print the positions of the backtest report to the console.
649
572
 
650
573
  Args:
651
- backtest_report: The backtest report
652
- target_symbol: The target symbol of the orders
653
- order_status: The status of the orders
574
+ backtest: The backtest report
575
+ backtest_date_range: The date range of the backtest
654
576
  amount_precision: The precision of the amount
655
577
  price_precision: The precision of the price
656
578
  time_precision: The precision of the time
@@ -659,7 +581,7 @@ def pretty_print_positions(
659
581
  Returns:
660
582
  None
661
583
  """
662
- results = backtest_report.results
584
+ results = backtest.get_backtest_run(backtest_date_range)
663
585
  selection = results.get_positions(symbol=symbol)
664
586
 
665
587
  print(f"{COLOR_YELLOW}Positions overview{COLOR_RESET}")
@@ -705,7 +627,8 @@ def pretty_print_positions(
705
627
 
706
628
 
707
629
  def pretty_print_trades(
708
- backtest_report,
630
+ backtest: Backtest,
631
+ backtest_date_range: BacktestDateRange = None,
709
632
  target_symbol = None,
710
633
  status = None,
711
634
  amount_precision=4,
@@ -717,10 +640,11 @@ def pretty_print_trades(
717
640
  Pretty print the trades of the backtest report to the console.
718
641
 
719
642
  Args:
720
- backtest_report: The backtest report
643
+ backtest: The backtest report
644
+ backtest_date_range: The date range of the backtest
721
645
  target_symbol: The target symbol of the trades
722
646
  status: The status of the trades
723
- amount_precesion: The precision of the amount
647
+ amount_precision: The precision of the amount
724
648
  price_precision: The precision of the price
725
649
  time_precision: The precision of the time
726
650
  percentage_precision: The precision of the percentage
@@ -728,8 +652,8 @@ def pretty_print_trades(
728
652
  Returns:
729
653
  None
730
654
  """
731
- results = backtest_report.results
732
- selection = results.get_trades(
655
+ run = backtest.get_backtest_run(backtest_date_range)
656
+ selection = run.get_trades(
733
657
  target_symbol=target_symbol,
734
658
  trade_status=status
735
659
  )
@@ -807,7 +731,7 @@ def pretty_print_trades(
807
731
  f"{float(trade.amount):.{amount_precision}f} ({float(trade.remaining):.{amount_precision}f}) {trade.target_symbol}"
808
732
  for trade in selection
809
733
  ]
810
- trades_table[f"Net gain ({results.trading_symbol})"] = [
734
+ trades_table[f"Net gain ({run.trading_symbol})"] = [
811
735
  f"{float(trade.net_gain):.{price_precision}f}"
812
736
  for trade in selection
813
737
  ]
@@ -821,15 +745,15 @@ def pretty_print_trades(
821
745
  f"{trade.duration:.{time_precision}f} hours" for trade in selection
822
746
  ]
823
747
  # Add (unrealized) to the net gain if the trade is still open
824
- trades_table[f"Net gain ({results.trading_symbol})"] = [
748
+ trades_table[f"Net gain ({run.trading_symbol})"] = [
825
749
  f"{float(trade.net_gain_absolute):.{price_precision}f} ({float(trade.net_gain_percentage):.{percentage_precision}f}%)" + (" (unrealized)" if not TradeStatus.CLOSED.equals(trade.status) else "")
826
750
  for trade in selection
827
751
  ]
828
- trades_table[f"Open price ({results.trading_symbol})"] = [
752
+ trades_table[f"Open price ({run.trading_symbol})"] = [
829
753
  f"{trade.open_price:.{price_precision}f}" for trade in selection
830
754
  ]
831
755
  trades_table[
832
- f"Close price's ({results.trading_symbol})"
756
+ f"Close price's ({run.trading_symbol})"
833
757
  ] = [
834
758
  get_close_prices(trade) for trade in selection
835
759
  ]
@@ -839,77 +763,6 @@ def pretty_print_trades(
839
763
  print(tabulate(trades_table, headers="keys", tablefmt="rounded_grid"))
840
764
 
841
765
 
842
- def pretty_print_backtest_reports_evaluation(
843
- backtest_reports_evaluation: BacktestReportsEvaluation,
844
- amount_precision=4,
845
- price_precision=2,
846
- time_precision=1,
847
- percentage_precision=2,
848
- backtest_date_range: BacktestDateRange = None
849
- ) -> None:
850
- """
851
- Pretty print the backtest reports evaluation to the console.
852
- """
853
- if backtest_date_range is not None:
854
- reports = backtest_reports_evaluation.get_reports(backtest_date_range=backtest_date_range)
855
-
856
- if len(reports) == 0:
857
- print(f"No reports available for date range {backtest_date_range}")
858
- return
859
- else:
860
- reports = backtest_reports_evaluation.backtest_reports
861
-
862
- number_of_backtest_reports = len(reports)
863
- most_profitable = backtest_reports_evaluation.get_profit_order(backtest_date_range)[0]
864
- most_growth = backtest_reports_evaluation.get_growth_order(backtest_date_range)[0]
865
-
866
- ascii_art = f"""
867
- :%%%#+- .=*#%%% {COLOR_GREEN}Backtest reports evaluation{COLOR_RESET}
868
- *%%%%%%%+------=*%%%%%%%- {COLOR_GREEN}---------------------------{COLOR_RESET}
869
- *%%%%%%%%%%%%%%%%%%%%%%%- {COLOR_YELLOW}Number of reports:{COLOR_RESET} {COLOR_GREEN}{number_of_backtest_reports} backtest reports{COLOR_RESET}
870
- .%%%%%%%%%%%%%%%%%%%%%%# {COLOR_YELLOW}Largest overall profit:{COLOR_RESET}{COLOR_GREEN}{COLOR_RESET}{COLOR_GREEN} (Algorithm {most_profitable.name}) {float(most_profitable.total_net_gain):.{price_precision}f} {most_profitable.trading_symbol} {float(most_profitable.total_net_gain_percentage):.{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}
871
- #%%%####%%%%%%%%**#%%%+ {COLOR_YELLOW}Largest overall growth:{COLOR_RESET}{COLOR_GREEN} (Algorithm {most_profitable.name}) {float(most_growth.growth):.{price_precision}f} {most_growth.trading_symbol} {float(most_growth.growth_percentage):.{percentage_precision}f}% ({most_growth.backtest_date_range.name} {most_growth.backtest_date_range.start_date} - {most_growth.backtest_date_range.end_date}){COLOR_RESET}
872
- .:-+*%%%%- {COLOR_PURPLE}-+..#{COLOR_RESET}%%%+.{COLOR_PURPLE}+- +{COLOR_RESET}%%%#*=-:
873
- .:-=*%%%%. {COLOR_PURPLE}+={COLOR_RESET} .%%# {COLOR_PURPLE}-+.-{COLOR_RESET}%%%%=-:..
874
- .:=+#%%%%%*###%%%%#*+#%%%%%%*+-:
875
- +%%%%%%%%%%%%%%%%%%%=
876
- :++ .=#%%%%%%%%%%%%%*-
877
- :++: :+%%%%%%#-.
878
- :++: .%%%%%#=
879
- :++: .#%%%%%#*=
880
- :++- :%%%%%%%%%+=
881
- .++- -%%%%%%%%%%%+=
882
- .++- .%%%%%%%%%%%%%+=
883
- .++- *%%%%%%%%%%%%%*+:
884
- .++- %%%%%%%%%%%%%%#+=
885
- =++........:::%%%%%%%%%%%%%%*+-
886
- .=++++++++++**#%%%%%%%%%%%%%++.
887
- """
888
-
889
- if len(backtest_reports_evaluation.backtest_reports) == 0:
890
- print("No backtest reports available in your evaluation")
891
- return
892
-
893
- print(ascii_art)
894
- if backtest_date_range is None:
895
- pretty_print_date_ranges(backtest_reports_evaluation.get_date_ranges())
896
- print("")
897
-
898
- pretty_print_price_efficiency(reports, precision=price_precision)
899
- print(f"{COLOR_YELLOW}All profits ordered{COLOR_RESET}")
900
- pretty_print_profit_evaluation(
901
- backtest_reports_evaluation.get_profit_order(backtest_date_range),
902
- price_precision=price_precision,
903
- percentage_precision=percentage_precision
904
- )
905
- print(f"{COLOR_YELLOW}All growths ordered{COLOR_RESET}")
906
- pretty_print_growth_evaluation(
907
- backtest_reports_evaluation.get_growth_order(backtest_date_range),
908
- percentage_precision=percentage_precision,
909
- price_precision=price_precision
910
- )
911
-
912
-
913
766
  def print_number_of_runs(report):
914
767
 
915
768
  if report.number_of_runs == 1:
@@ -920,7 +773,8 @@ def print_number_of_runs(report):
920
773
 
921
774
 
922
775
  def pretty_print_backtest(
923
- backtest_report,
776
+ backtest: Backtest,
777
+ backtest_date_range: BacktestDateRange = None,
924
778
  show_positions=True,
925
779
  show_trades=True,
926
780
  show_stop_losses=True,
@@ -936,14 +790,14 @@ def pretty_print_backtest(
936
790
  Pretty print the backtest report to the console.
937
791
 
938
792
  Args:
939
- backtest_report: BacktestReport - the backtest report
793
+ backtest: Backtest - the backtest report
940
794
  show_positions: bool - show the positions
941
795
  show_trades: bool - show the trades
942
796
  show_stop_losses: bool - show the stop losses
943
797
  show_triggered_stop_losses_only: bool - show only the triggered stop losses
944
798
  show_take_profits: bool - show the take profits
945
799
  show_triggered_take_profits_only: bool - show only the triggered take profits
946
- amount_precesion: int - the amount precision
800
+ amount_precision: int - the amount precision
947
801
  price_precision: int - the price precision
948
802
  time_precision: int - the time precision
949
803
  percentage_precision: int - the percentage precision
@@ -951,7 +805,8 @@ def pretty_print_backtest(
951
805
  Returns:
952
806
  None
953
807
  """
954
- backtest_results = backtest_report.results
808
+ backtest_results = backtest.get_backtest_run(backtest_date_range)
809
+ backtest_metrics = backtest.get_backtest_metrics(backtest_date_range)
955
810
  ascii_art = f"""
956
811
  :%%%#+- .=*#%%% {COLOR_GREEN}Backtest report{COLOR_RESET}
957
812
  *%%%%%%%+------=*%%%%%%%- {COLOR_GREEN}---------------------------{COLOR_RESET}
@@ -961,16 +816,16 @@ def pretty_print_backtest(
961
816
  .:-+*%%%%- {COLOR_PURPLE}-+..#{COLOR_RESET}%%%+.{COLOR_PURPLE}+- +{COLOR_RESET}%%%#*=-: {COLOR_YELLOW}Number of runs:{COLOR_RESET}{COLOR_GREEN} {backtest_results.number_of_runs}{COLOR_RESET}
962
817
  .:-=*%%%%. {COLOR_PURPLE}+={COLOR_RESET} .%%# {COLOR_PURPLE}-+.-{COLOR_RESET}%%%%=-:.. {COLOR_YELLOW}Number of orders:{COLOR_RESET}{COLOR_GREEN} {backtest_results.number_of_orders}{COLOR_RESET}
963
818
  .:=+#%%%%%*###%%%%#*+#%%%%%%*+-: {COLOR_YELLOW}Initial balance:{COLOR_RESET}{COLOR_GREEN} {backtest_results.initial_unallocated}{COLOR_RESET}
964
- +%%%%%%%%%%%%%%%%%%%= {COLOR_YELLOW}Final balance:{COLOR_RESET}{COLOR_GREEN} {float(backtest_results.total_value):.{price_precision}f}{COLOR_RESET}
965
- :++ .=#%%%%%%%%%%%%%*- {COLOR_YELLOW}Total net gain:{COLOR_RESET}{COLOR_GREEN} {float(backtest_results.total_net_gain):.{price_precision}f} {float(backtest_results.total_net_gain_percentage):.{percentage_precision}f}%{COLOR_RESET}
966
- :++: :+%%%%%%#-. {COLOR_YELLOW}Growth:{COLOR_RESET}{COLOR_GREEN} {float(backtest_results.growth):.{price_precision}f} {float(backtest_results.growth_percentage):.{percentage_precision}f}%{COLOR_RESET}
819
+ +%%%%%%%%%%%%%%%%%%%= {COLOR_YELLOW}Final balance:{COLOR_RESET}{COLOR_GREEN} {float(backtest_metrics.final_value):.{price_precision}f}{COLOR_RESET}
820
+ :++ .=#%%%%%%%%%%%%%*- {COLOR_YELLOW}Total net gain:{COLOR_RESET}{COLOR_GREEN} {float(backtest_metrics.total_net_gain):.{price_precision}f} {float(backtest_metrics.total_net_gain_percentage):.{percentage_precision}f}%{COLOR_RESET}
821
+ :++: :+%%%%%%#-. {COLOR_YELLOW}Growth:{COLOR_RESET}{COLOR_GREEN} {float(backtest_metrics.growth):.{price_precision}f} {float(backtest_metrics.growth_percentage):.{percentage_precision}f}%{COLOR_RESET}
967
822
  :++: .%%%%%#= {COLOR_YELLOW}Number of trades:{COLOR_RESET}{COLOR_GREEN} {backtest_results.number_of_trades}{COLOR_RESET}
968
823
  :++: .%%%%%#= {COLOR_YELLOW}Number of trades closed:{COLOR_RESET}{COLOR_GREEN} {backtest_results.number_of_trades_closed}{COLOR_RESET}
969
824
  :++: .#%%%%%#*= {COLOR_YELLOW}Number of trades open(end of backtest):{COLOR_RESET}{COLOR_GREEN} {backtest_results.number_of_trades_open}{COLOR_RESET}
970
- :++- :%%%%%%%%%+= {COLOR_YELLOW}Percentage positive trades:{COLOR_RESET}{COLOR_GREEN} {float(backtest_results.percentage_positive_trades):.{percentage_precision}f}%{COLOR_RESET}
971
- .++- -%%%%%%%%%%%+= {COLOR_YELLOW}Percentage negative trades:{COLOR_RESET}{COLOR_GREEN} {float(backtest_results.percentage_negative_trades):.{percentage_precision}f}%{COLOR_RESET}
972
- .++- .%%%%%%%%%%%%%+= {COLOR_YELLOW}Average trade size:{COLOR_RESET}{COLOR_GREEN} {float(backtest_results.average_trade_size):.{price_precision}f} {backtest_results.trading_symbol}{COLOR_RESET}
973
- .++- *%%%%%%%%%%%%%*+: {COLOR_YELLOW}Average trade duration:{COLOR_RESET}{COLOR_GREEN} {float(backtest_results.average_trade_duration):.{0}f} hours{COLOR_RESET}
825
+ :++- :%%%%%%%%%+= {COLOR_YELLOW}Percentage positive trades:{COLOR_RESET}{COLOR_GREEN} {float(backtest_metrics.percentage_positive_trades):.{percentage_precision}f}%{COLOR_RESET}
826
+ .++- -%%%%%%%%%%%+= {COLOR_YELLOW}Percentage negative trades:{COLOR_RESET}{COLOR_GREEN} {float(backtest_metrics.percentage_negative_trades):.{percentage_precision}f}%{COLOR_RESET}
827
+ .++- .%%%%%%%%%%%%%+= {COLOR_YELLOW}Average trade size:{COLOR_RESET}{COLOR_GREEN} {float(backtest_metrics.average_trade_size):.{price_precision}f} {backtest_results.trading_symbol}{COLOR_RESET}
828
+ .++- *%%%%%%%%%%%%%*+: {COLOR_YELLOW}Average trade duration:{COLOR_RESET}{COLOR_GREEN} {float(backtest_metrics.average_trade_duration):.{0}f} hours{COLOR_RESET}
974
829
  .++- %%%%%%%%%%%%%%#+=
975
830
  =++........:::%%%%%%%%%%%%%%*+-
976
831
  .=++++++++++**#%%%%%%%%%%%%%++.
@@ -980,11 +835,11 @@ def pretty_print_backtest(
980
835
 
981
836
  if show_positions:
982
837
  print(f"{COLOR_YELLOW}Positions overview{COLOR_RESET}")
983
- pretty_print_positions(backtest_report)
838
+ pretty_print_positions(backtest)
984
839
 
985
840
  if show_trades:
986
841
  pretty_print_trades(
987
- backtest_report=backtest_report,
842
+ backtest=backtest,
988
843
  amount_precision=amount_precision,
989
844
  price_precision=price_precision,
990
845
  time_precision=time_precision,
@@ -993,7 +848,7 @@ def pretty_print_backtest(
993
848
 
994
849
  if show_stop_losses:
995
850
  pretty_print_stop_losses(
996
- backtest_report=backtest_report,
851
+ backtest=backtest,
997
852
  triggered_only=show_triggered_stop_losses_only,
998
853
  amount_precision=amount_precision,
999
854
  price_precision=price_precision,
@@ -1003,7 +858,7 @@ def pretty_print_backtest(
1003
858
 
1004
859
  if show_take_profits:
1005
860
  pretty_print_take_profits(
1006
- backtest_report=backtest_report,
861
+ backtest=backtest,
1007
862
  triggered_only=show_triggered_take_profits_only,
1008
863
  amount_precision=amount_precision,
1009
864
  price_precision=price_precision,