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,580 +0,0 @@
1
- from datetime import datetime
2
- from logging import getLogger
3
-
4
- from pandas import DataFrame
5
-
6
- from investing_algorithm_framework.domain.constants import DATETIME_FORMAT
7
- from investing_algorithm_framework.domain.metrics import \
8
- get_price_efficiency_ratio
9
- from investing_algorithm_framework.domain.models \
10
- .backtesting.backtest_date_range import BacktestDateRange
11
- from investing_algorithm_framework.domain.models.base_model import BaseModel
12
- from investing_algorithm_framework.domain.models.time_unit import TimeUnit
13
-
14
- logger = getLogger(__name__)
15
-
16
-
17
- class BacktestReport(BaseModel):
18
- """
19
- Class that represents a backtest report. The backtest report
20
- contains information about the backtest.
21
- """
22
-
23
- def __init__(
24
- self,
25
- backtest_date_range: BacktestDateRange,
26
- name=None,
27
- time_unit=None,
28
- interval=0,
29
- strategy_identifiers=None,
30
- initial_unallocated=0.0,
31
- number_of_runs=0,
32
- trading_time_frame=None,
33
- trading_time_frame_start_date=None,
34
- symbols=None,
35
- market=None,
36
- number_of_orders=0,
37
- number_of_positions=0,
38
- market_data_file=None,
39
- number_of_trades_closed=0,
40
- number_of_trades_open=0,
41
- percentage_positive_trades=0.0,
42
- percentage_negative_trades=0.0,
43
- total_cost=0.0,
44
- trading_symbol=None,
45
- total_net_gain_percentage=0.0,
46
- total_net_gain=0.0,
47
- growth_rate=0.0,
48
- growth=0.0,
49
- total_value=0.0,
50
- positions=None,
51
- average_trade_duration=0,
52
- average_trade_size=0.0,
53
- trades=None,
54
- orders=None,
55
- created_at: datetime = None,
56
- context=None,
57
- ):
58
- self._traces = {}
59
- self.metrics = {}
60
- self._name = name
61
- self._strategy_identifiers = strategy_identifiers
62
- self.backtest_date_range = backtest_date_range
63
- self._number_of_runs = number_of_runs
64
- self._trading_time_frame = trading_time_frame
65
- self._trading_time_frame_start_date = trading_time_frame_start_date
66
- self._market = market
67
- self._number_of_orders = number_of_orders
68
- self._number_of_positions = number_of_positions
69
- self._market_data_file = market_data_file
70
- self._percentage_positive_trades = percentage_positive_trades
71
- self._percentage_negative_trades = percentage_negative_trades
72
- self._number_of_trades_closed = number_of_trades_closed
73
- self._number_of_trades_open = number_of_trades_open
74
- self._total_cost = total_cost
75
- self._growth_rate = growth_rate
76
- self._growth = growth
77
- self._initial_unallocated = initial_unallocated
78
- self._trading_symbol = trading_symbol
79
- self._total_net_gain_percentage = total_net_gain_percentage
80
- self._total_net_gain = total_net_gain
81
- self._total_value = total_value
82
- self._positions = positions
83
- self._orders = orders
84
- self._average_trade_duration = average_trade_duration
85
- self._average_trade_size = average_trade_size
86
- self._trades = trades
87
- self._created_at: datetime = created_at
88
- self._interval = interval
89
- self._time_unit = time_unit
90
- self._context = context
91
-
92
- self._symbols = symbols
93
-
94
- if self._symbols is None:
95
- self._symbols = []
96
-
97
- self._number_of_days = \
98
- (self.backtest_date_range.end_date
99
- - self.backtest_date_range.start_date).days
100
-
101
- @property
102
- def name(self):
103
- return self._name
104
-
105
- @property
106
- def strategy_identifiers(self):
107
- return self._strategy_identifiers
108
-
109
- @property
110
- def created_at(self):
111
- return self._created_at
112
-
113
- @property
114
- def portfolio_id(self):
115
- return self._portfolio_id
116
-
117
- @portfolio_id.setter
118
- def portfolio_id(self, portfolio_id):
119
- self._portfolio_id = portfolio_id
120
-
121
- @property
122
- def symbols(self):
123
- return self._symbols
124
-
125
- @property
126
- def trading_time_frame(self):
127
- return self._trading_time_frame
128
-
129
- @property
130
- def trading_time_frame_start_date(self):
131
- return self._trading_time_frame_start_date
132
-
133
- @property
134
- def number_of_runs(self):
135
- return self._number_of_runs
136
-
137
- @property
138
- def market(self):
139
- return self._market
140
-
141
- @property
142
- def number_of_days(self):
143
- return self._number_of_days
144
-
145
- @symbols.setter
146
- def symbols(self, value):
147
- self._symbols = value
148
-
149
- @market.setter
150
- def market(self, value):
151
- self._market = value
152
-
153
- @number_of_runs.setter
154
- def number_of_runs(self, value):
155
- self._number_of_runs = value
156
-
157
- @trading_time_frame.setter
158
- def trading_time_frame(self, value):
159
- self._trading_time_frame = value
160
-
161
- @trading_time_frame_start_date.setter
162
- def trading_time_frame_start_date(self, value):
163
- self._trading_time_frame_start_date = value
164
-
165
- @property
166
- def number_of_orders(self):
167
- return self._number_of_orders
168
-
169
- @number_of_orders.setter
170
- def number_of_orders(self, value):
171
- self._number_of_orders = value
172
-
173
- @property
174
- def number_of_positions(self):
175
- return self._number_of_positions
176
-
177
- @number_of_positions.setter
178
- def number_of_positions(self, value):
179
- self._number_of_positions = value
180
-
181
- @property
182
- def backtest_data_index_date(self):
183
- return self._backtest_data_index_date
184
-
185
- @backtest_data_index_date.setter
186
- def backtest_data_index_date(self, value):
187
- self._backtest_data_index_date = value
188
-
189
- @property
190
- def market_data_file(self):
191
- return self._market_data_file
192
-
193
- @market_data_file.setter
194
- def market_data_file(self, value):
195
- self._market_data_file = value
196
-
197
- @property
198
- def percentage_positive_trades(self):
199
- return float(self._percentage_positive_trades)
200
-
201
- @percentage_positive_trades.setter
202
- def percentage_positive_trades(self, value):
203
- self._percentage_positive_trades = value
204
-
205
- @property
206
- def percentage_negative_trades(self):
207
- return float(self._percentage_negative_trades)
208
-
209
- @percentage_negative_trades.setter
210
- def percentage_negative_trades(self, value):
211
- self._percentage_negative_trades = value
212
-
213
- @property
214
- def number_of_trades_closed(self):
215
- return self._number_of_trades_closed
216
-
217
- @number_of_trades_closed.setter
218
- def number_of_trades_closed(self, value):
219
- self._number_of_trades_closed = value
220
-
221
- @property
222
- def number_of_trades_open(self):
223
- return self._number_of_trades_open
224
-
225
- @number_of_trades_open.setter
226
- def number_of_trades_open(self, value):
227
- self._number_of_trades_open = value
228
-
229
- @property
230
- def total_cost(self):
231
- return self._total_cost
232
-
233
- @total_cost.setter
234
- def total_cost(self, value):
235
- self._total_cost = value
236
-
237
- @property
238
- def growth_rate(self):
239
- return self._growth_rate
240
-
241
- @growth_rate.setter
242
- def growth_rate(self, value):
243
- self._growth_rate = value
244
-
245
- @property
246
- def growth(self):
247
- return self._growth
248
-
249
- @growth.setter
250
- def growth(self, value):
251
- self._growth = value
252
-
253
- @property
254
- def initial_unallocated(self):
255
- return self._initial_unallocated
256
-
257
- @initial_unallocated.setter
258
- def initial_unallocated(self, value):
259
- self._initial_unallocated = value
260
-
261
- @property
262
- def trading_symbol(self):
263
- return self._trading_symbol
264
-
265
- @trading_symbol.setter
266
- def trading_symbol(self, value):
267
- self._trading_symbol = value
268
-
269
- @property
270
- def total_net_gain_percentage(self):
271
- return self._total_net_gain_percentage
272
-
273
- @total_net_gain_percentage.setter
274
- def total_net_gain_percentage(self, value):
275
- self._total_net_gain_percentage = value
276
-
277
- @property
278
- def total_net_gain(self):
279
- return self._total_net_gain
280
-
281
- @total_net_gain.setter
282
- def total_net_gain(self, value):
283
- self._total_net_gain = value
284
-
285
- @property
286
- def total_value(self):
287
- return self._total_value
288
-
289
- @total_value.setter
290
- def total_value(self, value):
291
- self._total_value = value
292
-
293
- @property
294
- def positions(self):
295
- return self._positions
296
-
297
- @positions.setter
298
- def positions(self, value):
299
- self._positions = value
300
-
301
- @property
302
- def orders(self):
303
- return self._orders
304
-
305
- @orders.setter
306
- def orders(self, value):
307
- self._orders = value
308
-
309
- @property
310
- def average_trade_duration(self):
311
- return self._average_trade_duration
312
-
313
- @average_trade_duration.setter
314
- def average_trade_duration(self, value):
315
- self._average_trade_duration = value
316
-
317
- @property
318
- def average_trade_size(self):
319
- return self._average_trade_size
320
-
321
- @average_trade_size.setter
322
- def average_trade_size(self, value):
323
- self._average_trade_size = value
324
-
325
- @property
326
- def trades(self):
327
- return self._trades
328
-
329
- @trades.setter
330
- def trades(self, value):
331
- self._trades = value
332
-
333
- @property
334
- def interval(self):
335
- return self._interval
336
-
337
- @interval.setter
338
- def interval(self, value):
339
- self._interval = value
340
-
341
- @property
342
- def context(self):
343
- return self._context
344
-
345
- @context.setter
346
- def context(self, value):
347
- self._context = value
348
-
349
- @property
350
- def time_unit(self):
351
- return self._time_unit
352
-
353
- @time_unit.setter
354
- def time_unit(self, value):
355
- self._time_unit = value
356
-
357
- def get_runs_per_day(self):
358
-
359
- if self.time_unit is None:
360
- return 0
361
- elif TimeUnit.SECOND.equals(self.time_unit):
362
- return 86400 / self.interval
363
- elif TimeUnit.MINUTE.equals(self.time_unit):
364
- return 1440 / self.interval
365
- else:
366
- return 24 / self.interval
367
-
368
- @property
369
- def backtest_start_date(self):
370
- return self.backtest_date_range.start_date
371
-
372
- @property
373
- def backtest_end_date(self):
374
- return self.backtest_date_range.end_date
375
-
376
- def __repr__(self):
377
- return self.repr(
378
- name=self.name,
379
- backtest_date_range=self.backtest_date_range,
380
- profit=self.get_profit(),
381
- profit_percentage=self.get_profit_percentage(),
382
- growth=self.get_growth(),
383
- growth_percentage=self.get_growth_percentage(),
384
- )
385
-
386
- def to_dict(self):
387
- """
388
- Convert the backtest report to a dictionary. So it can be
389
- saved to a file.
390
- """
391
-
392
- # Convert context to a dictionary
393
- if self.context is not None:
394
-
395
- for key, value in self.context.items():
396
- if isinstance(value, datetime):
397
- self.context[key] = value.strftime(DATETIME_FORMAT)
398
-
399
- if isinstance(value, DataFrame):
400
- self.context[key] = value.to_json()
401
-
402
- return {
403
- "name": self.name,
404
- "context": self.context if self.context is not None else {},
405
- "strategy_identifiers": self.strategy_identifiers,
406
- "backtest_date_range_identifier": self.backtest_date_range.name,
407
- "backtest_start_date": self.backtest_date_range.start_date
408
- .strftime(DATETIME_FORMAT),
409
- "backtest_end_date": self.backtest_date_range.end_date
410
- .strftime(DATETIME_FORMAT),
411
- "number_of_runs": self.number_of_runs,
412
- "symbols": self.symbols,
413
- "market": self.market,
414
- "number_of_days": self.number_of_days,
415
- "number_of_orders": self.number_of_orders,
416
- "number_of_positions": self.number_of_positions,
417
- "market_data_file": self.market_data_file,
418
- "percentage_positive_trades": self.percentage_positive_trades,
419
- "percentage_negative_trades": self.percentage_negative_trades,
420
- "number_of_trades_closed": self.number_of_trades_closed,
421
- "number_of_trades_open": self.number_of_trades_open,
422
- "total_cost": self.total_cost,
423
- "growth_rate": self.growth_rate,
424
- "growth": self.growth,
425
- "initial_unallocated": self.initial_unallocated,
426
- "trading_symbol": self.trading_symbol,
427
- "total_net_gain_percentage": self.total_net_gain_percentage,
428
- "total_net_gain": self.total_net_gain,
429
- "total_value": self.total_value,
430
- "average_trade_duration": self.average_trade_duration,
431
- "average_trade_size": self.average_trade_size,
432
- "positions": [position.to_dict() for position in self.positions],
433
- "trades": [trade.to_dict() for trade in self.trades],
434
- "orders": [
435
- order.to_dict(datetime_format=DATETIME_FORMAT)
436
- for order in self.orders
437
- ],
438
- "created_at": self.created_at.strftime(DATETIME_FORMAT),
439
- }
440
-
441
- @staticmethod
442
- def from_dict(data):
443
- """
444
- Factory method to create a backtest report from a dictionary.
445
- """
446
-
447
- backtest_date_range = BacktestDateRange(
448
- start_date=datetime.strptime(
449
- data["backtest_start_date"], DATETIME_FORMAT),
450
- end_date=datetime.strptime(
451
- data["backtest_end_date"], DATETIME_FORMAT)
452
- )
453
-
454
- return BacktestReport(
455
- name=data["name"],
456
- strategy_identifiers=data["strategy_identifiers"],
457
- number_of_runs=data["number_of_runs"],
458
- backtest_date_range=backtest_date_range,
459
- symbols=data["symbols"],
460
- market=data["market"],
461
- number_of_orders=data["number_of_orders"],
462
- number_of_positions=data["number_of_positions"],
463
- market_data_file=data["market_data_file"],
464
- percentage_positive_trades=data["percentage_positive_trades"],
465
- percentage_negative_trades=data["percentage_negative_trades"],
466
- number_of_trades_closed=data["number_of_trades_closed"],
467
- number_of_trades_open=data["number_of_trades_open"],
468
- total_cost=float(data["total_cost"]),
469
- growth_rate=float(data["growth_rate"]),
470
- growth=float(data["growth"]),
471
- initial_unallocated=float(data["initial_unallocated"]),
472
- trading_symbol=data["trading_symbol"],
473
- total_net_gain_percentage=float(data["total_net_gain_percentage"]),
474
- total_net_gain=float(data["total_net_gain"]),
475
- total_value=float(data["total_value"]),
476
- average_trade_duration=data["average_trade_duration"],
477
- average_trade_size=float(data["average_trade_size"]),
478
- )
479
-
480
- def get_trades(self, symbol=None):
481
- """
482
- Function to get trades. If a symbol is provided, it will
483
- return the trades for that symbol. If no symbol is provided,
484
- it will return all the trades.
485
- """
486
- if symbol is None:
487
- return self.trades
488
-
489
- return [trade for trade in self.trades if trade.symbol == symbol]
490
-
491
- def get_profit(self) -> float:
492
- return self._total_net_gain
493
-
494
- def get_profit_percentage(self) -> float:
495
- return self._total_net_gain_percentage
496
-
497
- def get_growth(self) -> float:
498
- return self._growth
499
-
500
- def get_growth_percentage(self) -> float:
501
- return self._growth_rate
502
-
503
- def get_trading_symbol(self) -> str:
504
- return self.trading_symbol
505
-
506
- def add_symbol(self, symbol):
507
-
508
- if symbol not in self.symbols:
509
- self.symbols.append(symbol)
510
-
511
- def calculate_metrics(self):
512
- """
513
- Parent method to calculate all metrics.
514
-
515
- returns:
516
- None
517
- """
518
- if self.traces is not None:
519
- self.metrics['efficiency_ratio'] = {}
520
-
521
- for strategy_id in self.traces:
522
- entries = self.traces[strategy_id]
523
-
524
- if entries is None:
525
- continue
526
-
527
- for symbol in entries:
528
-
529
- self.metrics['efficiency_ratio'][symbol] = \
530
- get_price_efficiency_ratio(
531
- self.traces[strategy_id][symbol]
532
- )
533
-
534
- @property
535
- def traces(self):
536
- """
537
- Get the traces of the backtest report.
538
- """
539
- return self._traces
540
-
541
- @traces.setter
542
- def traces(self, value):
543
- """
544
- Set the traces of the backtest report.
545
-
546
- Args:
547
- value (dict): The traces of the backtest report.
548
-
549
- returns:
550
- None
551
- """
552
- self._traces = value
553
-
554
- def get_trace(self, symbol, strategy_id=None):
555
- """
556
- Get the trace for a given symbol. If a strategy_id is provided,
557
- it will return the trace for that strategy.
558
-
559
- Args:
560
- symbol (str): The symbol
561
- strategy_id (str): The
562
- """
563
-
564
- if strategy_id is None:
565
-
566
- for strategy_id, trace in self.traces.items():
567
-
568
- if symbol in trace:
569
- return trace[symbol]
570
-
571
- else:
572
- if strategy_id in self.traces:
573
- return self.traces[strategy_id][symbol]
574
-
575
- else:
576
- raise ValueError(
577
- f"Trace {symbol} for strategy {strategy_id} not found"
578
- )
579
-
580
- return None