investing-algorithm-framework 7.19.14__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (260) hide show
  1. investing_algorithm_framework/__init__.py +197 -0
  2. investing_algorithm_framework/app/__init__.py +47 -0
  3. investing_algorithm_framework/app/algorithm/__init__.py +7 -0
  4. investing_algorithm_framework/app/algorithm/algorithm.py +239 -0
  5. investing_algorithm_framework/app/algorithm/algorithm_factory.py +114 -0
  6. investing_algorithm_framework/app/analysis/__init__.py +15 -0
  7. investing_algorithm_framework/app/analysis/backtest_data_ranges.py +121 -0
  8. investing_algorithm_framework/app/analysis/backtest_utils.py +107 -0
  9. investing_algorithm_framework/app/analysis/permutation.py +116 -0
  10. investing_algorithm_framework/app/analysis/ranking.py +297 -0
  11. investing_algorithm_framework/app/app.py +2204 -0
  12. investing_algorithm_framework/app/app_hook.py +28 -0
  13. investing_algorithm_framework/app/context.py +1667 -0
  14. investing_algorithm_framework/app/eventloop.py +590 -0
  15. investing_algorithm_framework/app/reporting/__init__.py +27 -0
  16. investing_algorithm_framework/app/reporting/ascii.py +921 -0
  17. investing_algorithm_framework/app/reporting/backtest_report.py +349 -0
  18. investing_algorithm_framework/app/reporting/charts/__init__.py +19 -0
  19. investing_algorithm_framework/app/reporting/charts/entry_exist_signals.py +66 -0
  20. investing_algorithm_framework/app/reporting/charts/equity_curve.py +37 -0
  21. investing_algorithm_framework/app/reporting/charts/equity_curve_drawdown.py +74 -0
  22. investing_algorithm_framework/app/reporting/charts/line_chart.py +11 -0
  23. investing_algorithm_framework/app/reporting/charts/monthly_returns_heatmap.py +70 -0
  24. investing_algorithm_framework/app/reporting/charts/ohlcv_data_completeness.py +51 -0
  25. investing_algorithm_framework/app/reporting/charts/rolling_sharp_ratio.py +79 -0
  26. investing_algorithm_framework/app/reporting/charts/yearly_returns_barchart.py +55 -0
  27. investing_algorithm_framework/app/reporting/generate.py +185 -0
  28. investing_algorithm_framework/app/reporting/tables/__init__.py +11 -0
  29. investing_algorithm_framework/app/reporting/tables/key_metrics_table.py +217 -0
  30. investing_algorithm_framework/app/reporting/tables/stop_loss_table.py +0 -0
  31. investing_algorithm_framework/app/reporting/tables/time_metrics_table.py +80 -0
  32. investing_algorithm_framework/app/reporting/tables/trade_metrics_table.py +147 -0
  33. investing_algorithm_framework/app/reporting/tables/trades_table.py +75 -0
  34. investing_algorithm_framework/app/reporting/tables/utils.py +29 -0
  35. investing_algorithm_framework/app/reporting/templates/report_template.html.j2 +154 -0
  36. investing_algorithm_framework/app/stateless/__init__.py +35 -0
  37. investing_algorithm_framework/app/stateless/action_handlers/__init__.py +84 -0
  38. investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +8 -0
  39. investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +15 -0
  40. investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +40 -0
  41. investing_algorithm_framework/app/stateless/exception_handler.py +40 -0
  42. investing_algorithm_framework/app/strategy.py +675 -0
  43. investing_algorithm_framework/app/task.py +41 -0
  44. investing_algorithm_framework/app/web/__init__.py +5 -0
  45. investing_algorithm_framework/app/web/controllers/__init__.py +13 -0
  46. investing_algorithm_framework/app/web/controllers/orders.py +20 -0
  47. investing_algorithm_framework/app/web/controllers/portfolio.py +20 -0
  48. investing_algorithm_framework/app/web/controllers/positions.py +18 -0
  49. investing_algorithm_framework/app/web/create_app.py +20 -0
  50. investing_algorithm_framework/app/web/error_handler.py +59 -0
  51. investing_algorithm_framework/app/web/responses.py +20 -0
  52. investing_algorithm_framework/app/web/run_strategies.py +4 -0
  53. investing_algorithm_framework/app/web/schemas/__init__.py +12 -0
  54. investing_algorithm_framework/app/web/schemas/order.py +12 -0
  55. investing_algorithm_framework/app/web/schemas/portfolio.py +22 -0
  56. investing_algorithm_framework/app/web/schemas/position.py +15 -0
  57. investing_algorithm_framework/app/web/setup_cors.py +6 -0
  58. investing_algorithm_framework/cli/__init__.py +0 -0
  59. investing_algorithm_framework/cli/cli.py +207 -0
  60. investing_algorithm_framework/cli/deploy_to_aws_lambda.py +499 -0
  61. investing_algorithm_framework/cli/deploy_to_azure_function.py +718 -0
  62. investing_algorithm_framework/cli/initialize_app.py +603 -0
  63. investing_algorithm_framework/cli/templates/.gitignore.template +178 -0
  64. investing_algorithm_framework/cli/templates/app.py.template +18 -0
  65. investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +48 -0
  66. investing_algorithm_framework/cli/templates/app_azure_function.py.template +14 -0
  67. investing_algorithm_framework/cli/templates/app_web.py.template +18 -0
  68. investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +22 -0
  69. investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +92 -0
  70. investing_algorithm_framework/cli/templates/aws_lambda_readme.md.template +110 -0
  71. investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +2 -0
  72. investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +65 -0
  73. investing_algorithm_framework/cli/templates/azure_function_host.json.template +15 -0
  74. investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +8 -0
  75. investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +3 -0
  76. investing_algorithm_framework/cli/templates/data_providers.py.template +17 -0
  77. investing_algorithm_framework/cli/templates/env.example.template +2 -0
  78. investing_algorithm_framework/cli/templates/env_azure_function.example.template +4 -0
  79. investing_algorithm_framework/cli/templates/market_data_providers.py.template +9 -0
  80. investing_algorithm_framework/cli/templates/readme.md.template +135 -0
  81. investing_algorithm_framework/cli/templates/requirements.txt.template +2 -0
  82. investing_algorithm_framework/cli/templates/run_backtest.py.template +20 -0
  83. investing_algorithm_framework/cli/templates/strategy.py.template +124 -0
  84. investing_algorithm_framework/create_app.py +54 -0
  85. investing_algorithm_framework/dependency_container.py +155 -0
  86. investing_algorithm_framework/domain/__init__.py +148 -0
  87. investing_algorithm_framework/domain/backtesting/__init__.py +21 -0
  88. investing_algorithm_framework/domain/backtesting/backtest.py +503 -0
  89. investing_algorithm_framework/domain/backtesting/backtest_date_range.py +96 -0
  90. investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +242 -0
  91. investing_algorithm_framework/domain/backtesting/backtest_metrics.py +459 -0
  92. investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +275 -0
  93. investing_algorithm_framework/domain/backtesting/backtest_run.py +435 -0
  94. investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +162 -0
  95. investing_algorithm_framework/domain/backtesting/combine_backtests.py +280 -0
  96. investing_algorithm_framework/domain/config.py +111 -0
  97. investing_algorithm_framework/domain/constants.py +83 -0
  98. investing_algorithm_framework/domain/data_provider.py +334 -0
  99. investing_algorithm_framework/domain/data_structures.py +42 -0
  100. investing_algorithm_framework/domain/decimal_parsing.py +40 -0
  101. investing_algorithm_framework/domain/exceptions.py +112 -0
  102. investing_algorithm_framework/domain/models/__init__.py +43 -0
  103. investing_algorithm_framework/domain/models/app_mode.py +34 -0
  104. investing_algorithm_framework/domain/models/base_model.py +25 -0
  105. investing_algorithm_framework/domain/models/data/__init__.py +7 -0
  106. investing_algorithm_framework/domain/models/data/data_source.py +214 -0
  107. investing_algorithm_framework/domain/models/data/data_type.py +46 -0
  108. investing_algorithm_framework/domain/models/event.py +35 -0
  109. investing_algorithm_framework/domain/models/market/__init__.py +5 -0
  110. investing_algorithm_framework/domain/models/market/market_credential.py +88 -0
  111. investing_algorithm_framework/domain/models/order/__init__.py +6 -0
  112. investing_algorithm_framework/domain/models/order/order.py +384 -0
  113. investing_algorithm_framework/domain/models/order/order_side.py +36 -0
  114. investing_algorithm_framework/domain/models/order/order_status.py +37 -0
  115. investing_algorithm_framework/domain/models/order/order_type.py +30 -0
  116. investing_algorithm_framework/domain/models/portfolio/__init__.py +9 -0
  117. investing_algorithm_framework/domain/models/portfolio/portfolio.py +169 -0
  118. investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +93 -0
  119. investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +208 -0
  120. investing_algorithm_framework/domain/models/position/__init__.py +4 -0
  121. investing_algorithm_framework/domain/models/position/position.py +68 -0
  122. investing_algorithm_framework/domain/models/position/position_snapshot.py +47 -0
  123. investing_algorithm_framework/domain/models/snapshot_interval.py +45 -0
  124. investing_algorithm_framework/domain/models/strategy_profile.py +33 -0
  125. investing_algorithm_framework/domain/models/time_frame.py +153 -0
  126. investing_algorithm_framework/domain/models/time_interval.py +124 -0
  127. investing_algorithm_framework/domain/models/time_unit.py +149 -0
  128. investing_algorithm_framework/domain/models/tracing/__init__.py +0 -0
  129. investing_algorithm_framework/domain/models/tracing/trace.py +23 -0
  130. investing_algorithm_framework/domain/models/trade/__init__.py +13 -0
  131. investing_algorithm_framework/domain/models/trade/trade.py +388 -0
  132. investing_algorithm_framework/domain/models/trade/trade_risk_type.py +34 -0
  133. investing_algorithm_framework/domain/models/trade/trade_status.py +40 -0
  134. investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +267 -0
  135. investing_algorithm_framework/domain/models/trade/trade_take_profit.py +303 -0
  136. investing_algorithm_framework/domain/order_executor.py +112 -0
  137. investing_algorithm_framework/domain/portfolio_provider.py +118 -0
  138. investing_algorithm_framework/domain/positions/__init__.py +4 -0
  139. investing_algorithm_framework/domain/positions/position_size.py +41 -0
  140. investing_algorithm_framework/domain/services/__init__.py +11 -0
  141. investing_algorithm_framework/domain/services/market_credential_service.py +37 -0
  142. investing_algorithm_framework/domain/services/portfolios/__init__.py +5 -0
  143. investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +9 -0
  144. investing_algorithm_framework/domain/services/rounding_service.py +27 -0
  145. investing_algorithm_framework/domain/services/state_handler.py +38 -0
  146. investing_algorithm_framework/domain/stateless_actions.py +7 -0
  147. investing_algorithm_framework/domain/strategy.py +44 -0
  148. investing_algorithm_framework/domain/utils/__init__.py +27 -0
  149. investing_algorithm_framework/domain/utils/csv.py +104 -0
  150. investing_algorithm_framework/domain/utils/custom_tqdm.py +22 -0
  151. investing_algorithm_framework/domain/utils/dates.py +57 -0
  152. investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +19 -0
  153. investing_algorithm_framework/domain/utils/polars.py +53 -0
  154. investing_algorithm_framework/domain/utils/random.py +41 -0
  155. investing_algorithm_framework/domain/utils/signatures.py +17 -0
  156. investing_algorithm_framework/domain/utils/stoppable_thread.py +26 -0
  157. investing_algorithm_framework/domain/utils/synchronized.py +12 -0
  158. investing_algorithm_framework/download_data.py +108 -0
  159. investing_algorithm_framework/infrastructure/__init__.py +50 -0
  160. investing_algorithm_framework/infrastructure/data_providers/__init__.py +36 -0
  161. investing_algorithm_framework/infrastructure/data_providers/ccxt.py +1143 -0
  162. investing_algorithm_framework/infrastructure/data_providers/csv.py +568 -0
  163. investing_algorithm_framework/infrastructure/data_providers/pandas.py +599 -0
  164. investing_algorithm_framework/infrastructure/database/__init__.py +10 -0
  165. investing_algorithm_framework/infrastructure/database/sql_alchemy.py +120 -0
  166. investing_algorithm_framework/infrastructure/models/__init__.py +16 -0
  167. investing_algorithm_framework/infrastructure/models/decimal_parser.py +14 -0
  168. investing_algorithm_framework/infrastructure/models/model_extension.py +6 -0
  169. investing_algorithm_framework/infrastructure/models/order/__init__.py +4 -0
  170. investing_algorithm_framework/infrastructure/models/order/order.py +124 -0
  171. investing_algorithm_framework/infrastructure/models/order/order_metadata.py +44 -0
  172. investing_algorithm_framework/infrastructure/models/order_trade_association.py +10 -0
  173. investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +4 -0
  174. investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +37 -0
  175. investing_algorithm_framework/infrastructure/models/portfolio/sql_portfolio.py +114 -0
  176. investing_algorithm_framework/infrastructure/models/position/__init__.py +4 -0
  177. investing_algorithm_framework/infrastructure/models/position/position.py +63 -0
  178. investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +23 -0
  179. investing_algorithm_framework/infrastructure/models/trades/__init__.py +9 -0
  180. investing_algorithm_framework/infrastructure/models/trades/trade.py +130 -0
  181. investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +40 -0
  182. investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +41 -0
  183. investing_algorithm_framework/infrastructure/order_executors/__init__.py +21 -0
  184. investing_algorithm_framework/infrastructure/order_executors/backtest_oder_executor.py +28 -0
  185. investing_algorithm_framework/infrastructure/order_executors/ccxt_order_executor.py +200 -0
  186. investing_algorithm_framework/infrastructure/portfolio_providers/__init__.py +19 -0
  187. investing_algorithm_framework/infrastructure/portfolio_providers/ccxt_portfolio_provider.py +199 -0
  188. investing_algorithm_framework/infrastructure/repositories/__init__.py +21 -0
  189. investing_algorithm_framework/infrastructure/repositories/order_metadata_repository.py +17 -0
  190. investing_algorithm_framework/infrastructure/repositories/order_repository.py +96 -0
  191. investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +30 -0
  192. investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +56 -0
  193. investing_algorithm_framework/infrastructure/repositories/position_repository.py +66 -0
  194. investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +21 -0
  195. investing_algorithm_framework/infrastructure/repositories/repository.py +299 -0
  196. investing_algorithm_framework/infrastructure/repositories/trade_repository.py +71 -0
  197. investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +23 -0
  198. investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +23 -0
  199. investing_algorithm_framework/infrastructure/services/__init__.py +7 -0
  200. investing_algorithm_framework/infrastructure/services/aws/__init__.py +6 -0
  201. investing_algorithm_framework/infrastructure/services/aws/state_handler.py +113 -0
  202. investing_algorithm_framework/infrastructure/services/azure/__init__.py +5 -0
  203. investing_algorithm_framework/infrastructure/services/azure/state_handler.py +158 -0
  204. investing_algorithm_framework/services/__init__.py +132 -0
  205. investing_algorithm_framework/services/backtesting/__init__.py +5 -0
  206. investing_algorithm_framework/services/backtesting/backtest_service.py +651 -0
  207. investing_algorithm_framework/services/configuration_service.py +96 -0
  208. investing_algorithm_framework/services/data_providers/__init__.py +5 -0
  209. investing_algorithm_framework/services/data_providers/data_provider_service.py +850 -0
  210. investing_algorithm_framework/services/market_credential_service.py +40 -0
  211. investing_algorithm_framework/services/metrics/__init__.py +114 -0
  212. investing_algorithm_framework/services/metrics/alpha.py +0 -0
  213. investing_algorithm_framework/services/metrics/beta.py +0 -0
  214. investing_algorithm_framework/services/metrics/cagr.py +60 -0
  215. investing_algorithm_framework/services/metrics/calmar_ratio.py +40 -0
  216. investing_algorithm_framework/services/metrics/drawdown.py +181 -0
  217. investing_algorithm_framework/services/metrics/equity_curve.py +24 -0
  218. investing_algorithm_framework/services/metrics/exposure.py +210 -0
  219. investing_algorithm_framework/services/metrics/generate.py +358 -0
  220. investing_algorithm_framework/services/metrics/mean_daily_return.py +83 -0
  221. investing_algorithm_framework/services/metrics/price_efficiency.py +57 -0
  222. investing_algorithm_framework/services/metrics/profit_factor.py +165 -0
  223. investing_algorithm_framework/services/metrics/recovery.py +113 -0
  224. investing_algorithm_framework/services/metrics/returns.py +452 -0
  225. investing_algorithm_framework/services/metrics/risk_free_rate.py +28 -0
  226. investing_algorithm_framework/services/metrics/sharpe_ratio.py +137 -0
  227. investing_algorithm_framework/services/metrics/sortino_ratio.py +74 -0
  228. investing_algorithm_framework/services/metrics/standard_deviation.py +157 -0
  229. investing_algorithm_framework/services/metrics/trades.py +500 -0
  230. investing_algorithm_framework/services/metrics/treynor_ratio.py +0 -0
  231. investing_algorithm_framework/services/metrics/ulcer.py +0 -0
  232. investing_algorithm_framework/services/metrics/value_at_risk.py +0 -0
  233. investing_algorithm_framework/services/metrics/volatility.py +97 -0
  234. investing_algorithm_framework/services/metrics/win_rate.py +177 -0
  235. investing_algorithm_framework/services/order_service/__init__.py +9 -0
  236. investing_algorithm_framework/services/order_service/order_backtest_service.py +178 -0
  237. investing_algorithm_framework/services/order_service/order_executor_lookup.py +110 -0
  238. investing_algorithm_framework/services/order_service/order_service.py +826 -0
  239. investing_algorithm_framework/services/portfolios/__init__.py +16 -0
  240. investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +54 -0
  241. investing_algorithm_framework/services/portfolios/portfolio_configuration_service.py +75 -0
  242. investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +106 -0
  243. investing_algorithm_framework/services/portfolios/portfolio_service.py +188 -0
  244. investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +136 -0
  245. investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +182 -0
  246. investing_algorithm_framework/services/positions/__init__.py +7 -0
  247. investing_algorithm_framework/services/positions/position_service.py +210 -0
  248. investing_algorithm_framework/services/positions/position_snapshot_service.py +18 -0
  249. investing_algorithm_framework/services/repository_service.py +40 -0
  250. investing_algorithm_framework/services/trade_order_evaluator/__init__.py +9 -0
  251. investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +132 -0
  252. investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +66 -0
  253. investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +41 -0
  254. investing_algorithm_framework/services/trade_service/__init__.py +3 -0
  255. investing_algorithm_framework/services/trade_service/trade_service.py +1083 -0
  256. investing_algorithm_framework-7.19.14.dist-info/LICENSE +201 -0
  257. investing_algorithm_framework-7.19.14.dist-info/METADATA +459 -0
  258. investing_algorithm_framework-7.19.14.dist-info/RECORD +260 -0
  259. investing_algorithm_framework-7.19.14.dist-info/WHEEL +4 -0
  260. investing_algorithm_framework-7.19.14.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,23 @@
1
+ import logging
2
+
3
+ from investing_algorithm_framework.infrastructure.models import \
4
+ SQLTradeStopLoss
5
+
6
+ from .repository import Repository
7
+
8
+ logger = logging.getLogger("investing_algorithm_framework")
9
+
10
+
11
+ class SQLTradeStopLossRepository(Repository):
12
+ base_class = SQLTradeStopLoss
13
+ DEFAULT_NOT_FOUND_MESSAGE = "The requested trade stop loss was not found"
14
+
15
+ def _apply_query_params(self, db, query, query_params):
16
+ trade_query_param = self.get_query_param("trade_id", query_params)
17
+
18
+ if trade_query_param:
19
+ query = query.filter(
20
+ SQLTradeStopLoss.trade_id == trade_query_param
21
+ )
22
+
23
+ return query
@@ -0,0 +1,23 @@
1
+ import logging
2
+
3
+ from investing_algorithm_framework.infrastructure.models import \
4
+ SQLTradeTakeProfit
5
+
6
+ from .repository import Repository
7
+
8
+ logger = logging.getLogger("investing_algorithm_framework")
9
+
10
+
11
+ class SQLTradeTakeProfitRepository(Repository):
12
+ base_class = SQLTradeTakeProfit
13
+ DEFAULT_NOT_FOUND_MESSAGE = "The requested trade take profit was not found"
14
+
15
+ def _apply_query_params(self, db, query, query_params):
16
+ trade_query_param = self.get_query_param("trade_id", query_params)
17
+
18
+ if trade_query_param:
19
+ query = query.filter(
20
+ SQLTradeTakeProfit.trade_id == trade_query_param
21
+ )
22
+
23
+ return query
@@ -0,0 +1,7 @@
1
+ from .azure import AzureBlobStorageStateHandler
2
+ from .aws import AWSS3StorageStateHandler
3
+
4
+ __all__ = [
5
+ "AzureBlobStorageStateHandler",
6
+ "AWSS3StorageStateHandler"
7
+ ]
@@ -0,0 +1,6 @@
1
+ from .state_handler import AWSS3StorageStateHandler
2
+
3
+
4
+ __all__ = [
5
+ "AWSS3StorageStateHandler",
6
+ ]
@@ -0,0 +1,113 @@
1
+ import os
2
+ import logging
3
+ import boto3
4
+ from botocore.exceptions import NoCredentialsError, PartialCredentialsError
5
+ from investing_algorithm_framework.domain import OperationalException, \
6
+ StateHandler
7
+
8
+ logger = logging.getLogger("investing_algorithm_framework")
9
+
10
+
11
+ class AWSS3StorageStateHandler(StateHandler):
12
+ """
13
+ A state handler for AWS S3 storage.
14
+
15
+ This class provides methods to save and load state to and from
16
+ AWS S3 storage.
17
+
18
+ Attributes:
19
+ bucket_name (str): The name of the AWS S3 bucket.
20
+ """
21
+
22
+ def __init__(self, bucket_name: str = None):
23
+ self.bucket_name = bucket_name
24
+ self.s3_client = None
25
+
26
+ def initialize(self):
27
+ self.bucket_name = self.bucket_name or os.getenv("AWS_S3_BUCKET_NAME")
28
+
29
+ if not self.bucket_name:
30
+ raise OperationalException(
31
+ "AWS S3 state handler requires a bucket name or the "
32
+ "AWS_S3_BUCKET_NAME environment variable to be set."
33
+ )
34
+
35
+ self.s3_client = boto3.client("s3")
36
+
37
+ def save(self, source_directory: str):
38
+ """
39
+ Save the state to AWS S3.
40
+
41
+ Args:
42
+ source_directory (str): Directory to save the state
43
+
44
+ Returns:
45
+ None
46
+ """
47
+ logger.info("Saving state to AWS S3 ...")
48
+
49
+ try:
50
+ # Walk through the directory
51
+ for root, _, files in os.walk(source_directory):
52
+ for file_name in files:
53
+ # Get the full path of the file
54
+ file_path = os.path.join(root, file_name)
55
+
56
+ # Construct the S3 object key (relative path in the bucket)
57
+ s3_key = os.path.relpath(file_path, source_directory)\
58
+ .replace("\\", "/")
59
+
60
+ # Upload the file
61
+ self.s3_client.upload_file(
62
+ file_path, self.bucket_name, s3_key
63
+ )
64
+
65
+ except (NoCredentialsError, PartialCredentialsError) as ex:
66
+ logger.error(f"Error saving state to AWS S3: {ex}")
67
+ raise OperationalException(
68
+ "AWS credentials are missing or incomplete."
69
+ )
70
+ except Exception as ex:
71
+ logger.error(f"Error saving state to AWS S3: {ex}")
72
+ raise ex
73
+
74
+ def load(self, target_directory: str):
75
+ """
76
+ Load the state from AWS S3.
77
+
78
+ Args:
79
+ target_directory (str): Directory to load the state
80
+
81
+ Returns:
82
+ None
83
+ """
84
+ logger.info("Loading state from AWS S3 ...")
85
+
86
+ try:
87
+ # Ensure the local directory exists
88
+ if not os.path.exists(target_directory):
89
+ os.makedirs(target_directory)
90
+
91
+ # List and download objects
92
+ response = self.s3_client.list_objects_v2(Bucket=self.bucket_name)
93
+ if "Contents" in response:
94
+ for obj in response["Contents"]:
95
+ s3_key = obj["Key"]
96
+ file_path = os.path.join(target_directory, s3_key)
97
+
98
+ # Create subdirectories locally if needed
99
+ os.makedirs(os.path.dirname(file_path), exist_ok=True)
100
+
101
+ # Download object to file
102
+ self.s3_client.download_file(
103
+ self.bucket_name, s3_key, file_path
104
+ )
105
+
106
+ except (NoCredentialsError, PartialCredentialsError) as ex:
107
+ logger.error(f"Error loading state from AWS S3: {ex}")
108
+ raise OperationalException(
109
+ "AWS credentials are missing or incomplete."
110
+ )
111
+ except Exception as ex:
112
+ logger.error(f"Error loading state from AWS S3: {ex}")
113
+ raise ex
@@ -0,0 +1,5 @@
1
+ from .state_handler import AzureBlobStorageStateHandler
2
+
3
+ __all__ = [
4
+ "AzureBlobStorageStateHandler"
5
+ ]
@@ -0,0 +1,158 @@
1
+ import os
2
+ import logging
3
+
4
+ from azure.storage.blob import ContainerClient
5
+ from investing_algorithm_framework.domain import OperationalException, \
6
+ StateHandler
7
+
8
+ logger = logging.getLogger("investing_algorithm_framework")
9
+
10
+
11
+ class AzureBlobStorageStateHandler(StateHandler):
12
+ """
13
+ A state handler for Azure Blob Storage.
14
+
15
+ This class provides methods to save and load state to and from
16
+ Azure Blob Storage.
17
+
18
+ Attributes:
19
+ connection_string (str): The connection string for Azure Blob Storage.
20
+ container_name (str): The name of the Azure Blob Storage container.
21
+ """
22
+
23
+ def __init__(
24
+ self, connection_string: str = None, container_name: str = None
25
+ ):
26
+ self.connection_string = connection_string
27
+ self.container_name = container_name
28
+
29
+ def initialize(self):
30
+ """
31
+ Internal helper to initialize the state handler.
32
+ """
33
+
34
+ if self.connection_string is None:
35
+
36
+ # Check if environment variable is set
37
+ self.connection_string = \
38
+ os.getenv("AZURE_STORAGE_CONNECTION_STRING")
39
+
40
+ if self.connection_string is None:
41
+ raise OperationalException(
42
+ "Azure Blob Storage state handler requires" +
43
+ " a connection string or an environment" +
44
+ " variable AZURE_STORAGE_CONNECTION_STRING to be set."
45
+ )
46
+
47
+ if self.container_name is None:
48
+
49
+ # Check if environment variable is set
50
+ self.container_name = os.getenv("AZURE_STORAGE_CONTAINER_NAME")
51
+
52
+ if self.container_name is None:
53
+ raise OperationalException(
54
+ "Azure Blob Storage state handler requires a" +
55
+ " container name or an environment" +
56
+ " variable AZURE_STORAGE_CONTAINER_NAME to be set."
57
+ )
58
+
59
+ def save(self, source_directory: str):
60
+ """
61
+ Save the state to Azure Blob Storage.
62
+
63
+ Parameters:
64
+ source_directory (str): Directory to save the state
65
+
66
+ Returns:
67
+ None
68
+ """
69
+ logger.info("Saving state to Azure Blob Storage ...")
70
+
71
+ try:
72
+ container_client = self._create_container_client()
73
+
74
+ # Create container if it does not exist
75
+ if not container_client.exists():
76
+ container_client.create_container()
77
+
78
+ # Walk through the directory
79
+ for root, _, files in os.walk(source_directory):
80
+ for file_name in files:
81
+ # Get the full path of the file
82
+ file_path = os.path.join(root, file_name)
83
+
84
+ # Construct the blob name (relative path in the container)
85
+ blob_name = os.path.relpath(file_path, source_directory)\
86
+ .replace("\\", "/")
87
+
88
+ # Upload the file
89
+ with open(file_path, "rb") as data:
90
+ container_client.upload_blob(
91
+ name=blob_name, data=data, overwrite=True
92
+ )
93
+
94
+ except Exception as ex:
95
+ logger.error(f"Error saving state to Azure Blob Storage: {ex}")
96
+ raise ex
97
+
98
+ def load(self, target_directory: str):
99
+ """
100
+ Load the state from Azure Blob Storage.
101
+
102
+ Parameters:
103
+ target_directory (str): Directory to load the state
104
+
105
+ Returns:
106
+ None
107
+ """
108
+ logger.info("Loading state from Azure Blob Storage ...")
109
+
110
+ try:
111
+ container_client = self._create_container_client()
112
+
113
+ # Ensure the local directory exists
114
+ if not os.path.exists(target_directory):
115
+ os.makedirs(target_directory)
116
+
117
+ # List and download blobs
118
+ for blob in container_client.list_blobs():
119
+ blob_name = blob.name
120
+ blob_file_path = os.path.join(target_directory, blob_name)
121
+
122
+ # Create subdirectories locally if needed
123
+ os.makedirs(os.path.dirname(blob_file_path), exist_ok=True)
124
+
125
+ # Download blob to file
126
+ with open(blob_file_path, "wb") as file:
127
+ blob_client = container_client.get_blob_client(blob_name)
128
+ file.write(blob_client.download_blob().readall())
129
+
130
+ except Exception as ex:
131
+ logger.error(f"Error loading state from Azure Blob Storage: {ex}")
132
+ raise ex
133
+
134
+ def _create_container_client(self):
135
+ """
136
+ Internal helper to create a Container clinet.
137
+
138
+ Returns:
139
+ ContainerClient
140
+ """
141
+
142
+ # Ensure the container exists
143
+ try:
144
+ container_client = ContainerClient.from_connection_string(
145
+ conn_str=self.connection_string,
146
+ container_name=self.container_name
147
+ )
148
+ container_client.create_container(timeout=10)
149
+ except Exception as e:
150
+
151
+ if "ContainerAlreadyExists" in str(e):
152
+ pass
153
+ else:
154
+ raise OperationalException(
155
+ f"Error occurred while creating the container: {e}"
156
+ )
157
+
158
+ return container_client
@@ -0,0 +1,132 @@
1
+ from .backtesting import BacktestService
2
+ from .trade_order_evaluator import BacktestTradeOrderEvaluator, \
3
+ TradeOrderEvaluator, DefaultTradeOrderEvaluator
4
+ from .configuration_service import ConfigurationService
5
+ from .market_credential_service import MarketCredentialService
6
+ from .data_providers import DataProviderService
7
+ from .order_service import OrderService, OrderBacktestService, \
8
+ OrderExecutorLookup
9
+ from .portfolios import PortfolioService, BacktestPortfolioService, \
10
+ PortfolioConfigurationService, PortfolioSyncService, \
11
+ PortfolioSnapshotService, PortfolioProviderLookup
12
+ from .positions import PositionService, PositionSnapshotService
13
+ from .repository_service import RepositoryService
14
+ from .trade_service import TradeService
15
+ from .metrics import get_annual_volatility, \
16
+ get_sortino_ratio, get_drawdown_series, get_max_drawdown, \
17
+ get_equity_curve, get_price_efficiency_ratio, get_sharpe_ratio, \
18
+ get_profit_factor, get_cumulative_profit_factor_series, \
19
+ get_rolling_profit_factor_series, \
20
+ get_cagr, get_standard_deviation_returns, \
21
+ get_standard_deviation_downside_returns, \
22
+ get_total_return, get_cumulative_exposure, get_exposure_ratio, \
23
+ get_yearly_returns, get_monthly_returns, get_best_year, \
24
+ get_best_month, get_worst_year, get_worst_month, get_best_trade, \
25
+ get_worst_trade, get_average_yearly_return, get_average_trade_gain, \
26
+ get_average_trade_loss, get_average_monthly_return, \
27
+ get_percentage_winning_months, get_average_trade_duration, \
28
+ get_trade_frequency, get_win_rate, get_win_loss_ratio, \
29
+ get_calmar_ratio, get_max_drawdown_absolute, get_current_win_loss_ratio, \
30
+ get_max_drawdown_duration, get_max_daily_drawdown, get_trades_per_day, \
31
+ get_trades_per_year, get_average_monthly_return_losing_months, \
32
+ get_average_monthly_return_winning_months, get_percentage_winning_years, \
33
+ get_rolling_sharpe_ratio, create_backtest_metrics, get_total_growth, \
34
+ get_total_loss, get_risk_free_rate_us, get_median_trade_return, \
35
+ get_average_trade_return, get_cumulative_return, \
36
+ get_cumulative_return_series, get_average_trade_size, \
37
+ get_positive_trades, get_negative_trades, get_number_of_trades, \
38
+ get_current_win_rate, get_current_average_trade_return, \
39
+ get_current_average_trade_loss, get_current_average_trade_duration, \
40
+ get_current_average_trade_gain, create_backtest_metrics_for_backtest
41
+
42
+ __all__ = [
43
+ "OrderService",
44
+ "RepositoryService",
45
+ "PortfolioService",
46
+ "PositionService",
47
+ "PortfolioConfigurationService",
48
+ "BacktestService",
49
+ "OrderBacktestService",
50
+ "ConfigurationService",
51
+ "PortfolioSyncService",
52
+ "PortfolioSnapshotService",
53
+ "PositionSnapshotService",
54
+ "MarketCredentialService",
55
+ "BacktestPortfolioService",
56
+ "TradeService",
57
+ "DataProviderService",
58
+ "OrderExecutorLookup",
59
+ "BacktestTradeOrderEvaluator",
60
+ "PortfolioProviderLookup",
61
+ "TradeOrderEvaluator",
62
+ "DefaultTradeOrderEvaluator",
63
+ "get_risk_free_rate_us",
64
+ "get_annual_volatility",
65
+ "get_sortino_ratio",
66
+ "get_drawdown_series",
67
+ "get_max_drawdown",
68
+ "get_equity_curve",
69
+ "get_price_efficiency_ratio",
70
+ "get_sharpe_ratio",
71
+ "get_profit_factor",
72
+ "get_cumulative_profit_factor_series",
73
+ "get_rolling_profit_factor_series",
74
+ "get_sharpe_ratio",
75
+ "get_cagr",
76
+ "get_standard_deviation_returns",
77
+ "get_standard_deviation_downside_returns",
78
+ "get_max_drawdown_absolute",
79
+ "get_total_return",
80
+ "get_cumulative_exposure",
81
+ "get_exposure_ratio",
82
+ "get_average_trade_duration",
83
+ "get_win_rate",
84
+ "get_win_loss_ratio",
85
+ "get_calmar_ratio",
86
+ "get_trade_frequency",
87
+ "get_yearly_returns",
88
+ "get_monthly_returns",
89
+ "get_best_year",
90
+ "get_best_month",
91
+ "get_worst_year",
92
+ "get_worst_month",
93
+ "get_best_trade",
94
+ "get_worst_trade",
95
+ "get_average_yearly_return",
96
+ "get_average_trade_loss",
97
+ "get_average_monthly_return",
98
+ "get_percentage_winning_months",
99
+ "get_average_trade_duration",
100
+ "get_trade_frequency",
101
+ "get_win_rate",
102
+ "get_win_loss_ratio",
103
+ "get_calmar_ratio",
104
+ "get_max_drawdown_duration",
105
+ "get_max_daily_drawdown",
106
+ "get_trades_per_day",
107
+ "get_trades_per_year",
108
+ "get_average_monthly_return_losing_months",
109
+ "get_average_monthly_return_winning_months",
110
+ "get_percentage_winning_years",
111
+ "get_rolling_sharpe_ratio",
112
+ "get_total_growth",
113
+ "create_backtest_metrics",
114
+ "get_total_loss",
115
+ "get_median_trade_return",
116
+ "get_average_trade_gain",
117
+ "get_average_trade_size",
118
+ "get_average_trade_return",
119
+ "get_positive_trades",
120
+ "get_negative_trades",
121
+ "get_number_of_trades",
122
+ "get_cumulative_return",
123
+ "get_cumulative_return_series",
124
+ "get_current_win_loss_ratio",
125
+ "get_current_win_rate",
126
+ "get_current_win_loss_ratio",
127
+ "get_current_average_trade_loss",
128
+ "get_current_average_trade_duration",
129
+ "get_current_average_trade_gain",
130
+ "get_current_average_trade_return",
131
+ "create_backtest_metrics_for_backtest"
132
+ ]
@@ -0,0 +1,5 @@
1
+ from .backtest_service import BacktestService
2
+
3
+ __all__ = [
4
+ "BacktestService",
5
+ ]