quantred 2.4.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 (334) hide show
  1. quantred-2.4.0/.dockerignore +23 -0
  2. quantred-2.4.0/.env.example +27 -0
  3. quantred-2.4.0/.github/pull_request_template.md +22 -0
  4. quantred-2.4.0/.github/scripts/require_published_dependency.py +65 -0
  5. quantred-2.4.0/.github/workflows/ci.yml +102 -0
  6. quantred-2.4.0/.github/workflows/docs.yml +110 -0
  7. quantred-2.4.0/.github/workflows/release.yml +98 -0
  8. quantred-2.4.0/.gitignore +171 -0
  9. quantred-2.4.0/.gitleaksignore +5 -0
  10. quantred-2.4.0/.nvmrc +1 -0
  11. quantred-2.4.0/AGENTS.md +53 -0
  12. quantred-2.4.0/CLAUDE.md +1 -0
  13. quantred-2.4.0/CONTRIBUTING.md +75 -0
  14. quantred-2.4.0/Dockerfile +62 -0
  15. quantred-2.4.0/LICENSE +21 -0
  16. quantred-2.4.0/Makefile +213 -0
  17. quantred-2.4.0/PKG-INFO +632 -0
  18. quantred-2.4.0/README.md +573 -0
  19. quantred-2.4.0/conftest.py +14 -0
  20. quantred-2.4.0/docker-compose.yml +127 -0
  21. quantred-2.4.0/docs/.nvmrc +1 -0
  22. quantred-2.4.0/docs/content/changelog.md +1107 -0
  23. quantred-2.4.0/docs/content/engineering/alphas.md +246 -0
  24. quantred-2.4.0/docs/content/engineering/architecture.md +93 -0
  25. quantred-2.4.0/docs/content/engineering/attribution.md +131 -0
  26. quantred-2.4.0/docs/content/engineering/broker-abstraction.md +163 -0
  27. quantred-2.4.0/docs/content/engineering/coding-standards.md +71 -0
  28. quantred-2.4.0/docs/content/engineering/data-flow.md +77 -0
  29. quantred-2.4.0/docs/content/engineering/data-panel.md +93 -0
  30. quantred-2.4.0/docs/content/engineering/embedding.md +95 -0
  31. quantred-2.4.0/docs/content/engineering/engine.md +166 -0
  32. quantred-2.4.0/docs/content/engineering/evaluation-metrics.md +128 -0
  33. quantred-2.4.0/docs/content/engineering/extending.md +180 -0
  34. quantred-2.4.0/docs/content/engineering/indicators.md +55 -0
  35. quantred-2.4.0/docs/content/engineering/information-analysis.md +108 -0
  36. quantred-2.4.0/docs/content/engineering/information-horizon.md +94 -0
  37. quantred-2.4.0/docs/content/engineering/mcp-server.md +324 -0
  38. quantred-2.4.0/docs/content/engineering/multi-period-trading.md +147 -0
  39. quantred-2.4.0/docs/content/engineering/multi-signal.md +89 -0
  40. quantred-2.4.0/docs/content/engineering/optimization.md +123 -0
  41. quantred-2.4.0/docs/content/engineering/philosophy.md +101 -0
  42. quantred-2.4.0/docs/content/engineering/portfolio-construction.md +266 -0
  43. quantred-2.4.0/docs/content/engineering/portfolio.md +75 -0
  44. quantred-2.4.0/docs/content/engineering/research-agent.md +145 -0
  45. quantred-2.4.0/docs/content/engineering/risk-model.md +145 -0
  46. quantred-2.4.0/docs/content/engineering/scanners.md +55 -0
  47. quantred-2.4.0/docs/content/engineering/separation-of-concerns.md +74 -0
  48. quantred-2.4.0/docs/content/engineering/strategies.md +140 -0
  49. quantred-2.4.0/docs/content/engineering/testing.md +89 -0
  50. quantred-2.4.0/docs/content/engineering/transaction-costs.md +105 -0
  51. quantred-2.4.0/docs/content/engineering/verdict.md +137 -0
  52. quantred-2.4.0/docs/content/engineering/walk-forward.md +263 -0
  53. quantred-2.4.0/docs/content/intro.md +94 -0
  54. quantred-2.4.0/docs/content/usage/agents.md +241 -0
  55. quantred-2.4.0/docs/content/usage/alphas.md +157 -0
  56. quantred-2.4.0/docs/content/usage/backtesting.md +305 -0
  57. quantred-2.4.0/docs/content/usage/brokers.md +58 -0
  58. quantred-2.4.0/docs/content/usage/configuration.md +215 -0
  59. quantred-2.4.0/docs/content/usage/docker.md +123 -0
  60. quantred-2.4.0/docs/content/usage/extras.md +75 -0
  61. quantred-2.4.0/docs/content/usage/first-run.md +300 -0
  62. quantred-2.4.0/docs/content/usage/getting-started.md +223 -0
  63. quantred-2.4.0/docs/content/usage/horizon.md +71 -0
  64. quantred-2.4.0/docs/content/usage/html-reports.md +106 -0
  65. quantred-2.4.0/docs/content/usage/information.md +190 -0
  66. quantred-2.4.0/docs/content/usage/installation.md +136 -0
  67. quantred-2.4.0/docs/content/usage/live-trading.md +941 -0
  68. quantred-2.4.0/docs/content/usage/migrating-to-quantred.md +256 -0
  69. quantred-2.4.0/docs/content/usage/optimization.md +146 -0
  70. quantred-2.4.0/docs/content/usage/portfolio.md +202 -0
  71. quantred-2.4.0/docs/content/usage/private-strategies.md +182 -0
  72. quantred-2.4.0/docs/content/usage/risk.md +109 -0
  73. quantred-2.4.0/docs/content/usage/run-configs.md +121 -0
  74. quantred-2.4.0/docs/content/usage/scanning.md +97 -0
  75. quantred-2.4.0/docs/content/usage/screening.md +139 -0
  76. quantred-2.4.0/docs/content/usage/stopping.md +223 -0
  77. quantred-2.4.0/docs/content/usage/trials.md +632 -0
  78. quantred-2.4.0/docs/content/usage/validation-diagnostics.md +271 -0
  79. quantred-2.4.0/docs/content/usage/verdict.md +204 -0
  80. quantred-2.4.0/docs/content/usage/walk-forward.md +344 -0
  81. quantred-2.4.0/docs/docusaurus.config.js +77 -0
  82. quantred-2.4.0/docs/package-lock.json +20967 -0
  83. quantred-2.4.0/docs/package.json +28 -0
  84. quantred-2.4.0/docs/sidebars.js +80 -0
  85. quantred-2.4.0/docs/src/css/custom.css +15 -0
  86. quantred-2.4.0/docs/static/.gitkeep +0 -0
  87. quantred-2.4.0/docs/static/img/demo.png +0 -0
  88. quantred-2.4.0/docs/wrangler.jsonc +14 -0
  89. quantred-2.4.0/example/.gitignore +8 -0
  90. quantred-2.4.0/example/README.md +206 -0
  91. quantred-2.4.0/example/configs/breakout.json +29 -0
  92. quantred-2.4.0/example/configs/reversion_longshort.json +31 -0
  93. quantred-2.4.0/example/my_signals/__init__.py +0 -0
  94. quantred-2.4.0/example/my_signals/scanners/__init__.py +5 -0
  95. quantred-2.4.0/example/my_signals/scanners/liquidity.py +85 -0
  96. quantred-2.4.0/example/my_signals/strategies/__init__.py +11 -0
  97. quantred-2.4.0/example/my_signals/strategies/breakout.py +156 -0
  98. quantred-2.4.0/example/my_signals/strategies/pairs_reversion.py +133 -0
  99. quantred-2.4.0/example/pyproject.toml +39 -0
  100. quantred-2.4.0/main.py +14 -0
  101. quantred-2.4.0/pyproject.toml +172 -0
  102. quantred-2.4.0/quantred/__init__.py +24 -0
  103. quantred-2.4.0/quantred/alphas/__init__.py +53 -0
  104. quantred-2.4.0/quantred/alphas/base.py +221 -0
  105. quantred-2.4.0/quantred/alphas/combine.py +260 -0
  106. quantred-2.4.0/quantred/alphas/horizon.py +153 -0
  107. quantred-2.4.0/quantred/alphas/refine.py +300 -0
  108. quantred-2.4.0/quantred/alphas/scorers.py +87 -0
  109. quantred-2.4.0/quantred/analytics/attribution.py +354 -0
  110. quantred-2.4.0/quantred/analytics/bootstrap.py +353 -0
  111. quantred-2.4.0/quantred/analytics/charts.py +393 -0
  112. quantred-2.4.0/quantred/analytics/excursion.py +185 -0
  113. quantred-2.4.0/quantred/analytics/execution_quality.py +180 -0
  114. quantred-2.4.0/quantred/analytics/exposure.py +167 -0
  115. quantred-2.4.0/quantred/analytics/htmlreport.py +1208 -0
  116. quantred-2.4.0/quantred/analytics/information.py +197 -0
  117. quantred-2.4.0/quantred/analytics/metrics.py +502 -0
  118. quantred-2.4.0/quantred/analytics/performance.py +639 -0
  119. quantred-2.4.0/quantred/analytics/reporting.py +1672 -0
  120. quantred-2.4.0/quantred/analytics/screening.py +190 -0
  121. quantred-2.4.0/quantred/analytics/series_comparison.py +303 -0
  122. quantred-2.4.0/quantred/analytics/trade_analytics.py +353 -0
  123. quantred-2.4.0/quantred/brokers/alpaca/broker.py +415 -0
  124. quantred-2.4.0/quantred/brokers/alpaca/factory.py +33 -0
  125. quantred-2.4.0/quantred/brokers/alpaca/market_data.py +166 -0
  126. quantred-2.4.0/quantred/brokers/base.py +220 -0
  127. quantred-2.4.0/quantred/brokers/dryrun.py +164 -0
  128. quantred-2.4.0/quantred/brokers/errors.py +70 -0
  129. quantred-2.4.0/quantred/cli.py +8619 -0
  130. quantred-2.4.0/quantred/costs/__init__.py +11 -0
  131. quantred-2.4.0/quantred/costs/base.py +126 -0
  132. quantred-2.4.0/quantred/costs/parametric.py +131 -0
  133. quantred-2.4.0/quantred/data/__init__.py +29 -0
  134. quantred-2.4.0/quantred/data/compute.py +332 -0
  135. quantred-2.4.0/quantred/data/edges.py +81 -0
  136. quantred-2.4.0/quantred/data/features.py +120 -0
  137. quantred-2.4.0/quantred/data/panel.py +61 -0
  138. quantred-2.4.0/quantred/data/scan.py +85 -0
  139. quantred-2.4.0/quantred/data/store.py +269 -0
  140. quantred-2.4.0/quantred/demo/__init__.py +22 -0
  141. quantred-2.4.0/quantred/demo/scanners.py +104 -0
  142. quantred-2.4.0/quantred/demo/strategies.py +125 -0
  143. quantred-2.4.0/quantred/engine/backtest.py +1206 -0
  144. quantred-2.4.0/quantred/engine/barcheck.py +228 -0
  145. quantred-2.4.0/quantred/engine/live.py +539 -0
  146. quantred-2.4.0/quantred/execution/decision.py +192 -0
  147. quantred-2.4.0/quantred/execution/flatten.py +302 -0
  148. quantred-2.4.0/quantred/execution/halt.py +165 -0
  149. quantred-2.4.0/quantred/execution/ledger.py +758 -0
  150. quantred-2.4.0/quantred/execution/live_trader.py +587 -0
  151. quantred-2.4.0/quantred/execution/order_id.py +83 -0
  152. quantred-2.4.0/quantred/execution/sizing.py +114 -0
  153. quantred-2.4.0/quantred/indicators/indicators.py +158 -0
  154. quantred-2.4.0/quantred/marketdata/base.py +62 -0
  155. quantred-2.4.0/quantred/marketdata/client.py +59 -0
  156. quantred-2.4.0/quantred/marketdata/session.py +112 -0
  157. quantred-2.4.0/quantred/marketdata/synthetic.py +74 -0
  158. quantred-2.4.0/quantred/marketdata/timeframe.py +125 -0
  159. quantred-2.4.0/quantred/mcp/__init__.py +6 -0
  160. quantred-2.4.0/quantred/mcp/selftest.py +139 -0
  161. quantred-2.4.0/quantred/mcp/server.py +2419 -0
  162. quantred-2.4.0/quantred/optimization/causality.py +607 -0
  163. quantred-2.4.0/quantred/optimization/config_store.py +300 -0
  164. quantred-2.4.0/quantred/optimization/optimizer.py +431 -0
  165. quantred-2.4.0/quantred/optimization/parallel.py +345 -0
  166. quantred-2.4.0/quantred/optimization/param_space.py +309 -0
  167. quantred-2.4.0/quantred/optimization/walk_forward.py +1254 -0
  168. quantred-2.4.0/quantred/portfolio/allocator.py +135 -0
  169. quantred-2.4.0/quantred/portfolio/benchmark.py +109 -0
  170. quantred-2.4.0/quantred/portfolio/optimizer.py +786 -0
  171. quantred-2.4.0/quantred/portfolio/policy.py +335 -0
  172. quantred-2.4.0/quantred/portfolio/posterior.py +208 -0
  173. quantred-2.4.0/quantred/research/__init__.py +30 -0
  174. quantred-2.4.0/quantred/research/agent.py +868 -0
  175. quantred-2.4.0/quantred/research/demo_proposals.py +222 -0
  176. quantred-2.4.0/quantred/research/llm.py +311 -0
  177. quantred-2.4.0/quantred/research/proposer.py +234 -0
  178. quantred-2.4.0/quantred/research/provider_errors.py +242 -0
  179. quantred-2.4.0/quantred/research/sandbox.py +340 -0
  180. quantred-2.4.0/quantred/risk/__init__.py +60 -0
  181. quantred-2.4.0/quantred/risk/base.py +218 -0
  182. quantred-2.4.0/quantred/risk/conditional.py +474 -0
  183. quantred-2.4.0/quantred/risk/exposures.py +88 -0
  184. quantred-2.4.0/quantred/risk/factor.py +119 -0
  185. quantred-2.4.0/quantred/risk/sample.py +89 -0
  186. quantred-2.4.0/quantred/risk/streaming.py +214 -0
  187. quantred-2.4.0/quantred/scanners/base.py +141 -0
  188. quantred-2.4.0/quantred/scanners/symbol_scanner.py +148 -0
  189. quantred-2.4.0/quantred/services/__init__.py +51 -0
  190. quantred-2.4.0/quantred/services/analysis.py +6082 -0
  191. quantred-2.4.0/quantred/services/audit.py +574 -0
  192. quantred-2.4.0/quantred/services/campaign.py +381 -0
  193. quantred-2.4.0/quantred/services/configs.py +282 -0
  194. quantred-2.4.0/quantred/services/data.py +172 -0
  195. quantred-2.4.0/quantred/services/dryrun.py +206 -0
  196. quantred-2.4.0/quantred/services/glossary.py +130 -0
  197. quantred-2.4.0/quantred/services/maintenance.py +314 -0
  198. quantred-2.4.0/quantred/services/registry.py +351 -0
  199. quantred-2.4.0/quantred/services/setup.py +1023 -0
  200. quantred-2.4.0/quantred/services/sizing.py +150 -0
  201. quantred-2.4.0/quantred/services/smallreal.py +450 -0
  202. quantred-2.4.0/quantred/settings.py +571 -0
  203. quantred-2.4.0/quantred/store/__init__.py +0 -0
  204. quantred-2.4.0/quantred/store/bars.py +660 -0
  205. quantred-2.4.0/quantred/store/trials.py +1804 -0
  206. quantred-2.4.0/quantred/strategies/base.py +643 -0
  207. quantred-2.4.0/quantred/strategies/signals.py +28 -0
  208. quantred-2.4.0/quantred/utils/errors.py +48 -0
  209. quantred-2.4.0/quantred/utils/extras.py +330 -0
  210. quantred-2.4.0/quantred/utils/logging_config.py +33 -0
  211. quantred-2.4.0/quantred/utils/numeric.py +46 -0
  212. quantred-2.4.0/quantred/utils/streaming.py +474 -0
  213. quantred-2.4.0/quantred/utils/timeutils.py +148 -0
  214. quantred-2.4.0/scripts/check_links.py +162 -0
  215. quantred-2.4.0/scripts/compose_smoke.sh +86 -0
  216. quantred-2.4.0/tests/conftest.py +39 -0
  217. quantred-2.4.0/tests/fakes.py +500 -0
  218. quantred-2.4.0/tests/state_leak_guard.py +100 -0
  219. quantred-2.4.0/tests/test_alphas.py +307 -0
  220. quantred-2.4.0/tests/test_attribution.py +447 -0
  221. quantred-2.4.0/tests/test_backtest.py +1209 -0
  222. quantred-2.4.0/tests/test_backtest_surface_parity.py +148 -0
  223. quantred-2.4.0/tests/test_bar_cache.py +664 -0
  224. quantred-2.4.0/tests/test_bar_path_concurrency.py +186 -0
  225. quantred-2.4.0/tests/test_benchmark_portfolio.py +109 -0
  226. quantred-2.4.0/tests/test_black_litterman.py +227 -0
  227. quantred-2.4.0/tests/test_bootstrap_skill.py +262 -0
  228. quantred-2.4.0/tests/test_broker_errors.py +203 -0
  229. quantred-2.4.0/tests/test_campaign_material.py +665 -0
  230. quantred-2.4.0/tests/test_causality_probes.py +365 -0
  231. quantred-2.4.0/tests/test_cli_dates.py +280 -0
  232. quantred-2.4.0/tests/test_cli_help.py +95 -0
  233. quantred-2.4.0/tests/test_cli_hints.py +83 -0
  234. quantred-2.4.0/tests/test_cli_input_refusals.py +705 -0
  235. quantred-2.4.0/tests/test_cli_name.py +229 -0
  236. quantred-2.4.0/tests/test_closing_inventory.py +108 -0
  237. quantred-2.4.0/tests/test_combine.py +121 -0
  238. quantred-2.4.0/tests/test_compute.py +464 -0
  239. quantred-2.4.0/tests/test_conditional_risk.py +345 -0
  240. quantred-2.4.0/tests/test_conditional_risk_service.py +167 -0
  241. quantred-2.4.0/tests/test_cost_aware.py +543 -0
  242. quantred-2.4.0/tests/test_costs.py +143 -0
  243. quantred-2.4.0/tests/test_data.py +110 -0
  244. quantred-2.4.0/tests/test_diagnostic_surfaces.py +565 -0
  245. quantred-2.4.0/tests/test_docs_commands.py +190 -0
  246. quantred-2.4.0/tests/test_dry_run.py +626 -0
  247. quantred-2.4.0/tests/test_dst_boundaries.py +151 -0
  248. quantred-2.4.0/tests/test_example_pack.py +288 -0
  249. quantred-2.4.0/tests/test_execution_quality.py +413 -0
  250. quantred-2.4.0/tests/test_extension_registry.py +511 -0
  251. quantred-2.4.0/tests/test_extras_map.py +478 -0
  252. quantred-2.4.0/tests/test_forecast_refinement_v2.py +285 -0
  253. quantred-2.4.0/tests/test_halt.py +631 -0
  254. quantred-2.4.0/tests/test_holdout_history.py +170 -0
  255. quantred-2.4.0/tests/test_honest_labels.py +287 -0
  256. quantred-2.4.0/tests/test_horizon.py +121 -0
  257. quantred-2.4.0/tests/test_html_report.py +386 -0
  258. quantred-2.4.0/tests/test_html_report_ux.py +304 -0
  259. quantred-2.4.0/tests/test_information.py +161 -0
  260. quantred-2.4.0/tests/test_ledger_fill_accounting.py +725 -0
  261. quantred-2.4.0/tests/test_links.py +110 -0
  262. quantred-2.4.0/tests/test_live_hardening.py +1116 -0
  263. quantred-2.4.0/tests/test_live_portfolio_cli.py +456 -0
  264. quantred-2.4.0/tests/test_live_trader.py +575 -0
  265. quantred-2.4.0/tests/test_long_short.py +380 -0
  266. quantred-2.4.0/tests/test_market_data_feed.py +112 -0
  267. quantred-2.4.0/tests/test_mcp_bad_input.py +118 -0
  268. quantred-2.4.0/tests/test_mcp_description_truth.py +538 -0
  269. quantred-2.4.0/tests/test_mcp_json_safe.py +115 -0
  270. quantred-2.4.0/tests/test_mcp_keyless.py +125 -0
  271. quantred-2.4.0/tests/test_mcp_save_config.py +163 -0
  272. quantred-2.4.0/tests/test_mcp_shutdown.py +277 -0
  273. quantred-2.4.0/tests/test_mcp_stdio.py +285 -0
  274. quantred-2.4.0/tests/test_mcp_surface.py +1195 -0
  275. quantred-2.4.0/tests/test_memoized_backtest.py +205 -0
  276. quantred-2.4.0/tests/test_min_notional_parity.py +148 -0
  277. quantred-2.4.0/tests/test_model_probe.py +486 -0
  278. quantred-2.4.0/tests/test_multi_period_policy.py +437 -0
  279. quantred-2.4.0/tests/test_net_cap_derivation.py +184 -0
  280. quantred-2.4.0/tests/test_net_exposure.py +142 -0
  281. quantred-2.4.0/tests/test_offline.py +112 -0
  282. quantred-2.4.0/tests/test_optimizer.py +110 -0
  283. quantred-2.4.0/tests/test_optimizer_book.py +150 -0
  284. quantred-2.4.0/tests/test_packaging.py +362 -0
  285. quantred-2.4.0/tests/test_parallel_trials.py +303 -0
  286. quantred-2.4.0/tests/test_param_constraints.py +220 -0
  287. quantred-2.4.0/tests/test_portfolio.py +55 -0
  288. quantred-2.4.0/tests/test_portfolio_excursion.py +276 -0
  289. quantred-2.4.0/tests/test_portfolio_optimizer.py +351 -0
  290. quantred-2.4.0/tests/test_promoted_cost.py +128 -0
  291. quantred-2.4.0/tests/test_release_order.py +70 -0
  292. quantred-2.4.0/tests/test_research.py +615 -0
  293. quantred-2.4.0/tests/test_research_cli.py +251 -0
  294. quantred-2.4.0/tests/test_research_history.py +133 -0
  295. quantred-2.4.0/tests/test_research_rounds.py +284 -0
  296. quantred-2.4.0/tests/test_risk.py +228 -0
  297. quantred-2.4.0/tests/test_risk_streaming.py +215 -0
  298. quantred-2.4.0/tests/test_run_config.py +956 -0
  299. quantred-2.4.0/tests/test_run_context.py +549 -0
  300. quantred-2.4.0/tests/test_saved_config_book.py +343 -0
  301. quantred-2.4.0/tests/test_scanner.py +245 -0
  302. quantred-2.4.0/tests/test_screen_command.py +246 -0
  303. quantred-2.4.0/tests/test_screening.py +180 -0
  304. quantred-2.4.0/tests/test_series_comparison.py +324 -0
  305. quantred-2.4.0/tests/test_services.py +1066 -0
  306. quantred-2.4.0/tests/test_settings.py +102 -0
  307. quantred-2.4.0/tests/test_setup.py +1149 -0
  308. quantred-2.4.0/tests/test_shutdown_signals.py +459 -0
  309. quantred-2.4.0/tests/test_signal_causality.py +255 -0
  310. quantred-2.4.0/tests/test_small_real_command.py +931 -0
  311. quantred-2.4.0/tests/test_small_real_contract.py +447 -0
  312. quantred-2.4.0/tests/test_state_leak_guard.py +346 -0
  313. quantred-2.4.0/tests/test_state_root.py +417 -0
  314. quantred-2.4.0/tests/test_store.py +195 -0
  315. quantred-2.4.0/tests/test_strategy.py +149 -0
  316. quantred-2.4.0/tests/test_strategy_registry.py +51 -0
  317. quantred-2.4.0/tests/test_stream.py +97 -0
  318. quantred-2.4.0/tests/test_stream_close.py +134 -0
  319. quantred-2.4.0/tests/test_surface_parity.py +1091 -0
  320. quantred-2.4.0/tests/test_synthetic.py +50 -0
  321. quantred-2.4.0/tests/test_trade_analytics.py +356 -0
  322. quantred-2.4.0/tests/test_trade_command_output.py +303 -0
  323. quantred-2.4.0/tests/test_trade_update_handling.py +340 -0
  324. quantred-2.4.0/tests/test_transition_package.py +217 -0
  325. quantred-2.4.0/tests/test_trial_browser.py +788 -0
  326. quantred-2.4.0/tests/test_trial_history_labels.py +313 -0
  327. quantred-2.4.0/tests/test_trial_id_prefix.py +135 -0
  328. quantred-2.4.0/tests/test_trial_store.py +775 -0
  329. quantred-2.4.0/tests/test_trial_store_maintenance.py +421 -0
  330. quantred-2.4.0/tests/test_units.py +228 -0
  331. quantred-2.4.0/tests/test_verdict.py +905 -0
  332. quantred-2.4.0/tests/test_walk_forward.py +751 -0
  333. quantred-2.4.0/tests/test_walk_forward_evidence_parity.py +219 -0
  334. quantred-2.4.0/uv.lock +3027 -0
@@ -0,0 +1,23 @@
1
+ # An allowlist, not a denylist: the Dockerfile copies the build context, and a
2
+ # checkout holds things that must never reach an image - `.env` (broker credentials),
3
+ # the gitignored `specs/`, `configs/` and `logs/` (a campaign's private strategy
4
+ # evidence and journal), `cache/`, `.git`, virtual environments and node_modules.
5
+ # A denylist misses the next one somebody adds; this names only what the image runs.
6
+ *
7
+
8
+ !pyproject.toml
9
+ !uv.lock
10
+ !README.md
11
+ !LICENSE
12
+ !main.py
13
+ !quantred/
14
+ !example/
15
+
16
+ # Even inside the allowed trees.
17
+ **/__pycache__
18
+ **/*.pyc
19
+ **/.pytest_cache
20
+ **/.ruff_cache
21
+ **/.DS_Store
22
+ **/.env
23
+ **/.venv
@@ -0,0 +1,27 @@
1
+ # Copy this file to .env and fill in your Alpaca credentials.
2
+ # .env is gitignored, so your keys are never committed.
3
+ #
4
+ # Get free paper-trading keys at https://app.alpaca.markets/
5
+ # -> Paper Account -> API Keys
6
+ #
7
+ # (No keys needed just to explore — run `make demo` for an offline walkthrough.)
8
+
9
+ APCA_API_KEY_ID=<APCA_API_KEY_ID>
10
+ APCA_API_SECRET_KEY=<APCA_API_SECRET_KEY>
11
+
12
+ # Keep this true until you are absolutely sure you want to trade real money.
13
+ PAPER_TRADE=true
14
+
15
+
16
+ # --- Optional: AI research agent (`python main.py research`) -----------------
17
+ # Only needed if you run the research agent. Set the key for the provider you
18
+ # use (or export it as a normal environment variable — either works). Ollama
19
+ # runs locally and needs no key.
20
+ #
21
+ # --provider anthropic (default): ANTHROPIC_API_KEY (needs the `ai` extra)
22
+ # --provider openai: OPENAI_API_KEY (needs the `openai` extra)
23
+ # --provider ollama (local): no key; optional OLLAMA_BASE_URL
24
+ #
25
+ # ANTHROPIC_API_KEY=sk-ant-...
26
+ # OPENAI_API_KEY=sk-...
27
+ # OLLAMA_BASE_URL=http://localhost:11434
@@ -0,0 +1,22 @@
1
+ <!-- Keep PRs small and focused on one layer/concern where possible. -->
2
+
3
+ ## What & why
4
+
5
+ <!-- What does this change do, and why? Link any issue. -->
6
+
7
+ ## How
8
+
9
+ <!-- Notable implementation choices, especially anything affecting a layer boundary. -->
10
+
11
+ ## Checklist
12
+
13
+ - [ ] `make test` passes (offline; no keys needed)
14
+ - [ ] `uv run ruff check .` and `uv run ruff format --check .` are clean
15
+ - [ ] New/changed behavior is covered by tests
16
+ - [ ] No vendor SDK (`alpaca`, ...) imported above the broker layer
17
+ - [ ] Touches one concern per layer (see [Separation of concerns](../docs/content/engineering/separation-of-concerns.md))
18
+ - [ ] Docs updated if usage or architecture changed (README / `docs/content`)
19
+
20
+ ## Screenshots / output
21
+
22
+ <!-- e.g. a backtest report, scan output, or relevant logs. Optional. -->
@@ -0,0 +1,65 @@
1
+ """Fail unless the engine version the transition package requires is already on PyPI.
2
+
3
+ The transition release of the old distribution name depends on ``quantred``. PyPI never
4
+ lets a version be replaced, so publishing it before a satisfying ``quantred`` exists would
5
+ leave a permanent release whose dependency cannot be installed. The tag order is a human
6
+ convention; this makes it a check.
7
+
8
+ Usage: require_published_dependency.py <pyproject.toml> [<releases.json>]
9
+ Without the second argument the release list is fetched from PyPI.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import json
15
+ import sys
16
+ import urllib.error
17
+ import urllib.request
18
+
19
+ import tomllib
20
+ from packaging.requirements import Requirement
21
+ from packaging.version import Version
22
+
23
+ TARGET = "quantred"
24
+
25
+
26
+ def satisfied(pyproject_text: str, releases: dict) -> str:
27
+ """The newest un-yanked release meeting the dependency, or raise SystemExit."""
28
+ deps = tomllib.loads(pyproject_text)["project"]["dependencies"]
29
+ wanted = [r for r in map(Requirement, deps) if r.name == TARGET]
30
+ if not wanted:
31
+ raise SystemExit(f"the transition package declares no dependency on {TARGET}")
32
+ spec = wanted[0].specifier
33
+ live = [
34
+ version
35
+ for version, files in releases.items()
36
+ if files and not all(f.get("yanked") for f in files) and version in spec
37
+ ]
38
+ if not live:
39
+ raise SystemExit(
40
+ f"{TARGET}{spec} is not on PyPI yet; publish it before the transition package "
41
+ "(a published release cannot be replaced)"
42
+ )
43
+ return str(max(map(Version, live)))
44
+
45
+
46
+ def main(argv: list[str]) -> int:
47
+ with open(argv[1], encoding="utf-8") as handle:
48
+ text = handle.read()
49
+ if len(argv) > 2:
50
+ with open(argv[2], encoding="utf-8") as handle:
51
+ data = json.load(handle)
52
+ else:
53
+ try:
54
+ with urllib.request.urlopen(f"https://pypi.org/pypi/{TARGET}/json", timeout=30) as response:
55
+ data = json.load(response)
56
+ except urllib.error.HTTPError as exc:
57
+ if exc.code != 404:
58
+ raise
59
+ data = {"releases": {}} # no such project yet: nothing satisfies the dependency
60
+ print(f"found {TARGET} {satisfied(text, data['releases'])}")
61
+ return 0
62
+
63
+
64
+ if __name__ == "__main__":
65
+ sys.exit(main(sys.argv))
@@ -0,0 +1,102 @@
1
+ name: CI
2
+
3
+ on:
4
+ # Every branch, not just main: the secret scan below is only useful if it sees a
5
+ # push that has no pull request behind it. The expensive job stays gated to
6
+ # main + PRs via its own `if` — see lint-and-test.
7
+ push:
8
+ pull_request:
9
+
10
+ # Cancel superseded runs on the same ref.
11
+ concurrency:
12
+ group: ${{ github.workflow }}-${{ github.ref }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ lint-and-test:
17
+ # Unchanged behavior: pull requests, and pushes to main. A push to a topic
18
+ # branch with a PR open would otherwise run the whole suite twice.
19
+ if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main'
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: actions/checkout@v7
23
+
24
+ - name: Install uv
25
+ uses: astral-sh/setup-uv@v7
26
+ with:
27
+ enable-cache: true
28
+
29
+ - name: Install dependencies
30
+ run: uv sync --extra dev
31
+
32
+ # The example pack registers through the same entry-point groups a user's own
33
+ # pack does. Installing it here is what makes CI exercise that path end to end -
34
+ # real packaging, real discovery, real contract compliance - rather than only the
35
+ # monkeypatched fakes the registry unit tests use.
36
+ - name: Install the example pack (exercises entry-point discovery)
37
+ run: uv pip install --no-deps -e example
38
+
39
+ - name: Lint (ruff)
40
+ run: uv run ruff check .
41
+
42
+ - name: Format check (ruff)
43
+ run: uv run ruff format --check .
44
+
45
+ - name: Docs link check
46
+ # Relative links and heading anchors across the docs site and top-level
47
+ # Markdown, and no tracked link into the gitignored specs/.
48
+ run: uv run python scripts/check_links.py
49
+
50
+ - name: Compose config validates
51
+ # Cheap and daemon-free: catches a malformed compose file on every PR. The
52
+ # behavioral checks (state survives `down`, live never starts, volumes are
53
+ # host-readable) need a daemon and live in scripts/compose_smoke.sh, run
54
+ # locally and recorded in the PR.
55
+ run: docker compose config --quiet
56
+
57
+ - name: Tests (pytest)
58
+ run: uv run pytest -q
59
+
60
+ secret-scan:
61
+ # The repository is public, so a committed key is disclosed the moment it
62
+ # lands. Unlike lint-and-test this runs on *every* branch push, not only main
63
+ # and PRs — a secret pushed to a topic branch is already public whether or not
64
+ # anyone opens a pull request. A branch with a PR open therefore scans twice
65
+ # (push + pull_request); at half a second a run that is not worth avoiding.
66
+ #
67
+ # GitHub's own secret scanning + push protection is enabled on the repo and
68
+ # catches known provider formats before a push lands. This is the second
69
+ # layer — it runs on forks, and it fails the build rather than only alerting
70
+ # the owner.
71
+ runs-on: ubuntu-latest
72
+ steps:
73
+ - uses: actions/checkout@v7
74
+ with:
75
+ # Everything reachable from this ref, not just the diff: a secret deleted
76
+ # in a later commit is still readable in the one that added it, and the
77
+ # default shallow clone hides exactly those commits.
78
+ fetch-depth: 0
79
+
80
+ - name: Install gitleaks
81
+ # Pinned to an exact release rather than an action, so a scan is
82
+ # reproducible and no third-party code runs with the workflow token.
83
+ env:
84
+ GITLEAKS_VERSION: 8.30.1
85
+ run: |
86
+ curl -sSfL -o /tmp/gitleaks.tar.gz \
87
+ "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
88
+ tar -xzf /tmp/gitleaks.tar.gz -C /usr/local/bin gitleaks
89
+ gitleaks version
90
+
91
+ - name: Scan history for secrets
92
+ # --redact keeps any match out of the public build log; the finding is in
93
+ # the uploaded report. Exits non-zero when anything is found.
94
+ run: gitleaks git --no-banner --redact --report-path gitleaks-report.json .
95
+
96
+ - name: Upload findings
97
+ if: failure()
98
+ uses: actions/upload-artifact@v7
99
+ with:
100
+ name: gitleaks-report
101
+ path: gitleaks-report.json
102
+ if-no-files-found: ignore
@@ -0,0 +1,110 @@
1
+ name: Docs
2
+
3
+ # Builds the documentation site on every PR (the Docusaurus production build compiles
4
+ # every page and, with onBrokenLinks/onBrokenAnchors set to 'throw', fails on any dead
5
+ # internal link or anchor) — and deploys it on main.
6
+ #
7
+ # The deploy exists because it did not: the site was published by hand, so it silently
8
+ # fell behind the repository. A page could be written, reviewed, merged, and linked
9
+ # from the README while 404ing for every reader.
10
+ on:
11
+ push:
12
+ branches: [main]
13
+ paths:
14
+ - 'docs/**'
15
+ - '.github/workflows/docs.yml'
16
+ pull_request:
17
+ paths:
18
+ - 'docs/**'
19
+ - '.github/workflows/docs.yml'
20
+
21
+ # Cancel superseded runs on the same ref.
22
+ concurrency:
23
+ group: ${{ github.workflow }}-${{ github.ref }}
24
+ cancel-in-progress: true
25
+
26
+ jobs:
27
+ build-docs:
28
+ runs-on: ubuntu-latest
29
+ defaults:
30
+ run:
31
+ working-directory: docs
32
+ steps:
33
+ - uses: actions/checkout@v7
34
+
35
+ - name: Install Node
36
+ uses: actions/setup-node@v7
37
+ with:
38
+ # .nvmrc is the single source: a contributor running `nvm use` and CI build
39
+ # on the same major, and there is no second place to forget to update.
40
+ node-version-file: .nvmrc
41
+ cache: npm
42
+ cache-dependency-path: docs/package-lock.json
43
+
44
+ - name: Install dependencies
45
+ run: npm ci
46
+
47
+ - name: Build docs (fails on broken links/anchors)
48
+ run: npm run build
49
+
50
+ - name: Upload the built site
51
+ if: github.ref == 'refs/heads/main'
52
+ uses: actions/upload-artifact@v7
53
+ with:
54
+ name: docs-site
55
+ path: docs/build/
56
+
57
+ deploy:
58
+ name: Deploy to Cloudflare
59
+ # Only from main, and only once the build above has actually succeeded.
60
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
61
+ needs: build-docs
62
+ runs-on: ubuntu-latest
63
+ defaults:
64
+ run:
65
+ working-directory: docs
66
+ steps:
67
+ - uses: actions/checkout@v7
68
+
69
+ - uses: actions/setup-node@v7
70
+ with:
71
+ # .nvmrc is the single source: a contributor running `nvm use` and CI build
72
+ # on the same major, and there is no second place to forget to update.
73
+ node-version-file: .nvmrc
74
+ cache: npm
75
+ cache-dependency-path: docs/package-lock.json
76
+
77
+ - run: npm ci
78
+
79
+ - uses: actions/download-artifact@v8
80
+ with:
81
+ name: docs-site
82
+ path: docs/build/
83
+
84
+ # Fail with an explanation, not a bare exit code. Without this, a missing
85
+ # secret surfaces as `wrangler` exiting 1 with nothing to act on — the reader
86
+ # has to guess that a credential is the problem.
87
+ - name: Check the deploy credentials exist
88
+ env:
89
+ CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
90
+ run: |
91
+ if [ -z "$CLOUDFLARE_API_TOKEN" ]; then
92
+ echo "::error title=Missing deploy credentials::CLOUDFLARE_API_TOKEN is not set."
93
+ echo ""
94
+ echo "The docs site cannot deploy without it, so tradeflow.mk-dir.com will"
95
+ echo "keep serving whatever was last published by hand."
96
+ echo ""
97
+ echo "Add it at: Settings -> Secrets and variables -> Actions"
98
+ echo " CLOUDFLARE_API_TOKEN a token with the Workers Scripts:Edit permission"
99
+ echo " CLOUDFLARE_ACCOUNT_ID optional; only if the account is ambiguous"
100
+ echo ""
101
+ echo "To publish once by hand in the meantime:"
102
+ echo " cd docs && npx wrangler login && npm run deploy"
103
+ exit 1
104
+ fi
105
+
106
+ - name: Deploy
107
+ env:
108
+ CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
109
+ CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
110
+ run: npx wrangler deploy
@@ -0,0 +1,98 @@
1
+ name: Release
2
+
3
+ # Publishes to PyPI when a version tag is pushed. Two properties matter here:
4
+ #
5
+ # 1. The tests run first, and a failure stops the publish. A release is the one
6
+ # moment a broken build becomes someone else's problem permanently — PyPI
7
+ # versions cannot be replaced, only yanked.
8
+ # 2. No API token is stored anywhere. Publishing uses PyPI's trusted publishing
9
+ # (OIDC), so the only thing that can release is this workflow, from this
10
+ # repository, on a tag. A leaked secret cannot publish because there is no
11
+ # secret.
12
+ #
13
+ # Set up once at https://pypi.org/manage/project/quantred/settings/publishing/ (a new
14
+ # project name needs its own trusted publisher; the one registered for the previous
15
+ # distribution name does not carry over)
16
+ # owner: makedirectory repository: quantred
17
+ # workflow: release.yml environment: pypi
18
+ #
19
+ # A tag `v*` publishes the engine from the repository root. A tag `tradeflow-engine-v*`
20
+ # publishes the final transition release of the old distribution name from
21
+ # packaging/tradeflow-engine instead. That project's trusted publisher must name the
22
+ # repository as it is now called (`quantred`, renamed from the old one) and the same
23
+ # workflow `release.yml` and environment `pypi`.
24
+
25
+ on:
26
+ push:
27
+ tags: ["v*", "tradeflow-engine-v*"]
28
+ workflow_dispatch:
29
+
30
+ jobs:
31
+ verify:
32
+ name: Test before publishing
33
+ runs-on: ubuntu-latest
34
+ steps:
35
+ - uses: actions/checkout@v7
36
+ - uses: astral-sh/setup-uv@v7
37
+ with:
38
+ enable-cache: true
39
+ - run: uv sync --extra dev
40
+ - run: uv run ruff check .
41
+ - run: uv run ruff format --check .
42
+ - run: uv run pytest -q
43
+
44
+ build:
45
+ name: Build the distribution
46
+ needs: verify
47
+ runs-on: ubuntu-latest
48
+ steps:
49
+ - uses: actions/checkout@v7
50
+ - uses: astral-sh/setup-uv@v7
51
+ - name: Build the engine (tag v*, or a manual run)
52
+ if: ${{ !startsWith(github.ref, 'refs/tags/tradeflow-engine-v') }}
53
+ run: uv build
54
+ - name: Build the transition package (tag tradeflow-engine-v*)
55
+ if: startsWith(github.ref, 'refs/tags/tradeflow-engine-v')
56
+ run: uv build packaging/tradeflow-engine -o dist
57
+ # Catches a malformed README or bad metadata before it is permanent.
58
+ - run: uvx twine check dist/*
59
+ # The tag and the packaged version must agree, or the release notes describe
60
+ # something other than what was published.
61
+ - name: Tag matches the packaged version
62
+ if: startsWith(github.ref, 'refs/tags/v')
63
+ run: |
64
+ TAG="${GITHUB_REF_NAME#v}"
65
+ BUILT=$(ls dist/*.tar.gz | sed -E 's/.*-([0-9][^-]*)\.tar\.gz/\1/')
66
+ echo "tag=$TAG built=$BUILT"
67
+ test "$TAG" = "$BUILT"
68
+ - name: Tag matches the transition package's version
69
+ if: startsWith(github.ref, 'refs/tags/tradeflow-engine-v')
70
+ run: |
71
+ TAG="${GITHUB_REF_NAME#tradeflow-engine-v}"
72
+ BUILT=$(ls dist/tradeflow_engine-*.tar.gz | sed -E 's/.*-([0-9][^-]*)\.tar\.gz/\1/')
73
+ echo "tag=$TAG built=$BUILT"
74
+ test "$TAG" = "$BUILT"
75
+ # PyPI cannot replace a version. Publishing this before the engine release it
76
+ # requires exists would leave a permanent release whose dependency cannot be
77
+ # installed, so the order of the two tags is checked, not remembered.
78
+ - name: The engine release this requires is on PyPI
79
+ if: startsWith(github.ref, 'refs/tags/tradeflow-engine-v')
80
+ run: uv run --no-project --with packaging python .github/scripts/require_published_dependency.py packaging/tradeflow-engine/pyproject.toml
81
+ - uses: actions/upload-artifact@v7
82
+ with:
83
+ name: dist
84
+ path: dist/
85
+
86
+ publish:
87
+ name: Publish to PyPI
88
+ needs: build
89
+ runs-on: ubuntu-latest
90
+ environment: pypi
91
+ permissions:
92
+ id-token: write # the OIDC token trusted publishing exchanges for an upload
93
+ steps:
94
+ - uses: actions/download-artifact@v8
95
+ with:
96
+ name: dist
97
+ path: dist/
98
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,171 @@
1
+ # Generated artifacts
2
+ optimization_results.csv
3
+ walkforward_results.csv
4
+
5
+ # Saved strategy configs (a human promotes these; never auto-applied).
6
+ # Anchored to the repo root: unanchored, this matched a `configs/` at *any* depth and
7
+ # silently excluded the example pack's own config — so a fresh clone got a pack missing
8
+ # the artefact its README tells you to run.
9
+ /configs/
10
+
11
+ # MCP audit log, research journal, and run artifacts. Anchored for the same reason.
12
+ /logs/
13
+
14
+ # Persistent bar cache - derived from Alpaca, safe to delete. Anchored for the same reason.
15
+ /cache/
16
+
17
+ # Docs site (Docusaurus)
18
+ docs/node_modules/
19
+ docs/build/
20
+ docs/.docusaurus/
21
+
22
+ # Mongo Data
23
+ /data/db
24
+
25
+ # Below is a standard to gitignore file for Python
26
+ # Byte-compiled / optimized / DLL files
27
+ __pycache__/
28
+ *.py[cod]
29
+ *$py.class
30
+
31
+ # C extensions
32
+ *.so
33
+
34
+ # Distribution / packaging
35
+ .Python
36
+ build/
37
+ develop-eggs/
38
+ dist/
39
+ downloads/
40
+ eggs/
41
+ .eggs/
42
+ lib/
43
+ lib64/
44
+ parts/
45
+ sdist/
46
+ var/
47
+ wheels/
48
+ pip-wheel-metadata/
49
+ share/python-wheels/
50
+ *.egg-info/
51
+ .installed.cfg
52
+ *.egg
53
+ MANIFEST
54
+
55
+ # PyInstaller
56
+ # Usually these files are written by a python script from a template
57
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
58
+ *.manifest
59
+ *.spec
60
+
61
+ # Installer logs
62
+ pip-log.txt
63
+ pip-delete-this-directory.txt
64
+
65
+ # Unit test / coverage reports
66
+ htmlcov/
67
+ .tox/
68
+ .nox/
69
+ .coverage
70
+ .coverage.*
71
+ .cache
72
+ nosetests.xml
73
+ coverage.xml
74
+ *.cover
75
+ .hypothesis/
76
+ .pytest_cache/
77
+
78
+ # Translations
79
+ *.mo
80
+ *.pot
81
+
82
+ # Django stuff:
83
+ *.log
84
+ local_settings.py
85
+ db.sqlite3
86
+ db.sqlite3-journal
87
+
88
+ # Flask stuff:
89
+ instance/
90
+ .webassets-cache
91
+
92
+ # Scrapy stuff:
93
+ .scrapy
94
+
95
+ # Sphinx documentation
96
+ docs/_build/
97
+
98
+ # PyBuilder
99
+ target/
100
+
101
+ # Jupyter Notebook
102
+ .ipynb_checkpoints
103
+
104
+ # IPython
105
+ profile_default/
106
+ ipython_config.py
107
+
108
+ # pyenv
109
+ .python-version
110
+
111
+ # pipenv
112
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
113
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
114
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
115
+ # install all needed dependencies.
116
+ #Pipfile.lock
117
+
118
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
119
+ __pypackages__/
120
+
121
+ # Celery stuff
122
+ celerybeat-schedule
123
+ celerybeat.pid
124
+
125
+ # SageMath parsed files
126
+ *.sage.py
127
+
128
+ # Environments
129
+ .env
130
+ .venv
131
+ env/
132
+ venv/
133
+ ENV/
134
+ env.bak/
135
+ venv.bak/
136
+
137
+ # Spyder project settings
138
+ .spyderproject
139
+ .spyproject
140
+
141
+ # Rope project settings
142
+ .ropeproject
143
+
144
+ # mkdocs documentation
145
+ /site
146
+
147
+ # mypy
148
+ .mypy_cache/
149
+ .dmypy.json
150
+ dmypy.json
151
+
152
+ # Pyre type checker
153
+ .pyre/
154
+
155
+ # pytype static type analyzer
156
+ .pytype/
157
+
158
+ # Cython debug symbols
159
+ cython_debug/
160
+
161
+ # macOS
162
+ .DS_Store
163
+
164
+ # VS Code settings
165
+ .vscode/
166
+
167
+ # Ruff
168
+ .ruff_cache/
169
+
170
+ # Specs
171
+ specs/
@@ -0,0 +1,5 @@
1
+ # Fake API keys in test fixtures, already in history. Each test plants one to check that
2
+ # a key is never printed or written; neither has ever been a real credential. The lines
3
+ # themselves now carry `gitleaks:allow`, which covers them from here on.
4
+ 27eb2eebf0dbce4dda8ed77f70f6be45f763dcef:tests/test_setup.py:generic-api-key:640
5
+ c8a28fbac456371971c76681942d2a36c7c9cabf:tests/test_model_probe.py:generic-api-key:18
quantred-2.4.0/.nvmrc ADDED
@@ -0,0 +1 @@
1
+ 24
@@ -0,0 +1,53 @@
1
+ # Working on QuantRed
2
+
3
+ Topic rules live in `.claude/rules/`; the cycle a change goes through, and the gate it
4
+ has to pass, are in [how a change gets built here](.claude/rules/build-process.md). The
5
+ procedures that cycle names are skills — `review-gate`, `consolidation-pass`,
6
+ `dependency-truth` — and `/ship-check` reports what the definition of done is missing.
7
+ This file is only what is true in every session.
8
+
9
+ ## The one invariant
10
+
11
+ **Two clocks.** The research clock (backtest, optimize, walk-forward, analytics, the
12
+ AI agent) is slow, exploratory, and only ever *proposes*. The trade clock
13
+ (`quantred/engine/live.py`, `quantred/execution/`) is deterministic and imports
14
+ **nothing** from `services/`, `analytics/`, `optimization/`, or `research/`.
15
+ Promotion between them is a manual human step.
16
+
17
+ A change that blurs this is wrong regardless of how well it works.
18
+
19
+ ## Verify, don't assert
20
+
21
+ The rule that has caught the most real defects here — every one of them looked
22
+ correct in the source:
23
+
24
+ - **Run the thing.** Installing the published package into a clean venv found four
25
+ onboarding dead ends that passed every test. An MCP dependency that every test and
26
+ lockfile agreed was fine shipped broken.
27
+ - **Check the environment, not the config.** Confirm an action tag resolves before
28
+ pushing it, a URL serves before linking it, a dependency's *resolved* version
29
+ rather than what the lockfile pinned.
30
+ - **Say what you actually verified**, and what you did not.
31
+
32
+ ## Commands
33
+
34
+ ```bash
35
+ uv run ruff check . && uv run ruff format --check . # exactly what CI runs
36
+ make test # offline, no keys
37
+ make check-links # tracked docs; specs/ never linked
38
+ make release-check # build + install into a clean venv
39
+ ```
40
+
41
+ ## Definition of done
42
+
43
+ Per [build-process](.claude/rules/build-process.md), none of it optional: right layer · offline deterministic tests via
44
+ `tests/fakes.py` · every applicable surface wired (CLI, MCP tool, Makefile) · docs
45
+ updated · all four commands above clean.
46
+
47
+ ## Git
48
+
49
+ - Branch off `main`; never commit to it directly.
50
+ - **Commit as you go.** Reconstructing per-change commits afterwards is impossible
51
+ once edits to shared files interleave.
52
+ - Messages explain the *why* and any deviation from plan; end with
53
+ `Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>`.
@@ -0,0 +1 @@
1
+ AGENTS.md