investing-algorithm-framework 3.7.0__py3-none-any.whl → 7.19.15__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of investing-algorithm-framework might be problematic. Click here for more details.

Files changed (256) hide show
  1. investing_algorithm_framework/__init__.py +168 -45
  2. investing_algorithm_framework/app/__init__.py +32 -1
  3. investing_algorithm_framework/app/algorithm/__init__.py +7 -0
  4. investing_algorithm_framework/app/algorithm/algorithm.py +239 -0
  5. investing_algorithm_framework/app/algorithm/algorithm_factory.py +114 -0
  6. investing_algorithm_framework/app/analysis/__init__.py +15 -0
  7. investing_algorithm_framework/app/analysis/backtest_data_ranges.py +121 -0
  8. investing_algorithm_framework/app/analysis/backtest_utils.py +107 -0
  9. investing_algorithm_framework/app/analysis/permutation.py +116 -0
  10. investing_algorithm_framework/app/analysis/ranking.py +297 -0
  11. investing_algorithm_framework/app/app.py +1933 -589
  12. investing_algorithm_framework/app/app_hook.py +28 -0
  13. investing_algorithm_framework/app/context.py +1725 -0
  14. investing_algorithm_framework/app/eventloop.py +590 -0
  15. investing_algorithm_framework/app/reporting/__init__.py +27 -0
  16. investing_algorithm_framework/app/reporting/ascii.py +921 -0
  17. investing_algorithm_framework/app/reporting/backtest_report.py +349 -0
  18. investing_algorithm_framework/app/reporting/charts/__init__.py +19 -0
  19. investing_algorithm_framework/app/reporting/charts/entry_exist_signals.py +66 -0
  20. investing_algorithm_framework/app/reporting/charts/equity_curve.py +37 -0
  21. investing_algorithm_framework/app/reporting/charts/equity_curve_drawdown.py +74 -0
  22. investing_algorithm_framework/app/reporting/charts/line_chart.py +11 -0
  23. investing_algorithm_framework/app/reporting/charts/monthly_returns_heatmap.py +70 -0
  24. investing_algorithm_framework/app/reporting/charts/ohlcv_data_completeness.py +51 -0
  25. investing_algorithm_framework/app/reporting/charts/rolling_sharp_ratio.py +79 -0
  26. investing_algorithm_framework/app/reporting/charts/yearly_returns_barchart.py +55 -0
  27. investing_algorithm_framework/app/reporting/generate.py +185 -0
  28. investing_algorithm_framework/app/reporting/tables/__init__.py +11 -0
  29. investing_algorithm_framework/app/reporting/tables/key_metrics_table.py +217 -0
  30. investing_algorithm_framework/app/reporting/tables/stop_loss_table.py +0 -0
  31. investing_algorithm_framework/app/reporting/tables/time_metrics_table.py +80 -0
  32. investing_algorithm_framework/app/reporting/tables/trade_metrics_table.py +147 -0
  33. investing_algorithm_framework/app/reporting/tables/trades_table.py +75 -0
  34. investing_algorithm_framework/app/reporting/tables/utils.py +29 -0
  35. investing_algorithm_framework/app/reporting/templates/report_template.html.j2 +154 -0
  36. investing_algorithm_framework/app/stateless/action_handlers/__init__.py +4 -2
  37. investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +1 -1
  38. investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +1 -1
  39. investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +14 -7
  40. investing_algorithm_framework/app/strategy.py +664 -84
  41. investing_algorithm_framework/app/task.py +5 -3
  42. investing_algorithm_framework/app/web/__init__.py +2 -1
  43. investing_algorithm_framework/app/web/create_app.py +4 -2
  44. investing_algorithm_framework/cli/__init__.py +0 -0
  45. investing_algorithm_framework/cli/cli.py +226 -0
  46. investing_algorithm_framework/cli/deploy_to_aws_lambda.py +501 -0
  47. investing_algorithm_framework/cli/deploy_to_azure_function.py +718 -0
  48. investing_algorithm_framework/cli/initialize_app.py +603 -0
  49. investing_algorithm_framework/cli/templates/.gitignore.template +178 -0
  50. investing_algorithm_framework/cli/templates/app.py.template +18 -0
  51. investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +48 -0
  52. investing_algorithm_framework/cli/templates/app_azure_function.py.template +14 -0
  53. investing_algorithm_framework/cli/templates/app_web.py.template +18 -0
  54. investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +22 -0
  55. investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +92 -0
  56. investing_algorithm_framework/cli/templates/aws_lambda_readme.md.template +110 -0
  57. investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +2 -0
  58. investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +65 -0
  59. investing_algorithm_framework/cli/templates/azure_function_host.json.template +15 -0
  60. investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +8 -0
  61. investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +3 -0
  62. investing_algorithm_framework/cli/templates/data_providers.py.template +17 -0
  63. investing_algorithm_framework/cli/templates/env.example.template +2 -0
  64. investing_algorithm_framework/cli/templates/env_azure_function.example.template +4 -0
  65. investing_algorithm_framework/cli/templates/market_data_providers.py.template +9 -0
  66. investing_algorithm_framework/cli/templates/readme.md.template +135 -0
  67. investing_algorithm_framework/cli/templates/requirements.txt.template +2 -0
  68. investing_algorithm_framework/cli/templates/run_backtest.py.template +20 -0
  69. investing_algorithm_framework/cli/templates/strategy.py.template +124 -0
  70. investing_algorithm_framework/create_app.py +40 -6
  71. investing_algorithm_framework/dependency_container.py +72 -56
  72. investing_algorithm_framework/domain/__init__.py +71 -47
  73. investing_algorithm_framework/domain/backtesting/__init__.py +21 -0
  74. investing_algorithm_framework/domain/backtesting/backtest.py +503 -0
  75. investing_algorithm_framework/domain/backtesting/backtest_date_range.py +96 -0
  76. investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +242 -0
  77. investing_algorithm_framework/domain/backtesting/backtest_metrics.py +459 -0
  78. investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +275 -0
  79. investing_algorithm_framework/domain/backtesting/backtest_run.py +605 -0
  80. investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +162 -0
  81. investing_algorithm_framework/domain/backtesting/combine_backtests.py +280 -0
  82. investing_algorithm_framework/domain/config.py +59 -91
  83. investing_algorithm_framework/domain/constants.py +13 -38
  84. investing_algorithm_framework/domain/data_provider.py +334 -0
  85. investing_algorithm_framework/domain/data_structures.py +3 -2
  86. investing_algorithm_framework/domain/exceptions.py +51 -1
  87. investing_algorithm_framework/domain/models/__init__.py +17 -12
  88. investing_algorithm_framework/domain/models/data/__init__.py +7 -0
  89. investing_algorithm_framework/domain/models/data/data_source.py +214 -0
  90. investing_algorithm_framework/domain/models/data/data_type.py +46 -0
  91. investing_algorithm_framework/domain/models/event.py +35 -0
  92. investing_algorithm_framework/domain/models/market/market_credential.py +55 -1
  93. investing_algorithm_framework/domain/models/order/order.py +77 -83
  94. investing_algorithm_framework/domain/models/order/order_status.py +2 -2
  95. investing_algorithm_framework/domain/models/order/order_type.py +1 -3
  96. investing_algorithm_framework/domain/models/portfolio/portfolio.py +81 -3
  97. investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +26 -3
  98. investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +108 -11
  99. investing_algorithm_framework/domain/models/position/__init__.py +2 -1
  100. investing_algorithm_framework/domain/models/position/position.py +12 -0
  101. investing_algorithm_framework/domain/models/position/position_size.py +41 -0
  102. investing_algorithm_framework/domain/models/risk_rules/__init__.py +7 -0
  103. investing_algorithm_framework/domain/models/risk_rules/stop_loss_rule.py +51 -0
  104. investing_algorithm_framework/domain/models/risk_rules/take_profit_rule.py +55 -0
  105. investing_algorithm_framework/domain/models/snapshot_interval.py +45 -0
  106. investing_algorithm_framework/domain/models/strategy_profile.py +19 -151
  107. investing_algorithm_framework/domain/models/time_frame.py +37 -0
  108. investing_algorithm_framework/domain/models/time_interval.py +33 -0
  109. investing_algorithm_framework/domain/models/time_unit.py +66 -2
  110. investing_algorithm_framework/domain/models/trade/__init__.py +8 -1
  111. investing_algorithm_framework/domain/models/trade/trade.py +295 -171
  112. investing_algorithm_framework/domain/models/trade/trade_status.py +9 -2
  113. investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +332 -0
  114. investing_algorithm_framework/domain/models/trade/trade_take_profit.py +365 -0
  115. investing_algorithm_framework/domain/order_executor.py +112 -0
  116. investing_algorithm_framework/domain/portfolio_provider.py +118 -0
  117. investing_algorithm_framework/domain/services/__init__.py +2 -9
  118. investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +0 -6
  119. investing_algorithm_framework/domain/services/state_handler.py +38 -0
  120. investing_algorithm_framework/domain/strategy.py +1 -29
  121. investing_algorithm_framework/domain/utils/__init__.py +12 -7
  122. investing_algorithm_framework/domain/utils/custom_tqdm.py +22 -0
  123. investing_algorithm_framework/domain/utils/dates.py +57 -0
  124. investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +19 -0
  125. investing_algorithm_framework/domain/utils/polars.py +53 -0
  126. investing_algorithm_framework/domain/utils/random.py +29 -0
  127. investing_algorithm_framework/download_data.py +108 -0
  128. investing_algorithm_framework/infrastructure/__init__.py +31 -18
  129. investing_algorithm_framework/infrastructure/data_providers/__init__.py +36 -0
  130. investing_algorithm_framework/infrastructure/data_providers/ccxt.py +1143 -0
  131. investing_algorithm_framework/infrastructure/data_providers/csv.py +568 -0
  132. investing_algorithm_framework/infrastructure/data_providers/pandas.py +599 -0
  133. investing_algorithm_framework/infrastructure/database/__init__.py +6 -2
  134. investing_algorithm_framework/infrastructure/database/sql_alchemy.py +86 -12
  135. investing_algorithm_framework/infrastructure/models/__init__.py +6 -11
  136. investing_algorithm_framework/infrastructure/models/order/__init__.py +2 -1
  137. investing_algorithm_framework/infrastructure/models/order/order.py +35 -49
  138. investing_algorithm_framework/infrastructure/models/order/order_metadata.py +44 -0
  139. investing_algorithm_framework/infrastructure/models/order_trade_association.py +10 -0
  140. investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +1 -1
  141. investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +8 -0
  142. investing_algorithm_framework/infrastructure/models/portfolio/{portfolio.py → sql_portfolio.py} +17 -5
  143. investing_algorithm_framework/infrastructure/models/trades/__init__.py +9 -0
  144. investing_algorithm_framework/infrastructure/models/trades/trade.py +130 -0
  145. investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +59 -0
  146. investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +55 -0
  147. investing_algorithm_framework/infrastructure/order_executors/__init__.py +21 -0
  148. investing_algorithm_framework/infrastructure/order_executors/backtest_oder_executor.py +28 -0
  149. investing_algorithm_framework/infrastructure/order_executors/ccxt_order_executor.py +200 -0
  150. investing_algorithm_framework/infrastructure/portfolio_providers/__init__.py +19 -0
  151. investing_algorithm_framework/infrastructure/portfolio_providers/ccxt_portfolio_provider.py +199 -0
  152. investing_algorithm_framework/infrastructure/repositories/__init__.py +8 -0
  153. investing_algorithm_framework/infrastructure/repositories/order_metadata_repository.py +17 -0
  154. investing_algorithm_framework/infrastructure/repositories/order_repository.py +5 -0
  155. investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +1 -1
  156. investing_algorithm_framework/infrastructure/repositories/position_repository.py +11 -0
  157. investing_algorithm_framework/infrastructure/repositories/repository.py +81 -27
  158. investing_algorithm_framework/infrastructure/repositories/trade_repository.py +71 -0
  159. investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +29 -0
  160. investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +29 -0
  161. investing_algorithm_framework/infrastructure/services/__init__.py +4 -4
  162. investing_algorithm_framework/infrastructure/services/aws/__init__.py +6 -0
  163. investing_algorithm_framework/infrastructure/services/aws/state_handler.py +113 -0
  164. investing_algorithm_framework/infrastructure/services/azure/__init__.py +5 -0
  165. investing_algorithm_framework/infrastructure/services/azure/state_handler.py +158 -0
  166. investing_algorithm_framework/services/__init__.py +113 -16
  167. investing_algorithm_framework/services/backtesting/__init__.py +0 -7
  168. investing_algorithm_framework/services/backtesting/backtest_service.py +566 -359
  169. investing_algorithm_framework/services/configuration_service.py +77 -11
  170. investing_algorithm_framework/services/data_providers/__init__.py +5 -0
  171. investing_algorithm_framework/services/data_providers/data_provider_service.py +850 -0
  172. investing_algorithm_framework/services/market_credential_service.py +16 -1
  173. investing_algorithm_framework/services/metrics/__init__.py +114 -0
  174. investing_algorithm_framework/services/metrics/alpha.py +0 -0
  175. investing_algorithm_framework/services/metrics/beta.py +0 -0
  176. investing_algorithm_framework/services/metrics/cagr.py +60 -0
  177. investing_algorithm_framework/services/metrics/calmar_ratio.py +40 -0
  178. investing_algorithm_framework/services/metrics/drawdown.py +181 -0
  179. investing_algorithm_framework/services/metrics/equity_curve.py +24 -0
  180. investing_algorithm_framework/services/metrics/exposure.py +210 -0
  181. investing_algorithm_framework/services/metrics/generate.py +358 -0
  182. investing_algorithm_framework/services/metrics/mean_daily_return.py +83 -0
  183. investing_algorithm_framework/services/metrics/profit_factor.py +165 -0
  184. investing_algorithm_framework/services/metrics/recovery.py +113 -0
  185. investing_algorithm_framework/services/metrics/returns.py +452 -0
  186. investing_algorithm_framework/services/metrics/risk_free_rate.py +28 -0
  187. investing_algorithm_framework/services/metrics/sharpe_ratio.py +137 -0
  188. investing_algorithm_framework/services/metrics/sortino_ratio.py +74 -0
  189. investing_algorithm_framework/services/metrics/standard_deviation.py +157 -0
  190. investing_algorithm_framework/services/metrics/trades.py +500 -0
  191. investing_algorithm_framework/services/metrics/treynor_ratio.py +0 -0
  192. investing_algorithm_framework/services/metrics/ulcer.py +0 -0
  193. investing_algorithm_framework/services/metrics/value_at_risk.py +0 -0
  194. investing_algorithm_framework/services/metrics/volatility.py +97 -0
  195. investing_algorithm_framework/services/metrics/win_rate.py +177 -0
  196. investing_algorithm_framework/services/order_service/__init__.py +3 -1
  197. investing_algorithm_framework/services/order_service/order_backtest_service.py +76 -89
  198. investing_algorithm_framework/services/order_service/order_executor_lookup.py +110 -0
  199. investing_algorithm_framework/services/order_service/order_service.py +407 -326
  200. investing_algorithm_framework/services/portfolios/__init__.py +3 -1
  201. investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +37 -3
  202. investing_algorithm_framework/services/portfolios/portfolio_configuration_service.py +22 -8
  203. investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +106 -0
  204. investing_algorithm_framework/services/portfolios/portfolio_service.py +96 -28
  205. investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +97 -28
  206. investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +116 -313
  207. investing_algorithm_framework/services/positions/__init__.py +7 -0
  208. investing_algorithm_framework/services/positions/position_service.py +210 -0
  209. investing_algorithm_framework/services/repository_service.py +8 -2
  210. investing_algorithm_framework/services/trade_order_evaluator/__init__.py +9 -0
  211. investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +113 -0
  212. investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +51 -0
  213. investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +80 -0
  214. investing_algorithm_framework/services/trade_service/__init__.py +7 -1
  215. investing_algorithm_framework/services/trade_service/trade_service.py +1013 -315
  216. investing_algorithm_framework/services/trade_service/trade_stop_loss_service.py +39 -0
  217. investing_algorithm_framework/services/trade_service/trade_take_profit_service.py +41 -0
  218. investing_algorithm_framework-7.19.15.dist-info/METADATA +537 -0
  219. investing_algorithm_framework-7.19.15.dist-info/RECORD +263 -0
  220. investing_algorithm_framework-7.19.15.dist-info/entry_points.txt +3 -0
  221. investing_algorithm_framework/app/algorithm.py +0 -1105
  222. investing_algorithm_framework/domain/graphs.py +0 -382
  223. investing_algorithm_framework/domain/metrics/__init__.py +0 -6
  224. investing_algorithm_framework/domain/models/backtesting/__init__.py +0 -11
  225. investing_algorithm_framework/domain/models/backtesting/backtest_date_range.py +0 -43
  226. investing_algorithm_framework/domain/models/backtesting/backtest_position.py +0 -120
  227. investing_algorithm_framework/domain/models/backtesting/backtest_report.py +0 -580
  228. investing_algorithm_framework/domain/models/backtesting/backtest_reports_evaluation.py +0 -243
  229. investing_algorithm_framework/domain/models/trading_data_types.py +0 -47
  230. investing_algorithm_framework/domain/models/trading_time_frame.py +0 -223
  231. investing_algorithm_framework/domain/services/market_data_sources.py +0 -344
  232. investing_algorithm_framework/domain/services/market_service.py +0 -153
  233. investing_algorithm_framework/domain/singleton.py +0 -9
  234. investing_algorithm_framework/domain/utils/backtesting.py +0 -472
  235. investing_algorithm_framework/infrastructure/models/market_data_sources/__init__.py +0 -12
  236. investing_algorithm_framework/infrastructure/models/market_data_sources/ccxt.py +0 -559
  237. investing_algorithm_framework/infrastructure/models/market_data_sources/csv.py +0 -254
  238. investing_algorithm_framework/infrastructure/models/market_data_sources/us_treasury_yield.py +0 -47
  239. investing_algorithm_framework/infrastructure/services/market_service/__init__.py +0 -5
  240. investing_algorithm_framework/infrastructure/services/market_service/ccxt_market_service.py +0 -455
  241. investing_algorithm_framework/infrastructure/services/performance_service/__init__.py +0 -7
  242. investing_algorithm_framework/infrastructure/services/performance_service/backtest_performance_service.py +0 -2
  243. investing_algorithm_framework/infrastructure/services/performance_service/performance_service.py +0 -350
  244. investing_algorithm_framework/services/backtesting/backtest_report_writer_service.py +0 -53
  245. investing_algorithm_framework/services/backtesting/graphs.py +0 -61
  246. investing_algorithm_framework/services/market_data_source_service/__init__.py +0 -8
  247. investing_algorithm_framework/services/market_data_source_service/backtest_market_data_source_service.py +0 -150
  248. investing_algorithm_framework/services/market_data_source_service/market_data_source_service.py +0 -189
  249. investing_algorithm_framework/services/position_service.py +0 -31
  250. investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -264
  251. investing_algorithm_framework-3.7.0.dist-info/METADATA +0 -339
  252. investing_algorithm_framework-3.7.0.dist-info/RECORD +0 -147
  253. /investing_algorithm_framework/{domain → services}/metrics/price_efficiency.py +0 -0
  254. /investing_algorithm_framework/services/{position_snapshot_service.py → positions/position_snapshot_service.py} +0 -0
  255. {investing_algorithm_framework-3.7.0.dist-info → investing_algorithm_framework-7.19.15.dist-info}/LICENSE +0 -0
  256. {investing_algorithm_framework-3.7.0.dist-info → investing_algorithm_framework-7.19.15.dist-info}/WHEEL +0 -0
@@ -0,0 +1,135 @@
1
+ # README created by investing_algorithm_framework
2
+
3
+ You can find the documentation for the investing_algorithm_framework
4
+ [here](https://coding-kitties.github.io/investing-algorithm-framework).
5
+
6
+
7
+ ## Getting Started
8
+
9
+ This project was created using the investing_algorithm_framework CLI. It provides a template for building a trading algorithm using the investing_algorithm_framework.
10
+
11
+ This repository contains a simple trading algorithm that uses the
12
+ `investing_algorithm_framework` to fetch data from [bitvavo](https://www.bitvavo.com/en/) and execute trades on the [bitvavo exchange](https://www.bitvavo.com/en/).
13
+
14
+ The trading strategy is a simple moving average crossover strategy that uses the 50 and 100 day moving averages and the 200 day moving average as a trend filter. The strategy is implemented in the `strategy.py` file. The data provider is implemented in the `data_providers.py` file.
15
+
16
+ All indicators are implemented with the [pyindicators](https://github.com/coding-kitties/PyIndicators) library.
17
+
18
+
19
+ #### 1. Install the requirements
20
+
21
+ You can install the requirements using the following command:
22
+ ```bash
23
+ pip install -r requirements.txt
24
+ ```
25
+
26
+ This will install the `investing_algorithm_framework`, `pyindicators`, and
27
+ `python-dotenv` libraries. If you use the azure functions type option, it will also install the `azure-functions` library.
28
+
29
+
30
+ #### 2. Create a `.env` file
31
+ You need to create a `.env` file in the root of the project. You can use the `.env.example` file as a template. The `.env` file should contain the following environment variables:
32
+
33
+ ```bash
34
+ BITVAVO_API_KEY=your_api_key
35
+ BITVAVO_API_SECRET=your_api_secret
36
+ ```
37
+
38
+ ##### 2.1 Changing the exchange
39
+ You can change the exchange in the `app.py` file. The default is set to `bitvavo`, but you can change it to any exchange you want. You can find the list of supported exchanges [here](https://investing-algorithm-framework.com/Getting%20Started/markets).
40
+
41
+ ##### 2.2 Azure Functions `.env` file
42
+ If you are using the azure functions type option, you also need to add the following environment variables:
43
+
44
+ ```
45
+ AZURE_STORAGE_CONNECTION_STRING=your_azure_storage_connection_string
46
+ AZURE_STORAGE_CONTAINER_NAME=your_azure_storage_container_name
47
+ ```
48
+
49
+ If you would like to have guidance on how to create the azure storage connection string, you can find it [here](https://learn.microsoft.com/en-us/azure/storage/common/storage-account-create?tabs=azure-portal).
50
+
51
+ #### 3. Run the app (Skip this step if you have not backtested your strategy)
52
+ > This will run the app as if it was run in production. It will execute live
53
+ > trades on your connected exchange. Please only run this if you are
54
+ > comfortable with this and have backtested your strategy.
55
+
56
+ You can run the app using the following command:
57
+ ```bash
58
+ python app.py
59
+ ```
60
+
61
+ This will start the app and run the trading algorithm. The app will fetch data from the bitvavo exchange and execute trades based on the trading strategy.
62
+
63
+ #### 3.1 Run the app with azure functions locally
64
+ > Make sure to have the azure functions core tools installed. You can find the
65
+ > installation instructions [here](https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local).
66
+
67
+ If you are using the azure functions type option, you can run the app locally using the following command:
68
+ ```bash
69
+ func start
70
+ ```
71
+
72
+ #### 4. Run the backtest
73
+ You can run the backtest using the following command:
74
+
75
+ ```bash
76
+ python run_backtest.py
77
+ ```
78
+
79
+ #### 5. Deployment
80
+ You can deploy your trading bot in varous ways.
81
+
82
+ ##### 5.1 Azure Functions
83
+ You can deploy your trading bot to azure functions using the following command:
84
+
85
+ ```bash
86
+ investing-algorithm-framework deploy --type function --cloud azure
87
+ ```
88
+ This will deploy your trading bot to azure functions. You can find the deployment instructions [here](https://investing-algorithm-framework.com/Getting%20Started/deployment).
89
+
90
+ ## Project Structure
91
+
92
+ > We highly recommend to keep the file structure as is, as it is
93
+ > designed to work with the investing_algorithm_framework CLI.
94
+ > You can add your own files and folders as needed, however, we
95
+ > recommend to keep the `strategies` folder for your strategies
96
+ > and the `app.py` file for your app entry point.
97
+
98
+ ```yaml
99
+ .
100
+ ├── app.py
101
+ ├── requirements.txt
102
+ ├── strategies
103
+ │ ├── data_providers.py
104
+ │ └── strategy.py
105
+ ├── .gitignore
106
+ ├── .env.example
107
+ └── README.md
108
+ ```
109
+
110
+ If you're using the azure functions type option, you will also have an `function_app.py`, `local.settings.json`, and `function.json` file. The `function_app.py` file is the entry point for the azure function, and the `local.settings.json` file is used to configure the local environment for the azure function. The `function.json` file is used to configure the function itself.
111
+
112
+ > You can change the time trigger in the `function_app.py` when
113
+ > using the azure functions type option. The default is set to
114
+ > every 30 seconds. You can change it to any time you want,
115
+ > but make sure to use the correct format for the time trigger.
116
+
117
+ ## Requirements
118
+
119
+ The project requires Python 3.10 or higher. You can create a virtual environment and install the requirements using the following commands:
120
+
121
+ ```bash
122
+ virtualenv venv
123
+ source venv/bin/activate # On Windows use `venv\Scripts\activate`
124
+ pip install -r requirements.txt
125
+ ```
126
+
127
+ By default pyindicators is installed as its specified in the requirements.txt file. This is a requirement for the example strategy in the `strategy.py` file. You can always remove it from the requirements.txt file if you don't need it.
128
+
129
+ ## Deployment
130
+
131
+ You can deploy your trading bot to azure functions using the following cli command:
132
+
133
+ ```bash
134
+ investing-algorithm-framework deploy --type function --cloud azure
135
+ ```
@@ -0,0 +1,2 @@
1
+ investing-algorithm-framework>=6.8.2
2
+ pyindicators>=0.5.4
@@ -0,0 +1,20 @@
1
+ from datetime import datetime
2
+
3
+ from investing_algorithm_framework import BacktestDateRange
4
+ from investing_algorithm_framework import create_app
5
+ from strategies.strategy import MyTradingStrategy
6
+
7
+ app = create_app()
8
+ app.add_strategy(MyTradingStrategy)
9
+ app.add_market(market="BITVAVO", trading_symbol="EUR")
10
+
11
+
12
+ if __name__ == "__main__":
13
+ backtest_date_range = BacktestDateRange(
14
+ start_date=datetime(2023, 1, 1),
15
+ end_date=datetime(2023, 12, 31),
16
+ )
17
+ report = app.run_backtest(
18
+ backtest_date_range=backtest_date_range, initial_amount=1000
19
+ )
20
+ report.show()
@@ -0,0 +1,124 @@
1
+ from investing_algorithm_framework import TimeUnit, TradingStrategy, Context, \
2
+ OrderSide
3
+ from .data_providers import btc_eur_ohlcv_2h, btc_eur_ticker
4
+ from pyindicators import ema, is_crossover, is_above, is_below, is_crossunder
5
+
6
+
7
+ class MyTradingStrategy(TradingStrategy):
8
+ """
9
+ A simple trading strategy that uses EMA crossovers to generate buy and
10
+ sell signals. The strategy uses a 50-period EMA and a 100-period EMA
11
+ to detect golden and death crosses. It also uses a 200-period EMA to
12
+ determine the overall trend direction. The strategy trades BTC/EUR
13
+ on a 2-hour timeframe. The strategy is designed to be used with the
14
+ Investing Algorithm Framework and uses the PyIndicators library
15
+ to calculate the EMAs and crossover signals.
16
+
17
+ The strategy uses a trailing stop loss and take profit to manage
18
+ risk. The stop loss is set to 5% below the entry price and the
19
+ take profit is set to 10% above the entry price. The stop loss and
20
+ take profit are both trailing, meaning that they will move up
21
+ with the price when the price goes up.
22
+ """
23
+ time_unit = TimeUnit.HOUR
24
+ interval = 2
25
+ symbol_pairs = ["BTC/EUR"]
26
+ market_data_sources = [btc_eur_ohlcv_2h, btc_eur_ticker]
27
+ fast = 50
28
+ slow = 100
29
+ trend = 200
30
+ stop_loss_percentage = 2
31
+ stop_loss_sell_size = 50
32
+ take_profit_percentage = 8
33
+ take_profit_sell_size = 50
34
+
35
+ def apply_strategy(self, context: Context, market_data):
36
+
37
+ for pair in self.symbol_pairs:
38
+ symbol = pair.split('/')[0]
39
+
40
+ # Don't trade if there are open orders for the symbol
41
+ # This is important to avoid placing new orders while there are
42
+ # existing orders that are not yet filled
43
+ if context.has_open_orders(symbol):
44
+ continue
45
+
46
+ ohlvc_data = market_data[f"{pair}-ohlcv-2h"]
47
+ # ticker_data = market_data[f"{symbol}-ticker"]
48
+ # Add fast, slow, and trend EMAs to the data
49
+ ohlvc_data = ema(
50
+ ohlvc_data,
51
+ source_column="Close",
52
+ period=self.fast,
53
+ result_column=f"ema_{self.fast}"
54
+ )
55
+ ohlvc_data = ema(
56
+ ohlvc_data,
57
+ source_column="Close",
58
+ period=self.slow,
59
+ result_column=f"ema_{self.slow}"
60
+ )
61
+ ohlvc_data = ema(
62
+ ohlvc_data,
63
+ source_column="Close",
64
+ period=self.trend,
65
+ result_column=f"ema_{self.trend}"
66
+ )
67
+
68
+ price = ohlvc_data["Close"][-1]
69
+
70
+ if not context.has_position(symbol) \
71
+ and self._is_buy_signal(ohlvc_data):
72
+ order = context.create_limit_order(
73
+ target_symbol=symbol,
74
+ order_side=OrderSide.BUY,
75
+ price=price,
76
+ percentage_of_portfolio=25,
77
+ precision=4,
78
+ )
79
+ trade = context.get_trade(order_id=order.id)
80
+ context.add_stop_loss(
81
+ trade=trade,
82
+ trade_risk_type="trailing",
83
+ percentage=self.stop_loss_percentage,
84
+ sell_percentage=self.stop_loss_sell_size
85
+ )
86
+ context.add_take_profit(
87
+ trade=trade,
88
+ percentage=self.take_profit_percentage,
89
+ trade_risk_type="trailing",
90
+ sell_percentage=self.take_profit_sell_size
91
+ )
92
+
93
+ if context.has_position(symbol) \
94
+ and self._is_sell_signal(ohlvc_data):
95
+ open_trades = context.get_open_trades(
96
+ target_symbol=symbol
97
+ )
98
+
99
+ for trade in open_trades:
100
+ context.close_trade(trade)
101
+
102
+ def _is_sell_signal(self, data):
103
+ return is_crossunder(
104
+ data,
105
+ first_column=f"ema_{self.fast}",
106
+ second_column=f"ema_{self.slow}",
107
+ number_of_data_points=2
108
+ ) and is_below(
109
+ data,
110
+ first_column=f"ema_{self.fast}",
111
+ second_column=f"ema_{self.trend}",
112
+ )
113
+
114
+ def _is_buy_signal(self, data):
115
+ return is_crossover(
116
+ data=data,
117
+ first_column=f"ema_{self.fast}",
118
+ second_column=f"ema_{self.slow}",
119
+ number_of_data_points=2
120
+ ) and is_above(
121
+ data=data,
122
+ first_column=f"ema_{self.fast}",
123
+ second_column=f"ema_{self.trend}",
124
+ )
@@ -1,20 +1,54 @@
1
+ import os
1
2
  import logging
3
+ import inspect
4
+ from dotenv import load_dotenv
2
5
 
3
6
  from .app import App
4
7
  from .dependency_container import setup_dependency_container
8
+ from .domain import AppMode, APPLICATION_DIRECTORY, APP_MODE
5
9
 
6
10
  logger = logging.getLogger("investing_algorithm_framework")
7
11
 
8
12
 
9
- def create_app(config=None, stateless=False, web=False) -> App:
10
- app = App(web=web, stateless=stateless)
13
+ def create_app(
14
+ config: dict = None,
15
+ state_handler=None,
16
+ web: bool = False,
17
+ name=None
18
+ ) -> App:
19
+ """
20
+ Factory method to create an app instance.
21
+
22
+ Args:
23
+ config (dict): Configuration dictionary
24
+ web (bool): Whether to create a web app
25
+ state_handler (StateHandler): State handler for the app
26
+ name (str): Name of the app
27
+
28
+ Returns:
29
+ App: App instance
30
+ """
31
+ # Load the environment variables
32
+ load_dotenv()
33
+
34
+ app = App(state_handler=state_handler)
11
35
  app = setup_dependency_container(
12
36
  app,
13
37
  ["investing_algorithm_framework"],
14
38
  ["investing_algorithm_framework"]
15
39
  )
16
- # After the container is setup, initialize the services
17
- app.initialize_services()
18
- app.set_config(config)
19
- logger.info("Investing algoritm framework app created")
40
+ app.name = name
41
+
42
+ if config is not None:
43
+ app.set_config_with_dict(config)
44
+
45
+ if web:
46
+ app.set_config(APP_MODE, AppMode.WEB.value)
47
+
48
+ # Add the application directory to the config
49
+ caller_frame = inspect.stack()[1]
50
+ caller_path = os.path.abspath(caller_frame.filename)
51
+ app.set_config(APPLICATION_DIRECTORY, caller_path)
52
+
53
+ logger.info("Investing algorithm framework app created")
20
54
  return app
@@ -1,16 +1,18 @@
1
1
  from dependency_injector import containers, providers
2
2
 
3
- from investing_algorithm_framework.app.algorithm import Algorithm
3
+ from investing_algorithm_framework.app.algorithm import AlgorithmFactory
4
+ from investing_algorithm_framework.app.context import Context
4
5
  from investing_algorithm_framework.infrastructure import SQLOrderRepository, \
5
6
  SQLPositionRepository, SQLPortfolioRepository, \
6
- SQLPortfolioSnapshotRepository, \
7
- SQLPositionSnapshotRepository, PerformanceService, CCXTMarketService
7
+ SQLPortfolioSnapshotRepository, SQLTradeRepository, \
8
+ SQLPositionSnapshotRepository, SQLTradeStopLossRepository, \
9
+ SQLTradeTakeProfitRepository, SQLOrderMetadataRepository
8
10
  from investing_algorithm_framework.services import OrderService, \
9
- PositionService, PortfolioService, StrategyOrchestratorService, \
10
- PortfolioConfigurationService, MarketDataSourceService, BacktestService, \
11
- ConfigurationService, PortfolioSnapshotService, PositionSnapshotService, \
12
- MarketCredentialService, TradeService, BacktestReportWriterService, \
13
- PortfolioSyncService
11
+ PositionService, PortfolioService, PortfolioConfigurationService, \
12
+ BacktestService, ConfigurationService, PortfolioSnapshotService, \
13
+ PositionSnapshotService, MarketCredentialService, TradeService, \
14
+ PortfolioSyncService, OrderExecutorLookup, PortfolioProviderLookup, \
15
+ DataProviderService, TradeTakeProfitService, TradeStopLossService
14
16
 
15
17
 
16
18
  def setup_dependency_container(app, modules=None, packages=None):
@@ -33,7 +35,14 @@ class DependencyContainer(containers.DeclarativeContainer):
33
35
  MarketCredentialService
34
36
  )
35
37
  order_repository = providers.Factory(SQLOrderRepository)
38
+ order_executor_lookup = providers.ThreadSafeSingleton(
39
+ OrderExecutorLookup
40
+ )
41
+ order_metadata_repository = providers.Factory(SQLOrderMetadataRepository)
36
42
  position_repository = providers.Factory(SQLPositionRepository)
43
+ portfolio_provider_lookup = providers.ThreadSafeSingleton(
44
+ PortfolioProviderLookup,
45
+ )
37
46
  portfolio_repository = providers.Factory(SQLPortfolioRepository)
38
47
  position_snapshot_repository = providers.Factory(
39
48
  SQLPositionSnapshotRepository
@@ -41,14 +50,14 @@ class DependencyContainer(containers.DeclarativeContainer):
41
50
  portfolio_snapshot_repository = providers.Factory(
42
51
  SQLPortfolioSnapshotRepository
43
52
  )
44
- market_service = providers.Factory(
45
- CCXTMarketService,
46
- market_credential_service=market_credential_service,
47
- )
48
- market_data_source_service = providers.Factory(
49
- MarketDataSourceService,
50
- market_service=market_service,
51
- market_credential_service=market_credential_service,
53
+ trade_repository = providers.Factory(SQLTradeRepository)
54
+ trade_take_profit_repository = providers\
55
+ .Factory(SQLTradeTakeProfitRepository)
56
+ trade_stop_loss_repository = providers.Factory(SQLTradeStopLossRepository)
57
+ data_provider_service = providers.ThreadSafeSingleton(
58
+ DataProviderService,
59
+ configuration_service=configuration_service,
60
+ market_credential_service=market_credential_service
52
61
  )
53
62
  position_snapshot_service = providers.Factory(
54
63
  PositionSnapshotService,
@@ -56,94 +65,101 @@ class DependencyContainer(containers.DeclarativeContainer):
56
65
  )
57
66
  portfolio_snapshot_service = providers.Factory(
58
67
  PortfolioSnapshotService,
68
+ order_repository=order_repository,
59
69
  repository=portfolio_snapshot_repository,
70
+ portfolio_repository=portfolio_repository,
60
71
  position_snapshot_service=position_snapshot_service,
61
72
  position_repository=position_repository,
73
+ data_provider_service=data_provider_service,
62
74
  )
63
75
  portfolio_configuration_service = providers.ThreadSafeSingleton(
64
76
  PortfolioConfigurationService,
65
77
  portfolio_repository=portfolio_repository,
66
78
  position_repository=position_repository,
67
79
  )
68
- order_service = providers.Factory(
69
- OrderService,
70
- configuration_service=configuration_service,
80
+ trade_service = providers.Factory(
81
+ TradeService,
71
82
  order_repository=order_repository,
83
+ trade_take_profit_repository=trade_take_profit_repository,
84
+ trade_stop_loss_repository=trade_stop_loss_repository,
85
+ configuration_service=configuration_service,
86
+ trade_repository=trade_repository,
72
87
  portfolio_repository=portfolio_repository,
73
88
  position_repository=position_repository,
74
- market_service=market_service,
75
- market_credential_service=market_credential_service,
76
- portfolio_configuration_service=portfolio_configuration_service,
77
- portfolio_snapshot_service=portfolio_snapshot_service
89
+ order_metadata_repository=order_metadata_repository,
90
+ )
91
+ trade_take_profit_service = providers.Factory(
92
+ TradeTakeProfitService,
93
+ repository=trade_take_profit_repository,
94
+ )
95
+ trade_stop_loss_service = providers.Factory(
96
+ TradeStopLossService,
97
+ repository=trade_stop_loss_repository,
78
98
  )
79
99
  position_service = providers.Factory(
80
100
  PositionService,
101
+ portfolio_repository=portfolio_repository,
81
102
  repository=position_repository,
82
- market_service=market_service,
83
- market_credential_service=market_credential_service,
103
+ )
104
+ order_service = providers.Factory(
105
+ OrderService,
106
+ configuration_service=configuration_service,
84
107
  order_repository=order_repository,
108
+ portfolio_repository=portfolio_repository,
109
+ position_service=position_service,
110
+ market_credential_service=market_credential_service,
111
+ portfolio_configuration_service=portfolio_configuration_service,
112
+ portfolio_snapshot_service=portfolio_snapshot_service,
113
+ trade_service=trade_service,
114
+ order_executor_lookup=order_executor_lookup,
115
+ portfolio_provider_lookup=portfolio_provider_lookup
85
116
  )
86
117
  portfolio_service = providers.Factory(
87
118
  PortfolioService,
88
119
  configuration_service=configuration_service,
89
120
  market_credential_service=market_credential_service,
90
- market_service=market_service,
91
121
  order_service=order_service,
92
122
  position_service=position_service,
93
123
  portfolio_repository=portfolio_repository,
94
124
  portfolio_configuration_service=portfolio_configuration_service,
95
125
  portfolio_snapshot_service=portfolio_snapshot_service,
96
- )
97
- trade_service = providers.Factory(
98
- TradeService,
99
- portfolio_repository=portfolio_repository,
100
- order_service=order_service,
101
- market_data_source_service=market_data_source_service,
102
- position_service=position_service,
126
+ portfolio_provider_lookup=portfolio_provider_lookup
103
127
  )
104
128
  portfolio_sync_service = providers.Factory(
105
129
  PortfolioSyncService,
106
130
  trade_service=trade_service,
107
131
  configuration_service=configuration_service,
108
- order_repository=order_repository,
132
+ order_service=order_service,
109
133
  position_repository=position_repository,
110
134
  portfolio_repository=portfolio_repository,
111
135
  portfolio_configuration_service=portfolio_configuration_service,
112
136
  market_credential_service=market_credential_service,
113
- market_service=market_service,
114
- )
115
- strategy_orchestrator_service = providers.Factory(
116
- StrategyOrchestratorService,
117
- market_data_source_service=market_data_source_service
118
- )
119
- performance_service = providers.Factory(
120
- PerformanceService,
121
- order_repository=order_repository,
122
- position_repository=position_repository,
123
- portfolio_repository=portfolio_repository
137
+ portfolio_provider_lookup=portfolio_provider_lookup,
124
138
  )
125
139
  backtest_service = providers.Factory(
126
140
  BacktestService,
127
141
  configuration_service=configuration_service,
128
142
  order_service=order_service,
129
- portfolio_repository=portfolio_repository,
130
- performance_service=performance_service,
143
+ trade_service=trade_service,
144
+ portfolio_service=portfolio_service,
131
145
  position_repository=position_repository,
132
- market_data_source_service=market_data_source_service,
133
- )
134
- backtest_report_writer_service = providers.Factory(
135
- BacktestReportWriterService,
146
+ portfolio_configuration_service=portfolio_configuration_service,
147
+ portfolio_snapshot_service=portfolio_snapshot_service,
148
+ data_provider_service=data_provider_service,
136
149
  )
137
- algorithm = providers.Factory(
138
- Algorithm,
150
+ context = providers.Factory(
151
+ Context,
139
152
  configuration_service=configuration_service,
140
153
  portfolio_configuration_service=portfolio_configuration_service,
141
154
  portfolio_service=portfolio_service,
142
155
  position_service=position_service,
143
156
  order_service=order_service,
144
- strategy_orchestrator_service=strategy_orchestrator_service,
145
157
  market_credential_service=market_credential_service,
146
- market_data_source_service=market_data_source_service,
147
- market_service=market_service,
148
158
  trade_service=trade_service,
159
+ data_provider_service=data_provider_service,
160
+ trade_stop_loss_service=trade_stop_loss_service,
161
+ trade_take_profit_service=trade_take_profit_service,
162
+ )
163
+ algorithm_factory = providers.Factory(
164
+ AlgorithmFactory,
149
165
  )