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,189 +0,0 @@
1
- from typing import List
2
-
3
- from investing_algorithm_framework.domain import MarketService, \
4
- MarketDataSource, OHLCVMarketDataSource, TickerMarketDataSource, \
5
- OrderBookMarketDataSource, TimeFrame
6
- from investing_algorithm_framework.services.market_credential_service \
7
- import MarketCredentialService
8
-
9
-
10
- class MarketDataSourceService:
11
- """
12
- This class is responsible for managing the market data sources.
13
-
14
- It is used by the algorithm to get market data from different sources.
15
- The MarketDataSourceService will first check if there is a market data
16
- source that matches the symbol, market and time frame provided by the user.
17
- If there is, it will use that market data source to get the data. If there
18
- is not, it will use the MarketService to get the data.
19
- """
20
- _market_data_sources: List[MarketDataSource] = []
21
-
22
- def __init__(
23
- self,
24
- market_service: MarketService,
25
- market_credential_service: MarketCredentialService,
26
- market_data_sources: List[MarketDataSource] = None,
27
- ):
28
-
29
- if market_data_sources is not None:
30
- self._market_data_sources: List[MarketDataSource] \
31
- = market_data_sources
32
-
33
- self._market_service: MarketService = market_service
34
- self._market_credential_service: MarketCredentialService = \
35
- market_credential_service
36
-
37
- def get_ticker(self, symbol, market=None):
38
- ticker_market_data_source = self.get_ticker_market_data_source(
39
- symbol=symbol, market=market
40
- )
41
-
42
- if ticker_market_data_source is not None:
43
- return ticker_market_data_source.get_data(
44
- market_credential_service=self._market_credential_service
45
- )
46
- return self._market_service.get_ticker(symbol, market)
47
-
48
- def get_order_book(self, symbol, market=None):
49
- order_book_market_data_source = self.get_order_book_market_data_source(
50
- symbol=symbol, market=market
51
- )
52
-
53
- if order_book_market_data_source is not None:
54
- return order_book_market_data_source.get_data(
55
- market_credential_service=self._market_credential_service
56
- )
57
-
58
- return self._market_service.get_order_book(symbol, market)
59
-
60
- def get_ohlcv(
61
- self,
62
- symbol,
63
- from_timestamp,
64
- time_frame,
65
- market=None,
66
- to_timestamp=None
67
- ):
68
- ohlcv_market_data_source = self.get_ohlcv_market_data_source(
69
- symbol=symbol, market=market, time_frame=time_frame
70
- )
71
-
72
- if ohlcv_market_data_source is not None:
73
- return ohlcv_market_data_source.get_data(
74
- from_timestamp=from_timestamp,
75
- to_timestamp=to_timestamp,
76
- market_credential_service=self._market_credential_service
77
- )
78
-
79
- return self._market_service.get_ohlcv(
80
- symbol=symbol,
81
- time_frame=time_frame,
82
- from_timestamp=from_timestamp,
83
- market=market,
84
- to_timestamp=to_timestamp
85
- )
86
-
87
- def get_data(self, identifier):
88
- for market_data_source in self._market_data_sources:
89
- if market_data_source.get_identifier() == identifier:
90
- return market_data_source.get_data(
91
- market_credential_service=self._market_credential_service
92
- )
93
-
94
- def get_ticker_market_data_source(self, symbol, market=None):
95
-
96
- if self.market_data_sources is not None:
97
- for market_data_source in self._market_data_sources:
98
- if isinstance(market_data_source, TickerMarketDataSource):
99
-
100
- if market is not None:
101
- if market_data_source.market.lower() == market.lower()\
102
- and market_data_source.symbol.lower() \
103
- == symbol.lower():
104
- return market_data_source
105
- else:
106
- if market_data_source.symbol.lower() \
107
- == symbol.lower():
108
- return market_data_source
109
-
110
- return None
111
-
112
- def get_ohlcv_market_data_source(
113
- self, symbol, time_frame=None, market=None
114
- ):
115
-
116
- if time_frame is not None:
117
- time_frame = TimeFrame.from_value(time_frame)
118
-
119
- if self.market_data_sources is not None:
120
-
121
- for market_data_source in self._market_data_sources:
122
- if isinstance(market_data_source, OHLCVMarketDataSource):
123
-
124
- if market is not None and time_frame is not None:
125
-
126
- if market_data_source.market.lower() == market.lower()\
127
- and market_data_source.symbol.lower() \
128
- == symbol.lower() and \
129
- market_data_source.timeframe == time_frame:
130
- return market_data_source
131
- elif market is not None:
132
- if market_data_source.market.lower() == market.lower()\
133
- and market_data_source.symbol.lower() \
134
- == symbol.lower():
135
- return market_data_source
136
- elif time_frame is not None:
137
- if market_data_source.symbol.lower() \
138
- == symbol.lower() and \
139
- market_data_source.timeframe == time_frame:
140
- return market_data_source
141
- else:
142
- if market_data_source.symbol.lower() \
143
- == symbol.lower():
144
- return market_data_source
145
-
146
- return None
147
-
148
- def get_order_book_market_data_source(self, symbol, market=None):
149
-
150
- if self.market_data_sources is not None:
151
- for market_data_source in self._market_data_sources:
152
- if isinstance(market_data_source, OrderBookMarketDataSource):
153
-
154
- if market is not None:
155
- if market_data_source.market.lower() == market.lower()\
156
- and market_data_source.symbol.lower() \
157
- == symbol.lower():
158
- return market_data_source
159
- else:
160
- if market_data_source.symbol.lower() \
161
- == symbol.lower():
162
- return market_data_source
163
-
164
- return None
165
-
166
- @property
167
- def market_data_sources(self):
168
- return self._market_data_sources
169
-
170
- @market_data_sources.setter
171
- def market_data_sources(self, market_data_sources):
172
- self._market_data_sources = market_data_sources
173
-
174
- def add(self, market_data_source):
175
-
176
- # Check if there is already a market data source with the same
177
- # identifier
178
- for existing_market_data_source in self._market_data_sources:
179
- if existing_market_data_source.get_identifier() == \
180
- market_data_source.get_identifier():
181
- return
182
-
183
- self._market_data_sources.append(market_data_source)
184
-
185
- def get_market_data_sources(self):
186
- return self._market_data_sources
187
-
188
- def has_ticker_market_data_source(self, symbol, market=None):
189
- return self.get_ticker_market_data_source(symbol, market) is not None
@@ -1,31 +0,0 @@
1
- from investing_algorithm_framework.domain import MarketService
2
- from investing_algorithm_framework.services.repository_service import \
3
- RepositoryService
4
-
5
-
6
- class PositionService(RepositoryService):
7
-
8
- def __init__(
9
- self,
10
- repository,
11
- order_repository,
12
- market_service: MarketService,
13
- market_credential_service
14
- ):
15
- super().__init__(repository)
16
- self._market_service: MarketService = market_service
17
- self._market_credentials_service = market_credential_service
18
- self._order_repository = order_repository
19
-
20
- def close_position(self, position_id, portfolio):
21
- self._market_service.market_data_credentials = \
22
- self._market_credentials_service.get_all()
23
- position = self.get(position_id)
24
-
25
- if position.amount > 0:
26
- self._market_service.create_market_sell_order(
27
- position.symbol,
28
- portfolio.get_trading_symbol(),
29
- position.amount,
30
- market=portfolio.get_market(),
31
- )
@@ -1,264 +0,0 @@
1
- import logging
2
- from datetime import datetime
3
-
4
- import schedule
5
-
6
- from investing_algorithm_framework.domain import StoppableThread, TimeUnit, \
7
- OperationalException, MarketDataSource
8
- from investing_algorithm_framework.services.market_data_source_service \
9
- import MarketDataSourceService
10
-
11
- logger = logging.getLogger("investing_algorithm_framework")
12
-
13
-
14
- class StrategyOrchestratorService:
15
- """
16
- Service that orchestrates the execution of strategies and tasks
17
-
18
- Attributes:
19
- - history: dict
20
- A dictionary that keeps track of the last time a strategy or task was
21
- run
22
- - _strategies: list
23
- A list of strategies
24
- - _tasks: list
25
- A list of tasks
26
- - threads: list
27
- A list of threads that are currently running
28
- - iterations: int
29
- The number of iterations that have been run
30
- - max_iterations: int
31
- The maximum number of iterations that can be run
32
- - market_data_source_service: MarketDataSourceService
33
- The service that provides market data
34
- """
35
-
36
- def __init__(self, market_data_source_service: MarketDataSourceService):
37
- self.history = {}
38
- self._strategies = []
39
- self._tasks = []
40
- self.threads = []
41
- self.iterations = 0
42
- self.max_iterations = -1
43
- self.clear()
44
- self.market_data_source_service: MarketDataSourceService \
45
- = market_data_source_service
46
-
47
- def cleanup_threads(self):
48
-
49
- for stoppable in self.threads:
50
- if not stoppable.is_alive():
51
- # get results from thread
52
- stoppable.done = True
53
- self.threads = [t for t in self.threads if not t.done]
54
-
55
- def run_strategy(self, strategy, algorithm, sync=False):
56
- self.cleanup_threads()
57
- matching_thread = next(
58
- (t for t in self.threads if t.name == strategy.worker_id),
59
- None
60
- )
61
-
62
- # Don't run a strategy that is already running
63
- if matching_thread:
64
- return
65
-
66
- market_data = {}
67
-
68
- if strategy.market_data_sources is not None \
69
- and len(strategy.market_data_sources) > 0:
70
-
71
- for data_id in strategy.market_data_sources:
72
-
73
- if isinstance(data_id, MarketDataSource):
74
- market_data[data_id.get_identifier()] = \
75
- self.market_data_source_service\
76
- .get_data(identifier=data_id.get_identifier())
77
- else:
78
- market_data[data_id] = \
79
- self.market_data_source_service \
80
- .get_data(identifier=data_id)
81
-
82
- logger.info(f"Running strategy {strategy.worker_id}")
83
-
84
- if sync:
85
- strategy.run_strategy(
86
- market_data=market_data, algorithm=algorithm
87
- )
88
- else:
89
- self.iterations += 1
90
- thread = StoppableThread(
91
- target=strategy.run_strategy,
92
- kwargs={
93
- "market_data": market_data,
94
- "algorithm": algorithm
95
- }
96
- )
97
- thread.name = strategy.worker_id
98
- thread.start()
99
- self.threads.append(thread)
100
-
101
- self.history[strategy.worker_id] = {"last_run": datetime.utcnow()}
102
-
103
- def run_task(self, task, algorithm, sync=False):
104
- self.cleanup_threads()
105
-
106
- matching_thread = next(
107
- (t for t in self.threads if t.name == task.worker_id),
108
- None
109
- )
110
-
111
- # Don't run a strategy that is already running
112
- if matching_thread:
113
- return
114
-
115
- logger.info(f"Running task {task.worker_id}")
116
-
117
- if sync:
118
- task.run(algorithm=algorithm)
119
- else:
120
- self.iterations += 1
121
- thread = StoppableThread(
122
- target=task.run,
123
- kwargs={"algorithm": algorithm}
124
- )
125
- thread.name = task.worker_id
126
- thread.start()
127
- self.threads.append(thread)
128
-
129
- self.history[task.worker_id] = {"last_run": datetime.utcnow()}
130
-
131
- def start(self, algorithm, number_of_iterations=None):
132
- """
133
- F
134
-
135
- """
136
- self.max_iterations = number_of_iterations
137
-
138
- for strategy in self.strategies:
139
- if TimeUnit.SECOND.equals(strategy.time_unit):
140
- schedule.every(strategy.interval)\
141
- .seconds.do(self.run_strategy, strategy, algorithm)
142
- elif TimeUnit.MINUTE.equals(strategy.time_unit):
143
- schedule.every(strategy.interval)\
144
- .minutes.do(self.run_strategy, strategy, algorithm)
145
- elif TimeUnit.HOUR.equals(strategy.time_unit):
146
- schedule.every(strategy.interval)\
147
- .hours.do(self.run_strategy, strategy, algorithm)
148
-
149
- for task in self.tasks:
150
- if TimeUnit.SECOND.equals(task.time_unit):
151
- schedule.every(task.interval)\
152
- .seconds.do(self.run_task, task, algorithm)
153
- elif TimeUnit.MINUTE.equals(task.time_unit):
154
- schedule.every(task.interval)\
155
- .minutes.do(self.run_task, task, algorithm)
156
- elif TimeUnit.HOUR.equals(task.time_unit):
157
- schedule.every(task.interval)\
158
- .hours.do(self.run_task, task, algorithm)
159
-
160
- def stop(self):
161
- for thread in self.threads:
162
- thread.stop()
163
-
164
- schedule.clear()
165
-
166
- def clear(self):
167
- self.threads = []
168
- schedule.clear()
169
-
170
- def get_strategies(self, identifiers=None):
171
- if identifiers is None:
172
- return self.strategies
173
-
174
- strategies = []
175
- for strategy in self.strategies:
176
- if strategy.worker_id in identifiers:
177
- strategies.append(strategy)
178
-
179
- return strategies
180
-
181
- def get_tasks(self):
182
- return self._tasks
183
-
184
- def get_jobs(self):
185
- return schedule.jobs
186
-
187
- def run_pending_jobs(self):
188
- if self.max_iterations is not None and \
189
- self.max_iterations != -1 and \
190
- self.iterations >= self.max_iterations:
191
- self.clear()
192
- else:
193
- schedule.run_pending()
194
-
195
- def add_strategy(self, strategy):
196
-
197
- if strategy.worker_id not in self._strategies:
198
- self._strategies.append(strategy)
199
- else:
200
- raise OperationalException(
201
- "Strategy already exists with the same name"
202
- )
203
-
204
- def add_strategies(self, strategies):
205
- has_duplicates = False
206
-
207
- for i in range(len(strategies)):
208
- for j in range(i + 1, len(strategies)):
209
- if strategies[i].worker_id == strategies[j].worker_id:
210
- has_duplicates = True
211
- break
212
-
213
- if has_duplicates:
214
- raise OperationalException(
215
- "There are duplicate strategies with the same name"
216
- )
217
-
218
- self.strategies = strategies
219
-
220
- def add_tasks(self, tasks):
221
- has_duplicates = False
222
-
223
- for i in range(len(tasks)):
224
- for j in range(i + 1, len(tasks)):
225
- if tasks[i].worker_id == tasks[j].worker_id:
226
- has_duplicates = True
227
- break
228
-
229
- if has_duplicates:
230
- raise OperationalException(
231
- "There are duplicate tasks with the same name"
232
- )
233
-
234
- self.tasks = tasks
235
-
236
- @property
237
- def strategies(self):
238
- return self._strategies
239
-
240
- @strategies.setter
241
- def strategies(self, strategies):
242
- self._strategies = strategies
243
-
244
- @property
245
- def tasks(self):
246
- return self._tasks
247
-
248
- @tasks.setter
249
- def tasks(self, tasks):
250
- self._tasks = tasks
251
-
252
- @property
253
- def running(self):
254
- if len(self.strategies) == 0 and len(self.tasks) == 0:
255
- return False
256
-
257
- if self.max_iterations == -1:
258
- return True
259
-
260
- return self.max_iterations is None \
261
- or self.iterations < self.max_iterations
262
-
263
- def has_run(self, worker_id):
264
- return worker_id in self.history