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
@@ -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
+ )
@@ -0,0 +1,197 @@
1
+ """
2
+ CLI command to validate backtest checkpoints from a directory.
3
+
4
+ This command scans a directory for backtest results and creates or updates
5
+ a checkpoints.json file with all found backtests organized by date ranges.
6
+ """
7
+ import json
8
+ import os
9
+ from typing import Dict, List
10
+
11
+ import click
12
+
13
+ from investing_algorithm_framework.domain import Backtest
14
+
15
+
16
+ def validate_and_create_checkpoints(
17
+ directory_path: str,
18
+ output_file: str = None,
19
+ verbose: bool = False
20
+ ) -> Dict[str, List[str]]:
21
+ """
22
+ Validate a directory for backtest checkpoints and create a checkpoint file.
23
+
24
+ Args:
25
+ directory_path (str): Path to the directory containing
26
+ backtest results.
27
+ output_file (str, optional): Custom path for the output
28
+ checkpoint file. If None, will create 'checkpoints.json'
29
+ in the directory_path.
30
+ verbose (bool): Whether to print detailed information.
31
+
32
+ Returns:
33
+ Dict[str, List[str]]: Dictionary mapping date range
34
+ keys to algorithm IDs.
35
+ """
36
+ if not os.path.exists(directory_path):
37
+ raise click.ClickException(
38
+ f"Directory {directory_path} does not exist."
39
+ )
40
+
41
+ # Determine output file path
42
+ if output_file is None:
43
+ output_file = os.path.join(directory_path, "checkpoints.json")
44
+
45
+ checkpoints = {}
46
+ valid_backtests = 0
47
+ invalid_dirs = 0
48
+
49
+ if verbose:
50
+ click.echo(f"Scanning directory: {directory_path}")
51
+ click.echo("-" * 60)
52
+
53
+ # Scan all subdirectories in the target directory
54
+ for item in os.listdir(directory_path):
55
+ item_path = os.path.join(directory_path, item)
56
+
57
+ # Skip files, only process directories
58
+ if not os.path.isdir(item_path):
59
+ continue
60
+
61
+ # Skip the checkpoints.json file itself
62
+ if item == "checkpoints.json":
63
+ continue
64
+
65
+ try:
66
+ # Try to load the backtest
67
+ backtest = Backtest.open(item_path)
68
+
69
+ if backtest.algorithm_id is None:
70
+ if verbose:
71
+ click.echo(
72
+ f"⚠️ Warning: {item} - No "
73
+ f"algorithm_id found, skipping"
74
+ )
75
+ invalid_dirs += 1
76
+ continue
77
+
78
+ # Process each backtest run to extract date ranges
79
+ if backtest.backtest_runs:
80
+ for run in backtest.get_all_backtest_runs():
81
+ # Create date range key in the format used by the framework
82
+ start_date = run.backtest_start_date.isoformat()
83
+ end_date = run.backtest_end_date.isoformat()
84
+ date_range_key = f"{start_date}_{end_date}"
85
+
86
+ # Add algorithm_id to the checkpoint for this date range
87
+ if date_range_key not in checkpoints:
88
+ checkpoints[date_range_key] = []
89
+
90
+ if backtest.algorithm_id \
91
+ not in checkpoints[date_range_key]:
92
+ checkpoints[date_range_key].append(
93
+ backtest.algorithm_id
94
+ )
95
+
96
+ if verbose:
97
+ click.echo(
98
+ f"✓ {item} - Algorithm: "
99
+ f"{backtest.algorithm_id}, "
100
+ f"Range: {start_date} to {end_date}"
101
+ )
102
+
103
+ valid_backtests += 1
104
+ else:
105
+ if verbose:
106
+ click.echo(
107
+ f"⚠️ Warning: {item} - No backtest runs found"
108
+ )
109
+ invalid_dirs += 1
110
+
111
+ except Exception as e:
112
+ if verbose:
113
+ click.echo(f"✗ {item} - Not a valid backtest: {str(e)}")
114
+ invalid_dirs += 1
115
+ continue
116
+
117
+ # Sort algorithm IDs in each checkpoint for consistency
118
+ for date_range_key in checkpoints:
119
+ checkpoints[date_range_key].sort()
120
+
121
+ # Write checkpoint file
122
+ with open(output_file, 'w') as f:
123
+ json.dump(checkpoints, f, indent=4)
124
+
125
+ # Print summary
126
+ if verbose:
127
+ click.echo("-" * 60)
128
+
129
+ click.echo("\n✓ Checkpoint validation complete!")
130
+ click.echo(f" Valid backtests found: {valid_backtests}")
131
+ click.echo(f" Invalid/skipped directories: {invalid_dirs}")
132
+ click.echo(f" Total date ranges: {len(checkpoints)}")
133
+ click.echo(f" Checkpoint file saved to: {output_file}\n")
134
+
135
+ if verbose and checkpoints:
136
+ click.echo("Date ranges found:")
137
+ for date_range_key, algorithm_ids in sorted(checkpoints.items()):
138
+ click.echo(
139
+ f" {date_range_key}: {len(algorithm_ids)} algorithm(s)"
140
+ )
141
+
142
+ return checkpoints
143
+
144
+
145
+ @click.command()
146
+ @click.argument(
147
+ 'directory',
148
+ type=click.Path(exists=True, file_okay=False, dir_okay=True),
149
+ required=True
150
+ )
151
+ @click.option(
152
+ '--output',
153
+ '-o',
154
+ type=click.Path(),
155
+ default=None,
156
+ help='Output path for the checkpoint file. '
157
+ 'Defaults to checkpoints.json in the target directory.'
158
+ )
159
+ @click.option(
160
+ '--verbose',
161
+ '-v',
162
+ is_flag=True,
163
+ default=False,
164
+ help='Print detailed information about each backtest found.'
165
+ )
166
+ def command(directory, output, verbose):
167
+ """
168
+ Validate a directory for backtest checkpoints and create/update
169
+ checkpoints.json.
170
+
171
+ This command scans DIRECTORY for backtest results, validates
172
+ each subdirectory to check if it contains a valid backtest, and
173
+ creates a checkpoints.json file mapping date ranges to algorithm IDs.
174
+
175
+ Example usage:
176
+
177
+ \b
178
+ # Validate backtests in a directory
179
+ iaf validate-checkpoints /path/to/backtest/results
180
+
181
+ \b
182
+ # With verbose output
183
+ iaf validate-checkpoints /path/to/backtest/results --verbose
184
+
185
+ \b
186
+ # Save to a custom location
187
+ iaf validate-checkpoints /path/to/backtest/results -o
188
+ /path/to/checkpoints.json
189
+ """
190
+ try:
191
+ validate_and_create_checkpoints(
192
+ directory_path=directory,
193
+ output_file=output,
194
+ verbose=verbose
195
+ )
196
+ except Exception as e:
197
+ raise click.ClickException(f"Error validating checkpoints: {str(e)}")
@@ -1,20 +1,54 @@
1
- from investing_algorithm_framework.app import App
1
+ import os
2
+ import logging
3
+ import inspect
4
+ from dotenv import load_dotenv
5
+
6
+ from .app import App
2
7
  from .dependency_container import setup_dependency_container
8
+ from .domain import AppMode, APPLICATION_DIRECTORY, APP_MODE
9
+
10
+ logger = logging.getLogger("investing_algorithm_framework")
3
11
 
4
12
 
5
13
  def create_app(
6
- config={},
7
- stateless=False,
8
- web=False,
9
- initialize=True
10
- ):
11
- app = App(config=config, web=web, stateless=stateless)
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)
12
35
  app = setup_dependency_container(
13
36
  app,
14
37
  ["investing_algorithm_framework"],
15
38
  ["investing_algorithm_framework"]
16
39
  )
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)
17
52
 
18
- if initialize:
19
- app.initialize()
53
+ logger.info("Investing algorithm framework app created")
20
54
  return app