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,422 +0,0 @@
1
- import logging
2
- from datetime import datetime
3
- from time import sleep
4
- import pandas as pd
5
- from dateutil.parser import parse
6
- import ccxt
7
-
8
- from investing_algorithm_framework.domain import OperationalException, \
9
- OHLCV, AssetPrice, Order
10
-
11
- logger = logging.getLogger(__name__)
12
-
13
-
14
- class MarketService:
15
- exchange = None
16
- _market = None
17
- api_key = None,
18
- secret_key = None
19
- exchange_class = None
20
- msec = 1000
21
- minute = 60 * msec
22
-
23
- @property
24
- def market(self):
25
- return self._market
26
-
27
- @market.setter
28
- def market(self, value):
29
-
30
- if not isinstance(value, str):
31
- raise OperationalException("Market must be a string")
32
-
33
- self._market = value.lower()
34
-
35
- if not hasattr(ccxt, self._market):
36
- raise OperationalException(
37
- f"No market service found for market id {self._market}"
38
- )
39
-
40
- self.exchange_class = getattr(ccxt, self._market)
41
- self.exchange = self.exchange_class()
42
-
43
- def initialize(self, portfolio_configuration):
44
- self.api_key = portfolio_configuration.api_key
45
- self.secret_key = portfolio_configuration.secret_key
46
- self._market = portfolio_configuration.market
47
-
48
- if not hasattr(ccxt, self.market):
49
- raise OperationalException(
50
- f"No market service found for market id {self.market}"
51
- )
52
-
53
- self.exchange_class = getattr(ccxt, self.market)
54
-
55
- if self.exchange_class is None:
56
- raise OperationalException(
57
- f"No market service found for market id {self.market}"
58
- )
59
-
60
- if self.api_key is not None or self.secret_key is not None:
61
- self.exchange = self.exchange_class({
62
- 'apiKey': self.api_key,
63
- 'secret': self.secret_key,
64
- })
65
- else:
66
- self.exchange = self.exchange_class({})
67
-
68
- def pair_exists(self, target_symbol: str, trading_symbol: str):
69
-
70
- if not self.exchange.has['fetchTicker']:
71
- raise OperationalException(
72
- f"Market service {self.market} does not support "
73
- f"functionality pair_exists"
74
- )
75
-
76
- try:
77
- data = self.get_ticker(f"{target_symbol}/{trading_symbol}")
78
- return "symbol" in data
79
- except OperationalException:
80
- return False
81
-
82
- def get_ticker(self, symbol):
83
-
84
- if not self.exchange.has['fetchTicker']:
85
- raise OperationalException(
86
- f"Market service {self.market} does not support "
87
- f"functionality get_ticker"
88
- )
89
-
90
- try:
91
- return self.exchange.fetchTicker(symbol)
92
- except Exception as e:
93
- logger.exception(e)
94
- raise OperationalException(
95
- f"Could not retrieve ticker for symbol {symbol}"
96
- )
97
-
98
- def get_tickers(self, symbols):
99
-
100
- if not self.exchange.has['fetchTickers']:
101
- raise OperationalException(
102
- f"Market service {self.market} does not support "
103
- f"functionality get_tickers"
104
- )
105
-
106
- try:
107
- return self.exchange.fetchTickers(symbols)
108
- except Exception as e:
109
- logger.exception(e)
110
- raise OperationalException(
111
- "Could not retrieve selection of tickers"
112
- )
113
-
114
- def get_order_book(self, symbol):
115
-
116
- if not self.exchange.has['fetchOrderBook']:
117
- raise OperationalException(
118
- f"Market service {self.market} does not support "
119
- f"functionality get_order_book"
120
- )
121
-
122
- try:
123
- return self.exchange.fetchOrderBook(symbol)
124
- except Exception as e:
125
- logger.exception(e)
126
- raise OperationalException("Could not retrieve order book")
127
-
128
- def get_order_books(self, symbols):
129
- data = {}
130
-
131
- for symbol in symbols:
132
- try:
133
- entry = self.get_order_book(symbol)
134
- del entry['symbol']
135
- data[symbol] = entry
136
- except Exception as e:
137
- logger.exception(e)
138
-
139
- return data
140
-
141
- def get_order(self, order):
142
- symbol = f"{order.target_symbol.upper()}/" \
143
- f"{order.trading_symbol.upper()}"
144
-
145
- if not self.exchange.has['fetchOrder']:
146
- raise OperationalException(
147
- f"Market service {self.market} does not support "
148
- f"functionality get_order"
149
- )
150
-
151
- try:
152
- order = self.exchange.fetchOrder(order.external_id, symbol)
153
- return Order.from_ccxt_order(order)
154
- except Exception as e:
155
- logger.exception(e)
156
- raise OperationalException("Could not retrieve order")
157
-
158
- def get_orders(self, symbol, since: datetime = None):
159
-
160
- if not self.exchange.has['fetchOrders']:
161
- raise OperationalException(
162
- f"Market service {self.market} does not support "
163
- f"functionality get_orders"
164
- )
165
-
166
- if since is not None:
167
- since = self.exchange.parse8601(
168
- since.strftime(":%Y-%m-%d %H:%M:%S")
169
- )
170
-
171
- try:
172
- ccxt_orders = self.exchange.fetchOrders(symbol, since=since)
173
- return [Order.from_ccxt_order(order) for order in ccxt_orders]
174
- except Exception as e:
175
- logger.exception(e)
176
- raise OperationalException("Could not retrieve orders")
177
- else:
178
- try:
179
- ccxt_orders = self.exchange.fetchOrders(symbol)
180
- return [Order.from_ccxt_order(order) for order in ccxt_orders]
181
- except Exception as e:
182
- logger.exception(e)
183
- raise OperationalException("Could not retrieve orders")
184
-
185
- def get_balance(self):
186
-
187
- if not self.exchange.has['fetchBalance']:
188
- raise OperationalException(
189
- f"Market service {self.market} does not support "
190
- f"functionality get_balance"
191
- )
192
-
193
- try:
194
- return self.exchange.fetchBalance()
195
- except Exception as e:
196
- logger.exception(e)
197
- raise OperationalException("Could not retrieve balance")
198
-
199
- def create_limit_buy_order(
200
- self,
201
- target_symbol: str,
202
- trading_symbol: str,
203
- amount: float,
204
- price: float
205
- ):
206
-
207
- if not self.exchange.has['createLimitBuyOrder']:
208
- raise OperationalException(
209
- f"Market service {self.market} does not support "
210
- f"functionality create_limit_buy_order"
211
- )
212
-
213
- symbol = f"{target_symbol.upper()}/{trading_symbol.upper()}"
214
-
215
- try:
216
- order = self.exchange.createLimitBuyOrder(
217
- symbol, amount, price
218
- )
219
- return Order.from_ccxt_order(order)
220
- except Exception as e:
221
- logger.exception(e)
222
- raise OperationalException("Could not create limit buy order")
223
-
224
- def create_limit_sell_order(
225
- self,
226
- target_symbol: str,
227
- trading_symbol: str,
228
- amount: float,
229
- price: float
230
- ):
231
-
232
- if not self.exchange.has['createLimitSellOrder']:
233
- raise OperationalException(
234
- f"Market service {self.market} does not support "
235
- f"functionality create_limit_sell_order"
236
- )
237
-
238
- symbol = f"{target_symbol.upper()}/{trading_symbol.upper()}"
239
-
240
- try:
241
- order = self.exchange.createLimitSellOrder(
242
- symbol, amount, price
243
- )
244
- return Order.from_ccxt_order(order)
245
- except Exception as e:
246
- logger.exception(e)
247
- raise OperationalException("Could not create limit sell order")
248
-
249
- def create_market_sell_order(
250
- self,
251
- target_symbol: str,
252
- trading_symbol: str,
253
- amount: float,
254
- ):
255
-
256
- if not self.exchange.has['createMarketSellOrder']:
257
- raise OperationalException(
258
- f"Market service {self.market} does not support "
259
- f"functionality create_market_sell_order"
260
- )
261
-
262
- symbol = f"{target_symbol.upper()}/{trading_symbol.upper()}"
263
-
264
- try:
265
- order = self.exchange.createMarketSellOrder(symbol, amount)
266
- return Order.from_ccxt_order(order)
267
- except Exception as e:
268
- logger.exception(e)
269
- raise OperationalException("Could not create market sell order")
270
-
271
- def cancel_order(self, order):
272
- if not self.exchange.has['cancelOrder']:
273
- raise OperationalException(
274
- f"Market service {self.market} does not support "
275
- f"functionality cancel_order"
276
- )
277
-
278
- self.exchange.cancelOrder(
279
- order.get_order_reference(),
280
- f"{order.get_target_symbol()}/{order.get_trading_symbol()}")
281
-
282
- def get_open_orders(
283
- self, target_symbol: str = None, trading_symbol: str = None
284
- ):
285
-
286
- if not self.exchange.has['fetchOpenOrders']:
287
- raise OperationalException(
288
- f"Market service {self.market} does not support "
289
- f"functionality get_open_orders"
290
- )
291
-
292
- try:
293
- if target_symbol is None or trading_symbol is None:
294
- return self.exchange.fetchOpenOrders()
295
-
296
- symbol = f"{target_symbol.upper()}/{trading_symbol.upper()}"
297
- ccxt_orders = self.exchange.fetchOpenOrders(symbol)
298
- return [Order.from_ccxt_order(order) for order in ccxt_orders]
299
- except Exception as e:
300
- logger.exception(e)
301
- raise OperationalException("Could not retrieve open orders")
302
-
303
- def get_closed_orders(
304
- self, target_symbol: str = None, trading_symbol: str = None
305
- ):
306
-
307
- if not self.exchange.has['fetchClosedOrders']:
308
- raise OperationalException(
309
- f"Market service {self.market} does not support "
310
- f"functionality get_closed_orders"
311
- )
312
-
313
- try:
314
- if target_symbol is None or trading_symbol is None:
315
- return self.exchange.fetchClosedOrders()
316
-
317
- symbol = f"{target_symbol.upper()}/{trading_symbol.upper()}"
318
- ccxt_orders = self.exchange.fetchClosedOrders(symbol)
319
- return [Order.from_ccxt_order(order) for order in ccxt_orders]
320
- except Exception as e:
321
- logger.exception(e)
322
- raise OperationalException("Could not retrieve closed orders")
323
-
324
- def get_prices(self, symbols):
325
- asset_prices = []
326
-
327
- try:
328
- tickers = self.exchange.fetchTickers(symbols)
329
- for ticker in tickers:
330
- asset_prices.append(
331
- AssetPrice(
332
- tickers[ticker]["symbol"],
333
- tickers[ticker]["ask"],
334
- tickers[ticker]["datetime"]
335
- )
336
- )
337
-
338
- return asset_prices
339
- except Exception as e:
340
- logger.exception(e)
341
- raise OperationalException("Could not retrieve prices")
342
-
343
- def get_ohclv(self, symbol, time_unit, since):
344
-
345
- if not self.exchange.has['fetchOHLCV']:
346
- raise OperationalException(
347
- f"Market service {self.market} does not support "
348
- f"functionality get_ohclvs"
349
- )
350
-
351
- from_timestamp = self.exchange.parse8601(
352
- since.strftime(":%Y-%m-%d %H:%M:%S")
353
- )
354
- now = self.exchange.milliseconds()
355
- data = []
356
-
357
- while from_timestamp < now:
358
- ohlcv = self.exchange.fetch_ohlcv(
359
- symbol, time_unit, from_timestamp
360
- )
361
- sleep(self.exchange.rateLimit / 1000)
362
- from_timestamp = \
363
- ohlcv[-1][0] + self.exchange.parse_timeframe(time_unit) * 1000
364
- ohlcv = [[self.exchange.iso8601(candle[0])] + candle[1:] for candle
365
- in ohlcv]
366
- data += ohlcv
367
-
368
- return OHLCV.from_dict({"symbol": symbol, "data": data})
369
-
370
- def get_ohclvs(self, symbols, time_frame, from_timestamp):
371
-
372
- if not self.exchange.has['fetchOHLCV']:
373
- raise OperationalException(
374
- f"Market service {self.market} does not support "
375
- f"functionality get_ohclvs"
376
- )
377
-
378
- now = self.exchange.milliseconds()
379
- ohlcvs = {}
380
-
381
- # Set timeout to 30 seconds
382
- self.exchange.timeout = 30000
383
-
384
- for symbol in symbols:
385
-
386
- try:
387
- time_stamp = self.exchange.parse8601(
388
- from_timestamp.strftime(":%Y-%m-%d %H:%M:%S")
389
- )
390
- dfs = []
391
-
392
- while time_stamp < now:
393
-
394
- ohlcv = self.exchange.fetch_ohlcv(
395
- symbol, time_frame.to_ccxt_string(), time_stamp
396
- )
397
- sleep(self.exchange.rateLimit / 1000)
398
- time_stamp = \
399
- ohlcv[-1][0] + \
400
- self.exchange.parse_timeframe(
401
- time_frame.to_ccxt_string()
402
- ) * 1000
403
-
404
- ohlcv = [[self.exchange.iso8601(candle[0])]
405
- + candle[1:] for candle in ohlcv]
406
- df = pd.DataFrame(ohlcv,
407
- columns=['timestamp', 'open', 'high',
408
- 'low', 'close', 'volume'])
409
- df['timestamp'] = df['timestamp'].apply(lambda x: parse(x))
410
- df['timestamp'] = pd.to_datetime(
411
- df['timestamp'], unit='ms'
412
- )
413
- df.set_index('timestamp', inplace=True)
414
- dfs.append(df)
415
-
416
- combined_df = pd.concat(dfs, axis=0)
417
- ohlcvs[symbol] = combined_df
418
- except Exception as e:
419
- logger.exception(e)
420
- logger.error(f"Could not retrieve ohclv data for {symbol}")
421
-
422
- return ohlcvs
@@ -1,75 +0,0 @@
1
- from investing_algorithm_framework.domain import TradingDataType, \
2
- OperationalException, TradingTimeFrame, DATETIME_FORMAT
3
- from datetime import datetime, timedelta
4
-
5
-
6
- class MarketDataService:
7
-
8
- def __init__(self, market_service):
9
- self.market_service = market_service
10
-
11
- def get_data_for_strategy(self, strategy):
12
- data = {}
13
-
14
- if strategy.market and \
15
- (strategy.trading_data_types or strategy.trading_data_type):
16
- self.market_service.market = strategy.market
17
-
18
- if not strategy.trading_data_types:
19
- strategy.trading_data_types = [strategy.trading_data_type]
20
-
21
- for trading_data_type in strategy.trading_data_types:
22
-
23
- if TradingDataType.TICKER.equals(trading_data_type):
24
- data["tickers"] = self.market_service.get_tickers(
25
- symbols=strategy.symbols
26
- )
27
-
28
- elif TradingDataType.ORDER_BOOK.equals(trading_data_type):
29
- data["order_books"] = self.market_service.get_order_books(
30
- symbols=strategy.symbols
31
- )
32
- elif TradingDataType.OHLCV.equals(trading_data_type):
33
-
34
- if strategy.trading_time_frame is None:
35
- raise OperationalException(
36
- "'trading_time_frame' attribute is not specified "
37
- "for OHLCV data"
38
- )
39
-
40
- trading_time_frame_start_date = \
41
- strategy.trading_time_frame_start_date
42
-
43
- if strategy.trading_time_frame_start_date is not None:
44
-
45
- if isinstance(
46
- strategy.trading_time_frame_start_date, str
47
- ):
48
- trading_time_frame_start_date = \
49
- datetime.strptime(
50
- strategy.trading_time_frame_start_date,
51
- DATETIME_FORMAT
52
- )
53
- elif not isinstance(
54
- trading_time_frame_start_date, datetime
55
- ):
56
- raise OperationalException(
57
- "Invalid type for 'trading_time_"
58
- "frame_start_date' attribute"
59
- )
60
- else:
61
- trading_time_frame = TradingTimeFrame\
62
- .from_value(strategy.trading_time_frame)
63
- trading_time_frame_start_date = \
64
- datetime.utcnow() - timedelta(
65
- minutes=trading_time_frame.minutes
66
- )
67
-
68
- data["ohlcvs"] = self.market_service.get_ohclvs(
69
- strategy.symbols,
70
- time_frame=TradingTimeFrame
71
- .from_value(strategy.trading_time_frame),
72
- from_timestamp=trading_time_frame_start_date
73
- )
74
-
75
- return data