investing-algorithm-framework 7.19.14__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 (260) hide show
  1. investing_algorithm_framework/__init__.py +197 -0
  2. investing_algorithm_framework/app/__init__.py +47 -0
  3. investing_algorithm_framework/app/algorithm/__init__.py +7 -0
  4. investing_algorithm_framework/app/algorithm/algorithm.py +239 -0
  5. investing_algorithm_framework/app/algorithm/algorithm_factory.py +114 -0
  6. investing_algorithm_framework/app/analysis/__init__.py +15 -0
  7. investing_algorithm_framework/app/analysis/backtest_data_ranges.py +121 -0
  8. investing_algorithm_framework/app/analysis/backtest_utils.py +107 -0
  9. investing_algorithm_framework/app/analysis/permutation.py +116 -0
  10. investing_algorithm_framework/app/analysis/ranking.py +297 -0
  11. investing_algorithm_framework/app/app.py +2204 -0
  12. investing_algorithm_framework/app/app_hook.py +28 -0
  13. investing_algorithm_framework/app/context.py +1667 -0
  14. investing_algorithm_framework/app/eventloop.py +590 -0
  15. investing_algorithm_framework/app/reporting/__init__.py +27 -0
  16. investing_algorithm_framework/app/reporting/ascii.py +921 -0
  17. investing_algorithm_framework/app/reporting/backtest_report.py +349 -0
  18. investing_algorithm_framework/app/reporting/charts/__init__.py +19 -0
  19. investing_algorithm_framework/app/reporting/charts/entry_exist_signals.py +66 -0
  20. investing_algorithm_framework/app/reporting/charts/equity_curve.py +37 -0
  21. investing_algorithm_framework/app/reporting/charts/equity_curve_drawdown.py +74 -0
  22. investing_algorithm_framework/app/reporting/charts/line_chart.py +11 -0
  23. investing_algorithm_framework/app/reporting/charts/monthly_returns_heatmap.py +70 -0
  24. investing_algorithm_framework/app/reporting/charts/ohlcv_data_completeness.py +51 -0
  25. investing_algorithm_framework/app/reporting/charts/rolling_sharp_ratio.py +79 -0
  26. investing_algorithm_framework/app/reporting/charts/yearly_returns_barchart.py +55 -0
  27. investing_algorithm_framework/app/reporting/generate.py +185 -0
  28. investing_algorithm_framework/app/reporting/tables/__init__.py +11 -0
  29. investing_algorithm_framework/app/reporting/tables/key_metrics_table.py +217 -0
  30. investing_algorithm_framework/app/reporting/tables/stop_loss_table.py +0 -0
  31. investing_algorithm_framework/app/reporting/tables/time_metrics_table.py +80 -0
  32. investing_algorithm_framework/app/reporting/tables/trade_metrics_table.py +147 -0
  33. investing_algorithm_framework/app/reporting/tables/trades_table.py +75 -0
  34. investing_algorithm_framework/app/reporting/tables/utils.py +29 -0
  35. investing_algorithm_framework/app/reporting/templates/report_template.html.j2 +154 -0
  36. investing_algorithm_framework/app/stateless/__init__.py +35 -0
  37. investing_algorithm_framework/app/stateless/action_handlers/__init__.py +84 -0
  38. investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +8 -0
  39. investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +15 -0
  40. investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +40 -0
  41. investing_algorithm_framework/app/stateless/exception_handler.py +40 -0
  42. investing_algorithm_framework/app/strategy.py +675 -0
  43. investing_algorithm_framework/app/task.py +41 -0
  44. investing_algorithm_framework/app/web/__init__.py +5 -0
  45. investing_algorithm_framework/app/web/controllers/__init__.py +13 -0
  46. investing_algorithm_framework/app/web/controllers/orders.py +20 -0
  47. investing_algorithm_framework/app/web/controllers/portfolio.py +20 -0
  48. investing_algorithm_framework/app/web/controllers/positions.py +18 -0
  49. investing_algorithm_framework/app/web/create_app.py +20 -0
  50. investing_algorithm_framework/app/web/error_handler.py +59 -0
  51. investing_algorithm_framework/app/web/responses.py +20 -0
  52. investing_algorithm_framework/app/web/run_strategies.py +4 -0
  53. investing_algorithm_framework/app/web/schemas/__init__.py +12 -0
  54. investing_algorithm_framework/app/web/schemas/order.py +12 -0
  55. investing_algorithm_framework/app/web/schemas/portfolio.py +22 -0
  56. investing_algorithm_framework/app/web/schemas/position.py +15 -0
  57. investing_algorithm_framework/app/web/setup_cors.py +6 -0
  58. investing_algorithm_framework/cli/__init__.py +0 -0
  59. investing_algorithm_framework/cli/cli.py +207 -0
  60. investing_algorithm_framework/cli/deploy_to_aws_lambda.py +499 -0
  61. investing_algorithm_framework/cli/deploy_to_azure_function.py +718 -0
  62. investing_algorithm_framework/cli/initialize_app.py +603 -0
  63. investing_algorithm_framework/cli/templates/.gitignore.template +178 -0
  64. investing_algorithm_framework/cli/templates/app.py.template +18 -0
  65. investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +48 -0
  66. investing_algorithm_framework/cli/templates/app_azure_function.py.template +14 -0
  67. investing_algorithm_framework/cli/templates/app_web.py.template +18 -0
  68. investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +22 -0
  69. investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +92 -0
  70. investing_algorithm_framework/cli/templates/aws_lambda_readme.md.template +110 -0
  71. investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +2 -0
  72. investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +65 -0
  73. investing_algorithm_framework/cli/templates/azure_function_host.json.template +15 -0
  74. investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +8 -0
  75. investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +3 -0
  76. investing_algorithm_framework/cli/templates/data_providers.py.template +17 -0
  77. investing_algorithm_framework/cli/templates/env.example.template +2 -0
  78. investing_algorithm_framework/cli/templates/env_azure_function.example.template +4 -0
  79. investing_algorithm_framework/cli/templates/market_data_providers.py.template +9 -0
  80. investing_algorithm_framework/cli/templates/readme.md.template +135 -0
  81. investing_algorithm_framework/cli/templates/requirements.txt.template +2 -0
  82. investing_algorithm_framework/cli/templates/run_backtest.py.template +20 -0
  83. investing_algorithm_framework/cli/templates/strategy.py.template +124 -0
  84. investing_algorithm_framework/create_app.py +54 -0
  85. investing_algorithm_framework/dependency_container.py +155 -0
  86. investing_algorithm_framework/domain/__init__.py +148 -0
  87. investing_algorithm_framework/domain/backtesting/__init__.py +21 -0
  88. investing_algorithm_framework/domain/backtesting/backtest.py +503 -0
  89. investing_algorithm_framework/domain/backtesting/backtest_date_range.py +96 -0
  90. investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +242 -0
  91. investing_algorithm_framework/domain/backtesting/backtest_metrics.py +459 -0
  92. investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +275 -0
  93. investing_algorithm_framework/domain/backtesting/backtest_run.py +435 -0
  94. investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +162 -0
  95. investing_algorithm_framework/domain/backtesting/combine_backtests.py +280 -0
  96. investing_algorithm_framework/domain/config.py +111 -0
  97. investing_algorithm_framework/domain/constants.py +83 -0
  98. investing_algorithm_framework/domain/data_provider.py +334 -0
  99. investing_algorithm_framework/domain/data_structures.py +42 -0
  100. investing_algorithm_framework/domain/decimal_parsing.py +40 -0
  101. investing_algorithm_framework/domain/exceptions.py +112 -0
  102. investing_algorithm_framework/domain/models/__init__.py +43 -0
  103. investing_algorithm_framework/domain/models/app_mode.py +34 -0
  104. investing_algorithm_framework/domain/models/base_model.py +25 -0
  105. investing_algorithm_framework/domain/models/data/__init__.py +7 -0
  106. investing_algorithm_framework/domain/models/data/data_source.py +214 -0
  107. investing_algorithm_framework/domain/models/data/data_type.py +46 -0
  108. investing_algorithm_framework/domain/models/event.py +35 -0
  109. investing_algorithm_framework/domain/models/market/__init__.py +5 -0
  110. investing_algorithm_framework/domain/models/market/market_credential.py +88 -0
  111. investing_algorithm_framework/domain/models/order/__init__.py +6 -0
  112. investing_algorithm_framework/domain/models/order/order.py +384 -0
  113. investing_algorithm_framework/domain/models/order/order_side.py +36 -0
  114. investing_algorithm_framework/domain/models/order/order_status.py +37 -0
  115. investing_algorithm_framework/domain/models/order/order_type.py +30 -0
  116. investing_algorithm_framework/domain/models/portfolio/__init__.py +9 -0
  117. investing_algorithm_framework/domain/models/portfolio/portfolio.py +169 -0
  118. investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +93 -0
  119. investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +208 -0
  120. investing_algorithm_framework/domain/models/position/__init__.py +4 -0
  121. investing_algorithm_framework/domain/models/position/position.py +68 -0
  122. investing_algorithm_framework/domain/models/position/position_snapshot.py +47 -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 +153 -0
  126. investing_algorithm_framework/domain/models/time_interval.py +124 -0
  127. investing_algorithm_framework/domain/models/time_unit.py +149 -0
  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 +13 -0
  131. investing_algorithm_framework/domain/models/trade/trade.py +388 -0
  132. investing_algorithm_framework/domain/models/trade/trade_risk_type.py +34 -0
  133. investing_algorithm_framework/domain/models/trade/trade_status.py +40 -0
  134. investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +267 -0
  135. investing_algorithm_framework/domain/models/trade/trade_take_profit.py +303 -0
  136. investing_algorithm_framework/domain/order_executor.py +112 -0
  137. investing_algorithm_framework/domain/portfolio_provider.py +118 -0
  138. investing_algorithm_framework/domain/positions/__init__.py +4 -0
  139. investing_algorithm_framework/domain/positions/position_size.py +41 -0
  140. investing_algorithm_framework/domain/services/__init__.py +11 -0
  141. investing_algorithm_framework/domain/services/market_credential_service.py +37 -0
  142. investing_algorithm_framework/domain/services/portfolios/__init__.py +5 -0
  143. investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +9 -0
  144. investing_algorithm_framework/domain/services/rounding_service.py +27 -0
  145. investing_algorithm_framework/domain/services/state_handler.py +38 -0
  146. investing_algorithm_framework/domain/stateless_actions.py +7 -0
  147. investing_algorithm_framework/domain/strategy.py +44 -0
  148. investing_algorithm_framework/domain/utils/__init__.py +27 -0
  149. investing_algorithm_framework/domain/utils/csv.py +104 -0
  150. investing_algorithm_framework/domain/utils/custom_tqdm.py +22 -0
  151. investing_algorithm_framework/domain/utils/dates.py +57 -0
  152. investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +19 -0
  153. investing_algorithm_framework/domain/utils/polars.py +53 -0
  154. investing_algorithm_framework/domain/utils/random.py +41 -0
  155. investing_algorithm_framework/domain/utils/signatures.py +17 -0
  156. investing_algorithm_framework/domain/utils/stoppable_thread.py +26 -0
  157. investing_algorithm_framework/domain/utils/synchronized.py +12 -0
  158. investing_algorithm_framework/download_data.py +108 -0
  159. investing_algorithm_framework/infrastructure/__init__.py +50 -0
  160. investing_algorithm_framework/infrastructure/data_providers/__init__.py +36 -0
  161. investing_algorithm_framework/infrastructure/data_providers/ccxt.py +1143 -0
  162. investing_algorithm_framework/infrastructure/data_providers/csv.py +568 -0
  163. investing_algorithm_framework/infrastructure/data_providers/pandas.py +599 -0
  164. investing_algorithm_framework/infrastructure/database/__init__.py +10 -0
  165. investing_algorithm_framework/infrastructure/database/sql_alchemy.py +120 -0
  166. investing_algorithm_framework/infrastructure/models/__init__.py +16 -0
  167. investing_algorithm_framework/infrastructure/models/decimal_parser.py +14 -0
  168. investing_algorithm_framework/infrastructure/models/model_extension.py +6 -0
  169. investing_algorithm_framework/infrastructure/models/order/__init__.py +4 -0
  170. investing_algorithm_framework/infrastructure/models/order/order.py +124 -0
  171. investing_algorithm_framework/infrastructure/models/order/order_metadata.py +44 -0
  172. investing_algorithm_framework/infrastructure/models/order_trade_association.py +10 -0
  173. investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +4 -0
  174. investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +37 -0
  175. investing_algorithm_framework/infrastructure/models/portfolio/sql_portfolio.py +114 -0
  176. investing_algorithm_framework/infrastructure/models/position/__init__.py +4 -0
  177. investing_algorithm_framework/infrastructure/models/position/position.py +63 -0
  178. investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +23 -0
  179. investing_algorithm_framework/infrastructure/models/trades/__init__.py +9 -0
  180. investing_algorithm_framework/infrastructure/models/trades/trade.py +130 -0
  181. investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +40 -0
  182. investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +41 -0
  183. investing_algorithm_framework/infrastructure/order_executors/__init__.py +21 -0
  184. investing_algorithm_framework/infrastructure/order_executors/backtest_oder_executor.py +28 -0
  185. investing_algorithm_framework/infrastructure/order_executors/ccxt_order_executor.py +200 -0
  186. investing_algorithm_framework/infrastructure/portfolio_providers/__init__.py +19 -0
  187. investing_algorithm_framework/infrastructure/portfolio_providers/ccxt_portfolio_provider.py +199 -0
  188. investing_algorithm_framework/infrastructure/repositories/__init__.py +21 -0
  189. investing_algorithm_framework/infrastructure/repositories/order_metadata_repository.py +17 -0
  190. investing_algorithm_framework/infrastructure/repositories/order_repository.py +96 -0
  191. investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +30 -0
  192. investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +56 -0
  193. investing_algorithm_framework/infrastructure/repositories/position_repository.py +66 -0
  194. investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +21 -0
  195. investing_algorithm_framework/infrastructure/repositories/repository.py +299 -0
  196. investing_algorithm_framework/infrastructure/repositories/trade_repository.py +71 -0
  197. investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +23 -0
  198. investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +23 -0
  199. investing_algorithm_framework/infrastructure/services/__init__.py +7 -0
  200. investing_algorithm_framework/infrastructure/services/aws/__init__.py +6 -0
  201. investing_algorithm_framework/infrastructure/services/aws/state_handler.py +113 -0
  202. investing_algorithm_framework/infrastructure/services/azure/__init__.py +5 -0
  203. investing_algorithm_framework/infrastructure/services/azure/state_handler.py +158 -0
  204. investing_algorithm_framework/services/__init__.py +132 -0
  205. investing_algorithm_framework/services/backtesting/__init__.py +5 -0
  206. investing_algorithm_framework/services/backtesting/backtest_service.py +651 -0
  207. investing_algorithm_framework/services/configuration_service.py +96 -0
  208. investing_algorithm_framework/services/data_providers/__init__.py +5 -0
  209. investing_algorithm_framework/services/data_providers/data_provider_service.py +850 -0
  210. investing_algorithm_framework/services/market_credential_service.py +40 -0
  211. investing_algorithm_framework/services/metrics/__init__.py +114 -0
  212. investing_algorithm_framework/services/metrics/alpha.py +0 -0
  213. investing_algorithm_framework/services/metrics/beta.py +0 -0
  214. investing_algorithm_framework/services/metrics/cagr.py +60 -0
  215. investing_algorithm_framework/services/metrics/calmar_ratio.py +40 -0
  216. investing_algorithm_framework/services/metrics/drawdown.py +181 -0
  217. investing_algorithm_framework/services/metrics/equity_curve.py +24 -0
  218. investing_algorithm_framework/services/metrics/exposure.py +210 -0
  219. investing_algorithm_framework/services/metrics/generate.py +358 -0
  220. investing_algorithm_framework/services/metrics/mean_daily_return.py +83 -0
  221. investing_algorithm_framework/services/metrics/price_efficiency.py +57 -0
  222. investing_algorithm_framework/services/metrics/profit_factor.py +165 -0
  223. investing_algorithm_framework/services/metrics/recovery.py +113 -0
  224. investing_algorithm_framework/services/metrics/returns.py +452 -0
  225. investing_algorithm_framework/services/metrics/risk_free_rate.py +28 -0
  226. investing_algorithm_framework/services/metrics/sharpe_ratio.py +137 -0
  227. investing_algorithm_framework/services/metrics/sortino_ratio.py +74 -0
  228. investing_algorithm_framework/services/metrics/standard_deviation.py +157 -0
  229. investing_algorithm_framework/services/metrics/trades.py +500 -0
  230. investing_algorithm_framework/services/metrics/treynor_ratio.py +0 -0
  231. investing_algorithm_framework/services/metrics/ulcer.py +0 -0
  232. investing_algorithm_framework/services/metrics/value_at_risk.py +0 -0
  233. investing_algorithm_framework/services/metrics/volatility.py +97 -0
  234. investing_algorithm_framework/services/metrics/win_rate.py +177 -0
  235. investing_algorithm_framework/services/order_service/__init__.py +9 -0
  236. investing_algorithm_framework/services/order_service/order_backtest_service.py +178 -0
  237. investing_algorithm_framework/services/order_service/order_executor_lookup.py +110 -0
  238. investing_algorithm_framework/services/order_service/order_service.py +826 -0
  239. investing_algorithm_framework/services/portfolios/__init__.py +16 -0
  240. investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +54 -0
  241. investing_algorithm_framework/services/portfolios/portfolio_configuration_service.py +75 -0
  242. investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +106 -0
  243. investing_algorithm_framework/services/portfolios/portfolio_service.py +188 -0
  244. investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +136 -0
  245. investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +182 -0
  246. investing_algorithm_framework/services/positions/__init__.py +7 -0
  247. investing_algorithm_framework/services/positions/position_service.py +210 -0
  248. investing_algorithm_framework/services/positions/position_snapshot_service.py +18 -0
  249. investing_algorithm_framework/services/repository_service.py +40 -0
  250. investing_algorithm_framework/services/trade_order_evaluator/__init__.py +9 -0
  251. investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +132 -0
  252. investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +66 -0
  253. investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +41 -0
  254. investing_algorithm_framework/services/trade_service/__init__.py +3 -0
  255. investing_algorithm_framework/services/trade_service/trade_service.py +1083 -0
  256. investing_algorithm_framework-7.19.14.dist-info/LICENSE +201 -0
  257. investing_algorithm_framework-7.19.14.dist-info/METADATA +459 -0
  258. investing_algorithm_framework-7.19.14.dist-info/RECORD +260 -0
  259. investing_algorithm_framework-7.19.14.dist-info/WHEEL +4 -0
  260. investing_algorithm_framework-7.19.14.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,41 @@
1
+ from investing_algorithm_framework.domain import \
2
+ TimeUnit
3
+
4
+
5
+ class Task:
6
+ time_unit: str = None
7
+ interval: int = None
8
+ worker_id: str = None
9
+ decorated = None
10
+
11
+ def __init__(
12
+ self,
13
+ time_unit=None,
14
+ interval=None,
15
+ worker_id=None,
16
+ decorated=None
17
+ ):
18
+ if time_unit is not None:
19
+ self.time_unit = TimeUnit.from_value(time_unit)
20
+
21
+ if interval is not None:
22
+ self.interval = interval
23
+
24
+ if decorated is not None:
25
+ self.decorated = decorated
26
+
27
+ if worker_id is not None:
28
+ self.worker_id = worker_id
29
+ elif self.decorated:
30
+ self.worker_id = decorated.__name__
31
+ else:
32
+ self.worker_id = self.__class__.__name__
33
+
34
+ def run(self, context):
35
+
36
+ if self.decorated:
37
+ self.decorated(context=context)
38
+ else:
39
+ raise NotImplementedError(
40
+ "run method must be implemented in the subclass"
41
+ )
@@ -0,0 +1,5 @@
1
+ from .create_app import create_flask_app
2
+ from .run_strategies import run_strategies
3
+ from .schemas import OrderSerializer
4
+
5
+ __all__ = ["create_flask_app", "run_strategies", 'OrderSerializer']
@@ -0,0 +1,13 @@
1
+ from investing_algorithm_framework.app.web.controllers.orders import \
2
+ blueprint as orders_blueprint
3
+ from investing_algorithm_framework.app.web.controllers.portfolio \
4
+ import blueprint as portfolio_blueprint
5
+ from investing_algorithm_framework.app.web.controllers.positions import \
6
+ blueprint as positions_blueprint
7
+
8
+
9
+ def setup_blueprints(flask_app):
10
+ flask_app.register_blueprint(portfolio_blueprint, prefix="/api")
11
+ flask_app.register_blueprint(orders_blueprint, prefix="/api")
12
+ flask_app.register_blueprint(positions_blueprint, prefix="/api")
13
+ return flask_app
@@ -0,0 +1,20 @@
1
+ import logging
2
+
3
+ from dependency_injector.wiring import inject, Provide
4
+ from flask import Blueprint, request
5
+
6
+ from investing_algorithm_framework.app.web.responses import create_response
7
+ from investing_algorithm_framework.app.web.schemas import OrderSerializer
8
+ from investing_algorithm_framework.dependency_container import \
9
+ DependencyContainer
10
+
11
+ logger = logging.getLogger("investing_algorithm_framework")
12
+
13
+ blueprint = Blueprint("order-views", __name__)
14
+
15
+
16
+ @blueprint.route("/api/orders", methods=["GET"])
17
+ @inject
18
+ def list_orders(order_service=Provide[DependencyContainer.order_service]):
19
+ orders = order_service.get_all(request.args)
20
+ return create_response(orders, OrderSerializer())
@@ -0,0 +1,20 @@
1
+ import logging
2
+
3
+ from dependency_injector.wiring import inject, Provide
4
+ from flask import Blueprint, request
5
+
6
+ from investing_algorithm_framework.app.web.responses import create_response
7
+ from investing_algorithm_framework.app.web.schemas import PortfolioSerializer
8
+ from investing_algorithm_framework.dependency_container import \
9
+ DependencyContainer
10
+
11
+ logger = logging.getLogger("investing_algorithm_framework")
12
+
13
+ blueprint = Blueprint("portfolio-views", __name__)
14
+
15
+
16
+ @blueprint.route("/api/portfolios", methods=["GET"])
17
+ @inject
18
+ def retrieve(portfolio_service=Provide[DependencyContainer.portfolio_service]):
19
+ portfolios = portfolio_service.get_all(request.args)
20
+ return create_response(portfolios, PortfolioSerializer())
@@ -0,0 +1,18 @@
1
+ import logging
2
+
3
+ from dependency_injector.wiring import inject, Provide
4
+ from flask import Blueprint, request
5
+
6
+ from investing_algorithm_framework.app.web.responses import create_response
7
+ from investing_algorithm_framework.app.web.schemas import PositionSerializer
8
+
9
+ logger = logging.getLogger("investing_algorithm_framework")
10
+
11
+ blueprint = Blueprint("position-views", __name__)
12
+
13
+
14
+ @blueprint.route("/api/positions", methods=["GET"])
15
+ @inject
16
+ def list_positions(position_service=Provide["position_service"]):
17
+ positions = position_service.get_all(request.args)
18
+ return create_response(positions, PositionSerializer())
@@ -0,0 +1,20 @@
1
+ from flask import Flask
2
+
3
+ from investing_algorithm_framework.app.web.controllers import setup_blueprints
4
+ from investing_algorithm_framework.app.web.setup_cors import setup_cors
5
+ from .error_handler import setup_error_handler
6
+
7
+
8
+ def create_flask_app(configuration_service):
9
+ app = Flask(__name__.split('.')[0])
10
+
11
+ flask_config = configuration_service.get_flask_config()
12
+
13
+ for key, value in flask_config.items():
14
+ app.config[key] = value
15
+
16
+ app = setup_cors(app)
17
+ app.strict_slashes = False
18
+ app = setup_blueprints(app)
19
+ app = setup_error_handler(app)
20
+ return app
@@ -0,0 +1,59 @@
1
+ import logging
2
+ from typing import Dict, List
3
+
4
+ import marshmallow.exceptions as marshmallow_exceptions
5
+ from flask import jsonify
6
+ from werkzeug.exceptions import HTTPException
7
+
8
+ from investing_algorithm_framework.domain import ApiException
9
+
10
+ logger = logging.getLogger("investing_algorithm_framework")
11
+
12
+
13
+ def setup_error_handler(app) -> None:
14
+ """
15
+ Function that will register all the specified error handlers for the app
16
+ """
17
+
18
+ def create_error_response(error_message, status_code: int = 400):
19
+
20
+ # Remove the default 404 not found message if it exists
21
+ if not isinstance(error_message, Dict):
22
+ error_message = error_message.replace("404 Not Found: ", '')
23
+
24
+ response = jsonify({"error_message": error_message})
25
+ response.status_code = status_code
26
+ return response
27
+
28
+ def format_marshmallow_validation_error(errors: Dict):
29
+ errors_message = {}
30
+
31
+ for key in errors:
32
+
33
+ if isinstance(errors[key], Dict):
34
+ errors_message[key] = \
35
+ format_marshmallow_validation_error(errors[key])
36
+
37
+ if isinstance(errors[key], List):
38
+ errors_message[key] = errors[key][0].lower()
39
+ return errors_message
40
+
41
+ def error_handler(error):
42
+ logger.error("exception of type {} occurred".format(type(error)))
43
+ logger.exception(error)
44
+
45
+ if isinstance(error, HTTPException):
46
+ return create_error_response(str(error), error.code)
47
+ elif isinstance(error, ApiException):
48
+ return create_error_response(
49
+ error.error_message, error.status_code
50
+ )
51
+ elif isinstance(error, marshmallow_exceptions.ValidationError):
52
+ error_message = format_marshmallow_validation_error(error.messages)
53
+ return create_error_response(error_message)
54
+ else:
55
+ # Internal error happened that was unknown
56
+ return "Internal server error", 500
57
+
58
+ app.errorhandler(Exception)(error_handler)
59
+ return app
@@ -0,0 +1,20 @@
1
+ import inspect
2
+
3
+ from flask import jsonify
4
+
5
+
6
+ def create_response(data, serializer, status_code=200):
7
+
8
+ if inspect.isclass(serializer):
9
+ serializer = serializer()
10
+
11
+ if isinstance(data, dict):
12
+ item_selection = data["items"]
13
+ data["items"] = serializer.dump(item_selection, many=True)
14
+ return data, status_code
15
+ elif isinstance(data, list):
16
+ data = serializer.dump(data, many=True)
17
+ return jsonify({"items": data, "total": len(data)}), status_code
18
+ else:
19
+ data = serializer.dump(data)
20
+ return jsonify(data), status_code
@@ -0,0 +1,4 @@
1
+ def run_strategies(strategy_orchestration_service):
2
+
3
+ if strategy_orchestration_service.running:
4
+ strategy_orchestration_service.run_pending_jobs()
@@ -0,0 +1,12 @@
1
+ from investing_algorithm_framework.app.web.schemas.order import \
2
+ OrderSerializer
3
+ from investing_algorithm_framework.app.web.schemas.portfolio import\
4
+ PortfolioSerializer
5
+ from investing_algorithm_framework.app.web.schemas.position import \
6
+ PositionSerializer
7
+
8
+ __all__ = [
9
+ "OrderSerializer",
10
+ "PositionSerializer",
11
+ "PortfolioSerializer"
12
+ ]
@@ -0,0 +1,12 @@
1
+ from marshmallow import Schema, fields
2
+
3
+
4
+ class OrderSerializer(Schema):
5
+ reference_id = fields.String(dump_only=True)
6
+ target_symbol = fields.String(dump_only=True)
7
+ trading_symbol = fields.String(dump_only=True)
8
+ price = fields.Float(dump_only=True)
9
+ amount = fields.Float(dump_only=True)
10
+ status = fields.String(dump_only=True)
11
+ order_type = fields.String(dump_only=True)
12
+ order_side = fields.String(dump_only=True)
@@ -0,0 +1,22 @@
1
+ from marshmallow import Schema, fields
2
+
3
+ from investing_algorithm_framework.dependency_container \
4
+ import DependencyContainer
5
+
6
+
7
+ class PortfolioSerializer(Schema):
8
+ identifier = fields.String(dump_only=True)
9
+ trading_symbol = fields.String(dump_only=True)
10
+ unallocated = fields.Float(dump_only=True)
11
+ orders = fields.Method("get_orders")
12
+ positions = fields.Method("get_positions")
13
+
14
+ @staticmethod
15
+ def get_orders(obj):
16
+ order_service = DependencyContainer.order_service()
17
+ return order_service.count({"portfolio": obj.identifier})
18
+
19
+ @staticmethod
20
+ def get_positions(obj):
21
+ position_service = DependencyContainer.position_service()
22
+ return position_service.count({"portfolio": obj.id})
@@ -0,0 +1,15 @@
1
+ from marshmallow import Schema, fields
2
+
3
+ from investing_algorithm_framework.dependency_container import \
4
+ DependencyContainer
5
+
6
+
7
+ class PositionSerializer(Schema):
8
+ symbol = fields.String()
9
+ amount = fields.Float(dump_only=True)
10
+ orders = fields.Method("get_orders")
11
+
12
+ @staticmethod
13
+ def get_orders(obj):
14
+ order_service = DependencyContainer.order_service()
15
+ return order_service.count({"position": obj.id})
@@ -0,0 +1,6 @@
1
+ from flask_cors import CORS
2
+
3
+
4
+ def setup_cors(app):
5
+ CORS(app)
6
+ return app
File without changes
@@ -0,0 +1,207 @@
1
+ import click
2
+
3
+ from .deploy_to_aws_lambda import command as deploy_to_aws_lambda_command
4
+ from .deploy_to_azure_function import command as \
5
+ deploy_to_azure_function_command
6
+ from .initialize_app import command as initialize_app_command
7
+
8
+ """
9
+ CLI for Investing Algorithm Framework
10
+
11
+ This module provides a command-line interface (CLI) for the
12
+ Investing Algorithm Framework.
13
+ """
14
+
15
+
16
+ @click.group()
17
+ def cli():
18
+ """CLI for Investing Algorithm Framework"""
19
+ pass
20
+
21
+
22
+ @click.command()
23
+ @click.option(
24
+ '--type',
25
+ default="default",
26
+ help="Type of app to create. "
27
+ "Options are: 'default', 'default_web', 'azure_function', 'aws_lambda'."
28
+ )
29
+ @click.option(
30
+ '--path', default=None, help="Path to directory to initialize the app in"
31
+ )
32
+ @click.option(
33
+ '--replace',
34
+ is_flag=True,
35
+ default=False,
36
+ help="If True, duplicate files will be replaced."
37
+ "If False, files will not be replaced."
38
+ )
39
+ def init(type, path, replace):
40
+ """
41
+ Command-line tool for creating an app skeleton.
42
+
43
+ Args:
44
+ type (str): Type of app to create. Options are: 'default',
45
+ 'default-web', 'azure-function'.
46
+ path (str): Path to directory to initialize the app in
47
+ replace (bool): If True, existing files will be replaced.
48
+ If False, existing files will not be replaced.
49
+
50
+ Returns:
51
+ None
52
+ """
53
+ initialize_app_command(path=path, app_type=type, replace=replace)
54
+
55
+
56
+ @click.command()
57
+ @click.option(
58
+ '--resource_group',
59
+ required=True,
60
+ help='The name of the resource group.',
61
+ )
62
+ @click.option(
63
+ '--subscription_id',
64
+ required=False,
65
+ help='The subscription ID. If not provided, the default will be used.'
66
+ )
67
+ @click.option(
68
+ '--storage_account_name',
69
+ required=False,
70
+ help='The name of the storage account.',
71
+ )
72
+ @click.option(
73
+ '--container_name',
74
+ required=False,
75
+ help='The name of the blob container.',
76
+ default='iafcontainer'
77
+ )
78
+ @click.option(
79
+ '--deployment_name',
80
+ required=True,
81
+ help='The name of the deployment. This will be" + \
82
+ "used as the name of the Function App.'
83
+ )
84
+ @click.option(
85
+ '--region',
86
+ required=True,
87
+ help='The Azure region for the resources.'
88
+ )
89
+ @click.option(
90
+ '--create_resource_group_if_not_exists',
91
+ is_flag=True,
92
+ help='Flag to create the resource group if it does not exist.'
93
+ )
94
+ @click.option(
95
+ '--skip_login',
96
+ is_flag=True,
97
+ help='Flag to create the resource group if it does not exist.',
98
+ default=False
99
+ )
100
+ def deploy_azure_function(
101
+ resource_group,
102
+ subscription_id,
103
+ storage_account_name,
104
+ container_name,
105
+ deployment_name,
106
+ region,
107
+ create_resource_group_if_not_exists,
108
+ skip_login
109
+ ):
110
+ """
111
+ Command-line tool for deploying a trading bot to Azure Function.
112
+
113
+ Args:
114
+ path (str): Path to directory to initialize the app in
115
+ resource_group (str): The name of the resource group.
116
+ subscription_id (str): The subscription ID. If not provided,
117
+ the default will be used.
118
+ storage_account_name (str): The name of the storage account.
119
+ container_name (str): The name of the blob container.
120
+ deployment_name (str): The name of the deployment. This will be
121
+ used as the name of the Function App.
122
+ region (str): The Azure region for the resources.
123
+ create_resource_group_if_not_exists (bool): Flag to create the
124
+ resource group if it does not exist.
125
+ skip_login (bool): Flag to skip the login process. This is
126
+ useful for CI/CD pipelines where the login is handled
127
+ separately.
128
+ region (str): The Azure region for the resources.
129
+ create_resource_group_if_not_exists (bool): Flag to create the
130
+ resource group if it does not exist.
131
+ skip_login (bool): Flag to skip the login process. This is
132
+ useful for CI/CD pipelines where the login is handled
133
+ separately.
134
+
135
+ Returns:
136
+ None
137
+ """
138
+ crg = create_resource_group_if_not_exists
139
+ deploy_to_azure_function_command(
140
+ resource_group=resource_group,
141
+ subscription_id=subscription_id,
142
+ storage_account_name=storage_account_name,
143
+ container_name=container_name,
144
+ deployment_name=deployment_name,
145
+ region=region,
146
+ create_resource_group_if_not_exists=crg,
147
+ skip_login=skip_login
148
+ )
149
+
150
+
151
+ @click.command()
152
+ @click.option(
153
+ '--lambda_function_name',
154
+ required=True,
155
+ help='The name of the AWS Lambda function to deploy.'
156
+ )
157
+ @click.option(
158
+ '--region',
159
+ required=True,
160
+ help='The AWS region where the Lambda function will be deployed.'
161
+ )
162
+ @click.option(
163
+ '--project_dir',
164
+ default=None,
165
+ help='The path to the project directory containing '
166
+ 'the Lambda function code.'
167
+ )
168
+ @click.option(
169
+ '--memory_size',
170
+ default=3000,
171
+ type=int,
172
+ help='The memory size for the Lambda function in MB. Default is 3000 MB.'
173
+ )
174
+ def deploy_aws_lambda(
175
+ lambda_function_name,
176
+ region,
177
+ project_dir=None,
178
+ memory_size=3000
179
+ ):
180
+ """
181
+ Command-line tool for deploying a trading bot to AWS lambda
182
+
183
+ Args:
184
+ lambda_function_name (str): The name of the AWS Lambda function
185
+ to deploy.
186
+ region (str): The AWS region where the Lambda function will
187
+ be deployed.
188
+ project_dir (str): The path to the project directory containing the
189
+ Lambda function code. If not provided, it defaults to
190
+ the current directory.
191
+ memory_size (int): The memory size for the Lambda function in MB.
192
+ Default is 3000 MB.
193
+
194
+ Returns:
195
+ None
196
+ """
197
+ deploy_to_aws_lambda_command(
198
+ lambda_function_name=lambda_function_name,
199
+ region=region,
200
+ project_dir=project_dir,
201
+ memory_size=memory_size
202
+ )
203
+
204
+
205
+ cli.add_command(init)
206
+ cli.add_command(deploy_azure_function)
207
+ cli.add_command(deploy_aws_lambda)