alphaengine 1.0.3__tar.gz → 1.1.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 (142) hide show
  1. {alphaengine-1.0.3 → alphaengine-1.1.0}/CHANGELOG.md +14 -0
  2. {alphaengine-1.0.3 → alphaengine-1.1.0}/PKG-INFO +102 -4
  3. {alphaengine-1.0.3 → alphaengine-1.1.0}/README.md +101 -3
  4. alphaengine-1.1.0/docs/plugins.md +60 -0
  5. alphaengine-1.1.0/docs/project-format.md +79 -0
  6. alphaengine-1.1.0/docs/result-format.md +89 -0
  7. alphaengine-1.1.0/examples/process_stress_monitor.yaml +15 -0
  8. alphaengine-1.1.0/examples/screen_validate_size.yaml +12 -0
  9. {alphaengine-1.0.3 → alphaengine-1.1.0}/pyproject.toml +6 -0
  10. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/_version.py +11 -1
  11. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/cli.py +1407 -36
  12. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/commands.py +304 -24
  13. alphaengine-1.1.0/src/alphaengine/complete.py +123 -0
  14. alphaengine-1.1.0/src/alphaengine/datasets.py +383 -0
  15. alphaengine-1.1.0/src/alphaengine/envelope.py +130 -0
  16. alphaengine-1.1.0/src/alphaengine/ideas.py +285 -0
  17. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/io.py +46 -4
  18. alphaengine-1.1.0/src/alphaengine/ledger.py +631 -0
  19. alphaengine-1.1.0/src/alphaengine/memo.py +374 -0
  20. alphaengine-1.1.0/src/alphaengine/pipeline.py +342 -0
  21. alphaengine-1.1.0/src/alphaengine/plugins.py +264 -0
  22. alphaengine-1.1.0/src/alphaengine/project.py +307 -0
  23. alphaengine-1.1.0/src/alphaengine/repl.py +149 -0
  24. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/sweep/runner.py +85 -1
  25. alphaengine-1.1.0/src/alphaengine/sync.py +381 -0
  26. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/tui/app.py +8 -0
  27. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/tui/dispatch.py +208 -4
  28. alphaengine-1.1.0/src/alphaengine/watch.py +272 -0
  29. alphaengine-1.1.0/tests/test_project.py +920 -0
  30. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_sim.py +1 -1
  31. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_tui.py +2 -2
  32. alphaengine-1.0.3/src/alphaengine/complete.py +0 -71
  33. alphaengine-1.0.3/src/alphaengine/repl.py +0 -80
  34. {alphaengine-1.0.3 → alphaengine-1.1.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  35. {alphaengine-1.0.3 → alphaengine-1.1.0}/.github/ISSUE_TEMPLATE/data_shape.md +0 -0
  36. {alphaengine-1.0.3 → alphaengine-1.1.0}/.github/ISSUE_TEMPLATE/method_request.md +0 -0
  37. {alphaengine-1.0.3 → alphaengine-1.1.0}/.github/dependabot.yml +0 -0
  38. {alphaengine-1.0.3 → alphaengine-1.1.0}/.github/workflows/ci.yml +0 -0
  39. {alphaengine-1.0.3 → alphaengine-1.1.0}/.github/workflows/codeql.yml +0 -0
  40. {alphaengine-1.0.3 → alphaengine-1.1.0}/.github/workflows/publish.yml +0 -0
  41. {alphaengine-1.0.3 → alphaengine-1.1.0}/.gitignore +0 -0
  42. {alphaengine-1.0.3 → alphaengine-1.1.0}/AGENTS.md +0 -0
  43. {alphaengine-1.0.3 → alphaengine-1.1.0}/CODE_OF_CONDUCT.md +0 -0
  44. {alphaengine-1.0.3 → alphaengine-1.1.0}/CONTRIBUTING.md +0 -0
  45. {alphaengine-1.0.3 → alphaengine-1.1.0}/LICENSE +0 -0
  46. {alphaengine-1.0.3 → alphaengine-1.1.0}/SECURITY.md +0 -0
  47. {alphaengine-1.0.3 → alphaengine-1.1.0}/docs/assets/banner.png +0 -0
  48. {alphaengine-1.0.3 → alphaengine-1.1.0}/docs/assets/data_boundary.png +0 -0
  49. {alphaengine-1.0.3 → alphaengine-1.1.0}/docs/assets/session.png +0 -0
  50. {alphaengine-1.0.3 → alphaengine-1.1.0}/docs/figure_contract.md +0 -0
  51. {alphaengine-1.0.3 → alphaengine-1.1.0}/docs/workflows/evaluate_process.json +0 -0
  52. {alphaengine-1.0.3 → alphaengine-1.1.0}/docs/workflows/research_week.json +0 -0
  53. {alphaengine-1.0.3 → alphaengine-1.1.0}/docs/workflows/stress_study.json +0 -0
  54. {alphaengine-1.0.3 → alphaengine-1.1.0}/scripts/gen_docs.py +0 -0
  55. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/__init__.py +0 -0
  56. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/__main__.py +0 -0
  57. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/agent/__init__.py +0 -0
  58. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/agent/answer.py +0 -0
  59. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/agent/bakeoff.py +0 -0
  60. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/agent/brief.py +0 -0
  61. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/agent/chart.py +0 -0
  62. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/agent/driver.py +0 -0
  63. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/agent/sim.py +0 -0
  64. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/auth.py +0 -0
  65. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/book.py +0 -0
  66. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/charts.py +0 -0
  67. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/client/__init__.py +0 -0
  68. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/client/agent.py +0 -0
  69. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/client/executor.py +0 -0
  70. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/client/session.py +0 -0
  71. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/connectors/__init__.py +0 -0
  72. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/context.py +0 -0
  73. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/__init__.py +0 -0
  74. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/active.py +0 -0
  75. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/allocate.py +0 -0
  76. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/backtest.py +0 -0
  77. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/bakeoff.py +0 -0
  78. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/covariance.py +0 -0
  79. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/cross_section.py +0 -0
  80. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/factors.py +0 -0
  81. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/market.py +0 -0
  82. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/options.py +0 -0
  83. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/pairs.py +0 -0
  84. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/panel.py +0 -0
  85. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/performance.py +0 -0
  86. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/portfolio.py +0 -0
  87. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/process.py +0 -0
  88. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/profile.py +0 -0
  89. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/rates.py +0 -0
  90. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/regime.py +0 -0
  91. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/relations.py +0 -0
  92. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/risk.py +0 -0
  93. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/screen.py +0 -0
  94. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/series_shapes.py +0 -0
  95. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/signals.py +0 -0
  96. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/stress.py +0 -0
  97. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/technical.py +0 -0
  98. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/trace.py +0 -0
  99. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/validation.py +0 -0
  100. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/walkforward.py +0 -0
  101. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/demo.py +0 -0
  102. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/demo_book.py +0 -0
  103. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/demo_returns.py +0 -0
  104. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/demo_signal.py +0 -0
  105. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/demo_universe.py +0 -0
  106. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/events.py +0 -0
  107. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/loaders.py +0 -0
  108. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/model.py +0 -0
  109. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/py.typed +0 -0
  110. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/study/__init__.py +0 -0
  111. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/study/report.py +0 -0
  112. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/study/schema.py +0 -0
  113. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/sweep/__init__.py +0 -0
  114. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/tui/__init__.py +0 -0
  115. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/tui/mark.py +0 -0
  116. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/tui/stage.py +0 -0
  117. {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/tui/typeface.py +0 -0
  118. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_agent.py +0 -0
  119. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_answer.py +0 -0
  120. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_bakeoff.py +0 -0
  121. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_book.py +0 -0
  122. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_cli.py +0 -0
  123. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_client.py +0 -0
  124. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_commands.py +0 -0
  125. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_context.py +0 -0
  126. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_coverage_paths.py +0 -0
  127. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_events.py +0 -0
  128. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_executor_ops.py +0 -0
  129. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_goldens.py +0 -0
  130. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_io.py +0 -0
  131. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_loaders.py +0 -0
  132. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_math_audit.py +0 -0
  133. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_model.py +0 -0
  134. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_portfolio.py +0 -0
  135. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_process.py +0 -0
  136. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_quant_maths.py +0 -0
  137. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_relations.py +0 -0
  138. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_screen.py +0 -0
  139. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_signals.py +0 -0
  140. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_smoke.py +0 -0
  141. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_sweep.py +0 -0
  142. {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_trace.py +0 -0
@@ -6,6 +6,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to Semantic Versioning (with computed golden values
7
7
  treated as part of the public contract).
8
8
 
9
+ ## [1.1.0] - 2026-10-24
10
+
11
+ ### Added
12
+ - **Project workspace (`ae init` and `ae` alias):** Initializes `.alphaengine/` (`project.toml`, `ledger/`, `data/`, `studies/`, `ideas/`, `universes/`, and SHA-256 content-addressed `objects/`). Commands walk up from the current directory to locate the project; documented in `docs/project-format.md`.
13
+ - **Project-wide ledger (`ae log`, `ae show`, `ae diff`, `ae rerun`):** Every run and `sweep()` inside a project writes an append-only run record and accumulates trial counts across runs on the same `idea_id` or `family`.
14
+ - **Dataset registry (`ae data add`, `ae data list`, `ae data show`, `ae data lineage`):** Registers CSV and Parquet datasets locally with full 64-hex SHA-256 hashes, row counts, date ranges, column schemas, and checks for duplicate timestamps, gaps, look-ahead rows (`--asof-col`), and survivorship hints.
15
+ - **Standard result envelope (`v1.0`), pipes, and declarative YAML pipelines:** Added `--json` and `--stdin` support across commands (`ae screen --json | ae validate --stdin | ae size --stdin`), `ae run <pipeline.yaml>`, two example pipelines in `examples/`, and `docs/result-format.md`.
16
+ - **Hypotheses as objects (`ae idea new`, `ae idea list`, `ae idea status`, `ae idea show`):** First-class hypothesis tracking with `--kill-if` rule evaluation, `--idea <id>` run linking, and pre-run prior-work checks.
17
+ - **Extended seal, verify, and committee memos:** `ae seal <run|idea>`, `ae verify <study.json> [--data <file>]`, and `ae report memo <idea|run> --format md|pdf` where every figure cites its `[run_id]`.
18
+ - **Research shell (`ae shell`):** Interactive shell with tab completion over verbs, run IDs, dataset names, and idea IDs, a project status line with cumulative trial count, inline ledger/idea commands, and automatic ledger recording of agent proposals.
19
+ - **Entry-point plugin system (`alphaengine.plugins`, `ae plugin list`):** Supports `loader`, `method`, and `template` plugins, with `quantconnect`, `vectorbt`, `csv`, `deflated_sharpe`, `combinatorial_oos_stability`, and `committee_memo` registered as built-ins (`docs/plugins.md`).
20
+ - **Local file watcher & live drift monitor:** `ae watch <pipeline.yaml>` re-runs pipelines when watched datasets change on disk; `ae monitor <run> --live <file>` compares live returns against the backtest's bootstrapped 95% intervals.
21
+ - **Opt-in workspace sync (`ae remote`, `ae push [--dry-run]`, `ae pull`):** Syncs sealed studies, allowlisted ledger runs, and ideas to `POST /api/workspace/sync` (with 404 fallback to `POST /api/me/runs/ingest`), enforcing the 512-element series cap and never uploading dataset rows.
22
+
9
23
  ## [1.0.3] - 2026-10-24
10
24
 
11
25
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: alphaengine
3
- Version: 1.0.3
3
+ Version: 1.1.0
4
4
  Summary: Validated research tooling for investment strategies: deflation, overfitting detection, and honest trial counts.
5
5
  Project-URL: Homepage, https://qosai.app
6
6
  Project-URL: Documentation, https://github.com/quantOSC/alphaengine#readme
@@ -249,6 +249,49 @@ distinction is the whole of the data boundary below.
249
249
 
250
250
  ---
251
251
 
252
+ ## Research OS quickstart
253
+
254
+ AlphaEngine works like `git` for quantitative research: initialize a local `.alphaengine/` project once, and every dataset registration, hypothesis, workflow run, parameter sweep, and sealed study is recorded in an append-only content-addressed ledger on your disk (see [project format](docs/project-format.md), [result envelope](docs/result-format.md), and [plugins](docs/plugins.md)). Both `alphaengine` and the short alias `ae` run the same entry point.
255
+
256
+ ```bash
257
+ # 1. Initialize a local .alphaengine/ workspace
258
+ ae init --name equity-momentum
259
+
260
+ # 2. Register a local CSV (or Parquet) dataset and run hygiene checks
261
+ ae data add prices.csv --name equities --asof-col date
262
+ ae data show equities
263
+
264
+ # 3. Record a falsifiable hypothesis with an explicit kill rule
265
+ ae idea new "Cross-sectional 20d momentum holds net of costs" --kill-if "DSR < 0.9" --family mom_20d
266
+
267
+ # 4. Run a validation, declarative YAML pipeline, or Unix JSON pipe
268
+ ae validate --project alphaengine.demo --idea idea_1
269
+ ae run examples/screen_validate_size.yaml
270
+ ae screen --data equities --json | ae validate --stdin --json | ae size --stdin
271
+
272
+ # 5. Inspect the append-only project ledger, cumulative trials, and diffs
273
+ ae log --family mom_20d
274
+ ae show HEAD
275
+ ae rerun HEAD
276
+
277
+ # 6. Seal into a Schema 1.2 Study, verify against data, and export a committee memo
278
+ ae seal HEAD
279
+ ae verify .alphaengine/studies/HEAD.json
280
+ ae report memo HEAD --format md
281
+ ```
282
+
283
+ ---
284
+
285
+ ## What's new in 1.1.0
286
+
287
+ - **Local-first project workspace (`ae init`):** Creates `.alphaengine/` (`project.toml`, `ledger/`, `data/`, `studies/`, `ideas/`, `universes/`, and SHA-256 content-addressed `objects/`). Commands walk up from the current directory to find the project; outside a project, every command behaves as a standalone call.
288
+ - **Project-wide ledger & cumulative trial counting (`ae log`, `ae show`, `ae diff`, `ae rerun`):** Runs and sweeps inside a project automatically record parameter hashes, dataset hashes, and figures, accumulating trial counts across runs on the same `idea_id` or `family`.
289
+ - **Dataset registry (`ae data add|list|show|lineage`):** Tracks local CSV and Parquet datasets by full SHA-256, row count, date range, column schema, and hygiene diagnostics (duplicate timestamps, missing/calendar gaps, `--asof-col` look-ahead hints, and survivorship hints).
290
+ - **Versioned `v1.0` JSON result envelope, `--stdin` pipes, & YAML pipelines:** Every command supports `--json` and `--stdin` (`ae screen --json | ae validate --stdin | ae size --stdin`), plus declarative multi-step recipes (`ae run pipeline.yaml`).
291
+ - **Hypotheses as objects (`ae idea new|list|status|show`):** Link runs with `--idea <id>`, evaluate `--kill-if` rules against cumulative figures, and receive automatic prior-work warnings before running overlapping parameter sets.
292
+ - **Seal, verify, & cited committee memos:** `ae seal <run|idea>`, `ae verify <study.json> [--data <file>]`, and `ae report memo <idea|run> --format md|pdf` (where every figure cites `[run_id]`).
293
+ - **Research shell (`ae shell`), plugins (`ae plugin list`), watcher (`ae watch`), live drift monitor (`ae monitor <run> --live <file>`), & opt-in sync (`ae remote`, `ae push [--dry-run]`, `ae pull`).**
294
+
252
295
  ## What's new in 1.0.3
253
296
 
254
297
  - **Opt-in series sharing & 512-element wire guard:** By default, workflow step traces (`/api/harness/runs/{id}/traces`) report scalar figures only; full series are shared only when you pass `--share-series` or set `ALPHAENGINE_SHARE_SERIES=1`.
@@ -339,9 +382,13 @@ w = hrp_weights(cov, names=names) # no matrix inverse; weights sum to one
339
382
 
340
383
  | Command | Does | Where |
341
384
  |---|---|---|
385
+ | `init [--name NAME]` | initialize a local .alphaengine/ research project in this directory | shell + session |
342
386
  | `demo` | run the built-in example offline, with no account and no data | shell + session |
343
387
  | `process [ou \| gbm \| jump \| garch]` | fit a named process to a series and stress it, offline | shell + session |
344
388
  | `runs [--limit N]` | your own week: what ran, what it decided, what it filed | shell + session |
389
+ | `log [--idea ID] [--family FAMILY] [--since DATE] [--verdict VERDICT]` | list local project ledger runs, trial counts, and verdicts | shell + session |
390
+ | `show <run>` | inspect one recorded project run, its hashes, trials, and figures | shell + session |
391
+ | `diff <run-a> <run-b>` | compare data, parameter, trial, and figure changes between two runs | shell + session |
345
392
  | `gaps` | what your record says is UNANSWERED, and what closes each one | shell + session |
346
393
  | `tonight [--budget N]` | what would run unattended tonight, without running any of it | shell + session |
347
394
  | `workflows` | what the server offers, what each needs, and which reproduce | shell + session |
@@ -365,8 +412,11 @@ w = hrp_weights(cov, names=names) # no matrix inverse; weights sum to one
365
412
  | `size` | what sizing does the risk model imply? | shell + session |
366
413
  | `monitor` | still inside the lines? | shell + session |
367
414
  | `run <workflow>` | run one workflow exactly as written | shell + session |
368
- | `seal <study.json>` | write canonical content_sha256 into a study and verify on re-run | shell |
369
- | `report <study.json> [--retail]` | send a saved study to quantOS (/api/me/runs/ingest or --retail ledger) | shell |
415
+ | `rerun <run>` | reproduce a recorded project run from its inputs and check figures | shell + session |
416
+ | `watch <pipeline.yaml> [--interval SECONDS]` | re-run a declarative pipeline whenever a registered dataset file changes | shell + session |
417
+ | `seal <study.json \| run \| idea>` | write canonical content_sha256 into a study (or seal a project run/idea) | shell + session |
418
+ | `verify <study.json> [--data FILE]` | verify a study.json content_sha256 seal and optionally re-check figures | shell + session |
419
+ | `report <study.json> [--retail] \| memo <idea \| run> [--format md \| pdf]` | send a study to quantOS, or export a cited committee memo (md/pdf) | shell + session |
370
420
  | `<anything else>` | ask in plain English; your model picks a workflow and drives it | session |
371
421
  | `status` | the current run, and what is loaded | session |
372
422
 
@@ -376,19 +426,25 @@ w = hrp_weights(cov, names=names) # no matrix inverse; weights sum to one
376
426
  |---|---|---|
377
427
  | `book [<name> \| status]` | show or load sleeves on the multi-strategy book | session |
378
428
  | `load <file \| module \| universe>` | a CSV, a project module, or a portal universe | session |
429
+ | `idea new "<thesis>" --kill-if "<rule>" [--family FAMILY] \| list \| status <id> <state> \| show <id>` | create, list, update, and evaluate local research hypotheses | shell + session |
379
430
  | `thesis [<name> \| clear]` | choose a portal thesis for the next run | session |
380
431
  | `correlation` | the correlation of every loaded name with every other name | session |
381
432
  | `covariance` | the sample covariance of every loaded name with every other name | session |
382
433
  | `cointegration` | which loaded names are cointegrated | session |
383
434
  | `portfolio` | weights for the names already loaded | session |
384
435
  | `universe <name>` | same as load: a universe registered in the portal | session |
385
- | `data <file>` | same as load: a local CSV or parquet | session |
436
+ | `data add <file> [--name NAME] [--asof-col COL] \| list \| show <name> \| lineage <run>` | register, inspect, and trace local CSV/Parquet datasets | shell + session |
386
437
  | `project <module>` | same as load: a module with data and backtest_fn | session |
387
438
 
388
439
  ### Session
389
440
 
390
441
  | Command | Does | Where |
391
442
  |---|---|---|
443
+ | `remote add <name> [url] \| list` | configure or list remote sync endpoints in .alphaengine/project.toml | shell + session |
444
+ | `push [remote] [--dry-run] [--share-series]` | sync sealed studies, ledger runs, and ideas to quantOS (opt-in network) | shell + session |
445
+ | `pull [remote]` | pull team runs and ideas from quantOS into the local ledger (read-only) | shell + session |
446
+ | `plugin list` | list installed loader, method, and report template plugins | shell + session |
447
+ | `shell` | open the interactive research shell with project completion and status | shell |
392
448
  | `logout [--purge]` | remove stored credentials from this machine | shell + session |
393
449
  | `version` | print the version | shell |
394
450
  | `help` | the short list: demo, login, load, then a question | session |
@@ -422,6 +478,20 @@ w = hrp_weights(cov, names=names) # no matrix inverse; weights sum to one
422
478
  | `--budget N` | how many runs a night is worth (default 3) |
423
479
  | `--purge` | remove ~/.config/alphaengine/credentials.json and clean up its config directory |
424
480
  | `--retail` | send the study to the retail experiment ledger (/api/retail/ledger/import) |
481
+ | `--name NAME` | name for the initialized project or registered dataset |
482
+ | `--idea ID` | attach the run or filter the log to a local hypothesis id |
483
+ | `--family FAMILY` | strategy or experiment family for cumulative trial counting |
484
+ | `--since DATE` | filter project log to runs on or after YYYY-MM-DD |
485
+ | `--verdict VERDICT` | filter project log by verdict (e.g. robust, marginal, likely_noise) |
486
+ | `--asof-col COL` | as-of column name or cutoff date for look-ahead checks in data add |
487
+ | `--json` | emit a versioned v1.0 JSON result envelope to stdout |
488
+ | `--stdin` | read an upstream JSON result envelope from standard input |
489
+ | `--kill-if RULE` | kill rule for a hypothesis, e.g. 'DSR < 0.9' |
490
+ | `--format FMT` | output format for report memo: md or pdf (default md) |
491
+ | `--dry-run` | print the exact sync payload without making a network call |
492
+ | `--live FILE` | live return series CSV to compare against a recorded backtest run |
493
+ | `--interval SECONDS` | polling interval in seconds for watch (default 1.0) |
494
+ | `--cycles N` | number of polling cycles for watch before exiting (0 means continuous) |
425
495
 
426
496
  ### Examples
427
497
 
@@ -434,11 +504,17 @@ alphaengine stress
434
504
  alphaengine overlap
435
505
  alphaengine size
436
506
  alphaengine monitor
507
+ alphaengine init
508
+ alphaengine init --name momentum
437
509
  alphaengine demo
438
510
  alphaengine process
439
511
  alphaengine process ou
440
512
  alphaengine runs
441
513
  alphaengine runs --limit 50
514
+ alphaengine log
515
+ alphaengine log --family momentum --verdict likely_noise
516
+ alphaengine show HEAD
517
+ alphaengine diff run_a run_b
442
518
  alphaengine gaps
443
519
  alphaengine tonight
444
520
  alphaengine tonight --budget 5
@@ -448,12 +524,34 @@ alphaengine commands
448
524
  alphaengine run screen_universe --universe sp500
449
525
  alphaengine run size_position --data returns.csv
450
526
  alphaengine run validate_study --project research.momentum
527
+ alphaengine run examples/screen_validate_size.yaml
528
+ alphaengine rerun HEAD
529
+ alphaengine watch examples/screen_validate_size.yaml
451
530
  alphaengine seal study.json
531
+ alphaengine seal HEAD
532
+ alphaengine verify study.json
533
+ alphaengine verify study.json --data prices.csv
452
534
  alphaengine report study.json
453
535
  alphaengine report study.json --retail
536
+ alphaengine report memo HEAD --format md
454
537
  alphaengine models
455
538
  alphaengine trace
539
+ alphaengine idea new "Cross-sectional momentum holds" --kill-if "DSR < 0.9" --family momentum
540
+ alphaengine idea list
541
+ alphaengine idea status idea_1 testing
542
+ alphaengine idea show idea_1
456
543
  alphaengine run screen_universe --thesis momentum
544
+ alphaengine data add prices.csv --name equities
545
+ alphaengine data list
546
+ alphaengine data show equities
547
+ alphaengine data lineage HEAD
548
+ alphaengine remote add quantos
549
+ alphaengine remote add quantos https://qosai.app
550
+ alphaengine push --dry-run
551
+ alphaengine push
552
+ alphaengine pull
553
+ alphaengine plugin list
554
+ alphaengine shell
457
555
  alphaengine logout
458
556
  alphaengine logout --purge
459
557
  alphaengine version
@@ -202,6 +202,49 @@ distinction is the whole of the data boundary below.
202
202
 
203
203
  ---
204
204
 
205
+ ## Research OS quickstart
206
+
207
+ AlphaEngine works like `git` for quantitative research: initialize a local `.alphaengine/` project once, and every dataset registration, hypothesis, workflow run, parameter sweep, and sealed study is recorded in an append-only content-addressed ledger on your disk (see [project format](docs/project-format.md), [result envelope](docs/result-format.md), and [plugins](docs/plugins.md)). Both `alphaengine` and the short alias `ae` run the same entry point.
208
+
209
+ ```bash
210
+ # 1. Initialize a local .alphaengine/ workspace
211
+ ae init --name equity-momentum
212
+
213
+ # 2. Register a local CSV (or Parquet) dataset and run hygiene checks
214
+ ae data add prices.csv --name equities --asof-col date
215
+ ae data show equities
216
+
217
+ # 3. Record a falsifiable hypothesis with an explicit kill rule
218
+ ae idea new "Cross-sectional 20d momentum holds net of costs" --kill-if "DSR < 0.9" --family mom_20d
219
+
220
+ # 4. Run a validation, declarative YAML pipeline, or Unix JSON pipe
221
+ ae validate --project alphaengine.demo --idea idea_1
222
+ ae run examples/screen_validate_size.yaml
223
+ ae screen --data equities --json | ae validate --stdin --json | ae size --stdin
224
+
225
+ # 5. Inspect the append-only project ledger, cumulative trials, and diffs
226
+ ae log --family mom_20d
227
+ ae show HEAD
228
+ ae rerun HEAD
229
+
230
+ # 6. Seal into a Schema 1.2 Study, verify against data, and export a committee memo
231
+ ae seal HEAD
232
+ ae verify .alphaengine/studies/HEAD.json
233
+ ae report memo HEAD --format md
234
+ ```
235
+
236
+ ---
237
+
238
+ ## What's new in 1.1.0
239
+
240
+ - **Local-first project workspace (`ae init`):** Creates `.alphaengine/` (`project.toml`, `ledger/`, `data/`, `studies/`, `ideas/`, `universes/`, and SHA-256 content-addressed `objects/`). Commands walk up from the current directory to find the project; outside a project, every command behaves as a standalone call.
241
+ - **Project-wide ledger & cumulative trial counting (`ae log`, `ae show`, `ae diff`, `ae rerun`):** Runs and sweeps inside a project automatically record parameter hashes, dataset hashes, and figures, accumulating trial counts across runs on the same `idea_id` or `family`.
242
+ - **Dataset registry (`ae data add|list|show|lineage`):** Tracks local CSV and Parquet datasets by full SHA-256, row count, date range, column schema, and hygiene diagnostics (duplicate timestamps, missing/calendar gaps, `--asof-col` look-ahead hints, and survivorship hints).
243
+ - **Versioned `v1.0` JSON result envelope, `--stdin` pipes, & YAML pipelines:** Every command supports `--json` and `--stdin` (`ae screen --json | ae validate --stdin | ae size --stdin`), plus declarative multi-step recipes (`ae run pipeline.yaml`).
244
+ - **Hypotheses as objects (`ae idea new|list|status|show`):** Link runs with `--idea <id>`, evaluate `--kill-if` rules against cumulative figures, and receive automatic prior-work warnings before running overlapping parameter sets.
245
+ - **Seal, verify, & cited committee memos:** `ae seal <run|idea>`, `ae verify <study.json> [--data <file>]`, and `ae report memo <idea|run> --format md|pdf` (where every figure cites `[run_id]`).
246
+ - **Research shell (`ae shell`), plugins (`ae plugin list`), watcher (`ae watch`), live drift monitor (`ae monitor <run> --live <file>`), & opt-in sync (`ae remote`, `ae push [--dry-run]`, `ae pull`).**
247
+
205
248
  ## What's new in 1.0.3
206
249
 
207
250
  - **Opt-in series sharing & 512-element wire guard:** By default, workflow step traces (`/api/harness/runs/{id}/traces`) report scalar figures only; full series are shared only when you pass `--share-series` or set `ALPHAENGINE_SHARE_SERIES=1`.
@@ -292,9 +335,13 @@ w = hrp_weights(cov, names=names) # no matrix inverse; weights sum to one
292
335
 
293
336
  | Command | Does | Where |
294
337
  |---|---|---|
338
+ | `init [--name NAME]` | initialize a local .alphaengine/ research project in this directory | shell + session |
295
339
  | `demo` | run the built-in example offline, with no account and no data | shell + session |
296
340
  | `process [ou \| gbm \| jump \| garch]` | fit a named process to a series and stress it, offline | shell + session |
297
341
  | `runs [--limit N]` | your own week: what ran, what it decided, what it filed | shell + session |
342
+ | `log [--idea ID] [--family FAMILY] [--since DATE] [--verdict VERDICT]` | list local project ledger runs, trial counts, and verdicts | shell + session |
343
+ | `show <run>` | inspect one recorded project run, its hashes, trials, and figures | shell + session |
344
+ | `diff <run-a> <run-b>` | compare data, parameter, trial, and figure changes between two runs | shell + session |
298
345
  | `gaps` | what your record says is UNANSWERED, and what closes each one | shell + session |
299
346
  | `tonight [--budget N]` | what would run unattended tonight, without running any of it | shell + session |
300
347
  | `workflows` | what the server offers, what each needs, and which reproduce | shell + session |
@@ -318,8 +365,11 @@ w = hrp_weights(cov, names=names) # no matrix inverse; weights sum to one
318
365
  | `size` | what sizing does the risk model imply? | shell + session |
319
366
  | `monitor` | still inside the lines? | shell + session |
320
367
  | `run <workflow>` | run one workflow exactly as written | shell + session |
321
- | `seal <study.json>` | write canonical content_sha256 into a study and verify on re-run | shell |
322
- | `report <study.json> [--retail]` | send a saved study to quantOS (/api/me/runs/ingest or --retail ledger) | shell |
368
+ | `rerun <run>` | reproduce a recorded project run from its inputs and check figures | shell + session |
369
+ | `watch <pipeline.yaml> [--interval SECONDS]` | re-run a declarative pipeline whenever a registered dataset file changes | shell + session |
370
+ | `seal <study.json \| run \| idea>` | write canonical content_sha256 into a study (or seal a project run/idea) | shell + session |
371
+ | `verify <study.json> [--data FILE]` | verify a study.json content_sha256 seal and optionally re-check figures | shell + session |
372
+ | `report <study.json> [--retail] \| memo <idea \| run> [--format md \| pdf]` | send a study to quantOS, or export a cited committee memo (md/pdf) | shell + session |
323
373
  | `<anything else>` | ask in plain English; your model picks a workflow and drives it | session |
324
374
  | `status` | the current run, and what is loaded | session |
325
375
 
@@ -329,19 +379,25 @@ w = hrp_weights(cov, names=names) # no matrix inverse; weights sum to one
329
379
  |---|---|---|
330
380
  | `book [<name> \| status]` | show or load sleeves on the multi-strategy book | session |
331
381
  | `load <file \| module \| universe>` | a CSV, a project module, or a portal universe | session |
382
+ | `idea new "<thesis>" --kill-if "<rule>" [--family FAMILY] \| list \| status <id> <state> \| show <id>` | create, list, update, and evaluate local research hypotheses | shell + session |
332
383
  | `thesis [<name> \| clear]` | choose a portal thesis for the next run | session |
333
384
  | `correlation` | the correlation of every loaded name with every other name | session |
334
385
  | `covariance` | the sample covariance of every loaded name with every other name | session |
335
386
  | `cointegration` | which loaded names are cointegrated | session |
336
387
  | `portfolio` | weights for the names already loaded | session |
337
388
  | `universe <name>` | same as load: a universe registered in the portal | session |
338
- | `data <file>` | same as load: a local CSV or parquet | session |
389
+ | `data add <file> [--name NAME] [--asof-col COL] \| list \| show <name> \| lineage <run>` | register, inspect, and trace local CSV/Parquet datasets | shell + session |
339
390
  | `project <module>` | same as load: a module with data and backtest_fn | session |
340
391
 
341
392
  ### Session
342
393
 
343
394
  | Command | Does | Where |
344
395
  |---|---|---|
396
+ | `remote add <name> [url] \| list` | configure or list remote sync endpoints in .alphaengine/project.toml | shell + session |
397
+ | `push [remote] [--dry-run] [--share-series]` | sync sealed studies, ledger runs, and ideas to quantOS (opt-in network) | shell + session |
398
+ | `pull [remote]` | pull team runs and ideas from quantOS into the local ledger (read-only) | shell + session |
399
+ | `plugin list` | list installed loader, method, and report template plugins | shell + session |
400
+ | `shell` | open the interactive research shell with project completion and status | shell |
345
401
  | `logout [--purge]` | remove stored credentials from this machine | shell + session |
346
402
  | `version` | print the version | shell |
347
403
  | `help` | the short list: demo, login, load, then a question | session |
@@ -375,6 +431,20 @@ w = hrp_weights(cov, names=names) # no matrix inverse; weights sum to one
375
431
  | `--budget N` | how many runs a night is worth (default 3) |
376
432
  | `--purge` | remove ~/.config/alphaengine/credentials.json and clean up its config directory |
377
433
  | `--retail` | send the study to the retail experiment ledger (/api/retail/ledger/import) |
434
+ | `--name NAME` | name for the initialized project or registered dataset |
435
+ | `--idea ID` | attach the run or filter the log to a local hypothesis id |
436
+ | `--family FAMILY` | strategy or experiment family for cumulative trial counting |
437
+ | `--since DATE` | filter project log to runs on or after YYYY-MM-DD |
438
+ | `--verdict VERDICT` | filter project log by verdict (e.g. robust, marginal, likely_noise) |
439
+ | `--asof-col COL` | as-of column name or cutoff date for look-ahead checks in data add |
440
+ | `--json` | emit a versioned v1.0 JSON result envelope to stdout |
441
+ | `--stdin` | read an upstream JSON result envelope from standard input |
442
+ | `--kill-if RULE` | kill rule for a hypothesis, e.g. 'DSR < 0.9' |
443
+ | `--format FMT` | output format for report memo: md or pdf (default md) |
444
+ | `--dry-run` | print the exact sync payload without making a network call |
445
+ | `--live FILE` | live return series CSV to compare against a recorded backtest run |
446
+ | `--interval SECONDS` | polling interval in seconds for watch (default 1.0) |
447
+ | `--cycles N` | number of polling cycles for watch before exiting (0 means continuous) |
378
448
 
379
449
  ### Examples
380
450
 
@@ -387,11 +457,17 @@ alphaengine stress
387
457
  alphaengine overlap
388
458
  alphaengine size
389
459
  alphaengine monitor
460
+ alphaengine init
461
+ alphaengine init --name momentum
390
462
  alphaengine demo
391
463
  alphaengine process
392
464
  alphaengine process ou
393
465
  alphaengine runs
394
466
  alphaengine runs --limit 50
467
+ alphaengine log
468
+ alphaengine log --family momentum --verdict likely_noise
469
+ alphaengine show HEAD
470
+ alphaengine diff run_a run_b
395
471
  alphaengine gaps
396
472
  alphaengine tonight
397
473
  alphaengine tonight --budget 5
@@ -401,12 +477,34 @@ alphaengine commands
401
477
  alphaengine run screen_universe --universe sp500
402
478
  alphaengine run size_position --data returns.csv
403
479
  alphaengine run validate_study --project research.momentum
480
+ alphaengine run examples/screen_validate_size.yaml
481
+ alphaengine rerun HEAD
482
+ alphaengine watch examples/screen_validate_size.yaml
404
483
  alphaengine seal study.json
484
+ alphaengine seal HEAD
485
+ alphaengine verify study.json
486
+ alphaengine verify study.json --data prices.csv
405
487
  alphaengine report study.json
406
488
  alphaengine report study.json --retail
489
+ alphaengine report memo HEAD --format md
407
490
  alphaengine models
408
491
  alphaengine trace
492
+ alphaengine idea new "Cross-sectional momentum holds" --kill-if "DSR < 0.9" --family momentum
493
+ alphaengine idea list
494
+ alphaengine idea status idea_1 testing
495
+ alphaengine idea show idea_1
409
496
  alphaengine run screen_universe --thesis momentum
497
+ alphaengine data add prices.csv --name equities
498
+ alphaengine data list
499
+ alphaengine data show equities
500
+ alphaengine data lineage HEAD
501
+ alphaengine remote add quantos
502
+ alphaengine remote add quantos https://qosai.app
503
+ alphaengine push --dry-run
504
+ alphaengine push
505
+ alphaengine pull
506
+ alphaengine plugin list
507
+ alphaengine shell
410
508
  alphaengine logout
411
509
  alphaengine logout --purge
412
510
  alphaengine version
@@ -0,0 +1,60 @@
1
+ # Authoring AlphaEngine Plugins (`alphaengine.plugins`)
2
+
3
+ AlphaEngine discovers plugins through standard Python package entry points under the group `"alphaengine.plugins"`.
4
+
5
+ Three plugin kinds are supported:
6
+
7
+ 1. **`loader`**: Reads external data formats or backtest artifacts (for example, the built-in `quantconnect`, `vectorbt`, and `csv` loaders).
8
+ 2. **`method`**: Runs a statistical validation or diagnostic function and returns a versioned `v1.0` JSON result envelope (or a `figures` dictionary that AlphaEngine wraps into an envelope).
9
+ 3. **`template`**: Renders a study or project run into a custom report or memo (for example, `committee_memo`).
10
+
11
+ Inspect installed plugins at any time with:
12
+
13
+ ```bash
14
+ ae plugin list
15
+ ```
16
+
17
+ ---
18
+
19
+ ## Minimal Example
20
+
21
+ ### 1. Write your plugin module (`my_ae_plugin.py`)
22
+
23
+ ```python
24
+ from alphaengine.plugins import PluginSpec
25
+
26
+
27
+ def tail_ratio_diagnostic(returns: list[float], *, n_trials: int = 1) -> dict:
28
+ """95th-percentile gain divided by 5th-percentile loss magnitude."""
29
+ import numpy as np
30
+
31
+ arr = np.asarray(returns, dtype=float)
32
+ q95 = float(np.quantile(arr, 0.95))
33
+ q05 = abs(float(np.quantile(arr, 0.05)))
34
+ ratio = round(q95 / max(q05, 1e-9), 4)
35
+ return {
36
+ "tail_ratio": ratio,
37
+ "n_trials": n_trials,
38
+ "n_trials_source": "asserted",
39
+ "verdict": "robust" if ratio >= 1.2 else "marginal",
40
+ }
41
+
42
+
43
+ def register() -> PluginSpec:
44
+ return PluginSpec(
45
+ name="tail_ratio",
46
+ kind="method",
47
+ description="95th/5th percentile tail ratio diagnostic",
48
+ fn=tail_ratio_diagnostic,
49
+ source="my-ae-plugin",
50
+ )
51
+ ```
52
+
53
+ ### 2. Declare the entry point in `pyproject.toml`
54
+
55
+ ```toml
56
+ [project.entry-points."alphaengine.plugins"]
57
+ tail_ratio = "my_ae_plugin:register"
58
+ ```
59
+
60
+ After `pip install -e .`, `ae plugin list` will display `tail_ratio` under `method`, and `run_method_plugin("tail_ratio", returns)` will execute it and return a standard `v1.0` result envelope.
@@ -0,0 +1,79 @@
1
+ # AlphaEngine Project On-Disk Format (`v1.0`)
2
+
3
+ **Format Version:** `1.0` (`PROJECT_FORMAT_VERSION = "1.0"`)
4
+
5
+ AlphaEngine stores a local research workspace inside a `.alphaengine/` directory at the root of your project, discovered by walking up from the current working directory (the same way `git` locates `.git/`). Outside a project directory, every CLI command and Python function behaves as a standalone call.
6
+
7
+ No database process or third-party storage library is required: all state is plain TOML, append-only JSON Lines (`.jsonl`), and content-addressed JSON blobs named by their full 64-character SHA-256 digest.
8
+
9
+ ---
10
+
11
+ ## Directory Layout
12
+
13
+ Running `ae init` (or `alphaengine init`) creates:
14
+
15
+ ```text
16
+ .alphaengine/
17
+ ├── project.toml # Project metadata and configured remotes
18
+ ├── ledger/
19
+ │ ├── runs.jsonl # Append-only run records (every command/step executed)
20
+ │ └── trials.jsonl # Append-only trial records across sweeps and ideas
21
+ ├── data/
22
+ │ └── datasets.jsonl # Append-only dataset registry and hygiene diagnostics
23
+ ├── studies/
24
+ │ └── <id>.json # Sealed Study artifacts (schema 1.2)
25
+ ├── ideas/
26
+ │ └── ideas.jsonl # Append-only hypothesis definitions and status transitions
27
+ ├── universes/
28
+ │ └── <name>.json # Local universe definitions
29
+ └── objects/
30
+ └── <sha256>.json # Content-addressed immutable JSON objects
31
+ ```
32
+
33
+ ---
34
+
35
+ ## 1. `project.toml`
36
+
37
+ Stores the project's human-readable name, UTC creation timestamp, on-disk format version, and optional sync remotes:
38
+
39
+ ```toml
40
+ # AlphaEngine local research project configuration
41
+ name = "equity-momentum"
42
+ created = "2026-10-24T18:00:00+00:00"
43
+ schema_version = "1.0"
44
+
45
+ [remotes]
46
+ quantos = "https://alpha-backend-production-51df.up.railway.app"
47
+ ```
48
+
49
+ ---
50
+
51
+ ## 2. Content-Addressed Object Store (`objects/<sha256>.json`)
52
+
53
+ Every structured record written to the ledger, dataset registry, or idea log is also serialized into canonical JSON:
54
+ - Dictionary keys sorted lexicographically (`sort_keys=True`)
55
+ - Compact separators (`(",", ":")`)
56
+ - Finite floats rounded deterministically; non-finite values mapped to `null`
57
+ - Encoded as UTF-8
58
+
59
+ The 64-character hex SHA-256 of those bytes determines the file path `.alphaengine/objects/<sha256>.json`. Reading an object via `Project.get_object(sha256)` re-hashes the file on disk and raises `ValueError` if the content was modified.
60
+
61
+ ---
62
+
63
+ ## 3. Append-Only Logs (`.jsonl`)
64
+
65
+ Each `.jsonl` file under `ledger/`, `data/`, and `ideas/` contains one UTF-8 JSON object per line, in chronological order:
66
+
67
+ - **`ledger/runs.jsonl`**: Every command or pipeline step executed inside the project (`run_id`, `timestamp`, `command`, `idea_id`, `family`, `params_hash`, `dataset_hashes`, `n_trials`, `n_trials_source`, `cumulative_trials`, `figures`, `verdict`, `engine_version`, `object_sha256`).
68
+ - **`ledger/trials.jsonl`**: Per-trial entries (`run_id`, `idea_id`, `family`, `index`, `params_hash`, `sharpe`, `failed`, `timestamp`).
69
+ - **`data/datasets.jsonl`**: Registered local datasets (`name`, `path`, `sha256`, `format`, `n_rows`, `start_date`, `end_date`, `columns`, `checks`, `registered_at`, `object_sha256`).
70
+ - **`ideas/ideas.jsonl`**: Hypothesis creation and status updates (`idea_id`, `thesis`, `family`, `kill_if`, `status`, `created_at`, `updated_at`, `object_sha256`).
71
+
72
+ ---
73
+
74
+ ## 4. Discovery Rule
75
+
76
+ When any `ae` / `alphaengine` command runs:
77
+ 1. It checks the current working directory and each parent directory for `.alphaengine/project.toml`.
78
+ 2. If found, the command attaches to that `Project` instance.
79
+ 3. If not found, commands that do not strictly require a project (`demo`, `process`, `seal <study.json>`, `report`, `version`, etc.) run in standalone mode without touching the filesystem.
@@ -0,0 +1,89 @@
1
+ # AlphaEngine Result Envelope (`v1.0`) & Declarative Pipelines
2
+
3
+ **Envelope Schema Version:** `1.0` (`ENVELOPE_SCHEMA_VERSION = "1.0"`)
4
+
5
+ Every AlphaEngine CLI command can emit a structured JSON result envelope with `--json` and read an upstream envelope from standard input with `--stdin`.
6
+
7
+ ```bash
8
+ ae screen --data prices.csv --json | ae validate --stdin --json | ae size --stdin --json
9
+ ```
10
+
11
+ ---
12
+
13
+ ## 1. JSON Result Envelope Schema (`v1.0`)
14
+
15
+ ```json
16
+ {
17
+ "schema_version": "1.0",
18
+ "engine_version": "1.0.3",
19
+ "run_id": "run_a1b2c3d4e5f6",
20
+ "timestamp": "2026-10-24T18:30:00+00:00",
21
+ "command": "screen_universe",
22
+ "idea_id": "idea_01",
23
+ "family": "cross_sectional_momentum",
24
+ "params_hash": "8f2a9c...",
25
+ "dataset_hashes": [
26
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
27
+ ],
28
+ "n_trials": 60,
29
+ "n_trials_source": "derived_from_universe",
30
+ "cumulative_trials": 60,
31
+ "project_trials": 60,
32
+ "verdict": "ranked",
33
+ "figures": {
34
+ "universe_size": 60,
35
+ "n_evaluated": 60,
36
+ "n_passing": 60,
37
+ "n_insufficient": 0,
38
+ "cumulative_trials": 60,
39
+ "project_trials": 60
40
+ },
41
+ "context": {
42
+ "data_path": "prices.csv",
43
+ "project_module": null,
44
+ "top_symbol": "SYM00",
45
+ "shortlist": ["SYM00", "SYM07", "SYM14"],
46
+ "returns": [0.0012, -0.0034, 0.0041]
47
+ }
48
+ }
49
+ ```
50
+
51
+ ### Field Reference
52
+
53
+ | Field | Type | Description |
54
+ |---|---|---|
55
+ | `schema_version` | `string` | Envelope format version (`"1.0"`). |
56
+ | `engine_version` | `string` | AlphaEngine package version (`__version__`). |
57
+ | `run_id` | `string` | Unique run identifier (`run_<12-hex>`). |
58
+ | `timestamp` | `string` | ISO-8601 UTC timestamp when the run completed. |
59
+ | `command` | `string` | Canonical command or workflow name executed. |
60
+ | `idea_id` | `string \| null` | Linked hypothesis id (`--idea`), if attached. |
61
+ | `family` | `string` | Strategy or experiment family used for cumulative trial counting. |
62
+ | `params_hash` | `string` | 64-hex SHA-256 of the run's input parameters. |
63
+ | `dataset_hashes` | `list[string]` | 64-hex SHA-256 digests of the input datasets. |
64
+ | `n_trials` | `int \| null` | Trial count for this individual run (`null` when `"not_recorded"`). |
65
+ | `n_trials_source` | `string` | Provenance of `n_trials` (`derived_from_grid`, `asserted`, `monte_carlo`, `not_recorded`, etc.). |
66
+ | `cumulative_trials` | `int` | Accumulated trial count across all project runs on the same `idea_id` or `family`. |
67
+ | `project_trials` | `int` | Total trials accumulated across the entire `.alphaengine/` project. |
68
+ | `verdict` | `string \| null` | Statistical or diagnostic verdict (`robust`, `marginal`, `likely_noise`, `clean`, `sized`, etc.; `null` when refused). |
69
+ | `figures` | `object` | Computed scalar figures and bounded tables (never > 512 elements). |
70
+ | `context` | `object` | Local pipe handoff context (`top_symbol`, `shortlist`, `returns`, `data_path`) consumed when piping into `--stdin`. |
71
+
72
+ ---
73
+
74
+ ## 2. Declarative Pipelines (`ae run pipeline.yaml`)
75
+
76
+ Multi-step research recipes can be declared in YAML and executed with `ae run <pipeline.yaml>`. Each step receives the upstream envelope and writes its own run record to `.alphaengine/ledger/runs.jsonl`.
77
+
78
+ ```yaml
79
+ name: momentum-validation-pipeline
80
+ family: equity_momentum
81
+ steps:
82
+ - command: diagnose
83
+ - command: screen
84
+ inputs:
85
+ rank_by: return_pct
86
+ top_n: 5
87
+ - command: validate
88
+ - command: size
89
+ ```
@@ -0,0 +1,15 @@
1
+ # Example 2: Process Calibration -> Stress -> Monitor Pipeline
2
+ # Run with: ae run examples/process_stress_monitor.yaml
3
+ name: process-stress-monitor
4
+ family: ou_mean_reversion
5
+ steps:
6
+ - command: process
7
+ dgp: ou
8
+ inputs:
9
+ n_paths: 80
10
+ - command: stress
11
+ inputs:
12
+ turnover: 0.15
13
+ - command: monitor
14
+ inputs:
15
+ tolerances: '{"max_drawdown_pct": 25.0, "var_pct": 4.0}'
@@ -0,0 +1,12 @@
1
+ # Example 1: Screen -> Validate -> Size Pipeline
2
+ # Run with: ae run examples/screen_validate_size.yaml
3
+ name: screen-validate-size
4
+ family: cross_sectional_momentum
5
+ steps:
6
+ - command: diagnose
7
+ - command: screen
8
+ inputs:
9
+ rank_by: return_pct
10
+ top_n: 5
11
+ - command: validate
12
+ - command: size