investing-algorithm-framework 8.0.0__tar.gz → 8.1.0__tar.gz
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-8.0.0 → investing_algorithm_framework-8.1.0}/PKG-INFO +1 -1
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/context.py +5 -1
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/backtest_report.py +45 -2
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/templates/dashboard.js +300 -120
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/templates/dashboard_template.html.j2 +2 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/strategy.py +10 -5
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/mcp_server.py +825 -22
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +16 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +16 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/backtesting/combine_backtests.py +120 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/order/order.py +27 -3
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/services/backtesting/vector_backtest_service.py +10 -2
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/trade_service/trade_service.py +2 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/pyproject.toml +1 -1
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/LICENSE +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/README.md +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/analysis/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/analysis/backtest_data_ranges.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/analysis/markdown.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/analysis/ranking.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/algorithm/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/algorithm/algorithm.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/algorithm/algorithm_factory.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/app.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/app_hook.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/eventloop.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/ascii.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/backtest_report_old.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/charts/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/charts/entry_exist_signals.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/charts/equity_curve.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/charts/equity_curve_drawdown.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/charts/line_chart.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/charts/monthly_returns_heatmap.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/charts/ohlcv_data_completeness.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/charts/rolling_sharp_ratio.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/charts/yearly_returns_barchart.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/generate.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/tables/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/tables/key_metrics_table.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/tables/stop_loss_table.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/tables/time_metrics_table.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/tables/trade_metrics_table.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/tables/trades_table.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/tables/utils.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/templates/dashboard.css +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/reporting/templates/report_template.html.j2 +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/stateless/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/stateless/action_handlers/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/stateless/exception_handler.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/task.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/web/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/web/controllers/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/web/controllers/orders.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/web/controllers/portfolio.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/web/controllers/positions.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/web/create_app.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/web/error_handler.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/web/responses.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/web/run_strategies.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/web/schemas/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/web/schemas/order.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/web/schemas/portfolio.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/web/schemas/position.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/app/web/setup_cors.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/cli.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/deploy_to_aws_lambda.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/deploy_to_azure_function.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/initialize_app.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/.gitignore.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/app.py.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/app_azure_function.py.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/app_web.py.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/aws_lambda_readme.md.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/azure_function_host.json.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/data_providers.py.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/env.example.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/env_azure_function.example.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/market_data_providers.py.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/readme.md.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/requirements.txt.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/run_backtest.py.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/templates/strategy.py.template +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/cli/validate_backtest_checkpoints.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/create_app.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/dependency_container.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/algorithm_id.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/backtesting/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/backtesting/backtest.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/backtesting/backtest_date_range.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/backtesting/backtest_metrics.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/backtesting/backtest_run.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/backtesting/backtest_utils.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/backtesting/templates/backtest.html +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/backtesting/templates/finterion-dark.png +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/backtesting/templates/finterion-light.png +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/config.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/constants.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/data_provider.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/data_structures.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/decimal_parsing.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/exceptions.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/app_mode.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/base_model.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/data/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/data/data_source.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/data/data_type.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/event.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/market/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/market/market_credential.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/order/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/order/order.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/order/order_side.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/order/order_status.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/order/order_type.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/portfolio/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/portfolio/portfolio.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/position/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/position/position.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/position/position_size.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/position/position_snapshot.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/risk_rules/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/risk_rules/scaling_rule.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/risk_rules/stop_loss_rule.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/risk_rules/take_profit_rule.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/risk_rules/trading_cost.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/snapshot_interval.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/strategy_profile.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/time_frame.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/time_interval.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/time_unit.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/tracing/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/tracing/trace.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/trade/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/trade/trade.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/trade/trade_status.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/models/trade/trade_take_profit.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/order_executor.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/portfolio_provider.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/services/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/services/market_credential_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/services/portfolios/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/services/rounding_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/services/state_handler.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/stateless_actions.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/strategy.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/utils/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/utils/csv.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/utils/custom_tqdm.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/utils/dates.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/utils/polars.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/utils/random.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/utils/signatures.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/utils/stoppable_thread.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/domain/utils/synchronized.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/download_data.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/data_providers/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/data_providers/ccxt.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/data_providers/csv.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/data_providers/pandas.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/database/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/database/sql_alchemy.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/decimal_parser.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/model_extension.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/order/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/order/trade_allocation.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/order_trade_association.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/portfolio/sql_portfolio.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/position/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/position/position.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/trades/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/trades/trade.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/order_executors/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/order_executors/backtest_oder_executor.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/order_executors/ccxt_order_executor.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/portfolio_providers/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/portfolio_providers/ccxt_portfolio_provider.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/repositories/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/repositories/order_repository.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/repositories/portfolio_snapshot_repository.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/repositories/position_repository.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/repositories/position_snapshot_repository.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/repositories/repository.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/repositories/trade_allocation_repository.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/repositories/trade_repository.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/services/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/services/aws/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/services/aws/state_handler.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/services/azure/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/services/azure/state_handler.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/services/backtesting/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/services/backtesting/backtest_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/infrastructure/services/backtesting/event_backtest_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/configuration_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/data_providers/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/data_providers/data.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/data_providers/data_provider_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/market_credential_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/alpha.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/beta.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/cagr.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/calmar_ratio.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/drawdown.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/equity_curve.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/exposure.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/generate.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/mean_daily_return.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/price_efficiency.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/profit_factor.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/recovery.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/returns.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/risk_free_rate.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/sharpe_ratio.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/sortino_ratio.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/standard_deviation.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/trades.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/treynor_ratio.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/ulcer.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/value_at_risk.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/volatility.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/metrics/win_rate.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/order_service/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/order_service/order_backtest_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/order_service/order_executor_lookup.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/order_service/order_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/portfolios/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/portfolios/portfolio_configuration_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/portfolios/portfolio_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/positions/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/positions/position_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/positions/position_snapshot_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/repository_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/trade_order_evaluator/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/trade_service/__init__.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/trade_service/trade_stop_loss_service.py +0 -0
- {investing_algorithm_framework-8.0.0 → investing_algorithm_framework-8.1.0}/investing_algorithm_framework/services/trade_service/trade_take_profit_service.py +0 -0
|
@@ -161,7 +161,8 @@ class Context:
|
|
|
161
161
|
market=None,
|
|
162
162
|
execute=True,
|
|
163
163
|
validate=True,
|
|
164
|
-
sync=True
|
|
164
|
+
sync=True,
|
|
165
|
+
metadata=None
|
|
165
166
|
) -> Order:
|
|
166
167
|
"""
|
|
167
168
|
Function to create a limit order. This function will create a limit
|
|
@@ -257,6 +258,9 @@ class Context:
|
|
|
257
258
|
"trading_symbol": portfolio.trading_symbol,
|
|
258
259
|
}
|
|
259
260
|
|
|
261
|
+
if metadata is not None:
|
|
262
|
+
order_data["metadata"] = metadata
|
|
263
|
+
|
|
260
264
|
if BACKTESTING_FLAG in self.configuration_service.config \
|
|
261
265
|
and self.configuration_service.config[BACKTESTING_FLAG]:
|
|
262
266
|
order_data["created_at"] = \
|
|
@@ -125,14 +125,17 @@ class BacktestReport:
|
|
|
125
125
|
with open(path, "w") as f:
|
|
126
126
|
f.write(self.html_report)
|
|
127
127
|
|
|
128
|
+
if browser:
|
|
129
|
+
webbrowser.open(f"file://{path}")
|
|
130
|
+
return
|
|
131
|
+
|
|
128
132
|
try:
|
|
129
133
|
from IPython import get_ipython
|
|
130
134
|
shell = get_ipython().__class__.__name__
|
|
131
135
|
if shell == 'ZMQInteractiveShell':
|
|
132
136
|
from IPython.display import display, HTML
|
|
133
137
|
display(HTML(self.html_report))
|
|
134
|
-
|
|
135
|
-
return
|
|
138
|
+
return
|
|
136
139
|
except (NameError, ImportError):
|
|
137
140
|
pass
|
|
138
141
|
|
|
@@ -463,6 +466,29 @@ class BacktestReport:
|
|
|
463
466
|
op_dt = t.opened_at
|
|
464
467
|
cl_dt = t.closed_at
|
|
465
468
|
total_fees = getattr(t, 'total_fees', 0) or 0
|
|
469
|
+
# Stop-loss / take-profit status
|
|
470
|
+
t_sls = getattr(t, 'stop_losses', None)
|
|
471
|
+
t_tps = getattr(t, 'take_profits', None)
|
|
472
|
+
sl_triggered = any(
|
|
473
|
+
getattr(sl, 'triggered', False)
|
|
474
|
+
for sl in (t_sls or [])
|
|
475
|
+
)
|
|
476
|
+
tp_triggered = any(
|
|
477
|
+
getattr(tp, 'triggered', False)
|
|
478
|
+
for tp in (t_tps or [])
|
|
479
|
+
)
|
|
480
|
+
has_sl = bool(t_sls and len(t_sls) > 0)
|
|
481
|
+
has_tp = bool(t_tps and len(t_tps) > 0)
|
|
482
|
+
# Collect unique order reasons
|
|
483
|
+
t_reasons = set()
|
|
484
|
+
for t_o in (getattr(t, 'orders', None)
|
|
485
|
+
or []):
|
|
486
|
+
t_o_meta = getattr(
|
|
487
|
+
t_o, 'metadata', None
|
|
488
|
+
) or {}
|
|
489
|
+
r = t_o_meta.get('order_reason')
|
|
490
|
+
if r:
|
|
491
|
+
t_reasons.add(r)
|
|
466
492
|
trades_list.append({
|
|
467
493
|
'id': idx_t,
|
|
468
494
|
'sym': sym,
|
|
@@ -476,6 +502,17 @@ class BacktestReport:
|
|
|
476
502
|
'total_fees': round(total_fees, 4),
|
|
477
503
|
'net_gain': round(ng, 2),
|
|
478
504
|
'pct': round(pct, 2),
|
|
505
|
+
'stop_loss': (
|
|
506
|
+
'Triggered' if sl_triggered
|
|
507
|
+
else ('Set' if has_sl else '')
|
|
508
|
+
),
|
|
509
|
+
'take_profit': (
|
|
510
|
+
'Triggered' if tp_triggered
|
|
511
|
+
else ('Set' if has_tp else '')
|
|
512
|
+
),
|
|
513
|
+
'reasons': ', '.join(
|
|
514
|
+
sorted(t_reasons)
|
|
515
|
+
),
|
|
479
516
|
})
|
|
480
517
|
sym_stats.setdefault(sym, {'count': 0, 'gain': 0})
|
|
481
518
|
sym_stats[sym]['count'] += 1
|
|
@@ -588,6 +625,11 @@ class BacktestReport:
|
|
|
588
625
|
o_slippage = getattr(o, 'slippage', None)
|
|
589
626
|
if o_slippage is None:
|
|
590
627
|
o_slippage = 0
|
|
628
|
+
o_meta = getattr(o, 'metadata', None)
|
|
629
|
+
o_meta = o_meta if o_meta else {}
|
|
630
|
+
o_reason = o_meta.get(
|
|
631
|
+
'order_reason', ''
|
|
632
|
+
)
|
|
591
633
|
orders_list.append({
|
|
592
634
|
'sym': getattr(o, 'target_symbol', '')
|
|
593
635
|
or '',
|
|
@@ -617,6 +659,7 @@ class BacktestReport:
|
|
|
617
659
|
'slippage': round(
|
|
618
660
|
float(o_slippage), 4
|
|
619
661
|
),
|
|
662
|
+
'reason': o_reason,
|
|
620
663
|
'created': _fmt_date(o_dt)
|
|
621
664
|
if o_dt else '',
|
|
622
665
|
'updated': _fmt_date(u_dt)
|
|
@@ -24,6 +24,8 @@ const COMP_COLS = [
|
|
|
24
24
|
['Volatility','annual_volatility','pct_abs','min'],
|
|
25
25
|
['Recovery','recovery_factor','ratio','max'],
|
|
26
26
|
['Net Gain %','total_net_gain_percentage','pct','max'],
|
|
27
|
+
['Consistency','consistency_score','pct_abs','max'],
|
|
28
|
+
['Stability','stability_score','pct_abs','max'],
|
|
27
29
|
['VaR 95%','var_95','pct','min'],
|
|
28
30
|
['CVaR 95%','cvar_95','pct','min'],
|
|
29
31
|
];
|
|
@@ -1720,6 +1722,54 @@ function rebuildRankingTable() {
|
|
|
1720
1722
|
if (bestIdx>=0) bestVals[key]=bestIdx;
|
|
1721
1723
|
});
|
|
1722
1724
|
|
|
1725
|
+
// Absolute-threshold color coding: red/yellow/green based on
|
|
1726
|
+
// financially meaningful breakpoints, NOT relative ranking.
|
|
1727
|
+
// Returns a 0-1 score where 0=bad, 1=good.
|
|
1728
|
+
var _absThresholds = {
|
|
1729
|
+
// [bad_end, neutral, good_start] — linear interpolation between
|
|
1730
|
+
// 'max' metrics: higher value = better
|
|
1731
|
+
'cagr': [-0.05, 0, 0.15],
|
|
1732
|
+
'sharpe_ratio': [-0.5, 0.5, 1.5],
|
|
1733
|
+
'sortino_ratio': [-0.5, 0.5, 2.0],
|
|
1734
|
+
'calmar_ratio': [-0.5, 0.5, 2.0],
|
|
1735
|
+
'recovery_factor': [-1, 0, 2.0],
|
|
1736
|
+
'total_net_gain_percentage': [-0.05, 0, 0.20],
|
|
1737
|
+
'consistency_score': [0.2, 0.5, 0.8],
|
|
1738
|
+
'stability_score': [0.2, 0.5, 0.8],
|
|
1739
|
+
// 'min' metrics: lower absolute value = better (inverted internally)
|
|
1740
|
+
'max_drawdown': [0.03, 0.10, 0.25], // abs values
|
|
1741
|
+
'annual_volatility': [0.05, 0.15, 0.40],
|
|
1742
|
+
'var_95': [0, -0.02, -0.05], // negative; closer to 0 = better
|
|
1743
|
+
'cvar_95': [0, -0.03, -0.08],
|
|
1744
|
+
};
|
|
1745
|
+
|
|
1746
|
+
function _metricColor(key, v, direction) {
|
|
1747
|
+
if (v == null) return '';
|
|
1748
|
+
var th = _absThresholds[key];
|
|
1749
|
+
if (!th) return '';
|
|
1750
|
+
var t; // 0=bad … 1=good
|
|
1751
|
+
if (direction === 'min') {
|
|
1752
|
+
// For min-direction: value at th[0] = best (green), th[2] = worst (red)
|
|
1753
|
+
if (key === 'max_drawdown') v = Math.abs(v);
|
|
1754
|
+
if (th[2] !== th[0]) t = 1 - Math.max(0, Math.min(1, (v - th[0]) / (th[2] - th[0])));
|
|
1755
|
+
else t = 0.5;
|
|
1756
|
+
} else {
|
|
1757
|
+
// For max-direction: value at th[0] = worst (red), th[2] = best (green)
|
|
1758
|
+
if (th[2] !== th[0]) t = Math.max(0, Math.min(1, (v - th[0]) / (th[2] - th[0])));
|
|
1759
|
+
else t = 0.5;
|
|
1760
|
+
}
|
|
1761
|
+
var h, s, l;
|
|
1762
|
+
if (t <= 0.5) {
|
|
1763
|
+
h = Math.round(t * 2 * 45);
|
|
1764
|
+
s = 70; l = 44;
|
|
1765
|
+
} else {
|
|
1766
|
+
h = Math.round(45 + (t - 0.5) * 2 * 95);
|
|
1767
|
+
s = 65; l = 38 - Math.round((t - 0.5) * 2 * 4);
|
|
1768
|
+
}
|
|
1769
|
+
var alpha = 0.15 + t * 0.20;
|
|
1770
|
+
return 'color:hsl(' + h + ',' + (s + 10) + '%,' + (l - 10) + '%)';
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1723
1773
|
let html = '';
|
|
1724
1774
|
pageIndices.forEach(i => {
|
|
1725
1775
|
const s = STRATEGIES[i];
|
|
@@ -1730,11 +1780,18 @@ function rebuildRankingTable() {
|
|
|
1730
1780
|
html += '<td class="sticky-col" onclick="showPage(\'strat-'+i+'\')"><span class="sb-dot" style="background:'+s.color+'"></span>'+s.name+(s.tag ? ' <span class="tag-badge">'+s.tag+'</span>' : '')+'</td>';
|
|
1731
1781
|
COMP_COLS.forEach(([label,key,ftype,direction]) => {
|
|
1732
1782
|
const v = key === 'cagr' ? s.summary.cagr : m[key];
|
|
1733
|
-
const isBest = bestVals[key]===i;
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1783
|
+
const isBest = bestVals[key]===i && pageIndices.length > 1;
|
|
1784
|
+
var colorStyle = _metricColor(key, v, direction);
|
|
1785
|
+
var star = isBest ? ' ★' : '';
|
|
1786
|
+
var txt;
|
|
1787
|
+
if (key==='max_drawdown' && v!=null) txt = (Math.abs(v)*100).toFixed(1)+'%';
|
|
1788
|
+
else if (key==='average_trade_duration' && v!=null) txt = v.toFixed(1)+'d';
|
|
1789
|
+
else txt = fmtVal(v,ftype);
|
|
1790
|
+
if (colorStyle) {
|
|
1791
|
+
html += '<td onclick="showPage(\'strat-'+i+'\')"><span style="'+colorStyle+';font-weight:600">'+txt+star+'</span></td>';
|
|
1792
|
+
} else {
|
|
1793
|
+
html += '<td onclick="showPage(\'strat-'+i+'\')">'+txt+star+'</td>';
|
|
1794
|
+
}
|
|
1738
1795
|
});
|
|
1739
1796
|
html += '</tr>';
|
|
1740
1797
|
});
|
|
@@ -1848,6 +1905,8 @@ function updateStratSummary(stratIdx) {
|
|
|
1848
1905
|
+ kpiCard('Windows', String(m.number_of_windows || 0))
|
|
1849
1906
|
+ kpiCard('Profitable', String(m.number_of_profitable_windows || 0), 'var(--green)')
|
|
1850
1907
|
+ kpiCard('Total Net Gain', fmtVal(m.total_net_gain_percentage,'pct'))
|
|
1908
|
+
+ kpiCard('Consistency (CV)', m.consistency_score != null ? (m.consistency_score * 100).toFixed(1) + '%' : '—', m.consistency_score != null && m.consistency_score >= 0.6 ? 'var(--green)' : m.consistency_score != null && m.consistency_score < 0.4 ? 'var(--red)' : null)
|
|
1909
|
+
+ kpiCard('Stability (σ)', m.stability_score != null ? (m.stability_score * 100).toFixed(1) + '%' : '—', m.stability_score != null && m.stability_score >= 0.6 ? 'var(--green)' : m.stability_score != null && m.stability_score < 0.4 ? 'var(--red)' : null)
|
|
1851
1910
|
+ kpiCard('Runs', String(strat.runIds.length))
|
|
1852
1911
|
+ '</div>';
|
|
1853
1912
|
} else {
|
|
@@ -6061,6 +6120,9 @@ var tradesHeaders = [
|
|
|
6061
6120
|
{key: 'total_fees', label: 'Fees', align: 'right'},
|
|
6062
6121
|
{key: 'net_gain', label: 'Net Gain', align: 'right', colorFn: function(r) { return r.net_gain >= 0 ? 'var(--green)' : 'var(--red)'; }},
|
|
6063
6122
|
{key: 'pct', label: 'Return %', align: 'right', colorFn: function(r) { return r.pct >= 0 ? 'var(--green)' : 'var(--red)'; }},
|
|
6123
|
+
{key: 'stop_loss', label: 'Stop Loss', colorFn: function(r) { return r.stop_loss === 'Triggered' ? '#E91E63' : (r.stop_loss === 'Set' ? 'var(--text-secondary)' : ''); }},
|
|
6124
|
+
{key: 'take_profit', label: 'Take Profit', colorFn: function(r) { return r.take_profit === 'Triggered' ? '#9C27B0' : (r.take_profit === 'Set' ? 'var(--text-secondary)' : ''); }},
|
|
6125
|
+
{key: 'reasons', label: 'Order Reasons'},
|
|
6064
6126
|
];
|
|
6065
6127
|
|
|
6066
6128
|
var ordersHeaders = [
|
|
@@ -6068,6 +6130,10 @@ var ordersHeaders = [
|
|
|
6068
6130
|
{key: 'side', label: 'Side', colorFn: function(r) { return r.side === 'BUY' ? 'var(--green)' : 'var(--red)'; }},
|
|
6069
6131
|
{key: 'type', label: 'Type'},
|
|
6070
6132
|
{key: 'status', label: 'Status'},
|
|
6133
|
+
{key: 'reason', label: 'Reason', colorFn: function(r) {
|
|
6134
|
+
var c = {'buy_signal':'var(--green)','sell_signal':'var(--red)','scale_in':'#2196F3','scale_out':'#FF9800','stop_loss':'#E91E63','take_profit':'#9C27B0'};
|
|
6135
|
+
return c[r.reason] || '';
|
|
6136
|
+
}},
|
|
6071
6137
|
{key: 'price', label: 'Price', align: 'right'},
|
|
6072
6138
|
{key: 'amount', label: 'Amount', align: 'right'},
|
|
6073
6139
|
{key: 'filled', label: 'Filled', align: 'right'},
|
|
@@ -6124,8 +6190,7 @@ function buildPositionsTable(stratIdx) {
|
|
|
6124
6190
|
pagTableRenderers[tableKey]();
|
|
6125
6191
|
}
|
|
6126
6192
|
|
|
6127
|
-
//
|
|
6128
|
-
var timelineChartInstances = {};
|
|
6193
|
+
// Timeline scatter chart (custom canvas — no Chart.js dependency)
|
|
6129
6194
|
|
|
6130
6195
|
function buildTimelineScatter(stratIdx) {
|
|
6131
6196
|
var sid = 'strat-' + stratIdx;
|
|
@@ -6136,142 +6201,257 @@ function buildTimelineScatter(stratIdx) {
|
|
|
6136
6201
|
|
|
6137
6202
|
var trades = rd.TRADES || [];
|
|
6138
6203
|
var orders = rd.ORDERS || [];
|
|
6139
|
-
if (trades.length === 0 && orders.length === 0) {
|
|
6140
|
-
el.innerHTML = '';
|
|
6141
|
-
return;
|
|
6142
|
-
}
|
|
6204
|
+
if (trades.length === 0 && orders.length === 0) { el.innerHTML = ''; return; }
|
|
6143
6205
|
|
|
6144
|
-
//
|
|
6145
|
-
var
|
|
6146
|
-
var sellPoints = [];
|
|
6206
|
+
// Collect all points with symbol info
|
|
6207
|
+
var allPoints = [];
|
|
6147
6208
|
orders.forEach(function(o) {
|
|
6148
|
-
if (!o.created) return;
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6209
|
+
if (!o.created || !o.price) return;
|
|
6210
|
+
allPoints.push({
|
|
6211
|
+
date: o.created, y: o.price, sym: o.sym,
|
|
6212
|
+
label: o.sym + ' ' + o.side + ' ' + o.status,
|
|
6213
|
+
series: o.side === 'BUY' ? 'buy' : 'sell'
|
|
6214
|
+
});
|
|
6152
6215
|
});
|
|
6153
|
-
|
|
6154
|
-
var tradeOpenPoints = [];
|
|
6155
|
-
var tradeClosePoints = [];
|
|
6156
6216
|
trades.forEach(function(t) {
|
|
6157
|
-
if (t.opened) {
|
|
6158
|
-
|
|
6217
|
+
if (t.opened && t.open_price) {
|
|
6218
|
+
allPoints.push({date: t.opened, y: t.open_price, sym: t.sym, label: t.sym + ' opened', series: 'tradeOpen'});
|
|
6159
6219
|
}
|
|
6160
6220
|
if (t.closed && t.close_price) {
|
|
6161
|
-
|
|
6162
|
-
|
|
6221
|
+
allPoints.push({
|
|
6222
|
+
date: t.closed, y: t.close_price, sym: t.sym,
|
|
6223
|
+
label: t.sym + ' closed (' + (t.net_gain >= 0 ? '+' : '') + t.pct + '%)',
|
|
6224
|
+
series: 'tradeClose', gain: t.net_gain
|
|
6225
|
+
});
|
|
6163
6226
|
}
|
|
6164
6227
|
});
|
|
6228
|
+
if (allPoints.length === 0) { el.innerHTML = ''; return; }
|
|
6165
6229
|
|
|
6166
|
-
//
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6230
|
+
// Collect unique symbols sorted
|
|
6231
|
+
var symSet = {};
|
|
6232
|
+
allPoints.forEach(function(p) { if (p.sym) symSet[p.sym] = true; });
|
|
6233
|
+
var symbols = Object.keys(symSet).sort();
|
|
6234
|
+
|
|
6235
|
+
// Build dropdown HTML — default is empty prompt
|
|
6236
|
+
var optionsHtml = '<option value="" selected>Select asset\u2026</option>';
|
|
6237
|
+
symbols.forEach(function(s) { optionsHtml += '<option value="' + s + '">' + s + '</option>'; });
|
|
6171
6238
|
|
|
6172
6239
|
el.innerHTML = '<div class="chart-card">'
|
|
6173
|
-
+ '<div class="chart-title"
|
|
6240
|
+
+ '<div class="chart-title" style="display:flex;align-items:center;gap:12px;">'
|
|
6241
|
+
+ 'Trade & Order Timeline'
|
|
6242
|
+
+ '<select id="sel-' + sid + '-timeline-sym" style="'
|
|
6243
|
+
+ 'font-size:12px;padding:3px 8px;border-radius:6px;'
|
|
6244
|
+
+ 'border:1px solid var(--border,#23232a);background:var(--surface,#111113);'
|
|
6245
|
+
+ 'color:var(--text,#eaeaf0);cursor:pointer;outline:none;">'
|
|
6246
|
+
+ optionsHtml + '</select>'
|
|
6247
|
+
+ '</div>'
|
|
6174
6248
|
+ '<div class="chart-wrap"><canvas id="c-' + sid + '-timeline"></canvas>'
|
|
6175
6249
|
+ '<div class="tooltip" id="tt-' + sid + '-timeline"></div></div></div>';
|
|
6176
6250
|
|
|
6177
|
-
|
|
6178
|
-
|
|
6251
|
+
// Store points on element for redraw
|
|
6252
|
+
el._allPoints = allPoints;
|
|
6253
|
+
el._stratIdx = stratIdx;
|
|
6254
|
+
|
|
6255
|
+
// Draw initial prompt message (no symbol selected)
|
|
6256
|
+
_drawTimelineCanvas(sid, allPoints, '');
|
|
6179
6257
|
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
pointBackgroundColor: 'rgba(16,185,129,0.7)',
|
|
6186
|
-
pointBorderColor: 'rgba(16,185,129,1)',
|
|
6187
|
-
pointRadius: 5,
|
|
6188
|
-
pointStyle: 'triangle',
|
|
6189
|
-
showLine: false,
|
|
6190
|
-
_labels: buyPoints.map(function(p) { return p.label; }),
|
|
6258
|
+
// Dropdown change handler
|
|
6259
|
+
var sel = document.getElementById('sel-' + sid + '-timeline-sym');
|
|
6260
|
+
if (sel) {
|
|
6261
|
+
sel.addEventListener('change', function() {
|
|
6262
|
+
_drawTimelineCanvas(sid, el._allPoints, sel.value);
|
|
6191
6263
|
});
|
|
6192
6264
|
}
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6265
|
+
}
|
|
6266
|
+
|
|
6267
|
+
function _drawTimelineCanvas(sid, allPoints, filterSym) {
|
|
6268
|
+
// Filter points
|
|
6269
|
+
// Show prompt when no symbol selected
|
|
6270
|
+
if (!filterSym) {
|
|
6271
|
+
var canvas = document.getElementById('c-' + sid + '-timeline');
|
|
6272
|
+
if (canvas) {
|
|
6273
|
+
var r2 = resizeCanvas('c-' + sid + '-timeline');
|
|
6274
|
+
if (r2) {
|
|
6275
|
+
r2.ctx.font = '14px JetBrains Mono, monospace';
|
|
6276
|
+
r2.ctx.fillStyle = COL.dim; r2.ctx.textAlign = 'center';
|
|
6277
|
+
r2.ctx.fillText('Select an asset to view trades & orders', r2.w / 2, r2.h / 2);
|
|
6278
|
+
}
|
|
6279
|
+
}
|
|
6280
|
+
return;
|
|
6205
6281
|
}
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6282
|
+
|
|
6283
|
+
// Filter points by symbol
|
|
6284
|
+
var points = allPoints.filter(function(p) { return p.sym === filterSym; });
|
|
6285
|
+
if (points.length === 0) {
|
|
6286
|
+
var canvas = document.getElementById('c-' + sid + '-timeline');
|
|
6287
|
+
if (canvas) {
|
|
6288
|
+
var r2 = resizeCanvas('c-' + sid + '-timeline');
|
|
6289
|
+
if (r2) {
|
|
6290
|
+
r2.ctx.font = '13px JetBrains Mono, monospace';
|
|
6291
|
+
r2.ctx.fillStyle = COL.dim; r2.ctx.textAlign = 'center';
|
|
6292
|
+
r2.ctx.fillText('No data for selected asset', r2.w / 2, r2.h / 2);
|
|
6293
|
+
}
|
|
6294
|
+
}
|
|
6295
|
+
return;
|
|
6217
6296
|
}
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6297
|
+
|
|
6298
|
+
// Sort by date
|
|
6299
|
+
points.sort(function(a,b) { return a.date < b.date ? -1 : a.date > b.date ? 1 : 0; });
|
|
6300
|
+
var uniqueDates = [];
|
|
6301
|
+
var seen = {};
|
|
6302
|
+
points.forEach(function(p) { if (!seen[p.date]) { uniqueDates.push(p.date); seen[p.date] = true; } });
|
|
6303
|
+
|
|
6304
|
+
// Y range
|
|
6305
|
+
var ys = points.map(function(p) { return p.y; });
|
|
6306
|
+
var yMin = Math.min.apply(null, ys);
|
|
6307
|
+
var yMax = Math.max.apply(null, ys);
|
|
6308
|
+
if (yMin === yMax) { yMin -= 1; yMax += 1; }
|
|
6309
|
+
var yPad = (yMax - yMin) * 0.08;
|
|
6310
|
+
yMin -= yPad; yMax += yPad;
|
|
6311
|
+
var yRange = yMax - yMin;
|
|
6312
|
+
|
|
6313
|
+
var r = resizeCanvas('c-' + sid + '-timeline');
|
|
6314
|
+
if (!r) return;
|
|
6315
|
+
var ctx = r.ctx, w = r.w, h = r.h;
|
|
6316
|
+
var pad = { t: 25, r: 70, b: 35, l: 10 };
|
|
6317
|
+
var cw = w - pad.l - pad.r;
|
|
6318
|
+
var ch = h - pad.t - pad.b;
|
|
6319
|
+
|
|
6320
|
+
// Grid lines & Y labels
|
|
6321
|
+
ctx.strokeStyle = COL.border; ctx.lineWidth = 1;
|
|
6322
|
+
ctx.font = '10px JetBrains Mono, monospace'; ctx.fillStyle = COL.dim; ctx.textAlign = 'right';
|
|
6323
|
+
for (var i = 0; i <= 5; i++) {
|
|
6324
|
+
var gy = pad.t + ch - (i / 5) * ch;
|
|
6325
|
+
var val = yMin + (i / 5) * yRange;
|
|
6326
|
+
ctx.beginPath(); ctx.moveTo(pad.l, gy); ctx.lineTo(w - pad.r, gy); ctx.stroke();
|
|
6327
|
+
ctx.fillText(val.toFixed(val >= 100 ? 0 : 2), w - pad.r + 55, gy + 3.5);
|
|
6229
6328
|
}
|
|
6230
6329
|
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
var
|
|
6234
|
-
var
|
|
6235
|
-
var
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
ticks: {color: textColor, font: {size: 10}},
|
|
6270
|
-
title: {display: true, text: 'Price', color: textColor}
|
|
6271
|
-
}
|
|
6272
|
-
}
|
|
6330
|
+
// X labels
|
|
6331
|
+
ctx.textAlign = 'center';
|
|
6332
|
+
var maxLabels = Math.min(uniqueDates.length, 8);
|
|
6333
|
+
var step = Math.max(1, Math.floor(uniqueDates.length / maxLabels));
|
|
6334
|
+
for (var i = 0; i < uniqueDates.length; i += step) {
|
|
6335
|
+
var xFrac = uniqueDates.length > 1 ? i / (uniqueDates.length - 1) : 0.5;
|
|
6336
|
+
var lx = pad.l + xFrac * cw;
|
|
6337
|
+
ctx.fillText(uniqueDates[i], lx, h - 5);
|
|
6338
|
+
}
|
|
6339
|
+
|
|
6340
|
+
// Series colors
|
|
6341
|
+
var seriesColors = {
|
|
6342
|
+
buy: { fill: 'rgba(16,185,129,0.8)', stroke: 'rgba(16,185,129,1)' },
|
|
6343
|
+
sell: { fill: 'rgba(239,68,68,0.8)', stroke: 'rgba(239,68,68,1)' },
|
|
6344
|
+
tradeOpen: { fill: 'rgba(34,211,238,0.8)', stroke: 'rgba(34,211,238,1)' },
|
|
6345
|
+
tradeClose: { fill: null, stroke: null },
|
|
6346
|
+
};
|
|
6347
|
+
|
|
6348
|
+
// Draw legend
|
|
6349
|
+
var legendItems = [
|
|
6350
|
+
{ label: 'Buy', color: seriesColors.buy.fill, shape: 'triangle' },
|
|
6351
|
+
{ label: 'Sell', color: seriesColors.sell.fill, shape: 'triangleDown' },
|
|
6352
|
+
{ label: 'Trade Open', color: seriesColors.tradeOpen.fill, shape: 'circle' },
|
|
6353
|
+
{ label: 'Trade Close +', color: COL.green, shape: 'rect' },
|
|
6354
|
+
{ label: 'Trade Close \u2212', color: COL.red, shape: 'rect' },
|
|
6355
|
+
];
|
|
6356
|
+
ctx.font = '10px JetBrains Mono, monospace';
|
|
6357
|
+
var lx = pad.l + 5;
|
|
6358
|
+
legendItems.forEach(function(item) {
|
|
6359
|
+
ctx.fillStyle = item.color;
|
|
6360
|
+
if (item.shape === 'circle') {
|
|
6361
|
+
ctx.beginPath(); ctx.arc(lx + 4, pad.t - 12, 4, 0, Math.PI * 2); ctx.fill();
|
|
6362
|
+
} else if (item.shape === 'triangle') {
|
|
6363
|
+
ctx.beginPath(); ctx.moveTo(lx, pad.t - 8); ctx.lineTo(lx + 8, pad.t - 8); ctx.lineTo(lx + 4, pad.t - 16); ctx.closePath(); ctx.fill();
|
|
6364
|
+
} else if (item.shape === 'triangleDown') {
|
|
6365
|
+
ctx.beginPath(); ctx.moveTo(lx, pad.t - 16); ctx.lineTo(lx + 8, pad.t - 16); ctx.lineTo(lx + 4, pad.t - 8); ctx.closePath(); ctx.fill();
|
|
6366
|
+
} else {
|
|
6367
|
+
ctx.fillRect(lx, pad.t - 16, 8, 8);
|
|
6273
6368
|
}
|
|
6369
|
+
ctx.fillStyle = COL.dim;
|
|
6370
|
+
ctx.textAlign = 'left';
|
|
6371
|
+
ctx.fillText(item.label, lx + 12, pad.t - 8);
|
|
6372
|
+
lx += ctx.measureText(item.label).width + 24;
|
|
6274
6373
|
});
|
|
6374
|
+
|
|
6375
|
+
// Draw points
|
|
6376
|
+
var hitBoxes = [];
|
|
6377
|
+
points.forEach(function(p) {
|
|
6378
|
+
var di = uniqueDates.indexOf(p.date);
|
|
6379
|
+
var xFrac = uniqueDates.length > 1 ? di / (uniqueDates.length - 1) : 0.5;
|
|
6380
|
+
var px = pad.l + xFrac * cw;
|
|
6381
|
+
var py = pad.t + ch - ((p.y - yMin) / yRange) * ch;
|
|
6382
|
+
var radius = 5;
|
|
6383
|
+
var sc = seriesColors[p.series];
|
|
6384
|
+
var fillC, strokeC;
|
|
6385
|
+
|
|
6386
|
+
if (p.series === 'tradeClose') {
|
|
6387
|
+
fillC = p.gain >= 0 ? COL.green : COL.red;
|
|
6388
|
+
strokeC = fillC;
|
|
6389
|
+
} else {
|
|
6390
|
+
fillC = sc.fill; strokeC = sc.stroke;
|
|
6391
|
+
}
|
|
6392
|
+
|
|
6393
|
+
ctx.fillStyle = fillC; ctx.strokeStyle = strokeC; ctx.lineWidth = 1.5;
|
|
6394
|
+
|
|
6395
|
+
if (p.series === 'buy') {
|
|
6396
|
+
ctx.beginPath();
|
|
6397
|
+
ctx.moveTo(px, py - radius); ctx.lineTo(px - radius, py + radius); ctx.lineTo(px + radius, py + radius);
|
|
6398
|
+
ctx.closePath(); ctx.fill(); ctx.stroke();
|
|
6399
|
+
} else if (p.series === 'sell') {
|
|
6400
|
+
ctx.beginPath();
|
|
6401
|
+
ctx.moveTo(px, py + radius); ctx.lineTo(px - radius, py - radius); ctx.lineTo(px + radius, py - radius);
|
|
6402
|
+
ctx.closePath(); ctx.fill(); ctx.stroke();
|
|
6403
|
+
} else if (p.series === 'tradeOpen') {
|
|
6404
|
+
ctx.beginPath(); ctx.arc(px, py, radius, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
|
|
6405
|
+
} else {
|
|
6406
|
+
var s = radius * 1.4;
|
|
6407
|
+
ctx.beginPath();
|
|
6408
|
+
ctx.moveTo(px - s + 2, py - s); ctx.lineTo(px + s - 2, py - s);
|
|
6409
|
+
ctx.quadraticCurveTo(px + s, py - s, px + s, py - s + 2);
|
|
6410
|
+
ctx.lineTo(px + s, py + s - 2);
|
|
6411
|
+
ctx.quadraticCurveTo(px + s, py + s, px + s - 2, py + s);
|
|
6412
|
+
ctx.lineTo(px - s + 2, py + s);
|
|
6413
|
+
ctx.quadraticCurveTo(px - s, py + s, px - s, py + s - 2);
|
|
6414
|
+
ctx.lineTo(px - s, py - s + 2);
|
|
6415
|
+
ctx.quadraticCurveTo(px - s, py - s, px - s + 2, py - s);
|
|
6416
|
+
ctx.closePath(); ctx.fill(); ctx.stroke();
|
|
6417
|
+
}
|
|
6418
|
+
|
|
6419
|
+
hitBoxes.push({ x: px, y: py, r: radius + 3, label: p.label, price: p.y, date: p.date });
|
|
6420
|
+
});
|
|
6421
|
+
|
|
6422
|
+
// Store hitbox data for tooltip
|
|
6423
|
+
var canvas = document.getElementById('c-' + sid + '-timeline');
|
|
6424
|
+
canvas._timelineHitBoxes = hitBoxes;
|
|
6425
|
+
|
|
6426
|
+
// Setup tooltip (remove old listeners by cloning)
|
|
6427
|
+
var tooltip = document.getElementById('tt-' + sid + '-timeline');
|
|
6428
|
+
if (canvas && tooltip) {
|
|
6429
|
+
var newCanvas = canvas.cloneNode(true);
|
|
6430
|
+
newCanvas._timelineHitBoxes = hitBoxes;
|
|
6431
|
+
newCanvas.getContext('2d').drawImage(canvas, 0, 0);
|
|
6432
|
+
canvas.parentNode.replaceChild(newCanvas, canvas);
|
|
6433
|
+
newCanvas.addEventListener('mousemove', function(e) {
|
|
6434
|
+
var rect = newCanvas.getBoundingClientRect();
|
|
6435
|
+
var mx = e.clientX - rect.left;
|
|
6436
|
+
var my = e.clientY - rect.top;
|
|
6437
|
+
var hit = null;
|
|
6438
|
+
var boxes = newCanvas._timelineHitBoxes || [];
|
|
6439
|
+
for (var i = 0; i < boxes.length; i++) {
|
|
6440
|
+
var b = boxes[i];
|
|
6441
|
+
var dx = mx - b.x, dy = my - b.y;
|
|
6442
|
+
if (dx * dx + dy * dy <= b.r * b.r) { hit = b; break; }
|
|
6443
|
+
}
|
|
6444
|
+
if (hit) {
|
|
6445
|
+
tooltip.textContent = hit.date + ': ' + hit.label + ' @ ' + hit.price.toFixed(2);
|
|
6446
|
+
tooltip.classList.add('visible');
|
|
6447
|
+
tooltip.style.left = (mx + 12) + 'px';
|
|
6448
|
+
tooltip.style.top = (my - 20) + 'px';
|
|
6449
|
+
} else {
|
|
6450
|
+
tooltip.classList.remove('visible');
|
|
6451
|
+
}
|
|
6452
|
+
});
|
|
6453
|
+
newCanvas.addEventListener('mouseleave', function() { tooltip.classList.remove('visible'); });
|
|
6454
|
+
}
|
|
6275
6455
|
}
|
|
6276
6456
|
|
|
6277
6457
|
function updateStratTables(stratIdx) {
|
|
@@ -148,6 +148,8 @@
|
|
|
148
148
|
<th data-col="annual_volatility">Volatility <span class="sort-arrow">▲</span></th>
|
|
149
149
|
<th data-col="recovery_factor">Recovery <span class="sort-arrow">▲</span></th>
|
|
150
150
|
<th data-col="total_net_gain_percentage">Net Gain % <span class="sort-arrow">▲</span></th>
|
|
151
|
+
<th data-col="consistency_score">Consistency <span class="sort-arrow">▲</span></th>
|
|
152
|
+
<th data-col="stability_score">Stability <span class="sort-arrow">▲</span></th>
|
|
151
153
|
<th data-col="var_95">VaR 95% <span class="sort-arrow">▲</span></th>
|
|
152
154
|
<th data-col="cvar_95">CVaR 95% <span class="sort-arrow">▲</span></th>
|
|
153
155
|
</tr>
|