aether-quant 0.6.0__tar.gz → 0.7.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.6.0 → aether_quant-0.7.0}/Dockerfile.retraining_worker +3 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/PKG-INFO +1 -1
- {aether_quant-0.6.0 → aether_quant-0.7.0}/README.md +194 -56
- {aether_quant-0.6.0 → aether_quant-0.7.0}/aether_quant.egg-info/PKG-INFO +1 -1
- {aether_quant-0.6.0 → aether_quant-0.7.0}/aether_quant.egg-info/SOURCES.txt +33 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/aether_quant.egg-info/scm_file_list.json +33 -0
- aether_quant-0.7.0/aether_quant.egg-info/scm_version.json +8 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/analyzer/README.md +15 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/analyzer/market_analyzer.py +20 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/aq_cli.py +70 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/config.json +78 -4
- {aether_quant-0.6.0 → aether_quant-0.7.0}/development/Changelog.md +534 -1
- {aether_quant-0.6.0 → aether_quant-0.7.0}/development/Problems.md +72 -0
- aether_quant-0.7.0/development/backtest_equity_chart.png +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/development/infrastructure.md +24 -1
- {aether_quant-0.6.0 → aether_quant-0.7.0}/development/v2_architecture.md +144 -23
- {aether_quant-0.6.0 → aether_quant-0.7.0}/experience/redis_queue.py +9 -0
- aether_quant-0.7.0/inference/README.md +125 -0
- aether_quant-0.7.0/inference/__init__.py +11 -0
- aether_quant-0.7.0/inference/exported_model.py +306 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/lean.json +1 -1
- {aether_quant-0.6.0 → aether_quant-0.7.0}/liquidity/README.md +34 -0
- aether_quant-0.7.0/liquidity/__init__.py +8 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/main.py +299 -19
- aether_quant-0.7.0/ml/gating_model.json +570 -0
- aether_quant-0.7.0/ml/gating_training_metrics.json +190 -0
- aether_quant-0.7.0/ml/multitask_feature_schema.json +52 -0
- aether_quant-0.7.0/ml/multitask_model.json +5888 -0
- aether_quant-0.7.0/ml/multitask_training_metrics.json +248 -0
- aether_quant-0.7.0/ml/sequence_feature_schema.json +53 -0
- aether_quant-0.7.0/ml/sequence_model.json +13258 -0
- aether_quant-0.7.0/ml/sequence_training_metrics.json +209 -0
- aether_quant-0.7.0/ml/versions/stage123-1783709428/gating_feature_schema.json +30 -0
- aether_quant-0.7.0/ml/versions/stage123-1783709428/gating_model.json +570 -0
- aether_quant-0.7.0/ml/versions/stage123-1783709428/gating_training_metrics.json +190 -0
- aether_quant-0.7.0/ml/versions/stage123-1783709428/multitask_feature_schema.json +52 -0
- aether_quant-0.7.0/ml/versions/stage123-1783709428/multitask_model.json +5888 -0
- aether_quant-0.7.0/ml/versions/stage123-1783709428/multitask_training_metrics.json +248 -0
- aether_quant-0.7.0/ml/versions/stage4-1783711025/gating_feature_schema.json +30 -0
- aether_quant-0.7.0/ml/versions/stage4-1783711025/gating_model.json +570 -0
- aether_quant-0.7.0/ml/versions/stage4-1783711025/gating_training_metrics.json +190 -0
- aether_quant-0.7.0/ml/versions/stage4-1783711025/multitask_feature_schema.json +52 -0
- aether_quant-0.7.0/ml/versions/stage4-1783711025/multitask_model.json +5888 -0
- aether_quant-0.7.0/ml/versions/stage4-1783711025/multitask_training_metrics.json +248 -0
- aether_quant-0.7.0/ml/versions/stage5-1783715333/sequence_feature_schema.json +53 -0
- aether_quant-0.7.0/ml/versions/stage5-1783715333/sequence_model.json +13258 -0
- aether_quant-0.7.0/ml/versions/stage5-1783715333/sequence_training_metrics.json +209 -0
- aether_quant-0.7.0/ml/versions/v1/multitask_feature_schema.json +52 -0
- aether_quant-0.7.0/ml/versions/v1/multitask_model.json +5888 -0
- aether_quant-0.7.0/ml/versions/v1/multitask_training_metrics.json +248 -0
- aether_quant-0.7.0/ml/versions/v1/sequence_feature_schema.json +53 -0
- aether_quant-0.7.0/ml/versions/v1/sequence_model.json +13258 -0
- aether_quant-0.7.0/ml/versions/v1/sequence_training_metrics.json +209 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/moe/README.md +43 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/moe/gating.py +64 -1
- {aether_quant-0.6.0 → aether_quant-0.7.0}/monitoring/neural_network_state.py +149 -13
- aether_quant-0.7.0/regime/README.md +57 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/retraining/README.md +15 -4
- {aether_quant-0.6.0 → aether_quant-0.7.0}/retraining/__init__.py +8 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/retraining/artifacts.py +40 -5
- {aether_quant-0.6.0 → aether_quant-0.7.0}/retraining/orchestrator.py +108 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/retraining/worker.py +14 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/risk/README.md +32 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/risk/position_sizing.py +25 -1
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_aq_cli.py +95 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_experience_queue.py +19 -2
- aether_quant-0.7.0/tests/test_exported_model.py +464 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_gating_network.py +127 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_lean_backtest_ml_coverage.py +46 -0
- aether_quant-0.7.0/tests/test_neural_network_state.py +311 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_retraining_artifacts.py +136 -1
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_retraining_orchestrator.py +149 -0
- aether_quant-0.7.0/tests/test_train_cross_sectional_features.py +243 -0
- aether_quant-0.7.0/tests/test_train_multitask.py +113 -0
- aether_quant-0.7.0/tests/test_train_multitask_architecture.py +189 -0
- aether_quant-0.7.0/tests/test_train_sequence_architecture.py +196 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/topology/README.md +34 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/train.py +840 -17
- aether_quant-0.7.0/train_multitask.py +403 -0
- aether_quant-0.7.0/train_sequence.py +403 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/neuralnet/NeuralNetworkScene3D.tsx +60 -7
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/types/state.ts +9 -1
- aether_quant-0.6.0/aether_quant.egg-info/scm_version.json +0 -8
- aether_quant-0.6.0/development/backtest_equity_chart.png +0 -0
- aether_quant-0.6.0/inference/README.md +0 -35
- aether_quant-0.6.0/inference/__init__.py +0 -3
- aether_quant-0.6.0/inference/exported_model.py +0 -68
- aether_quant-0.6.0/liquidity/__init__.py +0 -3
- aether_quant-0.6.0/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_model.json +0 -570
- aether_quant-0.6.0/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_training_metrics.json +0 -190
- aether_quant-0.6.0/regime/README.md +0 -18
- aether_quant-0.6.0/tests/test_exported_model.py +0 -106
- aether_quant-0.6.0/tests/test_neural_network_state.py +0 -148
- {aether_quant-0.6.0 → aether_quant-0.7.0}/.dockerignore +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/.env.compose.example +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/.env.live.example +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/.gitattributes +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/.github/workflows/ci.yml +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/.github/workflows/release.yml +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/.gitignore +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/Dockerfile +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/Dockerfile.workers +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/aether_quant.egg-info/dependency_links.txt +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/aether_quant.egg-info/entry_points.txt +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/aether_quant.egg-info/top_level.txt +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/analyzer/__init__.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/backtests/.gitkeep +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/data/alternative/estimize/consensus/aapl/.keep +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/data/alternative/estimize/estimate/.keep +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/data/alternative/estimize/release/.keep +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/data/alternative/sec/aapl/.keep +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/data/alternative/trading-economics/.keep +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/data/alternative/trading-economics/calendar/.keep +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/data/alternative/trading-economics/earnings/.keep +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/data/alternative/trading-economics/indicator/.keep +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/data_pipeline/README.md +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/data_pipeline/__init__.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/data_pipeline/fetch.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/data_pipeline/v2_manifest.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/data_pipeline/yfinance_backfill.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/development/README.md +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/development/logo.png +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/docker-compose.yml +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/execution/README.md +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/execution/__init__.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/execution/config_cache.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/execution/live_credentials.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/execution/live_credentials_io.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/execution/order_gate.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/execution/paper_readiness.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/execution/paper_readiness_io.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/execution/paper_readiness_report.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/execution/runtime_config_io.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/experience/README.md +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/experience/__init__.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/experience/observation_metrics.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/experience/postgres_worker.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/experience/simulated_portfolio.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/experts/README.md +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/experts/__init__.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/experts/expert_datasets.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/generate_backtest_report.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/liquidity/market_liquidity.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/ml/README.md +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/ml/gating_feature_schema.json +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_feature_schema.json +0 -0
- {aether_quant-0.6.0/ml → aether_quant-0.7.0/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459}/gating_model.json +0 -0
- {aether_quant-0.6.0/ml → aether_quant-0.7.0/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459}/gating_training_metrics.json +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/moe/__init__.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/monitoring/README.md +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/monitoring/__init__.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/monitoring/api_server.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/notifications/README.md +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/notifications/__init__.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/notifications/postgres_telegram.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/notifications/telegram_alerts.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/notifications/telegram_client.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/notifications/telegram_worker.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/performance/README.md +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/performance/__init__.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/performance/postgres_triggers.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/performance/trigger_worker.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/performance/triggers.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/pyproject.toml +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/regime/__init__.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/regime/market_regime.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/requirements/README.md +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/requirements/requirements-dev.txt +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/requirements/requirements-retraining-worker.txt +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/requirements/requirements-runtime.txt +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/requirements/requirements-workers.txt +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/requirements/requirements.txt +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/retraining/backtest_gate.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/retraining/lean_backtest.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/retraining/planning.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/retraining/postgres_registry.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/retraining/status_export.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/retraining/validation_gate.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/retraining/vault_client.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/retraining/vault_commands.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/risk/__init__.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/risk/manual_override.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/risk_controls.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/setup.cfg +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/README.md +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_backtest_gate.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_config_cache.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_expert_datasets.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_expert_models.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_fetch.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_generate_backtest_report.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_lean_backtest.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_learned_topology.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_live_credentials.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_live_credentials_io.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_manual_override.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_market_analyzer.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_market_liquidity.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_market_regime.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_market_topology.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_observation_metrics.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_order_gate.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_paper_readiness.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_paper_readiness_io.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_paper_readiness_report.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_position_sizing.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_postgres_telegram.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_postgres_triggers.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_postgres_worker.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_retraining_planning.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_retraining_postgres_registry.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_retraining_worker.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_risk_controls.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_runtime_config_io.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_simulated_portfolio.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_status_export.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_telegram_alerts.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_telegram_client.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_telegram_worker.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_train_gating.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_train_pipeline.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_train_topology.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_trigger_worker.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_triggers.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_v2_pipeline_manifest.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_validation_gate.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_vault_client.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_vault_commands.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/tests/test_yfinance_backfill.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/topology/__init__.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/topology/learned_topology.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/topology/market_topology.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/train_gating.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/train_topology.py +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/visualization/README.md +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/.gitignore +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/.oxlintrc.json +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/README.md +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/index.html +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/overview_v2_12.png +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/package-lock.json +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/package.json +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/public/favicon.svg +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/public/icons.svg +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/risk_v2_12.png +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/App.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/api/client.ts +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/api/hooks.ts +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/heatmap/AssetHeatmap.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/layout/AppShell.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/layout/Panel.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/monitoring/CountTable.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/monitoring/MonitoringFeeds.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/monitoring/ObservationPanel.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/monitoring/PaperReadinessPanel.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/monitoring/PerformanceTriggersPanel.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/monitoring/RawStateViewer.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/monitoring/RetrainingStatusPanel.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/neuralnet/NeuralNetworkStatsPanel.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/risk/AssetSizingTable.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/risk/LiquidityTable.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/risk/RiskBar.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/risk/RiskCore.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/risk/StrategyRiskCards.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/scene3d/Scene3D.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/scorecards/Scorecards.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/signals/Badge.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/signals/PositionsList.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/signals/SignalBoard.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/topology/ClusterList.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/topology/TopologyLearningPanel.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/topology/TopologyScene3D.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/tracing/AssetPerformancePanel.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/tracing/BacktestEquityPanel.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/tracing/DivergingBarChart.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/tracing/LineChart.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/tracing/MetricsSnapshotPanel.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/components/tracing/ObservationEquityPanel.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/index.css +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/lib/downsample.ts +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/lib/format.ts +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/main.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/pages/NeuralNetworkPage.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/pages/Overview.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/pages/RiskPage.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/pages/TopologyPage.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/pages/TracingPage.tsx +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/src/types/tracing.ts +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/tsconfig.app.json +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/tsconfig.json +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/tsconfig.node.json +0 -0
- {aether_quant-0.6.0 → aether_quant-0.7.0}/webui/vite.config.ts +0 -0
|
@@ -10,8 +10,11 @@ COPY experts/ ./experts/
|
|
|
10
10
|
COPY topology/ ./topology/
|
|
11
11
|
COPY moe/ ./moe/
|
|
12
12
|
COPY inference/ ./inference/
|
|
13
|
+
COPY risk/ ./risk/
|
|
13
14
|
COPY retraining/ ./retraining/
|
|
14
15
|
COPY train.py .
|
|
15
16
|
COPY train_topology.py .
|
|
16
17
|
COPY train_gating.py .
|
|
18
|
+
COPY train_multitask.py .
|
|
19
|
+
COPY train_sequence.py .
|
|
17
20
|
CMD ["python", "-m", "retraining.worker"]
|
|
@@ -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-642%2F642%20passing-brightgreen?style=flat-square&labelColor=1A1A1A" alt="642 of 642 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>
|
|
@@ -158,11 +158,14 @@ that a controlled retraining loop reads from to evolve the model over time.
|
|
|
158
158
|
|
|
159
159
|
```mermaid
|
|
160
160
|
flowchart LR
|
|
161
|
-
A["Lean data folder<br/>stocks, ETFs, crypto"] --> B["Feature pipeline<br/>train.py"]
|
|
161
|
+
A["Lean data folder<br/>stocks, ETFs, crypto"] --> B["Feature pipeline<br/>train.py<br/>48-dim: price/volume +<br/>regime + liquidity + topology"]
|
|
162
162
|
B --> C["Regime detection<br/>trend, volatility, drawdown, correlation"]
|
|
163
163
|
B --> D["3D topology modeling<br/>market structure and clusters"]
|
|
164
|
-
|
|
164
|
+
B -.-> U["Sequence encoder (Phase 2)<br/>causal-TCN, 30-bar window<br/>informational only"]
|
|
165
|
+
B --> V["Multitask heads<br/>baseline + 4 experts<br/>direction + magnitude + volatility"]
|
|
166
|
+
C --> E["Gating network<br/>the manager<br/>blends probability + magnitude/volatility"]
|
|
165
167
|
D --> E
|
|
168
|
+
V --> E
|
|
166
169
|
E --> F["Expert modules"]
|
|
167
170
|
F --> G["Bullish expert"]
|
|
168
171
|
F --> H["Bearish expert"]
|
|
@@ -180,6 +183,7 @@ flowchart LR
|
|
|
180
183
|
M --> O["Observation / simulation record"]
|
|
181
184
|
N --> P["Redis event stream<br/>temporary low-latency buffer"]
|
|
182
185
|
O --> P
|
|
186
|
+
U -.-> P
|
|
183
187
|
P --> Q["Experience worker<br/>async batch persistence"]
|
|
184
188
|
Q --> R["PostgreSQL experience database<br/>single source of truth"]
|
|
185
189
|
R --> S["Performance triggers<br/>100 observations, drawdown, Sharpe, regime shift"]
|
|
@@ -187,6 +191,11 @@ flowchart LR
|
|
|
187
191
|
T --> E
|
|
188
192
|
```
|
|
189
193
|
|
|
194
|
+
Dashed edges mark the Phase 2 sequence encoder's **informational-only**
|
|
195
|
+
path — it's computed every bar and reaches the experience log, but never
|
|
196
|
+
the gating network, market analyzer, or position sizing (see
|
|
197
|
+
`inference/README.md`'s Phase 2 section).
|
|
198
|
+
|
|
190
199
|
#### Tech Stack
|
|
191
200
|
|
|
192
201
|
```mermaid
|
|
@@ -203,6 +212,7 @@ flowchart TB
|
|
|
203
212
|
D --> D2["scikit-learn"]
|
|
204
213
|
D --> D3["NumPy / Pandas"]
|
|
205
214
|
D --> D4["MoE experts and gating network"]
|
|
215
|
+
D --> D5["Multitask heads (direction/magnitude/<br/>volatility) + causal-TCN sequence encoder"]
|
|
206
216
|
E["Monitoring and UI"] --> E1["React/Vite webui — Tracing dashboard (port 3002 dev / 8001 Docker)"]
|
|
207
217
|
E --> E2["FastAPI JSON API (port 8000)"]
|
|
208
218
|
E --> E3["Telegram alerts (V2-19)<br/>notifications/telegram_worker.py"]
|
|
@@ -215,6 +225,48 @@ and more), the module map, and an honest analysis of what would need to
|
|
|
215
225
|
change for this to become a genuinely low-latency/HFT system — see
|
|
216
226
|
**[`development/v2_architecture.md`](development/v2_architecture.md)**.
|
|
217
227
|
|
|
228
|
+
**The baseline model can now predict more than direction.** An optional
|
|
229
|
+
multi-task model (`train.py::AetherNetMultiTask`, trained by
|
|
230
|
+
`train_multitask.py`) predicts next-day direction, return magnitude and
|
|
231
|
+
volatility jointly from one shared trunk — the direction-only baseline and
|
|
232
|
+
experts are unchanged and still ship independently. All 4 experts also
|
|
233
|
+
have their own optional multitask heads (`train.py::_train_expert_multitask()`),
|
|
234
|
+
so `moe/gating.py` blends per-expert magnitude/volatility with a
|
|
235
|
+
baseline-scale anchor the same weighted-average way it already blends
|
|
236
|
+
direction. `main.py` threads the resulting `predicted_return_magnitude`/
|
|
237
|
+
`predicted_volatility` through the market analyzer (informational only,
|
|
238
|
+
never changes routing) and, opt-in via
|
|
239
|
+
`phase_v2.dynamic_risk.use_predicted_volatility`, into position sizing —
|
|
240
|
+
replacing the backward-looking `rolling_volatility_20d` average with an
|
|
241
|
+
actual forward-looking forecast for that one calculation.
|
|
242
|
+
|
|
243
|
+
**Regime, liquidity and topology are now genuine model input features,
|
|
244
|
+
not just downstream consumers of its output.** Model input dimensionality
|
|
245
|
+
grew from 30 to 48: regime one-hot/confidence/trend/risk score, an
|
|
246
|
+
asset-intrinsic liquidity spread/dollar-volume estimate, and cross-asset
|
|
247
|
+
topology correlation/risk state are all computed offline
|
|
248
|
+
(`train.py::add_regime_features()`/`add_liquidity_features()`/
|
|
249
|
+
`build_topology_features_by_date()`) and at runtime
|
|
250
|
+
(`main.py::_build_model_input()`, reordered so regime is computed
|
|
251
|
+
*before* the model runs) with verified train/runtime parity.
|
|
252
|
+
|
|
253
|
+
**A causal-TCN sequence encoder (Phase 2) now exists alongside the
|
|
254
|
+
flat-MLP trunk**, replacing the "zero temporal structure" limitation the
|
|
255
|
+
original root-cause investigation flagged — `train.py::AetherNetSequenceMultiTask`,
|
|
256
|
+
trained by `train_sequence.py`, over a rolling 30-bar window of
|
|
257
|
+
already-computed model inputs. Informational only this pass
|
|
258
|
+
(`main.py::_run_sequence_model()` — not yet wired into any trading
|
|
259
|
+
decision); see `inference/README.md`'s Phase 2 section for the new
|
|
260
|
+
`_conv1d_causal`/`_multihead_attention`/`_softmax`/`_layernorm_axis`
|
|
261
|
+
interpreter primitives (each independently verified against real PyTorch
|
|
262
|
+
modules).
|
|
263
|
+
|
|
264
|
+
See `inference/README.md`, `moe/README.md`, `risk/README.md`,
|
|
265
|
+
`regime/README.md`, `liquidity/README.md` and `topology/README.md` for
|
|
266
|
+
the full contracts, and `development/Changelog.md`'s "Multi-task
|
|
267
|
+
prediction" and "Phase 1 remainder + Phase 2" entries for the complete
|
|
268
|
+
writeup.
|
|
269
|
+
|
|
218
270
|
## Universe Size
|
|
219
271
|
|
|
220
272
|
The trading universe currently spans **20 assets** — 15 equities and 5
|
|
@@ -347,6 +399,9 @@ aether-quant/
|
|
|
347
399
|
├── main.py # Lean algorithm: inference, signal engine, risk controls
|
|
348
400
|
├── train.py # Training pipeline: dataset build, model training, validation
|
|
349
401
|
├── train_topology.py # Offline trainer for the learned topology overlay
|
|
402
|
+
├── train_gating.py # Offline trainer for the learned gating blend
|
|
403
|
+
├── train_multitask.py # Offline trainer for the joint direction+magnitude+volatility model
|
|
404
|
+
├── train_sequence.py # Offline trainer for the Phase 2 causal-TCN sequence encoder
|
|
350
405
|
├── generate_backtest_report.py # Regenerates this README's Backtest Results section
|
|
351
406
|
├── aq_cli.py # `aq` convenience CLI
|
|
352
407
|
├── config.json # Runtime configuration (phase1 / phase_v2 blocks)
|
|
@@ -404,13 +459,13 @@ and how it's wired in — this table is the index.
|
|
|
404
459
|
| Metric | Value |
|
|
405
460
|
|---|---|
|
|
406
461
|
| Backtest window | 2018-04-01 to 2021-04-02 |
|
|
407
|
-
| Sharpe Ratio | -0.
|
|
408
|
-
| Net Profit | -
|
|
409
|
-
| Compounding Annual Return | -
|
|
410
|
-
| Drawdown | 12.
|
|
411
|
-
| Total Orders |
|
|
412
|
-
| Win Rate |
|
|
413
|
-
| Last updated | 2026-07-
|
|
462
|
+
| Sharpe Ratio | -0.758 |
|
|
463
|
+
| Net Profit | -4.847% |
|
|
464
|
+
| Compounding Annual Return | -1.640% |
|
|
465
|
+
| Drawdown | 12.300% |
|
|
466
|
+
| Total Orders | 36 |
|
|
467
|
+
| Win Rate | 25% |
|
|
468
|
+
| Last updated | 2026-07-08 13:10 UTC (auto-generated by `aq backtest`) |
|
|
414
469
|
<!-- AQ:BACKTEST_END -->
|
|
415
470
|
|
|
416
471
|
<details>
|
|
@@ -419,33 +474,33 @@ and how it's wired in — this table is the index.
|
|
|
419
474
|
<!-- AQ:BACKTEST_FULL_STATS_START -->
|
|
420
475
|
| Metric | Value |
|
|
421
476
|
|---|---|
|
|
422
|
-
| Total Orders |
|
|
423
|
-
| Average Win | 0.
|
|
424
|
-
| Average Loss | -
|
|
425
|
-
| Compounding Annual Return | -
|
|
426
|
-
| Drawdown | 12.
|
|
427
|
-
| Expectancy | -0.
|
|
477
|
+
| Total Orders | 36 |
|
|
478
|
+
| Average Win | 0.38% |
|
|
479
|
+
| Average Loss | -0.67% |
|
|
480
|
+
| Compounding Annual Return | -1.640% |
|
|
481
|
+
| Drawdown | 12.300% |
|
|
482
|
+
| Expectancy | -0.609 |
|
|
428
483
|
| Start Equity | 100000.00 |
|
|
429
|
-
| End Equity |
|
|
430
|
-
| Net Profit | -
|
|
431
|
-
| Sharpe Ratio | -0.
|
|
432
|
-
| Sortino Ratio | -0.
|
|
433
|
-
| Probabilistic Sharpe Ratio | 0.
|
|
434
|
-
| Loss Rate |
|
|
435
|
-
| Win Rate |
|
|
436
|
-
| Profit-Loss Ratio | 0.
|
|
437
|
-
| Alpha | -0.
|
|
438
|
-
| Beta | 0.
|
|
439
|
-
| Annual Standard Deviation | 0.
|
|
440
|
-
| Annual Variance | 0.
|
|
441
|
-
| Information Ratio | -0.
|
|
442
|
-
| Tracking Error | 0.
|
|
443
|
-
| Treynor Ratio | -0.
|
|
444
|
-
| Total Fees | $
|
|
445
|
-
| Estimated Strategy Capacity | $
|
|
446
|
-
| Lowest Capacity Asset |
|
|
447
|
-
| Portfolio Turnover | 0.
|
|
448
|
-
| Drawdown Recovery |
|
|
484
|
+
| End Equity | 95153.40 |
|
|
485
|
+
| Net Profit | -4.847% |
|
|
486
|
+
| Sharpe Ratio | -0.758 |
|
|
487
|
+
| Sortino Ratio | -0.363 |
|
|
488
|
+
| Probabilistic Sharpe Ratio | 0.006% |
|
|
489
|
+
| Loss Rate | 75% |
|
|
490
|
+
| Win Rate | 25% |
|
|
491
|
+
| Profit-Loss Ratio | 0.56 |
|
|
492
|
+
| Alpha | -0.034 |
|
|
493
|
+
| Beta | 0.047 |
|
|
494
|
+
| Annual Standard Deviation | 0.038 |
|
|
495
|
+
| Annual Variance | 0.001 |
|
|
496
|
+
| Information Ratio | -0.786 |
|
|
497
|
+
| Tracking Error | 0.182 |
|
|
498
|
+
| Treynor Ratio | -0.603 |
|
|
499
|
+
| Total Fees | $25.59 |
|
|
500
|
+
| Estimated Strategy Capacity | $2300000.00 |
|
|
501
|
+
| Lowest Capacity Asset | BNO UN3IMQ2JU1YD |
|
|
502
|
+
| Portfolio Turnover | 0.14% |
|
|
503
|
+
| Drawdown Recovery | 32 |
|
|
449
504
|
<!-- AQ:BACKTEST_FULL_STATS_END -->
|
|
450
505
|
|
|
451
506
|
</details>
|
|
@@ -515,42 +570,125 @@ instead, without waiting on a PyPI release:
|
|
|
515
570
|
pip install -e .
|
|
516
571
|
```
|
|
517
572
|
|
|
518
|
-
Either way, `aq --help` gives the full command list
|
|
573
|
+
Either way, `aq --help` gives the full command list. Every command except
|
|
574
|
+
`aq trade-lock` and `aq fetch` is a thin `subprocess` wrapper around a
|
|
575
|
+
command already documented elsewhere in this README:
|
|
519
576
|
|
|
577
|
+
#### `aq train`
|
|
578
|
+
```text
|
|
579
|
+
aq train [--dataset-only|--init-only|--experts-only|--gating-only|--multitask-only|--sequence-only]
|
|
580
|
+
```
|
|
581
|
+
Runs `train.py`: builds the dataset and trains the baseline + expert
|
|
582
|
+
models. `--gating-only` trains just the learned gating blend
|
|
583
|
+
(`train_gating.py`) and installs it straight into active `ml/`,
|
|
584
|
+
mirroring what `--experts-only` already does for the expert models — see
|
|
585
|
+
`moe/README.md`. `--multitask-only` does the same for the joint
|
|
586
|
+
direction+magnitude+volatility model (`train_multitask.py`) — see
|
|
587
|
+
`inference/README.md`/`risk/README.md`. `--sequence-only` does the same
|
|
588
|
+
for the Phase 2 causal-TCN sequence encoder (`train_sequence.py`) — see
|
|
589
|
+
`inference/README.md`.
|
|
590
|
+
|
|
591
|
+
#### `aq test`
|
|
520
592
|
```text
|
|
521
|
-
aq train [--dataset-only|--init-only|--experts-only|--gating-only]
|
|
522
593
|
aq test
|
|
594
|
+
```
|
|
595
|
+
Runs the pytest suite and refreshes this README's test badge.
|
|
596
|
+
|
|
597
|
+
#### `aq backtest`
|
|
598
|
+
```text
|
|
523
599
|
aq backtest
|
|
600
|
+
```
|
|
601
|
+
Runs `lean backtest .` and refreshes this README's [Backtest Results](#backtest-results) section.
|
|
602
|
+
|
|
603
|
+
#### `aq report`
|
|
604
|
+
```text
|
|
524
605
|
aq report <backtest-folder> <result-id>
|
|
606
|
+
```
|
|
607
|
+
Generates Lean's own HTML backtest report (trade blotter, standard Lean
|
|
608
|
+
charts) at `backtests/<backtest-folder>/report.html`.
|
|
609
|
+
|
|
610
|
+
#### `aq api`
|
|
611
|
+
```text
|
|
525
612
|
aq api
|
|
613
|
+
```
|
|
614
|
+
Starts the FastAPI monitoring server on `:8001`.
|
|
615
|
+
|
|
616
|
+
#### `aq webui`
|
|
617
|
+
```text
|
|
526
618
|
aq webui
|
|
619
|
+
```
|
|
620
|
+
Starts the webui dev server (`npm run dev`).
|
|
621
|
+
|
|
622
|
+
#### `aq docker`
|
|
623
|
+
```text
|
|
527
624
|
aq docker up [--lean|--all]
|
|
528
625
|
aq docker build
|
|
626
|
+
```
|
|
627
|
+
`up` starts local infrastructure (default: Redis + PostgreSQL only).
|
|
628
|
+
`build` rebuilds the `aether-quant` app image.
|
|
629
|
+
|
|
630
|
+
#### `aq config`
|
|
631
|
+
```text
|
|
529
632
|
aq config [get <dotted.key>|set <dotted.key> <value>|keys [<dotted.prefix>]]
|
|
633
|
+
```
|
|
634
|
+
Reads or edits `config.json` directly, no manual file editing needed.
|
|
635
|
+
Bare `aq config` pretty-prints the whole file; `aq config keys
|
|
636
|
+
[<dotted.prefix>]` lists every leaf key path (handy for finding the right
|
|
637
|
+
key in a deeply nested file); `aq config get <dotted.key>` prints one
|
|
638
|
+
value (scalar, or a whole nested section as JSON); `aq config set
|
|
639
|
+
<dotted.key> <value>` writes it — the value is parsed as JSON first (so
|
|
640
|
+
`true`/`123`/`0.5`/`["a","b"]` become their real types automatically),
|
|
641
|
+
falling back to a plain string otherwise. Every `set` backs up the
|
|
642
|
+
previous file to `config.json.bak` first and prints old → new so a
|
|
643
|
+
mistake is immediately visible; changing a value's type (e.g. bool →
|
|
644
|
+
string) prints a warning but still writes it, since this command
|
|
645
|
+
intentionally gives full access to every key, not just a safe subset.
|
|
646
|
+
|
|
647
|
+
#### `aq lean`
|
|
648
|
+
```text
|
|
530
649
|
aq lean [get <dotted.key>|set <dotted.key> <value>|keys [<dotted.prefix>]]
|
|
650
|
+
```
|
|
651
|
+
The exact same `get`/`set`/`keys` tool as `aq config`, just pointed at
|
|
652
|
+
`lean.json` (the QuantConnect Lean CLI's own config file — broker
|
|
653
|
+
credentials, environments, data providers) instead. `aq lean set
|
|
654
|
+
ib-trading-mode live`, `aq lean keys environments.live-paper`, etc.
|
|
655
|
+
|
|
656
|
+
#### `aq retrain`
|
|
657
|
+
```text
|
|
531
658
|
aq retrain <plan|train|validate|backtest|commit|promote|rollback|status> [...]
|
|
659
|
+
```
|
|
660
|
+
Dispatches to `python -m retraining.orchestrator <stage> ...` for a
|
|
661
|
+
single manual pipeline stage.
|
|
662
|
+
|
|
663
|
+
#### `aq trade-lock`
|
|
664
|
+
```text
|
|
532
665
|
aq trade-lock --on|--off|--auto|--status
|
|
666
|
+
```
|
|
667
|
+
Manually overrides `main.py`'s sticky total-drawdown trade lock (see
|
|
668
|
+
`development/v2_architecture.md`'s Manual Trade-Lock Override Contract).
|
|
669
|
+
`--off` deliberately clears an otherwise-permanent lock; `--auto` returns
|
|
670
|
+
to fully automatic behavior.
|
|
671
|
+
|
|
672
|
+
#### `aq fetch`
|
|
673
|
+
```text
|
|
533
674
|
aq fetch <crypto|stock> --ticker <TICKER> --start <YYYY-MM-DD> --end <YYYY-MM-DD> [--apply]
|
|
675
|
+
```
|
|
676
|
+
Fetches historical OHLCV from Yahoo Finance for a ticker that isn't in
|
|
677
|
+
`config.json` yet, formats it into Lean's zip/CSV convention, and writes
|
|
678
|
+
it to the right spot under `data/` (`data/crypto/coinbase/daily/<ticker>_trade.zip`
|
|
679
|
+
or `data/equity/usa/daily/<ticker>.zip`). On `--apply`, it also appends a
|
|
680
|
+
new asset block to `config.json`'s `phase1.universe.assets[]` — no manual
|
|
681
|
+
editing needed. Dry run by default (no `--apply`): reports what would
|
|
682
|
+
happen, writes nothing. Never runs `train.py` itself — once applied, run
|
|
683
|
+
`python train.py --dataset-only` (then `python train.py` when ready)
|
|
684
|
+
yourself to actually train on the new ticker. `crypto`/`stock` today; a
|
|
685
|
+
`derivative` asset class is planned for V3.
|
|
686
|
+
|
|
687
|
+
#### `aq status`
|
|
688
|
+
```text
|
|
534
689
|
aq status
|
|
535
690
|
```
|
|
536
|
-
|
|
537
|
-
Every command except `aq trade-lock` and `aq fetch` is a thin `subprocess`
|
|
538
|
-
wrapper around a command already documented elsewhere in this README:
|
|
539
|
-
|
|
540
|
-
- **`aq train`** — runs `train.py`: builds the dataset and trains the baseline + expert models. `--gating-only` trains just the learned gating blend (`train_gating.py`) and installs it straight into active `ml/`, mirroring what `--experts-only` already does for the expert models — see `moe/README.md`.
|
|
541
|
-
- **`aq test`** — runs the pytest suite and refreshes this README's test badge.
|
|
542
|
-
- **`aq backtest`** — runs `lean backtest .` and refreshes this README's [Backtest Results](#backtest-results) section.
|
|
543
|
-
- **`aq report <backtest-folder> <result-id>`** — generates Lean's own HTML backtest report (trade blotter, standard Lean charts) at `backtests/<backtest-folder>/report.html`.
|
|
544
|
-
- **`aq api`** — starts the FastAPI monitoring server on `:8001`.
|
|
545
|
-
- **`aq webui`** — starts the webui dev server (`npm run dev`).
|
|
546
|
-
- **`aq docker up [--lean|--all]`** — starts local infrastructure (default: Redis + PostgreSQL only).
|
|
547
|
-
- **`aq docker build`** — rebuilds the `aether-quant` app image.
|
|
548
|
-
- **`aq config`** — reads or edits `config.json` directly, no manual file editing needed. Bare `aq config` pretty-prints the whole file; `aq config keys [<dotted.prefix>]` lists every leaf key path (handy for finding the right key in a deeply nested file); `aq config get <dotted.key>` prints one value (scalar, or a whole nested section as JSON); `aq config set <dotted.key> <value>` writes it — the value is parsed as JSON first (so `true`/`123`/`0.5`/`["a","b"]` become their real types automatically), falling back to a plain string otherwise. Every `set` backs up the previous file to `config.json.bak` first and prints old → new so a mistake is immediately visible; changing a value's type (e.g. bool → string) prints a warning but still writes it, since this command intentionally gives full access to every key, not just a safe subset.
|
|
549
|
-
- **`aq lean`** — the exact same `get`/`set`/`keys` tool as `aq config`, just pointed at `lean.json` (the QuantConnect Lean CLI's own config file — broker credentials, environments, data providers) instead. `aq lean set ib-trading-mode live`, `aq lean keys environments.live-paper`, etc.
|
|
550
|
-
- **`aq retrain <stage>`** — dispatches to `python -m retraining.orchestrator <stage> ...` for a single manual pipeline stage.
|
|
551
|
-
- **`aq trade-lock --on|--off|--auto|--status`** — manually overrides `main.py`'s sticky total-drawdown trade lock (see `development/v2_architecture.md`'s Manual Trade-Lock Override Contract). `--off` deliberately clears an otherwise-permanent lock; `--auto` returns to fully automatic behavior.
|
|
552
|
-
- **`aq fetch <crypto|stock> --ticker <TICKER> --start <YYYY-MM-DD> --end <YYYY-MM-DD> [--apply]`** — fetches historical OHLCV from Yahoo Finance for a ticker that isn't in `config.json` yet, formats it into Lean's zip/CSV convention, and writes it to the right spot under `data/` (`data/crypto/coinbase/daily/<ticker>_trade.zip` or `data/equity/usa/daily/<ticker>.zip`). On `--apply`, it also appends a new asset block to `config.json`'s `phase1.universe.assets[]` — no manual editing needed. Dry run by default (no `--apply`): reports what would happen, writes nothing. Never runs `train.py` itself — once applied, run `python train.py --dataset-only` (then `python train.py` when ready) yourself to actually train on the new ticker. `crypto`/`stock` today; a `derivative` asset class is planned for V3.
|
|
553
|
-
- **`aq status`** — shows `git status`.
|
|
691
|
+
Shows `git status`.
|
|
554
692
|
|
|
555
693
|
## Release Process
|
|
556
694
|
|
|
@@ -17,6 +17,8 @@ pyproject.toml
|
|
|
17
17
|
risk_controls.py
|
|
18
18
|
train.py
|
|
19
19
|
train_gating.py
|
|
20
|
+
train_multitask.py
|
|
21
|
+
train_sequence.py
|
|
20
22
|
train_topology.py
|
|
21
23
|
.github/workflows/ci.yml
|
|
22
24
|
.github/workflows/release.yml
|
|
@@ -80,9 +82,36 @@ ml/README.md
|
|
|
80
82
|
ml/gating_feature_schema.json
|
|
81
83
|
ml/gating_model.json
|
|
82
84
|
ml/gating_training_metrics.json
|
|
85
|
+
ml/multitask_feature_schema.json
|
|
86
|
+
ml/multitask_model.json
|
|
87
|
+
ml/multitask_training_metrics.json
|
|
88
|
+
ml/sequence_feature_schema.json
|
|
89
|
+
ml/sequence_model.json
|
|
90
|
+
ml/sequence_training_metrics.json
|
|
83
91
|
ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_feature_schema.json
|
|
84
92
|
ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_model.json
|
|
85
93
|
ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_training_metrics.json
|
|
94
|
+
ml/versions/stage123-1783709428/gating_feature_schema.json
|
|
95
|
+
ml/versions/stage123-1783709428/gating_model.json
|
|
96
|
+
ml/versions/stage123-1783709428/gating_training_metrics.json
|
|
97
|
+
ml/versions/stage123-1783709428/multitask_feature_schema.json
|
|
98
|
+
ml/versions/stage123-1783709428/multitask_model.json
|
|
99
|
+
ml/versions/stage123-1783709428/multitask_training_metrics.json
|
|
100
|
+
ml/versions/stage4-1783711025/gating_feature_schema.json
|
|
101
|
+
ml/versions/stage4-1783711025/gating_model.json
|
|
102
|
+
ml/versions/stage4-1783711025/gating_training_metrics.json
|
|
103
|
+
ml/versions/stage4-1783711025/multitask_feature_schema.json
|
|
104
|
+
ml/versions/stage4-1783711025/multitask_model.json
|
|
105
|
+
ml/versions/stage4-1783711025/multitask_training_metrics.json
|
|
106
|
+
ml/versions/stage5-1783715333/sequence_feature_schema.json
|
|
107
|
+
ml/versions/stage5-1783715333/sequence_model.json
|
|
108
|
+
ml/versions/stage5-1783715333/sequence_training_metrics.json
|
|
109
|
+
ml/versions/v1/multitask_feature_schema.json
|
|
110
|
+
ml/versions/v1/multitask_model.json
|
|
111
|
+
ml/versions/v1/multitask_training_metrics.json
|
|
112
|
+
ml/versions/v1/sequence_feature_schema.json
|
|
113
|
+
ml/versions/v1/sequence_model.json
|
|
114
|
+
ml/versions/v1/sequence_training_metrics.json
|
|
86
115
|
moe/README.md
|
|
87
116
|
moe/__init__.py
|
|
88
117
|
moe/gating.py
|
|
@@ -170,8 +199,12 @@ tests/test_status_export.py
|
|
|
170
199
|
tests/test_telegram_alerts.py
|
|
171
200
|
tests/test_telegram_client.py
|
|
172
201
|
tests/test_telegram_worker.py
|
|
202
|
+
tests/test_train_cross_sectional_features.py
|
|
173
203
|
tests/test_train_gating.py
|
|
204
|
+
tests/test_train_multitask.py
|
|
205
|
+
tests/test_train_multitask_architecture.py
|
|
174
206
|
tests/test_train_pipeline.py
|
|
207
|
+
tests/test_train_sequence_architecture.py
|
|
175
208
|
tests/test_train_topology.py
|
|
176
209
|
tests/test_trigger_worker.py
|
|
177
210
|
tests/test_triggers.py
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": [
|
|
3
3
|
"README.md",
|
|
4
|
+
"train_multitask.py",
|
|
4
5
|
"train_gating.py",
|
|
5
6
|
"Dockerfile.workers",
|
|
6
7
|
"aq_cli.py",
|
|
7
8
|
"Dockerfile",
|
|
8
9
|
"pyproject.toml",
|
|
10
|
+
"train_sequence.py",
|
|
9
11
|
".env.compose.example",
|
|
10
12
|
"Dockerfile.retraining_worker",
|
|
11
13
|
"train_topology.py",
|
|
@@ -165,6 +167,7 @@
|
|
|
165
167
|
"development/infrastructure.md",
|
|
166
168
|
"tests/test_order_gate.py",
|
|
167
169
|
"tests/test_config_cache.py",
|
|
170
|
+
"tests/test_train_sequence_architecture.py",
|
|
168
171
|
"tests/test_telegram_alerts.py",
|
|
169
172
|
"tests/test_trigger_worker.py",
|
|
170
173
|
"tests/test_v2_pipeline_manifest.py",
|
|
@@ -187,12 +190,14 @@
|
|
|
187
190
|
"tests/test_market_regime.py",
|
|
188
191
|
"tests/test_vault_client.py",
|
|
189
192
|
"tests/test_validation_gate.py",
|
|
193
|
+
"tests/test_train_multitask.py",
|
|
190
194
|
"tests/test_observation_metrics.py",
|
|
191
195
|
"tests/test_paper_readiness_io.py",
|
|
192
196
|
"tests/test_exported_model.py",
|
|
193
197
|
"tests/test_train_topology.py",
|
|
194
198
|
"tests/test_telegram_worker.py",
|
|
195
199
|
"tests/test_paper_readiness.py",
|
|
200
|
+
"tests/test_train_multitask_architecture.py",
|
|
196
201
|
"tests/test_triggers.py",
|
|
197
202
|
"tests/test_simulated_portfolio.py",
|
|
198
203
|
"tests/test_position_sizing.py",
|
|
@@ -201,6 +206,7 @@
|
|
|
201
206
|
"tests/test_live_credentials_io.py",
|
|
202
207
|
"tests/test_market_analyzer.py",
|
|
203
208
|
"tests/test_generate_backtest_report.py",
|
|
209
|
+
"tests/test_train_cross_sectional_features.py",
|
|
204
210
|
"tests/test_lean_backtest.py",
|
|
205
211
|
"tests/test_retraining_planning.py",
|
|
206
212
|
"tests/test_market_topology.py",
|
|
@@ -230,13 +236,40 @@
|
|
|
230
236
|
"requirements/requirements-dev.txt",
|
|
231
237
|
"requirements/requirements-workers.txt",
|
|
232
238
|
"requirements/requirements-retraining-worker.txt",
|
|
239
|
+
"ml/sequence_feature_schema.json",
|
|
233
240
|
"ml/README.md",
|
|
234
241
|
"ml/gating_model.json",
|
|
242
|
+
"ml/multitask_feature_schema.json",
|
|
243
|
+
"ml/multitask_model.json",
|
|
244
|
+
"ml/multitask_training_metrics.json",
|
|
235
245
|
"ml/gating_feature_schema.json",
|
|
236
246
|
"ml/gating_training_metrics.json",
|
|
247
|
+
"ml/sequence_model.json",
|
|
248
|
+
"ml/sequence_training_metrics.json",
|
|
249
|
+
"ml/versions/stage5-1783715333/sequence_feature_schema.json",
|
|
250
|
+
"ml/versions/stage5-1783715333/sequence_model.json",
|
|
251
|
+
"ml/versions/stage5-1783715333/sequence_training_metrics.json",
|
|
252
|
+
"ml/versions/v1/sequence_feature_schema.json",
|
|
253
|
+
"ml/versions/v1/multitask_feature_schema.json",
|
|
254
|
+
"ml/versions/v1/multitask_model.json",
|
|
255
|
+
"ml/versions/v1/multitask_training_metrics.json",
|
|
256
|
+
"ml/versions/v1/sequence_model.json",
|
|
257
|
+
"ml/versions/v1/sequence_training_metrics.json",
|
|
258
|
+
"ml/versions/stage4-1783711025/gating_model.json",
|
|
259
|
+
"ml/versions/stage4-1783711025/multitask_feature_schema.json",
|
|
260
|
+
"ml/versions/stage4-1783711025/multitask_model.json",
|
|
261
|
+
"ml/versions/stage4-1783711025/multitask_training_metrics.json",
|
|
262
|
+
"ml/versions/stage4-1783711025/gating_feature_schema.json",
|
|
263
|
+
"ml/versions/stage4-1783711025/gating_training_metrics.json",
|
|
237
264
|
"ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_model.json",
|
|
238
265
|
"ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_feature_schema.json",
|
|
239
266
|
"ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_training_metrics.json",
|
|
267
|
+
"ml/versions/stage123-1783709428/gating_model.json",
|
|
268
|
+
"ml/versions/stage123-1783709428/multitask_feature_schema.json",
|
|
269
|
+
"ml/versions/stage123-1783709428/multitask_model.json",
|
|
270
|
+
"ml/versions/stage123-1783709428/multitask_training_metrics.json",
|
|
271
|
+
"ml/versions/stage123-1783709428/gating_feature_schema.json",
|
|
272
|
+
"ml/versions/stage123-1783709428/gating_training_metrics.json",
|
|
240
273
|
".github/workflows/release.yml",
|
|
241
274
|
".github/workflows/ci.yml"
|
|
242
275
|
]
|
|
@@ -79,3 +79,18 @@ risk engine, and before action categorization / Lean order placement.
|
|
|
79
79
|
reasoning as the topology-elevated/isolated rules above. Default `false`
|
|
80
80
|
means output is byte-identical to pre-this-change behavior everywhere
|
|
81
81
|
the flag isn't explicitly turned on.
|
|
82
|
+
- **Multi-task prediction fields (additive, never change routing).**
|
|
83
|
+
`MarketAnalysisDecision` gains `predicted_return_magnitude`/
|
|
84
|
+
`predicted_volatility` (both `float | None`, default `None`), threaded
|
|
85
|
+
straight through from `main.py`'s optional multi-task model call
|
|
86
|
+
(`train_multitask.py`/`AetherNetMultiTask`, see `inference/README.md`)
|
|
87
|
+
into every one of this module's 8 return statements via two new
|
|
88
|
+
`build_market_analysis_decision(..., predicted_return_magnitude=None,
|
|
89
|
+
predicted_volatility=None)` parameters. Purely informational here — this
|
|
90
|
+
module's `trade`/`simulate`/`observe`/`reduce_risk` categorization does
|
|
91
|
+
not read either field; `predicted_volatility` only ever changes anything
|
|
92
|
+
downstream in `risk/position_sizing.py` (see `risk/README.md`), and only
|
|
93
|
+
when `phase_v2.dynamic_risk.use_predicted_volatility` is explicitly
|
|
94
|
+
enabled. Always `None` when no multitask model is loaded (or the model
|
|
95
|
+
call failed), matching every other optional-model fallback contract in
|
|
96
|
+
this codebase.
|
|
@@ -23,6 +23,8 @@ class MarketAnalysisDecision:
|
|
|
23
23
|
reasons: list[str]
|
|
24
24
|
signal_quality_score: float = 0.0
|
|
25
25
|
signal_quality_breakdown: dict = field(default_factory=dict)
|
|
26
|
+
predicted_return_magnitude: float | None = None
|
|
27
|
+
predicted_volatility: float | None = None
|
|
26
28
|
|
|
27
29
|
def to_dict(self) -> dict:
|
|
28
30
|
return asdict(self)
|
|
@@ -88,6 +90,8 @@ def build_market_analysis_decision(
|
|
|
88
90
|
retrain_min_regime_confidence: float = 0.20,
|
|
89
91
|
low_regime_confidence_threshold: float = 0.35,
|
|
90
92
|
use_composite_signal_score: bool = False,
|
|
93
|
+
predicted_return_magnitude: float | None = None,
|
|
94
|
+
predicted_volatility: float | None = None,
|
|
91
95
|
) -> MarketAnalysisDecision:
|
|
92
96
|
reasons: list[str] = []
|
|
93
97
|
decision_source = str(gating.get("decision_source", "unknown"))
|
|
@@ -130,6 +134,8 @@ def build_market_analysis_decision(
|
|
|
130
134
|
reasons=reasons,
|
|
131
135
|
signal_quality_score=signal_quality_score,
|
|
132
136
|
signal_quality_breakdown=signal_quality_breakdown,
|
|
137
|
+
predicted_return_magnitude=predicted_return_magnitude,
|
|
138
|
+
predicted_volatility=predicted_volatility,
|
|
133
139
|
)
|
|
134
140
|
|
|
135
141
|
# Priority 2: reduce_risk - asset-level risk regime override even
|
|
@@ -148,6 +154,8 @@ def build_market_analysis_decision(
|
|
|
148
154
|
reasons=reasons,
|
|
149
155
|
signal_quality_score=signal_quality_score,
|
|
150
156
|
signal_quality_breakdown=signal_quality_breakdown,
|
|
157
|
+
predicted_return_magnitude=predicted_return_magnitude,
|
|
158
|
+
predicted_volatility=predicted_volatility,
|
|
151
159
|
)
|
|
152
160
|
|
|
153
161
|
# Priority 3: reduce_risk - elevated cross-sectional volatility pressure
|
|
@@ -170,6 +178,8 @@ def build_market_analysis_decision(
|
|
|
170
178
|
reasons=reasons,
|
|
171
179
|
signal_quality_score=signal_quality_score,
|
|
172
180
|
signal_quality_breakdown=signal_quality_breakdown,
|
|
181
|
+
predicted_return_magnitude=predicted_return_magnitude,
|
|
182
|
+
predicted_volatility=predicted_volatility,
|
|
173
183
|
)
|
|
174
184
|
|
|
175
185
|
# Priority 4: retrain_candidate - zero experts contributing AND the
|
|
@@ -191,6 +201,8 @@ def build_market_analysis_decision(
|
|
|
191
201
|
reasons=reasons,
|
|
192
202
|
signal_quality_score=signal_quality_score,
|
|
193
203
|
signal_quality_breakdown=signal_quality_breakdown,
|
|
204
|
+
predicted_return_magnitude=predicted_return_magnitude,
|
|
205
|
+
predicted_volatility=predicted_volatility,
|
|
194
206
|
)
|
|
195
207
|
|
|
196
208
|
# Priority 5: simulate - liquidity blocked (zero volume or DDV below
|
|
@@ -210,6 +222,8 @@ def build_market_analysis_decision(
|
|
|
210
222
|
reasons=reasons,
|
|
211
223
|
signal_quality_score=signal_quality_score,
|
|
212
224
|
signal_quality_breakdown=signal_quality_breakdown,
|
|
225
|
+
predicted_return_magnitude=predicted_return_magnitude,
|
|
226
|
+
predicted_volatility=predicted_volatility,
|
|
213
227
|
)
|
|
214
228
|
|
|
215
229
|
# Priority 6: simulate - thin market; participation rate would be
|
|
@@ -228,6 +242,8 @@ def build_market_analysis_decision(
|
|
|
228
242
|
reasons=reasons,
|
|
229
243
|
signal_quality_score=signal_quality_score,
|
|
230
244
|
signal_quality_breakdown=signal_quality_breakdown,
|
|
245
|
+
predicted_return_magnitude=predicted_return_magnitude,
|
|
246
|
+
predicted_volatility=predicted_volatility,
|
|
231
247
|
)
|
|
232
248
|
|
|
233
249
|
# Priority 7: trade - only for trading-eligible assets with an actionable
|
|
@@ -256,6 +272,8 @@ def build_market_analysis_decision(
|
|
|
256
272
|
reasons=reasons,
|
|
257
273
|
signal_quality_score=signal_quality_score,
|
|
258
274
|
signal_quality_breakdown=signal_quality_breakdown,
|
|
275
|
+
predicted_return_magnitude=predicted_return_magnitude,
|
|
276
|
+
predicted_volatility=predicted_volatility,
|
|
259
277
|
)
|
|
260
278
|
|
|
261
279
|
# Priority 8: simulate vs observe.
|
|
@@ -278,6 +296,8 @@ def build_market_analysis_decision(
|
|
|
278
296
|
reasons=reasons,
|
|
279
297
|
signal_quality_score=signal_quality_score,
|
|
280
298
|
signal_quality_breakdown=signal_quality_breakdown,
|
|
299
|
+
predicted_return_magnitude=predicted_return_magnitude,
|
|
300
|
+
predicted_volatility=predicted_volatility,
|
|
281
301
|
)
|
|
282
302
|
|
|
283
303
|
reasons.append("no_actionable_edge")
|