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
@@ -1,382 +0,0 @@
1
- import pandas as pd
2
- import plotly.graph_objs as go
3
-
4
-
5
- def create_rsi_graph(data: pd.DataFrame):
6
- """
7
- Create a graph for the RSI metric.
8
- :param data: DataFrame with a 'RSI' column and a Datetime index
9
- :return: Plotly graph object
10
- """
11
-
12
- # Check if the index is of type datetime
13
- if not isinstance(data.index, pd.DatetimeIndex):
14
- raise ValueError("The index of the data should be of type datetime")
15
-
16
- # Check if the 'RSI' column exists
17
- if 'RSI' not in data.columns:
18
- raise ValueError("The data should have a 'RSI' column")
19
-
20
- return go.Scatter(
21
- x=data.index,
22
- y=data['RSI'],
23
- mode='lines',
24
- line=dict(color="green", width=1),
25
- name="RSI"
26
- )
27
-
28
-
29
- def create_prices_graph(
30
- data: pd.DataFrame,
31
- data_key="Close",
32
- graph_name="Price",
33
- color="blue",
34
- line_width=1
35
- ):
36
- """
37
- Create a graph for the close prices. By default, the key is set to 'Close'.
38
-
39
- Args:
40
- data (pd.DataFrame): The data to plot
41
- data_key (str): The key to use for the prices
42
- graph_name (str): The name of the graph
43
- color (str): The color of the graph
44
- line_width (int): The width of the line
45
-
46
- Returns:
47
- go.Scatter: The Plotly graph object
48
- """
49
-
50
- # Check if the index is of type datetime
51
- if not isinstance(data.index, pd.DatetimeIndex):
52
- raise ValueError("The index of the data should be of type datetime")
53
-
54
- # Check if the 'Close' column exists
55
- if data_key not in data.columns:
56
- raise ValueError("The data should have a 'Close' column")
57
-
58
- return go.Scatter(
59
- x=data.index,
60
- y=data[data_key],
61
- mode='lines',
62
- line=dict(color=color, width=line_width),
63
- name=graph_name
64
- )
65
-
66
-
67
- def create_adx_graph(data: pd.DataFrame):
68
- """
69
- Create a graph for the ADX metric.
70
- :param data: DataFrame with a 'ADX' column and a Datetime index
71
- :return: Plotly graph object
72
- """
73
-
74
- # Check if the index is of type datetime
75
- if not isinstance(data.index, pd.DatetimeIndex):
76
- raise ValueError("The index of the data should be of type datetime")
77
-
78
- # Check if the 'ADX' column exists
79
- if 'ADX' not in data.columns:
80
- raise ValueError("The data should have a 'ADX' column")
81
-
82
- return go.Scatter(
83
- x=data.index,
84
- y=data['ADX'],
85
- mode='lines',
86
- line=dict(color="green", width=1),
87
- name="ADX"
88
- )
89
-
90
-
91
- def create_di_plus_graph(data: pd.DataFrame):
92
- """
93
- Create a graph for the DI+ metric.
94
- :param data: DataFrame with a '+DI' column and a Datetime index
95
- :return: Plotly graph object
96
- """
97
-
98
- # Check if the index is of type datetime
99
- if not isinstance(data.index, pd.DatetimeIndex):
100
- raise ValueError("The index of the data should be of type datetime")
101
-
102
- # Check if the '+DI' column exists
103
- if '+DI' not in data.columns:
104
- raise ValueError("The data should have a '+DI' column")
105
-
106
- return go.Scatter(
107
- x=data.index,
108
- y=data['+DI'],
109
- mode='lines',
110
- line=dict(color="orange", width=1),
111
- name="+DI"
112
- )
113
-
114
-
115
- def create_di_minus_graph(data: pd.DataFrame):
116
- """
117
- Create a graph for the DI- metric.
118
- :param data: DataFrame with a '-DI' column and a Datetime index
119
- :return: Plotly graph object
120
- """
121
-
122
- # Check if the index is of type datetime
123
- if not isinstance(data.index, pd.DatetimeIndex):
124
- raise ValueError("The index of the data should be of type datetime")
125
-
126
- # Check if the '-DI' column exists
127
- if '-DI' not in data.columns:
128
- raise ValueError("The data should have a '-DI' column")
129
-
130
- return go.Scatter(
131
- x=data.index,
132
- y=data['-DI'],
133
- mode='lines',
134
- line=dict(color="purple", width=1),
135
- name="-DI"
136
- )
137
-
138
-
139
- def create_di_plus_di_minus_crossover_graph(data: pd.DataFrame):
140
- """
141
- Create a graph for the DI- and DI+ crossover.
142
- """
143
-
144
- # Check if the index is of type datetime
145
- if not isinstance(data.index, pd.DatetimeIndex):
146
- raise ValueError("The index of the data should be of type datetime")
147
-
148
- # Check if the '-DI' and '+DI' columns exist
149
- if '-DI' not in data.columns or '+DI' not in data.columns:
150
- raise ValueError("The data should have a '-DI' and '+DI' column")
151
-
152
- # Get all crossover indexes
153
- crossover_index = data[(data['+DI'] < data['-DI']) &
154
- (data['+DI'].shift(1) > data['-DI'].shift(1))].index
155
-
156
- # Use .loc to get the corresponding 'Close' values
157
- crossover_close_values = data.loc[crossover_index, '+DI']
158
-
159
- return go.Scatter(
160
- x=crossover_index,
161
- y=crossover_close_values,
162
- mode='markers',
163
- marker=dict(symbol='circle', size=10, color='blue'),
164
- name='DI- DI+ Crossover'
165
- )
166
-
167
-
168
- def create_ema_graph(data: pd.DataFrame, key, color="blue"):
169
- # Check if the index is of type datetime
170
- if not isinstance(data.index, pd.DatetimeIndex):
171
- raise ValueError("The index of the data should be of type datetime")
172
-
173
- # Check if the key columns exist
174
- if key not in data.columns:
175
- raise ValueError(f"The data should have a {key} column")
176
-
177
- return go.Scatter(
178
- x=data.index,
179
- y=data[key],
180
- mode='lines',
181
- line=dict(color=color, width=1),
182
- name=key
183
- )
184
-
185
-
186
- def create_crossover_graph(data: pd.DataFrame, key_one, key_two, color="blue"):
187
- # Check if the index is of type datetime
188
- if not isinstance(data.index, pd.DatetimeIndex):
189
- raise ValueError("The index of the data should be of type datetime")
190
-
191
- # Check if the key columns exist
192
- if key_one not in data.columns or key_two not in data.columns:
193
- raise ValueError(f"The data should have a {key_one} "
194
- f"and {key_two} column")
195
-
196
- # Get all crossover indexes
197
- crossover_index = data[
198
- (data[key_one] <= data[key_two]) &
199
- (data[key_one].shift(1) >= data[key_two].shift(1))
200
- ].index
201
-
202
- # Use .loc to get the corresponding 'Close' values
203
- crossover_close_values = data.loc[crossover_index, key_one]
204
-
205
- return go.Scatter(
206
- x=crossover_index,
207
- y=crossover_close_values,
208
- mode='markers',
209
- marker=dict(symbol='circle', size=10, color=color),
210
- name=f'{key_one} {key_two} Crossover'
211
- )
212
-
213
-
214
- def create_peaks_chart(data: pd.DataFrame, key="Close", order=5):
215
-
216
- # Check if the index is of type datetime
217
- if not isinstance(data.index, pd.DatetimeIndex):
218
- raise ValueError("The index of the data should be of type datetime")
219
-
220
- keys = [f'{key}_highs', f'{key}_lows']
221
-
222
- for key_column in keys:
223
- if key_column not in data.columns:
224
- raise ValueError(f"The data should have a '{key_column}' column")
225
-
226
- # Get all peak indexes
227
- hh_close_index = data[data[f'{key}_highs'] == 1].index
228
- lh_close_index = data[data[f'{key}_highs'] == -1].index
229
- ll_close_index = data[data[f'{key}_lows'] == 1].index
230
- hl_close_index = data[data[f'{key}_lows'] == -1].index
231
-
232
- # Use .loc to get the corresponding 'Close' values if
233
- # the index is in the DataFrame
234
- hh_close_values = data.loc[hh_close_index, key]
235
- lh_close_values = data.loc[lh_close_index, key]
236
- ll_close_values = data.loc[ll_close_index, key]
237
- hl_close_values = data.loc[hl_close_index, key]
238
-
239
- # Add higher highs
240
- higher_high_graph = go.Scatter(
241
- x=hh_close_index,
242
- # x=dates[hh_close_index - order].values,
243
- y=hh_close_values,
244
- mode='markers',
245
- marker=dict(symbol='triangle-up', size=10, color='blue'),
246
- name='Higher High Confirmation'
247
- )
248
-
249
- # Add lower highs
250
- lower_high_graph = go.Scatter(
251
- x=lh_close_index,
252
- y=lh_close_values,
253
- mode='markers',
254
- marker=dict(symbol='triangle-down', size=10, color='red'),
255
- name='Lower High Confirmation'
256
- )
257
-
258
- # Add lower lows
259
- lower_lows_graph = go.Scatter(
260
- x=ll_close_index,
261
- y=ll_close_values,
262
- mode='markers',
263
- marker=dict(symbol='triangle-down', size=10, color='green'),
264
- name='Lower Lows Confirmation'
265
- )
266
-
267
- # Add higher lows
268
- higher_lows = go.Scatter(
269
- x=hl_close_index,
270
- y=hl_close_values,
271
- mode='markers',
272
- marker=dict(symbol='triangle-up', size=10, color='purple'),
273
- name='Higher Lows Confirmation'
274
- )
275
-
276
- return higher_high_graph, lower_high_graph, lower_lows_graph, higher_lows
277
-
278
-
279
- def create_bullish_divergence_chart(
280
- data: pd.DataFrame, key_one, key_two, color='red'
281
- ):
282
- """
283
- A bullish divergence occurs when the "<key_one>_lows" makes
284
- a new low but the "<key_two>_lows" makes a higher low.
285
-
286
- For example, if the RSI makes a new low but the close price
287
- makes a higher low, then we have a bullish divergence.
288
- """
289
- divergence_index = data[(data[f'{key_one}_lows'] == -1)
290
- & (data[f'{key_two}_lows'] == 1)].index
291
- divergence_close_values = data.loc[divergence_index, 'Close']
292
-
293
- return go.Scatter(
294
- x=divergence_index,
295
- y=divergence_close_values,
296
- mode='markers',
297
- marker=dict(symbol='circle', size=10, color=color),
298
- name='Bullish Divergence'
299
- )
300
-
301
-
302
- def create_bearish_divergence_chart(
303
- data: pd.DataFrame, key_one, key_two, color='red'
304
- ):
305
- """
306
- A bearish divergence occurs when the "<key_one>_highs" makes a
307
- new high but the "<key_two>_highs" makes a lower high.
308
-
309
- For example, if the RSI makes a new high but the close price makes
310
- a lower high, then we have a bearish divergence.
311
- """
312
-
313
- # Add divergence charts
314
- divergence_index = data[(data[f'{key_one}_highs'] == -1)
315
- & (data[f'{key_two}_highs'] == 1)].index
316
- divergence_close_values = data.loc[divergence_index, 'Close']
317
-
318
- return go.Scatter(
319
- x=divergence_index,
320
- y=divergence_close_values,
321
- mode='markers',
322
- marker=dict(symbol='circle', size=10, color=color),
323
- name='Bearish Divergence'
324
- )
325
-
326
-
327
- def create_entry_graph(data: pd.DataFrame):
328
- # Iterate over each row in the DataFrame and check if there is a
329
- # bullish divergence between the RSI and the close price
330
- # and if there is a crossover between the DI+ and DI- for
331
- # the last 12 hours (6 candles)
332
- # Get all crossover indexes
333
- crossover_index = data[(data['+DI'] <= data['-DI']) &
334
- (data['+DI'].shift(1) >= data['-DI'].shift(1))]\
335
- .index
336
- data['di_crossover'] = 0
337
- data.loc[crossover_index, 'di_crossover'] = 1
338
-
339
- entry_indexes = []
340
-
341
- for row in data.itertuples():
342
-
343
- if row.di_crossover == 1:
344
- match = False
345
- # Check if there was a bullish divergence between
346
- # the RSI and the close price in the last 2 days
347
- rsi_window = data.loc[
348
- row.Index - pd.Timedelta(days=2):row.Index,
349
- 'RSI_lows'
350
- ]
351
- close_window = data.loc[
352
- row.Index - pd.Timedelta(days=2):row.Index,
353
- 'Close_lows'
354
- ]
355
-
356
- # Go over each row and check if there is a bullish
357
- # divergence between the RSI and the close price
358
- for rsi_row, close_row in zip(rsi_window, close_window):
359
-
360
- if rsi_row == -1 and close_row == 1:
361
- entry_indexes.append(row.Index)
362
- match = True
363
- break
364
-
365
- if not match:
366
- # Check if the RSI had decreased
367
- rsi_window = data.loc[
368
- row.Index - pd.Timedelta(days=1):row.Index, 'RSI'
369
- ]
370
- rsi_diff = rsi_window.diff().mean()
371
-
372
- if rsi_diff < -2:
373
- entry_indexes.append(row.Index)
374
-
375
- entry_close_values = data.loc[entry_indexes, 'Close']
376
- return go.Scatter(
377
- x=entry_indexes,
378
- y=entry_close_values,
379
- mode='markers',
380
- marker=dict(symbol='circle', size=10, color='green'),
381
- name='Entry Signal'
382
- )
@@ -1,6 +0,0 @@
1
- from .price_efficiency import get_price_efficiency_ratio
2
-
3
-
4
- __all__ = [
5
- "get_price_efficiency_ratio"
6
- ]
@@ -1,11 +0,0 @@
1
- from .backtest_position import BacktestPosition
2
- from .backtest_report import BacktestReport
3
- from .backtest_reports_evaluation import BacktestReportsEvaluation
4
- from .backtest_date_range import BacktestDateRange
5
-
6
- __all__ = [
7
- "BacktestReport",
8
- "BacktestPosition",
9
- "BacktestReportsEvaluation",
10
- "BacktestDateRange"
11
- ]
@@ -1,43 +0,0 @@
1
- from datetime import datetime
2
- from dateutil.parser import parse
3
-
4
-
5
- class BacktestDateRange:
6
- """
7
- Represents a date range for a backtest
8
- """
9
- def __init__(self, start_date, end_date=None, name=None):
10
-
11
- if isinstance(start_date, str):
12
- start_date = parse(start_date)
13
-
14
- if end_date is not None and isinstance(end_date, str):
15
- end_date = parse(end_date)
16
-
17
- self._start_date = start_date
18
- self._end_date = end_date
19
- self._name = name
20
-
21
- if end_date is None:
22
- self._end_date = datetime.now()
23
-
24
- if end_date < start_date:
25
- raise ValueError(
26
- "End date cannot be before start date for a backtest "
27
- "date range."
28
- )
29
-
30
- @property
31
- def start_date(self):
32
- return self._start_date
33
-
34
- @property
35
- def end_date(self):
36
- return self._end_date
37
-
38
- @property
39
- def name(self):
40
- return self._name
41
-
42
- def __str__(self):
43
- return f"{self.name}: {self._start_date} - {self._end_date}"
@@ -1,120 +0,0 @@
1
- from investing_algorithm_framework.domain.models.base_model import BaseModel
2
-
3
-
4
- class BacktestPosition(BaseModel):
5
-
6
- def __init__(
7
- self,
8
- position,
9
- trading_symbol=False,
10
- amount_pending_buy=0.0,
11
- amount_pending_sell=0.0,
12
- total_value_portfolio=0.0
13
- ):
14
- self._symbol = position.symbol
15
- self._amount = position.amount + amount_pending_sell
16
- self._cost = position.cost
17
- self._price = 0.0
18
- self._trading_symbol = trading_symbol
19
- self._amount_pending_buy = amount_pending_buy
20
- self._amount_pending_sell = amount_pending_sell
21
- self._total_value_portfolio = total_value_portfolio
22
-
23
- @property
24
- def price(self):
25
- return self._price
26
-
27
- @price.setter
28
- def price(self, value):
29
- self._price = value
30
-
31
- @property
32
- def cost(self):
33
-
34
- if self._trading_symbol:
35
- return self.amount
36
-
37
- return self._cost
38
-
39
- @property
40
- def value(self):
41
-
42
- if self._trading_symbol:
43
- return self.amount
44
-
45
- return self._price * self.amount
46
-
47
- @property
48
- def growth(self):
49
-
50
- if self._amount == 0:
51
- return 0.0
52
-
53
- if self._trading_symbol:
54
- return 0.0
55
-
56
- return self.value - self.cost
57
-
58
- @property
59
- def growth_rate(self):
60
-
61
- if self._trading_symbol:
62
- return 0.0
63
-
64
- if self.cost == 0:
65
- return 0.0
66
-
67
- return self.growth / self.cost * 100
68
-
69
- @property
70
- def symbol(self):
71
- return self._symbol
72
-
73
- @property
74
- def amount(self):
75
- return self._amount
76
-
77
- @property
78
- def amount_pending_sell(self):
79
- return self._amount_pending_sell
80
-
81
- @amount_pending_sell.setter
82
- def amount_pending_sell(self, value):
83
- self._amount_pending_sell = value
84
-
85
- @property
86
- def amount_pending_buy(self):
87
- return self._amount_pending_buy
88
-
89
- @amount_pending_buy.setter
90
- def amount_pending_buy(self, value):
91
- self._amount_pending_buy = value
92
-
93
- @property
94
- def percentage_of_portfolio(self):
95
-
96
- if self._total_value_portfolio == 0:
97
- return 0.0
98
-
99
- return (self.value / self._total_value_portfolio) * 100
100
-
101
- def get_percentage_of_portfolio(self):
102
-
103
- if self._total_value_portfolio == 0:
104
- return 0.0
105
-
106
- return self.value / self._total_value_portfolio * 100
107
-
108
- def to_dict(self):
109
- return {
110
- "symbol": self.symbol,
111
- "amount": self.amount,
112
- "cost": self.cost,
113
- "price": self.price,
114
- "value": self.value,
115
- "growth": self.growth,
116
- "growth_rate": self.growth_rate,
117
- "amount_pending_buy": self.amount_pending_buy,
118
- "amount_pending_sell": self.amount_pending_sell,
119
- "percentage_of_portfolio": self.percentage_of_portfolio
120
- }