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.
- investing_algorithm_framework/__init__.py +197 -0
- investing_algorithm_framework/app/__init__.py +47 -0
- investing_algorithm_framework/app/algorithm/__init__.py +7 -0
- investing_algorithm_framework/app/algorithm/algorithm.py +239 -0
- investing_algorithm_framework/app/algorithm/algorithm_factory.py +114 -0
- investing_algorithm_framework/app/analysis/__init__.py +15 -0
- investing_algorithm_framework/app/analysis/backtest_data_ranges.py +121 -0
- investing_algorithm_framework/app/analysis/backtest_utils.py +107 -0
- investing_algorithm_framework/app/analysis/permutation.py +116 -0
- investing_algorithm_framework/app/analysis/ranking.py +297 -0
- investing_algorithm_framework/app/app.py +2204 -0
- investing_algorithm_framework/app/app_hook.py +28 -0
- investing_algorithm_framework/app/context.py +1667 -0
- investing_algorithm_framework/app/eventloop.py +590 -0
- investing_algorithm_framework/app/reporting/__init__.py +27 -0
- investing_algorithm_framework/app/reporting/ascii.py +921 -0
- investing_algorithm_framework/app/reporting/backtest_report.py +349 -0
- investing_algorithm_framework/app/reporting/charts/__init__.py +19 -0
- investing_algorithm_framework/app/reporting/charts/entry_exist_signals.py +66 -0
- investing_algorithm_framework/app/reporting/charts/equity_curve.py +37 -0
- investing_algorithm_framework/app/reporting/charts/equity_curve_drawdown.py +74 -0
- investing_algorithm_framework/app/reporting/charts/line_chart.py +11 -0
- investing_algorithm_framework/app/reporting/charts/monthly_returns_heatmap.py +70 -0
- investing_algorithm_framework/app/reporting/charts/ohlcv_data_completeness.py +51 -0
- investing_algorithm_framework/app/reporting/charts/rolling_sharp_ratio.py +79 -0
- investing_algorithm_framework/app/reporting/charts/yearly_returns_barchart.py +55 -0
- investing_algorithm_framework/app/reporting/generate.py +185 -0
- investing_algorithm_framework/app/reporting/tables/__init__.py +11 -0
- investing_algorithm_framework/app/reporting/tables/key_metrics_table.py +217 -0
- investing_algorithm_framework/app/reporting/tables/stop_loss_table.py +0 -0
- investing_algorithm_framework/app/reporting/tables/time_metrics_table.py +80 -0
- investing_algorithm_framework/app/reporting/tables/trade_metrics_table.py +147 -0
- investing_algorithm_framework/app/reporting/tables/trades_table.py +75 -0
- investing_algorithm_framework/app/reporting/tables/utils.py +29 -0
- investing_algorithm_framework/app/reporting/templates/report_template.html.j2 +154 -0
- investing_algorithm_framework/app/stateless/__init__.py +35 -0
- investing_algorithm_framework/app/stateless/action_handlers/__init__.py +84 -0
- investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +8 -0
- investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +15 -0
- investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +40 -0
- investing_algorithm_framework/app/stateless/exception_handler.py +40 -0
- investing_algorithm_framework/app/strategy.py +675 -0
- investing_algorithm_framework/app/task.py +41 -0
- investing_algorithm_framework/app/web/__init__.py +5 -0
- investing_algorithm_framework/app/web/controllers/__init__.py +13 -0
- investing_algorithm_framework/app/web/controllers/orders.py +20 -0
- investing_algorithm_framework/app/web/controllers/portfolio.py +20 -0
- investing_algorithm_framework/app/web/controllers/positions.py +18 -0
- investing_algorithm_framework/app/web/create_app.py +20 -0
- investing_algorithm_framework/app/web/error_handler.py +59 -0
- investing_algorithm_framework/app/web/responses.py +20 -0
- investing_algorithm_framework/app/web/run_strategies.py +4 -0
- investing_algorithm_framework/app/web/schemas/__init__.py +12 -0
- investing_algorithm_framework/app/web/schemas/order.py +12 -0
- investing_algorithm_framework/app/web/schemas/portfolio.py +22 -0
- investing_algorithm_framework/app/web/schemas/position.py +15 -0
- investing_algorithm_framework/app/web/setup_cors.py +6 -0
- investing_algorithm_framework/cli/__init__.py +0 -0
- investing_algorithm_framework/cli/cli.py +207 -0
- investing_algorithm_framework/cli/deploy_to_aws_lambda.py +499 -0
- investing_algorithm_framework/cli/deploy_to_azure_function.py +718 -0
- investing_algorithm_framework/cli/initialize_app.py +603 -0
- investing_algorithm_framework/cli/templates/.gitignore.template +178 -0
- investing_algorithm_framework/cli/templates/app.py.template +18 -0
- investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +48 -0
- investing_algorithm_framework/cli/templates/app_azure_function.py.template +14 -0
- investing_algorithm_framework/cli/templates/app_web.py.template +18 -0
- investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +22 -0
- investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +92 -0
- investing_algorithm_framework/cli/templates/aws_lambda_readme.md.template +110 -0
- investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +2 -0
- investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +65 -0
- investing_algorithm_framework/cli/templates/azure_function_host.json.template +15 -0
- investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +8 -0
- investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +3 -0
- investing_algorithm_framework/cli/templates/data_providers.py.template +17 -0
- investing_algorithm_framework/cli/templates/env.example.template +2 -0
- investing_algorithm_framework/cli/templates/env_azure_function.example.template +4 -0
- investing_algorithm_framework/cli/templates/market_data_providers.py.template +9 -0
- investing_algorithm_framework/cli/templates/readme.md.template +135 -0
- investing_algorithm_framework/cli/templates/requirements.txt.template +2 -0
- investing_algorithm_framework/cli/templates/run_backtest.py.template +20 -0
- investing_algorithm_framework/cli/templates/strategy.py.template +124 -0
- investing_algorithm_framework/create_app.py +54 -0
- investing_algorithm_framework/dependency_container.py +155 -0
- investing_algorithm_framework/domain/__init__.py +148 -0
- investing_algorithm_framework/domain/backtesting/__init__.py +21 -0
- investing_algorithm_framework/domain/backtesting/backtest.py +503 -0
- investing_algorithm_framework/domain/backtesting/backtest_date_range.py +96 -0
- investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +242 -0
- investing_algorithm_framework/domain/backtesting/backtest_metrics.py +459 -0
- investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +275 -0
- investing_algorithm_framework/domain/backtesting/backtest_run.py +435 -0
- investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +162 -0
- investing_algorithm_framework/domain/backtesting/combine_backtests.py +280 -0
- investing_algorithm_framework/domain/config.py +111 -0
- investing_algorithm_framework/domain/constants.py +83 -0
- investing_algorithm_framework/domain/data_provider.py +334 -0
- investing_algorithm_framework/domain/data_structures.py +42 -0
- investing_algorithm_framework/domain/decimal_parsing.py +40 -0
- investing_algorithm_framework/domain/exceptions.py +112 -0
- investing_algorithm_framework/domain/models/__init__.py +43 -0
- investing_algorithm_framework/domain/models/app_mode.py +34 -0
- investing_algorithm_framework/domain/models/base_model.py +25 -0
- investing_algorithm_framework/domain/models/data/__init__.py +7 -0
- investing_algorithm_framework/domain/models/data/data_source.py +214 -0
- investing_algorithm_framework/domain/models/data/data_type.py +46 -0
- investing_algorithm_framework/domain/models/event.py +35 -0
- investing_algorithm_framework/domain/models/market/__init__.py +5 -0
- investing_algorithm_framework/domain/models/market/market_credential.py +88 -0
- investing_algorithm_framework/domain/models/order/__init__.py +6 -0
- investing_algorithm_framework/domain/models/order/order.py +384 -0
- investing_algorithm_framework/domain/models/order/order_side.py +36 -0
- investing_algorithm_framework/domain/models/order/order_status.py +37 -0
- investing_algorithm_framework/domain/models/order/order_type.py +30 -0
- investing_algorithm_framework/domain/models/portfolio/__init__.py +9 -0
- investing_algorithm_framework/domain/models/portfolio/portfolio.py +169 -0
- investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +93 -0
- investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +208 -0
- investing_algorithm_framework/domain/models/position/__init__.py +4 -0
- investing_algorithm_framework/domain/models/position/position.py +68 -0
- investing_algorithm_framework/domain/models/position/position_snapshot.py +47 -0
- investing_algorithm_framework/domain/models/snapshot_interval.py +45 -0
- investing_algorithm_framework/domain/models/strategy_profile.py +33 -0
- investing_algorithm_framework/domain/models/time_frame.py +153 -0
- investing_algorithm_framework/domain/models/time_interval.py +124 -0
- investing_algorithm_framework/domain/models/time_unit.py +149 -0
- investing_algorithm_framework/domain/models/tracing/__init__.py +0 -0
- investing_algorithm_framework/domain/models/tracing/trace.py +23 -0
- investing_algorithm_framework/domain/models/trade/__init__.py +13 -0
- investing_algorithm_framework/domain/models/trade/trade.py +388 -0
- investing_algorithm_framework/domain/models/trade/trade_risk_type.py +34 -0
- investing_algorithm_framework/domain/models/trade/trade_status.py +40 -0
- investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +267 -0
- investing_algorithm_framework/domain/models/trade/trade_take_profit.py +303 -0
- investing_algorithm_framework/domain/order_executor.py +112 -0
- investing_algorithm_framework/domain/portfolio_provider.py +118 -0
- investing_algorithm_framework/domain/positions/__init__.py +4 -0
- investing_algorithm_framework/domain/positions/position_size.py +41 -0
- investing_algorithm_framework/domain/services/__init__.py +11 -0
- investing_algorithm_framework/domain/services/market_credential_service.py +37 -0
- investing_algorithm_framework/domain/services/portfolios/__init__.py +5 -0
- investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +9 -0
- investing_algorithm_framework/domain/services/rounding_service.py +27 -0
- investing_algorithm_framework/domain/services/state_handler.py +38 -0
- investing_algorithm_framework/domain/stateless_actions.py +7 -0
- investing_algorithm_framework/domain/strategy.py +44 -0
- investing_algorithm_framework/domain/utils/__init__.py +27 -0
- investing_algorithm_framework/domain/utils/csv.py +104 -0
- investing_algorithm_framework/domain/utils/custom_tqdm.py +22 -0
- investing_algorithm_framework/domain/utils/dates.py +57 -0
- investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +19 -0
- investing_algorithm_framework/domain/utils/polars.py +53 -0
- investing_algorithm_framework/domain/utils/random.py +41 -0
- investing_algorithm_framework/domain/utils/signatures.py +17 -0
- investing_algorithm_framework/domain/utils/stoppable_thread.py +26 -0
- investing_algorithm_framework/domain/utils/synchronized.py +12 -0
- investing_algorithm_framework/download_data.py +108 -0
- investing_algorithm_framework/infrastructure/__init__.py +50 -0
- investing_algorithm_framework/infrastructure/data_providers/__init__.py +36 -0
- investing_algorithm_framework/infrastructure/data_providers/ccxt.py +1143 -0
- investing_algorithm_framework/infrastructure/data_providers/csv.py +568 -0
- investing_algorithm_framework/infrastructure/data_providers/pandas.py +599 -0
- investing_algorithm_framework/infrastructure/database/__init__.py +10 -0
- investing_algorithm_framework/infrastructure/database/sql_alchemy.py +120 -0
- investing_algorithm_framework/infrastructure/models/__init__.py +16 -0
- investing_algorithm_framework/infrastructure/models/decimal_parser.py +14 -0
- investing_algorithm_framework/infrastructure/models/model_extension.py +6 -0
- investing_algorithm_framework/infrastructure/models/order/__init__.py +4 -0
- investing_algorithm_framework/infrastructure/models/order/order.py +124 -0
- investing_algorithm_framework/infrastructure/models/order/order_metadata.py +44 -0
- investing_algorithm_framework/infrastructure/models/order_trade_association.py +10 -0
- investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +4 -0
- investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +37 -0
- investing_algorithm_framework/infrastructure/models/portfolio/sql_portfolio.py +114 -0
- investing_algorithm_framework/infrastructure/models/position/__init__.py +4 -0
- investing_algorithm_framework/infrastructure/models/position/position.py +63 -0
- investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +23 -0
- investing_algorithm_framework/infrastructure/models/trades/__init__.py +9 -0
- investing_algorithm_framework/infrastructure/models/trades/trade.py +130 -0
- investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +40 -0
- investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +41 -0
- investing_algorithm_framework/infrastructure/order_executors/__init__.py +21 -0
- investing_algorithm_framework/infrastructure/order_executors/backtest_oder_executor.py +28 -0
- investing_algorithm_framework/infrastructure/order_executors/ccxt_order_executor.py +200 -0
- investing_algorithm_framework/infrastructure/portfolio_providers/__init__.py +19 -0
- investing_algorithm_framework/infrastructure/portfolio_providers/ccxt_portfolio_provider.py +199 -0
- investing_algorithm_framework/infrastructure/repositories/__init__.py +21 -0
- investing_algorithm_framework/infrastructure/repositories/order_metadata_repository.py +17 -0
- investing_algorithm_framework/infrastructure/repositories/order_repository.py +96 -0
- investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +30 -0
- investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +56 -0
- investing_algorithm_framework/infrastructure/repositories/position_repository.py +66 -0
- investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +21 -0
- investing_algorithm_framework/infrastructure/repositories/repository.py +299 -0
- investing_algorithm_framework/infrastructure/repositories/trade_repository.py +71 -0
- investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +23 -0
- investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +23 -0
- investing_algorithm_framework/infrastructure/services/__init__.py +7 -0
- investing_algorithm_framework/infrastructure/services/aws/__init__.py +6 -0
- investing_algorithm_framework/infrastructure/services/aws/state_handler.py +113 -0
- investing_algorithm_framework/infrastructure/services/azure/__init__.py +5 -0
- investing_algorithm_framework/infrastructure/services/azure/state_handler.py +158 -0
- investing_algorithm_framework/services/__init__.py +132 -0
- investing_algorithm_framework/services/backtesting/__init__.py +5 -0
- investing_algorithm_framework/services/backtesting/backtest_service.py +651 -0
- investing_algorithm_framework/services/configuration_service.py +96 -0
- investing_algorithm_framework/services/data_providers/__init__.py +5 -0
- investing_algorithm_framework/services/data_providers/data_provider_service.py +850 -0
- investing_algorithm_framework/services/market_credential_service.py +40 -0
- investing_algorithm_framework/services/metrics/__init__.py +114 -0
- investing_algorithm_framework/services/metrics/alpha.py +0 -0
- investing_algorithm_framework/services/metrics/beta.py +0 -0
- investing_algorithm_framework/services/metrics/cagr.py +60 -0
- investing_algorithm_framework/services/metrics/calmar_ratio.py +40 -0
- investing_algorithm_framework/services/metrics/drawdown.py +181 -0
- investing_algorithm_framework/services/metrics/equity_curve.py +24 -0
- investing_algorithm_framework/services/metrics/exposure.py +210 -0
- investing_algorithm_framework/services/metrics/generate.py +358 -0
- investing_algorithm_framework/services/metrics/mean_daily_return.py +83 -0
- investing_algorithm_framework/services/metrics/price_efficiency.py +57 -0
- investing_algorithm_framework/services/metrics/profit_factor.py +165 -0
- investing_algorithm_framework/services/metrics/recovery.py +113 -0
- investing_algorithm_framework/services/metrics/returns.py +452 -0
- investing_algorithm_framework/services/metrics/risk_free_rate.py +28 -0
- investing_algorithm_framework/services/metrics/sharpe_ratio.py +137 -0
- investing_algorithm_framework/services/metrics/sortino_ratio.py +74 -0
- investing_algorithm_framework/services/metrics/standard_deviation.py +157 -0
- investing_algorithm_framework/services/metrics/trades.py +500 -0
- investing_algorithm_framework/services/metrics/treynor_ratio.py +0 -0
- investing_algorithm_framework/services/metrics/ulcer.py +0 -0
- investing_algorithm_framework/services/metrics/value_at_risk.py +0 -0
- investing_algorithm_framework/services/metrics/volatility.py +97 -0
- investing_algorithm_framework/services/metrics/win_rate.py +177 -0
- investing_algorithm_framework/services/order_service/__init__.py +9 -0
- investing_algorithm_framework/services/order_service/order_backtest_service.py +178 -0
- investing_algorithm_framework/services/order_service/order_executor_lookup.py +110 -0
- investing_algorithm_framework/services/order_service/order_service.py +826 -0
- investing_algorithm_framework/services/portfolios/__init__.py +16 -0
- investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +54 -0
- investing_algorithm_framework/services/portfolios/portfolio_configuration_service.py +75 -0
- investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +106 -0
- investing_algorithm_framework/services/portfolios/portfolio_service.py +188 -0
- investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +136 -0
- investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +182 -0
- investing_algorithm_framework/services/positions/__init__.py +7 -0
- investing_algorithm_framework/services/positions/position_service.py +210 -0
- investing_algorithm_framework/services/positions/position_snapshot_service.py +18 -0
- investing_algorithm_framework/services/repository_service.py +40 -0
- investing_algorithm_framework/services/trade_order_evaluator/__init__.py +9 -0
- investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +132 -0
- investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +66 -0
- investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +41 -0
- investing_algorithm_framework/services/trade_service/__init__.py +3 -0
- investing_algorithm_framework/services/trade_service/trade_service.py +1083 -0
- investing_algorithm_framework-7.19.14.dist-info/LICENSE +201 -0
- investing_algorithm_framework-7.19.14.dist-info/METADATA +459 -0
- investing_algorithm_framework-7.19.14.dist-info/RECORD +260 -0
- investing_algorithm_framework-7.19.14.dist-info/WHEEL +4 -0
- 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,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,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
|
+
]
|