aether-quant 5.4.8__tar.gz → 5.4.9__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-5.4.9/PKG-INFO +1252 -0
- aether_quant-5.4.9/aether_quant.egg-info/PKG-INFO +1252 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/aether_quant.egg-info/scm_version.json +2 -2
- {aether_quant-5.4.8 → aether_quant-5.4.9}/pyproject.toml +19 -0
- aether_quant-5.4.8/PKG-INFO +0 -7
- aether_quant-5.4.8/aether_quant.egg-info/PKG-INFO +0 -7
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.devcontainer/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.devcontainer/devcontainer.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.devcontainer/dind-v1-test/devcontainer.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.dockerignore +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.env.compose.example +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.env.live.example +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.gitattributes +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.githooks/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.githooks/pre-commit +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.github/workflows/ci.yml +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.github/workflows/release.yml +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/.gitignore +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/AGENTS.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/CODE_OF_CONDUCT.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/CONTRIBUTING.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/Dockerfile +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/Dockerfile.lean +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/LICENSE +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/REPRODUCIBILITY.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/RUNBOOK.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/SECURITY.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/aether_quant.egg-info/SOURCES.txt +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/aether_quant.egg-info/dependency_links.txt +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/aether_quant.egg-info/entry_points.txt +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/aether_quant.egg-info/scm_file_list.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/aether_quant.egg-info/top_level.txt +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/analyzer/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/analyzer/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/analyzer/market_analyzer.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/aq_cli.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/audit/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/audit/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/audit/hash_chain.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/audit/postgres_audit.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/audit/postgres_worker.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/audit/redis_queue.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/audit/status_export.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/backtests/.gitkeep +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/config.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/cpp_inference_ext/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/cpp_inference_ext/pyproject.toml +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/cpp_inference_ext/setup.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/cpp_inference_ext/src/linear_batched.cpp +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data/alternative/estimize/consensus/aapl/.keep +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data/alternative/estimize/estimate/.keep +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data/alternative/estimize/release/.keep +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data/alternative/sec/aapl/.keep +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data/alternative/trading-economics/.keep +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data/alternative/trading-economics/calendar/.keep +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data/alternative/trading-economics/earnings/.keep +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data/alternative/trading-economics/indicator/.keep +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data/reference/forex_pair_specs.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data/reference/futures_contract_specs.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data/reference/sector_mapping.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data_pipeline/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data_pipeline/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data_pipeline/bar_synthesis.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data_pipeline/dividend_backfill.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data_pipeline/factor_file_backfill.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data_pipeline/fetch.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data_pipeline/fred_backfill.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data_pipeline/ib_backfill.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data_pipeline/v2_manifest.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/data_pipeline/yfinance_backfill.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/Changelog.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/Problems.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/architecture.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/asset_universe.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/backtest_equity_chart.png +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/backups/Changelog.md.bak_pre_condense +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/backups/Changelog.md.bak_pre_condense_v54 +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/backups/Problems.md.bak_pre_condense +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/backups/Problems.md.bak_pre_condense_v54 +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/backups/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/infrastructure.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/logo.png +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/monte_carlo_equity_curves.png +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/development/project_structure.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/docker-compose.yml +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/ablation.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/benchmark_comparison.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/confidence_threshold_calibration.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/factor_neutralization_check.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/feature_parity.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/feature_reconciliation.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/impact_model.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/kill_switch_replay.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/limit_fill_simulator.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/model_predictions.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/monte_carlo.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/public_benchmarks.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/rank_book_simulator.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/rank_ic_core.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/rank_signal_calibration.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/rolling_ic_gate_calibration.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/evaluation/rolling_ic_gate_replay.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/config_cache.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/cost_model.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/lean_config_render.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/live_credentials.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/live_credentials_io.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/order_gate.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/paper_readiness.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/paper_readiness_io.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/paper_readiness_report.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/paper_readiness_scheduler.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/reconciliation.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/runtime_config_io.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/execution/secret_scan.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/experience/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/experience/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/experience/observation_metrics.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/experience/postgres_worker.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/experience/redis_queue.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/experience/simulated_portfolio.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/experts/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/experts/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/experts/expert_datasets.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/features/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/features/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/features/alt_data_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/features/bond_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/features/cross_asset_sensitivity.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/features/derivatives_macro_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/features/macro_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/features/options_greeks.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/features/sector_map.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/features/technical_indicators.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/generate_backtest_report.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/generate_evaluation_report.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/inference/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/inference/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/inference/exported_model.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/inference/parallel_inference.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/inference/strategy_selector_inference.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/json_safety.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/lean.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/liquidity/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/liquidity/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/liquidity/market_liquidity.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/main.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/bearish/metrics.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/bearish/model.pt +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/bearish/model_weights.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/bearish/multitask_model.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/bearish/multitask_training_metrics.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/bullish/metrics.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/bullish/model.pt +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/bullish/model_weights.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/bullish/multitask_model.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/bullish/multitask_training_metrics.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/sideways/metrics.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/sideways/model.pt +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/sideways/model_weights.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/sideways/multitask_model.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/sideways/multitask_training_metrics.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/volatility/metrics.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/volatility/model.pt +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/volatility/model_weights.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/volatility/multitask_model.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/expert_models/volatility/multitask_training_metrics.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/feature_schema.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/gating_feature_schema.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/gating_model.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/gating_training_metrics.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/model.pt +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/model_weights.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/multitask_feature_schema.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/multitask_model.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/multitask_training_metrics.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/scaler.pkl +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/scaler_stats.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/sequence_feature_schema.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/sequence_model.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/sequence_training_metrics.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/ml/_backup_pre_v537/training_metrics.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/moe/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/moe/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/moe/gating.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/monitoring/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/monitoring/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/monitoring/api_server.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/monitoring/assets_status.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/monitoring/evaluation_state.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/monitoring/neural_network_state.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/monitoring/strategy_catalog.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/notifications/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/notifications/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/notifications/postgres_telegram.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/notifications/telegram_alerts.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/notifications/telegram_client.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/notifications/telegram_worker.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/performance/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/performance/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/performance/postgres_triggers.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/performance/rank_ic_monitor.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/performance/trigger_worker.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/performance/triggers.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/portfolio/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/portfolio/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/portfolio/book_construction.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/portfolio/book_neutrality.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/portfolio/hrp_allocation.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/portfolio/options_arbitrage_detector.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/portfolio/options_assignment_risk.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/portfolio/options_margin_sizing.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/portfolio/options_strategy.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/portfolio/rank_signal.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/portfolio/rolling_ic_gate.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/regime/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/regime/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/regime/market_regime.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/requirements/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/requirements/lean-runtime.txt +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/requirements/requirements-dev.txt +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/requirements/requirements.txt +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/artifacts.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/auto_rollback.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/backtest_gate.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/lean_backtest.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/orchestrator.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/planning.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/postgres_registry.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/rollback_hardening.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/status_export.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/validation_gate.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/vault_client.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/vault_commands.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/retraining/worker.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/risk/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/risk/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/risk/asset_class_router.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/risk/forex_risk.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/risk/futures_risk.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/risk/kill_switch.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/risk/manual_override.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/risk/position_sizing.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/risk/rl_sizing.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/risk_controls.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/scripts/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/scripts/feature_parity_audit.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/scripts/gate_sweep.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/scripts/gate_sweep_score_stage.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/scripts/order_events_audit.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/scripts/overlap_vs_sharpe_analysis.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/scripts/profile_inference.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/scripts/profile_subsystems.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/scripts/promotion_gate_null_calibration.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/scripts/promotion_gate_null_gate_scheme.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/scripts/render_lean_credentials.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/scripts/run_lean_cli_windows.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/setup.cfg +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_ablation.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_alt_data_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_api_server.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_aq_cli.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_aq_test_ruff_flag.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_asset_class_router.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_assets_status.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_audit_postgres_worker.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_audit_queue.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_audit_status_export.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_auto_rollback.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_backtest_gate.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_bar_synthesis_parity.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_bond_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_book_neutrality.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_ci_workflows.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_cli_help_surface.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_confidence_threshold_calibration.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_config_cache.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_cost_model.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_cross_asset_sensitivity.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_derivatives_macro_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_dividend_backfill.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_dockerignore_secrets.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_evaluation_state.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_experience_queue.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_expert_datasets.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_expert_models.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_exported_model.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_factor_file_backfill.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_feature_parity.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_feature_reconciliation.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_fetch.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_forex_risk.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_fred_backfill.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_futures_risk.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_gating_network.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_generate_backtest_report.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_generate_evaluation_report.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_hash_chain.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_hrp_book_sizing.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_ib_backfill.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_impact_model.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_json_safety.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_kill_switch.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_kill_switch_replay.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_lean_backtest.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_lean_backtest_ml_coverage.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_lean_config_render.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_lean_runtime_imports.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_learned_topology.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_limit_fill_simulator.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_live_credentials.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_live_credentials_io.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_macro_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_manual_override.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_market_analyzer.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_market_liquidity.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_market_regime.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_market_topology.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_model_predictions.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_monte_carlo.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_neural_network_state.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_observation_metrics.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_options_arbitrage_detector.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_options_assignment_risk.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_options_greeks.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_options_margin_sizing.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_options_strategy.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_options_strategy_multileg.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_order_events_audit.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_order_gate.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_paper_readiness.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_paper_readiness_io.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_paper_readiness_report.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_paper_readiness_scheduler.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_parallel_inference.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_portfolio_book_construction.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_position_sizing.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_postgres_audit.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_postgres_telegram.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_postgres_triggers.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_postgres_worker.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_profile_inference.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_profile_subsystems.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_promotion_gate_era_rule.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_public_benchmarks.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_rank_book_simulator.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_rank_ic_core.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_rank_ic_monitor.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_rank_signal.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_rank_signal_calibration.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_reconciliation.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_retraining_artifacts.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_retraining_orchestrator.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_retraining_planning.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_retraining_postgres_registry.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_retraining_worker.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_risk_controls.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_rl_sizing.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_rl_sizing_v541.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_rollback_hardening.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_rolling_ic_gate.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_rolling_ic_gate_calibration.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_rolling_ic_gate_replay.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_runtime_config_io.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_secret_scan.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_sector_map.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_simulated_portfolio.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_status_export.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_strategy_catalog.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_strategy_selector_inference.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_technical_indicators.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_telegram_alerts.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_telegram_client.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_telegram_worker.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_alt_data_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_asset_class_context_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_bond_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_cross_asset_sensitivity.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_cross_sectional_batching.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_cross_sectional_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_derivatives_macro_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_gate_friendliness.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_gating.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_indicators.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_macro_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_multitask.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_multitask_architecture.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_optimizer_and_swa.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_pipeline.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_ranking_loss.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_ranking_validation.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_residual_rank_targets.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_rl_sizing.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_select_model_context_columns.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_sequence.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_sequence_architecture.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_strategy_selector.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_threshold_and_early_stop.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_topology.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_train_walk_forward_windows.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_trigger_worker.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_triggers.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_v2_pipeline_manifest.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_v543_new_features.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_v547_bug_hunt.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_validation_gate.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_vault_client.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_vault_commands.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_walk_forward_multimodel.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/tests/test_yfinance_backfill.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/topology/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/topology/__init__.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/topology/learned_topology.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/topology/market_topology.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/train.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/train_gating.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/train_multitask.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/train_rl_sizing.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/train_sequence.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/train_strategy_selector.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/train_topology.py +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/visualization/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/visualization/forex_order_sizing.jsonl +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/.gitignore +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/.oxlintrc.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/README.md +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/index.html +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/overview_v2_12.png +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/package-lock.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/package.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/public/favicon.svg +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/public/icons.svg +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/risk_v2_12.png +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/App.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/api/client.ts +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/api/hooks.ts +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/AblationPanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/AblationPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/BenchmarkPanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/BenchmarkPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/BookHistoryReconciliationPanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/BookHistoryReconciliationPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/BookSpreadCalibrationPanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/BookSpreadCalibrationPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/CapacityStressPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/MonteCarloPanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/MonteCarloPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/RankBookPerformancePanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/RankBookPerformancePanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/WalkForwardStabilityPanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/evaluation/WalkForwardStabilityPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/heatmap/AssetHeatmap.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/layout/AppShell.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/layout/Panel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/monitoring/AssetsStatusPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/monitoring/AuditLogPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/monitoring/CountTable.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/monitoring/KillSwitchPanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/monitoring/KillSwitchPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/monitoring/MonitoringFeeds.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/monitoring/ObservationPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/monitoring/PaperReadinessPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/monitoring/PerformanceTriggersPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/monitoring/RawStateViewer.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/monitoring/ReconciliationPanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/monitoring/ReconciliationPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/monitoring/RetrainingStatusPanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/monitoring/RetrainingStatusPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/neuralnet/NeuralNetworkScene3D.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/neuralnet/NeuralNetworkStatsPanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/neuralnet/NeuralNetworkStatsPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/neuralnet/TrainingRecipePanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/neuralnet/TrainingRecipePanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/optionsstrategy/CorporateActionsPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/optionsstrategy/DividendScheduleSummaryPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/optionsstrategy/ForexPairDetailPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/optionsstrategy/HeldMultiLegPositionsPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/optionsstrategy/StrategyCatalogBrowser.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/optionsstrategy/StrategySelectorScoresPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/portfolio/BookNeutralityPanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/portfolio/BookNeutralityPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/risk/AssetSizingTable.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/risk/AssetSizingTable.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/risk/DerivativesMacroPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/risk/LiquidityTable.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/risk/MacroSnapshotPanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/risk/MacroSnapshotPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/risk/NetEdgePanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/risk/NetEdgePanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/risk/RiskBar.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/risk/RiskCore.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/risk/SensitivityPanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/risk/SensitivityPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/risk/StrategyRiskCards.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/scene3d/Scene3D.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/scorecards/Scorecards.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/signals/Badge.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/signals/PositionsList.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/signals/RankSignalPanel.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/signals/RankSignalPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/signals/SignalBoard.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/topology/ClusterList.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/topology/TopologyLearningPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/topology/TopologyScene3D.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/topology/TopologyScene3D.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/tracing/AssetPerformancePanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/tracing/BacktestEquityPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/tracing/DivergingBarChart.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/tracing/DivergingBarChart.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/tracing/LineChart.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/tracing/LineChart.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/tracing/MetricsSnapshotPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/components/tracing/ObservationEquityPanel.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/index.css +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/lib/downsample.ts +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/lib/format.test.ts +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/lib/format.ts +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/main.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/pages/EvaluationPage.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/pages/NeuralNetworkPage.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/pages/OperationsPage.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/pages/OptionsStrategyPage.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/pages/Overview.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/pages/RiskPage.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/pages/TopologyPage.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/pages/TracingPage.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/pages/pages.test.tsx +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/test/setup.ts +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/types/audit.ts +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/types/evaluation.ts +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/types/state.ts +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/src/types/tracing.ts +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/tsconfig.app.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/tsconfig.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/tsconfig.node.json +0 -0
- {aether_quant-5.4.8 → aether_quant-5.4.9}/webui/vite.config.ts +0 -0
|
@@ -0,0 +1,1252 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aether-quant
|
|
3
|
+
Version: 5.4.9
|
|
4
|
+
Summary: Aether Quant convenience CLI
|
|
5
|
+
Author: leon1706-lol
|
|
6
|
+
License-Expression: LicenseRef-PolyForm-Noncommercial-1.0.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/leon1706-lol/Aether-quant
|
|
8
|
+
Project-URL: Repository, https://github.com/leon1706-lol/Aether-quant
|
|
9
|
+
Project-URL: Changelog, https://github.com/leon1706-lol/Aether-quant/blob/main/development/Changelog.md
|
|
10
|
+
Keywords: algorithmic-trading,quantitative-finance,pytorch,quantconnect
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
<p align="center">
|
|
23
|
+
<img src="development/logo.png" width="220" alt="Aether Quant logo">
|
|
24
|
+
</p>
|
|
25
|
+
|
|
26
|
+
<h1 align="center">Aether Quant</h1>
|
|
27
|
+
|
|
28
|
+
<p align="center">
|
|
29
|
+
<strong>Aether Quant's flagship trading model: a dynamic, self-adapting algorithmic trading system built on QuantConnect Lean and PyTorch, engineered to prove that dynamic models belong in dynamic markets.</strong>
|
|
30
|
+
</p>
|
|
31
|
+
|
|
32
|
+
<p align="center">
|
|
33
|
+
<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+">
|
|
34
|
+
<img src="https://img.shields.io/badge/%F0%9F%93%84%20license-PolyForm%20Noncommercial%201.0.0-8B5CF6?style=flat-square&labelColor=1A1A1A" alt="License: PolyForm Noncommercial 1.0.0">
|
|
35
|
+
<!-- AQ:TEST_BADGE_START --><img src="https://img.shields.io/badge/tests-2929%2F2929%20passing-brightgreen?style=flat-square&labelColor=1A1A1A" alt="2929 of 2929 tests passing"><!-- AQ:TEST_BADGE_END -->
|
|
36
|
+
<img src="https://img.shields.io/pypi/v/aether-quant?style=flat-square&labelColor=1A1A1A&color=FF8C00&logo=pypi&logoColor=white" alt="PyPI version">
|
|
37
|
+
<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">
|
|
38
|
+
</p>
|
|
39
|
+
|
|
40
|
+
<p align="center">
|
|
41
|
+
<img src="https://img.shields.io/badge/PyTorch-4B5563?style=flat-square&labelColor=1A1A1A&logo=pytorch&logoColor=white" alt="PyTorch">
|
|
42
|
+
<img src="https://img.shields.io/badge/scikit--learn-4B5563?style=flat-square&labelColor=1A1A1A&logo=scikitlearn&logoColor=white" alt="scikit-learn">
|
|
43
|
+
<img src="https://img.shields.io/badge/QuantConnect%20Lean-4B5563?style=flat-square&labelColor=1A1A1A&logo=quantconnect&logoColor=white" alt="QuantConnect Lean">
|
|
44
|
+
<img src="https://img.shields.io/badge/Interactive%20Brokers-4B5563?style=flat-square&labelColor=1A1A1A" alt="Interactive Brokers">
|
|
45
|
+
<img src="https://img.shields.io/badge/FastAPI-4B5563?style=flat-square&labelColor=1A1A1A&logo=fastapi&logoColor=white" alt="FastAPI">
|
|
46
|
+
<img src="https://img.shields.io/badge/React-4B5563?style=flat-square&labelColor=1A1A1A&logo=react&logoColor=white" alt="React">
|
|
47
|
+
<img src="https://img.shields.io/badge/TypeScript-4B5563?style=flat-square&labelColor=1A1A1A&logo=typescript&logoColor=white" alt="TypeScript">
|
|
48
|
+
<img src="https://img.shields.io/badge/Redis-4B5563?style=flat-square&labelColor=1A1A1A&logo=redis&logoColor=white" alt="Redis">
|
|
49
|
+
<img src="https://img.shields.io/badge/PostgreSQL-4B5563?style=flat-square&labelColor=1A1A1A&logo=postgresql&logoColor=white" alt="PostgreSQL">
|
|
50
|
+
<img src="https://img.shields.io/badge/GitHub%20Actions-4B5563?style=flat-square&labelColor=1A1A1A&logo=githubactions&logoColor=white" alt="GitHub Actions">
|
|
51
|
+
<img src="https://img.shields.io/badge/GitHub%20Codespaces-4B5563?style=flat-square&labelColor=1A1A1A&logo=github&logoColor=white" alt="GitHub Codespaces">
|
|
52
|
+
</p>
|
|
53
|
+
|
|
54
|
+
Aether Quant is not a single static strategy. It's a **dynamic system**.
|
|
55
|
+
At its core, an ensemble of neural models predicts, for every asset every
|
|
56
|
+
day, a multi-horizon view of the market: **direction** at 1, 5 and 20 days,
|
|
57
|
+
expected **return magnitude** and **volatility**, and the signal it actually
|
|
58
|
+
trades on: each asset's **cross-sectional rank**, which drives a
|
|
59
|
+
market-neutral **long/short book**. Predictions come from a
|
|
60
|
+
**Mixture-of-Experts** ensemble (bullish/bearish/sideways/volatility
|
|
61
|
+
specialists) routed by a learned gating network, plus a **causal-TCN
|
|
62
|
+
sequence encoder**, all reading one feature pipeline that folds in a
|
|
63
|
+
**market-regime detector**, a **3D market topology** layer, and a
|
|
64
|
+
**liquidity/market-impact engine**. A **unified multi-asset-class layer**
|
|
65
|
+
trades equities, crypto, bonds, futures, options, and Forex through one
|
|
66
|
+
coherent portfolio — real yield-curve features for bonds, margin-aware
|
|
67
|
+
sizing for futures, greeks-based sizing for options, and shared cross-asset
|
|
68
|
+
macro signals feeding every asset's prediction — while a **controlled
|
|
69
|
+
retraining loop** lets the model evolve as markets do. Everything is wired
|
|
70
|
+
together and validated end-to-end inside QuantConnect's Lean engine. The
|
|
71
|
+
thesis this project exists to test: **markets are non-stationary, so a
|
|
72
|
+
trading model should be too.** Every subsystem here exists to make the model
|
|
73
|
+
adapt to regime shifts, changing correlation structure, and liquidity
|
|
74
|
+
conditions. The [Architecture](#architecture) section below has the full
|
|
75
|
+
picture; [`development/architecture.md`](development/architecture.md) goes
|
|
76
|
+
deeper still.
|
|
77
|
+
|
|
78
|
+
## Known Limitations
|
|
79
|
+
|
|
80
|
+
Bonds are fully real today, no IB key needed. Futures and options are
|
|
81
|
+
fully wired end-to-end (chain parsing, greeks/IV, sizing, order placement,
|
|
82
|
+
position-close/exposure tracking, offline derivatives-macro training
|
|
83
|
+
features) but remain **data-empty until an Interactive Brokers key is
|
|
84
|
+
connected** (`phase_v2.ib.enabled`, see `aq ib status`/`aq assets
|
|
85
|
+
status`). Remaining, still-open items:
|
|
86
|
+
|
|
87
|
+
- **IB is unverified end-to-end**: futures margin uses a static reference file by default; an opt-in live (Lean/IB-calibrated) margin source exists (`phase_v2.futures_risk.margin_source`, see `development/Problems.md` #67) but, like the connection itself, has never been tested against a real Gateway. All 43 option structures (#38, #59) are unverified for the same reason, no option/future asset exists in the universe yet, and adding a real one goes through the IB-backed `aq fetch options --apply` path.
|
|
88
|
+
- **Production-safety machinery is unit- and backtest-verified, not field-tested**: the kill switch, position reconciliation, and auto-rollback (`aq kill-switch`, see [CLI Reference](#cli-reference)) are fully covered by unit tests and have now run for real inside a completed Lean backtest (kill switch stayed untripped through its warmup window, reconciliation reported zero false breaches) — but nothing has yet run them against a real, continuously-running broker/Postgres deployment over live/paper hours. That's the same gap IB testing itself needs to close.
|
|
89
|
+
|
|
90
|
+
## Table of Contents
|
|
91
|
+
|
|
92
|
+
- [Known Limitations](#known-limitations)
|
|
93
|
+
- [Download](#download)
|
|
94
|
+
- [Getting Started](#getting-started)
|
|
95
|
+
- [Requirements](#requirements)
|
|
96
|
+
- [Architecture](#architecture)
|
|
97
|
+
- [Universe Size](#universe-size)
|
|
98
|
+
- [Project Structure](#project-structure)
|
|
99
|
+
- [Module Documentation](#module-documentation)
|
|
100
|
+
- [Development Documentation](#development-documentation)
|
|
101
|
+
- [Open Source Files](#open-source-files)
|
|
102
|
+
- [Backtest Results](#backtest-results)
|
|
103
|
+
- [Lean Backtest](#lean-backtest)
|
|
104
|
+
- [Monte Carlo Simulation](#monte-carlo-simulation)
|
|
105
|
+
- [Offline Evaluation](#offline-evaluation)
|
|
106
|
+
- [Benchmark Comparison](#benchmark-comparison)
|
|
107
|
+
- [Walk-Forward Training/Testing](#walk-forward-trainingtesting)
|
|
108
|
+
- [Other Metrics](#other-metrics)
|
|
109
|
+
- [Disclaimer](#disclaimer)
|
|
110
|
+
- [Test Suite](#test-suite)
|
|
111
|
+
- [CLI Reference](#cli-reference)
|
|
112
|
+
- [`aq train`](#aq-train)
|
|
113
|
+
- [`aq test`](#aq-test)
|
|
114
|
+
- [`aq backtest`](#aq-backtest)
|
|
115
|
+
- [`aq profile`](#aq-profile)
|
|
116
|
+
- [`aq report`](#aq-report)
|
|
117
|
+
- [`aq api`](#aq-api)
|
|
118
|
+
- [`aq webui`](#aq-webui)
|
|
119
|
+
- [`aq docker`](#aq-docker)
|
|
120
|
+
- [`aq config`](#aq-config)
|
|
121
|
+
- [`aq lean`](#aq-lean)
|
|
122
|
+
- [`aq retrain`](#aq-retrain)
|
|
123
|
+
- [`aq paper-readiness`](#aq-paper-readiness)
|
|
124
|
+
- [`aq trade-lock`](#aq-trade-lock)
|
|
125
|
+
- [`aq kill-switch`](#aq-kill-switch)
|
|
126
|
+
- [`aq evaluate`](#aq-evaluate)
|
|
127
|
+
- [`aq fetch`](#aq-fetch)
|
|
128
|
+
- [`aq backfill`](#aq-backfill)
|
|
129
|
+
- [`aq ib`](#aq-ib)
|
|
130
|
+
- [`aq assets`](#aq-assets)
|
|
131
|
+
- [`aq render-lean-config`](#aq-render-lean-config)
|
|
132
|
+
- [`aq secrets-check`](#aq-secrets-check)
|
|
133
|
+
- [`aq audit-log`](#aq-audit-log)
|
|
134
|
+
- [`aq status`](#aq-status)
|
|
135
|
+
- [Release Process](#release-process)
|
|
136
|
+
- [Roadmap](#roadmap)
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Download
|
|
141
|
+
|
|
142
|
+
If you just want to use Aether Quant rather than develop on it, no local
|
|
143
|
+
`pip install -e .` or source checkout is needed: the CLI and backend are
|
|
144
|
+
published as ready-to-use releases:
|
|
145
|
+
|
|
146
|
+
```powershell
|
|
147
|
+
pip install aether-quant
|
|
148
|
+
docker pull ghcr.io/leon1706-lol/aether-quant:latest
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
`aq --help` is then available immediately (see [CLI Reference](#cli-reference)
|
|
152
|
+
below). `aq` checks PyPI at most once every 24h (short timeout, never
|
|
153
|
+
blocking) for a newer version and prints a one-line notice if one's
|
|
154
|
+
available (disable with `AQ_SKIP_UPDATE_CHECK=1`).
|
|
155
|
+
|
|
156
|
+
The Docker image is the same one `docker-compose.yml`'s `engine` service
|
|
157
|
+
(and every worker service, which all share this one build,
|
|
158
|
+
`aether-quant-engine`) pulls by default (override with the
|
|
159
|
+
`AETHER_QUANT_IMAGE` env var, e.g. to use a locally built image instead).
|
|
160
|
+
This is the single consolidated image (app + every worker, includes the
|
|
161
|
+
full ML stack), so expect a larger download than a minimal API-only image.
|
|
162
|
+
|
|
163
|
+
## Getting Started
|
|
164
|
+
|
|
165
|
+
For local development (this repo cloned, a virtual environment active):
|
|
166
|
+
|
|
167
|
+
1. Install dependencies:
|
|
168
|
+
|
|
169
|
+
```powershell
|
|
170
|
+
pip install -r requirements/requirements.txt
|
|
171
|
+
pip install -r requirements/requirements-dev.txt # local dev extras
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
2. Refresh the data inventory only:
|
|
175
|
+
|
|
176
|
+
```powershell
|
|
177
|
+
python train.py --init-only
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
3. Build the dataset and train the model:
|
|
181
|
+
|
|
182
|
+
```powershell
|
|
183
|
+
python train.py
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Or build dataset artifacts only, without training:
|
|
187
|
+
|
|
188
|
+
```powershell
|
|
189
|
+
python train.py --dataset-only
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
4. Start the webui locally (two processes):
|
|
193
|
+
|
|
194
|
+
```powershell
|
|
195
|
+
uvicorn monitoring.api_server:app --port 8001 --reload
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
```powershell
|
|
199
|
+
cd webui
|
|
200
|
+
npm install
|
|
201
|
+
npm run dev
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Then open `http://localhost:3002`.
|
|
205
|
+
|
|
206
|
+
5. Run a real backtest and refresh this README's [Backtest Results](#backtest-results):
|
|
207
|
+
|
|
208
|
+
```powershell
|
|
209
|
+
pip install -e . # registers the `aq` command from source
|
|
210
|
+
aq backtest
|
|
211
|
+
```
|
|
212
|
+
First run downloads the pinned QuantConnect Lean engine Docker image once (~40GB+) and builds the small local `aether-quant-lean:17900` layer; budget time and bandwidth for it. Later runs reuse both images.
|
|
213
|
+
|
|
214
|
+
## Requirements
|
|
215
|
+
|
|
216
|
+
- **Python ≥ 3.10** for the training pipeline, `main.py`'s Lean algorithm, the FastAPI monitoring server, and the `aq` CLI.
|
|
217
|
+
- **QuantConnect Lean CLI** (`pip install lean`) for running backtests and paper/live trading.
|
|
218
|
+
- **Docker & Docker Compose** for the local infrastructure (Redis, PostgreSQL, and the background workers, experience persistence, performance triggers, controlled retraining, Telegram alerts).
|
|
219
|
+
- **Node.js** (for the `webui/` React/Vite dashboard).
|
|
220
|
+
- **GitHub CLI (`gh`)** — optional, only needed to reproduce model training via a GitHub Codespace (this project's own convention for offloading training off a resource-constrained dev machine; see `development/Problems.md` #71).
|
|
221
|
+
|
|
222
|
+
This repo splits its Python dependencies across several `requirements*.txt`
|
|
223
|
+
files (full training stack vs. minimal per-Docker-image installs vs. local
|
|
224
|
+
dev extras) rather than one monolithic file. See
|
|
225
|
+
**[`requirements/README.md`](requirements/README.md)** for the exact
|
|
226
|
+
`pip install` command for every variant and which Dockerfile consumes each one.
|
|
227
|
+
|
|
228
|
+
## Architecture
|
|
229
|
+
|
|
230
|
+
Aether Quant runs a daily-bar decision pipeline entirely inside Lean's
|
|
231
|
+
`on_data()` callback: features (including bond/macro and options-implied
|
|
232
|
+
alt-data) flow through regime detection and 3D topology modeling (a
|
|
233
|
+
deterministic embedding plus a learned overlay), both feed a gating
|
|
234
|
+
network that routes across four specialized experts, an asset-class
|
|
235
|
+
router sizes the decision across equities/crypto/bonds/futures/options/
|
|
236
|
+
Forex, and every decision is persisted through a Redis → PostgreSQL
|
|
237
|
+
experience pipeline that a controlled retraining loop reads from to
|
|
238
|
+
evolve the model over time.
|
|
239
|
+
|
|
240
|
+
#### System Flow
|
|
241
|
+
|
|
242
|
+
```mermaid
|
|
243
|
+
flowchart LR
|
|
244
|
+
A["Lean data folder<br/>stocks, ETFs, bonds, crypto, Forex"] --> B["Feature pipeline<br/>train.py<br/>price/volume + indicators +<br/>regime + liquidity + topology + peer returns +<br/>bond/macro + alt-data (VIX/financial conditions)"]
|
|
245
|
+
B --> C["Regime detection<br/>trend, volatility, drawdown, correlation"]
|
|
246
|
+
B --> D["3D topology modeling<br/>deterministic + learned overlay"]
|
|
247
|
+
B --> V["Multitask + sequence heads<br/>baseline + 4 experts<br/>direction + magnitude + volatility + rank"]
|
|
248
|
+
C --> E["Gating network<br/>the manager"]
|
|
249
|
+
D --> E
|
|
250
|
+
V --> E
|
|
251
|
+
E --> F["Expert modules"]
|
|
252
|
+
F --> G["Bullish expert"]
|
|
253
|
+
F --> H["Bearish expert"]
|
|
254
|
+
F --> I["Sideways expert"]
|
|
255
|
+
F --> J["Volatility expert"]
|
|
256
|
+
G --> K["Market analyzer<br/>central decision layer"]
|
|
257
|
+
H --> K
|
|
258
|
+
I --> K
|
|
259
|
+
J --> K
|
|
260
|
+
C --> K
|
|
261
|
+
D --> K
|
|
262
|
+
L["Liquidity engine<br/>DDV, participation rate,<br/>slippage estimate"] --> K
|
|
263
|
+
K --> AC["Asset-class router<br/>equity/crypto/bond/futures/options/Forex"]
|
|
264
|
+
AC --> RK["rank_20d/rank_5d position sizing<br/>+ topology/RL sizing multipliers"]
|
|
265
|
+
RK --> M["Action categorization<br/>trade / simulate / observe<br/>reduce_risk / retrain_candidate"]
|
|
266
|
+
M --> N["Lean order execution"]
|
|
267
|
+
M --> O["Observation / simulation record"]
|
|
268
|
+
N --> P["Redis event stream<br/>temporary low-latency buffer"]
|
|
269
|
+
O --> P
|
|
270
|
+
P --> Q["Experience worker<br/>async batch persistence"]
|
|
271
|
+
Q --> R["PostgreSQL experience database<br/>single source of truth"]
|
|
272
|
+
R --> S["Performance triggers<br/>100 observations, drawdown, Sharpe, regime shift"]
|
|
273
|
+
S --> T["Controlled retraining<br/>versioned weights and rollback"]
|
|
274
|
+
T --> E
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
#### Tech Stack
|
|
278
|
+
|
|
279
|
+
```mermaid
|
|
280
|
+
flowchart TB
|
|
281
|
+
A["Infrastructure"] --> A1["Docker Compose<br/>(Redis, Postgres, aether-quant app)"]
|
|
282
|
+
A --> A2["Lean CLI<br/>(backtest + paper trading, local only)"]
|
|
283
|
+
A --> A3["30-day observation phase before live mode"]
|
|
284
|
+
A --> A4["GitHub Codespaces<br/>(cloud training compute)"]
|
|
285
|
+
B["Development"] --> B1["VS Code + Claude Code"]
|
|
286
|
+
B --> B2["GitHub"]
|
|
287
|
+
C["Data and storage"] --> C1["Lean data folder for training/backtesting"]
|
|
288
|
+
C --> C2["Redis temporary event stream"]
|
|
289
|
+
C --> C3["PostgreSQL permanent experience database"]
|
|
290
|
+
D["AI and modeling"] --> D1["PyTorch"]
|
|
291
|
+
D --> D2["scikit-learn"]
|
|
292
|
+
D --> D3["NumPy / Pandas"]
|
|
293
|
+
D --> D4["MoE experts and gating network"]
|
|
294
|
+
D --> D5["Multitask heads (direction/magnitude/<br/>volatility/rank) + causal-TCN sequence encoder"]
|
|
295
|
+
E["Monitoring and UI"] --> E1["React/Vite webui, Tracing dashboard (port 3002 dev / 8001 Docker)"]
|
|
296
|
+
E --> E2["FastAPI JSON API (port 8000)"]
|
|
297
|
+
E --> E3["Telegram alerts<br/>notifications/telegram_worker.py"]
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
These two diagrams are the high-level summary. For the full system —
|
|
301
|
+
every subsystem contract, the module map, the multi-asset-class and
|
|
302
|
+
signal-promotion-gate design, and an honest analysis of what would need
|
|
303
|
+
to change for this to become a genuinely low-latency/HFT system — see
|
|
304
|
+
**[`development/architecture.md`](development/architecture.md)**.
|
|
305
|
+
|
|
306
|
+
#### The model stack
|
|
307
|
+
|
|
308
|
+
Three model families are trained and shipped, all reading the same
|
|
309
|
+
train/runtime-parity feature pipeline (shared pure functions, never
|
|
310
|
+
hand-matched formulas, `features/`, `main.py::_build_model_input()`):
|
|
311
|
+
|
|
312
|
+
- **Baseline + 4 experts** (`train.py::AetherNet*`) — a direction model
|
|
313
|
+
plus bullish/bearish/sideways/volatility specialists, routed by the
|
|
314
|
+
learned gating network (`moe/gating.py`). Each also carries optional
|
|
315
|
+
multitask heads for return magnitude and volatility.
|
|
316
|
+
- **Multitask model** (`AetherNetMultiTaskHorizons`, `train_multitask.py`)
|
|
317
|
+
— a shared trunk with multiple heads: next-day direction,
|
|
318
|
+
`direction_5d`/`direction_20d`, and the cross-sectional rank heads
|
|
319
|
+
(`rank_5d`/`rank_20d`, plus market/sector/size-**residualized** variants
|
|
320
|
+
that measure real skill rather than beta). `rank_20d` is the primary
|
|
321
|
+
trading signal.
|
|
322
|
+
- **Sequence encoder** (`AetherNetSequenceMultiTaskHorizons`,
|
|
323
|
+
`train_sequence.py`) — a causal-TCN over a rolling 30-bar window of the
|
|
324
|
+
same inputs, adding temporal structure the flat-MLP trunk can't see;
|
|
325
|
+
its `rank_5d` head is the strongest signal in this project's history.
|
|
326
|
+
|
|
327
|
+
Both trainers are trained directly against a differentiable ranking
|
|
328
|
+
objective (soft-Spearman/ListNet over whole-date cross-sectional batches),
|
|
329
|
+
not an MSE proxy — the model now optimizes for the thing it actually
|
|
330
|
+
trades on.
|
|
331
|
+
|
|
332
|
+
**66 model inputs** — not just price/volume: regime state (one-hot /
|
|
333
|
+
confidence / trend / risk), liquidity spread/dollar-volume, cross-asset
|
|
334
|
+
topology correlation/risk, correlated-peer lagged returns, 7 technical
|
|
335
|
+
indicators, real bond yield-curve/credit-spread features, alt-data
|
|
336
|
+
(options-implied volatility, financial-conditions change), and per-asset
|
|
337
|
+
macro **sensitivity betas** (rolling regression of each asset's return
|
|
338
|
+
against ΔVIX/Δreal-rate/Δcredit/Δdollar, so macro actually varies
|
|
339
|
+
cross-sectionally instead of shifting every asset equally) — all computed
|
|
340
|
+
offline and at runtime by the same code, with verified parity.
|
|
341
|
+
|
|
342
|
+
The rank heads drive a dollar- and sector-neutral long/short book
|
|
343
|
+
(`portfolio/book_neutrality.py`) with per-position sizing
|
|
344
|
+
(`risk/position_sizing.py`, bounded and direction-preserving) that's
|
|
345
|
+
scaled down when a trade's expected edge doesn't clear its expected
|
|
346
|
+
round-trip cost (`execution/cost_model.py`). Book sizing itself is
|
|
347
|
+
config-selectable (`phase_v2.portfolio_book.allocation_method`): the
|
|
348
|
+
default `"rank"` uses the confidence formula, while `"hrp"` re-weights
|
|
349
|
+
the same selected symbols with Hierarchical Risk Parity inverse-variance
|
|
350
|
+
weights from their correlation structure (`portfolio/book_construction.py::
|
|
351
|
+
apply_hrp_weights()`) — selection never changes, only sizing. An
|
|
352
|
+
automated kill switch, position reconciliation against the broker's
|
|
353
|
+
actual holdings, and an opt-in auto-rollback sit in front of all of it
|
|
354
|
+
(`risk/kill_switch.py`, `execution/reconciliation.py`,
|
|
355
|
+
`retraining/auto_rollback.py`). All of it
|
|
356
|
+
is visible on the `/neural-network`, `/evaluation`, and `/operations`
|
|
357
|
+
webui tabs and in `ml/*_training_metrics.json`.
|
|
358
|
+
|
|
359
|
+
See `inference/README.md`, `moe/README.md`, `risk/README.md`,
|
|
360
|
+
`regime/README.md`, `liquidity/README.md` and `topology/README.md` for
|
|
361
|
+
the full per-subsystem contracts, and `development/architecture.md` for
|
|
362
|
+
how it all fits together.
|
|
363
|
+
|
|
364
|
+
## Universe Size
|
|
365
|
+
|
|
366
|
+
The trading universe currently spans **104 assets**: 55 stocks/broad-market
|
|
367
|
+
ETFs, 22 fixed-income (bond) ETFs, 12 crypto pairs, and 15 forex/FX pairs
|
|
368
|
+
(53% equity / 21% bond / 12% crypto / 14% forex by count), defined in
|
|
369
|
+
`config.json`'s `phase1.universe.assets` and shared across training,
|
|
370
|
+
validation, and backtesting (common window `2014-12-01` to `2021-03-31`).
|
|
371
|
+
Of these, tradeable names carry real positions while "observation-only"
|
|
372
|
+
names (thin history) are fed through the full model pipeline but never
|
|
373
|
+
sized. The 15 forex pairs (V4.10, fetched via `aq fetch forex`) all cover
|
|
374
|
+
the full common window with real Yahoo Finance history, unlike the 7
|
|
375
|
+
newly-added crypto pairs — expected to land "Trading" for the same reason,
|
|
376
|
+
though this hasn't been run through `train.py`'s actual asset-quality
|
|
377
|
+
classifier yet (left for a manual `python train.py --dataset-only` run,
|
|
378
|
+
same division of labor as this project's other deferred training steps).
|
|
379
|
+
|
|
380
|
+
See **[`development/asset_universe.md`](development/asset_universe.md)** for
|
|
381
|
+
the full ticker list, the trading-vs-observation split, the bond-ETF
|
|
382
|
+
duration/credit coverage, and the group-level diagram.
|
|
383
|
+
|
|
384
|
+
## Project Structure
|
|
385
|
+
|
|
386
|
+
The repository is a set of single-responsibility Python packages (one concern
|
|
387
|
+
per folder, each with its own README), a few top-level entry-point scripts
|
|
388
|
+
(`main.py` for the Lean algorithm, `train*.py` for the offline trainers,
|
|
389
|
+
`aq_cli.py` for the CLI), and the runtime config (`config.json` / `lean.json`).
|
|
390
|
+
|
|
391
|
+
See **[`development/project_structure.md`](development/project_structure.md)**
|
|
392
|
+
for the full annotated directory tree, and the
|
|
393
|
+
[Module Documentation](#module-documentation) table below for a per-package
|
|
394
|
+
index with links to each package's own README.
|
|
395
|
+
|
|
396
|
+
## Module Documentation
|
|
397
|
+
|
|
398
|
+
Every package below has its own README with the full detail on what it owns
|
|
399
|
+
and how it's wired in, this table is the index.
|
|
400
|
+
|
|
401
|
+
| Module | What it owns | Docs |
|
|
402
|
+
|---|---|---|
|
|
403
|
+
| `analyzer/` | Central market analyzer, the final per-asset action categorization layer | [README](analyzer/README.md) |
|
|
404
|
+
| `audit/` | Tamper-evident hash-chained audit log (credential loads, live-mode transitions, order path), Redis + PostgreSQL | [README](audit/README.md) |
|
|
405
|
+
| `backtests/` | Strategy validation output (active model + per-candidate reports), gitignored | [README](backtests/README.md) |
|
|
406
|
+
| `data/` | Local Lean data-folder format documentation | [README](data/README.md) |
|
|
407
|
+
| `data_pipeline/` | Lean-data contract + Yahoo Finance historical backfill | [README](data_pipeline/README.md) |
|
|
408
|
+
| `evaluation/` | Offline, cost-aware rank-book simulation (net Sharpe, turnover, capacity, cost stress) — the torch-free offline mirror of the live decision path | [README](evaluation/README.md) |
|
|
409
|
+
| `execution/` | Order gating, paper/live broker readiness, config-read caching, expected-net-edge cost model | [README](execution/README.md) |
|
|
410
|
+
| `experience/` | Observation/decision history, Redis buffer + PostgreSQL persistence | [README](experience/README.md) |
|
|
411
|
+
| `experts/` | Bullish, bearish, sideways, and volatility expert models | [README](experts/README.md) |
|
|
412
|
+
| `features/` | Shared feature-computation functions, called from both `train.py` and `main.py` for train/inference parity | [README](features/README.md) |
|
|
413
|
+
| `inference/` | Vectorized forward-pass interpreter for the exported neural networks | [README](inference/README.md) |
|
|
414
|
+
| `cpp_inference_ext/` | Optional C++/pybind11 accelerator (builds the `cpp_inference` module, never a hard dependency), a separate top-level folder name from the module it builds, deliberately, to avoid a namespace-package collision with the installed package | [README](cpp_inference_ext/README.md) |
|
|
415
|
+
| `liquidity/` | Liquidity and market-impact engine | [README](liquidity/README.md) |
|
|
416
|
+
| `ml/` | Model & dataset artifacts, including versioned retraining candidates | [README](ml/README.md) |
|
|
417
|
+
| `moe/` | Mixture-of-Experts gating network | [README](moe/README.md) |
|
|
418
|
+
| `monitoring/` | FastAPI JSON API serving runtime state to the webui | [README](monitoring/README.md) |
|
|
419
|
+
| `notifications/` | Telegram alerting worker | [README](notifications/README.md) |
|
|
420
|
+
| `performance/` | Performance trigger system (14 trigger functions) | [README](performance/README.md) |
|
|
421
|
+
| `portfolio/` | Stage-2 cross-sectional long/short book construction + Black-Scholes options sizing | [README](portfolio/README.md) |
|
|
422
|
+
| `regime/` | Market regime detection | [README](regime/README.md) |
|
|
423
|
+
| `requirements/` | All `requirements*.txt` variants and what consumes each | [README](requirements/README.md) |
|
|
424
|
+
| `retraining/` | Controlled retraining, plan/train/validate/backtest/commit/promote/rollback | [README](retraining/README.md) |
|
|
425
|
+
| `risk/` | Dynamic position sizing, leverage caps, drawdown-aware sizing | [README](risk/README.md) |
|
|
426
|
+
| `scripts/` | Standalone dev tooling (e.g. the inference-hot-path profiler) | [README](scripts/README.md) |
|
|
427
|
+
| `storage/` | Reserved placeholder for future persistent artifact storage | [README](storage/README.md) |
|
|
428
|
+
| `tests/` | Pytest suite conventions (<!-- AQ:TEST_COUNT_START -->2929<!-- AQ:TEST_COUNT_END --> tests) | [README](tests/README.md) |
|
|
429
|
+
| `topology/` | 3D market topology, deterministic SMACOF embedding + learned overlay | [README](topology/README.md) |
|
|
430
|
+
| `visualization/` | Shared runtime-state JSON/CSV exports | [README](visualization/README.md) |
|
|
431
|
+
| `webui/` | React/Vite dashboard (Overview, Operations, Risk, Options & Strategy, Topology, Neural Network, Tracing) | [README](webui/README.md) |
|
|
432
|
+
| `Aether-quant-Obsidian-Vault/` | Auto-generated Obsidian vault mirroring the repo's architecture/code graph | [README](Aether-quant-Obsidian-Vault/README.md) |
|
|
433
|
+
|
|
434
|
+
## Development Documentation
|
|
435
|
+
|
|
436
|
+
| Document | Contents |
|
|
437
|
+
|---|---|
|
|
438
|
+
| [`development/README.md`](development/README.md) | Index of this folder |
|
|
439
|
+
| [`development/asset_universe.md`](development/asset_universe.md) | The full 104-asset universe: ticker list, trading-vs-observation split, bond-ETF coverage, group diagram |
|
|
440
|
+
| [`development/project_structure.md`](development/project_structure.md) | The full annotated directory tree of the repository |
|
|
441
|
+
| [`development/architecture.md`](development/architecture.md) | The full system architecture: process-flow and tech-stack diagrams, the module map, per-subsystem "contract" sections, the multi-asset-class/ranking design, and the HFT-readiness analysis |
|
|
442
|
+
| [`development/infrastructure.md`](development/infrastructure.md) | Docker Compose runbook, start commands for every service, SQL inspection snippets, port reference |
|
|
443
|
+
| [`development/Changelog.md`](development/Changelog.md) | Detailed, append-only, per-phase build history, what was built, when, and why |
|
|
444
|
+
| [`development/Problems.md`](development/Problems.md) | Append-only audit log of bugs and infrastructure issues, each with a severity rating and fixed/open status |
|
|
445
|
+
| [`development/backups/`](development/backups/README.md) | Frozen pre-condensation snapshots of the two files above (restore points only — never edited) |
|
|
446
|
+
|
|
447
|
+
## Open Source Files
|
|
448
|
+
|
|
449
|
+
| File | Purpose |
|
|
450
|
+
|---|---|
|
|
451
|
+
| [`LICENSE`](LICENSE) | PolyForm Noncommercial 1.0.0 |
|
|
452
|
+
| [`CONTRIBUTING.md`](CONTRIBUTING.md) | How to contribute: setup, testing, code conventions, CI expectations |
|
|
453
|
+
| [`AGENTS.md`](AGENTS.md) | Agent instructions: file layout, commands, code conventions, status markers |
|
|
454
|
+
| [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) | Community conduct policy |
|
|
455
|
+
| [`SECURITY.md`](SECURITY.md) | Security vulnerability reporting policy |
|
|
456
|
+
| [`RUNBOOK.md`](RUNBOOK.md) | Operational procedures: everyday commands, cloud training, kill-switch trips, reconciliation breaches, data gaps |
|
|
457
|
+
| [`REPRODUCIBILITY.md`](REPRODUCIBILITY.md) | Exact steps to reproduce every claimed number |
|
|
458
|
+
| [`development/backups/`](development/backups/README.md) | Pre-condensation snapshots of development records |
|
|
459
|
+
|
|
460
|
+
## Backtest Results
|
|
461
|
+
|
|
462
|
+
### Lean Backtest
|
|
463
|
+
|
|
464
|
+
<!-- AQ:BACKTEST_START -->
|
|
465
|
+

|
|
466
|
+
|
|
467
|
+
| Metric | Value |
|
|
468
|
+
|---|---|
|
|
469
|
+
| Backtest window | 2019-01-01 to 2021-04-02 |
|
|
470
|
+
| Sharpe Ratio | -1.832 |
|
|
471
|
+
| Net Profit | -5.888% |
|
|
472
|
+
| Compounding Annual Return | -2.659% |
|
|
473
|
+
| Drawdown | 6.400% |
|
|
474
|
+
| Total Orders | 462 |
|
|
475
|
+
| Win Rate | 42% |
|
|
476
|
+
| Last updated | 2026-08-19 12:18 UTC (auto-generated by `aq backtest`) |
|
|
477
|
+
<!-- AQ:BACKTEST_END -->
|
|
478
|
+
|
|
479
|
+
<details>
|
|
480
|
+
<summary><strong>Full Lean statistics</strong> (Sharpe, Sortino, Alpha/Beta, fees, capacity, and everything else Lean reports)</summary>
|
|
481
|
+
|
|
482
|
+
<!-- AQ:BACKTEST_FULL_STATS_START -->
|
|
483
|
+
| Metric | Value |
|
|
484
|
+
|---|---|
|
|
485
|
+
| Total Orders | 462 |
|
|
486
|
+
| Average Win | 0.03% |
|
|
487
|
+
| Average Loss | -0.07% |
|
|
488
|
+
| Compounding Annual Return | -2.659% |
|
|
489
|
+
| Drawdown | 6.400% |
|
|
490
|
+
| Expectancy | -0.385 |
|
|
491
|
+
| Start Equity | 100000.00 |
|
|
492
|
+
| End Equity | 94112.31 |
|
|
493
|
+
| Net Profit | -5.888% |
|
|
494
|
+
| Sharpe Ratio | -1.832 |
|
|
495
|
+
| Sortino Ratio | -2.033 |
|
|
496
|
+
| Probabilistic Sharpe Ratio | 0.000% |
|
|
497
|
+
| Loss Rate | 58% |
|
|
498
|
+
| Win Rate | 42% |
|
|
499
|
+
| Profit-Loss Ratio | 0.46 |
|
|
500
|
+
| Alpha | -0.035 |
|
|
501
|
+
| Beta | 0.01 |
|
|
502
|
+
| Annual Standard Deviation | 0.018 |
|
|
503
|
+
| Annual Variance | 0 |
|
|
504
|
+
| Information Ratio | -1.039 |
|
|
505
|
+
| Tracking Error | 0.201 |
|
|
506
|
+
| Treynor Ratio | -3.358 |
|
|
507
|
+
| Total Fees | $596.54 |
|
|
508
|
+
| Estimated Strategy Capacity | $160000000.00 |
|
|
509
|
+
| Lowest Capacity Asset | BWX 2T |
|
|
510
|
+
| Portfolio Turnover | 1.43% |
|
|
511
|
+
| Drawdown Recovery | 10 |
|
|
512
|
+
<!-- AQ:BACKTEST_FULL_STATS_END -->
|
|
513
|
+
|
|
514
|
+
</details>
|
|
515
|
+
|
|
516
|
+
Regenerated on every `aq backtest` run
|
|
517
|
+
([`generate_backtest_report.py`](generate_backtest_report.py)) directly from
|
|
518
|
+
Lean's own result JSON, chart, headline table, and full stats all
|
|
519
|
+
overwritten, never hand-edited, so nothing here goes stale relative to your
|
|
520
|
+
last backtest.
|
|
521
|
+
|
|
522
|
+
### Monte Carlo Simulation
|
|
523
|
+
|
|
524
|
+
Monte Carlo simulation testing layer (`aq evaluate --rank-book --monte-carlo`):
|
|
525
|
+
the offline rank book's daily net returns are stationary-block-bootstrapped
|
|
526
|
+
into thousands of alternative equity histories — risk stated as a
|
|
527
|
+
distribution, not a single path. Auto-refreshes with every `aq evaluate`
|
|
528
|
+
run; the **red line** is the average of all generated runs, and the faint
|
|
529
|
+
**light blue semi-transparent lines** are each individual bootstrap run
|
|
530
|
+
showing the full range of possible outcomes.
|
|
531
|
+
|
|
532
|
+
<!-- AQ:MONTECARLO_START -->
|
|
533
|
+
1000-run stationary-block bootstrap of the offline rank book's daily net returns
|
|
534
|
+
(method=`block`, block=20d, seed=42). The red line marks the
|
|
535
|
+
average of all generated runs; faint lines are individual resampled histories.
|
|
536
|
+
|
|
537
|
+

|
|
538
|
+
|
|
539
|
+
| Metric | p5 | p50 | p95 |
|
|
540
|
+
|---|---|---|---|
|
|
541
|
+
| Final return | -1.997911% | 9.383797% | 21.449402% |
|
|
542
|
+
| Annualized Sharpe | -0.180362 | 0.996916 | 2.519184 |
|
|
543
|
+
| Max drawdown | 2.055742% | 4.782714% | 9.108808% |
|
|
544
|
+
| P(negative total return): **0.095** |||
|
|
545
|
+
<!-- AQ:MONTECARLO_END -->
|
|
546
|
+
|
|
547
|
+
<!-- AQ:MONTECARLO_FULL_STATS_START -->
|
|
548
|
+
Deeper distribution statistics across all Monte Carlo runs:
|
|
549
|
+
|
|
550
|
+
**Final total return (%)**
|
|
551
|
+
|
|
552
|
+
| p5 | p25 | p50 | p75 | p95 |
|
|
553
|
+
|---|---|---|---|---|
|
|
554
|
+
| -1.997911 | 4.942038 | 9.383797 | 14.249014 | 21.449402 |
|
|
555
|
+
|
|
556
|
+
**Annualized Sharpe**
|
|
557
|
+
|
|
558
|
+
| p5 | p25 | p50 | p75 | p95 |
|
|
559
|
+
|---|---|---|---|---|
|
|
560
|
+
| -0.180362 | 0.524577 | 0.996916 | 1.547445 | 2.519184 |
|
|
561
|
+
|
|
562
|
+
**Max drawdown (%)**
|
|
563
|
+
|
|
564
|
+
| p5 | p25 | p50 | p75 | p95 |
|
|
565
|
+
|---|---|---|---|---|
|
|
566
|
+
| 2.055742 | 3.438596 | 4.782714 | 6.090146 | 9.108808 |
|
|
567
|
+
|
|
568
|
+
- Best run total return: **35.2395%**
|
|
569
|
+
- Worst run total return: **-12.1537%**
|
|
570
|
+
- Probability of a negative total return: **0.095**
|
|
571
|
+
- Config: n_runs=1000, method=`block`, block_size=20d, seed=42 (pinned - the section only changes when underlying results change)
|
|
572
|
+
|
|
573
|
+
The red line in the chart above is the element-wise AVERAGE of all run equity curves; faint blue lines are the individual bootstrap histories.
|
|
574
|
+
<!-- AQ:MONTECARLO_FULL_STATS_END -->
|
|
575
|
+
|
|
576
|
+
### Offline Evaluation
|
|
577
|
+
|
|
578
|
+
Rank-book simulation (`aq evaluate --all`) net of costs, run over the full
|
|
579
|
+
backtest split against the currently active `ml/` models — the same
|
|
580
|
+
inference path and book-construction logic `main.py` uses live, not a
|
|
581
|
+
separately re-derived approximation. Two models feed the live ensemble
|
|
582
|
+
(`multitask`, `sequence`); both are shown side by side.
|
|
583
|
+
|
|
584
|
+
<!-- AQ:EVAL_START -->
|
|
585
|
+
| Metric | Multitask | Sequence |
|
|
586
|
+
|---|---|---|
|
|
587
|
+
| Gross Sharpe | 1.709 | 1.039 |
|
|
588
|
+
| Net Sharpe | 1.681 | 0.997 |
|
|
589
|
+
| Net total return | 10.61% | 9.68% |
|
|
590
|
+
| Max drawdown | -2.63% | -6.01% |
|
|
591
|
+
| Annualized turnover | 1.32 | 3.03 |
|
|
592
|
+
| Cost drag (bps/yr) | 7.9 | 18.2 |
|
|
593
|
+
| Capacity (USD) | 4,396,756 | 3,901,573 |
|
|
594
|
+
|
|
595
|
+
_Backtest split, full history. Last updated 2026-08-26 14:58 UTC (auto-generated by `aq evaluate --all`)._
|
|
596
|
+
<!-- AQ:EVAL_END -->
|
|
597
|
+
|
|
598
|
+
<details>
|
|
599
|
+
<summary><strong>Full offline evaluation statistics</strong> (rank book detail, capacity sweep by book breadth, cost stress test at 1x/2x/3x)</summary>
|
|
600
|
+
|
|
601
|
+
<!-- AQ:EVAL_FULL_STATS_START -->
|
|
602
|
+
**Multitask model**
|
|
603
|
+
|
|
604
|
+
| Metric | Value |
|
|
605
|
+
|---|---|
|
|
606
|
+
| gross_sharpe | 1.7091656727193105 |
|
|
607
|
+
| net_sharpe | 1.6805366401698374 |
|
|
608
|
+
| gross_total_return | 0.10806403794373853 |
|
|
609
|
+
| net_total_return | 0.10610463795202896 |
|
|
610
|
+
| net_max_drawdown | -0.026348856087680117 |
|
|
611
|
+
| annualized_turnover | 1.3163321186881831 |
|
|
612
|
+
| cost_drag_annual_bps | 7.8979927121291 |
|
|
613
|
+
| num_rebalances | 57 |
|
|
614
|
+
| num_dates_used | 565 |
|
|
615
|
+
| mean_names_long | 6.0 |
|
|
616
|
+
| mean_names_short | 6.0 |
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
Capacity: $4,396,756 (binding: BNO)
|
|
620
|
+
|
|
621
|
+
| top_n | Net Sharpe |
|
|
622
|
+
|---|---|
|
|
623
|
+
| 3 | 1.4791 |
|
|
624
|
+
| 6 | 1.6805 |
|
|
625
|
+
| 10 | 1.3894 |
|
|
626
|
+
| 15 | 1.7372 |
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
| Cost multiplier | Gross Sharpe | Net Sharpe | Cost drag (bps/yr) |
|
|
630
|
+
|---|---|---|---|
|
|
631
|
+
| 1.0x | 1.7092 | 1.6805 | 7.9 |
|
|
632
|
+
| 2.0x | 1.7092 | 1.6518 | 15.8 |
|
|
633
|
+
| 3.0x | 1.7092 | 1.6229 | 23.7 |
|
|
634
|
+
|
|
635
|
+
**Sequence model**
|
|
636
|
+
|
|
637
|
+
| Metric | Value |
|
|
638
|
+
|---|---|
|
|
639
|
+
| gross_sharpe | 1.0394716272052569 |
|
|
640
|
+
| net_sharpe | 0.9967165310570855 |
|
|
641
|
+
| gross_total_return | 0.10125475448372612 |
|
|
642
|
+
| net_total_return | 0.09677581003746671 |
|
|
643
|
+
| net_max_drawdown | -0.06005969882208184 |
|
|
644
|
+
| annualized_turnover | 3.030861810755615 |
|
|
645
|
+
| cost_drag_annual_bps | 18.1851708645337 |
|
|
646
|
+
| num_rebalances | 57 |
|
|
647
|
+
| num_dates_used | 565 |
|
|
648
|
+
| mean_names_long | 6.0 |
|
|
649
|
+
| mean_names_short | 6.0 |
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
Capacity: $3,901,573 (binding: BWX)
|
|
653
|
+
|
|
654
|
+
| top_n | Net Sharpe |
|
|
655
|
+
|---|---|
|
|
656
|
+
| 3 | 0.6791 |
|
|
657
|
+
| 6 | 0.9967 |
|
|
658
|
+
| 10 | 1.3030 |
|
|
659
|
+
| 15 | 1.1981 |
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
| Cost multiplier | Gross Sharpe | Net Sharpe | Cost drag (bps/yr) |
|
|
663
|
+
|---|---|---|---|
|
|
664
|
+
| 1.0x | 1.0395 | 0.9967 | 18.2 |
|
|
665
|
+
| 2.0x | 1.0395 | 0.9538 | 36.4 |
|
|
666
|
+
| 3.0x | 1.0395 | 0.9108 | 54.6 |
|
|
667
|
+
<!-- AQ:EVAL_FULL_STATS_END -->
|
|
668
|
+
|
|
669
|
+
</details>
|
|
670
|
+
|
|
671
|
+
Regenerated on every `aq evaluate` run
|
|
672
|
+
([`generate_evaluation_report.py`](generate_evaluation_report.py)) from
|
|
673
|
+
`ml/evaluation/*.json`.
|
|
674
|
+
|
|
675
|
+
### Benchmark Comparison
|
|
676
|
+
|
|
677
|
+
The rank book's edge stated relative to benchmarks rather than in
|
|
678
|
+
isolation (`aq evaluate --benchmarks`, included in `--all`): naive
|
|
679
|
+
strategy baselines (momentum top-N/mean-reversion/random-entry,
|
|
680
|
+
`evaluation/benchmark_comparison.py`) and public benchmarks (buy-and-hold
|
|
681
|
+
SPY, daily-rebalanced 60/40 SPY-TLT, `evaluation/public_benchmarks.py`) —
|
|
682
|
+
all computed over the SAME dataset window/split as the rank-book
|
|
683
|
+
simulation, with an identical Sharpe formula, so every row is directly
|
|
684
|
+
comparable. A benchmark that can't compute (e.g. a universe without
|
|
685
|
+
SPY/TLT) shows its skip reason instead of fabricated numbers.
|
|
686
|
+
|
|
687
|
+
<!-- AQ:BENCHMARK_START -->
|
|
688
|
+
| Strategy | Net Sharpe | Total return | Note |
|
|
689
|
+
|---|---|---|---|
|
|
690
|
+
| **Rank book (sequence)** | 0.997 | 9.68% | the strategy being benchmarked |
|
|
691
|
+
| **Rank book (multitask)** | 1.681 | 10.61% | the strategy being benchmarked |
|
|
692
|
+
| momentum | 0.476 | 28.83% | naive strategy baseline |
|
|
693
|
+
| mean_reversion | -0.119 | -20.96% | naive strategy baseline |
|
|
694
|
+
| random_entry | -0.217 | -8.48% | naive strategy baseline |
|
|
695
|
+
| sp500 | 1.214 | 56.39% | public benchmark |
|
|
696
|
+
| 60_40 | 1.624 | 43.06% | public benchmark |
|
|
697
|
+
|
|
698
|
+
_Same dataset window/split (`backtest`) as the rank-book simulation above; Sharpe formula identical across every row. Last updated 2026-08-26 14:58 UTC (auto-generated by `aq evaluate --benchmarks`)._
|
|
699
|
+
<!-- AQ:BENCHMARK_END -->
|
|
700
|
+
|
|
701
|
+
### Walk-Forward Training/Testing
|
|
702
|
+
|
|
703
|
+
Out-of-sample stability check: the full training pipeline (dataset build →
|
|
704
|
+
baseline/experts → multitask → sequence → net-performance simulation) run
|
|
705
|
+
independently on several expanding/rolling historical windows, so each
|
|
706
|
+
window's "backtest" split is data the model closest to it never trained
|
|
707
|
+
on — the closest thing this project has to genuine walk-forward validation,
|
|
708
|
+
distinct from the single final model shown above.
|
|
709
|
+
|
|
710
|
+
<!-- AQ:WALKFORWARD_START -->
|
|
711
|
+
| Metric | Mean | 95% CI | Stable? |
|
|
712
|
+
|---|---|---|---|
|
|
713
|
+
| backtest_mcc | 0.0221 | [0.0082, 0.0342] | yes |
|
|
714
|
+
| rank_5d_ic | 0.0693 | [0.0494, 0.0862] | yes |
|
|
715
|
+
| rank_20d_ic | 0.0849 | [0.0404, 0.1173] | yes |
|
|
716
|
+
| residual_rank_20d_ic | 0.0112 | [-0.0131, 0.0318] | yes |
|
|
717
|
+
| net_sharpe (per-window) | 0.654 | — | 5/6 windows positive |
|
|
718
|
+
|
|
719
|
+
6 expanding/rolling windows, run `walk-forward-a9cd8cfb-24f0-4963-b80b-8ee299df2613`. Last updated 2026-08-26 14:58 UTC (auto-generated by `aq train --walk-forward`).
|
|
720
|
+
<!-- AQ:WALKFORWARD_END -->
|
|
721
|
+
|
|
722
|
+
<details>
|
|
723
|
+
<summary><strong>Full walk-forward statistics</strong> (per-window breakdown)</summary>
|
|
724
|
+
|
|
725
|
+
<!-- AQ:WALKFORWARD_FULL_STATS_START -->
|
|
726
|
+
| Window | Backtest period | Model | Backtest MCC | Gross Sharpe | Net Sharpe | Net return | Max DD | Turnover |
|
|
727
|
+
|---|---|---|---|---|---|---|---|---|
|
|
728
|
+
| 0 | 2018-11-30 → 2019-11-29 | sequence | -0.0056 | 1.706 | 1.603 | 2.98% | -2.27% | 3.46x |
|
|
729
|
+
| 1 | 2019-02-28 → 2020-02-27 | sequence | 0.0040 | 0.073 | 0.029 | 0.03% | -1.46% | 0.92x |
|
|
730
|
+
| 2 | 2019-05-29 → 2020-05-27 | sequence | 0.0300 | 0.545 | 0.468 | 2.25% | -4.92% | 6.47x |
|
|
731
|
+
| 3 | 2019-08-27 → 2020-08-25 | sequence | 0.0262 | 0.905 | 0.875 | 2.63% | -2.68% | 1.44x |
|
|
732
|
+
| 4 | 2019-11-25 → 2020-11-23 | multitask | 0.0402 | -0.220 | -0.261 | -1.15% | -5.16% | 2.73x |
|
|
733
|
+
| 5 | 2020-02-23 → 2021-02-21 | multitask | 0.0376 | 1.251 | 1.212 | 6.59% | -4.39% | 3.44x |
|
|
734
|
+
<!-- AQ:WALKFORWARD_FULL_STATS_END -->
|
|
735
|
+
|
|
736
|
+
</details>
|
|
737
|
+
|
|
738
|
+
Regenerated on every `aq evaluate` run once a walk-forward summary exists on
|
|
739
|
+
disk ([`generate_evaluation_report.py`](generate_evaluation_report.py)) from
|
|
740
|
+
the newest `ml/versions/walk-forward-*/walk_forward_summary.json`.
|
|
741
|
+
|
|
742
|
+
### Other Metrics
|
|
743
|
+
|
|
744
|
+
Cross-checks between the real Lean backtest above and the offline tools —
|
|
745
|
+
the single most important comparison on this page, since offline numbers
|
|
746
|
+
have repeatedly run far more optimistic than real ones
|
|
747
|
+
(see [`development/Problems.md`](development/Problems.md) #90-#98).
|
|
748
|
+
|
|
749
|
+
<!-- AQ:OTHER_METRICS_START -->
|
|
750
|
+
**Sharpe: real Lean backtest vs. offline estimates** — offline numbers are consistently more optimistic than the real backtest; treat the gap itself as the headline number, not either side alone.
|
|
751
|
+
|
|
752
|
+
| Source | Sharpe |
|
|
753
|
+
|---|---|
|
|
754
|
+
| Real Lean backtest (2019-01-01 to 2021-04-02) | -1.832 |
|
|
755
|
+
| Offline evaluation — sequence model (full backtest split) | 0.997 |
|
|
756
|
+
| Offline evaluation — multitask model (full backtest split) | 1.681 |
|
|
757
|
+
| Walk-forward mean (out-of-sample, per-window) | 0.654 |
|
|
758
|
+
| Gap: sequence offline − real Lean | +2.829 |
|
|
759
|
+
| Gap: walk-forward − real Lean | +2.486 |
|
|
760
|
+
|
|
761
|
+
**Book-history reconciliation** (real Lean selections vs. a fresh offline re-derivation of the same dates)
|
|
762
|
+
|
|
763
|
+
| Metric | Value |
|
|
764
|
+
|---|---|
|
|
765
|
+
| Dates reconciled | 56 |
|
|
766
|
+
| Exact matches | 0 |
|
|
767
|
+
| Mean overlap fraction | 56.88% |
|
|
768
|
+
| Mean raw-score delta | 0.0185 |
|
|
769
|
+
| Replay mode | replay_hysteresis |
|
|
770
|
+
|
|
771
|
+
Book-member decision outcomes (672 total, real Lean run):
|
|
772
|
+
|
|
773
|
+
| Action | Count | Share |
|
|
774
|
+
|---|---|---|
|
|
775
|
+
| reduce_risk | 375 | 55.8% |
|
|
776
|
+
| simulate | 184 | 27.4% |
|
|
777
|
+
| trade | 112 | 16.7% |
|
|
778
|
+
| observe | 1 | 0.1% |
|
|
779
|
+
|
|
780
|
+
**Kill-switch: real trips vs. offline replay estimate**
|
|
781
|
+
|
|
782
|
+
| Source | Trips | Locked days |
|
|
783
|
+
|---|---|---|
|
|
784
|
+
| Real Lean backtest (2019-01-01 to 2021-04-02) | _not measurable from a standalone backtest (see Disclaimer)_ | — |
|
|
785
|
+
| Offline replay (approximation, see Disclaimer) | 78 | 73.5% |
|
|
786
|
+
|
|
787
|
+
_Last updated 2026-08-26 14:58 UTC (auto-generated by `aq evaluate`)._
|
|
788
|
+
<!-- AQ:OTHER_METRICS_END -->
|
|
789
|
+
|
|
790
|
+
Regenerated on every `aq evaluate` run
|
|
791
|
+
([`generate_evaluation_report.py`](generate_evaluation_report.py)) from
|
|
792
|
+
whatever combination of the above has actually been run.
|
|
793
|
+
|
|
794
|
+
### Disclaimer
|
|
795
|
+
|
|
796
|
+
- **Offline numbers are not a live-performance forecast.** This project has
|
|
797
|
+
repeatedly seen offline Sharpe run 2-6+ points more optimistic than the
|
|
798
|
+
matching real Lean backtest (Problems.md #90-#95) — read every number
|
|
799
|
+
above as a relative signal (better/worse than last time), not an absolute
|
|
800
|
+
prediction.
|
|
801
|
+
- **The Lean backtest is the only ground truth on this page.** Everything
|
|
802
|
+
else (offline evaluation, walk-forward, reconciliation, kill-switch
|
|
803
|
+
replay) is a deliberately approximate offline reconstruction, built
|
|
804
|
+
because a real Lean run is expensive to iterate on, not because it's
|
|
805
|
+
equally trustworthy.
|
|
806
|
+
- **Walk-forward windows train on less data than the final model.** Each
|
|
807
|
+
window sees only the history up to its own cutoff, so its numbers are
|
|
808
|
+
structurally more conservative than the single final model's — that's
|
|
809
|
+
the point (a stability check), not a bug.
|
|
810
|
+
- **The kill-switch replay is a known over-estimate.** It models only the
|
|
811
|
+
cheapest-to-reconstruct triggers and no bypass flags, so its trip count
|
|
812
|
+
and locked-day fraction should be read as a pessimistic upper bound, not
|
|
813
|
+
a prediction.
|
|
814
|
+
- **The real kill-switch trip count is not measurable from a standalone
|
|
815
|
+
backtest.** The trip-audit event is pushed only to a Redis Stream
|
|
816
|
+
(`audit/redis_queue.py`), never to the Lean text log, and fails silently
|
|
817
|
+
with no Redis reachable — a prior version of this page showed "0 real
|
|
818
|
+
trips" as if that were a genuine finding; it wasn't (that was always the
|
|
819
|
+
value regardless of how many trips actually occurred), and has been
|
|
820
|
+
corrected.
|
|
821
|
+
- **Book-history reconciliation needs a real backtest log to run against**
|
|
822
|
+
(`phase_v2.diagnostics.book_history.enabled`) and compares offline's
|
|
823
|
+
from-scratch re-derivation against live's actual (path-dependent,
|
|
824
|
+
hysteresis-carrying) selections — a low overlap fraction does not by
|
|
825
|
+
itself mean either side is "wrong," only that they diverged.
|
|
826
|
+
- **Capacity estimates are theoretical**, derived from a participation-rate
|
|
827
|
+
cap against historical volume, not validated against any real fill data
|
|
828
|
+
at that size.
|
|
829
|
+
|
|
830
|
+
## Test Suite
|
|
831
|
+
|
|
832
|
+
<!-- AQ:TEST_COUNT_START -->2929<!-- AQ:TEST_COUNT_END --> tests, one file per source module, run via:
|
|
833
|
+
|
|
834
|
+
```powershell
|
|
835
|
+
aq test
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
which, like the backtest chart above, automatically keeps the badge at
|
|
839
|
+
the top of this README in sync with the real pass count every time you run
|
|
840
|
+
it. See [`tests/README.md`](tests/README.md) for the suite's conventions.
|
|
841
|
+
|
|
842
|
+
## CLI Reference
|
|
843
|
+
|
|
844
|
+
Get the `aq` command from PyPI (`pip install aether-quant`, see
|
|
845
|
+
[Download](#download)) or, for local development, straight from source
|
|
846
|
+
(`pip install -e .`). Either way, `aq --help` gives the full command list.
|
|
847
|
+
Every command except `aq trade-lock` and `aq fetch` is a thin `subprocess`
|
|
848
|
+
wrapper around a command already documented elsewhere in this README:
|
|
849
|
+
|
|
850
|
+
#### `aq train`
|
|
851
|
+
```text
|
|
852
|
+
aq train [--dataset-only|--init-only|--experts-only|--gating-only|--multitask-only|--sequence-only|--topology-only|--strategy-selector-only|--rl-sizing-only|--walk-forward] [--step-days N] [--mode rolling|expanding] [--seed N] [--ranking-objective mse|soft_spearman|listnet]
|
|
853
|
+
```
|
|
854
|
+
**Builds the dataset and trains the models** (`train.py`). With no flags,
|
|
855
|
+
trains everything (baseline + experts + gating + multitask + sequence) and
|
|
856
|
+
installs it into the active `ml/` folder.
|
|
857
|
+
|
|
858
|
+
Scope flags (each trains just one piece, installs straight into `ml/`):
|
|
859
|
+
- `--dataset-only` / `--init-only`: (re)build the dataset / refresh the data inventory, no training.
|
|
860
|
+
- `--experts-only`: the 4 expert models (see `moe/README.md`).
|
|
861
|
+
- `--gating-only`: the learned gating blend (`train_gating.py`, `moe/README.md`).
|
|
862
|
+
- `--multitask-only`: the joint direction/magnitude/volatility + rank model (`train_multitask.py`, `risk/README.md`).
|
|
863
|
+
- `--sequence-only`: the causal-TCN sequence encoder (`train_sequence.py`, `inference/README.md`).
|
|
864
|
+
- `--topology-only`: the learned topology overlay (`train_topology.py`, `topology/README.md`). Different data source from every other flag here — fits over realized trading outcomes pulled from Postgres, needs `phase_v2.topology_learning.training.min_training_events` (default 500) accumulated events, and correctly no-ops ("skipped, active `ml/` left unchanged") rather than training on too little data.
|
|
865
|
+
- `--strategy-selector-only`: the options multi-leg strategy-selector model (`train_strategy_selector.py`, V4.7) — needs real option outcome events from Postgres, so it no-ops until options actually trade (see Known Limitations).
|
|
866
|
+
- `--rl-sizing-only`: the offline contextual-bandit sizing overlay (`train_rl_sizing.py`, default off at runtime) — reads `ml/datasets/*.csv` + a completed multitask model, not Postgres.
|
|
867
|
+
|
|
868
|
+
Walk-forward (diagnostic, **never** touches active `ml/`):
|
|
869
|
+
- `--walk-forward`: runs the whole pipeline once per rolling/expanding window instead of on the fixed `phase1.windows`; each window writes to `ml/versions/<run-id>/window_<i>/`. Trains multitask/sequence per window too by default (`phase_v2.retraining.walk_forward.train_multitask`/`train_sequence`, both `true`) — `--include-multitask`/`--include-sequence` only matter if you've turned either off in `config.json` and want it back on for one run; `--metrics` picks which dotted metric paths get tracked across windows.
|
|
870
|
+
- `--step-days N` / `--mode rolling|expanding`: override `phase_v2.retraining.walk_forward`'s defaults. See `retraining/README.md`.
|
|
871
|
+
- `--seed N` / `--ranking-objective mse|soft_spearman|listnet`: one-run overrides for `--multitask-only`/`--sequence-only`, for seed-ensembling or A/B-testing the ranking loss without editing `config.json` (default: `soft_spearman`, confirmed to beat MSE in a controlled comparison).
|
|
872
|
+
|
|
873
|
+
#### `aq test`
|
|
874
|
+
```text
|
|
875
|
+
aq test [--lean|--full] [--parallel] [--ruff] [--cli] [--risk] [--portfolio] [--features]
|
|
876
|
+
[--data-pipeline] [--webui] [--ml] [--retraining] [--notifications]
|
|
877
|
+
[--storage] [--live] [--audit] [--evaluation]
|
|
878
|
+
```
|
|
879
|
+
**Runs the pytest suite** and refreshes this README's test badge (only on a
|
|
880
|
+
full, unfiltered run, a filtered run's count is a subset, never written to
|
|
881
|
+
the badge).
|
|
882
|
+
|
|
883
|
+
- `--ruff`: (V5.3.10) run `ruff check .` **before** pytest — a lint failure fails fast without paying the full suite's wall-clock. Mirrors CI's python-lint job (single source of truth in `aq_cli.py::cmd_test`).
|
|
884
|
+
- `--lean` / `--full`: also run the real `lean backtest .` integration test (`tests/test_lean_backtest_ml_coverage.py`, over an hour). Excluded by default since its own `skipif` only checks whether Lean is *installed* (it always is here), so it would otherwise run every time.
|
|
885
|
+
- `--parallel`: run via `pytest-xdist` (`-n auto`). Off by default: multiple workers each importing PyTorch is a real OOM risk on low-memory machines.
|
|
886
|
+
- Subsystem filters, `--cli`, `--risk`, `--portfolio`, `--features`, `--data-pipeline`, `--webui`, `--ml`, `--retraining`, `--notifications`, `--storage`, `--live`, `--audit`, `--evaluation` restrict the run to just those test files (combinable). `aq test --help` lists the exact file mapping.
|
|
887
|
+
|
|
888
|
+
#### `aq backtest`
|
|
889
|
+
```text
|
|
890
|
+
aq backtest [--image IMAGE]
|
|
891
|
+
```
|
|
892
|
+
**Runs `lean backtest .`** and refreshes this README's [Backtest Results](#backtest-results) section from the real Lean output. Requires Docker Desktop running.
|
|
893
|
+
|
|
894
|
+
- **Default:** `aq` builds `aether-quant-lean:17900` once from the pinned `quantconnect/lean:17900` base and installs the Redis runtime dependency inside that image. This avoids Lean CLI's Windows temporary-`requirements.txt` bind mount.
|
|
895
|
+
- `--image IMAGE`: deliberately use another engine image. The default is the local project image, not the mutable `:latest` tag.
|
|
896
|
+
|
|
897
|
+
#### `aq profile`
|
|
898
|
+
```text
|
|
899
|
+
aq profile [--iterations N] [--sort cumulative] [--batched] [--symbols-per-bar N] [--parallel] [--pool-workers N] [--no-gc] [--bucket-report]
|
|
900
|
+
aq profile [--iterations N] [--sort cumulative] [--regime] [--topology] [--topology-cached] [--learned-topology] [--liquidity] [--gating] [--analyzer] [--indicators] [--options]
|
|
901
|
+
```
|
|
902
|
+
**Profiles the per-bar hot path** without needing a real backtest (which
|
|
903
|
+
takes over an hour), reports a `pstats` breakdown plus wall-clock
|
|
904
|
+
tail-latency percentiles (p50/p95/p99/max).
|
|
905
|
+
|
|
906
|
+
- **Default (no subsystem flag)**: profiles the inference path (`inference/exported_model.py`) against real exported weights, writing to `scripts/profile_inference_output.txt`. Add `--batched` to profile the optimized production path (precomputed weight/stack caches, plus the sequence-encoder symbol-batching comparison, V4.9) instead of a per-expert loop. `--symbols-per-bar N` (default 74) controls the batching group size for both `--batched`'s sequence comparison and `--parallel` below. `--parallel` (V4.9) runs a real `ProcessPoolExecutor` benchmark of `inference/parallel_inference.py`'s `run_symbol_inference()` against a sequential baseline, answering that module's own never-measured IPC/pickling break-even question (`--pool-workers N`, default 4).
|
|
907
|
+
- **Subsystem flags**: `--regime`, `--topology`, `--learned-topology`, `--liquidity`, `--gating`, `--analyzer`, `--indicators`, `--options` (V4.9 — `risk/asset_class_router.py::route_multi_leg_option_sizing()` end-to-end) profile the per-bar subsystems inference profiling never covered (combinable, e.g. `--regime --gating`). Writes to `scripts/profile_subsystems_output.txt`. `--topology-cached` profiles `build_market_topology()`'s correlation-stability embedding cache (`phase_v2.topology.cache_enabled`, Problems.md #36) specifically — needs slowly-drifting synthetic data, since `--topology`'s independent-per-iteration random returns can never show the cache's benefit.
|
|
908
|
+
- `--iterations N`: default 10000 for inference, 200 for subsystems (`build_market_topology()` alone costs ~500-600ms/call, so 10k iterations would take over an hour). `--batched`/`--parallel` with a subsystem flag is rejected — batching/pooling is meaningless for those pure functions.
|
|
909
|
+
|
|
910
|
+
Why this exists: it found `build_market_topology()`'s per-bar cost rivaling
|
|
911
|
+
the *entire* inference step, and drove a combined −89.2% reduction (weight
|
|
912
|
+
caching, `_conv1d_causal` vectorization, expert-loop batching). See
|
|
913
|
+
`development/Problems.md` #36. `_build_model_input()` itself isn't directly
|
|
914
|
+
profiled (it reads `self.*` state, not cleanly synthesizable); `--indicators`
|
|
915
|
+
covers its pure primitives instead.
|
|
916
|
+
|
|
917
|
+
#### `aq report`
|
|
918
|
+
```text
|
|
919
|
+
aq report <backtest-folder> <result-id>
|
|
920
|
+
```
|
|
921
|
+
Generates Lean's own HTML backtest report (trade blotter, standard Lean
|
|
922
|
+
charts) at `backtests/<backtest-folder>/report.html`.
|
|
923
|
+
|
|
924
|
+
#### `aq api`
|
|
925
|
+
```text
|
|
926
|
+
aq api
|
|
927
|
+
```
|
|
928
|
+
Starts the FastAPI monitoring server on `:8001`.
|
|
929
|
+
|
|
930
|
+
#### `aq webui`
|
|
931
|
+
```text
|
|
932
|
+
aq webui
|
|
933
|
+
```
|
|
934
|
+
Starts the webui dev server (`npm run dev`).
|
|
935
|
+
|
|
936
|
+
#### `aq docker`
|
|
937
|
+
```text
|
|
938
|
+
aq docker up [--lean|--all]
|
|
939
|
+
aq docker build
|
|
940
|
+
```
|
|
941
|
+
`up` starts local infrastructure (default: Redis + PostgreSQL only).
|
|
942
|
+
`build` rebuilds the `aether-quant` app image.
|
|
943
|
+
|
|
944
|
+
#### `aq config`
|
|
945
|
+
```text
|
|
946
|
+
aq config [get <dotted.key>|set <dotted.key> <value>|keys [<dotted.prefix>]]
|
|
947
|
+
```
|
|
948
|
+
**Reads or edits `config.json` by dotted key path**, no manual file editing.
|
|
949
|
+
|
|
950
|
+
- `aq config` (bare): pretty-print the whole file.
|
|
951
|
+
- `aq config keys [<prefix>]`: list every leaf key path (find the right key in a deeply nested file).
|
|
952
|
+
- `aq config get <key>`: print one value (a scalar, or a whole nested section as JSON).
|
|
953
|
+
- `aq config set <key> <value>`: write it. The value is parsed as JSON first (`true`/`123`/`0.5`/`["a","b"]` become real types), falling back to a string. Every `set` backs up to `config.json.bak` and prints old → new; a type change (e.g. bool → string) warns but still writes, since this gives full access to every key.
|
|
954
|
+
- `aq config preset --list|--show <name>|--apply <name> [--dry-run]`: applies a whole named bundle of dotted keys at once (`moderate`/`aggressive`, e.g. book size, liquidity thresholds, minimum net edge) — validates every key resolves before writing anything, so a partial config never lands. `aq evaluate --preset <name>` overlays the same bundle in memory only, for a free offline A/B before committing to one.
|
|
955
|
+
|
|
956
|
+
#### `aq lean`
|
|
957
|
+
```text
|
|
958
|
+
aq lean [get <dotted.key>|set <dotted.key> <value>|keys [<dotted.prefix>]]
|
|
959
|
+
```
|
|
960
|
+
The exact same `get`/`set`/`keys` tool as `aq config`, just pointed at
|
|
961
|
+
`lean.json` (the QuantConnect Lean CLI's own config file, broker
|
|
962
|
+
credentials, environments, data providers) instead. `aq lean set
|
|
963
|
+
ib-trading-mode live`, `aq lean keys environments.live-paper`, etc.
|
|
964
|
+
|
|
965
|
+
#### `aq retrain`
|
|
966
|
+
```text
|
|
967
|
+
aq retrain <plan|train|train_topology|train_gating|train_multitask|train_sequence|train_strategy_selector|validate|backtest|commit|promote|rollback|auto-rollback|status> [...]
|
|
968
|
+
```
|
|
969
|
+
**Dispatches to `python -m retraining.orchestrator <stage> ...`** for a
|
|
970
|
+
single manual pipeline stage, independent of the continuous worker.
|
|
971
|
+
|
|
972
|
+
Stages (each usable standalone, in the order the worker itself runs them):
|
|
973
|
+
- `plan`: decides whether a retraining cycle should even start — highest-priority eligible trigger, minimum observations, cooldown, daily cap.
|
|
974
|
+
- `train`: trains a new candidate model in isolation, never touching the active `ml/` files.
|
|
975
|
+
- `train_topology` / `train_gating` / `train_multitask` / `train_sequence` / `train_strategy_selector`: granular single-model variants of `train`, useful for retrying just one failed stage without re-running the whole pipeline.
|
|
976
|
+
- `validate`: candidate-vs-active comparison (drawdown, Sharpe, validation-loss stability, overfitting gap, plus the ranking-quality/net-performance gates — see `development/architecture.md`'s Cost-Aware Cross-Sectional Ranking Contract).
|
|
977
|
+
- `backtest`: a 3-way active/candidate/buy-and-hold comparison, plus an optional real Lean backtest if `lean` is on `PATH`.
|
|
978
|
+
- `commit`: hashes and pushes the candidate's artifacts to Aether-Vault.
|
|
979
|
+
- `promote`: makes a validated, committed candidate the active model, with rollback always available.
|
|
980
|
+
- `rollback --to-version-id <id>`: manually restores a previous version as active.
|
|
981
|
+
- `auto-rollback --status`: **read-only diagnostic**, not a mutation — reports whether the currently active model would be rolled back right now (and why/why not) without acting. The real enforcement runs inside the retraining worker's own poll loop, opt-in via `phase_v2.retraining.auto_rollback.enabled` (`false` by default — an automatic weight swap is the single most consequential action this system can take).
|
|
982
|
+
- `status`: prints the current retraining status view (same content as `visualization/grafana/retraining_status.json`).
|
|
983
|
+
|
|
984
|
+
#### `aq paper-readiness`
|
|
985
|
+
```text
|
|
986
|
+
aq paper-readiness
|
|
987
|
+
```
|
|
988
|
+
**Wraps `python -m execution.paper_readiness_report`** — a human-triggered
|
|
989
|
+
gate to run before switching `phase_v2.runtime.mode` to `"paper"`. Checks
|
|
990
|
+
broker config presence (`evaluate_paper_broker_config()`) and observation-mode
|
|
991
|
+
health (`evaluate_observation_readiness()` — minimum observation count,
|
|
992
|
+
`simulated_sharpe`/`simulated_max_drawdown` floors, no dominant
|
|
993
|
+
`rejected_by_reason`); writes `visualization/grafana/paper_readiness_report.json`,
|
|
994
|
+
also served at `/api/grafana/paper-readiness` and in `/api/state`.
|
|
995
|
+
|
|
996
|
+
#### `aq trade-lock`
|
|
997
|
+
```text
|
|
998
|
+
aq trade-lock --on|--off|--auto|--status
|
|
999
|
+
```
|
|
1000
|
+
**Manually overrides `main.py`'s sticky total-drawdown trade lock** (see
|
|
1001
|
+
`development/architecture.md`'s Manual Trade-Lock Override Contract).
|
|
1002
|
+
|
|
1003
|
+
- `--on`: force trading paused.
|
|
1004
|
+
- `--off`: force trading resumed — deliberately clears an otherwise-permanent lock.
|
|
1005
|
+
- `--auto`: return to fully automatic behavior.
|
|
1006
|
+
- `--status`: print the current override state.
|
|
1007
|
+
|
|
1008
|
+
#### `aq kill-switch`
|
|
1009
|
+
```text
|
|
1010
|
+
aq kill-switch --arm|--disarm|--auto|--status
|
|
1011
|
+
aq kill-switch --history [--limit N]
|
|
1012
|
+
```
|
|
1013
|
+
**Inspects and overrides the automated production kill switch**
|
|
1014
|
+
(`risk/kill_switch.py`) — the same override-file convention as
|
|
1015
|
+
`aq trade-lock` above, so the two switches can never disagree. A trip
|
|
1016
|
+
feeds `main.py`'s existing trade lock; it never creates a second one.
|
|
1017
|
+
|
|
1018
|
+
- `--arm`: force kill-switch evaluation on, even if `phase_v2.risk.kill_switch.enabled` is `false`.
|
|
1019
|
+
- `--disarm`: force kill-switch evaluation off, even if `enabled` is `true`.
|
|
1020
|
+
- `--auto`: defer entirely to `phase_v2.risk.kill_switch.enabled`.
|
|
1021
|
+
- `--status`: print the current override state.
|
|
1022
|
+
- `--history [--limit N]`: list past trips from the tamper-evident audit log (default 50 rows; needs `AETHER_POSTGRES_DSN`, same requirement as `aq audit-log` below).
|
|
1023
|
+
|
|
1024
|
+
#### `aq evaluate`
|
|
1025
|
+
```text
|
|
1026
|
+
aq evaluate --rank-book [--model sequence|multitask] [--head rank_20d] [--split backtest]
|
|
1027
|
+
aq evaluate --capacity | --stress | --calibrate-edge | --ablation [--variants a,b,c] | --all
|
|
1028
|
+
aq evaluate --calibrate-book-spread [--book-spread-percentile P]
|
|
1029
|
+
aq evaluate --calibrate-confidence-threshold [--confidence-threshold-percentile P]
|
|
1030
|
+
aq evaluate --calibrate-rolling-ic-floor [--rolling-ic-floor-percentile P]
|
|
1031
|
+
aq evaluate --reconcile-book-history [--book-history-path PATH] [--replay-hysteresis]
|
|
1032
|
+
[--reconcile-run-index N | --reconcile-all-runs]
|
|
1033
|
+
aq evaluate --reconcile-features --symbol TICKER [--book-history-path PATH]
|
|
1034
|
+
aq evaluate --monte-carlo [--mc-runs N] [--mc-block-size B] [--mc-seed S] [--mc-method block|iid]
|
|
1035
|
+
aq evaluate --benchmarks
|
|
1036
|
+
aq evaluate --replay-kill-switch
|
|
1037
|
+
aq evaluate --replay-rolling-ic-gate
|
|
1038
|
+
aq evaluate --simulate-limit-fills [--limit-fill-offset-sweep 0.5,1.0,2.0]
|
|
1039
|
+
aq evaluate --walk-forward-summary [--run-id <id>]
|
|
1040
|
+
aq evaluate [--preset aggressive|moderate] [--json]
|
|
1041
|
+
```
|
|
1042
|
+
**Runs the offline, cost-aware rank-book simulator** (`evaluation/`) — the
|
|
1043
|
+
torch-free mirror of the live decision path, so net Sharpe, turnover,
|
|
1044
|
+
capacity, and cost sensitivity can be measured without spending a Lean
|
|
1045
|
+
backtest.
|
|
1046
|
+
|
|
1047
|
+
- `--rank-book [--model sequence|multitask] [--head rank_20d] [--split backtest]`: simulate the constructed long/short book against realized returns for one model/head/dataset split — net/gross Sharpe, turnover, cost drag.
|
|
1048
|
+
- `--capacity`: sweep top-N breadth and estimate the participation-capped capacity ceiling.
|
|
1049
|
+
- `--stress`: re-run the simulation at 1x/2x/3x the configured cost.
|
|
1050
|
+
- `--calibrate-edge`: print an `edge_bps_per_rank_unit` calibrated from this split's realized rank-vs-return relationship — the one input `phase_v2.costs`'s net-edge gate needs before it can do anything (ships `enabled: false`/uncalibrated until this is run).
|
|
1051
|
+
- `--ablation [--variants a,b,c]`: isolate the contribution of neutrality, hysteresis, and the cost model by re-running the simulation with each turned off in turn (mechanisms with no offline equivalent, like gating or topology sizing, report an explicit "not measurable this way" result rather than a fabricated number). Not included in `--all`.
|
|
1052
|
+
- `--calibrate-book-spread [--book-spread-percentile P]`: print a `min_rank_confidence_spread` calibrated from this split's real per-date raw-score dispersion (default percentile 0.10) — the same "percentile of a real, achieved distribution" discipline as `--calibrate-edge`. Not included in `--all`.
|
|
1053
|
+
- `--calibrate-confidence-threshold [--confidence-threshold-percentile P]`: print a `min_confidence_to_trade` (and, when book-selection data is available, a separate book-selected threshold) calibrated from this split's real confidence-vs-forward-return relationship. Not included in `--all`.
|
|
1054
|
+
- `--calibrate-rolling-ic-floor [--rolling-ic-floor-percentile P]`: (V5.3.5) print a `phase_v2.rolling_ic_gate.min_rolling_mean_ic` calibrated from this split's real walk-forward rolling trailing-IC distribution (`portfolio/rolling_ic_gate.py`'s own aggregation, no lookahead). Not included in `--all`.
|
|
1055
|
+
- `--reconcile-book-history [--book-history-path PATH] [--replay-hysteresis] [--reconcile-run-index N | --reconcile-all-runs]`: compare a real Lean backtest's logged book selections (`phase_v2.diagnostics.book_history`) against a fresh offline re-derivation — ground truth for diagnosing live-vs-offline divergence. `--replay-hysteresis` walks forward carrying held allocations the way `main.py`'s live book does; the log is cumulative across runs, so by default only the LATEST run segment reconciles — `--reconcile-run-index N` (0-indexed, -1 = most recent) picks one, `--reconcile-all-runs` does each independently. Not included in `--all`.
|
|
1056
|
+
- `--reconcile-features --symbol TICKER [--book-history-path PATH]`: (V5.3.5.3) diff ONE symbol's logged live feature values (the allowlist-bounded `feature_snapshot` field written when `phase_v2.diagnostics.book_history.include_feature_snapshot` is on) against `full_dataset.csv`'s same (ticker, date) rows — per-feature deltas, worst offenders first, aggregated into `ml/evaluation/feature_reconciliation.json`. The tool that either names the exact diverging feature behind a live-vs-offline mismatch or rules the lead out cleanly. Not included in `--all`.
|
|
1057
|
+
- `--monte-carlo [--mc-runs N] [--mc-block-size B] [--mc-seed S] [--mc-method block|iid]`: (V5.3.8) Monte Carlo simulation testing layer — stationary-block bootstraps the base rank-book run's daily net returns into N alternative equity histories and refreshes the README's Monte Carlo section: all-run curves chart with the red average line + foldable deep-stat tables (return/Sharpe/maxDD percentiles, loss probability). Pinned seed by default so the README only changes when underlying results change. Implies the base `--rank-book` simulation; not included in `--all`.
|
|
1058
|
+
- `--benchmarks`: (V5.4.4) run every benchmark baseline over the SAME dataset window/split as the rank book — the momentum/mean-reversion/random-entry naive strategies plus the SP500 buy-and-hold and daily-rebalanced 60/40 SPY-TLT public benchmarks — writing `ml/evaluation/benchmark_comparison.json` and refreshing the README's Benchmark Comparison section. Included in `--all`.
|
|
1059
|
+
- `--replay-kill-switch`: (V5.2.8) day-by-day OFFLINE replay of the kill-switch + sticky trade-lock state machine against the rank book's own return series — an explicitly approximate estimate of how much of a run would have been locked out, without spending a real Lean backtest. See `development/Problems.md` #94 for the caveats. Not included in `--all`.
|
|
1060
|
+
- `--replay-rolling-ic-gate`: (V5.3.5) day-by-day, no-lookahead offline replay of the rolling-IC gate's engagement decision at the live rebalance cadence, with a per-era breakdown against the known bad eras — the pre-flight check before flipping `phase_v2.rolling_ic_gate.enabled` on. Not included in `--all`.
|
|
1061
|
+
- `--simulate-limit-fills [--limit-fill-offset-sweep 0.5,1.0,2.0]`: (V5.3.1) offline counterfactual estimate of how often a real limit order would fill vs. time out, using the dataset's own high/low bars and `phase_v2.limit_orders`' pricing/timeout config. See `development/Problems.md` #34/#96 for the caveats. Not included in `--all`.
|
|
1062
|
+
- `--all`: run `--rank-book`, `--capacity`, `--stress`, `--calibrate-edge` and `--benchmarks` together.
|
|
1063
|
+
- `--walk-forward-summary [--run-id <id>]`: print an already-written `ml/versions/walk-forward-*/walk_forward_summary.json` (default: the most recent run) — never runs training itself, run `aq train --walk-forward` first.
|
|
1064
|
+
- `--preset aggressive|moderate`: overlay a named config preset (`phase_v2.presets`) in memory only, never writes `config.json`, for a free A/B comparison — see `aq config preset` above.
|
|
1065
|
+
- `--json`: print the full report as JSON instead of a summary.
|
|
1066
|
+
|
|
1067
|
+
#### `aq fetch`
|
|
1068
|
+
```text
|
|
1069
|
+
aq fetch <crypto|stock> --ticker <TICKER> --start <YYYY-MM-DD> --end <YYYY-MM-DD> [--apply]
|
|
1070
|
+
aq fetch futures --ticker <TICKER> --start <YYYY-MM-DD> --end <YYYY-MM-DD> --expiry <YYYY-MM-DD> [--contract-month <YYYYMM>] [--family-ticker <ROOT>] [--apply]
|
|
1071
|
+
aq fetch options --ticker <TICKER> --start <YYYY-MM-DD> --end <YYYY-MM-DD> --expiry <YYYY-MM-DD> --strike <STRIKE> --right <call|put> [--family-ticker <ROOT>] [--apply]
|
|
1072
|
+
```
|
|
1073
|
+
**Backfills historical data for a new ticker** and (with `--apply`) registers
|
|
1074
|
+
it in `config.json`'s `phase1.universe.assets[]`, no manual editing.
|
|
1075
|
+
|
|
1076
|
+
- `crypto` / `stock`: fetch OHLCV from Yahoo Finance, written into Lean's zip/CSV layout (`data/crypto/coinbase/daily/<ticker>_trade.zip` or `data/equity/usa/daily/<ticker>.zip`).
|
|
1077
|
+
- `futures` / `options`: same, but source bars from Interactive Brokers (needs IB configured, see `aq ib status`; fails cleanly if not).
|
|
1078
|
+
- **Dry run by default**: without `--apply` it reports the plan and writes nothing. Never runs `train.py`: after `--apply`, run `python train.py --dataset-only` (then `python train.py`) yourself.
|
|
1079
|
+
|
|
1080
|
+
Derivatives-only flags:
|
|
1081
|
+
- `--contract-month <YYYYMM>` (futures): fetch a specific dated contract instead of the continuous one, to build a real term structure (e.g. `ES_FRONT`/`ES_NEXT`, same root, different month).
|
|
1082
|
+
- `--family-ticker <ROOT>` (futures/options): tag the asset with its root (e.g. `"ES"`, `"SPY"`) so `train.py`'s derivatives-macro features can group same-family contracts for term-structure/put-call/IV-skew. IB's historical API is per-contract and rate-limited, so building a training set is a repeated manual process, see `data_pipeline/README.md`.
|
|
1083
|
+
|
|
1084
|
+
#### `aq backfill`
|
|
1085
|
+
```text
|
|
1086
|
+
aq backfill <dividends|fred|yfinance> [--apply] [--tickers <TICKER> ...] [--series <SERIES> ...]
|
|
1087
|
+
```
|
|
1088
|
+
**Bulk-refreshes a whole data source across the entire configured universe**
|
|
1089
|
+
(Phase 4.8) — the opposite scope from `aq fetch` above, which is single-ticker/
|
|
1090
|
+
ad-hoc. Thin dispatcher to `python -m data_pipeline.<target>_backfill`; each
|
|
1091
|
+
target already has its own working `--apply`/`--tickers`/`--series` flags,
|
|
1092
|
+
passed through verbatim:
|
|
1093
|
+
- `dividends`: refreshes `data/reference/dividend_schedule/*.json` (real
|
|
1094
|
+
ex-dividend history + a cadence-projected next ex-div date) via `yfinance` —
|
|
1095
|
+
feeds the early-assignment-risk detector (`phase_v2.options_risk.assignment_risk_detector`).
|
|
1096
|
+
- `fred`: refreshes `data/reference/fred_series/*.csv` (Treasury yield curve /
|
|
1097
|
+
credit spread series) — feeds `features/bond_features.py`'s real yield-curve
|
|
1098
|
+
signals.
|
|
1099
|
+
- `yfinance`: refreshes thin local Lean zips (e.g. crypto tickers with sparse
|
|
1100
|
+
history) via Yahoo Finance.
|
|
1101
|
+
|
|
1102
|
+
**Dry run by default**, same convention as `aq fetch`: add `--apply` to
|
|
1103
|
+
actually write the cache/zip files. Never touches `config.json`.
|
|
1104
|
+
|
|
1105
|
+
#### `aq ib`
|
|
1106
|
+
```text
|
|
1107
|
+
aq ib status
|
|
1108
|
+
```
|
|
1109
|
+
**Reports Interactive Brokers readiness** as one of three states:
|
|
1110
|
+
- **disabled**: `phase_v2.ib.enabled` is `false` (the default; equities/crypto/bonds are unaffected either way).
|
|
1111
|
+
- **enabled but credentials missing**: `phase_v2.ib.enabled` is `true` but `lean.json`'s `ib-account`/`ib-user-name` are empty (set with `aq lean set ib-account <ACCOUNT>` / `aq lean set ib-user-name <USERNAME>`).
|
|
1112
|
+
- **reachable**: a live connect/disconnect round-trip against your running TWS/IB Gateway succeeded.
|
|
1113
|
+
|
|
1114
|
+
Credentials live entirely in `lean.json` (the same fields Lean's native
|
|
1115
|
+
`InteractiveBrokersBrokerage` uses); `phase_v2.ib` in `config.json` only adds
|
|
1116
|
+
the on/off switch plus the Gateway socket settings (`host`/`port`/`client_id`)
|
|
1117
|
+
for the offline `aq fetch futures`/`aq fetch options` backfill path. These are
|
|
1118
|
+
two distinct integrations on purpose: Lean's backtest engine never talks to IB
|
|
1119
|
+
(it only reads local data files), so historical futures/options bars must be
|
|
1120
|
+
backfilled separately before any backtest can use them, see
|
|
1121
|
+
`data_pipeline/README.md`.
|
|
1122
|
+
|
|
1123
|
+
#### `aq assets`
|
|
1124
|
+
```text
|
|
1125
|
+
aq assets status
|
|
1126
|
+
```
|
|
1127
|
+
**Full multi-asset-class readiness at a glance** (read-only), reports:
|
|
1128
|
+
- IB status (same three states as `aq ib status`).
|
|
1129
|
+
- Whether `phase_v2.futures_risk.enabled` / `phase_v2.options_risk.enabled` are on.
|
|
1130
|
+
- How many futures contract margin specs are loaded.
|
|
1131
|
+
- FRED yield-curve cache coverage (series count + most recent date).
|
|
1132
|
+
- How many futures/options assets are configured in the universe.
|
|
1133
|
+
|
|
1134
|
+
Toggle any of these with the generic `aq config set
|
|
1135
|
+
phase_v2.{ib,futures_risk,options_risk}.enabled true|false`, there's no
|
|
1136
|
+
separate enable/disable subcommand.
|
|
1137
|
+
|
|
1138
|
+
#### `aq render-lean-config`
|
|
1139
|
+
```text
|
|
1140
|
+
aq render-lean-config [--base lean.json] [--out lean.live.json] [--env-file .env.live]
|
|
1141
|
+
```
|
|
1142
|
+
**Renders the gitignored, secret-bearing `lean.live.json` from `.env.live`'s
|
|
1143
|
+
`AETHER_*` environment variables**, leaving the tracked `lean.json` template
|
|
1144
|
+
all-empty (`execution/lean_config_render.py`). Live/paper deploys pass Lean's
|
|
1145
|
+
own `--lean-config lean.live.json` to use the rendered file instead. Prints
|
|
1146
|
+
only the field *names* that were filled, never the secret values. Also emits
|
|
1147
|
+
a `credential_load` event to the tamper-evident audit log (see `aq
|
|
1148
|
+
audit-log` below) — a short-lived, one-shot `AuditQueue` push that never
|
|
1149
|
+
blocks or fails this command on a Redis hiccup.
|
|
1150
|
+
|
|
1151
|
+
#### `aq secrets-check`
|
|
1152
|
+
```text
|
|
1153
|
+
aq secrets-check
|
|
1154
|
+
```
|
|
1155
|
+
**Fails (non-zero exit) if a secret is about to be committed** — either a
|
|
1156
|
+
populated secret field in the tracked `lean.json` (should be empty; secrets
|
|
1157
|
+
belong in the gitignored `lean.live.json` above) or a real `.env` file that's
|
|
1158
|
+
somehow tracked by git. Pure detection logic lives in
|
|
1159
|
+
`execution/secret_scan.py`. Backs `.githooks/pre-commit` — this is what
|
|
1160
|
+
actually stops a secret from landing in a commit, not just a suggestion.
|
|
1161
|
+
|
|
1162
|
+
#### `aq audit-log`
|
|
1163
|
+
```text
|
|
1164
|
+
aq audit-log [--event-type order_placement|credential_load|live_mode_transition] [--since YYYY-MM-DD] [--limit N] [--verify]
|
|
1165
|
+
```
|
|
1166
|
+
**Queries the tamper-evident audit log** (order placement, credential loads,
|
|
1167
|
+
live-mode transitions — `development/Problems.md` #42) — a separate,
|
|
1168
|
+
compliance-focused hash-chained event log from the trading `experience/`
|
|
1169
|
+
event stream. Requires `AETHER_POSTGRES_DSN` (same var every other
|
|
1170
|
+
Postgres-backed `aq` command uses), and the `audit-worker` docker-compose
|
|
1171
|
+
service must have drained at least one batch from Redis into Postgres
|
|
1172
|
+
(`python -m audit.postgres_worker`) for anything to show up.
|
|
1173
|
+
|
|
1174
|
+
- Default (no flags): prints the most recent entries (`--limit`, default
|
|
1175
|
+
100), optionally filtered by `--event-type` and/or `--since`.
|
|
1176
|
+
- `--verify`: walks the whole hash chain instead and reports the first
|
|
1177
|
+
broken link, if any — the actual tamper-detection check, not just a log
|
|
1178
|
+
viewer. An empty table is trivially valid.
|
|
1179
|
+
|
|
1180
|
+
#### `aq status`
|
|
1181
|
+
```text
|
|
1182
|
+
aq status
|
|
1183
|
+
```
|
|
1184
|
+
Shows `git status`.
|
|
1185
|
+
|
|
1186
|
+
## Release Process
|
|
1187
|
+
|
|
1188
|
+
A release is exactly one manual step, deliberately no automatic release on
|
|
1189
|
+
every push to `main`, only on an explicitly pushed version tag
|
|
1190
|
+
(`.github/workflows/release.yml`, triggered on `push: tags: ["v*.*.*"]`):
|
|
1191
|
+
|
|
1192
|
+
```powershell
|
|
1193
|
+
git tag v0.1.0
|
|
1194
|
+
git push origin v0.1.0
|
|
1195
|
+
```
|
|
1196
|
+
|
|
1197
|
+
This then automatically runs (no manual version bump anywhere in the repo,
|
|
1198
|
+
`pyproject.toml` reads the version straight from the tag via
|
|
1199
|
+
`setuptools-scm`):
|
|
1200
|
+
|
|
1201
|
+
1. The test suite (`pytest`), a failure blocks the release entirely.
|
|
1202
|
+
2. PyPI publishing via Trusted Publishing (OIDC), no PyPI token is stored as a GitHub secret.
|
|
1203
|
+
3. Docker image build and push to `ghcr.io/leon1706-lol/aether-quant`, tagged with the version number and `:latest`.
|
|
1204
|
+
|
|
1205
|
+
**One-time manual setup, before the first tag is ever pushed** (can't be
|
|
1206
|
+
done from here):
|
|
1207
|
+
|
|
1208
|
+
- Create a "Trusted Publisher" on pypi.org for this project (pointing at `leon1706-lol/Aether-quant` + the `release.yml` workflow file).
|
|
1209
|
+
- After the very first tag push: check the **Packages** tab of this repo to see whether the new `aether-quant` package is private, and switch it to public if needed so `docker pull` works for everyone.
|
|
1210
|
+
|
|
1211
|
+
## Roadmap
|
|
1212
|
+
|
|
1213
|
+
All finished work and changes can be found in
|
|
1214
|
+
[`development/Changelog.md`](development/Changelog.md), kept separate to keep this README short.
|
|
1215
|
+
|
|
1216
|
+
|
|
1217
|
+
### Next, open
|
|
1218
|
+
|
|
1219
|
+
- **Interactive Brokers end-to-end verification** — the one blocker behind the README's Known Limitations; written and mock-tested, unverifiable without a key.
|
|
1220
|
+
- **Computing beyond GitHub Codespaces** (#53): Oracle Cloud Always Free + Remote-SSH as a more powerful, persistent free compute option.
|
|
1221
|
+
|
|
1222
|
+
### Later (HFT)
|
|
1223
|
+
|
|
1224
|
+
`development/architecture.md`'s own "Why This Is Not HFT, And What It
|
|
1225
|
+
Would Take" analysis is the honest starting point here, not marketing
|
|
1226
|
+
aspiration, but a concrete six-point gap list the system's own architecture
|
|
1227
|
+
docs already identify (daily bars everywhere, no tick/L1-L2 data, no
|
|
1228
|
+
slippage/latency-aware execution, offline batch retraining, polling
|
|
1229
|
+
infrastructure, no colocated broker connectivity). Its own conclusion is
|
|
1230
|
+
blunt: closing these gaps is **"closer to a second, parallel trading system
|
|
1231
|
+
than an incremental change."** Bolting HFT onto today's daily-bar
|
|
1232
|
+
architecture isn't realistic; it would need to be built alongside it, not
|
|
1233
|
+
on top of it.
|
|
1234
|
+
|
|
1235
|
+
If pursued, sequence it as its own workstream, in this order:
|
|
1236
|
+
1. **Tick/L1-L2 market data pipeline**: a new storage layer entirely, replacing the daily Lean zip files.
|
|
1237
|
+
2. **A genuinely new short-horizon model**: using minute/second-resolution data for faster trades (not milliseconds), not a retrained version of today's daily classifier.
|
|
1238
|
+
3. **Execution/latency infrastructure**: slippage/latency-aware, queue-position-aware execution and a low-latency event-driven runtime, replacing the daily-bar `on_data()` callback and the 30s+ polling background workers.
|
|
1239
|
+
4. Further out: real broker/exchange connectivity beyond paper trading, continuous/online retraining, multi-timeframe ensembles, and reinforcement-learning-based position sizing/execution.
|
|
1240
|
+
|
|
1241
|
+
---
|
|
1242
|
+
|
|
1243
|
+
<p align="center">
|
|
1244
|
+
Built by <strong>Leon Schwarzkopf</strong>, <a href="mailto:leonschwarzkopf08@gmail.com">leonschwarzkopf08@gmail.com</a>
|
|
1245
|
+
</p>
|
|
1246
|
+
|
|
1247
|
+
---
|
|
1248
|
+
|
|
1249
|
+
<div align="center">
|
|
1250
|
+
<sub>Aether Quant</sub>
|
|
1251
|
+
</div>
|
|
1252
|
+
|