aether-quant 0.7.0__tar.gz → 0.8.0__tar.gz

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