investing-algorithm-framework 1.3.1__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 (282) hide show
  1. investing_algorithm_framework/__init__.py +195 -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 +31 -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 +2233 -264
  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/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 +6 -3
  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 +2 -1
  39. investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +14 -7
  40. investing_algorithm_framework/app/stateless/exception_handler.py +1 -1
  41. investing_algorithm_framework/app/strategy.py +873 -52
  42. investing_algorithm_framework/app/task.py +5 -3
  43. investing_algorithm_framework/app/web/__init__.py +2 -1
  44. investing_algorithm_framework/app/web/controllers/__init__.py +2 -2
  45. investing_algorithm_framework/app/web/controllers/orders.py +4 -3
  46. investing_algorithm_framework/app/web/controllers/portfolio.py +1 -1
  47. investing_algorithm_framework/app/web/controllers/positions.py +3 -3
  48. investing_algorithm_framework/app/web/create_app.py +4 -2
  49. investing_algorithm_framework/app/web/error_handler.py +1 -1
  50. investing_algorithm_framework/app/web/schemas/order.py +2 -2
  51. investing_algorithm_framework/app/web/schemas/position.py +1 -0
  52. investing_algorithm_framework/cli/__init__.py +0 -0
  53. investing_algorithm_framework/cli/cli.py +231 -0
  54. investing_algorithm_framework/cli/deploy_to_aws_lambda.py +501 -0
  55. investing_algorithm_framework/cli/deploy_to_azure_function.py +718 -0
  56. investing_algorithm_framework/cli/initialize_app.py +603 -0
  57. investing_algorithm_framework/cli/templates/.gitignore.template +178 -0
  58. investing_algorithm_framework/cli/templates/app.py.template +18 -0
  59. investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +48 -0
  60. investing_algorithm_framework/cli/templates/app_azure_function.py.template +14 -0
  61. investing_algorithm_framework/cli/templates/app_web.py.template +18 -0
  62. investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +22 -0
  63. investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +92 -0
  64. investing_algorithm_framework/cli/templates/aws_lambda_readme.md.template +110 -0
  65. investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +2 -0
  66. investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +65 -0
  67. investing_algorithm_framework/cli/templates/azure_function_host.json.template +15 -0
  68. investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +8 -0
  69. investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +3 -0
  70. investing_algorithm_framework/cli/templates/data_providers.py.template +17 -0
  71. investing_algorithm_framework/cli/templates/env.example.template +2 -0
  72. investing_algorithm_framework/cli/templates/env_azure_function.example.template +4 -0
  73. investing_algorithm_framework/cli/templates/market_data_providers.py.template +9 -0
  74. investing_algorithm_framework/cli/templates/readme.md.template +135 -0
  75. investing_algorithm_framework/cli/templates/requirements.txt.template +2 -0
  76. investing_algorithm_framework/cli/templates/run_backtest.py.template +20 -0
  77. investing_algorithm_framework/cli/templates/strategy.py.template +124 -0
  78. investing_algorithm_framework/cli/validate_backtest_checkpoints.py +197 -0
  79. investing_algorithm_framework/create_app.py +43 -9
  80. investing_algorithm_framework/dependency_container.py +121 -33
  81. investing_algorithm_framework/domain/__init__.py +109 -22
  82. investing_algorithm_framework/domain/algorithm_id.py +69 -0
  83. investing_algorithm_framework/domain/backtesting/__init__.py +25 -0
  84. investing_algorithm_framework/domain/backtesting/backtest.py +548 -0
  85. investing_algorithm_framework/domain/backtesting/backtest_date_range.py +113 -0
  86. investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +241 -0
  87. investing_algorithm_framework/domain/backtesting/backtest_metrics.py +470 -0
  88. investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +275 -0
  89. investing_algorithm_framework/domain/backtesting/backtest_run.py +663 -0
  90. investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +162 -0
  91. investing_algorithm_framework/domain/backtesting/backtest_utils.py +198 -0
  92. investing_algorithm_framework/domain/backtesting/combine_backtests.py +392 -0
  93. investing_algorithm_framework/domain/config.py +60 -138
  94. investing_algorithm_framework/domain/constants.py +23 -34
  95. investing_algorithm_framework/domain/data_provider.py +334 -0
  96. investing_algorithm_framework/domain/data_structures.py +42 -0
  97. investing_algorithm_framework/domain/decimal_parsing.py +40 -0
  98. investing_algorithm_framework/domain/exceptions.py +51 -1
  99. investing_algorithm_framework/domain/models/__init__.py +29 -14
  100. investing_algorithm_framework/domain/models/app_mode.py +34 -0
  101. investing_algorithm_framework/domain/models/base_model.py +3 -1
  102. investing_algorithm_framework/domain/models/data/__init__.py +7 -0
  103. investing_algorithm_framework/domain/models/data/data_source.py +222 -0
  104. investing_algorithm_framework/domain/models/data/data_type.py +46 -0
  105. investing_algorithm_framework/domain/models/event.py +35 -0
  106. investing_algorithm_framework/domain/models/market/__init__.py +5 -0
  107. investing_algorithm_framework/domain/models/market/market_credential.py +88 -0
  108. investing_algorithm_framework/domain/models/order/__init__.py +3 -4
  109. investing_algorithm_framework/domain/models/order/order.py +243 -86
  110. investing_algorithm_framework/domain/models/order/order_status.py +2 -2
  111. investing_algorithm_framework/domain/models/order/order_type.py +1 -3
  112. investing_algorithm_framework/domain/models/portfolio/__init__.py +7 -2
  113. investing_algorithm_framework/domain/models/portfolio/portfolio.py +134 -1
  114. investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +37 -37
  115. investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +208 -0
  116. investing_algorithm_framework/domain/models/position/__init__.py +3 -2
  117. investing_algorithm_framework/domain/models/position/position.py +29 -0
  118. investing_algorithm_framework/domain/models/position/position_size.py +41 -0
  119. investing_algorithm_framework/domain/models/position/{position_cost.py → position_snapshot.py} +16 -8
  120. investing_algorithm_framework/domain/models/risk_rules/__init__.py +7 -0
  121. investing_algorithm_framework/domain/models/risk_rules/stop_loss_rule.py +51 -0
  122. investing_algorithm_framework/domain/models/risk_rules/take_profit_rule.py +55 -0
  123. investing_algorithm_framework/domain/models/snapshot_interval.py +45 -0
  124. investing_algorithm_framework/domain/models/strategy_profile.py +33 -0
  125. investing_algorithm_framework/domain/models/time_frame.py +94 -98
  126. investing_algorithm_framework/domain/models/time_interval.py +33 -0
  127. investing_algorithm_framework/domain/models/time_unit.py +111 -2
  128. investing_algorithm_framework/domain/models/tracing/__init__.py +0 -0
  129. investing_algorithm_framework/domain/models/tracing/trace.py +23 -0
  130. investing_algorithm_framework/domain/models/trade/__init__.py +11 -0
  131. investing_algorithm_framework/domain/models/trade/trade.py +389 -0
  132. investing_algorithm_framework/domain/models/trade/trade_status.py +40 -0
  133. investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +332 -0
  134. investing_algorithm_framework/domain/models/trade/trade_take_profit.py +365 -0
  135. investing_algorithm_framework/domain/order_executor.py +112 -0
  136. investing_algorithm_framework/domain/portfolio_provider.py +118 -0
  137. investing_algorithm_framework/domain/services/__init__.py +11 -0
  138. investing_algorithm_framework/domain/services/market_credential_service.py +37 -0
  139. investing_algorithm_framework/domain/services/portfolios/__init__.py +5 -0
  140. investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +9 -0
  141. investing_algorithm_framework/domain/services/rounding_service.py +27 -0
  142. investing_algorithm_framework/domain/services/state_handler.py +38 -0
  143. investing_algorithm_framework/domain/strategy.py +1 -29
  144. investing_algorithm_framework/domain/utils/__init__.py +16 -4
  145. investing_algorithm_framework/domain/utils/csv.py +22 -0
  146. investing_algorithm_framework/domain/utils/custom_tqdm.py +22 -0
  147. investing_algorithm_framework/domain/utils/dates.py +57 -0
  148. investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +19 -0
  149. investing_algorithm_framework/domain/utils/polars.py +53 -0
  150. investing_algorithm_framework/domain/utils/random.py +29 -0
  151. investing_algorithm_framework/download_data.py +244 -0
  152. investing_algorithm_framework/infrastructure/__init__.py +39 -11
  153. investing_algorithm_framework/infrastructure/data_providers/__init__.py +36 -0
  154. investing_algorithm_framework/infrastructure/data_providers/ccxt.py +1152 -0
  155. investing_algorithm_framework/infrastructure/data_providers/csv.py +568 -0
  156. investing_algorithm_framework/infrastructure/data_providers/pandas.py +599 -0
  157. investing_algorithm_framework/infrastructure/database/__init__.py +6 -2
  158. investing_algorithm_framework/infrastructure/database/sql_alchemy.py +87 -13
  159. investing_algorithm_framework/infrastructure/models/__init__.py +13 -4
  160. investing_algorithm_framework/infrastructure/models/decimal_parser.py +14 -0
  161. investing_algorithm_framework/infrastructure/models/order/__init__.py +2 -2
  162. investing_algorithm_framework/infrastructure/models/order/order.py +73 -73
  163. investing_algorithm_framework/infrastructure/models/order/order_metadata.py +44 -0
  164. investing_algorithm_framework/infrastructure/models/order_trade_association.py +10 -0
  165. investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +3 -2
  166. investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +37 -0
  167. investing_algorithm_framework/infrastructure/models/portfolio/{portfolio.py → sql_portfolio.py} +57 -3
  168. investing_algorithm_framework/infrastructure/models/position/__init__.py +2 -2
  169. investing_algorithm_framework/infrastructure/models/position/position.py +16 -11
  170. investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +23 -0
  171. investing_algorithm_framework/infrastructure/models/trades/__init__.py +9 -0
  172. investing_algorithm_framework/infrastructure/models/trades/trade.py +130 -0
  173. investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +59 -0
  174. investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +55 -0
  175. investing_algorithm_framework/infrastructure/order_executors/__init__.py +21 -0
  176. investing_algorithm_framework/infrastructure/order_executors/backtest_oder_executor.py +28 -0
  177. investing_algorithm_framework/infrastructure/order_executors/ccxt_order_executor.py +200 -0
  178. investing_algorithm_framework/infrastructure/portfolio_providers/__init__.py +19 -0
  179. investing_algorithm_framework/infrastructure/portfolio_providers/ccxt_portfolio_provider.py +199 -0
  180. investing_algorithm_framework/infrastructure/repositories/__init__.py +13 -5
  181. investing_algorithm_framework/infrastructure/repositories/order_metadata_repository.py +17 -0
  182. investing_algorithm_framework/infrastructure/repositories/order_repository.py +32 -19
  183. investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +2 -2
  184. investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +56 -0
  185. investing_algorithm_framework/infrastructure/repositories/position_repository.py +47 -4
  186. investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +21 -0
  187. investing_algorithm_framework/infrastructure/repositories/repository.py +85 -31
  188. investing_algorithm_framework/infrastructure/repositories/trade_repository.py +71 -0
  189. investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +29 -0
  190. investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +29 -0
  191. investing_algorithm_framework/infrastructure/services/__init__.py +9 -2
  192. investing_algorithm_framework/infrastructure/services/aws/__init__.py +6 -0
  193. investing_algorithm_framework/infrastructure/services/aws/state_handler.py +193 -0
  194. investing_algorithm_framework/infrastructure/services/azure/__init__.py +5 -0
  195. investing_algorithm_framework/infrastructure/services/azure/state_handler.py +158 -0
  196. investing_algorithm_framework/infrastructure/services/backtesting/__init__.py +9 -0
  197. investing_algorithm_framework/infrastructure/services/backtesting/backtest_service.py +2596 -0
  198. investing_algorithm_framework/infrastructure/services/backtesting/event_backtest_service.py +285 -0
  199. investing_algorithm_framework/infrastructure/services/backtesting/vector_backtest_service.py +468 -0
  200. investing_algorithm_framework/services/__init__.py +127 -10
  201. investing_algorithm_framework/services/configuration_service.py +95 -0
  202. investing_algorithm_framework/services/data_providers/__init__.py +5 -0
  203. investing_algorithm_framework/services/data_providers/data_provider_service.py +1058 -0
  204. investing_algorithm_framework/services/market_credential_service.py +40 -0
  205. investing_algorithm_framework/services/metrics/__init__.py +119 -0
  206. investing_algorithm_framework/services/metrics/alpha.py +0 -0
  207. investing_algorithm_framework/services/metrics/beta.py +0 -0
  208. investing_algorithm_framework/services/metrics/cagr.py +60 -0
  209. investing_algorithm_framework/services/metrics/calmar_ratio.py +40 -0
  210. investing_algorithm_framework/services/metrics/drawdown.py +218 -0
  211. investing_algorithm_framework/services/metrics/equity_curve.py +24 -0
  212. investing_algorithm_framework/services/metrics/exposure.py +210 -0
  213. investing_algorithm_framework/services/metrics/generate.py +358 -0
  214. investing_algorithm_framework/services/metrics/mean_daily_return.py +84 -0
  215. investing_algorithm_framework/services/metrics/price_efficiency.py +57 -0
  216. investing_algorithm_framework/services/metrics/profit_factor.py +165 -0
  217. investing_algorithm_framework/services/metrics/recovery.py +113 -0
  218. investing_algorithm_framework/services/metrics/returns.py +452 -0
  219. investing_algorithm_framework/services/metrics/risk_free_rate.py +28 -0
  220. investing_algorithm_framework/services/metrics/sharpe_ratio.py +137 -0
  221. investing_algorithm_framework/services/metrics/sortino_ratio.py +74 -0
  222. investing_algorithm_framework/services/metrics/standard_deviation.py +156 -0
  223. investing_algorithm_framework/services/metrics/trades.py +473 -0
  224. investing_algorithm_framework/services/metrics/treynor_ratio.py +0 -0
  225. investing_algorithm_framework/services/metrics/ulcer.py +0 -0
  226. investing_algorithm_framework/services/metrics/value_at_risk.py +0 -0
  227. investing_algorithm_framework/services/metrics/volatility.py +118 -0
  228. investing_algorithm_framework/services/metrics/win_rate.py +177 -0
  229. investing_algorithm_framework/services/order_service/__init__.py +9 -0
  230. investing_algorithm_framework/services/order_service/order_backtest_service.py +178 -0
  231. investing_algorithm_framework/services/order_service/order_executor_lookup.py +110 -0
  232. investing_algorithm_framework/services/order_service/order_service.py +826 -0
  233. investing_algorithm_framework/services/portfolios/__init__.py +16 -0
  234. investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +54 -0
  235. investing_algorithm_framework/services/{portfolio_configuration_service.py → portfolios/portfolio_configuration_service.py} +27 -12
  236. investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +106 -0
  237. investing_algorithm_framework/services/portfolios/portfolio_service.py +188 -0
  238. investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +136 -0
  239. investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +182 -0
  240. investing_algorithm_framework/services/positions/__init__.py +7 -0
  241. investing_algorithm_framework/services/positions/position_service.py +210 -0
  242. investing_algorithm_framework/services/positions/position_snapshot_service.py +18 -0
  243. investing_algorithm_framework/services/repository_service.py +8 -2
  244. investing_algorithm_framework/services/trade_order_evaluator/__init__.py +9 -0
  245. investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +117 -0
  246. investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +51 -0
  247. investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +80 -0
  248. investing_algorithm_framework/services/trade_service/__init__.py +9 -0
  249. investing_algorithm_framework/services/trade_service/trade_service.py +1099 -0
  250. investing_algorithm_framework/services/trade_service/trade_stop_loss_service.py +39 -0
  251. investing_algorithm_framework/services/trade_service/trade_take_profit_service.py +41 -0
  252. investing_algorithm_framework-7.25.6.dist-info/METADATA +535 -0
  253. investing_algorithm_framework-7.25.6.dist-info/RECORD +268 -0
  254. {investing_algorithm_framework-1.3.1.dist-info → investing_algorithm_framework-7.25.6.dist-info}/WHEEL +1 -2
  255. investing_algorithm_framework-7.25.6.dist-info/entry_points.txt +3 -0
  256. investing_algorithm_framework/app/algorithm.py +0 -410
  257. investing_algorithm_framework/domain/models/market_data/__init__.py +0 -11
  258. investing_algorithm_framework/domain/models/market_data/asset_price.py +0 -50
  259. investing_algorithm_framework/domain/models/market_data/ohlcv.py +0 -76
  260. investing_algorithm_framework/domain/models/market_data/order_book.py +0 -63
  261. investing_algorithm_framework/domain/models/market_data/ticker.py +0 -92
  262. investing_algorithm_framework/domain/models/order/order_fee.py +0 -45
  263. investing_algorithm_framework/domain/models/trading_data_types.py +0 -47
  264. investing_algorithm_framework/domain/models/trading_time_frame.py +0 -205
  265. investing_algorithm_framework/domain/singleton.py +0 -9
  266. investing_algorithm_framework/infrastructure/models/order/order_fee.py +0 -21
  267. investing_algorithm_framework/infrastructure/models/position/position_cost.py +0 -32
  268. investing_algorithm_framework/infrastructure/repositories/order_fee_repository.py +0 -15
  269. investing_algorithm_framework/infrastructure/repositories/position_cost_repository.py +0 -16
  270. investing_algorithm_framework/infrastructure/services/market_service.py +0 -422
  271. investing_algorithm_framework/services/market_data_service.py +0 -75
  272. investing_algorithm_framework/services/order_service.py +0 -464
  273. investing_algorithm_framework/services/portfolio_service.py +0 -105
  274. investing_algorithm_framework/services/position_cost_service.py +0 -5
  275. investing_algorithm_framework/services/position_service.py +0 -50
  276. investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -219
  277. investing_algorithm_framework/setup_logging.py +0 -40
  278. investing_algorithm_framework-1.3.1.dist-info/AUTHORS.md +0 -8
  279. investing_algorithm_framework-1.3.1.dist-info/METADATA +0 -172
  280. investing_algorithm_framework-1.3.1.dist-info/RECORD +0 -103
  281. investing_algorithm_framework-1.3.1.dist-info/top_level.txt +0 -1
  282. {investing_algorithm_framework-1.3.1.dist-info → investing_algorithm_framework-7.25.6.dist-info}/LICENSE +0 -0
@@ -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,10 +1,20 @@
1
+ from datetime import timedelta
1
2
  from enum import Enum
3
+ from investing_algorithm_framework.domain.exceptions import \
4
+ OperationalException
2
5
 
3
6
 
4
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
+ """
5
14
  SECOND = "SECOND"
6
15
  MINUTE = "MINUTE"
7
16
  HOUR = "HOUR"
17
+ DAY = "DAY"
8
18
 
9
19
  @staticmethod
10
20
  def from_string(value: str):
@@ -16,10 +26,50 @@ class TimeUnit(Enum):
16
26
  if value.upper() == entry.value:
17
27
  return entry
18
28
 
19
- raise ValueError(
20
- 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)}"
21
37
  )
22
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
+
23
73
  def equals(self, other):
24
74
 
25
75
  if isinstance(other, Enum):
@@ -38,3 +88,62 @@ class TimeUnit(Enum):
38
88
  return entry
39
89
 
40
90
  return TimeUnit.from_string(value)
91
+
92
+ def create_date(self, start_date, interval):
93
+
94
+ if TimeUnit.SECOND.equals(self):
95
+ return timedelta(minutes=interval)
96
+ elif TimeUnit.MINUTE.equals(self):
97
+ return timedelta(minutes=interval)
98
+ elif TimeUnit.HOUR.equals(self):
99
+ return timedelta(hours=interval)
100
+ elif TimeUnit.DAY.equals(self):
101
+ return timedelta(days=interval)
102
+
103
+ raise ValueError(f"Unsupported time unit: {self}")
104
+
105
+ @property
106
+ def single_name(self):
107
+
108
+ if TimeUnit.SECOND.equals(self.value):
109
+ return "second"
110
+
111
+ if TimeUnit.MINUTE.equals(self.value):
112
+ return "minute"
113
+
114
+ if TimeUnit.HOUR.equals(self.value):
115
+ return "hour"
116
+
117
+ if TimeUnit.DAY.equals(self.value):
118
+ return "day"
119
+
120
+ @property
121
+ def plural_name(self):
122
+
123
+ if TimeUnit.SECOND.equals(self.value):
124
+ return "seconds"
125
+
126
+ if TimeUnit.MINUTE.equals(self.value):
127
+ return "minutes"
128
+
129
+ if TimeUnit.HOUR.equals(self.value):
130
+ return "hours"
131
+
132
+ if TimeUnit.DAY.equals(self.value):
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
+ ]