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
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
from datetime import datetime, timezone
|
|
2
|
+
from uuid import uuid4
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from investing_algorithm_framework.domain import BacktestDateRange, \
|
|
8
|
+
BacktestRun, Portfolio, TimeFrame, PortfolioConfiguration, \
|
|
9
|
+
PortfolioSnapshot, OperationalException, Order, OrderType, OrderStatus, \
|
|
10
|
+
OrderSide, Trade, TradeStatus, DataType
|
|
11
|
+
from investing_algorithm_framework.services import DataProviderService, \
|
|
12
|
+
create_backtest_metrics
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# if (
|
|
16
|
+
# portfolio_configurations is None
|
|
17
|
+
# or len(portfolio_configurations) == 0
|
|
18
|
+
# ) and (
|
|
19
|
+
# initial_amount is None
|
|
20
|
+
# or trading_symbol is None
|
|
21
|
+
# or market is None
|
|
22
|
+
# ):
|
|
23
|
+
# raise OperationalException(
|
|
24
|
+
# "No initial amount, trading symbol or market provided "
|
|
25
|
+
# "for the backtest and no portfolio configurations found. "
|
|
26
|
+
# "please register a portfolio configuration "
|
|
27
|
+
# "or specify the initial amount, trading symbol and "
|
|
28
|
+
# "market parameters before running a backtest."
|
|
29
|
+
# )
|
|
30
|
+
#
|
|
31
|
+
# if portfolio_configurations is None \
|
|
32
|
+
# or len(portfolio_configurations) == 0:
|
|
33
|
+
# portfolio_configurations = []
|
|
34
|
+
# portfolio_configurations.append(
|
|
35
|
+
# PortfolioConfiguration(
|
|
36
|
+
# identifier="vector_backtest",
|
|
37
|
+
# market=market,
|
|
38
|
+
# trading_symbol=trading_symbol,
|
|
39
|
+
# initial_balance=initial_amount
|
|
40
|
+
# )
|
|
41
|
+
# )
|
|
42
|
+
#
|
|
43
|
+
# portfolio_configuration = portfolio_configurations[0]
|
|
44
|
+
|
|
45
|
+
class VectorBacktestService:
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self, data_provider_service: DataProviderService
|
|
49
|
+
):
|
|
50
|
+
self.data_provider_service = data_provider_service
|
|
51
|
+
|
|
52
|
+
def run(
|
|
53
|
+
self,
|
|
54
|
+
strategy,
|
|
55
|
+
backtest_date_range: BacktestDateRange,
|
|
56
|
+
portfolio_configuration: PortfolioConfiguration,
|
|
57
|
+
risk_free_rate: float = 0.027,
|
|
58
|
+
dynamic_position_sizing: bool = False,
|
|
59
|
+
) -> BacktestRun:
|
|
60
|
+
"""
|
|
61
|
+
Vectorized backtest for multiple assets using strategy
|
|
62
|
+
buy/sell signals.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
strategy: The strategy to backtest.
|
|
66
|
+
backtest_date_range: The date range for the backtest.
|
|
67
|
+
portfolio_configuration: Portfolio configuration containing
|
|
68
|
+
initial balance, market, and trading symbol.
|
|
69
|
+
risk_free_rate: The risk-free rate to use for the backtest
|
|
70
|
+
metrics. Default is 0.027 (2.7%).
|
|
71
|
+
dynamic_position_sizing: If True, position sizes are recalculated
|
|
72
|
+
at each trade based on current portfolio value (similar to
|
|
73
|
+
event-based backtesting). If False (default), position sizes
|
|
74
|
+
are calculated once at the start based on initial portfolio
|
|
75
|
+
value. Default is False for backward compatibility.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
BacktestRun: The backtest run containing the results and metrics.
|
|
79
|
+
"""
|
|
80
|
+
initial_amount = portfolio_configuration.initial_balance
|
|
81
|
+
trading_symbol = portfolio_configuration.trading_symbol
|
|
82
|
+
portfolio = Portfolio.from_portfolio_configuration(
|
|
83
|
+
portfolio_configuration
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Load vectorized backtest data
|
|
87
|
+
data = self.data_provider_service.get_vectorized_backtest_data(
|
|
88
|
+
data_sources=strategy.data_sources,
|
|
89
|
+
start_date=backtest_date_range.start_date,
|
|
90
|
+
end_date=backtest_date_range.end_date
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Compute signals from strategy
|
|
94
|
+
buy_signals = strategy.generate_buy_signals(data)
|
|
95
|
+
sell_signals = strategy.generate_sell_signals(data)
|
|
96
|
+
|
|
97
|
+
# Build master index (union of all indices in signal dict)
|
|
98
|
+
index = pd.Index([])
|
|
99
|
+
|
|
100
|
+
most_granular_ohlcv_data_source = \
|
|
101
|
+
self.get_most_granular_ohlcv_data_source(
|
|
102
|
+
strategy.data_sources
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
most_granular_ohlcv_data = self.data_provider_service.get_ohlcv_data(
|
|
106
|
+
symbol=most_granular_ohlcv_data_source.symbol,
|
|
107
|
+
start_date=backtest_date_range.start_date,
|
|
108
|
+
end_date=backtest_date_range.end_date,
|
|
109
|
+
pandas=True
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Make sure to filter out the buy and sell signals that are before
|
|
113
|
+
# the backtest start date
|
|
114
|
+
buy_signals = {k: v[v.index >= backtest_date_range.start_date]
|
|
115
|
+
for k, v in buy_signals.items()}
|
|
116
|
+
sell_signals = {k: v[v.index >= backtest_date_range.start_date]
|
|
117
|
+
for k, v in sell_signals.items()}
|
|
118
|
+
|
|
119
|
+
index = index.union(most_granular_ohlcv_data.index)
|
|
120
|
+
index = index.sort_values()
|
|
121
|
+
|
|
122
|
+
# Initialize trades and portfolio values
|
|
123
|
+
trades = []
|
|
124
|
+
orders = []
|
|
125
|
+
granular_ohlcv_data_order_by_symbol = {}
|
|
126
|
+
snapshots = [
|
|
127
|
+
PortfolioSnapshot(
|
|
128
|
+
trading_symbol=trading_symbol,
|
|
129
|
+
portfolio_id=portfolio.identifier,
|
|
130
|
+
created_at=backtest_date_range.start_date,
|
|
131
|
+
unallocated=portfolio_configuration.initial_balance,
|
|
132
|
+
total_value=portfolio_configuration.initial_balance,
|
|
133
|
+
total_net_gain=0.0
|
|
134
|
+
)
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
# Pre-compute all data needed for each symbol
|
|
138
|
+
symbol_data = {}
|
|
139
|
+
for symbol in buy_signals.keys():
|
|
140
|
+
full_symbol = f"{symbol}/{trading_symbol}"
|
|
141
|
+
|
|
142
|
+
# find PositionSize object
|
|
143
|
+
pos_size_obj = next(
|
|
144
|
+
(p for p in strategy.position_sizes if
|
|
145
|
+
p.symbol == symbol), None
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
if pos_size_obj is None:
|
|
149
|
+
raise OperationalException(
|
|
150
|
+
f"No position size object defined "
|
|
151
|
+
f"for symbol {symbol}, please make sure to "
|
|
152
|
+
f"register a PositionSize object in the strategy."
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Load most granular OHLCV data for the symbol
|
|
156
|
+
df = self.data_provider_service.get_ohlcv_data(
|
|
157
|
+
symbol=full_symbol,
|
|
158
|
+
start_date=backtest_date_range.start_date,
|
|
159
|
+
end_date=backtest_date_range.end_date,
|
|
160
|
+
pandas=True
|
|
161
|
+
)
|
|
162
|
+
granular_ohlcv_data_order_by_symbol[full_symbol] = df
|
|
163
|
+
|
|
164
|
+
# Align signals with most granular OHLCV data
|
|
165
|
+
close = df["Close"].reindex(index, method='ffill')
|
|
166
|
+
buy_signal = buy_signals[symbol].reindex(index, fill_value=False)
|
|
167
|
+
sell_signal = sell_signals[symbol].reindex(index, fill_value=False)
|
|
168
|
+
|
|
169
|
+
signal = pd.Series(0, index=index)
|
|
170
|
+
signal[buy_signal] = 1
|
|
171
|
+
signal[sell_signal] = -1
|
|
172
|
+
signal = signal.replace(0, np.nan).ffill().shift(1).fillna(0)
|
|
173
|
+
signal = signal.astype(float)
|
|
174
|
+
|
|
175
|
+
# Calculate initial capital for trade
|
|
176
|
+
# (used when dynamic_position_sizing=False)
|
|
177
|
+
initial_capital_for_trade = pos_size_obj.get_size(
|
|
178
|
+
Portfolio(
|
|
179
|
+
unallocated=portfolio_configuration.initial_balance,
|
|
180
|
+
initial_balance=portfolio_configuration.initial_balance,
|
|
181
|
+
trading_symbol=trading_symbol,
|
|
182
|
+
net_size=0,
|
|
183
|
+
market="BACKTEST",
|
|
184
|
+
identifier="vector_backtest"
|
|
185
|
+
),
|
|
186
|
+
asset_price=close.iloc[0] if len(close) > 0 else 1.0
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
symbol_data[symbol] = {
|
|
190
|
+
'full_symbol': full_symbol,
|
|
191
|
+
'pos_size_obj': pos_size_obj,
|
|
192
|
+
'close': close,
|
|
193
|
+
'signal': signal,
|
|
194
|
+
'initial_capital_for_trade': initial_capital_for_trade,
|
|
195
|
+
'last_trade': None, # Track open trade per symbol
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
# Shared portfolio state for dynamic position sizing
|
|
199
|
+
current_unallocated = initial_amount
|
|
200
|
+
total_realized_gains = 0.0
|
|
201
|
+
open_trades_value = {} # Track value of open trades per symbol
|
|
202
|
+
|
|
203
|
+
# Process all timestamps in chronological order
|
|
204
|
+
for i in range(len(index)):
|
|
205
|
+
current_date = index[i]
|
|
206
|
+
|
|
207
|
+
# Convert the pd.Timestamp to an utc datetime object
|
|
208
|
+
if isinstance(current_date, pd.Timestamp):
|
|
209
|
+
current_date = current_date.to_pydatetime()
|
|
210
|
+
|
|
211
|
+
if current_date.tzinfo is None:
|
|
212
|
+
current_date = current_date.replace(tzinfo=timezone.utc)
|
|
213
|
+
|
|
214
|
+
# Process each symbol at this timestamp
|
|
215
|
+
for symbol, data in symbol_data.items():
|
|
216
|
+
current_signal = data['signal'].iloc[i]
|
|
217
|
+
current_price = float(data['close'].iloc[i])
|
|
218
|
+
pos_size_obj = data['pos_size_obj']
|
|
219
|
+
last_trade = data['last_trade']
|
|
220
|
+
|
|
221
|
+
# If we are not in a position, and we get a buy signal
|
|
222
|
+
if current_signal == 1 and last_trade is None:
|
|
223
|
+
# Calculate capital for this trade
|
|
224
|
+
if dynamic_position_sizing:
|
|
225
|
+
# Calculate current portfolio value:
|
|
226
|
+
# unallocated + value of all open trades
|
|
227
|
+
open_trades_total = sum(open_trades_value.values())
|
|
228
|
+
current_portfolio_value = \
|
|
229
|
+
current_unallocated + open_trades_total
|
|
230
|
+
capital_for_trade = pos_size_obj.get_size(
|
|
231
|
+
Portfolio(
|
|
232
|
+
unallocated=current_portfolio_value,
|
|
233
|
+
initial_balance=initial_amount,
|
|
234
|
+
trading_symbol=trading_symbol,
|
|
235
|
+
net_size=0,
|
|
236
|
+
market="BACKTEST",
|
|
237
|
+
identifier="vector_backtest"
|
|
238
|
+
),
|
|
239
|
+
asset_price=current_price
|
|
240
|
+
)
|
|
241
|
+
# Don't exceed available unallocated funds
|
|
242
|
+
capital_for_trade = min(
|
|
243
|
+
capital_for_trade, current_unallocated
|
|
244
|
+
)
|
|
245
|
+
else:
|
|
246
|
+
capital_for_trade = data['initial_capital_for_trade']
|
|
247
|
+
|
|
248
|
+
if capital_for_trade <= 0:
|
|
249
|
+
continue # Skip if no capital available
|
|
250
|
+
|
|
251
|
+
amount = float(capital_for_trade / current_price)
|
|
252
|
+
|
|
253
|
+
# Update shared portfolio state
|
|
254
|
+
if dynamic_position_sizing:
|
|
255
|
+
current_unallocated -= capital_for_trade
|
|
256
|
+
|
|
257
|
+
buy_order = Order(
|
|
258
|
+
id=uuid4(),
|
|
259
|
+
target_symbol=symbol,
|
|
260
|
+
trading_symbol=trading_symbol,
|
|
261
|
+
order_type=OrderType.LIMIT,
|
|
262
|
+
price=current_price,
|
|
263
|
+
amount=amount,
|
|
264
|
+
status=OrderStatus.CLOSED,
|
|
265
|
+
created_at=current_date,
|
|
266
|
+
updated_at=current_date,
|
|
267
|
+
order_side=OrderSide.BUY
|
|
268
|
+
)
|
|
269
|
+
orders.append(buy_order)
|
|
270
|
+
trade = Trade(
|
|
271
|
+
id=uuid4(),
|
|
272
|
+
orders=[buy_order],
|
|
273
|
+
target_symbol=symbol,
|
|
274
|
+
trading_symbol=trading_symbol,
|
|
275
|
+
available_amount=amount,
|
|
276
|
+
remaining=0,
|
|
277
|
+
filled_amount=amount,
|
|
278
|
+
open_price=current_price,
|
|
279
|
+
opened_at=current_date,
|
|
280
|
+
closed_at=None,
|
|
281
|
+
amount=amount,
|
|
282
|
+
status=TradeStatus.OPEN.value,
|
|
283
|
+
cost=capital_for_trade
|
|
284
|
+
)
|
|
285
|
+
data['last_trade'] = trade
|
|
286
|
+
trades.append(trade)
|
|
287
|
+
|
|
288
|
+
# Track open trade value
|
|
289
|
+
if dynamic_position_sizing:
|
|
290
|
+
open_trades_value[symbol] = capital_for_trade
|
|
291
|
+
|
|
292
|
+
# If we are in a position, and we get a sell signal
|
|
293
|
+
if current_signal == -1 and last_trade is not None:
|
|
294
|
+
net_gain_val = (
|
|
295
|
+
current_price - last_trade.open_price
|
|
296
|
+
) * last_trade.available_amount
|
|
297
|
+
|
|
298
|
+
# Update shared portfolio state
|
|
299
|
+
if dynamic_position_sizing:
|
|
300
|
+
current_unallocated += last_trade.cost + net_gain_val
|
|
301
|
+
total_realized_gains += net_gain_val
|
|
302
|
+
if symbol in open_trades_value:
|
|
303
|
+
del open_trades_value[symbol]
|
|
304
|
+
|
|
305
|
+
sell_order = Order(
|
|
306
|
+
id=uuid4(),
|
|
307
|
+
target_symbol=symbol,
|
|
308
|
+
trading_symbol=trading_symbol,
|
|
309
|
+
order_type=OrderType.LIMIT,
|
|
310
|
+
price=current_price,
|
|
311
|
+
amount=last_trade.available_amount,
|
|
312
|
+
status=OrderStatus.CLOSED,
|
|
313
|
+
created_at=current_date,
|
|
314
|
+
updated_at=current_date,
|
|
315
|
+
order_side=OrderSide.SELL
|
|
316
|
+
)
|
|
317
|
+
orders.append(sell_order)
|
|
318
|
+
trade_orders = last_trade.orders
|
|
319
|
+
trade_orders.append(sell_order)
|
|
320
|
+
last_trade.update(
|
|
321
|
+
{
|
|
322
|
+
"orders": trade_orders,
|
|
323
|
+
"closed_at": current_date,
|
|
324
|
+
"status": TradeStatus.CLOSED.value,
|
|
325
|
+
"updated_at": current_date,
|
|
326
|
+
"net_gain": net_gain_val
|
|
327
|
+
}
|
|
328
|
+
)
|
|
329
|
+
data['last_trade'] = None
|
|
330
|
+
|
|
331
|
+
# Update open trade values at each timestamp for
|
|
332
|
+
# accurate portfolio value
|
|
333
|
+
if dynamic_position_sizing:
|
|
334
|
+
for symbol, data in symbol_data.items():
|
|
335
|
+
if data['last_trade'] is not None:
|
|
336
|
+
current_price = float(data['close'].iloc[i])
|
|
337
|
+
open_trades_value[symbol] = (
|
|
338
|
+
data['last_trade'].available_amount * current_price
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
unallocated = initial_amount
|
|
342
|
+
total_net_gain = 0.0
|
|
343
|
+
open_trades = []
|
|
344
|
+
|
|
345
|
+
# Create portfolio snapshots
|
|
346
|
+
for ts in index:
|
|
347
|
+
allocated = 0
|
|
348
|
+
interval_datetime = pd.Timestamp(ts).to_pydatetime()
|
|
349
|
+
interval_datetime = interval_datetime.replace(tzinfo=timezone.utc)
|
|
350
|
+
|
|
351
|
+
for trade in trades:
|
|
352
|
+
|
|
353
|
+
if trade.opened_at == interval_datetime:
|
|
354
|
+
# Snapshot taken at the moment a trade is opened
|
|
355
|
+
unallocated -= trade.cost
|
|
356
|
+
open_trades.append(trade)
|
|
357
|
+
|
|
358
|
+
if trade.closed_at == interval_datetime:
|
|
359
|
+
# Snapshot taken at the moment a trade is closed
|
|
360
|
+
unallocated += trade.cost + trade.net_gain
|
|
361
|
+
total_net_gain += trade.net_gain
|
|
362
|
+
open_trades.remove(trade)
|
|
363
|
+
|
|
364
|
+
for open_trade in open_trades:
|
|
365
|
+
ohlcv = granular_ohlcv_data_order_by_symbol[
|
|
366
|
+
f"{open_trade.target_symbol}/{trading_symbol}"
|
|
367
|
+
]
|
|
368
|
+
try:
|
|
369
|
+
price = ohlcv.loc[:ts, "Close"].iloc[-1]
|
|
370
|
+
open_trade.last_reported_price = price
|
|
371
|
+
except IndexError:
|
|
372
|
+
continue # skip if no price yet
|
|
373
|
+
|
|
374
|
+
allocated += open_trade.filled_amount * price
|
|
375
|
+
|
|
376
|
+
# total_value = invested_value + unallocated
|
|
377
|
+
# total_net_gain = total_value - initial_amount
|
|
378
|
+
snapshots.append(
|
|
379
|
+
PortfolioSnapshot(
|
|
380
|
+
portfolio_id=portfolio.identifier,
|
|
381
|
+
created_at=interval_datetime,
|
|
382
|
+
unallocated=unallocated,
|
|
383
|
+
total_value=unallocated + allocated,
|
|
384
|
+
total_net_gain=total_net_gain
|
|
385
|
+
)
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
unique_symbols = set()
|
|
389
|
+
for trade in trades:
|
|
390
|
+
unique_symbols.add(trade.target_symbol)
|
|
391
|
+
|
|
392
|
+
number_of_trades_closed = len(
|
|
393
|
+
[t for t in trades if TradeStatus.CLOSED.equals(t.status)]
|
|
394
|
+
)
|
|
395
|
+
number_of_trades_open = len(
|
|
396
|
+
[t for t in trades if TradeStatus.OPEN.equals(t.status)]
|
|
397
|
+
)
|
|
398
|
+
# Create a backtest run object
|
|
399
|
+
run = BacktestRun(
|
|
400
|
+
trading_symbol=trading_symbol,
|
|
401
|
+
initial_unallocated=initial_amount,
|
|
402
|
+
number_of_runs=1,
|
|
403
|
+
portfolio_snapshots=snapshots,
|
|
404
|
+
trades=trades,
|
|
405
|
+
orders=orders,
|
|
406
|
+
positions=[],
|
|
407
|
+
created_at=datetime.now(timezone.utc),
|
|
408
|
+
backtest_start_date=backtest_date_range.start_date,
|
|
409
|
+
backtest_end_date=backtest_date_range.end_date,
|
|
410
|
+
backtest_date_range_name=backtest_date_range.name,
|
|
411
|
+
number_of_days=(
|
|
412
|
+
backtest_date_range.end_date - backtest_date_range.end_date
|
|
413
|
+
).days,
|
|
414
|
+
number_of_trades=len(trades),
|
|
415
|
+
number_of_orders=len(orders),
|
|
416
|
+
number_of_trades_closed=number_of_trades_closed,
|
|
417
|
+
number_of_trades_open=number_of_trades_open,
|
|
418
|
+
number_of_positions=len(unique_symbols),
|
|
419
|
+
symbols=list(buy_signals.keys())
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
# Create backtest metrics
|
|
423
|
+
run.backtest_metrics = create_backtest_metrics(
|
|
424
|
+
run, risk_free_rate=risk_free_rate
|
|
425
|
+
)
|
|
426
|
+
return run
|
|
427
|
+
|
|
428
|
+
@staticmethod
|
|
429
|
+
def get_most_granular_ohlcv_data_source(data_sources):
|
|
430
|
+
"""
|
|
431
|
+
Get the most granular data source from a list of data sources.
|
|
432
|
+
|
|
433
|
+
Args:
|
|
434
|
+
data_sources: List of data sources.
|
|
435
|
+
|
|
436
|
+
Returns:
|
|
437
|
+
The most granular data source.
|
|
438
|
+
"""
|
|
439
|
+
granularity_order = {
|
|
440
|
+
TimeFrame.ONE_MINUTE: 1,
|
|
441
|
+
TimeFrame.FIVE_MINUTE: 5,
|
|
442
|
+
TimeFrame.FIFTEEN_MINUTE: 15,
|
|
443
|
+
TimeFrame.ONE_HOUR: 60,
|
|
444
|
+
TimeFrame.TWO_HOUR: 120,
|
|
445
|
+
TimeFrame.FOUR_HOUR: 240,
|
|
446
|
+
TimeFrame.TWELVE_HOUR: 720,
|
|
447
|
+
TimeFrame.ONE_DAY: 1440,
|
|
448
|
+
TimeFrame.ONE_WEEK: 10080,
|
|
449
|
+
TimeFrame.ONE_MONTH: 43200
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
most_granular = None
|
|
453
|
+
highest_granularity = float('inf')
|
|
454
|
+
|
|
455
|
+
ohlcv_data_sources = [
|
|
456
|
+
ds for ds in data_sources if DataType.OHLCV.equals(ds.data_type)
|
|
457
|
+
]
|
|
458
|
+
|
|
459
|
+
if len(ohlcv_data_sources) == 0:
|
|
460
|
+
raise OperationalException("No OHLCV data sources found")
|
|
461
|
+
|
|
462
|
+
for source in ohlcv_data_sources:
|
|
463
|
+
|
|
464
|
+
if granularity_order[source.time_frame] < highest_granularity:
|
|
465
|
+
highest_granularity = granularity_order[source.time_frame]
|
|
466
|
+
most_granular = source
|
|
467
|
+
|
|
468
|
+
return most_granular
|
|
@@ -1,19 +1,136 @@
|
|
|
1
|
-
from .
|
|
2
|
-
|
|
3
|
-
from .
|
|
4
|
-
from .
|
|
1
|
+
from .trade_order_evaluator import BacktestTradeOrderEvaluator, \
|
|
2
|
+
TradeOrderEvaluator, DefaultTradeOrderEvaluator
|
|
3
|
+
from .configuration_service import ConfigurationService
|
|
4
|
+
from .market_credential_service import MarketCredentialService
|
|
5
|
+
from .data_providers import DataProviderService
|
|
6
|
+
from .order_service import OrderService, OrderBacktestService, \
|
|
7
|
+
OrderExecutorLookup
|
|
8
|
+
from .portfolios import PortfolioService, BacktestPortfolioService, \
|
|
9
|
+
PortfolioConfigurationService, PortfolioSyncService, \
|
|
10
|
+
PortfolioSnapshotService, PortfolioProviderLookup
|
|
11
|
+
from .positions import PositionService, PositionSnapshotService
|
|
5
12
|
from .repository_service import RepositoryService
|
|
6
|
-
from .
|
|
7
|
-
|
|
8
|
-
from .
|
|
13
|
+
from .trade_service import TradeService, TradeStopLossService, \
|
|
14
|
+
TradeTakeProfitService
|
|
15
|
+
from .metrics import get_annual_volatility, get_mean_daily_return, \
|
|
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, get_daily_returns_std, \
|
|
20
|
+
get_cagr, get_standard_deviation_returns, get_mean_yearly_return, \
|
|
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
|
|
9
41
|
|
|
10
42
|
__all__ = [
|
|
11
|
-
"
|
|
43
|
+
"get_mean_daily_return",
|
|
44
|
+
"get_daily_returns_std",
|
|
12
45
|
"OrderService",
|
|
13
46
|
"RepositoryService",
|
|
14
47
|
"PortfolioService",
|
|
15
48
|
"PositionService",
|
|
16
49
|
"PortfolioConfigurationService",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
50
|
+
"OrderBacktestService",
|
|
51
|
+
"ConfigurationService",
|
|
52
|
+
"PortfolioSyncService",
|
|
53
|
+
"PortfolioSnapshotService",
|
|
54
|
+
"PositionSnapshotService",
|
|
55
|
+
"MarketCredentialService",
|
|
56
|
+
"BacktestPortfolioService",
|
|
57
|
+
"TradeService",
|
|
58
|
+
"DataProviderService",
|
|
59
|
+
"OrderExecutorLookup",
|
|
60
|
+
"BacktestTradeOrderEvaluator",
|
|
61
|
+
"PortfolioProviderLookup",
|
|
62
|
+
"TradeOrderEvaluator",
|
|
63
|
+
"DefaultTradeOrderEvaluator",
|
|
64
|
+
"get_risk_free_rate_us",
|
|
65
|
+
"get_annual_volatility",
|
|
66
|
+
"get_sortino_ratio",
|
|
67
|
+
"get_drawdown_series",
|
|
68
|
+
"get_max_drawdown",
|
|
69
|
+
"get_equity_curve",
|
|
70
|
+
"get_price_efficiency_ratio",
|
|
71
|
+
"get_sharpe_ratio",
|
|
72
|
+
"get_profit_factor",
|
|
73
|
+
"get_cumulative_profit_factor_series",
|
|
74
|
+
"get_rolling_profit_factor_series",
|
|
75
|
+
"get_sharpe_ratio",
|
|
76
|
+
"get_cagr",
|
|
77
|
+
"get_standard_deviation_returns",
|
|
78
|
+
"get_standard_deviation_downside_returns",
|
|
79
|
+
"get_max_drawdown_absolute",
|
|
80
|
+
"get_total_return",
|
|
81
|
+
"get_cumulative_exposure",
|
|
82
|
+
"get_exposure_ratio",
|
|
83
|
+
"get_average_trade_duration",
|
|
84
|
+
"get_win_rate",
|
|
85
|
+
"get_win_loss_ratio",
|
|
86
|
+
"get_calmar_ratio",
|
|
87
|
+
"get_trade_frequency",
|
|
88
|
+
"get_yearly_returns",
|
|
89
|
+
"get_monthly_returns",
|
|
90
|
+
"get_best_year",
|
|
91
|
+
"get_best_month",
|
|
92
|
+
"get_worst_year",
|
|
93
|
+
"get_worst_month",
|
|
94
|
+
"get_best_trade",
|
|
95
|
+
"get_worst_trade",
|
|
96
|
+
"get_average_yearly_return",
|
|
97
|
+
"get_average_trade_loss",
|
|
98
|
+
"get_average_monthly_return",
|
|
99
|
+
"get_percentage_winning_months",
|
|
100
|
+
"get_average_trade_duration",
|
|
101
|
+
"get_trade_frequency",
|
|
102
|
+
"get_win_rate",
|
|
103
|
+
"get_win_loss_ratio",
|
|
104
|
+
"get_calmar_ratio",
|
|
105
|
+
"get_max_drawdown_duration",
|
|
106
|
+
"get_max_daily_drawdown",
|
|
107
|
+
"get_trades_per_day",
|
|
108
|
+
"get_trades_per_year",
|
|
109
|
+
"get_average_monthly_return_losing_months",
|
|
110
|
+
"get_average_monthly_return_winning_months",
|
|
111
|
+
"get_percentage_winning_years",
|
|
112
|
+
"get_rolling_sharpe_ratio",
|
|
113
|
+
"get_total_growth",
|
|
114
|
+
"create_backtest_metrics",
|
|
115
|
+
"get_total_loss",
|
|
116
|
+
"get_median_trade_return",
|
|
117
|
+
"get_average_trade_gain",
|
|
118
|
+
"get_average_trade_size",
|
|
119
|
+
"get_average_trade_return",
|
|
120
|
+
"get_positive_trades",
|
|
121
|
+
"get_negative_trades",
|
|
122
|
+
"get_number_of_trades",
|
|
123
|
+
"get_cumulative_return",
|
|
124
|
+
"get_cumulative_return_series",
|
|
125
|
+
"get_current_win_loss_ratio",
|
|
126
|
+
"get_current_win_rate",
|
|
127
|
+
"get_current_win_loss_ratio",
|
|
128
|
+
"get_current_average_trade_loss",
|
|
129
|
+
"get_current_average_trade_duration",
|
|
130
|
+
"get_current_average_trade_gain",
|
|
131
|
+
"get_current_average_trade_return",
|
|
132
|
+
"create_backtest_metrics_for_backtest",
|
|
133
|
+
"TradeStopLossService",
|
|
134
|
+
"TradeTakeProfitService",
|
|
135
|
+
"get_mean_yearly_return"
|
|
19
136
|
]
|