investing-algorithm-framework 1.5__py3-none-any.whl → 7.25.6__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.
Files changed (276) hide show
  1. investing_algorithm_framework/__init__.py +192 -16
  2. investing_algorithm_framework/analysis/__init__.py +16 -0
  3. investing_algorithm_framework/analysis/backtest_data_ranges.py +202 -0
  4. investing_algorithm_framework/analysis/data.py +170 -0
  5. investing_algorithm_framework/analysis/markdown.py +91 -0
  6. investing_algorithm_framework/analysis/ranking.py +298 -0
  7. investing_algorithm_framework/app/__init__.py +29 -4
  8. investing_algorithm_framework/app/algorithm/__init__.py +7 -0
  9. investing_algorithm_framework/app/algorithm/algorithm.py +193 -0
  10. investing_algorithm_framework/app/algorithm/algorithm_factory.py +118 -0
  11. investing_algorithm_framework/app/app.py +2220 -379
  12. investing_algorithm_framework/app/app_hook.py +28 -0
  13. investing_algorithm_framework/app/context.py +1724 -0
  14. investing_algorithm_framework/app/eventloop.py +620 -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/time_metrics_table.py +80 -0
  31. investing_algorithm_framework/app/reporting/tables/trade_metrics_table.py +147 -0
  32. investing_algorithm_framework/app/reporting/tables/trades_table.py +75 -0
  33. investing_algorithm_framework/app/reporting/tables/utils.py +29 -0
  34. investing_algorithm_framework/app/reporting/templates/report_template.html.j2 +154 -0
  35. investing_algorithm_framework/app/stateless/action_handlers/__init__.py +6 -3
  36. investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +1 -1
  37. investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +2 -1
  38. investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +14 -7
  39. investing_algorithm_framework/app/strategy.py +867 -60
  40. investing_algorithm_framework/app/task.py +5 -3
  41. investing_algorithm_framework/app/web/__init__.py +2 -1
  42. investing_algorithm_framework/app/web/controllers/__init__.py +2 -2
  43. investing_algorithm_framework/app/web/controllers/orders.py +3 -2
  44. investing_algorithm_framework/app/web/controllers/positions.py +2 -2
  45. investing_algorithm_framework/app/web/create_app.py +4 -2
  46. investing_algorithm_framework/app/web/schemas/position.py +1 -0
  47. investing_algorithm_framework/cli/__init__.py +0 -0
  48. investing_algorithm_framework/cli/cli.py +231 -0
  49. investing_algorithm_framework/cli/deploy_to_aws_lambda.py +501 -0
  50. investing_algorithm_framework/cli/deploy_to_azure_function.py +718 -0
  51. investing_algorithm_framework/cli/initialize_app.py +603 -0
  52. investing_algorithm_framework/cli/templates/.gitignore.template +178 -0
  53. investing_algorithm_framework/cli/templates/app.py.template +18 -0
  54. investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +48 -0
  55. investing_algorithm_framework/cli/templates/app_azure_function.py.template +14 -0
  56. investing_algorithm_framework/cli/templates/app_web.py.template +18 -0
  57. investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +22 -0
  58. investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +92 -0
  59. investing_algorithm_framework/cli/templates/aws_lambda_readme.md.template +110 -0
  60. investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +2 -0
  61. investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +65 -0
  62. investing_algorithm_framework/cli/templates/azure_function_host.json.template +15 -0
  63. investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +8 -0
  64. investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +3 -0
  65. investing_algorithm_framework/cli/templates/data_providers.py.template +17 -0
  66. investing_algorithm_framework/cli/templates/env.example.template +2 -0
  67. investing_algorithm_framework/cli/templates/env_azure_function.example.template +4 -0
  68. investing_algorithm_framework/cli/templates/market_data_providers.py.template +9 -0
  69. investing_algorithm_framework/cli/templates/readme.md.template +135 -0
  70. investing_algorithm_framework/cli/templates/requirements.txt.template +2 -0
  71. investing_algorithm_framework/cli/templates/run_backtest.py.template +20 -0
  72. investing_algorithm_framework/cli/templates/strategy.py.template +124 -0
  73. investing_algorithm_framework/cli/validate_backtest_checkpoints.py +197 -0
  74. investing_algorithm_framework/create_app.py +40 -7
  75. investing_algorithm_framework/dependency_container.py +100 -47
  76. investing_algorithm_framework/domain/__init__.py +97 -30
  77. investing_algorithm_framework/domain/algorithm_id.py +69 -0
  78. investing_algorithm_framework/domain/backtesting/__init__.py +25 -0
  79. investing_algorithm_framework/domain/backtesting/backtest.py +548 -0
  80. investing_algorithm_framework/domain/backtesting/backtest_date_range.py +113 -0
  81. investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +241 -0
  82. investing_algorithm_framework/domain/backtesting/backtest_metrics.py +470 -0
  83. investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +275 -0
  84. investing_algorithm_framework/domain/backtesting/backtest_run.py +663 -0
  85. investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +162 -0
  86. investing_algorithm_framework/domain/backtesting/backtest_utils.py +198 -0
  87. investing_algorithm_framework/domain/backtesting/combine_backtests.py +392 -0
  88. investing_algorithm_framework/domain/config.py +59 -136
  89. investing_algorithm_framework/domain/constants.py +18 -37
  90. investing_algorithm_framework/domain/data_provider.py +334 -0
  91. investing_algorithm_framework/domain/data_structures.py +42 -0
  92. investing_algorithm_framework/domain/exceptions.py +51 -1
  93. investing_algorithm_framework/domain/models/__init__.py +26 -19
  94. investing_algorithm_framework/domain/models/app_mode.py +34 -0
  95. investing_algorithm_framework/domain/models/data/__init__.py +7 -0
  96. investing_algorithm_framework/domain/models/data/data_source.py +222 -0
  97. investing_algorithm_framework/domain/models/data/data_type.py +46 -0
  98. investing_algorithm_framework/domain/models/event.py +35 -0
  99. investing_algorithm_framework/domain/models/market/__init__.py +5 -0
  100. investing_algorithm_framework/domain/models/market/market_credential.py +88 -0
  101. investing_algorithm_framework/domain/models/order/__init__.py +3 -4
  102. investing_algorithm_framework/domain/models/order/order.py +198 -65
  103. investing_algorithm_framework/domain/models/order/order_status.py +2 -2
  104. investing_algorithm_framework/domain/models/order/order_type.py +1 -3
  105. investing_algorithm_framework/domain/models/portfolio/__init__.py +6 -2
  106. investing_algorithm_framework/domain/models/portfolio/portfolio.py +98 -3
  107. investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +37 -43
  108. investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +108 -11
  109. investing_algorithm_framework/domain/models/position/__init__.py +2 -1
  110. investing_algorithm_framework/domain/models/position/position.py +20 -0
  111. investing_algorithm_framework/domain/models/position/position_size.py +41 -0
  112. investing_algorithm_framework/domain/models/position/position_snapshot.py +0 -2
  113. investing_algorithm_framework/domain/models/risk_rules/__init__.py +7 -0
  114. investing_algorithm_framework/domain/models/risk_rules/stop_loss_rule.py +51 -0
  115. investing_algorithm_framework/domain/models/risk_rules/take_profit_rule.py +55 -0
  116. investing_algorithm_framework/domain/models/snapshot_interval.py +45 -0
  117. investing_algorithm_framework/domain/models/strategy_profile.py +19 -141
  118. investing_algorithm_framework/domain/models/time_frame.py +94 -98
  119. investing_algorithm_framework/domain/models/time_interval.py +33 -0
  120. investing_algorithm_framework/domain/models/time_unit.py +66 -2
  121. investing_algorithm_framework/domain/models/tracing/__init__.py +0 -0
  122. investing_algorithm_framework/domain/models/tracing/trace.py +23 -0
  123. investing_algorithm_framework/domain/models/trade/__init__.py +11 -0
  124. investing_algorithm_framework/domain/models/trade/trade.py +389 -0
  125. investing_algorithm_framework/domain/models/trade/trade_status.py +40 -0
  126. investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +332 -0
  127. investing_algorithm_framework/domain/models/trade/trade_take_profit.py +365 -0
  128. investing_algorithm_framework/domain/order_executor.py +112 -0
  129. investing_algorithm_framework/domain/portfolio_provider.py +118 -0
  130. investing_algorithm_framework/domain/services/__init__.py +11 -0
  131. investing_algorithm_framework/domain/services/market_credential_service.py +37 -0
  132. investing_algorithm_framework/domain/services/portfolios/__init__.py +5 -0
  133. investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +9 -0
  134. investing_algorithm_framework/domain/services/rounding_service.py +27 -0
  135. investing_algorithm_framework/domain/services/state_handler.py +38 -0
  136. investing_algorithm_framework/domain/strategy.py +1 -29
  137. investing_algorithm_framework/domain/utils/__init__.py +15 -5
  138. investing_algorithm_framework/domain/utils/csv.py +22 -0
  139. investing_algorithm_framework/domain/utils/custom_tqdm.py +22 -0
  140. investing_algorithm_framework/domain/utils/dates.py +57 -0
  141. investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +19 -0
  142. investing_algorithm_framework/domain/utils/polars.py +53 -0
  143. investing_algorithm_framework/domain/utils/random.py +29 -0
  144. investing_algorithm_framework/download_data.py +244 -0
  145. investing_algorithm_framework/infrastructure/__init__.py +37 -11
  146. investing_algorithm_framework/infrastructure/data_providers/__init__.py +36 -0
  147. investing_algorithm_framework/infrastructure/data_providers/ccxt.py +1152 -0
  148. investing_algorithm_framework/infrastructure/data_providers/csv.py +568 -0
  149. investing_algorithm_framework/infrastructure/data_providers/pandas.py +599 -0
  150. investing_algorithm_framework/infrastructure/database/__init__.py +6 -2
  151. investing_algorithm_framework/infrastructure/database/sql_alchemy.py +86 -12
  152. investing_algorithm_framework/infrastructure/models/__init__.py +7 -3
  153. investing_algorithm_framework/infrastructure/models/order/__init__.py +2 -2
  154. investing_algorithm_framework/infrastructure/models/order/order.py +53 -53
  155. investing_algorithm_framework/infrastructure/models/order/order_metadata.py +44 -0
  156. investing_algorithm_framework/infrastructure/models/order_trade_association.py +10 -0
  157. investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +1 -1
  158. investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +8 -2
  159. investing_algorithm_framework/infrastructure/models/portfolio/{portfolio.py → sql_portfolio.py} +17 -6
  160. investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +3 -1
  161. investing_algorithm_framework/infrastructure/models/trades/__init__.py +9 -0
  162. investing_algorithm_framework/infrastructure/models/trades/trade.py +130 -0
  163. investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +59 -0
  164. investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +55 -0
  165. investing_algorithm_framework/infrastructure/order_executors/__init__.py +21 -0
  166. investing_algorithm_framework/infrastructure/order_executors/backtest_oder_executor.py +28 -0
  167. investing_algorithm_framework/infrastructure/order_executors/ccxt_order_executor.py +200 -0
  168. investing_algorithm_framework/infrastructure/portfolio_providers/__init__.py +19 -0
  169. investing_algorithm_framework/infrastructure/portfolio_providers/ccxt_portfolio_provider.py +199 -0
  170. investing_algorithm_framework/infrastructure/repositories/__init__.py +10 -4
  171. investing_algorithm_framework/infrastructure/repositories/order_metadata_repository.py +17 -0
  172. investing_algorithm_framework/infrastructure/repositories/order_repository.py +16 -5
  173. investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +2 -2
  174. investing_algorithm_framework/infrastructure/repositories/position_repository.py +11 -0
  175. investing_algorithm_framework/infrastructure/repositories/repository.py +84 -30
  176. investing_algorithm_framework/infrastructure/repositories/trade_repository.py +71 -0
  177. investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +29 -0
  178. investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +29 -0
  179. investing_algorithm_framework/infrastructure/services/__init__.py +9 -4
  180. investing_algorithm_framework/infrastructure/services/aws/__init__.py +6 -0
  181. investing_algorithm_framework/infrastructure/services/aws/state_handler.py +193 -0
  182. investing_algorithm_framework/infrastructure/services/azure/__init__.py +5 -0
  183. investing_algorithm_framework/infrastructure/services/azure/state_handler.py +158 -0
  184. investing_algorithm_framework/infrastructure/services/backtesting/__init__.py +9 -0
  185. investing_algorithm_framework/infrastructure/services/backtesting/backtest_service.py +2596 -0
  186. investing_algorithm_framework/infrastructure/services/backtesting/event_backtest_service.py +285 -0
  187. investing_algorithm_framework/infrastructure/services/backtesting/vector_backtest_service.py +468 -0
  188. investing_algorithm_framework/services/__init__.py +123 -15
  189. investing_algorithm_framework/services/configuration_service.py +77 -11
  190. investing_algorithm_framework/services/data_providers/__init__.py +5 -0
  191. investing_algorithm_framework/services/data_providers/data_provider_service.py +1058 -0
  192. investing_algorithm_framework/services/market_credential_service.py +40 -0
  193. investing_algorithm_framework/services/metrics/__init__.py +119 -0
  194. investing_algorithm_framework/services/metrics/alpha.py +0 -0
  195. investing_algorithm_framework/services/metrics/beta.py +0 -0
  196. investing_algorithm_framework/services/metrics/cagr.py +60 -0
  197. investing_algorithm_framework/services/metrics/calmar_ratio.py +40 -0
  198. investing_algorithm_framework/services/metrics/drawdown.py +218 -0
  199. investing_algorithm_framework/services/metrics/equity_curve.py +24 -0
  200. investing_algorithm_framework/services/metrics/exposure.py +210 -0
  201. investing_algorithm_framework/services/metrics/generate.py +358 -0
  202. investing_algorithm_framework/services/metrics/mean_daily_return.py +84 -0
  203. investing_algorithm_framework/services/metrics/price_efficiency.py +57 -0
  204. investing_algorithm_framework/services/metrics/profit_factor.py +165 -0
  205. investing_algorithm_framework/services/metrics/recovery.py +113 -0
  206. investing_algorithm_framework/services/metrics/returns.py +452 -0
  207. investing_algorithm_framework/services/metrics/risk_free_rate.py +28 -0
  208. investing_algorithm_framework/services/metrics/sharpe_ratio.py +137 -0
  209. investing_algorithm_framework/services/metrics/sortino_ratio.py +74 -0
  210. investing_algorithm_framework/services/metrics/standard_deviation.py +156 -0
  211. investing_algorithm_framework/services/metrics/trades.py +473 -0
  212. investing_algorithm_framework/services/metrics/treynor_ratio.py +0 -0
  213. investing_algorithm_framework/services/metrics/ulcer.py +0 -0
  214. investing_algorithm_framework/services/metrics/value_at_risk.py +0 -0
  215. investing_algorithm_framework/services/metrics/volatility.py +118 -0
  216. investing_algorithm_framework/services/metrics/win_rate.py +177 -0
  217. investing_algorithm_framework/services/order_service/__init__.py +9 -0
  218. investing_algorithm_framework/services/order_service/order_backtest_service.py +178 -0
  219. investing_algorithm_framework/services/order_service/order_executor_lookup.py +110 -0
  220. investing_algorithm_framework/services/order_service/order_service.py +826 -0
  221. investing_algorithm_framework/services/portfolios/__init__.py +16 -0
  222. investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +54 -0
  223. investing_algorithm_framework/services/{portfolio_configuration_service.py → portfolios/portfolio_configuration_service.py} +27 -12
  224. investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +106 -0
  225. investing_algorithm_framework/services/portfolios/portfolio_service.py +188 -0
  226. investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +136 -0
  227. investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +182 -0
  228. investing_algorithm_framework/services/positions/__init__.py +7 -0
  229. investing_algorithm_framework/services/positions/position_service.py +210 -0
  230. investing_algorithm_framework/services/repository_service.py +8 -2
  231. investing_algorithm_framework/services/trade_order_evaluator/__init__.py +9 -0
  232. investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +117 -0
  233. investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +51 -0
  234. investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +80 -0
  235. investing_algorithm_framework/services/trade_service/__init__.py +9 -0
  236. investing_algorithm_framework/services/trade_service/trade_service.py +1099 -0
  237. investing_algorithm_framework/services/trade_service/trade_stop_loss_service.py +39 -0
  238. investing_algorithm_framework/services/trade_service/trade_take_profit_service.py +41 -0
  239. investing_algorithm_framework-7.25.6.dist-info/METADATA +535 -0
  240. investing_algorithm_framework-7.25.6.dist-info/RECORD +268 -0
  241. {investing_algorithm_framework-1.5.dist-info → investing_algorithm_framework-7.25.6.dist-info}/WHEEL +1 -2
  242. investing_algorithm_framework-7.25.6.dist-info/entry_points.txt +3 -0
  243. investing_algorithm_framework/app/algorithm.py +0 -630
  244. investing_algorithm_framework/domain/models/backtest_profile.py +0 -414
  245. investing_algorithm_framework/domain/models/market_data/__init__.py +0 -11
  246. investing_algorithm_framework/domain/models/market_data/asset_price.py +0 -50
  247. investing_algorithm_framework/domain/models/market_data/ohlcv.py +0 -105
  248. investing_algorithm_framework/domain/models/market_data/order_book.py +0 -63
  249. investing_algorithm_framework/domain/models/market_data/ticker.py +0 -92
  250. investing_algorithm_framework/domain/models/order/order_fee.py +0 -45
  251. investing_algorithm_framework/domain/models/trade.py +0 -78
  252. investing_algorithm_framework/domain/models/trading_data_types.py +0 -47
  253. investing_algorithm_framework/domain/models/trading_time_frame.py +0 -223
  254. investing_algorithm_framework/domain/singleton.py +0 -9
  255. investing_algorithm_framework/domain/utils/backtesting.py +0 -82
  256. investing_algorithm_framework/infrastructure/models/order/order_fee.py +0 -21
  257. investing_algorithm_framework/infrastructure/repositories/order_fee_repository.py +0 -15
  258. investing_algorithm_framework/infrastructure/services/market_backtest_service.py +0 -360
  259. investing_algorithm_framework/infrastructure/services/market_service.py +0 -410
  260. investing_algorithm_framework/infrastructure/services/performance_service.py +0 -192
  261. investing_algorithm_framework/services/backtest_service.py +0 -268
  262. investing_algorithm_framework/services/market_data_service.py +0 -77
  263. investing_algorithm_framework/services/order_backtest_service.py +0 -122
  264. investing_algorithm_framework/services/order_service.py +0 -752
  265. investing_algorithm_framework/services/portfolio_service.py +0 -164
  266. investing_algorithm_framework/services/portfolio_snapshot_service.py +0 -68
  267. investing_algorithm_framework/services/position_cost_service.py +0 -5
  268. investing_algorithm_framework/services/position_service.py +0 -63
  269. investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -225
  270. investing_algorithm_framework-1.5.dist-info/AUTHORS.md +0 -8
  271. investing_algorithm_framework-1.5.dist-info/METADATA +0 -230
  272. investing_algorithm_framework-1.5.dist-info/RECORD +0 -119
  273. investing_algorithm_framework-1.5.dist-info/top_level.txt +0 -1
  274. /investing_algorithm_framework/{infrastructure/services/performance_backtest_service.py → app/reporting/tables/stop_loss_table.py} +0 -0
  275. /investing_algorithm_framework/services/{position_snapshot_service.py → positions/position_snapshot_service.py} +0 -0
  276. {investing_algorithm_framework-1.5.dist-info → investing_algorithm_framework-7.25.6.dist-info}/LICENSE +0 -0
@@ -1,131 +1,25 @@
1
- from .base_model import BaseModel
2
- from .time_unit import TimeUnit
3
-
4
-
5
- class StrategyProfile(BaseModel):
6
-
7
- def __init__(
8
- self,
9
- strategy_id=None,
10
- interval=None,
11
- time_unit=None,
12
- trading_time_frame=None,
13
- trading_time_frame_start_date=None,
14
- symbols=None,
15
- market=None,
16
- backtest_start_date_data=None,
17
- backtest_data_index_date=None,
18
- trading_data_type=None,
19
- trading_data_types=None,
20
- ):
21
- self._strategy_id = strategy_id
22
- self._interval = interval
23
- self._time_unit = time_unit
24
- self._number_of_runs = 0
25
- self._trading_time_frame = trading_time_frame
26
- self._trading_time_frame_start_date = trading_time_frame_start_date
27
- self._backtest_start_date_data = backtest_start_date_data
28
- self._backtest_data_index_date = backtest_data_index_date
29
- self._symbols = symbols
30
- self._market = market
31
- self._trading_data_type = trading_data_type
32
- self._trading_data_types = trading_data_types
33
-
34
- @property
35
- def strategy_id(self):
36
- return self._strategy_id
37
-
38
- @strategy_id.setter
39
- def strategy_id(self, strategy_id):
40
- self._strategy_id = strategy_id
41
-
42
- @property
43
- def interval(self):
44
- return self._interval
45
-
46
- @interval.setter
47
- def interval(self, value):
48
- self._interval = value
49
-
50
- @property
51
- def time_unit(self):
52
- return self._time_unit
53
-
54
- @time_unit.setter
55
- def time_unit(self, value):
56
- self._time_unit = value
57
-
58
- @property
59
- def symbols(self):
60
- return self._symbols
61
-
62
- @property
63
- def trading_time_frame(self):
64
- return self._trading_time_frame
65
-
66
- @property
67
- def trading_time_frame_start_date(self):
68
- return self._trading_time_frame_start_date
69
-
70
- @property
71
- def number_of_runs(self):
72
- return self._number_of_runs
1
+ from dataclasses import dataclass
73
2
 
74
- @property
75
- def market(self):
76
- return self._market
77
-
78
- @symbols.setter
79
- def symbols(self, value):
80
- self._symbols = value
81
-
82
- @market.setter
83
- def market(self, value):
84
- self._market = value
85
-
86
- @number_of_runs.setter
87
- def number_of_runs(self, value):
88
- self._number_of_runs = value
89
-
90
- @trading_time_frame.setter
91
- def trading_time_frame(self, value):
92
- self._trading_time_frame = value
93
-
94
- @property
95
- def backtest_start_date_data(self):
96
- return self._backtest_start_date_data
97
-
98
- @backtest_start_date_data.setter
99
- def backtest_start_date_data(self, value):
100
- self._backtest_start_date_data = value
101
-
102
- @property
103
- def backtest_data_index_date(self):
104
- return self._backtest_data_index_date
105
-
106
- @backtest_data_index_date.setter
107
- def backtest_data_index_date(self, value):
108
- self._backtest_data_index_date = value
109
-
110
- @property
111
- def trading_data_type(self):
112
- return self._trading_data_type
113
-
114
- @trading_data_type.setter
115
- def trading_data_type(self, value):
116
- self._trading_data_type = value
117
-
118
- @property
119
- def trading_data_types(self):
120
-
121
- if self.trading_data_type is not None:
122
- return [self.trading_data_type]
3
+ from .time_unit import TimeUnit
123
4
 
124
- return self._trading_data_types
125
5
 
126
- @trading_data_types.setter
127
- def trading_data_types(self, value):
128
- self._trading_data_types = value
6
+ @dataclass(frozen=True)
7
+ class StrategyProfile:
8
+ """
9
+ StrategyProfile class that represents the profile of a trading strategy.
10
+ """
11
+ strategy_id: str = None
12
+ interval: int = None
13
+ time_unit: TimeUnit = None
14
+ trading_time_frame: str = None
15
+ trading_time_frame_start_date: str = None
16
+ backtest_start_date_data: str = None
17
+ backtest_data_index_date: str = None
18
+ symbols: list = None
19
+ market: str = None
20
+ trading_data_type: str = None
21
+ trading_data_types: list = None
22
+ data_sources: list = None
129
23
 
130
24
  def get_runs_per_day(self):
131
25
 
@@ -137,19 +31,3 @@ class StrategyProfile(BaseModel):
137
31
  return 1440 / self.interval
138
32
  else:
139
33
  return 24 / self.interval
140
-
141
- def __repr__(self):
142
- return self.repr(
143
- strategy_id=self._strategy_id,
144
- number_of_runs=self._number_of_runs,
145
- trading_time_frame=self._trading_time_frame,
146
- trading_time_frame_start_date=self._trading_time_frame_start_date,
147
- symbols=self._symbols,
148
- time_unit=self.time_unit,
149
- interval=self.interval,
150
- market=self._market,
151
- backtest_start_date_data=self._backtest_start_date_data,
152
- backtest_data_index_date=self._backtest_data_index_date,
153
- trading_data_type=self._trading_data_type,
154
- trading_data_types=self._trading_data_types,
155
- )
@@ -1,16 +1,24 @@
1
- from datetime import datetime, timedelta
2
1
  from enum import Enum
3
2
 
4
- from dateutil import relativedelta
5
-
6
3
 
7
4
  class TimeFrame(Enum):
8
5
  CURRENT = "CURRENT"
9
- ONE_HOUR = "ONE_HOUR"
10
- ONE_DAY = "ONE_DAY"
11
- ONE_WEEK = "ONE_WEEK"
12
- ONE_MONTH = "ONE_MONTH"
13
- ONE_YEAR = "ONE_YEAR"
6
+ ONE_MINUTE = "1m"
7
+ TWO_MINUTE = "2m"
8
+ THREE_MINUTE = "3m"
9
+ FOUR_MINUTE = "4m"
10
+ FIVE_MINUTE = "5m"
11
+ TEN_MINUTE = "10m"
12
+ FIFTEEN_MINUTE = "15m"
13
+ THIRTY_MINUTE = "30m"
14
+ ONE_HOUR = "1h"
15
+ TWO_HOUR = "2h"
16
+ FOUR_HOUR = "4h"
17
+ TWELVE_HOUR = "12h"
18
+ ONE_DAY = "1d"
19
+ ONE_WEEK = "1W"
20
+ ONE_MONTH = "1M"
21
+ ONE_YEAR = "1Y"
14
22
 
15
23
  @staticmethod
16
24
  def from_string(value: str):
@@ -19,7 +27,25 @@ class TimeFrame(Enum):
19
27
 
20
28
  for entry in TimeFrame:
21
29
 
22
- if value.upper() == entry.value:
30
+ # For hour timeframes compare with and without H
31
+ if "H" in entry.value:
32
+
33
+ if value == entry.value:
34
+ return entry
35
+
36
+ if value == entry.value.replace("H", "h"):
37
+ return entry
38
+
39
+ # For hour timeframes compare with and without H
40
+ if "d" in entry.value:
41
+
42
+ if value == entry.value:
43
+ return entry
44
+
45
+ if value == entry.value.replace("d", "D"):
46
+ return entry
47
+
48
+ if value == entry.value:
23
49
  return entry
24
50
 
25
51
  raise ValueError(
@@ -50,108 +76,78 @@ class TimeFrame(Enum):
50
76
  else:
51
77
  return TimeFrame.from_string(other) == self
52
78
 
53
- def create_time_frame(self, end_datetime=None):
54
-
55
- if end_datetime is None:
56
- end_datetime = datetime.utcnow()
57
-
58
- if TimeFrame.ONE_HOUR.equals(self):
59
- start_datetime = end_datetime - \
60
- relativedelta.relativedelta(hours=1)
61
- elif TimeFrame.ONE_DAY.equals(self):
62
- start_datetime = end_datetime - \
63
- relativedelta.relativedelta(hours=24)
64
- elif TimeFrame.ONE_WEEK.equals(self):
65
- start_datetime = end_datetime - \
66
- relativedelta.relativedelta(days=7)
67
- elif TimeFrame.ONE_MONTH.equals(self):
68
- start_datetime = \
69
- end_datetime - relativedelta.relativedelta(days=28)
70
- elif TimeFrame.ONE_YEAR.equals(self):
71
- start_datetime = \
72
- end_datetime - relativedelta.relativedelta(days=365)
73
- else:
74
- raise NotImplementedError(
75
- f"Timeframe {self.value} not implemented"
76
- )
79
+ @property
80
+ def amount_of_minutes(self):
77
81
 
78
- return start_datetime, end_datetime
79
-
80
- def duration(self):
81
- if TimeFrame.ONE_HOUR.equals(self):
82
- return relativedelta.relativedelta(hours=1)
83
- elif TimeFrame.ONE_DAY.equals(self):
84
- return relativedelta.relativedelta(hours=24)
85
- elif TimeFrame.ONE_WEEK.equals(self):
86
- return relativedelta.relativedelta(days=7)
87
- elif TimeFrame.ONE_MONTH.equals(self):
88
- return relativedelta.relativedelta(days=28)
89
- elif TimeFrame.ONE_YEAR.equals(self):
90
- return relativedelta.relativedelta(days=365)
91
- else:
92
- raise NotImplementedError(
93
- f"Timeframe {self.value} not implemented"
94
- )
82
+ if self.equals(TimeFrame.ONE_MINUTE):
83
+ return 1
95
84
 
96
- @property
97
- def time_interval(self):
98
- from investing_algorithm_framework.core.models import TimeInterval
99
-
100
- if TimeFrame.CURRENT.equals(self):
101
- return TimeInterval.CURRENT
102
- elif TimeFrame.ONE_HOUR.equals(self):
103
- return TimeInterval.MINUTES_ONE
104
- elif TimeFrame.ONE_DAY.equals(self):
105
- return TimeInterval.MINUTES_FIFTEEN
106
- elif TimeFrame.ONE_WEEK.equals(self):
107
- return TimeInterval.HOURS_ONE
108
- elif TimeFrame.ONE_MONTH.equals(self):
109
- return TimeInterval.HOURS_FOUR
110
- elif TimeFrame.ONE_YEAR.equals(self):
111
- return TimeInterval.DAYS_ONE
112
- else:
113
- raise NotImplementedError(
114
- f"Timeframe {self.value} not implemented"
115
- )
85
+ if self.equals(TimeFrame.TWO_MINUTE):
86
+ return 2
116
87
 
117
- @property
118
- def intervals(self):
119
- intervals = []
120
- start_datetime, end_datetime = self.create_time_frame()
121
- delta = end_datetime - start_datetime
88
+ if self.equals(TimeFrame.THREE_MINUTE):
89
+ return 3
122
90
 
123
- intervals.append(end_datetime)
91
+ if self.equals(TimeFrame.FOUR_MINUTE):
92
+ return 4
124
93
 
125
- if TimeFrame.ONE_HOUR.equals(self):
94
+ if self.equals(TimeFrame.FIVE_MINUTE):
95
+ return 5
126
96
 
127
- for i in range(1, int(delta.total_seconds() / 60)):
128
- intervals.append(end_datetime - timedelta(minutes=i))
97
+ if self.equals(TimeFrame.TEN_MINUTE):
98
+ return 10
129
99
 
130
- elif TimeFrame.ONE_DAY.equals(self):
100
+ if self.equals(TimeFrame.FIFTEEN_MINUTE):
101
+ return 15
131
102
 
132
- for i in range(1, int((delta.total_seconds() / 60) / 15)):
133
- intervals.append(end_datetime - timedelta(minutes=i * 15))
103
+ if self.equals(TimeFrame.THIRTY_MINUTE):
104
+ return 30
134
105
 
135
- elif TimeFrame.ONE_WEEK.equals(self):
106
+ if self.equals(TimeFrame.ONE_HOUR):
107
+ return 60
136
108
 
137
- for i in range(1, int((delta.total_seconds() / 60) / 60)):
138
- intervals.append(end_datetime - timedelta(hours=i))
109
+ if self.equals(TimeFrame.TWO_HOUR):
110
+ return 120
139
111
 
140
- elif TimeFrame.ONE_MONTH.equals(self):
112
+ if self.equals(TimeFrame.FOUR_HOUR):
113
+ return 240
141
114
 
142
- for i in range(1, int(((delta.total_seconds() / 60) / 60) / 4)):
143
- intervals.append(end_datetime - timedelta(hours=i * 4))
115
+ if self.equals(TimeFrame.TWELVE_HOUR):
116
+ return 720
144
117
 
145
- elif TimeFrame.ONE_YEAR.equals(self):
118
+ if self.equals(TimeFrame.ONE_DAY):
119
+ return 1440
146
120
 
147
- for i in range(1, int(delta.days)):
148
- intervals.append(
149
- end_datetime - relativedelta.relativedelta(days=i)
150
- )
121
+ if self.equals(TimeFrame.ONE_WEEK):
122
+ return 10080
151
123
 
152
- else:
153
- raise NotImplementedError(
154
- f"Timeframe {self.value} not implemented"
155
- )
124
+ if self.equals(TimeFrame.ONE_MONTH):
125
+ return 40320
126
+
127
+ if self.equals(TimeFrame.ONE_YEAR):
128
+ return 525600
129
+
130
+ raise ValueError(
131
+ f"Could not determine amount of minutes for {self.value}"
132
+ )
156
133
 
157
- return intervals
134
+ # Add comparison methods for ordering
135
+ def __lt__(self, other):
136
+ if isinstance(other, TimeFrame):
137
+ return self.amount_of_minutes < other.amount_of_minutes
138
+ raise TypeError(f"Cannot compare TimeFrame with {type(other)}")
139
+
140
+ def __le__(self, other):
141
+ if isinstance(other, TimeFrame):
142
+ return self.amount_of_minutes <= other.amount_of_minutes
143
+ raise TypeError(f"Cannot compare TimeFrame with {type(other)}")
144
+
145
+ def __gt__(self, other):
146
+ if isinstance(other, TimeFrame):
147
+ return self.amount_of_minutes > other.amount_of_minutes
148
+ raise TypeError(f"Cannot compare TimeFrame with {type(other)}")
149
+
150
+ def __ge__(self, other):
151
+ if isinstance(other, TimeFrame):
152
+ return self.amount_of_minutes >= other.amount_of_minutes
153
+ raise TypeError(f"Cannot compare TimeFrame with {type(other)}")
@@ -25,6 +25,39 @@ class TimeInterval(Enum):
25
25
  f"Could not convert {value} to TimeInterval"
26
26
  )
27
27
 
28
+ @staticmethod
29
+ def from_ohlcv_data_file(file_path: str):
30
+ """
31
+ Extracts the time interval from the file name of an OHLCV data file.
32
+ The file name should contain the time interval in the format
33
+ 'symbol_timeinterval.csv'.
34
+
35
+ Args:
36
+ file_path (str): The file path of the OHLCV data file.
37
+
38
+ Returns:
39
+ TimeInterval: The extracted time interval.
40
+ """
41
+ if not isinstance(file_path, str):
42
+ raise ValueError("File path must be a string.")
43
+
44
+ parts = file_path.split('_')
45
+ if len(parts) < 2:
46
+ raise ValueError(
47
+ "File name does not contain a valid time interval."
48
+ )
49
+
50
+ time_interval_str = parts[-1].split('.')[0].upper()
51
+ try:
52
+ return TimeInterval.from_string(time_interval_str)
53
+ except ValueError:
54
+ raise ValueError(
55
+ "Could not extract time interval from "
56
+ f"file name: {file_path}. "
57
+ "Expected format 'symbol_timeinterval.csv', "
58
+ f"got '{time_interval_str}'."
59
+ )
60
+
28
61
  def equals(self, other):
29
62
 
30
63
  if isinstance(other, Enum):
@@ -1,8 +1,16 @@
1
1
  from datetime import timedelta
2
2
  from enum import Enum
3
+ from investing_algorithm_framework.domain.exceptions import \
4
+ OperationalException
3
5
 
4
6
 
5
7
  class TimeUnit(Enum):
8
+ """
9
+ Enum class the represents a time unit such as
10
+ second, minute, hour or day. This can class
11
+ can be used to specify time specification within
12
+ the framework.
13
+ """
6
14
  SECOND = "SECOND"
7
15
  MINUTE = "MINUTE"
8
16
  HOUR = "HOUR"
@@ -18,10 +26,50 @@ class TimeUnit(Enum):
18
26
  if value.upper() == entry.value:
19
27
  return entry
20
28
 
21
- raise ValueError(
22
- f"Could not convert value {value} to time unit"
29
+ raise OperationalException(
30
+ f"Could not convert string {value} to time unit"
31
+ )
32
+
33
+ raise OperationalException(
34
+ f"Could not convert value {value} to time unit," +
35
+ " please make sure that the value is either of type string or" +
36
+ f"TimeUnit. Its current type is {type(value)}"
23
37
  )
24
38
 
39
+ @staticmethod
40
+ def from_ohlcv_data_file(file_path: str):
41
+ """
42
+ Extracts the time unit from the file name of an OHLCV data file.
43
+ The file name should contain the time unit in the
44
+ format 'symbol_timeunit.csv'.
45
+
46
+ Args:
47
+ file_path (str): The file path of the OHLCV data file.
48
+
49
+ Returns:
50
+ TimeUnit: The extracted time unit.
51
+ """
52
+ if not isinstance(file_path, str):
53
+ raise OperationalException(
54
+ "File path must be a string."
55
+ )
56
+
57
+ parts = file_path.split('_')
58
+ if len(parts) < 2:
59
+ raise OperationalException(
60
+ "File name does not contain a valid time unit."
61
+ )
62
+
63
+ time_unit_str = parts[-1].split('.')[0].upper()
64
+ try:
65
+ return TimeUnit.from_string(time_unit_str)
66
+ except ValueError:
67
+ raise OperationalException(
68
+ f"Could not extract time unit from file name: {file_path}. "
69
+ "Expected format 'symbol_timeunit.csv', "
70
+ f"got '{time_unit_str}'."
71
+ )
72
+
25
73
  def equals(self, other):
26
74
 
27
75
  if isinstance(other, Enum):
@@ -83,3 +131,19 @@ class TimeUnit(Enum):
83
131
 
84
132
  if TimeUnit.DAY.equals(self.value):
85
133
  return "days"
134
+
135
+ @property
136
+ def amount_of_minutes(self):
137
+ if TimeUnit.SECOND.equals(self):
138
+ return 1 / 60
139
+
140
+ if TimeUnit.MINUTE.equals(self):
141
+ return 1
142
+
143
+ if TimeUnit.HOUR.equals(self):
144
+ return 60
145
+
146
+ if TimeUnit.DAY.equals(self):
147
+ return 60 * 24
148
+
149
+ raise ValueError(f"Unsupported time unit: {self}")
@@ -0,0 +1,23 @@
1
+ class Trace:
2
+ """
3
+ Represents a trace of a trading strategy. A trace contains
4
+ data that has been generated by a trading strategy during its
5
+ execution.
6
+
7
+ The data can be used to analyze the performance of the trading after
8
+ it has been executed. Usually, the data contains metrics that
9
+ have been generated by the trading strategy during its execution,
10
+ and the signals that have been generated.
11
+ """
12
+
13
+ def __init__(
14
+ self,
15
+ strategy_id: str,
16
+ symbol: str,
17
+ data,
18
+ drop_duplicates=True
19
+ ):
20
+ self.strategy_id = strategy_id
21
+ self.symbol = symbol
22
+ self.data = data
23
+ self.drop_duplicates = drop_duplicates
@@ -0,0 +1,11 @@
1
+ from .trade import Trade
2
+ from .trade_status import TradeStatus
3
+ from .trade_stop_loss import TradeStopLoss
4
+ from .trade_take_profit import TradeTakeProfit
5
+
6
+ __all__ = [
7
+ "Trade",
8
+ "TradeStatus",
9
+ "TradeStopLoss",
10
+ "TradeTakeProfit",
11
+ ]