aether-quant 0.8.0__tar.gz → 0.9.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 (351) hide show
  1. {aether_quant-0.8.0 → aether_quant-0.9.0}/.github/workflows/release.yml +8 -0
  2. {aether_quant-0.8.0 → aether_quant-0.9.0}/.gitignore +3 -0
  3. {aether_quant-0.8.0 → aether_quant-0.9.0}/Dockerfile.retraining_worker +2 -0
  4. aether_quant-0.9.0/LICENSE +133 -0
  5. {aether_quant-0.8.0 → aether_quant-0.9.0}/PKG-INFO +3 -1
  6. {aether_quant-0.8.0 → aether_quant-0.9.0}/README.md +168 -96
  7. {aether_quant-0.8.0 → aether_quant-0.9.0}/aether_quant.egg-info/PKG-INFO +3 -1
  8. {aether_quant-0.8.0 → aether_quant-0.9.0}/aether_quant.egg-info/SOURCES.txt +36 -0
  9. {aether_quant-0.8.0 → aether_quant-0.9.0}/aether_quant.egg-info/scm_file_list.json +36 -0
  10. aether_quant-0.9.0/aether_quant.egg-info/scm_version.json +8 -0
  11. {aether_quant-0.8.0 → aether_quant-0.9.0}/aq_cli.py +285 -24
  12. {aether_quant-0.8.0 → aether_quant-0.9.0}/config.json +117 -12
  13. aether_quant-0.9.0/data_pipeline/README.md +203 -0
  14. {aether_quant-0.8.0 → aether_quant-0.9.0}/data_pipeline/fetch.py +39 -3
  15. aether_quant-0.9.0/data_pipeline/fred_backfill.py +232 -0
  16. aether_quant-0.9.0/data_pipeline/ib_backfill.py +287 -0
  17. {aether_quant-0.8.0 → aether_quant-0.9.0}/development/Changelog.md +257 -0
  18. {aether_quant-0.8.0 → aether_quant-0.9.0}/development/Problems.md +224 -0
  19. aether_quant-0.9.0/features/README.md +48 -0
  20. aether_quant-0.9.0/features/__init__.py +93 -0
  21. aether_quant-0.9.0/features/bond_features.py +114 -0
  22. aether_quant-0.9.0/features/derivatives_macro_features.py +72 -0
  23. aether_quant-0.9.0/features/options_greeks.py +190 -0
  24. {aether_quant-0.8.0 → aether_quant-0.9.0}/inference/README.md +37 -1
  25. {aether_quant-0.8.0 → aether_quant-0.9.0}/inference/__init__.py +4 -0
  26. {aether_quant-0.8.0 → aether_quant-0.9.0}/inference/exported_model.py +223 -9
  27. {aether_quant-0.8.0 → aether_quant-0.9.0}/main.py +704 -46
  28. aether_quant-0.9.0/ml/gating_model.json +570 -0
  29. aether_quant-0.9.0/ml/gating_training_metrics.json +130 -0
  30. {aether_quant-0.8.0/ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c → aether_quant-0.9.0/ml}/multitask_feature_schema.json +14 -1
  31. aether_quant-0.9.0/ml/multitask_model.json +8548 -0
  32. aether_quant-0.9.0/ml/multitask_training_metrics.json +6316 -0
  33. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/sequence_feature_schema.json +27 -1
  34. aether_quant-0.9.0/ml/sequence_model.json +19470 -0
  35. aether_quant-0.9.0/ml/sequence_training_metrics.json +6278 -0
  36. aether_quant-0.9.0/ml/versions/gating-only-0cb50d98-39c9-4cde-bcdd-c174bf126426/gating_model.json +570 -0
  37. aether_quant-0.9.0/ml/versions/gating-only-0cb50d98-39c9-4cde-bcdd-c174bf126426/gating_training_metrics.json +130 -0
  38. aether_quant-0.9.0/ml/versions/multitask-only-8c59799d-c7f1-40be-9c76-8f5eefdac6d9/multitask_feature_schema.json +89 -0
  39. aether_quant-0.9.0/ml/versions/multitask-only-8c59799d-c7f1-40be-9c76-8f5eefdac6d9/multitask_model.json +8548 -0
  40. aether_quant-0.9.0/ml/versions/multitask-only-8c59799d-c7f1-40be-9c76-8f5eefdac6d9/multitask_training_metrics.json +6316 -0
  41. aether_quant-0.9.0/ml/versions/sequence-only-d649549b-9527-4e55-b61e-cd1e26cf8ca6/sequence_feature_schema.json +90 -0
  42. aether_quant-0.9.0/ml/versions/sequence-only-d649549b-9527-4e55-b61e-cd1e26cf8ca6/sequence_model.json +19470 -0
  43. aether_quant-0.9.0/ml/versions/sequence-only-d649549b-9527-4e55-b61e-cd1e26cf8ca6/sequence_training_metrics.json +6278 -0
  44. aether_quant-0.9.0/ml/versions/stage4-1783711025/gating_feature_schema.json +30 -0
  45. {aether_quant-0.8.0 → aether_quant-0.9.0}/monitoring/api_server.py +6 -0
  46. aether_quant-0.9.0/monitoring/assets_status.py +64 -0
  47. {aether_quant-0.8.0 → aether_quant-0.9.0}/portfolio/README.md +41 -0
  48. aether_quant-0.9.0/portfolio/__init__.py +16 -0
  49. aether_quant-0.9.0/portfolio/options_strategy.py +157 -0
  50. {aether_quant-0.8.0 → aether_quant-0.9.0}/pyproject.toml +3 -0
  51. {aether_quant-0.8.0 → aether_quant-0.9.0}/requirements/requirements-dev.txt +13 -0
  52. {aether_quant-0.8.0 → aether_quant-0.9.0}/risk/README.md +46 -0
  53. {aether_quant-0.8.0 → aether_quant-0.9.0}/risk/__init__.py +12 -0
  54. aether_quant-0.9.0/risk/asset_class_router.py +166 -0
  55. aether_quant-0.9.0/risk/futures_risk.py +161 -0
  56. aether_quant-0.9.0/scripts/README.md +32 -0
  57. aether_quant-0.9.0/scripts/profile_inference.py +165 -0
  58. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_aq_cli.py +349 -4
  59. aether_quant-0.9.0/tests/test_asset_class_router.py +117 -0
  60. aether_quant-0.9.0/tests/test_assets_status.py +92 -0
  61. aether_quant-0.9.0/tests/test_bond_features.py +117 -0
  62. aether_quant-0.9.0/tests/test_derivatives_macro_features.py +100 -0
  63. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_exported_model.py +210 -0
  64. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_fetch.py +134 -2
  65. aether_quant-0.9.0/tests/test_fred_backfill.py +185 -0
  66. aether_quant-0.9.0/tests/test_futures_risk.py +148 -0
  67. aether_quant-0.9.0/tests/test_ib_backfill.py +336 -0
  68. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_lean_backtest_ml_coverage.py +13 -4
  69. aether_quant-0.9.0/tests/test_options_greeks.py +150 -0
  70. aether_quant-0.9.0/tests/test_options_strategy.py +201 -0
  71. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_portfolio_book_construction.py +25 -0
  72. aether_quant-0.9.0/tests/test_train_asset_class_context_features.py +87 -0
  73. aether_quant-0.9.0/tests/test_train_bond_features.py +176 -0
  74. aether_quant-0.9.0/tests/test_train_derivatives_macro_features.py +220 -0
  75. {aether_quant-0.8.0 → aether_quant-0.9.0}/train.py +306 -0
  76. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/api/client.ts +2 -1
  77. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/api/hooks.ts +9 -0
  78. aether_quant-0.9.0/webui/src/components/monitoring/AssetsStatusPanel.tsx +69 -0
  79. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/risk/AssetSizingTable.tsx +24 -1
  80. aether_quant-0.9.0/webui/src/components/risk/DerivativesMacroPanel.tsx +96 -0
  81. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/pages/Overview.tsx +5 -0
  82. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/pages/RiskPage.tsx +2 -0
  83. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/types/state.ts +86 -0
  84. aether_quant-0.8.0/aether_quant.egg-info/scm_version.json +0 -8
  85. aether_quant-0.8.0/data_pipeline/README.md +0 -99
  86. aether_quant-0.8.0/features/__init__.py +0 -35
  87. aether_quant-0.8.0/ml/sequence_model.json +0 -15233
  88. aether_quant-0.8.0/ml/sequence_training_metrics.json +0 -506
  89. aether_quant-0.8.0/ml/versions/gating-only-05c572c8-9566-4152-805c-fa57142a3f8c/gating_model.json +0 -570
  90. aether_quant-0.8.0/ml/versions/gating-only-05c572c8-9566-4152-805c-fa57142a3f8c/gating_training_metrics.json +0 -130
  91. aether_quant-0.8.0/ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c/multitask_model.json +0 -7703
  92. aether_quant-0.8.0/ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c/multitask_training_metrics.json +0 -6320
  93. aether_quant-0.8.0/portfolio/__init__.py +0 -8
  94. {aether_quant-0.8.0 → aether_quant-0.9.0}/.dockerignore +0 -0
  95. {aether_quant-0.8.0 → aether_quant-0.9.0}/.env.compose.example +0 -0
  96. {aether_quant-0.8.0 → aether_quant-0.9.0}/.env.live.example +0 -0
  97. {aether_quant-0.8.0 → aether_quant-0.9.0}/.gitattributes +0 -0
  98. {aether_quant-0.8.0 → aether_quant-0.9.0}/.github/workflows/ci.yml +0 -0
  99. {aether_quant-0.8.0 → aether_quant-0.9.0}/Dockerfile +0 -0
  100. {aether_quant-0.8.0 → aether_quant-0.9.0}/Dockerfile.workers +0 -0
  101. {aether_quant-0.8.0 → aether_quant-0.9.0}/aether_quant.egg-info/dependency_links.txt +0 -0
  102. {aether_quant-0.8.0 → aether_quant-0.9.0}/aether_quant.egg-info/entry_points.txt +0 -0
  103. {aether_quant-0.8.0 → aether_quant-0.9.0}/aether_quant.egg-info/top_level.txt +0 -0
  104. {aether_quant-0.8.0 → aether_quant-0.9.0}/analyzer/README.md +0 -0
  105. {aether_quant-0.8.0 → aether_quant-0.9.0}/analyzer/__init__.py +0 -0
  106. {aether_quant-0.8.0 → aether_quant-0.9.0}/analyzer/market_analyzer.py +0 -0
  107. {aether_quant-0.8.0 → aether_quant-0.9.0}/backtests/.gitkeep +0 -0
  108. {aether_quant-0.8.0 → aether_quant-0.9.0}/data/alternative/estimize/consensus/aapl/.keep +0 -0
  109. {aether_quant-0.8.0 → aether_quant-0.9.0}/data/alternative/estimize/estimate/.keep +0 -0
  110. {aether_quant-0.8.0 → aether_quant-0.9.0}/data/alternative/estimize/release/.keep +0 -0
  111. {aether_quant-0.8.0 → aether_quant-0.9.0}/data/alternative/sec/aapl/.keep +0 -0
  112. {aether_quant-0.8.0 → aether_quant-0.9.0}/data/alternative/trading-economics/.keep +0 -0
  113. {aether_quant-0.8.0 → aether_quant-0.9.0}/data/alternative/trading-economics/calendar/.keep +0 -0
  114. {aether_quant-0.8.0 → aether_quant-0.9.0}/data/alternative/trading-economics/earnings/.keep +0 -0
  115. {aether_quant-0.8.0 → aether_quant-0.9.0}/data/alternative/trading-economics/indicator/.keep +0 -0
  116. {aether_quant-0.8.0 → aether_quant-0.9.0}/data_pipeline/__init__.py +0 -0
  117. {aether_quant-0.8.0 → aether_quant-0.9.0}/data_pipeline/v2_manifest.py +0 -0
  118. {aether_quant-0.8.0 → aether_quant-0.9.0}/data_pipeline/yfinance_backfill.py +0 -0
  119. {aether_quant-0.8.0 → aether_quant-0.9.0}/development/README.md +0 -0
  120. {aether_quant-0.8.0 → aether_quant-0.9.0}/development/backtest_equity_chart.png +0 -0
  121. {aether_quant-0.8.0 → aether_quant-0.9.0}/development/infrastructure.md +0 -0
  122. {aether_quant-0.8.0 → aether_quant-0.9.0}/development/logo.png +0 -0
  123. {aether_quant-0.8.0 → aether_quant-0.9.0}/development/v2_architecture.md +0 -0
  124. {aether_quant-0.8.0 → aether_quant-0.9.0}/docker-compose.yml +0 -0
  125. {aether_quant-0.8.0 → aether_quant-0.9.0}/execution/README.md +0 -0
  126. {aether_quant-0.8.0 → aether_quant-0.9.0}/execution/__init__.py +0 -0
  127. {aether_quant-0.8.0 → aether_quant-0.9.0}/execution/config_cache.py +0 -0
  128. {aether_quant-0.8.0 → aether_quant-0.9.0}/execution/live_credentials.py +0 -0
  129. {aether_quant-0.8.0 → aether_quant-0.9.0}/execution/live_credentials_io.py +0 -0
  130. {aether_quant-0.8.0 → aether_quant-0.9.0}/execution/order_gate.py +0 -0
  131. {aether_quant-0.8.0 → aether_quant-0.9.0}/execution/paper_readiness.py +0 -0
  132. {aether_quant-0.8.0 → aether_quant-0.9.0}/execution/paper_readiness_io.py +0 -0
  133. {aether_quant-0.8.0 → aether_quant-0.9.0}/execution/paper_readiness_report.py +0 -0
  134. {aether_quant-0.8.0 → aether_quant-0.9.0}/execution/paper_readiness_scheduler.py +0 -0
  135. {aether_quant-0.8.0 → aether_quant-0.9.0}/execution/runtime_config_io.py +0 -0
  136. {aether_quant-0.8.0 → aether_quant-0.9.0}/experience/README.md +0 -0
  137. {aether_quant-0.8.0 → aether_quant-0.9.0}/experience/__init__.py +0 -0
  138. {aether_quant-0.8.0 → aether_quant-0.9.0}/experience/observation_metrics.py +0 -0
  139. {aether_quant-0.8.0 → aether_quant-0.9.0}/experience/postgres_worker.py +0 -0
  140. {aether_quant-0.8.0 → aether_quant-0.9.0}/experience/redis_queue.py +0 -0
  141. {aether_quant-0.8.0 → aether_quant-0.9.0}/experience/simulated_portfolio.py +0 -0
  142. {aether_quant-0.8.0 → aether_quant-0.9.0}/experts/README.md +0 -0
  143. {aether_quant-0.8.0 → aether_quant-0.9.0}/experts/__init__.py +0 -0
  144. {aether_quant-0.8.0 → aether_quant-0.9.0}/experts/expert_datasets.py +0 -0
  145. {aether_quant-0.8.0 → aether_quant-0.9.0}/features/macro_features.py +0 -0
  146. {aether_quant-0.8.0 → aether_quant-0.9.0}/features/technical_indicators.py +0 -0
  147. {aether_quant-0.8.0 → aether_quant-0.9.0}/generate_backtest_report.py +0 -0
  148. {aether_quant-0.8.0 → aether_quant-0.9.0}/lean.json +0 -0
  149. {aether_quant-0.8.0 → aether_quant-0.9.0}/liquidity/README.md +0 -0
  150. {aether_quant-0.8.0 → aether_quant-0.9.0}/liquidity/__init__.py +0 -0
  151. {aether_quant-0.8.0 → aether_quant-0.9.0}/liquidity/market_liquidity.py +0 -0
  152. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/README.md +0 -0
  153. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/gating_feature_schema.json +0 -0
  154. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/gating-only-05c572c8-9566-4152-805c-fa57142a3f8c/gating_feature_schema.json +0 -0
  155. {aether_quant-0.8.0/ml → aether_quant-0.9.0/ml/versions/gating-only-05c572c8-9566-4152-805c-fa57142a3f8c}/gating_model.json +0 -0
  156. {aether_quant-0.8.0/ml → aether_quant-0.9.0/ml/versions/gating-only-05c572c8-9566-4152-805c-fa57142a3f8c}/gating_training_metrics.json +0 -0
  157. {aether_quant-0.8.0/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459 → aether_quant-0.9.0/ml/versions/gating-only-0cb50d98-39c9-4cde-bcdd-c174bf126426}/gating_feature_schema.json +0 -0
  158. {aether_quant-0.8.0/ml/versions/stage123-1783709428 → aether_quant-0.9.0/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459}/gating_feature_schema.json +0 -0
  159. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_model.json +0 -0
  160. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/gating-only-26218402-34d9-4a0a-add8-ee5d50dd0459/gating_training_metrics.json +0 -0
  161. {aether_quant-0.8.0/ml → aether_quant-0.9.0/ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c}/multitask_feature_schema.json +0 -0
  162. {aether_quant-0.8.0/ml → aether_quant-0.9.0/ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c}/multitask_model.json +0 -0
  163. {aether_quant-0.8.0/ml → aether_quant-0.9.0/ml/versions/multitask-only-f5708084-512b-4484-a47b-0720f9c1460c}/multitask_training_metrics.json +0 -0
  164. {aether_quant-0.8.0/ml/versions/stage4-1783711025 → aether_quant-0.9.0/ml/versions/stage123-1783709428}/gating_feature_schema.json +0 -0
  165. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/stage123-1783709428/gating_model.json +0 -0
  166. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/stage123-1783709428/gating_training_metrics.json +0 -0
  167. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/stage123-1783709428/multitask_feature_schema.json +0 -0
  168. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/stage123-1783709428/multitask_model.json +0 -0
  169. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/stage123-1783709428/multitask_training_metrics.json +0 -0
  170. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/stage4-1783711025/gating_model.json +0 -0
  171. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/stage4-1783711025/gating_training_metrics.json +0 -0
  172. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/stage4-1783711025/multitask_feature_schema.json +0 -0
  173. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/stage4-1783711025/multitask_model.json +0 -0
  174. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/stage4-1783711025/multitask_training_metrics.json +0 -0
  175. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/stage5-1783715333/sequence_feature_schema.json +0 -0
  176. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/stage5-1783715333/sequence_model.json +0 -0
  177. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/stage5-1783715333/sequence_training_metrics.json +0 -0
  178. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/v1/multitask_feature_schema.json +0 -0
  179. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/v1/multitask_model.json +0 -0
  180. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/v1/multitask_training_metrics.json +0 -0
  181. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/v1/sequence_feature_schema.json +0 -0
  182. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/v1/sequence_model.json +0 -0
  183. {aether_quant-0.8.0 → aether_quant-0.9.0}/ml/versions/v1/sequence_training_metrics.json +0 -0
  184. {aether_quant-0.8.0 → aether_quant-0.9.0}/moe/README.md +0 -0
  185. {aether_quant-0.8.0 → aether_quant-0.9.0}/moe/__init__.py +0 -0
  186. {aether_quant-0.8.0 → aether_quant-0.9.0}/moe/gating.py +0 -0
  187. {aether_quant-0.8.0 → aether_quant-0.9.0}/monitoring/README.md +0 -0
  188. {aether_quant-0.8.0 → aether_quant-0.9.0}/monitoring/__init__.py +0 -0
  189. {aether_quant-0.8.0 → aether_quant-0.9.0}/monitoring/neural_network_state.py +0 -0
  190. {aether_quant-0.8.0 → aether_quant-0.9.0}/notifications/README.md +0 -0
  191. {aether_quant-0.8.0 → aether_quant-0.9.0}/notifications/__init__.py +0 -0
  192. {aether_quant-0.8.0 → aether_quant-0.9.0}/notifications/postgres_telegram.py +0 -0
  193. {aether_quant-0.8.0 → aether_quant-0.9.0}/notifications/telegram_alerts.py +0 -0
  194. {aether_quant-0.8.0 → aether_quant-0.9.0}/notifications/telegram_client.py +0 -0
  195. {aether_quant-0.8.0 → aether_quant-0.9.0}/notifications/telegram_worker.py +0 -0
  196. {aether_quant-0.8.0 → aether_quant-0.9.0}/performance/README.md +0 -0
  197. {aether_quant-0.8.0 → aether_quant-0.9.0}/performance/__init__.py +0 -0
  198. {aether_quant-0.8.0 → aether_quant-0.9.0}/performance/postgres_triggers.py +0 -0
  199. {aether_quant-0.8.0 → aether_quant-0.9.0}/performance/rank_ic_monitor.py +0 -0
  200. {aether_quant-0.8.0 → aether_quant-0.9.0}/performance/trigger_worker.py +0 -0
  201. {aether_quant-0.8.0 → aether_quant-0.9.0}/performance/triggers.py +0 -0
  202. {aether_quant-0.8.0 → aether_quant-0.9.0}/portfolio/book_construction.py +0 -0
  203. {aether_quant-0.8.0 → aether_quant-0.9.0}/regime/README.md +0 -0
  204. {aether_quant-0.8.0 → aether_quant-0.9.0}/regime/__init__.py +0 -0
  205. {aether_quant-0.8.0 → aether_quant-0.9.0}/regime/market_regime.py +0 -0
  206. {aether_quant-0.8.0 → aether_quant-0.9.0}/requirements/README.md +0 -0
  207. {aether_quant-0.8.0 → aether_quant-0.9.0}/requirements/requirements-retraining-worker.txt +0 -0
  208. {aether_quant-0.8.0 → aether_quant-0.9.0}/requirements/requirements-runtime.txt +0 -0
  209. {aether_quant-0.8.0 → aether_quant-0.9.0}/requirements/requirements-workers.txt +0 -0
  210. {aether_quant-0.8.0 → aether_quant-0.9.0}/requirements/requirements.txt +0 -0
  211. {aether_quant-0.8.0 → aether_quant-0.9.0}/retraining/README.md +0 -0
  212. {aether_quant-0.8.0 → aether_quant-0.9.0}/retraining/__init__.py +0 -0
  213. {aether_quant-0.8.0 → aether_quant-0.9.0}/retraining/artifacts.py +0 -0
  214. {aether_quant-0.8.0 → aether_quant-0.9.0}/retraining/backtest_gate.py +0 -0
  215. {aether_quant-0.8.0 → aether_quant-0.9.0}/retraining/lean_backtest.py +0 -0
  216. {aether_quant-0.8.0 → aether_quant-0.9.0}/retraining/orchestrator.py +0 -0
  217. {aether_quant-0.8.0 → aether_quant-0.9.0}/retraining/planning.py +0 -0
  218. {aether_quant-0.8.0 → aether_quant-0.9.0}/retraining/postgres_registry.py +0 -0
  219. {aether_quant-0.8.0 → aether_quant-0.9.0}/retraining/status_export.py +0 -0
  220. {aether_quant-0.8.0 → aether_quant-0.9.0}/retraining/validation_gate.py +0 -0
  221. {aether_quant-0.8.0 → aether_quant-0.9.0}/retraining/vault_client.py +0 -0
  222. {aether_quant-0.8.0 → aether_quant-0.9.0}/retraining/vault_commands.py +0 -0
  223. {aether_quant-0.8.0 → aether_quant-0.9.0}/retraining/worker.py +0 -0
  224. {aether_quant-0.8.0 → aether_quant-0.9.0}/risk/manual_override.py +0 -0
  225. {aether_quant-0.8.0 → aether_quant-0.9.0}/risk/position_sizing.py +0 -0
  226. {aether_quant-0.8.0 → aether_quant-0.9.0}/risk_controls.py +0 -0
  227. {aether_quant-0.8.0 → aether_quant-0.9.0}/setup.cfg +0 -0
  228. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/README.md +0 -0
  229. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_backtest_gate.py +0 -0
  230. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_config_cache.py +0 -0
  231. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_experience_queue.py +0 -0
  232. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_expert_datasets.py +0 -0
  233. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_expert_models.py +0 -0
  234. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_gating_network.py +0 -0
  235. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_generate_backtest_report.py +0 -0
  236. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_lean_backtest.py +0 -0
  237. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_learned_topology.py +0 -0
  238. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_live_credentials.py +0 -0
  239. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_live_credentials_io.py +0 -0
  240. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_macro_features.py +0 -0
  241. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_manual_override.py +0 -0
  242. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_market_analyzer.py +0 -0
  243. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_market_liquidity.py +0 -0
  244. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_market_regime.py +0 -0
  245. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_market_topology.py +0 -0
  246. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_neural_network_state.py +0 -0
  247. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_observation_metrics.py +0 -0
  248. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_order_gate.py +0 -0
  249. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_paper_readiness.py +0 -0
  250. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_paper_readiness_io.py +0 -0
  251. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_paper_readiness_report.py +0 -0
  252. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_paper_readiness_scheduler.py +0 -0
  253. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_position_sizing.py +0 -0
  254. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_postgres_telegram.py +0 -0
  255. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_postgres_triggers.py +0 -0
  256. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_postgres_worker.py +0 -0
  257. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_rank_ic_monitor.py +0 -0
  258. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_retraining_artifacts.py +0 -0
  259. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_retraining_orchestrator.py +0 -0
  260. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_retraining_planning.py +0 -0
  261. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_retraining_postgres_registry.py +0 -0
  262. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_retraining_worker.py +0 -0
  263. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_risk_controls.py +0 -0
  264. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_runtime_config_io.py +0 -0
  265. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_simulated_portfolio.py +0 -0
  266. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_status_export.py +0 -0
  267. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_technical_indicators.py +0 -0
  268. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_telegram_alerts.py +0 -0
  269. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_telegram_client.py +0 -0
  270. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_telegram_worker.py +0 -0
  271. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_train_cross_sectional_features.py +0 -0
  272. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_train_gating.py +0 -0
  273. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_train_indicators.py +0 -0
  274. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_train_macro_features.py +0 -0
  275. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_train_multitask.py +0 -0
  276. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_train_multitask_architecture.py +0 -0
  277. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_train_pipeline.py +0 -0
  278. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_train_ranking_validation.py +0 -0
  279. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_train_sequence.py +0 -0
  280. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_train_sequence_architecture.py +0 -0
  281. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_train_topology.py +0 -0
  282. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_train_walk_forward_windows.py +0 -0
  283. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_trigger_worker.py +0 -0
  284. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_triggers.py +0 -0
  285. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_v2_pipeline_manifest.py +0 -0
  286. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_validation_gate.py +0 -0
  287. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_vault_client.py +0 -0
  288. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_vault_commands.py +0 -0
  289. {aether_quant-0.8.0 → aether_quant-0.9.0}/tests/test_yfinance_backfill.py +0 -0
  290. {aether_quant-0.8.0 → aether_quant-0.9.0}/topology/README.md +0 -0
  291. {aether_quant-0.8.0 → aether_quant-0.9.0}/topology/__init__.py +0 -0
  292. {aether_quant-0.8.0 → aether_quant-0.9.0}/topology/learned_topology.py +0 -0
  293. {aether_quant-0.8.0 → aether_quant-0.9.0}/topology/market_topology.py +0 -0
  294. {aether_quant-0.8.0 → aether_quant-0.9.0}/train_gating.py +0 -0
  295. {aether_quant-0.8.0 → aether_quant-0.9.0}/train_multitask.py +0 -0
  296. {aether_quant-0.8.0 → aether_quant-0.9.0}/train_sequence.py +0 -0
  297. {aether_quant-0.8.0 → aether_quant-0.9.0}/train_topology.py +0 -0
  298. {aether_quant-0.8.0 → aether_quant-0.9.0}/visualization/README.md +0 -0
  299. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/.gitignore +0 -0
  300. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/.oxlintrc.json +0 -0
  301. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/README.md +0 -0
  302. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/index.html +0 -0
  303. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/overview_v2_12.png +0 -0
  304. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/package-lock.json +0 -0
  305. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/package.json +0 -0
  306. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/public/favicon.svg +0 -0
  307. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/public/icons.svg +0 -0
  308. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/risk_v2_12.png +0 -0
  309. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/App.tsx +0 -0
  310. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/heatmap/AssetHeatmap.tsx +0 -0
  311. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/layout/AppShell.tsx +0 -0
  312. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/layout/Panel.tsx +0 -0
  313. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/monitoring/CountTable.tsx +0 -0
  314. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/monitoring/MonitoringFeeds.tsx +0 -0
  315. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/monitoring/ObservationPanel.tsx +0 -0
  316. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/monitoring/PaperReadinessPanel.tsx +0 -0
  317. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/monitoring/PerformanceTriggersPanel.tsx +0 -0
  318. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/monitoring/RawStateViewer.tsx +0 -0
  319. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/monitoring/RetrainingStatusPanel.tsx +0 -0
  320. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/neuralnet/NeuralNetworkScene3D.tsx +0 -0
  321. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/neuralnet/NeuralNetworkStatsPanel.tsx +0 -0
  322. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/risk/LiquidityTable.tsx +0 -0
  323. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/risk/RiskBar.tsx +0 -0
  324. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/risk/RiskCore.tsx +0 -0
  325. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/risk/StrategyRiskCards.tsx +0 -0
  326. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/scene3d/Scene3D.tsx +0 -0
  327. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/scorecards/Scorecards.tsx +0 -0
  328. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/signals/Badge.tsx +0 -0
  329. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/signals/PositionsList.tsx +0 -0
  330. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/signals/SignalBoard.tsx +0 -0
  331. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/topology/ClusterList.tsx +0 -0
  332. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/topology/TopologyLearningPanel.tsx +0 -0
  333. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/topology/TopologyScene3D.tsx +0 -0
  334. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/tracing/AssetPerformancePanel.tsx +0 -0
  335. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/tracing/BacktestEquityPanel.tsx +0 -0
  336. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/tracing/DivergingBarChart.tsx +0 -0
  337. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/tracing/LineChart.tsx +0 -0
  338. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/tracing/MetricsSnapshotPanel.tsx +0 -0
  339. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/components/tracing/ObservationEquityPanel.tsx +0 -0
  340. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/index.css +0 -0
  341. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/lib/downsample.ts +0 -0
  342. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/lib/format.ts +0 -0
  343. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/main.tsx +0 -0
  344. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/pages/NeuralNetworkPage.tsx +0 -0
  345. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/pages/TopologyPage.tsx +0 -0
  346. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/pages/TracingPage.tsx +0 -0
  347. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/src/types/tracing.ts +0 -0
  348. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/tsconfig.app.json +0 -0
  349. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/tsconfig.json +0 -0
  350. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/tsconfig.node.json +0 -0
  351. {aether_quant-0.8.0 → aether_quant-0.9.0}/webui/vite.config.ts +0 -0
@@ -70,3 +70,11 @@ jobs:
70
70
  push: true
71
71
  tags: ${{ steps.meta.outputs.tags }}
72
72
  labels: ${{ steps.meta.outputs.labels }}
73
+ # GitHub Actions cache backend - without this, every release
74
+ # build started cold (no layer reuse across releases) even
75
+ # though the Dockerfile itself is already correctly ordered
76
+ # (deps installed before source COPY, see development/Problems.md).
77
+ # mode=max caches every intermediate layer, not just the final
78
+ # image, so the npm ci/pip install layers survive between runs.
79
+ cache-from: type=gha
80
+ cache-to: type=gha,mode=max
@@ -97,3 +97,6 @@ webui/dist/
97
97
  # Lean CLI's ephemeral per-backtest Docker containers instead of rebuilding
98
98
  # every run (see Problems.md)
99
99
  .matplotlib_cache/
100
+
101
+ # scripts/profile_inference.py's pstats dump - regenerable output, not source
102
+ scripts/profile_inference_output*.txt
@@ -12,6 +12,8 @@ COPY topology/ ./topology/
12
12
  COPY moe/ ./moe/
13
13
  COPY inference/ ./inference/
14
14
  COPY risk/ ./risk/
15
+ COPY liquidity/ ./liquidity/
16
+ COPY data_pipeline/ ./data_pipeline/
15
17
  COPY retraining/ ./retraining/
16
18
  COPY train.py .
17
19
  COPY train_topology.py .
@@ -0,0 +1,133 @@
1
+ Required Notice: Copyright Leon Schwarzkopf (Aether Quant)
2
+
3
+ # PolyForm Noncommercial License 1.0.0
4
+
5
+ <https://polyformproject.org/licenses/noncommercial/1.0.0>
6
+
7
+ ## Acceptance
8
+
9
+ In order to get any license under these terms, you must agree
10
+ to them as both strict obligations and conditions to all
11
+ your licenses.
12
+
13
+ ## Copyright License
14
+
15
+ The licensor grants you a copyright license for the
16
+ software to do everything you might do with the software
17
+ that would otherwise infringe the licensor's copyright
18
+ in it for any permitted purpose. However, you may
19
+ only distribute the software according to [Distribution
20
+ License](#distribution-license) and make changes or new works
21
+ based on the software according to [Changes and New Works
22
+ License](#changes-and-new-works-license).
23
+
24
+ ## Distribution License
25
+
26
+ The licensor grants you an additional copyright license
27
+ to distribute copies of the software. Your license
28
+ to distribute covers distributing the software with
29
+ changes and new works permitted by [Changes and New Works
30
+ License](#changes-and-new-works-license).
31
+
32
+ ## Notices
33
+
34
+ You must ensure that anyone who gets a copy of any part of
35
+ the software from you also gets a copy of these terms or the
36
+ URL for them above, as well as copies of any plain-text lines
37
+ beginning with `Required Notice:` that the licensor provided
38
+ with the software. For example:
39
+
40
+ > Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
41
+
42
+ ## Changes and New Works License
43
+
44
+ The licensor grants you an additional copyright license to
45
+ make changes and new works based on the software for any
46
+ permitted purpose.
47
+
48
+ ## Patent License
49
+
50
+ The licensor grants you a patent license for the software that
51
+ covers patent claims the licensor can license, or becomes able
52
+ to license, that you would infringe by using the software.
53
+
54
+ ## Noncommercial Purposes
55
+
56
+ Any noncommercial purpose is a permitted purpose.
57
+
58
+ ## Personal Uses
59
+
60
+ Personal use for research, experiment, and testing for
61
+ the benefit of public knowledge, personal study, private
62
+ entertainment, hobby projects, amateur pursuits, or religious
63
+ observance, without any anticipated commercial application,
64
+ is use for a permitted purpose.
65
+
66
+ ## Noncommercial Organizations
67
+
68
+ Use by any charitable organization, educational institution,
69
+ public research organization, public safety or health
70
+ organization, environmental protection organization,
71
+ or government institution is use for a permitted purpose
72
+ regardless of the source of funding or obligations resulting
73
+ from the funding.
74
+
75
+ ## Fair Use
76
+
77
+ You may have "fair use" rights for the software under the
78
+ law. These terms do not limit them.
79
+
80
+ ## No Other Rights
81
+
82
+ These terms do not allow you to sublicense or transfer any of
83
+ your licenses to anyone else, or prevent the licensor from
84
+ granting licenses to anyone else. These terms do not imply
85
+ any other licenses.
86
+
87
+ ## Patent Defense
88
+
89
+ If you make any written claim that the software infringes or
90
+ contributes to infringement of any patent, your patent license
91
+ for the software granted under these terms ends immediately. If
92
+ your company makes such a claim, your patent license ends
93
+ immediately for work on behalf of your company.
94
+
95
+ ## Violations
96
+
97
+ The first time you are notified in writing that you have
98
+ violated any of these terms, or done anything with the software
99
+ not covered by your licenses, your licenses can nonetheless
100
+ continue if you come into full compliance with these terms,
101
+ and take practical steps to correct past violations, within
102
+ 32 days of receiving notice. Otherwise, all your licenses
103
+ end immediately.
104
+
105
+ ## No Liability
106
+
107
+ ***As far as the law allows, the software comes as is, without
108
+ any warranty or condition, and the licensor will not be liable
109
+ to you for any damages arising out of these terms or the use
110
+ or nature of the software, under any kind of legal claim.***
111
+
112
+ ## Definitions
113
+
114
+ The **licensor** is the individual or entity offering these
115
+ terms, and the **software** is the software the licensor makes
116
+ available under these terms.
117
+
118
+ **You** refers to the individual or entity agreeing to these
119
+ terms.
120
+
121
+ **Your company** is any legal entity, sole proprietorship,
122
+ or other kind of organization that you work for, plus all
123
+ organizations that have control over, are under the control of,
124
+ or are under common control with that organization. **Control**
125
+ means ownership of substantially all the assets of an entity,
126
+ or the power to direct its management and policies by vote,
127
+ contract, or otherwise. Control can be direct or indirect.
128
+
129
+ **Your licenses** are all the licenses granted to you for the
130
+ software under these terms.
131
+
132
+ **Use** means anything you do with the software requiring one
133
+ of your licenses.
@@ -1,5 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aether-quant
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: Aether Quant convenience CLI
5
5
  Requires-Python: >=3.10
6
+ License-File: LICENSE
7
+ Dynamic: license-file
@@ -5,20 +5,22 @@
5
5
  <h1 align="center">Aether Quant</h1>
6
6
 
7
7
  <p align="center">
8
- <strong>My state-of-the-art 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>
8
+ <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>
9
9
  </p>
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-934%2F945%20passing-red?style=flat-square&labelColor=1A1A1A" alt="934 of 945 tests passing"><!-- AQ:TEST_BADGE_END -->
14
- <img src="https://img.shields.io/pypi/v/aether-quant?style=flat-square&labelColor=1A1A1A&color=FF8C00" alt="PyPI version">
13
+ <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">
14
+ <!-- AQ:TEST_BADGE_START --><img src="https://img.shields.io/badge/tests-1156%2F1156%20passing-brightgreen?style=flat-square&labelColor=1A1A1A" alt="1156 of 1156 tests passing"><!-- AQ:TEST_BADGE_END -->
15
+ <img src="https://img.shields.io/pypi/v/aether-quant?style=flat-square&labelColor=1A1A1A&color=FF8C00&logo=pypi&logoColor=white" alt="PyPI version">
15
16
  <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
17
  </p>
17
18
 
18
19
  <p align="center">
19
20
  <img src="https://img.shields.io/badge/PyTorch-4B5563?style=flat-square&labelColor=1A1A1A&logo=pytorch&logoColor=white" alt="PyTorch">
20
21
  <img src="https://img.shields.io/badge/scikit--learn-4B5563?style=flat-square&labelColor=1A1A1A&logo=scikitlearn&logoColor=white" alt="scikit-learn">
21
- <img src="https://img.shields.io/badge/QuantConnect%20Lean-4B5563?style=flat-square&labelColor=1A1A1A" alt="QuantConnect Lean">
22
+ <img src="https://img.shields.io/badge/QuantConnect%20Lean-4B5563?style=flat-square&labelColor=1A1A1A&logo=quantconnect&logoColor=white" alt="QuantConnect Lean">
23
+ <img src="https://img.shields.io/badge/Interactive%20Brokers-4B5563?style=flat-square&labelColor=1A1A1A" alt="Interactive Brokers">
22
24
  <img src="https://img.shields.io/badge/FastAPI-4B5563?style=flat-square&labelColor=1A1A1A&logo=fastapi&logoColor=white" alt="FastAPI">
23
25
  <img src="https://img.shields.io/badge/React-4B5563?style=flat-square&labelColor=1A1A1A&logo=react&logoColor=white" alt="React">
24
26
  <img src="https://img.shields.io/badge/TypeScript-4B5563?style=flat-square&labelColor=1A1A1A&logo=typescript&logoColor=white" alt="TypeScript">
@@ -34,8 +36,14 @@ topology layer that combines a deterministic correlation embedding with a
34
36
  learned probabilistic overlay, a liquidity/market-impact engine that adjusts
35
37
  position sizing to real trading conditions, a cross-sectional ranking signal
36
38
  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
+ of the trading universe, a **unified multi-asset-class layer** that trades
40
+ equities, crypto, bonds, futures, and options through one coherent portfolio
41
+ — real yield-curve/duration features for bonds, margin-aware sizing for
42
+ futures, Black-Scholes-greeks-based sizing for options, and shared
43
+ cross-asset macro signals (yield curve shape, futures term structure,
44
+ options sentiment) feeding every asset's prediction, not just its own — and
45
+ a controlled retraining loop that lets the model itself evolve as markets do
46
+ — all wired together and validated
39
47
  end-to-end inside QuantConnect's Lean engine. The thesis this project exists
40
48
  to test is simple to state and hard to prove: **markets are non-stationary,
41
49
  so a trading model should be too.** Every subsystem here exists to make the
@@ -43,8 +51,24 @@ model adapt — to regime shifts, to changing correlation structure, to
43
51
  liquidity conditions — rather than to fit one historical window and hope it
44
52
  generalizes.
45
53
 
54
+ ## Known Limitations
55
+
56
+ Bonds are fully real today — no IB key needed. Futures and options are
57
+ fully wired end-to-end (chain parsing, greeks/IV, sizing, order placement,
58
+ position-close/exposure tracking, offline derivatives-macro training
59
+ features) but remain **data-empty until an Interactive Brokers key is
60
+ connected** (`phase_v2.ib.enabled` — see `aq ib status`/`aq assets
61
+ status`). Remaining, still-open items:
62
+
63
+ - **No backtest has been run against this code yet** — verified via unit tests and Lean's own type stubs only, not a real Lean runtime. Run one before trusting it in paper trading (see "run it yourself" below).
64
+ - **Futures margin uses a static reference file**, not live IB margin.
65
+ - **IB connection has never been tested against a real Gateway** — `aq ib status`/`aq assets status` report readiness only.
66
+ - **Single-leg options only** — no automatic multi-leg spread selection.
67
+ - **Disabling an asset class doesn't liquidate existing positions in it** — it only stops opening/managing new ones (`aq config set phase_v2.*.enabled`).
68
+
46
69
  ## Table of Contents
47
70
 
71
+ - [Known Limitations](#known-limitations)
48
72
  - [Download](#download)
49
73
  - [Getting Started](#getting-started)
50
74
  - [Requirements](#requirements)
@@ -56,6 +80,21 @@ generalizes.
56
80
  - [Backtest Results](#backtest-results)
57
81
  - [Test Suite](#test-suite)
58
82
  - [CLI Reference](#cli-reference)
83
+ - [`aq train`](#aq-train)
84
+ - [`aq test`](#aq-test)
85
+ - [`aq backtest`](#aq-backtest)
86
+ - [`aq report`](#aq-report)
87
+ - [`aq api`](#aq-api)
88
+ - [`aq webui`](#aq-webui)
89
+ - [`aq docker`](#aq-docker)
90
+ - [`aq config`](#aq-config)
91
+ - [`aq lean`](#aq-lean)
92
+ - [`aq retrain`](#aq-retrain)
93
+ - [`aq trade-lock`](#aq-trade-lock)
94
+ - [`aq fetch`](#aq-fetch)
95
+ - [`aq ib`](#aq-ib)
96
+ - [`aq assets`](#aq-assets)
97
+ - [`aq status`](#aq-status)
59
98
  - [Release Process](#release-process)
60
99
  - [Runbook](#runbook)
61
100
  - [Roadmap](#roadmap)
@@ -375,87 +414,21 @@ for the exact row-count thresholds). This is re-evaluated automatically
375
414
  every time `train.py` rebuilds the dataset, so an asset can move between
376
415
  these two roles as more history accumulates.
377
416
 
417
+ Asset classes sit on opposite sides of the hub (equities/crypto feed in
418
+ from above, fixed income from below) rather than a single top row — ticker
419
+ detail is in the table above, this is the group-level view:
420
+
378
421
  ```mermaid
379
422
  flowchart TD
380
- DNN(("Baseline DNN<br/>+ MoE Experts<br/>bullish / bearish /<br/>sideways / volatility"))
381
-
382
- subgraph Equities["Equities (15)"]
383
- AAPL["AAPL"]
384
- SPY["SPY"]
385
- QQQ["QQQ"]
386
- IWM["IWM"]
387
- EEM["EEM"]
388
- BAC["BAC"]
389
- IBM["IBM"]
390
- AIG["AIG"]
391
- BNO["BNO"]
392
- FB["FB"]
393
- GOOG["GOOG"]
394
- GOOGL["GOOGL"]
395
- USO["USO"]
396
- WM["WM"]
397
- AAA["AAA"]
398
- end
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
-
413
- subgraph Crypto["Crypto (5)"]
414
- BTCUSD["BTCUSD"]
415
- ETHUSD["ETHUSD"]
416
- LTCUSD["LTCUSD"]
417
- XRPUSD["XRPUSD"]
418
- ADAUSD["ADAUSD"]
419
- end
420
-
421
- AAPL --- DNN
422
- SPY --- DNN
423
- QQQ --- DNN
424
- IWM --- DNN
425
- EEM --- DNN
426
- BAC --- DNN
427
- IBM --- DNN
428
- AIG --- DNN
429
- BNO --- DNN
430
- FB --- DNN
431
- GOOG --- DNN
432
- GOOGL --- DNN
433
- USO --- DNN
434
- WM --- DNN
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
446
- BTCUSD --- DNN
447
- ETHUSD --- DNN
448
- LTCUSD --- DNN
449
- XRPUSD --- DNN
450
- ADAUSD --- DNN
423
+ Equities["Equities<br/>15 tickers"] --> DNN
424
+ Crypto["Crypto<br/>5 tickers"] --> DNN
425
+ DNN(("Baseline DNN<br/>+ MoE Experts")) --> FixedIncome["Fixed Income ETFs<br/>10 tickers"]
451
426
 
452
427
  classDef hub fill:#1A1A1A,stroke:#FF8C00,color:#FF8C00,stroke-width:2px;
453
- classDef trading fill:#FF8C00,stroke:#1A1A1A,color:#1A1A1A,stroke-width:1px;
454
- classDef observation fill:#3A3A3A,stroke:#FF8C00,color:#FF8C00,stroke-width:1px,stroke-dasharray: 4 2;
428
+ classDef group fill:#FF8C00,stroke:#1A1A1A,color:#1A1A1A,stroke-width:1px;
455
429
 
456
430
  class DNN hub;
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;
458
- class AAA,ETHUSD,XRPUSD,ADAUSD observation;
431
+ class Equities,Crypto,FixedIncome group;
459
432
  ```
460
433
 
461
434
  ## Project Structure
@@ -469,6 +442,8 @@ aether-quant/
469
442
  ├── analyzer/ # Central market analyzer (final per-asset decision layer)
470
443
  ├── moe/ # Mixture-of-Experts gating network
471
444
  ├── experts/ # Bullish / bearish / sideways / volatility expert models
445
+ ├── features/ # Shared feature-computation functions (train.py + main.py parity)
446
+ ├── portfolio/ # Stage-2 cross-sectional long/short book construction + options sizing
472
447
  ├── regime/ # Market regime detection
473
448
  ├── topology/ # 3D market topology (deterministic SMACOF + learned overlay)
474
449
  ├── liquidity/ # Liquidity / market-impact engine
@@ -484,6 +459,7 @@ aether-quant/
484
459
  ├── webui/ # React/Vite dashboard (Overview, Risk, Topology, Neural Network, Tracing)
485
460
  ├── ml/ # Model weights, datasets, versioned retraining candidates
486
461
  ├── storage/ # Reserved for future persistent artifact storage
462
+ ├── scripts/ # Standalone dev tooling (e.g. profile_inference.py)
487
463
  ├── requirements/ # All requirements*.txt variants
488
464
  ├── tests/ # Full pytest suite (828 tests)
489
465
  ├── backtests/ # Lean backtest run outputs (gitignored)
@@ -510,11 +486,13 @@ and how it's wired in — this table is the index.
510
486
  | Module | What it owns | Docs |
511
487
  |---|---|---|
512
488
  | `analyzer/` | Central market analyzer — the final per-asset action categorization layer | [README](analyzer/README.md) |
489
+ | `backtests/` | Strategy validation output (active model + per-candidate reports), gitignored | [README](backtests/README.md) |
513
490
  | `data/` | Local Lean data-folder format documentation | [README](data/README.md) |
514
491
  | `data_pipeline/` | Lean-data contract + Yahoo Finance historical backfill | [README](data_pipeline/README.md) |
515
492
  | `execution/` | Order gating, paper/live broker readiness, config-read caching | [README](execution/README.md) |
516
493
  | `experience/` | Observation/decision history — Redis buffer + PostgreSQL persistence | [README](experience/README.md) |
517
494
  | `experts/` | Bullish, bearish, sideways, and volatility expert models | [README](experts/README.md) |
495
+ | `features/` | Shared feature-computation functions, called from both `train.py` and `main.py` for train/inference parity | [README](features/README.md) |
518
496
  | `inference/` | Vectorized forward-pass interpreter for the exported neural networks | [README](inference/README.md) |
519
497
  | `liquidity/` | Liquidity and market-impact engine | [README](liquidity/README.md) |
520
498
  | `ml/` | Model & dataset artifacts, including versioned retraining candidates | [README](ml/README.md) |
@@ -522,12 +500,14 @@ and how it's wired in — this table is the index.
522
500
  | `monitoring/` | FastAPI JSON API serving runtime state to the webui | [README](monitoring/README.md) |
523
501
  | `notifications/` | Telegram alerting worker | [README](notifications/README.md) |
524
502
  | `performance/` | Performance trigger system (14 trigger functions) | [README](performance/README.md) |
503
+ | `portfolio/` | Stage-2 cross-sectional long/short book construction + Black-Scholes options sizing | [README](portfolio/README.md) |
525
504
  | `regime/` | Market regime detection | [README](regime/README.md) |
526
505
  | `requirements/` | All `requirements*.txt` variants and what consumes each | [README](requirements/README.md) |
527
506
  | `retraining/` | Controlled retraining — plan/train/validate/backtest/commit/promote/rollback | [README](retraining/README.md) |
528
507
  | `risk/` | Dynamic position sizing, leverage caps, drawdown-aware sizing | [README](risk/README.md) |
508
+ | `scripts/` | Standalone dev tooling (e.g. the inference-hot-path profiler) | [README](scripts/README.md) |
529
509
  | `storage/` | Reserved placeholder for future persistent artifact storage | [README](storage/README.md) |
530
- | `tests/` | Pytest suite conventions (828 tests) | [README](tests/README.md) |
510
+ | `tests/` | Pytest suite conventions (<!-- AQ:TEST_COUNT_START -->1156<!-- AQ:TEST_COUNT_END --> tests) | [README](tests/README.md) |
531
511
  | `topology/` | 3D market topology — deterministic SMACOF embedding + learned overlay | [README](topology/README.md) |
532
512
  | `visualization/` | Shared runtime-state JSON/CSV exports | [README](visualization/README.md) |
533
513
  | `webui/` | React/Vite dashboard (Overview, Risk, Topology, Neural Network, Tracing) | [README](webui/README.md) |
@@ -635,7 +615,7 @@ genuinely halted trading exactly as designed.
635
615
 
636
616
  ## Test Suite
637
617
 
638
- 828 tests, one file per source module, run via:
618
+ <!-- AQ:TEST_COUNT_START -->1156<!-- AQ:TEST_COUNT_END --> tests, one file per source module, run via:
639
619
 
640
620
  ```powershell
641
621
  aq test
@@ -690,9 +670,25 @@ mechanism" section.
690
670
 
691
671
  #### `aq test`
692
672
  ```text
693
- aq test
673
+ aq test [--lean|--full] [--parallel] [--cli] [--risk] [--portfolio] [--features]
674
+ [--data-pipeline] [--webui] [--ml] [--retraining] [--notifications]
675
+ [--storage] [--live]
694
676
  ```
695
- Runs the pytest suite and refreshes this README's test badge.
677
+ Runs the pytest suite and refreshes this README's test badge (only on a
678
+ full, unfiltered default run — a subsystem-filtered run's pass count is a
679
+ subset, never written into the badge). By default, excludes
680
+ `tests/test_lean_backtest_ml_coverage.py`'s real `lean backtest .`
681
+ integration test (over an hour wall-clock) — its own `skipif` only checks
682
+ whether the Lean CLI is *installed*, which it is in this repo's `.venv`, so
683
+ without this exclusion it silently ran on every `aq test`. Pass
684
+ `--lean`/`--full` to include it when you deliberately want full-system
685
+ coverage. `--parallel` runs via `pytest-xdist` (`-n auto`) — off by
686
+ default, since multiple workers each importing PyTorch is a real OOM risk
687
+ on memory-constrained machines. Any combination of the subsystem flags
688
+ (`--cli`, `--risk`, `--portfolio`, `--features`, `--data-pipeline`,
689
+ `--webui`, `--ml`, `--retraining`, `--notifications`, `--storage`,
690
+ `--live`) restricts the run to just those subsystems' test files instead
691
+ of the whole tree — run `aq test --help` for the exact file mapping.
696
692
 
697
693
  #### `aq backtest`
698
694
  ```text
@@ -772,17 +768,73 @@ to fully automatic behavior.
772
768
  #### `aq fetch`
773
769
  ```text
774
770
  aq fetch <crypto|stock> --ticker <TICKER> --start <YYYY-MM-DD> --end <YYYY-MM-DD> [--apply]
771
+ aq fetch futures --ticker <TICKER> --start <YYYY-MM-DD> --end <YYYY-MM-DD> --expiry <YYYY-MM-DD> [--contract-month <YYYYMM>] [--family-ticker <ROOT>] [--apply]
772
+ 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]
773
+ ```
774
+ `crypto`/`stock` fetch historical OHLCV from Yahoo Finance for a ticker
775
+ that isn't in `config.json` yet, formats it into Lean's zip/CSV
776
+ convention, and writes it to the right spot under `data/`
777
+ (`data/crypto/coinbase/daily/<ticker>_trade.zip` or
778
+ `data/equity/usa/daily/<ticker>.zip`). `futures`/`options` do the same but
779
+ source historical bars from Interactive Brokers instead — see `aq ib
780
+ status` below; both fail with a clean error (no traceback) if IB isn't
781
+ configured. On `--apply`, it also appends a new asset block to
782
+ `config.json`'s `phase1.universe.assets[]` — no manual editing needed. Dry
783
+ run by default (no `--apply`): reports what would happen, writes nothing.
784
+ Never runs `train.py` itself — once applied, run `python train.py
785
+ --dataset-only` (then `python train.py` when ready) yourself to actually
786
+ train on the new ticker.
787
+
788
+ `--contract-month` (futures only, e.g. `202603`) fetches a specific dated
789
+ contract instead of the default continuous contract — needed to build a
790
+ real historical term structure (fetch e.g. an `ES_FRONT` and `ES_NEXT`
791
+ ticker, same root, different `--contract-month`). `--family-ticker`
792
+ (futures/options) tags the asset with its root symbol (e.g. `"ES"`,
793
+ `"SPY"`) so `train.py`'s offline derivatives-macro features can group
794
+ same-family contracts together for term-structure/put-call/IV-skew
795
+ computation — see `data_pipeline/README.md` for the full acquisition
796
+ workflow (IB's historical API is per-contract and rate-limited, so
797
+ building a real training-time derivatives dataset is a manual, repeated
798
+ `aq fetch futures`/`aq fetch options` process, not a single bulk fetch).
799
+
800
+ #### `aq ib`
801
+ ```text
802
+ aq ib status
775
803
  ```
776
- Fetches historical OHLCV from Yahoo Finance for a ticker that isn't in
777
- `config.json` yet, formats it into Lean's zip/CSV convention, and writes
778
- it to the right spot under `data/` (`data/crypto/coinbase/daily/<ticker>_trade.zip`
779
- or `data/equity/usa/daily/<ticker>.zip`). On `--apply`, it also appends a
780
- new asset block to `config.json`'s `phase1.universe.assets[]` — no manual
781
- editing needed. Dry run by default (no `--apply`): reports what would
782
- happen, writes nothing. Never runs `train.py` itself — once applied, run
783
- `python train.py --dataset-only` (then `python train.py` when ready)
784
- yourself to actually train on the new ticker. `crypto`/`stock` today; a
785
- `derivative` asset class is planned for V3.
804
+ Reports Interactive Brokers readiness as one of three states: **disabled**
805
+ (`phase_v2.ib.enabled` is `false` in `config.json` — the default; the rest
806
+ of the system, equities/crypto/bonds, is fully unaffected either way),
807
+ **enabled but credentials missing** (`phase_v2.ib.enabled` is `true` but
808
+ `lean.json`'s `ib-account`/`ib-user-name` are empty — set them with `aq
809
+ lean set ib-account <ACCOUNT>` / `aq lean set ib-user-name <USERNAME>`),
810
+ or **reachable** (a live connect/disconnect round-trip against your
811
+ running TWS/IB Gateway succeeded). IB credentials live entirely in
812
+ `lean.json` — the same fields Lean's own native live/paper
813
+ `InteractiveBrokersBrokerage` already uses (`environments.live-interactive`)
814
+ — `phase_v2.ib` in `config.json` only adds a master on/off switch plus the
815
+ local Gateway socket connection settings (`host`/`port`/`client_id`) used
816
+ by the separate, offline `aq fetch futures`/`aq fetch options` historical
817
+ backfill path (`data_pipeline/ib_backfill.py`). See
818
+ `risk/README.md`/`data_pipeline/README.md` for why these are two
819
+ deliberately distinct integrations: Lean's backtest engine never talks to
820
+ IB regardless of `lean.json`'s contents (it only ever reads local data
821
+ files), so historical futures/options bars still need this separate,
822
+ offline data-prep step before any backtest can use them.
823
+
824
+ #### `aq assets`
825
+ ```text
826
+ aq assets status
827
+ ```
828
+ One command reporting full multi-asset-class readiness at a glance: IB
829
+ status (same three states as `aq ib status`), whether
830
+ `phase_v2.futures_risk.enabled`/`phase_v2.options_risk.enabled` are on,
831
+ how many futures contract margin specs are loaded, how much of the local
832
+ FRED yield-curve cache is populated (series count + most recent date),
833
+ and how many futures/options assets are actually configured in
834
+ `config.json`'s universe. Read-only reporting — toggling any of these
835
+ asset classes on or off is done with the existing generic
836
+ `aq config set phase_v2.{ib,futures_risk,options_risk}.enabled true|false`
837
+ (no separate enable/disable subcommand needed).
786
838
 
787
839
  #### `aq status`
788
840
  ```text
@@ -948,7 +1000,21 @@ architecture docs already identify:
948
1000
  - **A low-latency, event-driven runtime** — replacing the daily-bar `on_data()` callback and the 30s+ polling background workers with something closer to a real-time event loop.
949
1001
  - **Real broker/exchange connectivity beyond paper trading** — building on the credential/readiness groundwork V2-21/V2-22 already laid.
950
1002
  - **Continuous / online retraining** — moving beyond today's offline, cooldown-gated batch retraining pipeline.
951
- - Further out: an expanded asset universe, multi-timeframe ensembles, and reinforcement-learning-based position sizing/execution.
1003
+ - Further out: multi-timeframe ensembles and reinforcement-learning-based position sizing/execution.
1004
+
1005
+ **Expanded asset universe — delivered.** Bonds, futures, and options now
1006
+ trade and are observed alongside equities/crypto, with real duration-aware
1007
+ bond features, a margin-based futures risk model, Black-Scholes options
1008
+ greeks/IV, real order placement (including for options, against the
1009
+ specific resolved contract), and Interactive Brokers as the futures/options
1010
+ data source (toggleable via `aq config set phase_v2.ib.enabled`/`aq ib
1011
+ status` — the whole system works fully with IB disabled). See `aq fetch
1012
+ futures`/`aq fetch options` above and `risk/README.md`,
1013
+ `portfolio/README.md`, `features/README.md` for the full design. See
1014
+ [Known Limitations](#known-limitations) above for what's still deliberately
1015
+ out of scope (automatic multi-leg spread selection) or unverified (no
1016
+ completed backtest or live IB Gateway test yet), and
1017
+ `development/Problems.md` #29 for the full non-goals list.
952
1018
 
953
1019
  ## Contributing
954
1020
 
@@ -959,6 +1025,12 @@ architecture docs already identify:
959
1025
 
960
1026
  ---
961
1027
 
1028
+ <p align="center">
1029
+ Built by <strong>Leon Schwarzkopf</strong> — -//-
1030
+ </p>
1031
+
1032
+ ---
1033
+
962
1034
  <div align="center">
963
1035
  <sub>Aether Quant</sub>
964
1036
  </div>
@@ -1,5 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aether-quant
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: Aether Quant convenience CLI
5
5
  Requires-Python: >=3.10
6
+ License-File: LICENSE
7
+ Dynamic: license-file