investing-algorithm-framework 1.3.1__py3-none-any.whl → 7.25.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- investing_algorithm_framework/__init__.py +195 -16
- investing_algorithm_framework/analysis/__init__.py +16 -0
- investing_algorithm_framework/analysis/backtest_data_ranges.py +202 -0
- investing_algorithm_framework/analysis/data.py +170 -0
- investing_algorithm_framework/analysis/markdown.py +91 -0
- investing_algorithm_framework/analysis/ranking.py +298 -0
- investing_algorithm_framework/app/__init__.py +31 -4
- investing_algorithm_framework/app/algorithm/__init__.py +7 -0
- investing_algorithm_framework/app/algorithm/algorithm.py +193 -0
- investing_algorithm_framework/app/algorithm/algorithm_factory.py +118 -0
- investing_algorithm_framework/app/app.py +2233 -264
- investing_algorithm_framework/app/app_hook.py +28 -0
- investing_algorithm_framework/app/context.py +1724 -0
- investing_algorithm_framework/app/eventloop.py +620 -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/action_handlers/__init__.py +6 -3
- investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +1 -1
- investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +2 -1
- investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +14 -7
- investing_algorithm_framework/app/stateless/exception_handler.py +1 -1
- investing_algorithm_framework/app/strategy.py +873 -52
- investing_algorithm_framework/app/task.py +5 -3
- investing_algorithm_framework/app/web/__init__.py +2 -1
- investing_algorithm_framework/app/web/controllers/__init__.py +2 -2
- investing_algorithm_framework/app/web/controllers/orders.py +4 -3
- investing_algorithm_framework/app/web/controllers/portfolio.py +1 -1
- investing_algorithm_framework/app/web/controllers/positions.py +3 -3
- investing_algorithm_framework/app/web/create_app.py +4 -2
- investing_algorithm_framework/app/web/error_handler.py +1 -1
- investing_algorithm_framework/app/web/schemas/order.py +2 -2
- investing_algorithm_framework/app/web/schemas/position.py +1 -0
- investing_algorithm_framework/cli/__init__.py +0 -0
- investing_algorithm_framework/cli/cli.py +231 -0
- investing_algorithm_framework/cli/deploy_to_aws_lambda.py +501 -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/cli/validate_backtest_checkpoints.py +197 -0
- investing_algorithm_framework/create_app.py +43 -9
- investing_algorithm_framework/dependency_container.py +121 -33
- investing_algorithm_framework/domain/__init__.py +109 -22
- investing_algorithm_framework/domain/algorithm_id.py +69 -0
- investing_algorithm_framework/domain/backtesting/__init__.py +25 -0
- investing_algorithm_framework/domain/backtesting/backtest.py +548 -0
- investing_algorithm_framework/domain/backtesting/backtest_date_range.py +113 -0
- investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +241 -0
- investing_algorithm_framework/domain/backtesting/backtest_metrics.py +470 -0
- investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +275 -0
- investing_algorithm_framework/domain/backtesting/backtest_run.py +663 -0
- investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +162 -0
- investing_algorithm_framework/domain/backtesting/backtest_utils.py +198 -0
- investing_algorithm_framework/domain/backtesting/combine_backtests.py +392 -0
- investing_algorithm_framework/domain/config.py +60 -138
- investing_algorithm_framework/domain/constants.py +23 -34
- 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 +51 -1
- investing_algorithm_framework/domain/models/__init__.py +29 -14
- investing_algorithm_framework/domain/models/app_mode.py +34 -0
- investing_algorithm_framework/domain/models/base_model.py +3 -1
- investing_algorithm_framework/domain/models/data/__init__.py +7 -0
- investing_algorithm_framework/domain/models/data/data_source.py +222 -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 +3 -4
- investing_algorithm_framework/domain/models/order/order.py +243 -86
- investing_algorithm_framework/domain/models/order/order_status.py +2 -2
- investing_algorithm_framework/domain/models/order/order_type.py +1 -3
- investing_algorithm_framework/domain/models/portfolio/__init__.py +7 -2
- investing_algorithm_framework/domain/models/portfolio/portfolio.py +134 -1
- investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +37 -37
- investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +208 -0
- investing_algorithm_framework/domain/models/position/__init__.py +3 -2
- investing_algorithm_framework/domain/models/position/position.py +29 -0
- investing_algorithm_framework/domain/models/position/position_size.py +41 -0
- investing_algorithm_framework/domain/models/position/{position_cost.py → position_snapshot.py} +16 -8
- investing_algorithm_framework/domain/models/risk_rules/__init__.py +7 -0
- investing_algorithm_framework/domain/models/risk_rules/stop_loss_rule.py +51 -0
- investing_algorithm_framework/domain/models/risk_rules/take_profit_rule.py +55 -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 +94 -98
- investing_algorithm_framework/domain/models/time_interval.py +33 -0
- investing_algorithm_framework/domain/models/time_unit.py +111 -2
- 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 +11 -0
- investing_algorithm_framework/domain/models/trade/trade.py +389 -0
- investing_algorithm_framework/domain/models/trade/trade_status.py +40 -0
- investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +332 -0
- investing_algorithm_framework/domain/models/trade/trade_take_profit.py +365 -0
- investing_algorithm_framework/domain/order_executor.py +112 -0
- investing_algorithm_framework/domain/portfolio_provider.py +118 -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/strategy.py +1 -29
- investing_algorithm_framework/domain/utils/__init__.py +16 -4
- investing_algorithm_framework/domain/utils/csv.py +22 -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 +29 -0
- investing_algorithm_framework/download_data.py +244 -0
- investing_algorithm_framework/infrastructure/__init__.py +39 -11
- investing_algorithm_framework/infrastructure/data_providers/__init__.py +36 -0
- investing_algorithm_framework/infrastructure/data_providers/ccxt.py +1152 -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 +6 -2
- investing_algorithm_framework/infrastructure/database/sql_alchemy.py +87 -13
- investing_algorithm_framework/infrastructure/models/__init__.py +13 -4
- investing_algorithm_framework/infrastructure/models/decimal_parser.py +14 -0
- investing_algorithm_framework/infrastructure/models/order/__init__.py +2 -2
- investing_algorithm_framework/infrastructure/models/order/order.py +73 -73
- 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 +3 -2
- investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +37 -0
- investing_algorithm_framework/infrastructure/models/portfolio/{portfolio.py → sql_portfolio.py} +57 -3
- investing_algorithm_framework/infrastructure/models/position/__init__.py +2 -2
- investing_algorithm_framework/infrastructure/models/position/position.py +16 -11
- 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 +59 -0
- investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +55 -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 +13 -5
- investing_algorithm_framework/infrastructure/repositories/order_metadata_repository.py +17 -0
- investing_algorithm_framework/infrastructure/repositories/order_repository.py +32 -19
- investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +2 -2
- investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +56 -0
- investing_algorithm_framework/infrastructure/repositories/position_repository.py +47 -4
- investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +21 -0
- investing_algorithm_framework/infrastructure/repositories/repository.py +85 -31
- investing_algorithm_framework/infrastructure/repositories/trade_repository.py +71 -0
- investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +29 -0
- investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +29 -0
- investing_algorithm_framework/infrastructure/services/__init__.py +9 -2
- investing_algorithm_framework/infrastructure/services/aws/__init__.py +6 -0
- investing_algorithm_framework/infrastructure/services/aws/state_handler.py +193 -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/infrastructure/services/backtesting/__init__.py +9 -0
- investing_algorithm_framework/infrastructure/services/backtesting/backtest_service.py +2596 -0
- investing_algorithm_framework/infrastructure/services/backtesting/event_backtest_service.py +285 -0
- investing_algorithm_framework/infrastructure/services/backtesting/vector_backtest_service.py +468 -0
- investing_algorithm_framework/services/__init__.py +127 -10
- investing_algorithm_framework/services/configuration_service.py +95 -0
- investing_algorithm_framework/services/data_providers/__init__.py +5 -0
- investing_algorithm_framework/services/data_providers/data_provider_service.py +1058 -0
- investing_algorithm_framework/services/market_credential_service.py +40 -0
- investing_algorithm_framework/services/metrics/__init__.py +119 -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 +218 -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 +84 -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 +156 -0
- investing_algorithm_framework/services/metrics/trades.py +473 -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 +118 -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/{portfolio_configuration_service.py → portfolios/portfolio_configuration_service.py} +27 -12
- 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 +8 -2
- investing_algorithm_framework/services/trade_order_evaluator/__init__.py +9 -0
- investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +117 -0
- investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +51 -0
- investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +80 -0
- investing_algorithm_framework/services/trade_service/__init__.py +9 -0
- investing_algorithm_framework/services/trade_service/trade_service.py +1099 -0
- investing_algorithm_framework/services/trade_service/trade_stop_loss_service.py +39 -0
- investing_algorithm_framework/services/trade_service/trade_take_profit_service.py +41 -0
- investing_algorithm_framework-7.25.6.dist-info/METADATA +535 -0
- investing_algorithm_framework-7.25.6.dist-info/RECORD +268 -0
- {investing_algorithm_framework-1.3.1.dist-info → investing_algorithm_framework-7.25.6.dist-info}/WHEEL +1 -2
- investing_algorithm_framework-7.25.6.dist-info/entry_points.txt +3 -0
- investing_algorithm_framework/app/algorithm.py +0 -410
- investing_algorithm_framework/domain/models/market_data/__init__.py +0 -11
- investing_algorithm_framework/domain/models/market_data/asset_price.py +0 -50
- investing_algorithm_framework/domain/models/market_data/ohlcv.py +0 -76
- investing_algorithm_framework/domain/models/market_data/order_book.py +0 -63
- investing_algorithm_framework/domain/models/market_data/ticker.py +0 -92
- investing_algorithm_framework/domain/models/order/order_fee.py +0 -45
- investing_algorithm_framework/domain/models/trading_data_types.py +0 -47
- investing_algorithm_framework/domain/models/trading_time_frame.py +0 -205
- investing_algorithm_framework/domain/singleton.py +0 -9
- investing_algorithm_framework/infrastructure/models/order/order_fee.py +0 -21
- investing_algorithm_framework/infrastructure/models/position/position_cost.py +0 -32
- investing_algorithm_framework/infrastructure/repositories/order_fee_repository.py +0 -15
- investing_algorithm_framework/infrastructure/repositories/position_cost_repository.py +0 -16
- investing_algorithm_framework/infrastructure/services/market_service.py +0 -422
- investing_algorithm_framework/services/market_data_service.py +0 -75
- investing_algorithm_framework/services/order_service.py +0 -464
- investing_algorithm_framework/services/portfolio_service.py +0 -105
- investing_algorithm_framework/services/position_cost_service.py +0 -5
- investing_algorithm_framework/services/position_service.py +0 -50
- investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -219
- investing_algorithm_framework/setup_logging.py +0 -40
- investing_algorithm_framework-1.3.1.dist-info/AUTHORS.md +0 -8
- investing_algorithm_framework-1.3.1.dist-info/METADATA +0 -172
- investing_algorithm_framework-1.3.1.dist-info/RECORD +0 -103
- investing_algorithm_framework-1.3.1.dist-info/top_level.txt +0 -1
- {investing_algorithm_framework-1.3.1.dist-info → investing_algorithm_framework-7.25.6.dist-info}/LICENSE +0 -0
|
@@ -1,16 +1,24 @@
|
|
|
1
|
-
from datetime import datetime, timedelta
|
|
2
1
|
from enum import Enum
|
|
3
2
|
|
|
4
|
-
from dateutil import relativedelta
|
|
5
|
-
|
|
6
3
|
|
|
7
4
|
class TimeFrame(Enum):
|
|
8
5
|
CURRENT = "CURRENT"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
ONE_MINUTE = "1m"
|
|
7
|
+
TWO_MINUTE = "2m"
|
|
8
|
+
THREE_MINUTE = "3m"
|
|
9
|
+
FOUR_MINUTE = "4m"
|
|
10
|
+
FIVE_MINUTE = "5m"
|
|
11
|
+
TEN_MINUTE = "10m"
|
|
12
|
+
FIFTEEN_MINUTE = "15m"
|
|
13
|
+
THIRTY_MINUTE = "30m"
|
|
14
|
+
ONE_HOUR = "1h"
|
|
15
|
+
TWO_HOUR = "2h"
|
|
16
|
+
FOUR_HOUR = "4h"
|
|
17
|
+
TWELVE_HOUR = "12h"
|
|
18
|
+
ONE_DAY = "1d"
|
|
19
|
+
ONE_WEEK = "1W"
|
|
20
|
+
ONE_MONTH = "1M"
|
|
21
|
+
ONE_YEAR = "1Y"
|
|
14
22
|
|
|
15
23
|
@staticmethod
|
|
16
24
|
def from_string(value: str):
|
|
@@ -19,7 +27,25 @@ class TimeFrame(Enum):
|
|
|
19
27
|
|
|
20
28
|
for entry in TimeFrame:
|
|
21
29
|
|
|
22
|
-
|
|
30
|
+
# For hour timeframes compare with and without H
|
|
31
|
+
if "H" in entry.value:
|
|
32
|
+
|
|
33
|
+
if value == entry.value:
|
|
34
|
+
return entry
|
|
35
|
+
|
|
36
|
+
if value == entry.value.replace("H", "h"):
|
|
37
|
+
return entry
|
|
38
|
+
|
|
39
|
+
# For hour timeframes compare with and without H
|
|
40
|
+
if "d" in entry.value:
|
|
41
|
+
|
|
42
|
+
if value == entry.value:
|
|
43
|
+
return entry
|
|
44
|
+
|
|
45
|
+
if value == entry.value.replace("d", "D"):
|
|
46
|
+
return entry
|
|
47
|
+
|
|
48
|
+
if value == entry.value:
|
|
23
49
|
return entry
|
|
24
50
|
|
|
25
51
|
raise ValueError(
|
|
@@ -50,108 +76,78 @@ class TimeFrame(Enum):
|
|
|
50
76
|
else:
|
|
51
77
|
return TimeFrame.from_string(other) == self
|
|
52
78
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if end_datetime is None:
|
|
56
|
-
end_datetime = datetime.utcnow()
|
|
57
|
-
|
|
58
|
-
if TimeFrame.ONE_HOUR.equals(self):
|
|
59
|
-
start_datetime = end_datetime - \
|
|
60
|
-
relativedelta.relativedelta(hours=1)
|
|
61
|
-
elif TimeFrame.ONE_DAY.equals(self):
|
|
62
|
-
start_datetime = end_datetime - \
|
|
63
|
-
relativedelta.relativedelta(hours=24)
|
|
64
|
-
elif TimeFrame.ONE_WEEK.equals(self):
|
|
65
|
-
start_datetime = end_datetime - \
|
|
66
|
-
relativedelta.relativedelta(days=7)
|
|
67
|
-
elif TimeFrame.ONE_MONTH.equals(self):
|
|
68
|
-
start_datetime = \
|
|
69
|
-
end_datetime - relativedelta.relativedelta(days=28)
|
|
70
|
-
elif TimeFrame.ONE_YEAR.equals(self):
|
|
71
|
-
start_datetime = \
|
|
72
|
-
end_datetime - relativedelta.relativedelta(days=365)
|
|
73
|
-
else:
|
|
74
|
-
raise NotImplementedError(
|
|
75
|
-
f"Timeframe {self.value} not implemented"
|
|
76
|
-
)
|
|
79
|
+
@property
|
|
80
|
+
def amount_of_minutes(self):
|
|
77
81
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def duration(self):
|
|
81
|
-
if TimeFrame.ONE_HOUR.equals(self):
|
|
82
|
-
return relativedelta.relativedelta(hours=1)
|
|
83
|
-
elif TimeFrame.ONE_DAY.equals(self):
|
|
84
|
-
return relativedelta.relativedelta(hours=24)
|
|
85
|
-
elif TimeFrame.ONE_WEEK.equals(self):
|
|
86
|
-
return relativedelta.relativedelta(days=7)
|
|
87
|
-
elif TimeFrame.ONE_MONTH.equals(self):
|
|
88
|
-
return relativedelta.relativedelta(days=28)
|
|
89
|
-
elif TimeFrame.ONE_YEAR.equals(self):
|
|
90
|
-
return relativedelta.relativedelta(days=365)
|
|
91
|
-
else:
|
|
92
|
-
raise NotImplementedError(
|
|
93
|
-
f"Timeframe {self.value} not implemented"
|
|
94
|
-
)
|
|
82
|
+
if self.equals(TimeFrame.ONE_MINUTE):
|
|
83
|
+
return 1
|
|
95
84
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
from investing_algorithm_framework.core.models import TimeInterval
|
|
99
|
-
|
|
100
|
-
if TimeFrame.CURRENT.equals(self):
|
|
101
|
-
return TimeInterval.CURRENT
|
|
102
|
-
elif TimeFrame.ONE_HOUR.equals(self):
|
|
103
|
-
return TimeInterval.MINUTES_ONE
|
|
104
|
-
elif TimeFrame.ONE_DAY.equals(self):
|
|
105
|
-
return TimeInterval.MINUTES_FIFTEEN
|
|
106
|
-
elif TimeFrame.ONE_WEEK.equals(self):
|
|
107
|
-
return TimeInterval.HOURS_ONE
|
|
108
|
-
elif TimeFrame.ONE_MONTH.equals(self):
|
|
109
|
-
return TimeInterval.HOURS_FOUR
|
|
110
|
-
elif TimeFrame.ONE_YEAR.equals(self):
|
|
111
|
-
return TimeInterval.DAYS_ONE
|
|
112
|
-
else:
|
|
113
|
-
raise NotImplementedError(
|
|
114
|
-
f"Timeframe {self.value} not implemented"
|
|
115
|
-
)
|
|
85
|
+
if self.equals(TimeFrame.TWO_MINUTE):
|
|
86
|
+
return 2
|
|
116
87
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
intervals = []
|
|
120
|
-
start_datetime, end_datetime = self.create_time_frame()
|
|
121
|
-
delta = end_datetime - start_datetime
|
|
88
|
+
if self.equals(TimeFrame.THREE_MINUTE):
|
|
89
|
+
return 3
|
|
122
90
|
|
|
123
|
-
|
|
91
|
+
if self.equals(TimeFrame.FOUR_MINUTE):
|
|
92
|
+
return 4
|
|
124
93
|
|
|
125
|
-
if
|
|
94
|
+
if self.equals(TimeFrame.FIVE_MINUTE):
|
|
95
|
+
return 5
|
|
126
96
|
|
|
127
|
-
|
|
128
|
-
|
|
97
|
+
if self.equals(TimeFrame.TEN_MINUTE):
|
|
98
|
+
return 10
|
|
129
99
|
|
|
130
|
-
|
|
100
|
+
if self.equals(TimeFrame.FIFTEEN_MINUTE):
|
|
101
|
+
return 15
|
|
131
102
|
|
|
132
|
-
|
|
133
|
-
|
|
103
|
+
if self.equals(TimeFrame.THIRTY_MINUTE):
|
|
104
|
+
return 30
|
|
134
105
|
|
|
135
|
-
|
|
106
|
+
if self.equals(TimeFrame.ONE_HOUR):
|
|
107
|
+
return 60
|
|
136
108
|
|
|
137
|
-
|
|
138
|
-
|
|
109
|
+
if self.equals(TimeFrame.TWO_HOUR):
|
|
110
|
+
return 120
|
|
139
111
|
|
|
140
|
-
|
|
112
|
+
if self.equals(TimeFrame.FOUR_HOUR):
|
|
113
|
+
return 240
|
|
141
114
|
|
|
142
|
-
|
|
143
|
-
|
|
115
|
+
if self.equals(TimeFrame.TWELVE_HOUR):
|
|
116
|
+
return 720
|
|
144
117
|
|
|
145
|
-
|
|
118
|
+
if self.equals(TimeFrame.ONE_DAY):
|
|
119
|
+
return 1440
|
|
146
120
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
end_datetime - relativedelta.relativedelta(days=i)
|
|
150
|
-
)
|
|
121
|
+
if self.equals(TimeFrame.ONE_WEEK):
|
|
122
|
+
return 10080
|
|
151
123
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
124
|
+
if self.equals(TimeFrame.ONE_MONTH):
|
|
125
|
+
return 40320
|
|
126
|
+
|
|
127
|
+
if self.equals(TimeFrame.ONE_YEAR):
|
|
128
|
+
return 525600
|
|
129
|
+
|
|
130
|
+
raise ValueError(
|
|
131
|
+
f"Could not determine amount of minutes for {self.value}"
|
|
132
|
+
)
|
|
156
133
|
|
|
157
|
-
|
|
134
|
+
# Add comparison methods for ordering
|
|
135
|
+
def __lt__(self, other):
|
|
136
|
+
if isinstance(other, TimeFrame):
|
|
137
|
+
return self.amount_of_minutes < other.amount_of_minutes
|
|
138
|
+
raise TypeError(f"Cannot compare TimeFrame with {type(other)}")
|
|
139
|
+
|
|
140
|
+
def __le__(self, other):
|
|
141
|
+
if isinstance(other, TimeFrame):
|
|
142
|
+
return self.amount_of_minutes <= other.amount_of_minutes
|
|
143
|
+
raise TypeError(f"Cannot compare TimeFrame with {type(other)}")
|
|
144
|
+
|
|
145
|
+
def __gt__(self, other):
|
|
146
|
+
if isinstance(other, TimeFrame):
|
|
147
|
+
return self.amount_of_minutes > other.amount_of_minutes
|
|
148
|
+
raise TypeError(f"Cannot compare TimeFrame with {type(other)}")
|
|
149
|
+
|
|
150
|
+
def __ge__(self, other):
|
|
151
|
+
if isinstance(other, TimeFrame):
|
|
152
|
+
return self.amount_of_minutes >= other.amount_of_minutes
|
|
153
|
+
raise TypeError(f"Cannot compare TimeFrame with {type(other)}")
|
|
@@ -25,6 +25,39 @@ class TimeInterval(Enum):
|
|
|
25
25
|
f"Could not convert {value} to TimeInterval"
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
+
@staticmethod
|
|
29
|
+
def from_ohlcv_data_file(file_path: str):
|
|
30
|
+
"""
|
|
31
|
+
Extracts the time interval from the file name of an OHLCV data file.
|
|
32
|
+
The file name should contain the time interval in the format
|
|
33
|
+
'symbol_timeinterval.csv'.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
file_path (str): The file path of the OHLCV data file.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
TimeInterval: The extracted time interval.
|
|
40
|
+
"""
|
|
41
|
+
if not isinstance(file_path, str):
|
|
42
|
+
raise ValueError("File path must be a string.")
|
|
43
|
+
|
|
44
|
+
parts = file_path.split('_')
|
|
45
|
+
if len(parts) < 2:
|
|
46
|
+
raise ValueError(
|
|
47
|
+
"File name does not contain a valid time interval."
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
time_interval_str = parts[-1].split('.')[0].upper()
|
|
51
|
+
try:
|
|
52
|
+
return TimeInterval.from_string(time_interval_str)
|
|
53
|
+
except ValueError:
|
|
54
|
+
raise ValueError(
|
|
55
|
+
"Could not extract time interval from "
|
|
56
|
+
f"file name: {file_path}. "
|
|
57
|
+
"Expected format 'symbol_timeinterval.csv', "
|
|
58
|
+
f"got '{time_interval_str}'."
|
|
59
|
+
)
|
|
60
|
+
|
|
28
61
|
def equals(self, other):
|
|
29
62
|
|
|
30
63
|
if isinstance(other, Enum):
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
+
from datetime import timedelta
|
|
1
2
|
from enum import Enum
|
|
3
|
+
from investing_algorithm_framework.domain.exceptions import \
|
|
4
|
+
OperationalException
|
|
2
5
|
|
|
3
6
|
|
|
4
7
|
class TimeUnit(Enum):
|
|
8
|
+
"""
|
|
9
|
+
Enum class the represents a time unit such as
|
|
10
|
+
second, minute, hour or day. This can class
|
|
11
|
+
can be used to specify time specification within
|
|
12
|
+
the framework.
|
|
13
|
+
"""
|
|
5
14
|
SECOND = "SECOND"
|
|
6
15
|
MINUTE = "MINUTE"
|
|
7
16
|
HOUR = "HOUR"
|
|
17
|
+
DAY = "DAY"
|
|
8
18
|
|
|
9
19
|
@staticmethod
|
|
10
20
|
def from_string(value: str):
|
|
@@ -16,10 +26,50 @@ class TimeUnit(Enum):
|
|
|
16
26
|
if value.upper() == entry.value:
|
|
17
27
|
return entry
|
|
18
28
|
|
|
19
|
-
|
|
20
|
-
|
|
29
|
+
raise OperationalException(
|
|
30
|
+
f"Could not convert string {value} to time unit"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
raise OperationalException(
|
|
34
|
+
f"Could not convert value {value} to time unit," +
|
|
35
|
+
" please make sure that the value is either of type string or" +
|
|
36
|
+
f"TimeUnit. Its current type is {type(value)}"
|
|
21
37
|
)
|
|
22
38
|
|
|
39
|
+
@staticmethod
|
|
40
|
+
def from_ohlcv_data_file(file_path: str):
|
|
41
|
+
"""
|
|
42
|
+
Extracts the time unit from the file name of an OHLCV data file.
|
|
43
|
+
The file name should contain the time unit in the
|
|
44
|
+
format 'symbol_timeunit.csv'.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
file_path (str): The file path of the OHLCV data file.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
TimeUnit: The extracted time unit.
|
|
51
|
+
"""
|
|
52
|
+
if not isinstance(file_path, str):
|
|
53
|
+
raise OperationalException(
|
|
54
|
+
"File path must be a string."
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
parts = file_path.split('_')
|
|
58
|
+
if len(parts) < 2:
|
|
59
|
+
raise OperationalException(
|
|
60
|
+
"File name does not contain a valid time unit."
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
time_unit_str = parts[-1].split('.')[0].upper()
|
|
64
|
+
try:
|
|
65
|
+
return TimeUnit.from_string(time_unit_str)
|
|
66
|
+
except ValueError:
|
|
67
|
+
raise OperationalException(
|
|
68
|
+
f"Could not extract time unit from file name: {file_path}. "
|
|
69
|
+
"Expected format 'symbol_timeunit.csv', "
|
|
70
|
+
f"got '{time_unit_str}'."
|
|
71
|
+
)
|
|
72
|
+
|
|
23
73
|
def equals(self, other):
|
|
24
74
|
|
|
25
75
|
if isinstance(other, Enum):
|
|
@@ -38,3 +88,62 @@ class TimeUnit(Enum):
|
|
|
38
88
|
return entry
|
|
39
89
|
|
|
40
90
|
return TimeUnit.from_string(value)
|
|
91
|
+
|
|
92
|
+
def create_date(self, start_date, interval):
|
|
93
|
+
|
|
94
|
+
if TimeUnit.SECOND.equals(self):
|
|
95
|
+
return timedelta(minutes=interval)
|
|
96
|
+
elif TimeUnit.MINUTE.equals(self):
|
|
97
|
+
return timedelta(minutes=interval)
|
|
98
|
+
elif TimeUnit.HOUR.equals(self):
|
|
99
|
+
return timedelta(hours=interval)
|
|
100
|
+
elif TimeUnit.DAY.equals(self):
|
|
101
|
+
return timedelta(days=interval)
|
|
102
|
+
|
|
103
|
+
raise ValueError(f"Unsupported time unit: {self}")
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def single_name(self):
|
|
107
|
+
|
|
108
|
+
if TimeUnit.SECOND.equals(self.value):
|
|
109
|
+
return "second"
|
|
110
|
+
|
|
111
|
+
if TimeUnit.MINUTE.equals(self.value):
|
|
112
|
+
return "minute"
|
|
113
|
+
|
|
114
|
+
if TimeUnit.HOUR.equals(self.value):
|
|
115
|
+
return "hour"
|
|
116
|
+
|
|
117
|
+
if TimeUnit.DAY.equals(self.value):
|
|
118
|
+
return "day"
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def plural_name(self):
|
|
122
|
+
|
|
123
|
+
if TimeUnit.SECOND.equals(self.value):
|
|
124
|
+
return "seconds"
|
|
125
|
+
|
|
126
|
+
if TimeUnit.MINUTE.equals(self.value):
|
|
127
|
+
return "minutes"
|
|
128
|
+
|
|
129
|
+
if TimeUnit.HOUR.equals(self.value):
|
|
130
|
+
return "hours"
|
|
131
|
+
|
|
132
|
+
if TimeUnit.DAY.equals(self.value):
|
|
133
|
+
return "days"
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def amount_of_minutes(self):
|
|
137
|
+
if TimeUnit.SECOND.equals(self):
|
|
138
|
+
return 1 / 60
|
|
139
|
+
|
|
140
|
+
if TimeUnit.MINUTE.equals(self):
|
|
141
|
+
return 1
|
|
142
|
+
|
|
143
|
+
if TimeUnit.HOUR.equals(self):
|
|
144
|
+
return 60
|
|
145
|
+
|
|
146
|
+
if TimeUnit.DAY.equals(self):
|
|
147
|
+
return 60 * 24
|
|
148
|
+
|
|
149
|
+
raise ValueError(f"Unsupported time unit: {self}")
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class Trace:
|
|
2
|
+
"""
|
|
3
|
+
Represents a trace of a trading strategy. A trace contains
|
|
4
|
+
data that has been generated by a trading strategy during its
|
|
5
|
+
execution.
|
|
6
|
+
|
|
7
|
+
The data can be used to analyze the performance of the trading after
|
|
8
|
+
it has been executed. Usually, the data contains metrics that
|
|
9
|
+
have been generated by the trading strategy during its execution,
|
|
10
|
+
and the signals that have been generated.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
strategy_id: str,
|
|
16
|
+
symbol: str,
|
|
17
|
+
data,
|
|
18
|
+
drop_duplicates=True
|
|
19
|
+
):
|
|
20
|
+
self.strategy_id = strategy_id
|
|
21
|
+
self.symbol = symbol
|
|
22
|
+
self.data = data
|
|
23
|
+
self.drop_duplicates = drop_duplicates
|