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,410 +0,0 @@
1
- import logging
2
- from typing import List
3
-
4
- from investing_algorithm_framework.domain import OrderStatus, OrderFee, \
5
- Position, Order, Portfolio, OrderType, OrderSide, ApiException
6
-
7
- logger = logging.getLogger(__name__)
8
-
9
-
10
- class Algorithm:
11
-
12
- def __init__(
13
- self,
14
- portfolio_configuration_service,
15
- portfolio_service,
16
- position_service,
17
- order_service,
18
- market_service,
19
- market_data_service,
20
- strategy_orchestrator_service
21
- ):
22
- self.portfolio_service = portfolio_service
23
- self.position_service = position_service
24
- self.order_service = order_service
25
- self.market_service = market_service
26
- self._config = None
27
- self.portfolio_configuration_service = portfolio_configuration_service
28
- self.strategy_orchestrator_service = strategy_orchestrator_service
29
- self.market_data_service = market_data_service
30
-
31
- def start(self, number_of_iterations=None, stateless=False):
32
-
33
- if not stateless:
34
- self.strategy_orchestrator_service.start(
35
- algorithm=self,
36
- number_of_iterations=number_of_iterations
37
- )
38
-
39
- @property
40
- def config(self):
41
- return self._config
42
-
43
- @config.setter
44
- def config(self, config):
45
- self._config = config
46
-
47
- @property
48
- def running(self) -> bool:
49
- return self.strategy_orchestrator_service.running
50
-
51
- def run_jobs(self):
52
- self.strategy_orchestrator_service.run_pending_jobs()
53
-
54
- def create_order(
55
- self,
56
- target_symbol,
57
- price,
58
- type,
59
- side,
60
- amount,
61
- market=None,
62
- execute=True,
63
- validate=True,
64
- sync=True
65
- ):
66
- portfolio = self.portfolio_service.find({"market": market})
67
- return self.order_service.create(
68
- {
69
- "target_symbol": target_symbol,
70
- "price": price,
71
- "amount": amount,
72
- "type": type,
73
- "side": side,
74
- "portfolio_id": portfolio.id,
75
- "status": OrderStatus.CREATED.value,
76
- "trading_symbol": portfolio.trading_symbol,
77
- },
78
- execute=execute,
79
- validate=validate,
80
- sync=sync
81
- )
82
-
83
- def create_limit_order(
84
- self,
85
- target_symbol,
86
- price,
87
- side,
88
- amount=None,
89
- percentage_of_portfolio=None,
90
- percentage_of_position=None,
91
- market=None,
92
- execute=True,
93
- validate=True,
94
- sync=True
95
- ):
96
- portfolio = self.portfolio_service.find({"market": market})
97
-
98
- if percentage_of_portfolio is not None and OrderSide.BUY.equals(side):
99
- size = portfolio.net_size * (percentage_of_portfolio / 100)
100
- amount = size / price
101
-
102
- if percentage_of_position is not None and OrderSide.SELL.equals(side):
103
- position = self.position_service.find(
104
- {
105
- "symbol": target_symbol,
106
- "portfolio": portfolio.id
107
- }
108
- )
109
- amount = position.amount * (percentage_of_position / 100)
110
-
111
- return self.order_service.create(
112
- {
113
- "target_symbol": target_symbol,
114
- "price": price,
115
- "amount": amount,
116
- "type": OrderType.LIMIT.value,
117
- "side": OrderSide.from_value(side).value,
118
- "portfolio_id": portfolio.id,
119
- "status": OrderStatus.CREATED.value,
120
- "trading_symbol": portfolio.trading_symbol,
121
- },
122
- execute=execute,
123
- validate=validate,
124
- sync=sync
125
- )
126
-
127
- def create_market_order(
128
- self,
129
- target_symbol,
130
- side,
131
- amount,
132
- market=None,
133
- execute=False,
134
- validate=False,
135
- sync=True
136
- ):
137
- portfolio = self.portfolio_service.find({"market": market})
138
- return self.order_service.create(
139
- {
140
- "target_symbol": target_symbol,
141
- "amount": amount,
142
- "type": OrderType.MARKET.value,
143
- "side": OrderSide.from_value(side).value,
144
- "portfolio_id": portfolio.id,
145
- "status": OrderStatus.CREATED.value,
146
- "trading_symbol": portfolio.trading_symbol,
147
- },
148
- execute=execute,
149
- validate=validate,
150
- sync=sync
151
- )
152
-
153
- def get_portfolio(self, market=None) -> Portfolio:
154
-
155
- if market is None:
156
- return self.portfolio_service.find({})
157
-
158
- return self.portfolio_service.find({{"market": market}})
159
-
160
- def get_unallocated(self, market=None) -> Position:
161
-
162
- if market:
163
- portfolio = self.portfolio_service.find({{"market": market}})
164
- else:
165
- portfolio = self.portfolio_service.find({})
166
-
167
- trading_symbol = portfolio.trading_symbol
168
- return self.position_service.find(
169
- {"portfolio": portfolio.id, "symbol": trading_symbol}
170
- ).amount
171
-
172
- def reset(self):
173
- self._workers = []
174
- self._running_workers = []
175
-
176
- def get_order(
177
- self,
178
- reference_id=None,
179
- market=None,
180
- target_symbol=None,
181
- trading_symbol=None,
182
- side=None,
183
- type=None
184
- ) -> Order:
185
- query_params = {}
186
-
187
- if reference_id:
188
- query_params["reference_id"] = reference_id
189
-
190
- if target_symbol:
191
- query_params["target_symbol"] = target_symbol
192
-
193
- if trading_symbol:
194
- query_params["trading_symbol"] = trading_symbol
195
-
196
- if side:
197
- query_params["side"] = side
198
-
199
- if type:
200
- query_params["type"] = type
201
-
202
- if market:
203
- portfolio = self.portfolio_service.find({"market": market})
204
- positions = self.position_service.get_all(
205
- {"portfolio": portfolio.id}
206
- )
207
- query_params["position"] = [position.id for position in positions]
208
-
209
- return self.order_service.find(query_params)
210
-
211
- def get_orders(
212
- self,
213
- target_symbol=None,
214
- status=None,
215
- type=None,
216
- side=None,
217
- market=None
218
- ) -> List[Order]:
219
-
220
- if market is None:
221
- portfolio = self.portfolio_service.get_all()[0]
222
- else:
223
- portfolio = self.portfolio_service.find({"market": market})
224
-
225
- positions = self.position_service.get_all({"portfolio": portfolio.id})
226
- return self.order_service.get_all(
227
- {
228
- "position": [position.id for position in positions],
229
- "target_symbol": target_symbol,
230
- "status": status,
231
- "type": type,
232
- "side": side
233
- }
234
- )
235
-
236
- def get_order_fee(self, order_id) -> OrderFee:
237
- return self.order_service.get_order_fee(order_id)
238
-
239
- def get_positions(self, market=None, identifier=None) -> List[Position]:
240
- query_params = {}
241
-
242
- if market is not None:
243
- query_params["market"] = market
244
-
245
- if identifier is not None:
246
- query_params["identifier"] = identifier
247
-
248
- portfolios = self.portfolio_service.get_all(query_params)
249
-
250
- if not portfolios:
251
- raise ApiException("No portfolio found.")
252
-
253
- portfolio = portfolios[0]
254
- return self.position_service.get_all(
255
- {"portfolio": portfolio.id}
256
- )
257
-
258
- def get_position(self, symbol, market=None, identifier=None) -> Position:
259
- query_params = {}
260
-
261
- if market is not None:
262
- query_params["market"] = market
263
-
264
- if identifier is not None:
265
- query_params["identifier"] = identifier
266
-
267
- portfolios = self.portfolio_service.get_all(query_params)
268
-
269
- if not portfolios:
270
- raise ApiException("No portfolio found.")
271
-
272
- portfolio = portfolios[0]
273
-
274
- try:
275
- return self.position_service.find(
276
- {"portfolio": portfolio.id, "symbol": symbol}
277
- )
278
- except ApiException:
279
- return None
280
-
281
- def position_exists(self, symbol, market=None, identifier=None) -> bool:
282
- query_params = {}
283
-
284
- if market is not None:
285
- query_params["market"] = market
286
-
287
- if identifier is not None:
288
- query_params["identifier"] = identifier
289
-
290
- query_params["symbol"] = symbol
291
- return self.position_service.exists(query_params)
292
-
293
- def get_position_percentage(
294
- self, symbol, market=None, identifier=None
295
- ) -> float:
296
- query_params = {}
297
-
298
- if market is not None:
299
- query_params["market"] = market
300
-
301
- if identifier is not None:
302
- query_params["identifier"] = identifier
303
-
304
- portfolios = self.portfolio_service.get_all(query_params)
305
-
306
- if not portfolios:
307
- raise ApiException("No portfolio found.")
308
-
309
- portfolio = portfolios[0]
310
- position = self.position_service.find(
311
- {"portfolio": portfolio.id, "symbol": symbol}
312
- )
313
- ticker = self.market_service.get_ticker(
314
- f"{symbol.upper()}/{portfolio.trading_symbol.upper()}"
315
- )
316
- return (position.amount * ticker["bid"] /
317
- self.get_allocated(identifier=portfolio.identifier)) * 100
318
-
319
- def close_position(self, symbol, market=None, identifier=None):
320
- query_params = {}
321
-
322
- if market is not None:
323
- query_params["market"] = market
324
-
325
- if identifier is not None:
326
- query_params["identifier"] = identifier
327
-
328
- position = self.get_position(symbol, market, identifier)
329
-
330
- if position is None:
331
- raise ApiException("No position found.")
332
-
333
- if position.amount == 0:
334
- return
335
-
336
- for order in self.order_service\
337
- .get_all({
338
- "position": position.id, "status": OrderStatus.OPEN.value
339
- }):
340
- self.order_service.cancel_order(order.id)
341
-
342
- portfolio = self.portfolio_service.find({"position": position.id})
343
- self.market_service.market = portfolio.market
344
- ticker = self.market_service.get_ticker(
345
- symbol=f"{symbol.upper()}/{portfolio.trading_symbol.upper()}"
346
- )
347
- self.create_limit_order(
348
- target_symbol=position.symbol,
349
- amount=position.amount,
350
- side=OrderSide.SELL.value,
351
- price=ticker["bid"],
352
- )
353
-
354
- def add_strategies(self, strategies):
355
- self.strategy_orchestrator_service.add_strategies(strategies)
356
-
357
- def add_tasks(self, tasks):
358
- self.strategy_orchestrator_service.add_tasks(tasks)
359
-
360
- def get_allocated(self, market=None, identifier=None) -> float:
361
-
362
- if self.portfolio_configuration_service.count() > 1 \
363
- and identifier is None and market is None:
364
- raise ApiException(
365
- "Multiple portfolios found. Please specify a "
366
- "portfolio identifier."
367
- )
368
-
369
- if market is not None and identifier is not None:
370
- portfolio_configurations = self.portfolio_configuration_service\
371
- .get_all()
372
-
373
- else:
374
- query_params = {
375
- "market": market,
376
- "identifier": identifier
377
- }
378
- portfolio_configurations = [self.portfolio_configuration_service
379
- .find(query_params)]
380
-
381
- portfolios = []
382
-
383
- for portfolio_configuration in portfolio_configurations:
384
- portfolio = self.portfolio_service.find(
385
- {"identifier": portfolio_configuration.identifier}
386
- )
387
- portfolio.configuration = portfolio_configuration
388
- portfolios.append(portfolio)
389
-
390
- allocated = 0
391
-
392
- for portfolio in portfolios:
393
- positions = self.position_service.get_all(
394
- {"portfolio": portfolio.id}
395
- )
396
-
397
- for position in positions:
398
- if portfolio.trading_symbol == position.symbol:
399
- continue
400
-
401
- symbol = f"{position.symbol.upper()}/" \
402
- f"{portfolio.trading_symbol.upper()}"
403
- self.market_service.initialize(portfolio.configuration)
404
- price = self.market_service.get_ticker(symbol)
405
- allocated = allocated + (position.amount * price["bid"])
406
-
407
- return allocated
408
-
409
- def get_portfolio_configurations(self):
410
- return self.portfolio_configuration_service.get_all()
@@ -1,11 +0,0 @@
1
- from .order_book import OrderBook
2
- from .ticker import Ticker
3
- from .ohlcv import OHLCV
4
- from .asset_price import AssetPrice
5
-
6
- __all__ = [
7
- "Ticker",
8
- "OrderBook",
9
- "OHLCV",
10
- "AssetPrice"
11
- ]
@@ -1,50 +0,0 @@
1
- from datetime import datetime
2
-
3
-
4
- class AssetPrice:
5
-
6
- def __init__(self, symbol, price, datetime):
7
- self.symbol = symbol
8
- self.price = price
9
- self.datetime = datetime
10
-
11
- def get_symbol(self):
12
- return self.symbol
13
-
14
- def get_price(self):
15
-
16
- if self.price is None:
17
- return 0
18
-
19
- return self.price
20
-
21
- def get_datetime(self):
22
-
23
- if self.datetime is None:
24
- return datetime.utcnow()
25
-
26
- return self.datetime
27
-
28
- def repr(self, **fields) -> str:
29
- """
30
- Helper for __repr__
31
- """
32
-
33
- field_strings = []
34
- at_least_one_attached_attribute = False
35
-
36
- for key, field in fields.items():
37
- field_strings.append(f'{key}={field!r}')
38
- at_least_one_attached_attribute = True
39
-
40
- if at_least_one_attached_attribute:
41
- return f"<{self.__class__.__name__}({','.join(field_strings)})>"
42
-
43
- return f"<{self.__class__.__name__} {id(self)}>"
44
-
45
- def __repr__(self):
46
- return self.repr(
47
- symbol=self.get_symbol(),
48
- price=self.price,
49
- datetime=self.datetime
50
- )
@@ -1,76 +0,0 @@
1
- from datetime import datetime
2
-
3
- import pandas as pd
4
-
5
-
6
- class OHLCV:
7
- DEFAULT_DATETIME_STRING = "%Y-%m-%dT%H:%M:%S.%f%z"
8
- COLUMNS = ["open", "high", "low", "close", "volume"]
9
-
10
- def __init__(self, symbol, data):
11
- self.symbol = symbol
12
- self.target_symbol = symbol.split("/")[0]
13
- self.trading_symbol = symbol.split("/")[1]
14
- self.data = data
15
-
16
- def get_symbol(self):
17
- return self.symbol
18
-
19
- def get_target_symbol(self):
20
- return self.target_symbol
21
-
22
- def get_trading_symbol(self):
23
- return self.trading_symbol
24
-
25
- def get_data(self):
26
- return self.data
27
-
28
- def to_dict(self, date_format="%Y-%m-%d-%H:%M:%S"):
29
- dict_data = {}
30
-
31
- for column in self.COLUMNS:
32
- dict_data[column] = []
33
-
34
- for row in self.get_data():
35
- date = datetime.strptime(row[0], self.DEFAULT_DATETIME_STRING)
36
- date = date.strftime(date_format)
37
- dict_data["open"].append(date)
38
- dict_data["high"].append(row[1])
39
- dict_data["low"].append(row[2])
40
- dict_data["close"].append(row[3])
41
- dict_data["volume"].append(row[4])
42
-
43
- return dict_data
44
-
45
- @staticmethod
46
- def from_dict(data):
47
- return OHLCV(
48
- symbol=data.get("symbol"),
49
- data=data.get("data"),
50
- )
51
-
52
- def repr(self, **fields) -> str:
53
- """
54
- Helper for __repr__
55
- """
56
-
57
- field_strings = []
58
- at_least_one_attached_attribute = False
59
-
60
- for key, field in fields.items():
61
- field_strings.append(f'{key}={field!r}')
62
- at_least_one_attached_attribute = True
63
-
64
- if at_least_one_attached_attribute:
65
- return f"<{self.__class__.__name__}({','.join(field_strings)})>"
66
-
67
- return f"<{self.__class__.__name__} {id(self)}>"
68
-
69
- def __repr__(self):
70
- return self.repr(
71
- symbol=self.get_symbol(),
72
- data=self.get_data()
73
- )
74
-
75
- def to_df(self):
76
- return pd.DataFrame(self.get_data(), columns=self.COLUMNS)
@@ -1,63 +0,0 @@
1
- from datetime import datetime
2
- from typing import List
3
-
4
-
5
- class OrderBook:
6
-
7
- def __init__(self, symbol, bids: List, asks: List, creation_date=None):
8
- self.symbol = symbol
9
- self.bids = bids
10
- self.asks = asks
11
-
12
- if creation_date is None:
13
- self.creation_date = datetime.now()
14
-
15
- def get_bids(self):
16
- return self.bids
17
-
18
- def get_asks(self):
19
- return self.asks
20
-
21
- def get_symbol(self):
22
- return self.symbol
23
-
24
- def to_dict(self):
25
-
26
- return {
27
- "symbol": self.symbol,
28
- "bids": self.bids,
29
- "asks": self.asks
30
- }
31
-
32
- @staticmethod
33
- def from_dict(data):
34
- return OrderBook(
35
- data.get("symbol"),
36
- data.get("bids"),
37
- data.get("asks"),
38
- data.get("creation_date")
39
- )
40
-
41
- def repr(self, **fields) -> str:
42
- """
43
- Helper for __repr__
44
- """
45
-
46
- field_strings = []
47
- at_least_one_attached_attribute = False
48
-
49
- for key, field in fields.items():
50
- field_strings.append(f'{key}={field!r}')
51
- at_least_one_attached_attribute = True
52
-
53
- if at_least_one_attached_attribute:
54
- return f"<{self.__class__.__name__}({','.join(field_strings)})>"
55
-
56
- return f"<{self.__class__.__name__} {id(self)}>"
57
-
58
- def __repr__(self):
59
- return self.repr(
60
- symbol=self.symbol,
61
- bids=self.bids,
62
- asks=self.asks
63
- )
@@ -1,92 +0,0 @@
1
- from datetime import datetime
2
-
3
-
4
- class Ticker:
5
-
6
- def __init__(
7
- self,
8
- symbol,
9
- price,
10
- ask_price=None,
11
- ask_volume=None,
12
- bid_price=None,
13
- bid_volume=None,
14
- high_price=None,
15
- low_price=None,
16
- creation_date=None
17
- ):
18
- self.symbol = symbol
19
- self.price = price
20
- self.ask_price = ask_price
21
- self.ask_volume = ask_volume
22
- self.bid_price = bid_price
23
- self.bid_volume = bid_volume
24
- self.high_price = high_price
25
- self.low_price = low_price
26
-
27
- if creation_date is None:
28
- self.creation_date = datetime.now()
29
-
30
- def get_price(self):
31
- return self.price
32
-
33
- def get_creation_date(self):
34
- return self.creation_date
35
-
36
- def get_symbol(self):
37
- return self.symbol
38
-
39
- def to_dict(self):
40
- return {
41
- "symbol": self.symbol,
42
- "price": self.price,
43
- "ask_price": self.ask_price,
44
- "ask_volume": self.ask_volume,
45
- "bid_price": self.bid_price,
46
- "bid_volume": self.bid_volume,
47
- "high_price": self.high_price,
48
- "low_price": self.low_price
49
- }
50
-
51
- @staticmethod
52
- def from_dict(data):
53
- return Ticker(
54
- symbol=data.get("symbol"),
55
- price=data.get("price"),
56
- ask_price=data.get("ask_price"),
57
- ask_volume=data.get("ask_volume"),
58
- bid_price=data.get("bid_price"),
59
- bid_volume=data.get("bid_volume"),
60
- high_price=data.get("high_price"),
61
- low_price=data.get("low_price"),
62
- creation_date=data.get("creation_date")
63
- )
64
-
65
- def repr(self, **fields) -> str:
66
- """
67
- Helper for __repr__
68
- """
69
-
70
- field_strings = []
71
- at_least_one_attached_attribute = False
72
-
73
- for key, field in fields.items():
74
- field_strings.append(f'{key}={field!r}')
75
- at_least_one_attached_attribute = True
76
-
77
- if at_least_one_attached_attribute:
78
- return f"<{self.__class__.__name__}({','.join(field_strings)})>"
79
-
80
- return f"<{self.__class__.__name__} {id(self)}>"
81
-
82
- def __repr__(self):
83
- return self.repr(
84
- symbol=self.symbol,
85
- price=self.price,
86
- ask_price=self.ask_price,
87
- ask_volume=self.ask_volume,
88
- bid_price=self.bid_price,
89
- bid_volume=self.bid_volume,
90
- high_price=self.high_price,
91
- low_price=self.low_price
92
- )