aether-quant 0.7.0__tar.gz → 0.8.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.
- {aether_quant-0.7.0 → aether_quant-0.8.0}/Dockerfile.retraining_worker +1 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/PKG-INFO +1 -1
- {aether_quant-0.7.0 → aether_quant-0.8.0}/README.md +120 -20
- {aether_quant-0.7.0 → aether_quant-0.8.0}/aether_quant.egg-info/PKG-INFO +1 -1
- {aether_quant-0.7.0 → aether_quant-0.8.0}/aether_quant.egg-info/SOURCES.txt +24 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/aether_quant.egg-info/scm_file_list.json +24 -0
- aether_quant-0.8.0/aether_quant.egg-info/scm_version.json +8 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/analyzer/README.md +20 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/analyzer/market_analyzer.py +13 -6
- {aether_quant-0.7.0 → aether_quant-0.8.0}/aq_cli.py +25 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/config.json +211 -10
- {aether_quant-0.7.0 → aether_quant-0.8.0}/data_pipeline/README.md +35 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/data_pipeline/yfinance_backfill.py +9 -1
- {aether_quant-0.7.0 → aether_quant-0.8.0}/development/Changelog.md +772 -2
- {aether_quant-0.7.0 → aether_quant-0.8.0}/development/Problems.md +229 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/development/v2_architecture.md +171 -11
- {aether_quant-0.7.0 → aether_quant-0.8.0}/docker-compose.yml +26 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/execution/README.md +51 -0
- aether_quant-0.8.0/execution/paper_readiness_scheduler.py +137 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/experience/redis_queue.py +16 -0
- aether_quant-0.8.0/features/__init__.py +35 -0
- aether_quant-0.8.0/features/macro_features.py +79 -0
- aether_quant-0.8.0/features/technical_indicators.py +185 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/inference/README.md +8 -4
- {aether_quant-0.7.0 → aether_quant-0.8.0}/inference/__init__.py +2 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/inference/exported_model.py +15 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/lean.json +1 -1
- {aether_quant-0.7.0 → aether_quant-0.8.0}/main.py +536 -132
- aether_quant-0.8.0/ml/gating_model.json +570 -0
- aether_quant-0.8.0/ml/gating_training_metrics.json +130 -0
- {aether_quant-0.7.0/ml/versions/v1 → aether_quant-0.8.0/ml}/multitask_feature_schema.json +25 -1
- aether_quant-0.8.0/ml/multitask_model.json +7703 -0
- aether_quant-0.8.0/ml/multitask_training_metrics.json +6320 -0
- {aether_quant-0.7.0/ml/versions/v1 → aether_quant-0.8.0/ml}/sequence_feature_schema.json +11 -0
- aether_quant-0.8.0/ml/sequence_model.json +15233 -0
- aether_quant-0.8.0/ml/sequence_training_metrics.json +506 -0
- aether_quant-0.8.0/ml/versions/gating-only-05c572c8-9566-4152-805c-fa57142a3f8c/gating_model.json +570 -0
- aether_quant-0.8.0/ml/versions/gating-only-05c572c8-9566-4152-805c-fa57142a3f8c/gating_training_metrics.json +130 -0
- aether_quant-0.8.0/ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c/multitask_feature_schema.json +76 -0
- aether_quant-0.8.0/ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c/multitask_model.json +7703 -0
- aether_quant-0.8.0/ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c/multitask_training_metrics.json +6320 -0
- aether_quant-0.8.0/ml/versions/stage4-1783711025/gating_feature_schema.json +30 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/ml/versions/v1/multitask_model.json +1 -1
- {aether_quant-0.7.0 → aether_quant-0.8.0}/ml/versions/v1/multitask_training_metrics.json +38 -2
- {aether_quant-0.7.0 → aether_quant-0.8.0}/ml/versions/v1/sequence_model.json +1 -1
- {aether_quant-0.7.0 → aether_quant-0.8.0}/ml/versions/v1/sequence_training_metrics.json +41 -2
- {aether_quant-0.7.0 → aether_quant-0.8.0}/moe/README.md +62 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/moe/gating.py +44 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/monitoring/neural_network_state.py +70 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/performance/README.md +20 -2
- aether_quant-0.8.0/performance/rank_ic_monitor.py +122 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/performance/trigger_worker.py +16 -1
- {aether_quant-0.7.0 → aether_quant-0.8.0}/performance/triggers.py +78 -1
- aether_quant-0.8.0/portfolio/README.md +154 -0
- aether_quant-0.8.0/portfolio/__init__.py +8 -0
- aether_quant-0.8.0/portfolio/book_construction.py +137 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/retraining/README.md +19 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/retraining/planning.py +8 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/risk/README.md +57 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/risk/position_sizing.py +54 -1
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/README.md +2 -2
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_aq_cli.py +31 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_experience_queue.py +17 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_exported_model.py +19 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_gating_network.py +114 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_lean_backtest_ml_coverage.py +14 -8
- aether_quant-0.8.0/tests/test_macro_features.py +49 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_market_analyzer.py +46 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_market_topology.py +103 -1
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_neural_network_state.py +116 -0
- aether_quant-0.8.0/tests/test_paper_readiness_scheduler.py +104 -0
- aether_quant-0.8.0/tests/test_portfolio_book_construction.py +150 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_position_sizing.py +87 -0
- aether_quant-0.8.0/tests/test_rank_ic_monitor.py +137 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_retraining_planning.py +17 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_retraining_worker.py +16 -2
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_simulated_portfolio.py +29 -0
- aether_quant-0.8.0/tests/test_technical_indicators.py +261 -0
- aether_quant-0.8.0/tests/test_train_cross_sectional_features.py +535 -0
- aether_quant-0.8.0/tests/test_train_indicators.py +187 -0
- aether_quant-0.8.0/tests/test_train_macro_features.py +157 -0
- aether_quant-0.8.0/tests/test_train_multitask.py +278 -0
- aether_quant-0.8.0/tests/test_train_pipeline.py +931 -0
- aether_quant-0.8.0/tests/test_train_ranking_validation.py +385 -0
- aether_quant-0.8.0/tests/test_train_sequence.py +193 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_train_sequence_architecture.py +54 -0
- aether_quant-0.8.0/tests/test_train_walk_forward_windows.py +131 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_trigger_worker.py +29 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_triggers.py +95 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/topology/market_topology.py +36 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/train.py +1737 -26
- {aether_quant-0.7.0 → aether_quant-0.8.0}/train_multitask.py +187 -84
- {aether_quant-0.7.0 → aether_quant-0.8.0}/train_sequence.py +184 -73
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/neuralnet/NeuralNetworkStatsPanel.tsx +65 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/risk/AssetSizingTable.tsx +8 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/signals/Badge.tsx +5 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/types/state.ts +53 -0
- aether_quant-0.7.0/aether_quant.egg-info/scm_version.json +0 -8
- aether_quant-0.7.0/ml/versions/stage4-1783711025/gating_model.json +0 -570
- aether_quant-0.7.0/ml/versions/stage4-1783711025/gating_training_metrics.json +0 -190
- aether_quant-0.7.0/ml/versions/stage4-1783711025/multitask_model.json +0 -5888
- aether_quant-0.7.0/ml/versions/stage4-1783711025/multitask_training_metrics.json +0 -248
- aether_quant-0.7.0/ml/versions/stage5-1783715333/sequence_model.json +0 -13258
- aether_quant-0.7.0/ml/versions/stage5-1783715333/sequence_training_metrics.json +0 -209
- aether_quant-0.7.0/tests/test_train_cross_sectional_features.py +0 -243
- aether_quant-0.7.0/tests/test_train_multitask.py +0 -113
- aether_quant-0.7.0/tests/test_train_pipeline.py +0 -285
- {aether_quant-0.7.0 → aether_quant-0.8.0}/.dockerignore +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/.env.compose.example +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/.env.live.example +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/.gitattributes +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/.github/workflows/ci.yml +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/.github/workflows/release.yml +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/.gitignore +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/Dockerfile +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/Dockerfile.workers +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/aether_quant.egg-info/dependency_links.txt +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/aether_quant.egg-info/entry_points.txt +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/aether_quant.egg-info/top_level.txt +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/analyzer/__init__.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/backtests/.gitkeep +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/data/alternative/estimize/consensus/aapl/.keep +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/data/alternative/estimize/estimate/.keep +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/data/alternative/estimize/release/.keep +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/data/alternative/sec/aapl/.keep +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/data/alternative/trading-economics/.keep +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/data/alternative/trading-economics/calendar/.keep +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/data/alternative/trading-economics/earnings/.keep +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/data/alternative/trading-economics/indicator/.keep +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/data_pipeline/__init__.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/data_pipeline/fetch.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/data_pipeline/v2_manifest.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/development/README.md +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/development/backtest_equity_chart.png +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/development/infrastructure.md +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/development/logo.png +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/execution/__init__.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/execution/config_cache.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/execution/live_credentials.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/execution/live_credentials_io.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/execution/order_gate.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/execution/paper_readiness.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/execution/paper_readiness_io.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/execution/paper_readiness_report.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/execution/runtime_config_io.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/experience/README.md +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/experience/__init__.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/experience/observation_metrics.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/experience/postgres_worker.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/experience/simulated_portfolio.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/experts/README.md +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/experts/__init__.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/experts/expert_datasets.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/generate_backtest_report.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/liquidity/README.md +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/liquidity/__init__.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/liquidity/market_liquidity.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/ml/README.md +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/ml/gating_feature_schema.json +0 -0
- {aether_quant-0.7.0/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459 → aether_quant-0.8.0/ml/versions/gating-only-05c572c8-9566-4152-805c-fa57142a3f8c}/gating_feature_schema.json +0 -0
- {aether_quant-0.7.0/ml/versions/stage123-1783709428 → aether_quant-0.8.0/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459}/gating_feature_schema.json +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_model.json +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_training_metrics.json +0 -0
- {aether_quant-0.7.0/ml/versions/stage4-1783711025 → aether_quant-0.8.0/ml/versions/stage123-1783709428}/gating_feature_schema.json +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/ml/versions/stage123-1783709428/gating_model.json +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/ml/versions/stage123-1783709428/gating_training_metrics.json +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/ml/versions/stage123-1783709428/multitask_feature_schema.json +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/ml/versions/stage123-1783709428/multitask_model.json +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/ml/versions/stage123-1783709428/multitask_training_metrics.json +0 -0
- {aether_quant-0.7.0/ml → aether_quant-0.8.0/ml/versions/stage4-1783711025}/gating_model.json +0 -0
- {aether_quant-0.7.0/ml → aether_quant-0.8.0/ml/versions/stage4-1783711025}/gating_training_metrics.json +0 -0
- {aether_quant-0.7.0/ml → aether_quant-0.8.0/ml/versions/stage4-1783711025}/multitask_feature_schema.json +0 -0
- {aether_quant-0.7.0/ml → aether_quant-0.8.0/ml/versions/stage4-1783711025}/multitask_model.json +0 -0
- {aether_quant-0.7.0/ml → aether_quant-0.8.0/ml/versions/stage4-1783711025}/multitask_training_metrics.json +0 -0
- {aether_quant-0.7.0/ml → aether_quant-0.8.0/ml/versions/stage5-1783715333}/sequence_feature_schema.json +0 -0
- {aether_quant-0.7.0/ml → aether_quant-0.8.0/ml/versions/stage5-1783715333}/sequence_model.json +0 -0
- {aether_quant-0.7.0/ml → aether_quant-0.8.0/ml/versions/stage5-1783715333}/sequence_training_metrics.json +0 -0
- {aether_quant-0.7.0/ml/versions/stage4-1783711025 → aether_quant-0.8.0/ml/versions/v1}/multitask_feature_schema.json +0 -0
- {aether_quant-0.7.0/ml/versions/stage5-1783715333 → aether_quant-0.8.0/ml/versions/v1}/sequence_feature_schema.json +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/moe/__init__.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/monitoring/README.md +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/monitoring/__init__.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/monitoring/api_server.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/notifications/README.md +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/notifications/__init__.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/notifications/postgres_telegram.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/notifications/telegram_alerts.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/notifications/telegram_client.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/notifications/telegram_worker.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/performance/__init__.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/performance/postgres_triggers.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/pyproject.toml +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/regime/README.md +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/regime/__init__.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/regime/market_regime.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/requirements/README.md +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/requirements/requirements-dev.txt +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/requirements/requirements-retraining-worker.txt +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/requirements/requirements-runtime.txt +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/requirements/requirements-workers.txt +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/requirements/requirements.txt +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/retraining/__init__.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/retraining/artifacts.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/retraining/backtest_gate.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/retraining/lean_backtest.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/retraining/orchestrator.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/retraining/postgres_registry.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/retraining/status_export.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/retraining/validation_gate.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/retraining/vault_client.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/retraining/vault_commands.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/retraining/worker.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/risk/__init__.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/risk/manual_override.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/risk_controls.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/setup.cfg +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_backtest_gate.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_config_cache.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_expert_datasets.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_expert_models.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_fetch.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_generate_backtest_report.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_lean_backtest.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_learned_topology.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_live_credentials.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_live_credentials_io.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_manual_override.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_market_liquidity.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_market_regime.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_observation_metrics.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_order_gate.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_paper_readiness.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_paper_readiness_io.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_paper_readiness_report.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_postgres_telegram.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_postgres_triggers.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_postgres_worker.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_retraining_artifacts.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_retraining_orchestrator.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_retraining_postgres_registry.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_risk_controls.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_runtime_config_io.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_status_export.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_telegram_alerts.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_telegram_client.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_telegram_worker.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_train_gating.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_train_multitask_architecture.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_train_topology.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_v2_pipeline_manifest.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_validation_gate.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_vault_client.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_vault_commands.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/tests/test_yfinance_backfill.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/topology/README.md +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/topology/__init__.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/topology/learned_topology.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/train_gating.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/train_topology.py +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/visualization/README.md +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/.gitignore +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/.oxlintrc.json +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/README.md +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/index.html +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/overview_v2_12.png +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/package-lock.json +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/package.json +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/public/favicon.svg +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/public/icons.svg +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/risk_v2_12.png +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/App.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/api/client.ts +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/api/hooks.ts +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/heatmap/AssetHeatmap.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/layout/AppShell.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/layout/Panel.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/monitoring/CountTable.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/monitoring/MonitoringFeeds.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/monitoring/ObservationPanel.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/monitoring/PaperReadinessPanel.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/monitoring/PerformanceTriggersPanel.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/monitoring/RawStateViewer.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/monitoring/RetrainingStatusPanel.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/neuralnet/NeuralNetworkScene3D.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/risk/LiquidityTable.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/risk/RiskBar.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/risk/RiskCore.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/risk/StrategyRiskCards.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/scene3d/Scene3D.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/scorecards/Scorecards.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/signals/PositionsList.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/signals/SignalBoard.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/topology/ClusterList.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/topology/TopologyLearningPanel.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/topology/TopologyScene3D.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/tracing/AssetPerformancePanel.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/tracing/BacktestEquityPanel.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/tracing/DivergingBarChart.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/tracing/LineChart.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/tracing/MetricsSnapshotPanel.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/components/tracing/ObservationEquityPanel.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/index.css +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/lib/downsample.ts +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/lib/format.ts +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/main.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/pages/NeuralNetworkPage.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/pages/Overview.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/pages/RiskPage.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/pages/TopologyPage.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/pages/TracingPage.tsx +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/src/types/tracing.ts +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/tsconfig.app.json +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/tsconfig.json +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/tsconfig.node.json +0 -0
- {aether_quant-0.7.0 → aether_quant-0.8.0}/webui/vite.config.ts +0 -0
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
12
|
<img src="https://img.shields.io/badge/python-3.10%2B-FF8C00?style=flat-square&labelColor=1A1A1A&logo=python&logoColor=white" alt="Python 3.10+">
|
|
13
|
-
<!-- AQ:TEST_BADGE_START --><img src="https://img.shields.io/badge/tests-
|
|
13
|
+
<!-- AQ:TEST_BADGE_START --><img src="https://img.shields.io/badge/tests-934%2F945%20passing-red?style=flat-square&labelColor=1A1A1A" alt="934 of 945 tests passing"><!-- AQ:TEST_BADGE_END -->
|
|
14
14
|
<img src="https://img.shields.io/pypi/v/aether-quant?style=flat-square&labelColor=1A1A1A&color=FF8C00" alt="PyPI version">
|
|
15
15
|
<img src="https://img.shields.io/badge/docker-ghcr.io%2Faether--quant-2496ED?style=flat-square&labelColor=1A1A1A&logo=docker&logoColor=white" alt="Docker image on GHCR">
|
|
16
16
|
</p>
|
|
@@ -32,14 +32,16 @@ Mixture-of-Experts ensemble (bullish/bearish/sideways/volatility specialists)
|
|
|
32
32
|
routed by a learned gating network, a market-regime detector, a 3D market
|
|
33
33
|
topology layer that combines a deterministic correlation embedding with a
|
|
34
34
|
learned probabilistic overlay, a liquidity/market-impact engine that adjusts
|
|
35
|
-
position sizing to real trading conditions,
|
|
36
|
-
that
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
position sizing to real trading conditions, a cross-sectional ranking signal
|
|
36
|
+
that sizes each position by its predicted relative strength against the rest
|
|
37
|
+
of the trading universe, and a controlled retraining loop that lets the
|
|
38
|
+
model itself evolve as markets do — all wired together and validated
|
|
39
|
+
end-to-end inside QuantConnect's Lean engine. The thesis this project exists
|
|
40
|
+
to test is simple to state and hard to prove: **markets are non-stationary,
|
|
41
|
+
so a trading model should be too.** Every subsystem here exists to make the
|
|
42
|
+
model adapt — to regime shifts, to changing correlation structure, to
|
|
43
|
+
liquidity conditions — rather than to fit one historical window and hope it
|
|
44
|
+
generalizes.
|
|
43
45
|
|
|
44
46
|
## Table of Contents
|
|
45
47
|
|
|
@@ -158,7 +160,7 @@ that a controlled retraining loop reads from to evolve the model over time.
|
|
|
158
160
|
|
|
159
161
|
```mermaid
|
|
160
162
|
flowchart LR
|
|
161
|
-
A["Lean data folder<br/>stocks, ETFs, crypto"] --> B["Feature pipeline<br/>train.py<br/>
|
|
163
|
+
A["Lean data folder<br/>stocks, ETFs, bonds, crypto"] --> B["Feature pipeline<br/>train.py<br/>62-dim: price/volume + indicators +<br/>regime + liquidity + topology + peer returns + macro"]
|
|
162
164
|
B --> C["Regime detection<br/>trend, volatility, drawdown, correlation"]
|
|
163
165
|
B --> D["3D topology modeling<br/>market structure and clusters"]
|
|
164
166
|
B -.-> U["Sequence encoder (Phase 2)<br/>causal-TCN, 30-bar window<br/>informational only"]
|
|
@@ -250,6 +252,52 @@ topology correlation/risk state are all computed offline
|
|
|
250
252
|
(`main.py::_build_model_input()`, reordered so regime is computed
|
|
251
253
|
*before* the model runs) with verified train/runtime parity.
|
|
252
254
|
|
|
255
|
+
**Multi-horizon direction, cross-sectional ranking, correlated-peer
|
|
256
|
+
returns and technical indicators (model input 48 → 59).** A root-cause
|
|
257
|
+
investigation found every model — baseline, all 4 experts, the multitask
|
|
258
|
+
heads, the sequence encoder — sitting at backtest MCC 0.02-0.07 (noise) on
|
|
259
|
+
next-day binary direction, and traced (and fixed) real data bugs
|
|
260
|
+
confounding those numbers: an unadjusted-split bug in `train.py`'s own
|
|
261
|
+
Lean-zip reader (Lean's live/backtest engine was never affected — see
|
|
262
|
+
`development/Problems.md` #24) and a data-feed volume-unit discontinuity
|
|
263
|
+
that blew up the sequence model's RMSE 31x (#23). Beyond the fixes,
|
|
264
|
+
`AetherNetMultiTaskHorizons`/`AetherNetSequenceMultiTaskHorizons` (new
|
|
265
|
+
sibling classes to the originals — experts/baseline/gating stay
|
|
266
|
+
1d-direction-only by design) add 4 heads: `direction_5d`/`direction_20d`
|
|
267
|
+
(longer-horizon direction) and `rank_5d`/`rank_20d` (per-date
|
|
268
|
+
cross-sectional percentile rank of forward return — the most learnable
|
|
269
|
+
target this investigation found, maps directly onto a long/short
|
|
270
|
+
portfolio, evaluated via rank-IC, `train.py::compute_rank_ic()`, not MCC).
|
|
271
|
+
11 new scaled input features: 4 correlated-peer lagged-return features
|
|
272
|
+
(`topology/market_topology.py`'s `top_peers`/`top_peer_returns`, a genuine
|
|
273
|
+
new information channel from correlation data the model previously only
|
|
274
|
+
saw as a compressed scalar) and 7 technical indicators (`features/`
|
|
275
|
+
package — RSI, ATR%, Bollinger %B, volume z-score, MACD histogram,
|
|
276
|
+
distance-from-52-week-high, cross-sectional momentum rank), all computed
|
|
277
|
+
identically offline and at runtime by construction (shared pure
|
|
278
|
+
functions, not hand-matched duplicated formulas). All new signals are
|
|
279
|
+
visible on `/neural-network` and in `*_training_metrics.json`; see
|
|
280
|
+
`development/Changelog.md`'s "Frontier-model edge investigation" entry
|
|
281
|
+
for the full build and the real rank-IC results.
|
|
282
|
+
|
|
283
|
+
**`rank_20d` now sizes positions (opt-in).** A follow-up pass wired the
|
|
284
|
+
one Phase-4 signal with a statistically significant full-series result —
|
|
285
|
+
`rank_20d`, sequence model mean IC `0.073`/t-stat `4.40` — into an actual
|
|
286
|
+
trading decision: `risk/position_sizing.py::rank_sizing_multiplier()`
|
|
287
|
+
adds a fourth, bounded, direction-preserving factor to the sizing chain,
|
|
288
|
+
scaling an already-approved trade UP toward `max_rank_multiplier` (default
|
|
289
|
+
`1.25`) when the model predicts this asset near the top of the universe's
|
|
290
|
+
20-day forward-return ranking, and DOWN toward `min_rank_multiplier`
|
|
291
|
+
(default `0.75`) near the bottom — never flipping direction, same
|
|
292
|
+
convention as the existing `topology_sizing_multiplier()`. **Off by
|
|
293
|
+
default** (`phase_v2.dynamic_risk.rank_sizing_enabled: false`): the
|
|
294
|
+
signal's non-overlapping-date subsample (28 independent 20-day windows)
|
|
295
|
+
was not yet independently significant on its own (t-stat `1.20`), so it
|
|
296
|
+
ships wired end-to-end but not promoted to on-by-default until validated
|
|
297
|
+
on more out-of-sample data. `direction_5d`/`direction_20d`/`rank_5d`
|
|
298
|
+
remain informational-only. See `risk/README.md`'s "Cross-sectional
|
|
299
|
+
rank_20d → position sizing" section.
|
|
300
|
+
|
|
253
301
|
**A causal-TCN sequence encoder (Phase 2) now exists alongside the
|
|
254
302
|
flat-MLP trunk**, replacing the "zero temporal structure" limitation the
|
|
255
303
|
original root-cause investigation flagged — `train.py::AetherNetSequenceMultiTask`,
|
|
@@ -269,10 +317,21 @@ writeup.
|
|
|
269
317
|
|
|
270
318
|
## Universe Size
|
|
271
319
|
|
|
272
|
-
The trading universe currently spans **
|
|
273
|
-
crypto pairs — defined in
|
|
274
|
-
shared across training,
|
|
275
|
-
(`phase1.universe.common_window`: `2014-12-01`
|
|
320
|
+
The trading universe currently spans **30 assets** — 15 stocks/broad-market
|
|
321
|
+
ETFs, 10 fixed-income (bond) ETFs, and 5 crypto pairs — defined in
|
|
322
|
+
`config.json`'s `phase1.universe.assets` and shared across training,
|
|
323
|
+
validation, and backtesting (`phase1.universe.common_window`: `2014-12-01`
|
|
324
|
+
to `2021-03-31`). The bond ETF sleeve (Phase 1 of the 5/10 -> 9/10 roadmap,
|
|
325
|
+
see [`development/Changelog.md`](development/Changelog.md)) was added
|
|
326
|
+
specifically as a new, genuinely different information channel — not more
|
|
327
|
+
of the same equity cross-section — and deliberately spans the duration
|
|
328
|
+
curve (short/intermediate/long/aggregate) and credit spectrum
|
|
329
|
+
(Treasury/investment-grade/high-yield/municipal/emerging-market) so the
|
|
330
|
+
yield-curve-slope and credit-spread macro proxies computed from it
|
|
331
|
+
(`features/macro_features.py`) are meaningful. Bond ETFs are registered
|
|
332
|
+
with `security_type: "equity"` (they trade through Lean's ordinary equity
|
|
333
|
+
subscription path, like every other ETF already in the universe, e.g.
|
|
334
|
+
SPY/QQQ/IWM/EEM — not a new Lean security type).
|
|
276
335
|
|
|
277
336
|
| Ticker | Type | Role |
|
|
278
337
|
|---|---|---|
|
|
@@ -291,6 +350,16 @@ shared across training, validation, and backtesting
|
|
|
291
350
|
| USO | Equity | Trading |
|
|
292
351
|
| WM | Equity | Trading |
|
|
293
352
|
| AAA | Equity | Observation-only (thin history) |
|
|
353
|
+
| SHY | Equity (Fixed Income ETF) | Trading — short-duration Treasury (1-3y) |
|
|
354
|
+
| IEF | Equity (Fixed Income ETF) | Trading — intermediate-duration Treasury (7-10y) |
|
|
355
|
+
| TLT | Equity (Fixed Income ETF) | Trading — long-duration Treasury (20y+) |
|
|
356
|
+
| AGG | Equity (Fixed Income ETF) | Trading — broad aggregate bond benchmark |
|
|
357
|
+
| LQD | Equity (Fixed Income ETF) | Trading — investment-grade corporate |
|
|
358
|
+
| HYG | Equity (Fixed Income ETF) | Trading — high-yield corporate |
|
|
359
|
+
| TIP | Equity (Fixed Income ETF) | Trading — inflation-protected (TIPS) |
|
|
360
|
+
| MBB | Equity (Fixed Income ETF) | Trading — mortgage-backed |
|
|
361
|
+
| EMB | Equity (Fixed Income ETF) | Trading — emerging-market sovereign debt |
|
|
362
|
+
| MUB | Equity (Fixed Income ETF) | Trading — municipal |
|
|
294
363
|
| BTCUSD | Crypto | Trading |
|
|
295
364
|
| ETHUSD | Crypto | Observation-only (thin history) |
|
|
296
365
|
| LTCUSD | Crypto | Trading |
|
|
@@ -328,6 +397,19 @@ flowchart TD
|
|
|
328
397
|
AAA["AAA"]
|
|
329
398
|
end
|
|
330
399
|
|
|
400
|
+
subgraph FixedIncome["Fixed Income ETFs (10)"]
|
|
401
|
+
SHY["SHY"]
|
|
402
|
+
IEF["IEF"]
|
|
403
|
+
TLT["TLT"]
|
|
404
|
+
AGG["AGG"]
|
|
405
|
+
LQD["LQD"]
|
|
406
|
+
HYG["HYG"]
|
|
407
|
+
TIP["TIP"]
|
|
408
|
+
MBB["MBB"]
|
|
409
|
+
EMB["EMB"]
|
|
410
|
+
MUB["MUB"]
|
|
411
|
+
end
|
|
412
|
+
|
|
331
413
|
subgraph Crypto["Crypto (5)"]
|
|
332
414
|
BTCUSD["BTCUSD"]
|
|
333
415
|
ETHUSD["ETHUSD"]
|
|
@@ -351,6 +433,16 @@ flowchart TD
|
|
|
351
433
|
USO --- DNN
|
|
352
434
|
WM --- DNN
|
|
353
435
|
AAA --- DNN
|
|
436
|
+
SHY --- DNN
|
|
437
|
+
IEF --- DNN
|
|
438
|
+
TLT --- DNN
|
|
439
|
+
AGG --- DNN
|
|
440
|
+
LQD --- DNN
|
|
441
|
+
HYG --- DNN
|
|
442
|
+
TIP --- DNN
|
|
443
|
+
MBB --- DNN
|
|
444
|
+
EMB --- DNN
|
|
445
|
+
MUB --- DNN
|
|
354
446
|
BTCUSD --- DNN
|
|
355
447
|
ETHUSD --- DNN
|
|
356
448
|
LTCUSD --- DNN
|
|
@@ -362,7 +454,7 @@ flowchart TD
|
|
|
362
454
|
classDef observation fill:#3A3A3A,stroke:#FF8C00,color:#FF8C00,stroke-width:1px,stroke-dasharray: 4 2;
|
|
363
455
|
|
|
364
456
|
class DNN hub;
|
|
365
|
-
class AAPL,SPY,QQQ,IWM,EEM,BAC,IBM,AIG,BNO,FB,GOOG,GOOGL,USO,WM,BTCUSD,LTCUSD trading;
|
|
457
|
+
class AAPL,SPY,QQQ,IWM,EEM,BAC,IBM,AIG,BNO,FB,GOOG,GOOGL,USO,WM,SHY,IEF,TLT,AGG,LQD,HYG,TIP,MBB,EMB,MUB,BTCUSD,LTCUSD trading;
|
|
366
458
|
class AAA,ETHUSD,XRPUSD,ADAUSD observation;
|
|
367
459
|
```
|
|
368
460
|
|
|
@@ -393,7 +485,7 @@ aether-quant/
|
|
|
393
485
|
├── ml/ # Model weights, datasets, versioned retraining candidates
|
|
394
486
|
├── storage/ # Reserved for future persistent artifact storage
|
|
395
487
|
├── requirements/ # All requirements*.txt variants
|
|
396
|
-
├── tests/ # Full pytest suite (
|
|
488
|
+
├── tests/ # Full pytest suite (828 tests)
|
|
397
489
|
├── backtests/ # Lean backtest run outputs (gitignored)
|
|
398
490
|
├── Aether-quant-Obsidian-Vault/ # Auto-generated code-graph / architecture vault
|
|
399
491
|
├── main.py # Lean algorithm: inference, signal engine, risk controls
|
|
@@ -435,7 +527,7 @@ and how it's wired in — this table is the index.
|
|
|
435
527
|
| `retraining/` | Controlled retraining — plan/train/validate/backtest/commit/promote/rollback | [README](retraining/README.md) |
|
|
436
528
|
| `risk/` | Dynamic position sizing, leverage caps, drawdown-aware sizing | [README](risk/README.md) |
|
|
437
529
|
| `storage/` | Reserved placeholder for future persistent artifact storage | [README](storage/README.md) |
|
|
438
|
-
| `tests/` | Pytest suite conventions (
|
|
530
|
+
| `tests/` | Pytest suite conventions (828 tests) | [README](tests/README.md) |
|
|
439
531
|
| `topology/` | 3D market topology — deterministic SMACOF embedding + learned overlay | [README](topology/README.md) |
|
|
440
532
|
| `visualization/` | Shared runtime-state JSON/CSV exports | [README](visualization/README.md) |
|
|
441
533
|
| `webui/` | React/Vite dashboard (Overview, Risk, Topology, Neural Network, Tracing) | [README](webui/README.md) |
|
|
@@ -543,7 +635,7 @@ genuinely halted trading exactly as designed.
|
|
|
543
635
|
|
|
544
636
|
## Test Suite
|
|
545
637
|
|
|
546
|
-
|
|
638
|
+
828 tests, one file per source module, run via:
|
|
547
639
|
|
|
548
640
|
```powershell
|
|
549
641
|
aq test
|
|
@@ -576,7 +668,7 @@ command already documented elsewhere in this README:
|
|
|
576
668
|
|
|
577
669
|
#### `aq train`
|
|
578
670
|
```text
|
|
579
|
-
aq train [--dataset-only|--init-only|--experts-only|--gating-only|--multitask-only|--sequence-only]
|
|
671
|
+
aq train [--dataset-only|--init-only|--experts-only|--gating-only|--multitask-only|--sequence-only|--walk-forward] [--step-days N] [--mode rolling|expanding]
|
|
580
672
|
```
|
|
581
673
|
Runs `train.py`: builds the dataset and trains the baseline + expert
|
|
582
674
|
models. `--gating-only` trains just the learned gating blend
|
|
@@ -586,7 +678,15 @@ mirroring what `--experts-only` already does for the expert models — see
|
|
|
586
678
|
direction+magnitude+volatility model (`train_multitask.py`) — see
|
|
587
679
|
`inference/README.md`/`risk/README.md`. `--sequence-only` does the same
|
|
588
680
|
for the Phase 2 causal-TCN sequence encoder (`train_sequence.py`) — see
|
|
589
|
-
`inference/README.md`.
|
|
681
|
+
`inference/README.md`. `--walk-forward` (Phase 4 of the 5/10 -> 9/10
|
|
682
|
+
roadmap) wraps `python train.py --walk-forward`, running the dataset-build
|
|
683
|
+
+ training pipeline once per rolling/expanding window instead of once on
|
|
684
|
+
the fixed `phase1.windows` — diagnostic only, never touches active `ml/`
|
|
685
|
+
(each window writes to `ml/versions/<run-id>/window_<i>/`, same as
|
|
686
|
+
`--candidate`); `--step-days`/`--mode` override
|
|
687
|
+
`phase_v2.retraining.walk_forward`'s `step_days`/`mode` defaults — see
|
|
688
|
+
`retraining/README.md`'s "Walk-forward retraining is a separate, scheduled
|
|
689
|
+
mechanism" section.
|
|
590
690
|
|
|
591
691
|
#### `aq test`
|
|
592
692
|
```text
|
|
@@ -62,6 +62,7 @@ execution/order_gate.py
|
|
|
62
62
|
execution/paper_readiness.py
|
|
63
63
|
execution/paper_readiness_io.py
|
|
64
64
|
execution/paper_readiness_report.py
|
|
65
|
+
execution/paper_readiness_scheduler.py
|
|
65
66
|
execution/runtime_config_io.py
|
|
66
67
|
experience/README.md
|
|
67
68
|
experience/__init__.py
|
|
@@ -72,6 +73,9 @@ experience/simulated_portfolio.py
|
|
|
72
73
|
experts/README.md
|
|
73
74
|
experts/__init__.py
|
|
74
75
|
experts/expert_datasets.py
|
|
76
|
+
features/__init__.py
|
|
77
|
+
features/macro_features.py
|
|
78
|
+
features/technical_indicators.py
|
|
75
79
|
inference/README.md
|
|
76
80
|
inference/__init__.py
|
|
77
81
|
inference/exported_model.py
|
|
@@ -88,9 +92,15 @@ ml/multitask_training_metrics.json
|
|
|
88
92
|
ml/sequence_feature_schema.json
|
|
89
93
|
ml/sequence_model.json
|
|
90
94
|
ml/sequence_training_metrics.json
|
|
95
|
+
ml/versions/gating-only-05c572c8-9566-4152-805c-fa57142a3f8c/gating_feature_schema.json
|
|
96
|
+
ml/versions/gating-only-05c572c8-9566-4152-805c-fa57142a3f8c/gating_model.json
|
|
97
|
+
ml/versions/gating-only-05c572c8-9566-4152-805c-fa57142a3f8c/gating_training_metrics.json
|
|
91
98
|
ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_feature_schema.json
|
|
92
99
|
ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_model.json
|
|
93
100
|
ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_training_metrics.json
|
|
101
|
+
ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c/multitask_feature_schema.json
|
|
102
|
+
ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c/multitask_model.json
|
|
103
|
+
ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c/multitask_training_metrics.json
|
|
94
104
|
ml/versions/stage123-1783709428/gating_feature_schema.json
|
|
95
105
|
ml/versions/stage123-1783709428/gating_model.json
|
|
96
106
|
ml/versions/stage123-1783709428/gating_training_metrics.json
|
|
@@ -128,8 +138,12 @@ notifications/telegram_worker.py
|
|
|
128
138
|
performance/README.md
|
|
129
139
|
performance/__init__.py
|
|
130
140
|
performance/postgres_triggers.py
|
|
141
|
+
performance/rank_ic_monitor.py
|
|
131
142
|
performance/trigger_worker.py
|
|
132
143
|
performance/triggers.py
|
|
144
|
+
portfolio/README.md
|
|
145
|
+
portfolio/__init__.py
|
|
146
|
+
portfolio/book_construction.py
|
|
133
147
|
regime/README.md
|
|
134
148
|
regime/__init__.py
|
|
135
149
|
regime/market_regime.py
|
|
@@ -172,6 +186,7 @@ tests/test_lean_backtest_ml_coverage.py
|
|
|
172
186
|
tests/test_learned_topology.py
|
|
173
187
|
tests/test_live_credentials.py
|
|
174
188
|
tests/test_live_credentials_io.py
|
|
189
|
+
tests/test_macro_features.py
|
|
175
190
|
tests/test_manual_override.py
|
|
176
191
|
tests/test_market_analyzer.py
|
|
177
192
|
tests/test_market_liquidity.py
|
|
@@ -183,10 +198,13 @@ tests/test_order_gate.py
|
|
|
183
198
|
tests/test_paper_readiness.py
|
|
184
199
|
tests/test_paper_readiness_io.py
|
|
185
200
|
tests/test_paper_readiness_report.py
|
|
201
|
+
tests/test_paper_readiness_scheduler.py
|
|
202
|
+
tests/test_portfolio_book_construction.py
|
|
186
203
|
tests/test_position_sizing.py
|
|
187
204
|
tests/test_postgres_telegram.py
|
|
188
205
|
tests/test_postgres_triggers.py
|
|
189
206
|
tests/test_postgres_worker.py
|
|
207
|
+
tests/test_rank_ic_monitor.py
|
|
190
208
|
tests/test_retraining_artifacts.py
|
|
191
209
|
tests/test_retraining_orchestrator.py
|
|
192
210
|
tests/test_retraining_planning.py
|
|
@@ -196,16 +214,22 @@ tests/test_risk_controls.py
|
|
|
196
214
|
tests/test_runtime_config_io.py
|
|
197
215
|
tests/test_simulated_portfolio.py
|
|
198
216
|
tests/test_status_export.py
|
|
217
|
+
tests/test_technical_indicators.py
|
|
199
218
|
tests/test_telegram_alerts.py
|
|
200
219
|
tests/test_telegram_client.py
|
|
201
220
|
tests/test_telegram_worker.py
|
|
202
221
|
tests/test_train_cross_sectional_features.py
|
|
203
222
|
tests/test_train_gating.py
|
|
223
|
+
tests/test_train_indicators.py
|
|
224
|
+
tests/test_train_macro_features.py
|
|
204
225
|
tests/test_train_multitask.py
|
|
205
226
|
tests/test_train_multitask_architecture.py
|
|
206
227
|
tests/test_train_pipeline.py
|
|
228
|
+
tests/test_train_ranking_validation.py
|
|
229
|
+
tests/test_train_sequence.py
|
|
207
230
|
tests/test_train_sequence_architecture.py
|
|
208
231
|
tests/test_train_topology.py
|
|
232
|
+
tests/test_train_walk_forward_windows.py
|
|
209
233
|
tests/test_trigger_worker.py
|
|
210
234
|
tests/test_triggers.py
|
|
211
235
|
tests/test_v2_pipeline_manifest.py
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
"risk/__init__.py",
|
|
33
33
|
"risk/manual_override.py",
|
|
34
34
|
"risk/position_sizing.py",
|
|
35
|
+
"features/__init__.py",
|
|
36
|
+
"features/macro_features.py",
|
|
37
|
+
"features/technical_indicators.py",
|
|
35
38
|
"notifications/telegram_client.py",
|
|
36
39
|
"notifications/README.md",
|
|
37
40
|
"notifications/__init__.py",
|
|
@@ -84,6 +87,7 @@
|
|
|
84
87
|
"execution/live_credentials_io.py",
|
|
85
88
|
"execution/paper_readiness_io.py",
|
|
86
89
|
"execution/live_credentials.py",
|
|
90
|
+
"execution/paper_readiness_scheduler.py",
|
|
87
91
|
"monitoring/neural_network_state.py",
|
|
88
92
|
"monitoring/README.md",
|
|
89
93
|
"monitoring/__init__.py",
|
|
@@ -92,7 +96,11 @@
|
|
|
92
96
|
"performance/__init__.py",
|
|
93
97
|
"performance/triggers.py",
|
|
94
98
|
"performance/postgres_triggers.py",
|
|
99
|
+
"performance/rank_ic_monitor.py",
|
|
95
100
|
"performance/trigger_worker.py",
|
|
101
|
+
"portfolio/README.md",
|
|
102
|
+
"portfolio/__init__.py",
|
|
103
|
+
"portfolio/book_construction.py",
|
|
96
104
|
"liquidity/README.md",
|
|
97
105
|
"liquidity/__init__.py",
|
|
98
106
|
"liquidity/market_liquidity.py",
|
|
@@ -165,10 +173,12 @@
|
|
|
165
173
|
"development/Changelog.md",
|
|
166
174
|
"development/v2_architecture.md",
|
|
167
175
|
"development/infrastructure.md",
|
|
176
|
+
"tests/test_train_sequence.py",
|
|
168
177
|
"tests/test_order_gate.py",
|
|
169
178
|
"tests/test_config_cache.py",
|
|
170
179
|
"tests/test_train_sequence_architecture.py",
|
|
171
180
|
"tests/test_telegram_alerts.py",
|
|
181
|
+
"tests/test_train_walk_forward_windows.py",
|
|
172
182
|
"tests/test_trigger_worker.py",
|
|
173
183
|
"tests/test_v2_pipeline_manifest.py",
|
|
174
184
|
"tests/test_paper_readiness_report.py",
|
|
@@ -183,9 +193,11 @@
|
|
|
183
193
|
"tests/test_expert_datasets.py",
|
|
184
194
|
"tests/test_expert_models.py",
|
|
185
195
|
"tests/test_live_credentials.py",
|
|
196
|
+
"tests/test_paper_readiness_scheduler.py",
|
|
186
197
|
"tests/test_retraining_orchestrator.py",
|
|
187
198
|
"tests/test_telegram_client.py",
|
|
188
199
|
"tests/test_yfinance_backfill.py",
|
|
200
|
+
"tests/test_technical_indicators.py",
|
|
189
201
|
"tests/test_neural_network_state.py",
|
|
190
202
|
"tests/test_market_regime.py",
|
|
191
203
|
"tests/test_vault_client.py",
|
|
@@ -193,10 +205,13 @@
|
|
|
193
205
|
"tests/test_train_multitask.py",
|
|
194
206
|
"tests/test_observation_metrics.py",
|
|
195
207
|
"tests/test_paper_readiness_io.py",
|
|
208
|
+
"tests/test_train_ranking_validation.py",
|
|
209
|
+
"tests/test_portfolio_book_construction.py",
|
|
196
210
|
"tests/test_exported_model.py",
|
|
197
211
|
"tests/test_train_topology.py",
|
|
198
212
|
"tests/test_telegram_worker.py",
|
|
199
213
|
"tests/test_paper_readiness.py",
|
|
214
|
+
"tests/test_train_indicators.py",
|
|
200
215
|
"tests/test_train_multitask_architecture.py",
|
|
201
216
|
"tests/test_triggers.py",
|
|
202
217
|
"tests/test_simulated_portfolio.py",
|
|
@@ -214,8 +229,11 @@
|
|
|
214
229
|
"tests/test_manual_override.py",
|
|
215
230
|
"tests/test_postgres_telegram.py",
|
|
216
231
|
"tests/test_retraining_worker.py",
|
|
232
|
+
"tests/test_macro_features.py",
|
|
233
|
+
"tests/test_rank_ic_monitor.py",
|
|
217
234
|
"tests/test_retraining_postgres_registry.py",
|
|
218
235
|
"tests/test_learned_topology.py",
|
|
236
|
+
"tests/test_train_macro_features.py",
|
|
219
237
|
"tests/test_gating_network.py",
|
|
220
238
|
"tests/test_train_pipeline.py",
|
|
221
239
|
"tests/test_experience_queue.py",
|
|
@@ -249,6 +267,9 @@
|
|
|
249
267
|
"ml/versions/stage5-1783715333/sequence_feature_schema.json",
|
|
250
268
|
"ml/versions/stage5-1783715333/sequence_model.json",
|
|
251
269
|
"ml/versions/stage5-1783715333/sequence_training_metrics.json",
|
|
270
|
+
"ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c/multitask_feature_schema.json",
|
|
271
|
+
"ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c/multitask_model.json",
|
|
272
|
+
"ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c/multitask_training_metrics.json",
|
|
252
273
|
"ml/versions/v1/sequence_feature_schema.json",
|
|
253
274
|
"ml/versions/v1/multitask_feature_schema.json",
|
|
254
275
|
"ml/versions/v1/multitask_model.json",
|
|
@@ -261,6 +282,9 @@
|
|
|
261
282
|
"ml/versions/stage4-1783711025/multitask_training_metrics.json",
|
|
262
283
|
"ml/versions/stage4-1783711025/gating_feature_schema.json",
|
|
263
284
|
"ml/versions/stage4-1783711025/gating_training_metrics.json",
|
|
285
|
+
"ml/versions/gating-only-05c572c8-9566-4152-805c-fa57142a3f8c/gating_model.json",
|
|
286
|
+
"ml/versions/gating-only-05c572c8-9566-4152-805c-fa57142a3f8c/gating_feature_schema.json",
|
|
287
|
+
"ml/versions/gating-only-05c572c8-9566-4152-805c-fa57142a3f8c/gating_training_metrics.json",
|
|
264
288
|
"ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_model.json",
|
|
265
289
|
"ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_feature_schema.json",
|
|
266
290
|
"ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_training_metrics.json",
|
|
@@ -94,3 +94,23 @@ risk engine, and before action categorization / Lean order placement.
|
|
|
94
94
|
enabled. Always `None` when no multitask model is loaded (or the model
|
|
95
95
|
call failed), matching every other optional-model fallback contract in
|
|
96
96
|
this codebase.
|
|
97
|
+
- **Follow-up:** these two fields now transitively reflect the Phase 2
|
|
98
|
+
sequence encoder too, whenever `phase_v2.gating_network.sequence_weight`
|
|
99
|
+
is enabled (`moe/README.md`'s "Phase 2 sequence encoder now optionally
|
|
100
|
+
blends into the gating decision" section) — `main.py` reads them from
|
|
101
|
+
`gating_payload["final_magnitude"/"final_volatility"]`, which the
|
|
102
|
+
sequence blend adjusts before this module ever sees them. No change
|
|
103
|
+
to this module was needed or made: it was evaluated as a candidate
|
|
104
|
+
direct-integration point for the sequence model and deliberately
|
|
105
|
+
passed over in favor of gating, for the same "stay fully
|
|
106
|
+
deterministic" reason the topology-elevated/isolated rules and the
|
|
107
|
+
composite signal score above already establish.
|
|
108
|
+
- **Follow-up (Phase 3 of the 5/10 -> 9/10 roadmap):** `signal_name` can
|
|
109
|
+
now also be `"short"` (`portfolio/book_construction.py`'s Stage-2
|
|
110
|
+
long/short book) — every safety-tier check in this module that used
|
|
111
|
+
to test `signal_name in {"buy", "sell"}` now tests
|
|
112
|
+
`{"buy", "sell", "short"}`, so a book-selected short passes through
|
|
113
|
+
the exact same deterministic trade-lock/risk-off/topology/liquidity
|
|
114
|
+
categorization as any other directional signal, never bypassing it.
|
|
115
|
+
See `portfolio/README.md` for why book construction lives in its own
|
|
116
|
+
package rather than here.
|
|
@@ -93,6 +93,13 @@ def build_market_analysis_decision(
|
|
|
93
93
|
predicted_return_magnitude: float | None = None,
|
|
94
94
|
predicted_volatility: float | None = None,
|
|
95
95
|
) -> MarketAnalysisDecision:
|
|
96
|
+
# signal_name == "short" (Phase 3 of the 5/10 -> 9/10 roadmap,
|
|
97
|
+
# portfolio/book_construction.py) is treated identically to "buy"/"sell"
|
|
98
|
+
# by every safety-tier check below (`in {"buy", "sell", "short"}`) - a
|
|
99
|
+
# book-selected short position passes through the exact same
|
|
100
|
+
# deterministic trade-lock/risk-off/topology/liquidity categorization
|
|
101
|
+
# as any other directional signal, never bypassing it. See
|
|
102
|
+
# analyzer/README.md for why this categorization stays deterministic.
|
|
96
103
|
reasons: list[str] = []
|
|
97
104
|
decision_source = str(gating.get("decision_source", "unknown"))
|
|
98
105
|
regime_confidence = float(regime.get("confidence", 0.0) or 0.0)
|
|
@@ -140,7 +147,7 @@ def build_market_analysis_decision(
|
|
|
140
147
|
|
|
141
148
|
# Priority 2: reduce_risk - asset-level risk regime override even
|
|
142
149
|
# without a portfolio-wide lock (e.g. risk_off + would-be trade).
|
|
143
|
-
if risk_regime == "risk_off" and signal_name in {"buy", "sell"}:
|
|
150
|
+
if risk_regime == "risk_off" and signal_name in {"buy", "sell", "short"}:
|
|
144
151
|
reasons.append("risk_off_regime_overrides_directional_signal")
|
|
145
152
|
return MarketAnalysisDecision(
|
|
146
153
|
action="reduce_risk",
|
|
@@ -164,7 +171,7 @@ def build_market_analysis_decision(
|
|
|
164
171
|
# feeding the retrain-trigger/retraining pipeline, but deliberately left
|
|
165
172
|
# this rule reading only the deterministic topology_risk - see
|
|
166
173
|
# analyzer/README.md and development/v2_architecture.md's V2-17.5 section.
|
|
167
|
-
if topology_risk == "elevated" and signal_name in {"buy", "sell"}:
|
|
174
|
+
if topology_risk == "elevated" and signal_name in {"buy", "sell", "short"}:
|
|
168
175
|
reasons.append("topology_elevated_volatility_pressure_overrides_directional_signal")
|
|
169
176
|
return MarketAnalysisDecision(
|
|
170
177
|
action="reduce_risk",
|
|
@@ -208,7 +215,7 @@ def build_market_analysis_decision(
|
|
|
208
215
|
# Priority 5: simulate - liquidity blocked (zero volume or DDV below
|
|
209
216
|
# the floor). An unexecutable order must not reach the order book.
|
|
210
217
|
# See V2-18 for future data-driven calibration of these thresholds.
|
|
211
|
-
if liquidity_action == "block" and signal_name in {"buy", "sell"}:
|
|
218
|
+
if liquidity_action == "block" and signal_name in {"buy", "sell", "short"}:
|
|
212
219
|
reasons.append("liquidity_blocked_insufficient_volume_simulate_instead")
|
|
213
220
|
return MarketAnalysisDecision(
|
|
214
221
|
action="simulate",
|
|
@@ -228,7 +235,7 @@ def build_market_analysis_decision(
|
|
|
228
235
|
|
|
229
236
|
# Priority 6: simulate - thin market; participation rate would be
|
|
230
237
|
# uncomfortably large relative to daily volume.
|
|
231
|
-
if liquidity_action == "simulate_instead" and signal_name in {"buy", "sell"}:
|
|
238
|
+
if liquidity_action == "simulate_instead" and signal_name in {"buy", "sell", "short"}:
|
|
232
239
|
reasons.append("liquidity_thin_market_simulate_instead")
|
|
233
240
|
return MarketAnalysisDecision(
|
|
234
241
|
action="simulate",
|
|
@@ -254,7 +261,7 @@ def build_market_analysis_decision(
|
|
|
254
261
|
# use_composite_signal_score=True).
|
|
255
262
|
if (
|
|
256
263
|
trading_eligible
|
|
257
|
-
and signal_name in {"buy", "sell"}
|
|
264
|
+
and signal_name in {"buy", "sell", "short"}
|
|
258
265
|
and trade_metric >= min_confidence_to_trade
|
|
259
266
|
and topology_risk != "isolated"
|
|
260
267
|
and liquidity_action not in {"block", "simulate_instead"}
|
|
@@ -277,7 +284,7 @@ def build_market_analysis_decision(
|
|
|
277
284
|
)
|
|
278
285
|
|
|
279
286
|
# Priority 8: simulate vs observe.
|
|
280
|
-
if signal_name in {"buy", "sell"} and regime_confidence >= low_regime_confidence_threshold:
|
|
287
|
+
if signal_name in {"buy", "sell", "short"} and regime_confidence >= low_regime_confidence_threshold:
|
|
281
288
|
if topology_risk == "isolated":
|
|
282
289
|
reasons.append("topology_isolated_asset_lacks_peer_confirmation_simulate_instead")
|
|
283
290
|
elif trading_eligible:
|
|
@@ -192,6 +192,12 @@ def cmd_train(args: argparse.Namespace) -> int:
|
|
|
192
192
|
cmd.append("--init-only")
|
|
193
193
|
elif args.experts_only:
|
|
194
194
|
cmd.append("--experts-only")
|
|
195
|
+
elif args.walk_forward:
|
|
196
|
+
cmd.append("--walk-forward")
|
|
197
|
+
if args.step_days is not None:
|
|
198
|
+
cmd += ["--step-days", str(args.step_days)]
|
|
199
|
+
if args.mode is not None:
|
|
200
|
+
cmd += ["--mode", args.mode]
|
|
195
201
|
return _run(cmd)
|
|
196
202
|
|
|
197
203
|
|
|
@@ -612,6 +618,25 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
612
618
|
action="store_true",
|
|
613
619
|
help="Train the Phase 2 causal-TCN sequence encoder only (wraps python train_sequence.py)",
|
|
614
620
|
)
|
|
621
|
+
train_group.add_argument(
|
|
622
|
+
"--walk-forward",
|
|
623
|
+
action="store_true",
|
|
624
|
+
help=(
|
|
625
|
+
"Phase 4 of the 5/10 -> 9/10 roadmap: run the dataset-build + training pipeline once per "
|
|
626
|
+
"walk-forward window (wraps python train.py --walk-forward). Never touches active ml/ - "
|
|
627
|
+
"diagnostic only, writes to ml/versions/<run-id>/window_<i>/."
|
|
628
|
+
),
|
|
629
|
+
)
|
|
630
|
+
train_parser.add_argument(
|
|
631
|
+
"--step-days", type=int, default=None, help="Walk-forward step size in days (only with --walk-forward)."
|
|
632
|
+
)
|
|
633
|
+
train_parser.add_argument(
|
|
634
|
+
"--mode",
|
|
635
|
+
type=str,
|
|
636
|
+
choices=("rolling", "expanding"),
|
|
637
|
+
default=None,
|
|
638
|
+
help="Walk-forward mode: rolling or expanding (only with --walk-forward).",
|
|
639
|
+
)
|
|
615
640
|
train_parser.set_defaults(func=cmd_train)
|
|
616
641
|
|
|
617
642
|
test_parser = subparsers.add_parser("test", help="Run the test suite (wraps pytest tests/)")
|