aether-quant 0.4.0__tar.gz → 0.6.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.4.0 → aether_quant-0.6.0}/.gitignore +0 -2
- {aether_quant-0.4.0 → aether_quant-0.6.0}/Dockerfile.retraining_worker +3 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/PKG-INFO +1 -1
- {aether_quant-0.4.0 → aether_quant-0.6.0}/README.md +65 -38
- {aether_quant-0.4.0 → aether_quant-0.6.0}/aether_quant.egg-info/PKG-INFO +1 -1
- {aether_quant-0.4.0 → aether_quant-0.6.0}/aether_quant.egg-info/SOURCES.txt +10 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/aether_quant.egg-info/scm_file_list.json +10 -0
- aether_quant-0.6.0/aether_quant.egg-info/scm_version.json +8 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/analyzer/README.md +37 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/analyzer/__init__.py +2 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/analyzer/market_analyzer.py +81 -2
- {aether_quant-0.4.0 → aether_quant-0.6.0}/aq_cli.py +192 -1
- aether_quant-0.6.0/config.json +543 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/development/Changelog.md +262 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/development/Problems.md +103 -12
- aether_quant-0.6.0/development/backtest_equity_chart.png +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/development/v2_architecture.md +20 -0
- aether_quant-0.6.0/lean.json +649 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/main.py +70 -2
- aether_quant-0.6.0/ml/gating_feature_schema.json +30 -0
- aether_quant-0.6.0/ml/gating_model.json +570 -0
- aether_quant-0.6.0/ml/gating_training_metrics.json +190 -0
- aether_quant-0.6.0/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_feature_schema.json +30 -0
- aether_quant-0.6.0/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_model.json +570 -0
- aether_quant-0.6.0/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_training_metrics.json +190 -0
- aether_quant-0.6.0/moe/README.md +61 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/moe/__init__.py +4 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/moe/gating.py +101 -36
- {aether_quant-0.4.0 → aether_quant-0.6.0}/monitoring/README.md +1 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/monitoring/neural_network_state.py +41 -22
- {aether_quant-0.4.0 → aether_quant-0.6.0}/retraining/__init__.py +4 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/retraining/artifacts.py +23 -6
- {aether_quant-0.4.0 → aether_quant-0.6.0}/retraining/orchestrator.py +54 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/retraining/worker.py +6 -0
- aether_quant-0.6.0/risk/README.md +50 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/risk/position_sizing.py +52 -1
- {aether_quant-0.4.0 → aether_quant-0.6.0}/risk_controls.py +14 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_aq_cli.py +284 -0
- aether_quant-0.6.0/tests/test_gating_network.py +235 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_market_analyzer.py +118 -1
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_neural_network_state.py +34 -5
- aether_quant-0.6.0/tests/test_position_sizing.py +123 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_retraining_artifacts.py +66 -1
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_retraining_orchestrator.py +49 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_retraining_worker.py +20 -12
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_risk_controls.py +19 -0
- aether_quant-0.6.0/tests/test_train_gating.py +179 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/topology/README.md +7 -0
- aether_quant-0.6.0/train_gating.py +436 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/README.md +13 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/neuralnet/NeuralNetworkScene3D.tsx +5 -3
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/types/state.ts +2 -2
- aether_quant-0.4.0/aether_quant.egg-info/scm_version.json +0 -8
- aether_quant-0.4.0/development/backtest_equity_chart.png +0 -0
- aether_quant-0.4.0/moe/README.md +0 -19
- aether_quant-0.4.0/risk/README.md +0 -19
- aether_quant-0.4.0/tests/test_gating_network.py +0 -97
- aether_quant-0.4.0/tests/test_position_sizing.py +0 -55
- {aether_quant-0.4.0 → aether_quant-0.6.0}/.dockerignore +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/.env.compose.example +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/.env.live.example +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/.gitattributes +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/.github/workflows/ci.yml +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/.github/workflows/release.yml +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/Dockerfile +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/Dockerfile.workers +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/aether_quant.egg-info/dependency_links.txt +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/aether_quant.egg-info/entry_points.txt +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/aether_quant.egg-info/top_level.txt +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/backtests/.gitkeep +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/data/alternative/estimize/consensus/aapl/.keep +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/data/alternative/estimize/estimate/.keep +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/data/alternative/estimize/release/.keep +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/data/alternative/sec/aapl/.keep +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/data/alternative/trading-economics/.keep +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/data/alternative/trading-economics/calendar/.keep +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/data/alternative/trading-economics/earnings/.keep +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/data/alternative/trading-economics/indicator/.keep +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/data_pipeline/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/data_pipeline/__init__.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/data_pipeline/fetch.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/data_pipeline/v2_manifest.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/data_pipeline/yfinance_backfill.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/development/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/development/infrastructure.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/development/logo.png +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/docker-compose.yml +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/execution/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/execution/__init__.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/execution/config_cache.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/execution/live_credentials.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/execution/live_credentials_io.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/execution/order_gate.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/execution/paper_readiness.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/execution/paper_readiness_io.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/execution/paper_readiness_report.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/execution/runtime_config_io.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/experience/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/experience/__init__.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/experience/observation_metrics.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/experience/postgres_worker.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/experience/redis_queue.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/experience/simulated_portfolio.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/experts/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/experts/__init__.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/experts/expert_datasets.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/generate_backtest_report.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/inference/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/inference/__init__.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/inference/exported_model.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/liquidity/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/liquidity/__init__.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/liquidity/market_liquidity.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/ml/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/monitoring/__init__.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/monitoring/api_server.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/notifications/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/notifications/__init__.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/notifications/postgres_telegram.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/notifications/telegram_alerts.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/notifications/telegram_client.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/notifications/telegram_worker.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/performance/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/performance/__init__.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/performance/postgres_triggers.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/performance/trigger_worker.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/performance/triggers.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/pyproject.toml +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/regime/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/regime/__init__.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/regime/market_regime.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/requirements/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/requirements/requirements-dev.txt +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/requirements/requirements-retraining-worker.txt +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/requirements/requirements-runtime.txt +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/requirements/requirements-workers.txt +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/requirements/requirements.txt +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/retraining/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/retraining/backtest_gate.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/retraining/lean_backtest.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/retraining/planning.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/retraining/postgres_registry.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/retraining/status_export.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/retraining/validation_gate.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/retraining/vault_client.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/retraining/vault_commands.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/risk/__init__.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/risk/manual_override.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/setup.cfg +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_backtest_gate.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_config_cache.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_experience_queue.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_expert_datasets.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_expert_models.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_exported_model.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_fetch.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_generate_backtest_report.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_lean_backtest.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_lean_backtest_ml_coverage.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_learned_topology.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_live_credentials.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_live_credentials_io.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_manual_override.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_market_liquidity.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_market_regime.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_market_topology.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_observation_metrics.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_order_gate.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_paper_readiness.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_paper_readiness_io.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_paper_readiness_report.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_postgres_telegram.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_postgres_triggers.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_postgres_worker.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_retraining_planning.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_retraining_postgres_registry.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_runtime_config_io.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_simulated_portfolio.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_status_export.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_telegram_alerts.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_telegram_client.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_telegram_worker.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_train_pipeline.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_train_topology.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_trigger_worker.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_triggers.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_v2_pipeline_manifest.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_validation_gate.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_vault_client.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_vault_commands.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/tests/test_yfinance_backfill.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/topology/__init__.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/topology/learned_topology.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/topology/market_topology.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/train.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/train_topology.py +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/visualization/README.md +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/.gitignore +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/.oxlintrc.json +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/index.html +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/overview_v2_12.png +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/package-lock.json +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/package.json +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/public/favicon.svg +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/public/icons.svg +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/risk_v2_12.png +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/App.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/api/client.ts +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/api/hooks.ts +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/heatmap/AssetHeatmap.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/layout/AppShell.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/layout/Panel.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/monitoring/CountTable.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/monitoring/MonitoringFeeds.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/monitoring/ObservationPanel.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/monitoring/PaperReadinessPanel.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/monitoring/PerformanceTriggersPanel.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/monitoring/RawStateViewer.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/monitoring/RetrainingStatusPanel.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/neuralnet/NeuralNetworkStatsPanel.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/risk/AssetSizingTable.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/risk/LiquidityTable.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/risk/RiskBar.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/risk/RiskCore.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/risk/StrategyRiskCards.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/scene3d/Scene3D.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/scorecards/Scorecards.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/signals/Badge.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/signals/PositionsList.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/signals/SignalBoard.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/topology/ClusterList.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/topology/TopologyLearningPanel.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/topology/TopologyScene3D.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/tracing/AssetPerformancePanel.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/tracing/BacktestEquityPanel.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/tracing/DivergingBarChart.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/tracing/LineChart.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/tracing/MetricsSnapshotPanel.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/components/tracing/ObservationEquityPanel.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/index.css +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/lib/downsample.ts +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/lib/format.ts +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/main.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/pages/NeuralNetworkPage.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/pages/Overview.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/pages/RiskPage.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/pages/TopologyPage.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/pages/TracingPage.tsx +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/src/types/tracing.ts +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/tsconfig.app.json +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/tsconfig.json +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/tsconfig.node.json +0 -0
- {aether_quant-0.4.0 → aether_quant-0.6.0}/webui/vite.config.ts +0 -0
|
@@ -8,7 +8,10 @@ COPY performance/ ./performance/
|
|
|
8
8
|
COPY regime/ ./regime/
|
|
9
9
|
COPY experts/ ./experts/
|
|
10
10
|
COPY topology/ ./topology/
|
|
11
|
+
COPY moe/ ./moe/
|
|
12
|
+
COPY inference/ ./inference/
|
|
11
13
|
COPY retraining/ ./retraining/
|
|
12
14
|
COPY train.py .
|
|
13
15
|
COPY train_topology.py .
|
|
16
|
+
COPY train_gating.py .
|
|
14
17
|
CMD ["python", "-m", "retraining.worker"]
|
|
@@ -10,11 +10,23 @@
|
|
|
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-611%2F611%20passing-brightgreen?style=flat-square&labelColor=1A1A1A" alt="611 of 611 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>
|
|
17
17
|
|
|
18
|
+
<p align="center">
|
|
19
|
+
<img src="https://img.shields.io/badge/PyTorch-4B5563?style=flat-square&labelColor=1A1A1A&logo=pytorch&logoColor=white" alt="PyTorch">
|
|
20
|
+
<img src="https://img.shields.io/badge/scikit--learn-4B5563?style=flat-square&labelColor=1A1A1A&logo=scikitlearn&logoColor=white" alt="scikit-learn">
|
|
21
|
+
<img src="https://img.shields.io/badge/QuantConnect%20Lean-4B5563?style=flat-square&labelColor=1A1A1A" alt="QuantConnect Lean">
|
|
22
|
+
<img src="https://img.shields.io/badge/FastAPI-4B5563?style=flat-square&labelColor=1A1A1A&logo=fastapi&logoColor=white" alt="FastAPI">
|
|
23
|
+
<img src="https://img.shields.io/badge/React-4B5563?style=flat-square&labelColor=1A1A1A&logo=react&logoColor=white" alt="React">
|
|
24
|
+
<img src="https://img.shields.io/badge/TypeScript-4B5563?style=flat-square&labelColor=1A1A1A&logo=typescript&logoColor=white" alt="TypeScript">
|
|
25
|
+
<img src="https://img.shields.io/badge/Redis-4B5563?style=flat-square&labelColor=1A1A1A&logo=redis&logoColor=white" alt="Redis">
|
|
26
|
+
<img src="https://img.shields.io/badge/PostgreSQL-4B5563?style=flat-square&labelColor=1A1A1A&logo=postgresql&logoColor=white" alt="PostgreSQL">
|
|
27
|
+
<img src="https://img.shields.io/badge/GitHub%20Actions-4B5563?style=flat-square&labelColor=1A1A1A&logo=githubactions&logoColor=white" alt="GitHub Actions">
|
|
28
|
+
</p>
|
|
29
|
+
|
|
18
30
|
Aether Quant is not a single static strategy — it's a **dynamic system**: a
|
|
19
31
|
Mixture-of-Experts ensemble (bullish/bearish/sideways/volatility specialists)
|
|
20
32
|
routed by a learned gating network, a market-regime detector, a 3D market
|
|
@@ -391,14 +403,14 @@ and how it's wired in — this table is the index.
|
|
|
391
403
|
|
|
392
404
|
| Metric | Value |
|
|
393
405
|
|---|---|
|
|
394
|
-
| Backtest window |
|
|
395
|
-
| Sharpe Ratio | -0.
|
|
396
|
-
| Net Profit | -
|
|
397
|
-
| Compounding Annual Return | -2.
|
|
398
|
-
| Drawdown | 12.
|
|
399
|
-
| Total Orders |
|
|
400
|
-
| Win Rate |
|
|
401
|
-
| Last updated | 2026-07-
|
|
406
|
+
| Backtest window | 2018-04-01 to 2021-04-02 |
|
|
407
|
+
| Sharpe Ratio | -0.71 |
|
|
408
|
+
| Net Profit | -8.069% |
|
|
409
|
+
| Compounding Annual Return | -2.761% |
|
|
410
|
+
| Drawdown | 12.500% |
|
|
411
|
+
| Total Orders | 27 |
|
|
412
|
+
| Win Rate | 17% |
|
|
413
|
+
| Last updated | 2026-07-06 17:20 UTC (auto-generated by `aq backtest`) |
|
|
402
414
|
<!-- AQ:BACKTEST_END -->
|
|
403
415
|
|
|
404
416
|
<details>
|
|
@@ -407,33 +419,33 @@ and how it's wired in — this table is the index.
|
|
|
407
419
|
<!-- AQ:BACKTEST_FULL_STATS_START -->
|
|
408
420
|
| Metric | Value |
|
|
409
421
|
|---|---|
|
|
410
|
-
| Total Orders |
|
|
411
|
-
| Average Win | 0% |
|
|
412
|
-
| Average Loss | -1.
|
|
413
|
-
| Compounding Annual Return | -2.
|
|
414
|
-
| Drawdown | 12.
|
|
415
|
-
| Expectancy | -
|
|
416
|
-
| Start Equity | 100000 |
|
|
417
|
-
| End Equity |
|
|
418
|
-
| Net Profit | -
|
|
419
|
-
| Sharpe Ratio | -0.
|
|
420
|
-
| Sortino Ratio | -0.
|
|
421
|
-
| Probabilistic Sharpe Ratio | 0.
|
|
422
|
-
| Loss Rate |
|
|
423
|
-
| Win Rate |
|
|
424
|
-
| Profit-Loss Ratio | 0 |
|
|
425
|
-
| Alpha | -0.
|
|
426
|
-
| Beta | 0.
|
|
427
|
-
| Annual Standard Deviation | 0.
|
|
428
|
-
| Annual Variance | 0.
|
|
429
|
-
| Information Ratio | -
|
|
430
|
-
| Tracking Error | 0.
|
|
431
|
-
| Treynor Ratio | -0.
|
|
432
|
-
| Total Fees | $
|
|
433
|
-
| Estimated Strategy Capacity | $
|
|
422
|
+
| Total Orders | 27 |
|
|
423
|
+
| Average Win | 0.18% |
|
|
424
|
+
| Average Loss | -1.70% |
|
|
425
|
+
| Compounding Annual Return | -2.761% |
|
|
426
|
+
| Drawdown | 12.500% |
|
|
427
|
+
| Expectancy | -0.816 |
|
|
428
|
+
| Start Equity | 100000.00 |
|
|
429
|
+
| End Equity | 91930.60 |
|
|
430
|
+
| Net Profit | -8.069% |
|
|
431
|
+
| Sharpe Ratio | -0.71 |
|
|
432
|
+
| Sortino Ratio | -0.471 |
|
|
433
|
+
| Probabilistic Sharpe Ratio | 0.171% |
|
|
434
|
+
| Loss Rate | 83% |
|
|
435
|
+
| Win Rate | 17% |
|
|
436
|
+
| Profit-Loss Ratio | 0.11 |
|
|
437
|
+
| Alpha | -0.058 |
|
|
438
|
+
| Beta | 0.195 |
|
|
439
|
+
| Annual Standard Deviation | 0.051 |
|
|
440
|
+
| Annual Variance | 0.003 |
|
|
441
|
+
| Information Ratio | -0.972 |
|
|
442
|
+
| Tracking Error | 0.155 |
|
|
443
|
+
| Treynor Ratio | -0.184 |
|
|
444
|
+
| Total Fees | $12.00 |
|
|
445
|
+
| Estimated Strategy Capacity | $210000000.00 |
|
|
434
446
|
| Lowest Capacity Asset | IBM R735QTJ8XC9X |
|
|
435
|
-
| Portfolio Turnover | 0.
|
|
436
|
-
| Drawdown Recovery |
|
|
447
|
+
| Portfolio Turnover | 0.07% |
|
|
448
|
+
| Drawdown Recovery | 503 |
|
|
437
449
|
<!-- AQ:BACKTEST_FULL_STATS_END -->
|
|
438
450
|
|
|
439
451
|
</details>
|
|
@@ -463,6 +475,17 @@ experience-worker performance-trigger-worker retraining-worker`) with the
|
|
|
463
475
|
backtest run inside that network, plus an actual trigger condition being
|
|
464
476
|
met during the run.
|
|
465
477
|
|
|
478
|
+
**If `phase_v2.backtest.bypass_safety_gates` is `true`:** this backtest
|
|
479
|
+
also does not represent live/paper-deployable behavior. That flag (default
|
|
480
|
+
`false`) disables the sticky total-drawdown lock and the regime detector's
|
|
481
|
+
drawdown-driven `risk_off` override — both real, designed safety behavior
|
|
482
|
+
in live/paper mode — purely to generate enough trade volume for
|
|
483
|
+
statistically meaningful backtest metrics (see `development/Problems.md`
|
|
484
|
+
#18). A backtest run with this flag set shows the underlying model's
|
|
485
|
+
signal quality across more market conditions, not what this system would
|
|
486
|
+
have actually done if deployed — in live/paper mode, both gates would have
|
|
487
|
+
genuinely halted trading exactly as designed.
|
|
488
|
+
|
|
466
489
|
## Test Suite
|
|
467
490
|
|
|
468
491
|
507 tests, one file per source module, run via:
|
|
@@ -495,7 +518,7 @@ pip install -e .
|
|
|
495
518
|
Either way, `aq --help` gives the full command list:
|
|
496
519
|
|
|
497
520
|
```text
|
|
498
|
-
aq train [--dataset-only|--init-only|--experts-only]
|
|
521
|
+
aq train [--dataset-only|--init-only|--experts-only|--gating-only]
|
|
499
522
|
aq test
|
|
500
523
|
aq backtest
|
|
501
524
|
aq report <backtest-folder> <result-id>
|
|
@@ -503,6 +526,8 @@ aq api
|
|
|
503
526
|
aq webui
|
|
504
527
|
aq docker up [--lean|--all]
|
|
505
528
|
aq docker build
|
|
529
|
+
aq config [get <dotted.key>|set <dotted.key> <value>|keys [<dotted.prefix>]]
|
|
530
|
+
aq lean [get <dotted.key>|set <dotted.key> <value>|keys [<dotted.prefix>]]
|
|
506
531
|
aq retrain <plan|train|validate|backtest|commit|promote|rollback|status> [...]
|
|
507
532
|
aq trade-lock --on|--off|--auto|--status
|
|
508
533
|
aq fetch <crypto|stock> --ticker <TICKER> --start <YYYY-MM-DD> --end <YYYY-MM-DD> [--apply]
|
|
@@ -512,7 +537,7 @@ aq status
|
|
|
512
537
|
Every command except `aq trade-lock` and `aq fetch` is a thin `subprocess`
|
|
513
538
|
wrapper around a command already documented elsewhere in this README:
|
|
514
539
|
|
|
515
|
-
- **`aq train`** — runs `train.py`: builds the dataset and trains the baseline + expert models.
|
|
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`.
|
|
516
541
|
- **`aq test`** — runs the pytest suite and refreshes this README's test badge.
|
|
517
542
|
- **`aq backtest`** — runs `lean backtest .` and refreshes this README's [Backtest Results](#backtest-results) section.
|
|
518
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`.
|
|
@@ -520,6 +545,8 @@ wrapper around a command already documented elsewhere in this README:
|
|
|
520
545
|
- **`aq webui`** — starts the webui dev server (`npm run dev`).
|
|
521
546
|
- **`aq docker up [--lean|--all]`** — starts local infrastructure (default: Redis + PostgreSQL only).
|
|
522
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.
|
|
523
550
|
- **`aq retrain <stage>`** — dispatches to `python -m retraining.orchestrator <stage> ...` for a single manual pipeline stage.
|
|
524
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.
|
|
525
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.
|
|
@@ -695,5 +722,5 @@ architecture docs already identify:
|
|
|
695
722
|
---
|
|
696
723
|
|
|
697
724
|
<div align="center">
|
|
698
|
-
<sub>
|
|
725
|
+
<sub>Aether Quant</sub>
|
|
699
726
|
</div>
|
|
@@ -8,12 +8,15 @@ Dockerfile.retraining_worker
|
|
|
8
8
|
Dockerfile.workers
|
|
9
9
|
README.md
|
|
10
10
|
aq_cli.py
|
|
11
|
+
config.json
|
|
11
12
|
docker-compose.yml
|
|
12
13
|
generate_backtest_report.py
|
|
14
|
+
lean.json
|
|
13
15
|
main.py
|
|
14
16
|
pyproject.toml
|
|
15
17
|
risk_controls.py
|
|
16
18
|
train.py
|
|
19
|
+
train_gating.py
|
|
17
20
|
train_topology.py
|
|
18
21
|
.github/workflows/ci.yml
|
|
19
22
|
.github/workflows/release.yml
|
|
@@ -74,6 +77,12 @@ liquidity/README.md
|
|
|
74
77
|
liquidity/__init__.py
|
|
75
78
|
liquidity/market_liquidity.py
|
|
76
79
|
ml/README.md
|
|
80
|
+
ml/gating_feature_schema.json
|
|
81
|
+
ml/gating_model.json
|
|
82
|
+
ml/gating_training_metrics.json
|
|
83
|
+
ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_feature_schema.json
|
|
84
|
+
ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_model.json
|
|
85
|
+
ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_training_metrics.json
|
|
77
86
|
moe/README.md
|
|
78
87
|
moe/__init__.py
|
|
79
88
|
moe/gating.py
|
|
@@ -161,6 +170,7 @@ tests/test_status_export.py
|
|
|
161
170
|
tests/test_telegram_alerts.py
|
|
162
171
|
tests/test_telegram_client.py
|
|
163
172
|
tests/test_telegram_worker.py
|
|
173
|
+
tests/test_train_gating.py
|
|
164
174
|
tests/test_train_pipeline.py
|
|
165
175
|
tests/test_train_topology.py
|
|
166
176
|
tests/test_trigger_worker.py
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": [
|
|
3
3
|
"README.md",
|
|
4
|
+
"train_gating.py",
|
|
4
5
|
"Dockerfile.workers",
|
|
5
6
|
"aq_cli.py",
|
|
6
7
|
"Dockerfile",
|
|
@@ -8,8 +9,10 @@
|
|
|
8
9
|
".env.compose.example",
|
|
9
10
|
"Dockerfile.retraining_worker",
|
|
10
11
|
"train_topology.py",
|
|
12
|
+
"config.json",
|
|
11
13
|
"train.py",
|
|
12
14
|
".env.live.example",
|
|
15
|
+
"lean.json",
|
|
13
16
|
".dockerignore",
|
|
14
17
|
"generate_backtest_report.py",
|
|
15
18
|
".gitattributes",
|
|
@@ -211,6 +214,7 @@
|
|
|
211
214
|
"tests/test_train_pipeline.py",
|
|
212
215
|
"tests/test_experience_queue.py",
|
|
213
216
|
"tests/test_vault_commands.py",
|
|
217
|
+
"tests/test_train_gating.py",
|
|
214
218
|
"tests/test_fetch.py",
|
|
215
219
|
"data/alternative/sec/aapl/.keep",
|
|
216
220
|
"data/alternative/trading-economics/.keep",
|
|
@@ -227,6 +231,12 @@
|
|
|
227
231
|
"requirements/requirements-workers.txt",
|
|
228
232
|
"requirements/requirements-retraining-worker.txt",
|
|
229
233
|
"ml/README.md",
|
|
234
|
+
"ml/gating_model.json",
|
|
235
|
+
"ml/gating_feature_schema.json",
|
|
236
|
+
"ml/gating_training_metrics.json",
|
|
237
|
+
"ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_model.json",
|
|
238
|
+
"ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_feature_schema.json",
|
|
239
|
+
"ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_training_metrics.json",
|
|
230
240
|
".github/workflows/release.yml",
|
|
231
241
|
".github/workflows/ci.yml"
|
|
232
242
|
]
|
|
@@ -38,7 +38,44 @@ risk engine, and before action categorization / Lean order placement.
|
|
|
38
38
|
explicitly ruled out of scope for that phase as a materially riskier
|
|
39
39
|
change than what its safety rule ("confidence/uncertainty only, never a
|
|
40
40
|
randomized decision") allows.
|
|
41
|
+
- **Follow-up:** the learned topology overlay's confidence/disagreement
|
|
42
|
+
scores now *do* reach a real trade — but through position sizing
|
|
43
|
+
(`risk/position_sizing.py::topology_sizing_multiplier()`), not this
|
|
44
|
+
module. That integration point was chosen specifically because sizing
|
|
45
|
+
is already a continuous, shrink-only multiplier applied after this
|
|
46
|
+
analyzer has categorized the action, so it changes only *how large* an
|
|
47
|
+
already-approved trade is, never *whether* one happens — preserving
|
|
48
|
+
exactly the "confidence/uncertainty only, never a randomized decision"
|
|
49
|
+
rule above. This module's own `trade`/`simulate`/`observe`/
|
|
50
|
+
`reduce_risk` categorization remains fully deterministic and
|
|
51
|
+
unaffected. See `risk/README.md` for details.
|
|
41
52
|
- `main.py` only calls `_apply_signal` when `action == "trade"`. All five
|
|
42
53
|
actions are written into the per-asset `signal_payload` for
|
|
43
54
|
dashboard/Grafana visibility regardless of whether a real order is
|
|
44
55
|
placed.
|
|
56
|
+
- **Real composite scoring (additive, config-gated).** Until now, every
|
|
57
|
+
priority tier here checked exactly one raw field in isolation against a
|
|
58
|
+
fixed threshold (confidence alone, `topology_risk` alone,
|
|
59
|
+
`liquidity_action` alone) — pure if/elif routing, no aggregation. New
|
|
60
|
+
`compute_signal_quality_score(confidence, regime_confidence, topology,
|
|
61
|
+
liquidity)` computes a real bounded `[0,1]` composite — a small,
|
|
62
|
+
hand-tuned weighted blend of raw model confidence (0.45), regime
|
|
63
|
+
confidence (0.20), topology peer-support (0.20, penalized when
|
|
64
|
+
`topology_risk` is `isolated`/`elevated`), and liquidity friction (0.15,
|
|
65
|
+
penalized by `participation_rate`) — mirroring `moe/gating.py`'s
|
|
66
|
+
`_quality_multiplier`/`_performance_score` style: real math over
|
|
67
|
+
already-available fields, not a trained model. `MarketAnalysisDecision`
|
|
68
|
+
gains `signal_quality_score`/`signal_quality_breakdown` fields that are
|
|
69
|
+
**always** computed and populated on every decision, regardless of any
|
|
70
|
+
flag — visible in `visualization/state.json` immediately for dashboard
|
|
71
|
+
use. It only ever changes routing when
|
|
72
|
+
`phase_v2.market_analyzer.use_composite_signal_score` is explicitly
|
|
73
|
+
`true` (default `false`) — in that case it replaces raw `confidence`
|
|
74
|
+
with the composite score in the `trade` gate (priority 7) and the
|
|
75
|
+
`simulate`-vs-`observe` split (priority 8) only. The hard safety-override
|
|
76
|
+
tiers (trade-lock, `risk_off` regime, elevated topology, liquidity
|
|
77
|
+
blocked — priorities 1-6) are **never** affected by this flag, regardless
|
|
78
|
+
of its value — they stay simple categorical gates on purpose, same
|
|
79
|
+
reasoning as the topology-elevated/isolated rules above. Default `false`
|
|
80
|
+
means output is byte-identical to pre-this-change behavior everywhere
|
|
81
|
+
the flag isn't explicitly turned on.
|
|
@@ -4,10 +4,12 @@ from .market_analyzer import (
|
|
|
4
4
|
ACTIONS,
|
|
5
5
|
MarketAnalysisDecision,
|
|
6
6
|
build_market_analysis_decision,
|
|
7
|
+
compute_signal_quality_score,
|
|
7
8
|
)
|
|
8
9
|
|
|
9
10
|
__all__ = [
|
|
10
11
|
"ACTIONS",
|
|
11
12
|
"MarketAnalysisDecision",
|
|
12
13
|
"build_market_analysis_decision",
|
|
14
|
+
"compute_signal_quality_score",
|
|
13
15
|
]
|
|
@@ -4,7 +4,7 @@ action."""
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
-
from dataclasses import asdict, dataclass
|
|
7
|
+
from dataclasses import asdict, dataclass, field
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
ACTIONS = ("observe", "simulate", "trade", "reduce_risk", "retrain_candidate")
|
|
@@ -21,11 +21,57 @@ class MarketAnalysisDecision:
|
|
|
21
21
|
topology_considered: bool
|
|
22
22
|
liquidity_considered: bool
|
|
23
23
|
reasons: list[str]
|
|
24
|
+
signal_quality_score: float = 0.0
|
|
25
|
+
signal_quality_breakdown: dict = field(default_factory=dict)
|
|
24
26
|
|
|
25
27
|
def to_dict(self) -> dict:
|
|
26
28
|
return asdict(self)
|
|
27
29
|
|
|
28
30
|
|
|
31
|
+
def _clamp01(value: float) -> float:
|
|
32
|
+
return max(0.0, min(1.0, value))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def compute_signal_quality_score(
|
|
36
|
+
confidence: float,
|
|
37
|
+
regime_confidence: float,
|
|
38
|
+
topology: dict,
|
|
39
|
+
liquidity: dict,
|
|
40
|
+
) -> tuple[float, dict]:
|
|
41
|
+
"""Bounded [0,1] composite of raw model confidence, regime confidence,
|
|
42
|
+
topology peer-support and liquidity friction. Always computed and
|
|
43
|
+
exposed (signal_quality_score/signal_quality_breakdown) for dashboard
|
|
44
|
+
visibility; only influences routing in build_market_analysis_decision()
|
|
45
|
+
when use_composite_signal_score=True - see analyzer/README.md. Small
|
|
46
|
+
hand-tuned weights, mirroring moe/gating.py's
|
|
47
|
+
_quality_multiplier/_performance_score style - not a trained model."""
|
|
48
|
+
confidence_component = _clamp01(float(confidence))
|
|
49
|
+
regime_component = _clamp01(float(regime_confidence))
|
|
50
|
+
|
|
51
|
+
correlation_strength = _clamp01(float(topology.get("correlation_strength", 0.0) or 0.0))
|
|
52
|
+
topology_penalty = {"isolated": 0.3, "elevated": 0.6}.get(str(topology.get("topology_risk", "unknown")), 1.0)
|
|
53
|
+
topology_component = correlation_strength * topology_penalty if topology else regime_component
|
|
54
|
+
|
|
55
|
+
participation_rate = _clamp01(float(liquidity.get("participation_rate", 0.0) or 0.0))
|
|
56
|
+
liquidity_component = _clamp01(1.0 - participation_rate) if liquidity else 1.0
|
|
57
|
+
|
|
58
|
+
weights = {"confidence": 0.45, "regime": 0.20, "topology": 0.20, "liquidity": 0.15}
|
|
59
|
+
score = (
|
|
60
|
+
weights["confidence"] * confidence_component
|
|
61
|
+
+ weights["regime"] * regime_component
|
|
62
|
+
+ weights["topology"] * topology_component
|
|
63
|
+
+ weights["liquidity"] * liquidity_component
|
|
64
|
+
)
|
|
65
|
+
breakdown = {
|
|
66
|
+
"confidence_component": confidence_component,
|
|
67
|
+
"regime_component": regime_component,
|
|
68
|
+
"topology_component": topology_component,
|
|
69
|
+
"liquidity_component": liquidity_component,
|
|
70
|
+
"weights": dict(weights),
|
|
71
|
+
}
|
|
72
|
+
return _clamp01(score), breakdown
|
|
73
|
+
|
|
74
|
+
|
|
29
75
|
def build_market_analysis_decision(
|
|
30
76
|
signal_name: str,
|
|
31
77
|
confidence: float,
|
|
@@ -41,6 +87,7 @@ def build_market_analysis_decision(
|
|
|
41
87
|
min_confidence_to_trade: float = 0.12,
|
|
42
88
|
retrain_min_regime_confidence: float = 0.20,
|
|
43
89
|
low_regime_confidence_threshold: float = 0.35,
|
|
90
|
+
use_composite_signal_score: bool = False,
|
|
44
91
|
) -> MarketAnalysisDecision:
|
|
45
92
|
reasons: list[str] = []
|
|
46
93
|
decision_source = str(gating.get("decision_source", "unknown"))
|
|
@@ -57,6 +104,17 @@ def build_market_analysis_decision(
|
|
|
57
104
|
else:
|
|
58
105
|
reasons.append("topology_absent_v2_11_pending")
|
|
59
106
|
|
|
107
|
+
# Always computed and exposed for dashboard visibility, regardless of
|
|
108
|
+
# use_composite_signal_score - see compute_signal_quality_score()'s
|
|
109
|
+
# docstring and analyzer/README.md. trade_metric is what priorities 7/8
|
|
110
|
+
# actually gate on below: the composite score when the flag is on,
|
|
111
|
+
# otherwise raw confidence - byte-identical to pre-flag behavior when
|
|
112
|
+
# use_composite_signal_score=False (the default).
|
|
113
|
+
signal_quality_score, signal_quality_breakdown = compute_signal_quality_score(
|
|
114
|
+
confidence, regime_confidence, topology, liquidity
|
|
115
|
+
)
|
|
116
|
+
trade_metric = signal_quality_score if use_composite_signal_score else confidence
|
|
117
|
+
|
|
60
118
|
# Priority 1: reduce_risk - portfolio-level risk lock always wins.
|
|
61
119
|
if trade_lock_active:
|
|
62
120
|
reasons.append(trade_lock_reason or "risk_lock_active")
|
|
@@ -70,6 +128,8 @@ def build_market_analysis_decision(
|
|
|
70
128
|
topology_considered=topology_considered,
|
|
71
129
|
liquidity_considered=liquidity_considered,
|
|
72
130
|
reasons=reasons,
|
|
131
|
+
signal_quality_score=signal_quality_score,
|
|
132
|
+
signal_quality_breakdown=signal_quality_breakdown,
|
|
73
133
|
)
|
|
74
134
|
|
|
75
135
|
# Priority 2: reduce_risk - asset-level risk regime override even
|
|
@@ -86,6 +146,8 @@ def build_market_analysis_decision(
|
|
|
86
146
|
topology_considered=topology_considered,
|
|
87
147
|
liquidity_considered=liquidity_considered,
|
|
88
148
|
reasons=reasons,
|
|
149
|
+
signal_quality_score=signal_quality_score,
|
|
150
|
+
signal_quality_breakdown=signal_quality_breakdown,
|
|
89
151
|
)
|
|
90
152
|
|
|
91
153
|
# Priority 3: reduce_risk - elevated cross-sectional volatility pressure
|
|
@@ -106,6 +168,8 @@ def build_market_analysis_decision(
|
|
|
106
168
|
topology_considered=topology_considered,
|
|
107
169
|
liquidity_considered=liquidity_considered,
|
|
108
170
|
reasons=reasons,
|
|
171
|
+
signal_quality_score=signal_quality_score,
|
|
172
|
+
signal_quality_breakdown=signal_quality_breakdown,
|
|
109
173
|
)
|
|
110
174
|
|
|
111
175
|
# Priority 4: retrain_candidate - zero experts contributing AND the
|
|
@@ -125,6 +189,8 @@ def build_market_analysis_decision(
|
|
|
125
189
|
topology_considered=topology_considered,
|
|
126
190
|
liquidity_considered=liquidity_considered,
|
|
127
191
|
reasons=reasons,
|
|
192
|
+
signal_quality_score=signal_quality_score,
|
|
193
|
+
signal_quality_breakdown=signal_quality_breakdown,
|
|
128
194
|
)
|
|
129
195
|
|
|
130
196
|
# Priority 5: simulate - liquidity blocked (zero volume or DDV below
|
|
@@ -142,6 +208,8 @@ def build_market_analysis_decision(
|
|
|
142
208
|
topology_considered=topology_considered,
|
|
143
209
|
liquidity_considered=liquidity_considered,
|
|
144
210
|
reasons=reasons,
|
|
211
|
+
signal_quality_score=signal_quality_score,
|
|
212
|
+
signal_quality_breakdown=signal_quality_breakdown,
|
|
145
213
|
)
|
|
146
214
|
|
|
147
215
|
# Priority 6: simulate - thin market; participation rate would be
|
|
@@ -158,15 +226,20 @@ def build_market_analysis_decision(
|
|
|
158
226
|
topology_considered=topology_considered,
|
|
159
227
|
liquidity_considered=liquidity_considered,
|
|
160
228
|
reasons=reasons,
|
|
229
|
+
signal_quality_score=signal_quality_score,
|
|
230
|
+
signal_quality_breakdown=signal_quality_breakdown,
|
|
161
231
|
)
|
|
162
232
|
|
|
163
233
|
# Priority 7: trade - only for trading-eligible assets with an actionable
|
|
164
234
|
# directional signal, sufficient confidence, no topology isolation, and
|
|
165
235
|
# no liquidity block (redundant guard — tiers 5/6 already caught those).
|
|
236
|
+
# Gates on trade_metric, not raw confidence directly - see trade_metric's
|
|
237
|
+
# definition above (identical to confidence unless
|
|
238
|
+
# use_composite_signal_score=True).
|
|
166
239
|
if (
|
|
167
240
|
trading_eligible
|
|
168
241
|
and signal_name in {"buy", "sell"}
|
|
169
|
-
and
|
|
242
|
+
and trade_metric >= min_confidence_to_trade
|
|
170
243
|
and topology_risk != "isolated"
|
|
171
244
|
and liquidity_action not in {"block", "simulate_instead"}
|
|
172
245
|
):
|
|
@@ -181,6 +254,8 @@ def build_market_analysis_decision(
|
|
|
181
254
|
topology_considered=topology_considered,
|
|
182
255
|
liquidity_considered=liquidity_considered,
|
|
183
256
|
reasons=reasons,
|
|
257
|
+
signal_quality_score=signal_quality_score,
|
|
258
|
+
signal_quality_breakdown=signal_quality_breakdown,
|
|
184
259
|
)
|
|
185
260
|
|
|
186
261
|
# Priority 8: simulate vs observe.
|
|
@@ -201,6 +276,8 @@ def build_market_analysis_decision(
|
|
|
201
276
|
topology_considered=topology_considered,
|
|
202
277
|
liquidity_considered=liquidity_considered,
|
|
203
278
|
reasons=reasons,
|
|
279
|
+
signal_quality_score=signal_quality_score,
|
|
280
|
+
signal_quality_breakdown=signal_quality_breakdown,
|
|
204
281
|
)
|
|
205
282
|
|
|
206
283
|
reasons.append("no_actionable_edge")
|
|
@@ -214,4 +291,6 @@ def build_market_analysis_decision(
|
|
|
214
291
|
topology_considered=topology_considered,
|
|
215
292
|
liquidity_considered=liquidity_considered,
|
|
216
293
|
reasons=reasons,
|
|
294
|
+
signal_quality_score=signal_quality_score,
|
|
295
|
+
signal_quality_breakdown=signal_quality_breakdown,
|
|
217
296
|
)
|