investing-algorithm-framework 6.9.1__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 (192) hide show
  1. investing_algorithm_framework/__init__.py +147 -44
  2. investing_algorithm_framework/app/__init__.py +23 -6
  3. investing_algorithm_framework/app/algorithm/algorithm.py +5 -41
  4. investing_algorithm_framework/app/algorithm/algorithm_factory.py +17 -10
  5. investing_algorithm_framework/app/analysis/__init__.py +15 -0
  6. investing_algorithm_framework/app/analysis/backtest_data_ranges.py +121 -0
  7. investing_algorithm_framework/app/analysis/backtest_utils.py +107 -0
  8. investing_algorithm_framework/app/analysis/permutation.py +116 -0
  9. investing_algorithm_framework/app/analysis/ranking.py +297 -0
  10. investing_algorithm_framework/app/app.py +1322 -707
  11. investing_algorithm_framework/app/context.py +196 -88
  12. investing_algorithm_framework/app/eventloop.py +590 -0
  13. investing_algorithm_framework/app/reporting/__init__.py +16 -5
  14. investing_algorithm_framework/app/reporting/ascii.py +57 -202
  15. investing_algorithm_framework/app/reporting/backtest_report.py +284 -170
  16. investing_algorithm_framework/app/reporting/charts/__init__.py +10 -2
  17. investing_algorithm_framework/app/reporting/charts/entry_exist_signals.py +66 -0
  18. investing_algorithm_framework/app/reporting/charts/equity_curve.py +37 -0
  19. investing_algorithm_framework/app/reporting/charts/equity_curve_drawdown.py +11 -26
  20. investing_algorithm_framework/app/reporting/charts/line_chart.py +11 -0
  21. investing_algorithm_framework/app/reporting/charts/ohlcv_data_completeness.py +51 -0
  22. investing_algorithm_framework/app/reporting/charts/rolling_sharp_ratio.py +1 -1
  23. investing_algorithm_framework/app/reporting/generate.py +100 -114
  24. investing_algorithm_framework/app/reporting/tables/key_metrics_table.py +40 -32
  25. investing_algorithm_framework/app/reporting/tables/time_metrics_table.py +34 -27
  26. investing_algorithm_framework/app/reporting/tables/trade_metrics_table.py +23 -19
  27. investing_algorithm_framework/app/reporting/tables/trades_table.py +1 -1
  28. investing_algorithm_framework/app/reporting/tables/utils.py +1 -0
  29. investing_algorithm_framework/app/reporting/templates/report_template.html.j2 +10 -16
  30. investing_algorithm_framework/app/strategy.py +315 -175
  31. investing_algorithm_framework/app/task.py +5 -3
  32. investing_algorithm_framework/cli/cli.py +30 -12
  33. investing_algorithm_framework/cli/deploy_to_aws_lambda.py +131 -34
  34. investing_algorithm_framework/cli/initialize_app.py +20 -1
  35. investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +18 -6
  36. investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +22 -0
  37. investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +92 -0
  38. investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +2 -2
  39. investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +1 -1
  40. investing_algorithm_framework/create_app.py +3 -5
  41. investing_algorithm_framework/dependency_container.py +25 -39
  42. investing_algorithm_framework/domain/__init__.py +45 -38
  43. investing_algorithm_framework/domain/backtesting/__init__.py +21 -0
  44. investing_algorithm_framework/domain/backtesting/backtest.py +503 -0
  45. investing_algorithm_framework/domain/backtesting/backtest_date_range.py +96 -0
  46. investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +242 -0
  47. investing_algorithm_framework/domain/backtesting/backtest_metrics.py +459 -0
  48. investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +275 -0
  49. investing_algorithm_framework/domain/backtesting/backtest_run.py +605 -0
  50. investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +162 -0
  51. investing_algorithm_framework/domain/backtesting/combine_backtests.py +280 -0
  52. investing_algorithm_framework/domain/config.py +27 -0
  53. investing_algorithm_framework/domain/constants.py +6 -34
  54. investing_algorithm_framework/domain/data_provider.py +200 -56
  55. investing_algorithm_framework/domain/exceptions.py +34 -1
  56. investing_algorithm_framework/domain/models/__init__.py +10 -19
  57. investing_algorithm_framework/domain/models/base_model.py +0 -6
  58. investing_algorithm_framework/domain/models/data/__init__.py +7 -0
  59. investing_algorithm_framework/domain/models/data/data_source.py +214 -0
  60. investing_algorithm_framework/domain/models/{market_data_type.py → data/data_type.py} +7 -7
  61. investing_algorithm_framework/domain/models/market/market_credential.py +6 -0
  62. investing_algorithm_framework/domain/models/order/order.py +34 -13
  63. investing_algorithm_framework/domain/models/order/order_status.py +1 -1
  64. investing_algorithm_framework/domain/models/order/order_type.py +1 -1
  65. investing_algorithm_framework/domain/models/portfolio/portfolio.py +14 -1
  66. investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +5 -1
  67. investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +51 -11
  68. investing_algorithm_framework/domain/models/position/__init__.py +2 -1
  69. investing_algorithm_framework/domain/models/position/position.py +9 -0
  70. investing_algorithm_framework/domain/models/position/position_size.py +41 -0
  71. investing_algorithm_framework/domain/models/risk_rules/__init__.py +7 -0
  72. investing_algorithm_framework/domain/models/risk_rules/stop_loss_rule.py +51 -0
  73. investing_algorithm_framework/domain/models/risk_rules/take_profit_rule.py +55 -0
  74. investing_algorithm_framework/domain/models/snapshot_interval.py +0 -1
  75. investing_algorithm_framework/domain/models/strategy_profile.py +19 -151
  76. investing_algorithm_framework/domain/models/time_frame.py +7 -0
  77. investing_algorithm_framework/domain/models/time_interval.py +33 -0
  78. investing_algorithm_framework/domain/models/time_unit.py +63 -1
  79. investing_algorithm_framework/domain/models/trade/__init__.py +0 -2
  80. investing_algorithm_framework/domain/models/trade/trade.py +56 -32
  81. investing_algorithm_framework/domain/models/trade/trade_status.py +8 -2
  82. investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +106 -41
  83. investing_algorithm_framework/domain/models/trade/trade_take_profit.py +161 -99
  84. investing_algorithm_framework/domain/order_executor.py +19 -0
  85. investing_algorithm_framework/domain/portfolio_provider.py +20 -1
  86. investing_algorithm_framework/domain/services/__init__.py +0 -13
  87. investing_algorithm_framework/domain/strategy.py +1 -29
  88. investing_algorithm_framework/domain/utils/__init__.py +5 -1
  89. investing_algorithm_framework/domain/utils/custom_tqdm.py +22 -0
  90. investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +19 -0
  91. investing_algorithm_framework/domain/utils/polars.py +17 -14
  92. investing_algorithm_framework/download_data.py +40 -10
  93. investing_algorithm_framework/infrastructure/__init__.py +13 -25
  94. investing_algorithm_framework/infrastructure/data_providers/__init__.py +7 -4
  95. investing_algorithm_framework/infrastructure/data_providers/ccxt.py +811 -546
  96. investing_algorithm_framework/infrastructure/data_providers/csv.py +433 -122
  97. investing_algorithm_framework/infrastructure/data_providers/pandas.py +599 -0
  98. investing_algorithm_framework/infrastructure/database/__init__.py +6 -2
  99. investing_algorithm_framework/infrastructure/database/sql_alchemy.py +81 -0
  100. investing_algorithm_framework/infrastructure/models/__init__.py +0 -13
  101. investing_algorithm_framework/infrastructure/models/order/order.py +9 -3
  102. investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +27 -8
  103. investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +21 -7
  104. investing_algorithm_framework/infrastructure/order_executors/__init__.py +2 -0
  105. investing_algorithm_framework/infrastructure/order_executors/backtest_oder_executor.py +28 -0
  106. investing_algorithm_framework/infrastructure/repositories/repository.py +16 -2
  107. investing_algorithm_framework/infrastructure/repositories/trade_repository.py +2 -2
  108. investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +6 -0
  109. investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +6 -0
  110. investing_algorithm_framework/infrastructure/services/__init__.py +0 -4
  111. investing_algorithm_framework/services/__init__.py +105 -8
  112. investing_algorithm_framework/services/backtesting/backtest_service.py +536 -476
  113. investing_algorithm_framework/services/configuration_service.py +14 -4
  114. investing_algorithm_framework/services/data_providers/__init__.py +5 -0
  115. investing_algorithm_framework/services/data_providers/data_provider_service.py +850 -0
  116. investing_algorithm_framework/{app/reporting → services}/metrics/__init__.py +48 -17
  117. investing_algorithm_framework/{app/reporting → services}/metrics/drawdown.py +10 -10
  118. investing_algorithm_framework/{app/reporting → services}/metrics/equity_curve.py +2 -2
  119. investing_algorithm_framework/{app/reporting → services}/metrics/exposure.py +60 -2
  120. investing_algorithm_framework/services/metrics/generate.py +358 -0
  121. investing_algorithm_framework/{app/reporting → services}/metrics/profit_factor.py +36 -0
  122. investing_algorithm_framework/{app/reporting → services}/metrics/recovery.py +2 -2
  123. investing_algorithm_framework/{app/reporting → services}/metrics/returns.py +146 -147
  124. investing_algorithm_framework/services/metrics/risk_free_rate.py +28 -0
  125. investing_algorithm_framework/{app/reporting/metrics/sharp_ratio.py → services/metrics/sharpe_ratio.py} +6 -10
  126. investing_algorithm_framework/{app/reporting → services}/metrics/sortino_ratio.py +3 -7
  127. investing_algorithm_framework/services/metrics/trades.py +500 -0
  128. investing_algorithm_framework/services/metrics/volatility.py +97 -0
  129. investing_algorithm_framework/{app/reporting → services}/metrics/win_rate.py +70 -3
  130. investing_algorithm_framework/services/order_service/order_backtest_service.py +21 -31
  131. investing_algorithm_framework/services/order_service/order_service.py +9 -71
  132. investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +0 -2
  133. investing_algorithm_framework/services/portfolios/portfolio_service.py +3 -13
  134. investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +62 -96
  135. investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +0 -3
  136. investing_algorithm_framework/services/repository_service.py +5 -2
  137. investing_algorithm_framework/services/trade_order_evaluator/__init__.py +9 -0
  138. investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +113 -0
  139. investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +51 -0
  140. investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +80 -0
  141. investing_algorithm_framework/services/trade_service/__init__.py +7 -1
  142. investing_algorithm_framework/services/trade_service/trade_service.py +51 -29
  143. investing_algorithm_framework/services/trade_service/trade_stop_loss_service.py +39 -0
  144. investing_algorithm_framework/services/trade_service/trade_take_profit_service.py +41 -0
  145. investing_algorithm_framework-7.19.15.dist-info/METADATA +537 -0
  146. {investing_algorithm_framework-6.9.1.dist-info → investing_algorithm_framework-7.19.15.dist-info}/RECORD +159 -148
  147. investing_algorithm_framework/app/reporting/evaluation.py +0 -243
  148. investing_algorithm_framework/app/reporting/metrics/risk_free_rate.py +0 -8
  149. investing_algorithm_framework/app/reporting/metrics/volatility.py +0 -69
  150. investing_algorithm_framework/cli/templates/requirements_azure_function.txt.template +0 -3
  151. investing_algorithm_framework/domain/models/backtesting/__init__.py +0 -9
  152. investing_algorithm_framework/domain/models/backtesting/backtest_date_range.py +0 -47
  153. investing_algorithm_framework/domain/models/backtesting/backtest_position.py +0 -120
  154. investing_algorithm_framework/domain/models/backtesting/backtest_reports_evaluation.py +0 -0
  155. investing_algorithm_framework/domain/models/backtesting/backtest_results.py +0 -440
  156. investing_algorithm_framework/domain/models/data_source.py +0 -21
  157. investing_algorithm_framework/domain/models/date_range.py +0 -64
  158. investing_algorithm_framework/domain/models/trade/trade_risk_type.py +0 -34
  159. investing_algorithm_framework/domain/models/trading_data_types.py +0 -48
  160. investing_algorithm_framework/domain/models/trading_time_frame.py +0 -223
  161. investing_algorithm_framework/domain/services/market_data_sources.py +0 -543
  162. investing_algorithm_framework/domain/services/market_service.py +0 -153
  163. investing_algorithm_framework/domain/services/observable.py +0 -51
  164. investing_algorithm_framework/domain/services/observer.py +0 -19
  165. investing_algorithm_framework/infrastructure/models/market_data_sources/__init__.py +0 -16
  166. investing_algorithm_framework/infrastructure/models/market_data_sources/ccxt.py +0 -746
  167. investing_algorithm_framework/infrastructure/models/market_data_sources/csv.py +0 -270
  168. investing_algorithm_framework/infrastructure/models/market_data_sources/pandas.py +0 -312
  169. investing_algorithm_framework/infrastructure/services/market_service/__init__.py +0 -5
  170. investing_algorithm_framework/infrastructure/services/market_service/ccxt_market_service.py +0 -471
  171. investing_algorithm_framework/infrastructure/services/performance_service/__init__.py +0 -7
  172. investing_algorithm_framework/infrastructure/services/performance_service/backtest_performance_service.py +0 -2
  173. investing_algorithm_framework/infrastructure/services/performance_service/performance_service.py +0 -322
  174. investing_algorithm_framework/services/market_data_source_service/__init__.py +0 -10
  175. investing_algorithm_framework/services/market_data_source_service/backtest_market_data_source_service.py +0 -269
  176. investing_algorithm_framework/services/market_data_source_service/data_provider_service.py +0 -350
  177. investing_algorithm_framework/services/market_data_source_service/market_data_source_service.py +0 -377
  178. investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -296
  179. investing_algorithm_framework-6.9.1.dist-info/METADATA +0 -440
  180. /investing_algorithm_framework/{app/reporting → services}/metrics/alpha.py +0 -0
  181. /investing_algorithm_framework/{app/reporting → services}/metrics/beta.py +0 -0
  182. /investing_algorithm_framework/{app/reporting → services}/metrics/cagr.py +0 -0
  183. /investing_algorithm_framework/{app/reporting → services}/metrics/calmar_ratio.py +0 -0
  184. /investing_algorithm_framework/{app/reporting → services}/metrics/mean_daily_return.py +0 -0
  185. /investing_algorithm_framework/{app/reporting → services}/metrics/price_efficiency.py +0 -0
  186. /investing_algorithm_framework/{app/reporting → services}/metrics/standard_deviation.py +0 -0
  187. /investing_algorithm_framework/{app/reporting → services}/metrics/treynor_ratio.py +0 -0
  188. /investing_algorithm_framework/{app/reporting → services}/metrics/ulcer.py +0 -0
  189. /investing_algorithm_framework/{app/reporting → services}/metrics/value_at_risk.py +0 -0
  190. {investing_algorithm_framework-6.9.1.dist-info → investing_algorithm_framework-7.19.15.dist-info}/LICENSE +0 -0
  191. {investing_algorithm_framework-6.9.1.dist-info → investing_algorithm_framework-7.19.15.dist-info}/WHEEL +0 -0
  192. {investing_algorithm_framework-6.9.1.dist-info → investing_algorithm_framework-7.19.15.dist-info}/entry_points.txt +0 -0
@@ -1,471 +0,0 @@
1
- import logging
2
- from datetime import datetime
3
- from time import sleep
4
- from typing import Dict
5
-
6
- import ccxt
7
- import polars as pl
8
- from dateutil import parser
9
-
10
- from investing_algorithm_framework.domain import OperationalException, Order, \
11
- MarketService, DATETIME_FORMAT
12
-
13
- logger = logging.getLogger(__name__)
14
-
15
-
16
- class CCXTMarketService(MarketService):
17
- """
18
- Market service implementation using the CCXT library
19
- """
20
- msec = 1000
21
- minute = 60 * msec
22
-
23
- def __init__(self, market_credential_service):
24
- super(CCXTMarketService, self).__init__(
25
- market_credential_service=market_credential_service,
26
- )
27
-
28
- @property
29
- def config(self):
30
- return self._config
31
-
32
- @config.setter
33
- def config(self, config):
34
- self._config = config
35
-
36
- def initialize_exchange(self, market, market_credential):
37
- market = market.lower()
38
- if not hasattr(ccxt, market):
39
- raise OperationalException(
40
- f"No market service found for market id {market}"
41
- )
42
-
43
- exchange_class = getattr(ccxt, market)
44
-
45
- if exchange_class is None:
46
- raise OperationalException(
47
- f"No market service found for market id {market}"
48
- )
49
-
50
- if market_credential is not None:
51
- exchange = exchange_class({
52
- 'apiKey': market_credential.api_key,
53
- 'secret': market_credential.secret_key,
54
- })
55
- else:
56
- exchange = exchange_class({})
57
-
58
- return exchange
59
-
60
- def pair_exists(self, target_symbol: str, trading_symbol: str, market):
61
- market_credential = self.get_market_credential(market)
62
- exchange = self.initialize_exchange(market, market_credential)
63
-
64
- if not exchange.has['fetchTicker']:
65
- raise OperationalException(
66
- f"Market service {market} does not support "
67
- f"functionality pair_exists"
68
- )
69
-
70
- symbol = f"{target_symbol.upper()}/{trading_symbol.upper()}"
71
- try:
72
- data = exchange.fetchTicker(symbol)
73
- return "symbol" in data
74
- except OperationalException:
75
- return False
76
-
77
- def get_ticker(self, symbol, market):
78
- market_credential = self.get_market_credential(market)
79
- exchange = self.initialize_exchange(market, market_credential)
80
-
81
- if not exchange.has['fetchTicker']:
82
- raise OperationalException(
83
- f"Market service {market} does not support "
84
- f"functionality get_ticker"
85
- )
86
-
87
- try:
88
- return exchange.fetchTicker(symbol)
89
- except Exception as e:
90
- logger.exception(e)
91
- raise OperationalException(
92
- f"Could not retrieve ticker for symbol {symbol}"
93
- )
94
-
95
- def get_tickers(self, symbols, market):
96
- market_credential = self.get_market_credential(market)
97
- exchange = self.initialize_exchange(market, market_credential)
98
-
99
- if not exchange.has['fetchTickers']:
100
- raise OperationalException(
101
- f"Market service {market} does not support "
102
- f"functionality get_tickers"
103
- )
104
-
105
- try:
106
- return exchange.fetchTickers(symbols)
107
- except Exception as e:
108
- logger.exception(e)
109
- raise OperationalException(
110
- "Could not retrieve selection of tickers"
111
- )
112
-
113
- def get_order_book(self, symbol, market):
114
- market_credential = self.get_market_credential(market)
115
- exchange = self.initialize_exchange(market, market_credential)
116
-
117
- if not exchange.has['fetchOrderBook']:
118
- raise OperationalException(
119
- f"Market service {market} does not support "
120
- f"functionality get_order_book"
121
- )
122
-
123
- try:
124
- return exchange.fetchOrderBook(symbol)
125
- except Exception as e:
126
- logger.exception(e)
127
- raise OperationalException("Could not retrieve order book")
128
-
129
- def get_order_books(self, symbols, market):
130
- data = {}
131
-
132
- for symbol in symbols:
133
- try:
134
- entry = self.get_order_book(symbol, market)
135
- del entry['symbol']
136
- data[symbol] = entry
137
- except Exception as e:
138
- logger.exception(e)
139
-
140
- return data
141
-
142
- def get_order(self, order, market):
143
- market_credential = self.get_market_credential(market)
144
- exchange = self.initialize_exchange(market, market_credential)
145
- symbol = f"{order.target_symbol.upper()}/" \
146
- f"{order.trading_symbol.upper()}"
147
-
148
- if not exchange.has['fetchOrder']:
149
- raise OperationalException(
150
- f"Market service {market} does not support "
151
- f"functionality get_order"
152
- )
153
-
154
- try:
155
- order = exchange.fetchOrder(order.external_id, symbol)
156
- return Order.from_ccxt_order(order)
157
- except Exception as e:
158
- logger.exception(e)
159
- raise OperationalException("Could not retrieve order")
160
-
161
- def get_orders(self, symbol, market, since: datetime = None):
162
- market_credential = self.get_market_credential(market)
163
- exchange = self.initialize_exchange(market, market_credential)
164
-
165
- if self.config is not None and "DATETIME_FORMAT" in self.config:
166
- datetime_format = self.config["DATETIME_FORMAT"]
167
- else:
168
- datetime_format = DATETIME_FORMAT
169
-
170
- if not exchange.has['fetchOrders']:
171
- raise OperationalException(
172
- f"Market service {market} does not support "
173
- f"functionality get_orders"
174
- )
175
-
176
- if since is not None:
177
- since = exchange.parse8601(datetime_format)
178
-
179
- try:
180
- ccxt_orders = exchange.fetchOrders(symbol, since=since)
181
- return [Order.from_ccxt_order(order) for order in ccxt_orders]
182
- except Exception as e:
183
- logger.exception(e)
184
- raise OperationalException("Could not retrieve orders")
185
- else:
186
- try:
187
- ccxt_orders = exchange.fetchOrders(symbol)
188
- return [Order.from_ccxt_order(order) for order in ccxt_orders]
189
- except Exception as e:
190
- logger.exception(e)
191
- raise OperationalException("Could not retrieve orders")
192
-
193
- def get_balance(self, market) -> Dict[str, float]:
194
- market_credential = self.get_market_credential(market)
195
-
196
- if market_credential is None:
197
- raise OperationalException(
198
- f"You don't have a market credential for market {market}"
199
- )
200
-
201
- exchange = self.initialize_exchange(market, market_credential)
202
-
203
- if not exchange.has['fetchBalance']:
204
- raise OperationalException(
205
- f"Market service {market} does not support "
206
- f"functionality get_balance"
207
- )
208
-
209
- try:
210
- return exchange.fetchBalance()["free"]
211
- except Exception as e:
212
- logger.exception(e)
213
- raise OperationalException(
214
- f"Please make sure you have "
215
- f"registered a valid market credential "
216
- f"object to the app: {str(e)}"
217
- )
218
-
219
- def create_limit_buy_order(
220
- self,
221
- target_symbol: str,
222
- trading_symbol: str,
223
- amount: float,
224
- price: float,
225
- market
226
- ):
227
- market_credential = self.get_market_credential(market)
228
- exchange = self.initialize_exchange(market, market_credential)
229
-
230
- if not exchange.has['createLimitBuyOrder']:
231
- raise OperationalException(
232
- f"Market service {market} does not support "
233
- f"functionality create_limit_buy_order"
234
- )
235
-
236
- symbol = f"{target_symbol.upper()}/{trading_symbol.upper()}"
237
-
238
- try:
239
- order = exchange.createLimitBuyOrder(
240
- symbol, amount, price
241
- )
242
- return Order.from_ccxt_order(order)
243
- except Exception as e:
244
- logger.exception(e)
245
- raise OperationalException("Could not create limit buy order")
246
-
247
- def create_limit_sell_order(
248
- self,
249
- target_symbol: str,
250
- trading_symbol: str,
251
- amount: float,
252
- price: float,
253
- market
254
- ):
255
- market_credential = self.get_market_credential(market)
256
- exchange = self.initialize_exchange(market, market_credential)
257
-
258
- if not exchange.has['createLimitSellOrder']:
259
- raise OperationalException(
260
- f"Market service {market} does not support "
261
- f"functionality create_limit_sell_order"
262
- )
263
-
264
- symbol = f"{target_symbol.upper()}/{trading_symbol.upper()}"
265
-
266
- try:
267
- order = exchange.createLimitSellOrder(
268
- symbol, amount, price
269
- )
270
- return Order.from_ccxt_order(order)
271
- except Exception as e:
272
- logger.exception(e)
273
- raise OperationalException("Could not create limit sell order")
274
-
275
- def create_market_sell_order(
276
- self,
277
- target_symbol: str,
278
- trading_symbol: str,
279
- amount: float,
280
- market
281
- ):
282
- market_credential = self.get_market_credential(market)
283
- exchange = self.initialize_exchange(market, market_credential)
284
-
285
- if not exchange.has['createMarketSellOrder']:
286
- raise OperationalException(
287
- f"Market service {market} does not support "
288
- f"functionality create_market_sell_order"
289
- )
290
-
291
- symbol = f"{target_symbol.upper()}/{trading_symbol.upper()}"
292
-
293
- try:
294
- order = exchange.createMarketSellOrder(symbol, amount)
295
- return Order.from_ccxt_order(order)
296
- except Exception as e:
297
- logger.exception(e)
298
- raise OperationalException("Could not create market sell order")
299
-
300
- def cancel_order(self, order, market):
301
- market_credential = self.get_market_credential(market)
302
- exchange = self.initialize_exchange(market, market_credential)
303
-
304
- if not exchange.has['cancelOrder']:
305
- raise OperationalException(
306
- f"Market service {market} does not support "
307
- f"functionality cancel_order"
308
- )
309
-
310
- exchange.cancelOrder(
311
- order.get_order_reference(),
312
- f"{order.get_target_symbol()}/{order.get_trading_symbol()}")
313
-
314
- def get_open_orders(
315
- self, market, target_symbol: str = None, trading_symbol: str = None
316
- ):
317
- market_credential = self.get_market_credential(market)
318
- exchange = self.initialize_exchange(market, market_credential)
319
-
320
- if not exchange.has['fetchOpenOrders']:
321
- raise OperationalException(
322
- f"Market service {market} does not support "
323
- f"functionality get_open_orders"
324
- )
325
-
326
- try:
327
- if target_symbol is None or trading_symbol is None:
328
- return exchange.fetchOpenOrders()
329
-
330
- symbol = f"{target_symbol.upper()}/{trading_symbol.upper()}"
331
- ccxt_orders = exchange.fetchOpenOrders(symbol)
332
- return [Order.from_ccxt_order(order) for order in ccxt_orders]
333
- except Exception as e:
334
- logger.exception(e)
335
- raise OperationalException("Could not retrieve open orders")
336
-
337
- def get_closed_orders(
338
- self, market, target_symbol: str = None, trading_symbol: str = None
339
- ):
340
- market_credential = self.get_market_credential(market)
341
- exchange = self.initialize_exchange(market, market_credential)
342
-
343
- if not exchange.has['fetchClosedOrders']:
344
- raise OperationalException(
345
- f"Market service {market} does not support "
346
- f"functionality get_closed_orders"
347
- )
348
-
349
- try:
350
- if target_symbol is None or trading_symbol is None:
351
- return exchange.fetchClosedOrders()
352
-
353
- symbol = f"{target_symbol.upper()}/{trading_symbol.upper()}"
354
- ccxt_orders = exchange.fetchClosedOrders(symbol)
355
- return [Order.from_ccxt_order(order) for order in ccxt_orders]
356
- except Exception as e:
357
- logger.exception(e)
358
- raise OperationalException("Could not retrieve closed orders")
359
-
360
- def get_ohlcv(
361
- self, symbol, time_frame, from_timestamp, market, to_timestamp=None
362
- ) -> pl.DataFrame:
363
- """
364
- Function to retrieve ohlcv data for a symbol, time frame and market
365
-
366
- Args:
367
- symbol (str): The symbol to retrieve ohlcv data for
368
- time_frame: The time frame to retrieve ohlcv data for
369
- from_timestamp: The start date to retrieve ohlcv data from
370
- market: The market to retrieve ohlcv data from
371
- to_timestamp: The end date to retrieve ohlcv data to
372
-
373
- Returns:
374
- DataFrame: The ohlcv data for the symbol, time frame and market
375
- in polars DataFrame format
376
- """
377
-
378
- if self.config is not None and "DATETIME_FORMAT" in self.config:
379
- datetime_format = self.config["DATETIME_FORMAT"]
380
- else:
381
- datetime_format = DATETIME_FORMAT
382
-
383
- market_credential = self.get_market_credential(market)
384
- exchange = self.initialize_exchange(market, market_credential)
385
-
386
- if not exchange.has['fetchOHLCV']:
387
- raise OperationalException(
388
- f"Market service {market} does not support "
389
- f"functionality get_ohclvs"
390
- )
391
-
392
- from_time_stamp = exchange.parse8601(
393
- from_timestamp.strftime(datetime_format)
394
- )
395
-
396
- if to_timestamp is None:
397
- to_timestamp = exchange.milliseconds()
398
- else:
399
- to_timestamp = exchange.parse8601(
400
- to_timestamp.strftime(datetime_format)
401
- )
402
- data = []
403
-
404
- while from_time_stamp < to_timestamp:
405
- ohlcv = exchange.fetch_ohlcv(symbol, time_frame, from_time_stamp)
406
-
407
- if len(ohlcv) > 0:
408
- from_time_stamp = \
409
- ohlcv[-1][0] + exchange.parse_timeframe(time_frame) * 1000
410
- else:
411
- from_time_stamp = to_timestamp
412
-
413
- for candle in ohlcv:
414
- datetime_stamp = parser.parse(exchange.iso8601(candle[0]))
415
-
416
- to_timestamp_datetime = parser.parse(
417
- exchange.iso8601(to_timestamp),
418
- )
419
-
420
- if datetime_stamp <= to_timestamp_datetime:
421
- datetime_stamp = datetime_stamp\
422
- .strftime(datetime_format)
423
-
424
- data.append(
425
- [datetime_stamp] +
426
- [float(value) for value in candle[1:]]
427
- )
428
-
429
- sleep(exchange.rateLimit / 1000)
430
-
431
- # Predefined column names
432
- col_names = ["Datetime", "Open", "High", "Low", "Close", "Volume"]
433
-
434
- # Combine the Series into a DataFrame with given column names
435
- df = pl.DataFrame(data, schema=col_names, orient="row")
436
- return df
437
-
438
- def get_ohlcvs(
439
- self,
440
- symbols,
441
- time_frame,
442
- from_timestamp,
443
- market,
444
- to_timestamp=None
445
- ) -> Dict[str, pl.DataFrame]:
446
- ohlcvs = {}
447
-
448
- for symbol in symbols:
449
-
450
- try:
451
- ohlcvs[symbol] = self.get_ohlcv(
452
- symbol=symbol,
453
- time_frame=time_frame,
454
- from_timestamp=from_timestamp,
455
- to_timestamp=to_timestamp,
456
- market=market
457
- )
458
- except Exception as e:
459
- logger.exception(e)
460
- logger.error(f"Could not retrieve ohlcv data for {symbol}")
461
-
462
- return ohlcvs
463
-
464
- def get_symbols(self, market):
465
- """
466
- Get all available symbols for a given market
467
- """
468
- market_credential = self.get_market_credential(market)
469
- exchange = self.initialize_exchange(market, market_credential)
470
- market_information = exchange.load_markets()
471
- return list(market_information.keys())
@@ -1,7 +0,0 @@
1
- from .backtest_performance_service import BacktestPerformanceService
2
- from .performance_service import PerformanceService
3
-
4
- __all__ = [
5
- "PerformanceService",
6
- "BacktestPerformanceService"
7
- ]
@@ -1,2 +0,0 @@
1
- class BacktestPerformanceService:
2
- pass