investing-algorithm-framework 1.5__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 +192 -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 +29 -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 +2220 -379
- 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/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/strategy.py +867 -60
- 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 +3 -2
- investing_algorithm_framework/app/web/controllers/positions.py +2 -2
- investing_algorithm_framework/app/web/create_app.py +4 -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 +40 -7
- investing_algorithm_framework/dependency_container.py +100 -47
- investing_algorithm_framework/domain/__init__.py +97 -30
- 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 +59 -136
- investing_algorithm_framework/domain/constants.py +18 -37
- investing_algorithm_framework/domain/data_provider.py +334 -0
- investing_algorithm_framework/domain/data_structures.py +42 -0
- investing_algorithm_framework/domain/exceptions.py +51 -1
- investing_algorithm_framework/domain/models/__init__.py +26 -19
- investing_algorithm_framework/domain/models/app_mode.py +34 -0
- 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 +198 -65
- 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 +6 -2
- investing_algorithm_framework/domain/models/portfolio/portfolio.py +98 -3
- investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +37 -43
- investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +108 -11
- investing_algorithm_framework/domain/models/position/__init__.py +2 -1
- investing_algorithm_framework/domain/models/position/position.py +20 -0
- investing_algorithm_framework/domain/models/position/position_size.py +41 -0
- investing_algorithm_framework/domain/models/position/position_snapshot.py +0 -2
- 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 +19 -141
- 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 +66 -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 +15 -5
- 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 +37 -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 +86 -12
- investing_algorithm_framework/infrastructure/models/__init__.py +7 -3
- investing_algorithm_framework/infrastructure/models/order/__init__.py +2 -2
- investing_algorithm_framework/infrastructure/models/order/order.py +53 -53
- 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 +1 -1
- investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +8 -2
- investing_algorithm_framework/infrastructure/models/portfolio/{portfolio.py → sql_portfolio.py} +17 -6
- investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +3 -1
- 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 +10 -4
- investing_algorithm_framework/infrastructure/repositories/order_metadata_repository.py +17 -0
- investing_algorithm_framework/infrastructure/repositories/order_repository.py +16 -5
- investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +2 -2
- investing_algorithm_framework/infrastructure/repositories/position_repository.py +11 -0
- investing_algorithm_framework/infrastructure/repositories/repository.py +84 -30
- 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 -4
- 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 +123 -15
- investing_algorithm_framework/services/configuration_service.py +77 -11
- 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/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.5.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 -630
- investing_algorithm_framework/domain/models/backtest_profile.py +0 -414
- 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 -105
- 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/trade.py +0 -78
- investing_algorithm_framework/domain/models/trading_data_types.py +0 -47
- investing_algorithm_framework/domain/models/trading_time_frame.py +0 -223
- investing_algorithm_framework/domain/singleton.py +0 -9
- investing_algorithm_framework/domain/utils/backtesting.py +0 -82
- investing_algorithm_framework/infrastructure/models/order/order_fee.py +0 -21
- investing_algorithm_framework/infrastructure/repositories/order_fee_repository.py +0 -15
- investing_algorithm_framework/infrastructure/services/market_backtest_service.py +0 -360
- investing_algorithm_framework/infrastructure/services/market_service.py +0 -410
- investing_algorithm_framework/infrastructure/services/performance_service.py +0 -192
- investing_algorithm_framework/services/backtest_service.py +0 -268
- investing_algorithm_framework/services/market_data_service.py +0 -77
- investing_algorithm_framework/services/order_backtest_service.py +0 -122
- investing_algorithm_framework/services/order_service.py +0 -752
- investing_algorithm_framework/services/portfolio_service.py +0 -164
- investing_algorithm_framework/services/portfolio_snapshot_service.py +0 -68
- investing_algorithm_framework/services/position_cost_service.py +0 -5
- investing_algorithm_framework/services/position_service.py +0 -63
- investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -225
- investing_algorithm_framework-1.5.dist-info/AUTHORS.md +0 -8
- investing_algorithm_framework-1.5.dist-info/METADATA +0 -230
- investing_algorithm_framework-1.5.dist-info/RECORD +0 -119
- investing_algorithm_framework-1.5.dist-info/top_level.txt +0 -1
- /investing_algorithm_framework/{infrastructure/services/performance_backtest_service.py → app/reporting/tables/stop_loss_table.py} +0 -0
- /investing_algorithm_framework/services/{position_snapshot_service.py → positions/position_snapshot_service.py} +0 -0
- {investing_algorithm_framework-1.5.dist-info → investing_algorithm_framework-7.25.6.dist-info}/LICENSE +0 -0
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
from datetime import datetime
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class Ticker:
|
|
5
|
-
|
|
6
|
-
def __init__(
|
|
7
|
-
self,
|
|
8
|
-
symbol,
|
|
9
|
-
price,
|
|
10
|
-
ask_price=None,
|
|
11
|
-
ask_volume=None,
|
|
12
|
-
bid_price=None,
|
|
13
|
-
bid_volume=None,
|
|
14
|
-
high_price=None,
|
|
15
|
-
low_price=None,
|
|
16
|
-
creation_date=None
|
|
17
|
-
):
|
|
18
|
-
self.symbol = symbol
|
|
19
|
-
self.price = price
|
|
20
|
-
self.ask_price = ask_price
|
|
21
|
-
self.ask_volume = ask_volume
|
|
22
|
-
self.bid_price = bid_price
|
|
23
|
-
self.bid_volume = bid_volume
|
|
24
|
-
self.high_price = high_price
|
|
25
|
-
self.low_price = low_price
|
|
26
|
-
|
|
27
|
-
if creation_date is None:
|
|
28
|
-
self.creation_date = datetime.now()
|
|
29
|
-
|
|
30
|
-
def get_price(self):
|
|
31
|
-
return self.price
|
|
32
|
-
|
|
33
|
-
def get_creation_date(self):
|
|
34
|
-
return self.creation_date
|
|
35
|
-
|
|
36
|
-
def get_symbol(self):
|
|
37
|
-
return self.symbol
|
|
38
|
-
|
|
39
|
-
def to_dict(self):
|
|
40
|
-
return {
|
|
41
|
-
"symbol": self.symbol,
|
|
42
|
-
"price": self.price,
|
|
43
|
-
"ask_price": self.ask_price,
|
|
44
|
-
"ask_volume": self.ask_volume,
|
|
45
|
-
"bid_price": self.bid_price,
|
|
46
|
-
"bid_volume": self.bid_volume,
|
|
47
|
-
"high_price": self.high_price,
|
|
48
|
-
"low_price": self.low_price
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
@staticmethod
|
|
52
|
-
def from_dict(data):
|
|
53
|
-
return Ticker(
|
|
54
|
-
symbol=data.get("symbol"),
|
|
55
|
-
price=data.get("price"),
|
|
56
|
-
ask_price=data.get("ask_price"),
|
|
57
|
-
ask_volume=data.get("ask_volume"),
|
|
58
|
-
bid_price=data.get("bid_price"),
|
|
59
|
-
bid_volume=data.get("bid_volume"),
|
|
60
|
-
high_price=data.get("high_price"),
|
|
61
|
-
low_price=data.get("low_price"),
|
|
62
|
-
creation_date=data.get("creation_date")
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
def repr(self, **fields) -> str:
|
|
66
|
-
"""
|
|
67
|
-
Helper for __repr__
|
|
68
|
-
"""
|
|
69
|
-
|
|
70
|
-
field_strings = []
|
|
71
|
-
at_least_one_attached_attribute = False
|
|
72
|
-
|
|
73
|
-
for key, field in fields.items():
|
|
74
|
-
field_strings.append(f'{key}={field!r}')
|
|
75
|
-
at_least_one_attached_attribute = True
|
|
76
|
-
|
|
77
|
-
if at_least_one_attached_attribute:
|
|
78
|
-
return f"<{self.__class__.__name__}({','.join(field_strings)})>"
|
|
79
|
-
|
|
80
|
-
return f"<{self.__class__.__name__} {id(self)}>"
|
|
81
|
-
|
|
82
|
-
def __repr__(self):
|
|
83
|
-
return self.repr(
|
|
84
|
-
symbol=self.symbol,
|
|
85
|
-
price=self.price,
|
|
86
|
-
ask_price=self.ask_price,
|
|
87
|
-
ask_volume=self.ask_volume,
|
|
88
|
-
bid_price=self.bid_price,
|
|
89
|
-
bid_volume=self.bid_volume,
|
|
90
|
-
high_price=self.high_price,
|
|
91
|
-
low_price=self.low_price
|
|
92
|
-
)
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
from investing_algorithm_framework.domain.models.base_model import BaseModel
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class OrderFee(BaseModel):
|
|
5
|
-
def __init__(self, currency, cost, rate):
|
|
6
|
-
self.currency = currency
|
|
7
|
-
self.cost = cost
|
|
8
|
-
self.rate = rate
|
|
9
|
-
|
|
10
|
-
def get_currency(self):
|
|
11
|
-
return self.currency
|
|
12
|
-
|
|
13
|
-
def set_currency(self, currency):
|
|
14
|
-
self.currency = currency
|
|
15
|
-
|
|
16
|
-
def get_cost(self):
|
|
17
|
-
return self.cost
|
|
18
|
-
|
|
19
|
-
def set_cost(self, cost):
|
|
20
|
-
self.cost = cost
|
|
21
|
-
|
|
22
|
-
def get_rate(self):
|
|
23
|
-
return self.rate
|
|
24
|
-
|
|
25
|
-
@staticmethod
|
|
26
|
-
def from_ccxt_fee(ccxt_fee):
|
|
27
|
-
return OrderFee(
|
|
28
|
-
currency=ccxt_fee.get('currency'),
|
|
29
|
-
cost=ccxt_fee.get('cost'),
|
|
30
|
-
rate=ccxt_fee.get('rate'),
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
def to_dict(self):
|
|
34
|
-
return {
|
|
35
|
-
"currency": self.currency,
|
|
36
|
-
"cost": self.cost,
|
|
37
|
-
"rate": self.rate
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
def __repr__(self):
|
|
41
|
-
return self.repr(
|
|
42
|
-
currency=self.get_currency(),
|
|
43
|
-
cost=self.get_cost(),
|
|
44
|
-
rate=self.get_rate(),
|
|
45
|
-
)
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
from investing_algorithm_framework.domain.models.base_model import BaseModel
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class Trade(BaseModel):
|
|
5
|
-
|
|
6
|
-
def __init__(
|
|
7
|
-
self,
|
|
8
|
-
target_symbol,
|
|
9
|
-
trading_symbol,
|
|
10
|
-
amount,
|
|
11
|
-
open_price,
|
|
12
|
-
closed_price,
|
|
13
|
-
closed_at,
|
|
14
|
-
opened_at
|
|
15
|
-
):
|
|
16
|
-
self._target_symbol = target_symbol
|
|
17
|
-
self._trading_symbol = trading_symbol
|
|
18
|
-
self._amount = amount
|
|
19
|
-
self._open_price = open_price
|
|
20
|
-
self._closed_price = closed_price
|
|
21
|
-
self._closed_at = closed_at
|
|
22
|
-
self._opened_at = opened_at
|
|
23
|
-
self._trading_symbol = trading_symbol
|
|
24
|
-
|
|
25
|
-
@property
|
|
26
|
-
def target_symbol(self):
|
|
27
|
-
return self._target_symbol
|
|
28
|
-
|
|
29
|
-
@property
|
|
30
|
-
def trading_symbol(self):
|
|
31
|
-
return self._trading_symbol
|
|
32
|
-
|
|
33
|
-
@property
|
|
34
|
-
def amount(self):
|
|
35
|
-
return self._amount
|
|
36
|
-
|
|
37
|
-
@property
|
|
38
|
-
def open_price(self):
|
|
39
|
-
return self._open_price
|
|
40
|
-
|
|
41
|
-
@property
|
|
42
|
-
def closed_price(self):
|
|
43
|
-
return self._closed_price
|
|
44
|
-
|
|
45
|
-
@property
|
|
46
|
-
def closed_at(self):
|
|
47
|
-
return self._closed_at
|
|
48
|
-
|
|
49
|
-
@property
|
|
50
|
-
def opened_at(self):
|
|
51
|
-
return self._opened_at
|
|
52
|
-
|
|
53
|
-
@property
|
|
54
|
-
def size(self):
|
|
55
|
-
return self.amount * self.open_price
|
|
56
|
-
|
|
57
|
-
@property
|
|
58
|
-
def net_gain(self):
|
|
59
|
-
return self.amount * (self.closed_price - self.open_price)
|
|
60
|
-
|
|
61
|
-
@property
|
|
62
|
-
def net_gain_percentage(self):
|
|
63
|
-
return self.net_gain / self.size * 100
|
|
64
|
-
|
|
65
|
-
@property
|
|
66
|
-
def duration(self):
|
|
67
|
-
return (self.closed_at - self.opened_at).total_seconds() / 3600
|
|
68
|
-
|
|
69
|
-
def __repr__(self):
|
|
70
|
-
return self.repr(
|
|
71
|
-
target_symbol=self.target_symbol,
|
|
72
|
-
trading_symbol=self.trading_symbol,
|
|
73
|
-
amount=self.amount,
|
|
74
|
-
open_price=self.open_price,
|
|
75
|
-
closed_price=self.closed_price,
|
|
76
|
-
opened_at=self.opened_at,
|
|
77
|
-
closed_at=self.closed_at,
|
|
78
|
-
)
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
from enum import Enum
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class TradingDataType(Enum):
|
|
5
|
-
TICKER = 'TICKER'
|
|
6
|
-
ORDER_BOOK = 'ORDER_BOOK'
|
|
7
|
-
OHLCV = "OHLCV"
|
|
8
|
-
|
|
9
|
-
@staticmethod
|
|
10
|
-
def from_value(value):
|
|
11
|
-
|
|
12
|
-
if isinstance(value, TradingDataType):
|
|
13
|
-
for trading_data_type in TradingDataType:
|
|
14
|
-
|
|
15
|
-
if value == trading_data_type:
|
|
16
|
-
return trading_data_type
|
|
17
|
-
|
|
18
|
-
elif isinstance(value, str):
|
|
19
|
-
return TradingDataType.from_string(value)
|
|
20
|
-
|
|
21
|
-
raise ValueError(
|
|
22
|
-
"Could not convert value to trading data type"
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
@staticmethod
|
|
26
|
-
def from_string(value: str):
|
|
27
|
-
|
|
28
|
-
if isinstance(value, str):
|
|
29
|
-
for order_type in TradingDataType:
|
|
30
|
-
|
|
31
|
-
if value.upper() == order_type.value:
|
|
32
|
-
return order_type
|
|
33
|
-
|
|
34
|
-
raise ValueError(
|
|
35
|
-
"Could not convert value to trading data type"
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
def equals(self, other):
|
|
39
|
-
|
|
40
|
-
if other is None:
|
|
41
|
-
return False
|
|
42
|
-
|
|
43
|
-
if isinstance(other, Enum):
|
|
44
|
-
return self.value == other.value
|
|
45
|
-
|
|
46
|
-
else:
|
|
47
|
-
return TradingDataType.from_string(other) == self
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
from enum import Enum
|
|
2
|
-
from datetime import timedelta, datetime
|
|
3
|
-
|
|
4
|
-
from investing_algorithm_framework.domain.exceptions import \
|
|
5
|
-
OperationalException
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class TradingTimeFrame(Enum):
|
|
9
|
-
ONE_MINUTE = "ONE_MINUTE"
|
|
10
|
-
FIFTEEN_MINUTE = "FIFTEEN_MINUTE"
|
|
11
|
-
ONE_HOUR = "ONE_HOUR"
|
|
12
|
-
TWO_HOUR = "TWO_HOUR"
|
|
13
|
-
ONE_DAY = 'ONE_DAY'
|
|
14
|
-
ONE_MONTH = "ONE_MONTH"
|
|
15
|
-
ONE_YEAR = "ONE_YEAR"
|
|
16
|
-
|
|
17
|
-
def create_time_frame_from_limit(self, limit: int = 50):
|
|
18
|
-
|
|
19
|
-
if TradingTimeFrame.ONE_MINUTE.equals(self):
|
|
20
|
-
hold = 1
|
|
21
|
-
start_date = datetime.now() - timedelta(minutes=limit)
|
|
22
|
-
elif TradingTimeFrame.FIFTEEN_MINUTE.equals(self):
|
|
23
|
-
hold = 15
|
|
24
|
-
start_date = datetime.now() - timedelta(minutes=(limit * 15))
|
|
25
|
-
elif TradingTimeFrame.ONE_HOUR.equals(self):
|
|
26
|
-
hold = 60
|
|
27
|
-
start_date = datetime.now() - timedelta(hours=limit)
|
|
28
|
-
elif TradingTimeFrame.TWO_HOUR.equals(self):
|
|
29
|
-
hold = 60 * 2
|
|
30
|
-
start_date = datetime.now() - timedelta(hours=limit)
|
|
31
|
-
elif TradingTimeFrame.ONE_DAY.equals(self):
|
|
32
|
-
hold = 60 * 24
|
|
33
|
-
start_date = datetime.now() - timedelta(days=limit)
|
|
34
|
-
elif TradingTimeFrame.ONE_MONTH.equals(self):
|
|
35
|
-
hold = 60 * 24 * 30
|
|
36
|
-
start_date = datetime.now() - timedelta(weeks=(4 * limit))
|
|
37
|
-
else:
|
|
38
|
-
hold = 60 * 24 * 365
|
|
39
|
-
start_date = datetime.now() - timedelta(days=(limit * 365))
|
|
40
|
-
|
|
41
|
-
iteration = 1
|
|
42
|
-
dates = []
|
|
43
|
-
while iteration < limit or \
|
|
44
|
-
start_date + timedelta(minutes=hold) < datetime.now():
|
|
45
|
-
dates.append(start_date + timedelta(minutes=hold))
|
|
46
|
-
start_date += timedelta(minutes=hold)
|
|
47
|
-
iteration += 1
|
|
48
|
-
|
|
49
|
-
dates.append(datetime.now())
|
|
50
|
-
return dates
|
|
51
|
-
|
|
52
|
-
def create_time_frame_from_start_date(self, start_date: datetime):
|
|
53
|
-
|
|
54
|
-
if start_date > datetime.now():
|
|
55
|
-
raise OperationalException("Start date cannot be in the future")
|
|
56
|
-
|
|
57
|
-
if TradingTimeFrame.ONE_MINUTE.equals(self):
|
|
58
|
-
hold = 1
|
|
59
|
-
elif TradingTimeFrame.FIFTEEN_MINUTE.equals(self):
|
|
60
|
-
hold = 15
|
|
61
|
-
elif TradingTimeFrame.ONE_HOUR.equals(self):
|
|
62
|
-
hold = 60
|
|
63
|
-
elif TradingTimeFrame.TWO_HOUR.equals(self):
|
|
64
|
-
hold = 60 * 2
|
|
65
|
-
elif TradingTimeFrame.ONE_DAY.equals(self):
|
|
66
|
-
hold = 60 * 24
|
|
67
|
-
elif TradingTimeFrame.ONE_MONTH.equals(self):
|
|
68
|
-
hold = 60 * 24 * 30
|
|
69
|
-
else:
|
|
70
|
-
hold = 60 * 24 * 365
|
|
71
|
-
|
|
72
|
-
iteration = 1
|
|
73
|
-
dates = []
|
|
74
|
-
|
|
75
|
-
while start_date < datetime.now():
|
|
76
|
-
dates.append(start_date + timedelta(minutes=hold))
|
|
77
|
-
start_date += timedelta(minutes=hold)
|
|
78
|
-
iteration += 1
|
|
79
|
-
|
|
80
|
-
dates.append(datetime.now())
|
|
81
|
-
return dates
|
|
82
|
-
|
|
83
|
-
def to_ccxt_string(self):
|
|
84
|
-
|
|
85
|
-
if TradingTimeFrame.ONE_MINUTE.equals(self):
|
|
86
|
-
return "1m"
|
|
87
|
-
|
|
88
|
-
if TradingTimeFrame.FIFTEEN_MINUTE.equals(self):
|
|
89
|
-
return "15m"
|
|
90
|
-
|
|
91
|
-
if TradingTimeFrame.ONE_HOUR.equals(self):
|
|
92
|
-
return "1h"
|
|
93
|
-
|
|
94
|
-
if TradingTimeFrame.TWO_HOUR.equals(self):
|
|
95
|
-
return "2h"
|
|
96
|
-
|
|
97
|
-
if TradingTimeFrame.ONE_DAY.equals(self):
|
|
98
|
-
return "1d"
|
|
99
|
-
|
|
100
|
-
if TradingTimeFrame.ONE_MONTH.equals(self):
|
|
101
|
-
return "1m"
|
|
102
|
-
|
|
103
|
-
if TradingTimeFrame.ONE_YEAR.equals(self):
|
|
104
|
-
return "1y"
|
|
105
|
-
|
|
106
|
-
raise OperationalException("Data time unit value is not supported")
|
|
107
|
-
|
|
108
|
-
@staticmethod
|
|
109
|
-
def from_value(value):
|
|
110
|
-
|
|
111
|
-
if isinstance(value, TradingTimeFrame):
|
|
112
|
-
for data_time_unit in TradingTimeFrame:
|
|
113
|
-
|
|
114
|
-
if value == data_time_unit:
|
|
115
|
-
return data_time_unit
|
|
116
|
-
|
|
117
|
-
elif isinstance(value, str):
|
|
118
|
-
return TradingTimeFrame.from_string(value)
|
|
119
|
-
|
|
120
|
-
raise ValueError(
|
|
121
|
-
"Could not convert value to data time unit"
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
@staticmethod
|
|
125
|
-
def from_string(value: str):
|
|
126
|
-
|
|
127
|
-
if isinstance(value, str):
|
|
128
|
-
for data_time_unit in TradingTimeFrame:
|
|
129
|
-
|
|
130
|
-
if value.upper() == data_time_unit.value:
|
|
131
|
-
return data_time_unit
|
|
132
|
-
|
|
133
|
-
raise ValueError(
|
|
134
|
-
"Could not convert value to data time unit"
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
def equals(self, other):
|
|
138
|
-
|
|
139
|
-
if other is None:
|
|
140
|
-
return False
|
|
141
|
-
|
|
142
|
-
if isinstance(other, Enum):
|
|
143
|
-
return self.value == other.value
|
|
144
|
-
|
|
145
|
-
else:
|
|
146
|
-
return TradingTimeFrame.from_string(other) == self
|
|
147
|
-
|
|
148
|
-
def create_start_date(self, limit=50):
|
|
149
|
-
|
|
150
|
-
if TradingTimeFrame.ONE_MINUTE.equals(self):
|
|
151
|
-
return datetime.now() - timedelta(minutes=limit)
|
|
152
|
-
|
|
153
|
-
if TradingTimeFrame.FIFTEEN_MINUTE.equals(self):
|
|
154
|
-
return datetime.now() - timedelta(minutes=(limit * 15))
|
|
155
|
-
|
|
156
|
-
if TradingTimeFrame.ONE_HOUR.equals(self):
|
|
157
|
-
return datetime.now() - timedelta(hours=limit)
|
|
158
|
-
|
|
159
|
-
if TradingTimeFrame.TWO_HOUR.equals(self):
|
|
160
|
-
return datetime.now() - timedelta(hours=limit * 2)
|
|
161
|
-
|
|
162
|
-
if TradingTimeFrame.ONE_DAY.equals(self):
|
|
163
|
-
return datetime.now() - timedelta(days=limit)
|
|
164
|
-
|
|
165
|
-
if TradingTimeFrame.ONE_MONTH.equals(self):
|
|
166
|
-
return datetime.now() - timedelta(weeks=(4 * limit))
|
|
167
|
-
|
|
168
|
-
if TradingTimeFrame.ONE_YEAR.equals(self):
|
|
169
|
-
return datetime.now() - timedelta(days=(limit * 365))
|
|
170
|
-
|
|
171
|
-
raise OperationalException("Data time unit value is not supported")
|
|
172
|
-
|
|
173
|
-
@property
|
|
174
|
-
def minutes(self):
|
|
175
|
-
|
|
176
|
-
if TradingTimeFrame.ONE_MINUTE.equals(self):
|
|
177
|
-
return 1
|
|
178
|
-
|
|
179
|
-
if TradingTimeFrame.FIFTEEN_MINUTE.equals(self):
|
|
180
|
-
return 15
|
|
181
|
-
|
|
182
|
-
if TradingTimeFrame.ONE_HOUR.equals(self):
|
|
183
|
-
return 60
|
|
184
|
-
|
|
185
|
-
if TradingTimeFrame.TWO_HOUR.equals(self):
|
|
186
|
-
return 120
|
|
187
|
-
|
|
188
|
-
if TradingTimeFrame.ONE_DAY.equals(self):
|
|
189
|
-
return 60 * 24
|
|
190
|
-
|
|
191
|
-
if TradingTimeFrame.ONE_MONTH.equals(self):
|
|
192
|
-
return 60 * 24 * 30
|
|
193
|
-
|
|
194
|
-
if TradingTimeFrame.ONE_YEAR.equals(self):
|
|
195
|
-
return 60 * 24 * 365
|
|
196
|
-
|
|
197
|
-
raise OperationalException("Data time frame value is not supported")
|
|
198
|
-
|
|
199
|
-
@property
|
|
200
|
-
def milliseconds(self):
|
|
201
|
-
|
|
202
|
-
if TradingTimeFrame.ONE_MINUTE.equals(self):
|
|
203
|
-
return 60 * 1000
|
|
204
|
-
|
|
205
|
-
if TradingTimeFrame.FIFTEEN_MINUTE.equals(self):
|
|
206
|
-
return 15 * 60 * 1000
|
|
207
|
-
|
|
208
|
-
if TradingTimeFrame.ONE_HOUR.equals(self):
|
|
209
|
-
return 60 * 60 * 1000
|
|
210
|
-
|
|
211
|
-
if TradingTimeFrame.TWO_HOUR.equals(self):
|
|
212
|
-
return 2* 60 * 60 * 1000
|
|
213
|
-
|
|
214
|
-
if TradingTimeFrame.ONE_DAY.equals(self):
|
|
215
|
-
return 60 * 60 * 24 * 1000
|
|
216
|
-
|
|
217
|
-
if TradingTimeFrame.ONE_MONTH.equals(self):
|
|
218
|
-
return 60 * 60 * 24 * 30 * 1000
|
|
219
|
-
|
|
220
|
-
if TradingTimeFrame.ONE_YEAR.equals(self):
|
|
221
|
-
return 60 * 60 * 24 * 365 * 1000
|
|
222
|
-
|
|
223
|
-
raise OperationalException("Data time frame value is not supported")
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
def print_number_of_runs(report):
|
|
4
|
-
|
|
5
|
-
if report.number_of_runs == 1:
|
|
6
|
-
|
|
7
|
-
if report.inteval > 1:
|
|
8
|
-
print(f"Strategy ran every {report.interval} {report.time_unit} for a total of {report.number_of_runs} time")
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def pretty_print_backtest(backtest_report, show_positions=True, show_trades=True, precision=4):
|
|
12
|
-
print("====================Backtest report===============================")
|
|
13
|
-
print(f"* Start date: {backtest_report.backtest_start_date}")
|
|
14
|
-
print(f"* End date: {backtest_report.backtest_end_date}")
|
|
15
|
-
print(f"* Number of days: {backtest_report.number_of_days}")
|
|
16
|
-
print(f"* Number of runs: {backtest_report.number_of_runs}")
|
|
17
|
-
print("====================Portfolio overview============================")
|
|
18
|
-
print(f"* Number of orders: {backtest_report.number_of_orders}")
|
|
19
|
-
print(f"* Initial balance: "
|
|
20
|
-
f"{backtest_report.initial_unallocated:.{precision}f} "
|
|
21
|
-
f"{backtest_report.trading_symbol}")
|
|
22
|
-
print(f"* Final balance: {backtest_report.total_value:.{precision}f} "
|
|
23
|
-
f"{backtest_report.trading_symbol}")
|
|
24
|
-
print(f"* Total net gain: {backtest_report.total_net_gain:.{precision}f} "
|
|
25
|
-
f"{backtest_report.trading_symbol}")
|
|
26
|
-
print(f"* Total net gain percentage: "
|
|
27
|
-
f"{backtest_report.total_net_gain_percentage:.{precision}f}%")
|
|
28
|
-
print(f"* Growth rate: "
|
|
29
|
-
f"{float(backtest_report.growth_rate):.{precision}f}%")
|
|
30
|
-
print(f"* Growth {backtest_report.growth:.{precision}f} "
|
|
31
|
-
f"{backtest_report.trading_symbol}")
|
|
32
|
-
|
|
33
|
-
if show_positions:
|
|
34
|
-
print("====================Positions overview========================")
|
|
35
|
-
print(f"* Number of positions at the end of backtest: {backtest_report.number_of_positions}")
|
|
36
|
-
print(f"* Total cost of current positions: "
|
|
37
|
-
f"{backtest_report.total_cost:.{precision}f} "
|
|
38
|
-
f"{backtest_report.trading_symbol}")
|
|
39
|
-
for position in backtest_report.positions:
|
|
40
|
-
print(
|
|
41
|
-
f"{position.symbol}, "
|
|
42
|
-
f"amount: {position.amount:.{precision}f}, "
|
|
43
|
-
f"cost: {position.cost:.{precision}f} "
|
|
44
|
-
f"{backtest_report.trading_symbol}, "
|
|
45
|
-
f"value: {position.value:.{precision}f} "
|
|
46
|
-
f"{backtest_report.trading_symbol}, "
|
|
47
|
-
f"growth: {position.growth:.{precision}f} "
|
|
48
|
-
f"{backtest_report.trading_symbol} "
|
|
49
|
-
f"({position.growth_rate:.{precision}f}%)."
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
if show_trades:
|
|
53
|
-
print("====================Trades overview===========================")
|
|
54
|
-
print(f"* Number of trades closed: "
|
|
55
|
-
f"{backtest_report.number_of_trades_closed}")
|
|
56
|
-
print(
|
|
57
|
-
f"* Number of trades open: "
|
|
58
|
-
f"{backtest_report.number_of_trades_open}"
|
|
59
|
-
)
|
|
60
|
-
print(f"* Percentage of positive trades: "
|
|
61
|
-
f"{backtest_report.percentage_positive_trades}%")
|
|
62
|
-
print(f"* Percentage of negative trades: "
|
|
63
|
-
f"{backtest_report.percentage_negative_trades}%")
|
|
64
|
-
print(f"* Average trade size: "
|
|
65
|
-
f"{backtest_report.average_trade_size:.{precision}f} "
|
|
66
|
-
f"{backtest_report.trading_symbol}")
|
|
67
|
-
print(f"* Average trade duration: "
|
|
68
|
-
f"{backtest_report.average_trade_duration} hours")
|
|
69
|
-
for trade in backtest_report.trades:
|
|
70
|
-
print(
|
|
71
|
-
f"{trade.target_symbol} -> {trade.trading_symbol}, "
|
|
72
|
-
f"open date: {trade.opened_at}, "
|
|
73
|
-
f"close date: {trade.closed_at}, "
|
|
74
|
-
f"size: {trade.size:.{precision}f} {trade.trading_symbol}, "
|
|
75
|
-
f"net gain: {trade.net_gain:.{precision}f}, "
|
|
76
|
-
f"net gain percentage: "
|
|
77
|
-
f"{trade.net_gain_percentage:.{precision}f}%, "
|
|
78
|
-
f"duration: {trade.duration} hours, "
|
|
79
|
-
f"open price: {trade.open_price}, "
|
|
80
|
-
f"close price: {trade.closed_price}"
|
|
81
|
-
)
|
|
82
|
-
print("==================================================================")
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
from sqlalchemy import Column, Integer, String, ForeignKey, Float
|
|
2
|
-
from sqlalchemy.orm import relationship
|
|
3
|
-
|
|
4
|
-
from investing_algorithm_framework.domain import OrderFee
|
|
5
|
-
from investing_algorithm_framework.infrastructure.database import SQLBaseModel
|
|
6
|
-
from investing_algorithm_framework.infrastructure.models.model_extension \
|
|
7
|
-
import SQLAlchemyModelExtension
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class SQLOrderFee(OrderFee, SQLBaseModel, SQLAlchemyModelExtension):
|
|
11
|
-
__tablename__ = "order_fees"
|
|
12
|
-
id = Column(Integer, primary_key=True, unique=True)
|
|
13
|
-
currency = Column(String)
|
|
14
|
-
cost = Column(Float)
|
|
15
|
-
rate = Column(Float)
|
|
16
|
-
order_id = Column(Integer, ForeignKey('orders.id'))
|
|
17
|
-
order = relationship("SQLOrder", back_populates="fee")
|
|
18
|
-
|
|
19
|
-
def __init__(self, currency, cost, rate, order_id):
|
|
20
|
-
super().__init__(currency, cost, rate)
|
|
21
|
-
self.order_id = order_id
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
from investing_algorithm_framework.infrastructure.models import SQLOrderFee
|
|
2
|
-
from .repository import Repository
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class SQLOrderFeeRepository(Repository):
|
|
6
|
-
base_class = SQLOrderFee
|
|
7
|
-
DEFAULT_NOT_FOUND_MESSAGE = "Order fee not found"
|
|
8
|
-
|
|
9
|
-
def _apply_query_params(self, db, query, query_params):
|
|
10
|
-
order_query_param = self.get_query_param("order", query_params)
|
|
11
|
-
|
|
12
|
-
if order_query_param:
|
|
13
|
-
query = query.filter_by(order_id=order_query_param)
|
|
14
|
-
|
|
15
|
-
return query
|