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.
- {alphaengine-1.0.3 → alphaengine-1.1.0}/CHANGELOG.md +14 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/PKG-INFO +102 -4
- {alphaengine-1.0.3 → alphaengine-1.1.0}/README.md +101 -3
- alphaengine-1.1.0/docs/plugins.md +60 -0
- alphaengine-1.1.0/docs/project-format.md +79 -0
- alphaengine-1.1.0/docs/result-format.md +89 -0
- alphaengine-1.1.0/examples/process_stress_monitor.yaml +15 -0
- alphaengine-1.1.0/examples/screen_validate_size.yaml +12 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/pyproject.toml +6 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/_version.py +11 -1
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/cli.py +1407 -36
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/commands.py +304 -24
- alphaengine-1.1.0/src/alphaengine/complete.py +123 -0
- alphaengine-1.1.0/src/alphaengine/datasets.py +383 -0
- alphaengine-1.1.0/src/alphaengine/envelope.py +130 -0
- alphaengine-1.1.0/src/alphaengine/ideas.py +285 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/io.py +46 -4
- alphaengine-1.1.0/src/alphaengine/ledger.py +631 -0
- alphaengine-1.1.0/src/alphaengine/memo.py +374 -0
- alphaengine-1.1.0/src/alphaengine/pipeline.py +342 -0
- alphaengine-1.1.0/src/alphaengine/plugins.py +264 -0
- alphaengine-1.1.0/src/alphaengine/project.py +307 -0
- alphaengine-1.1.0/src/alphaengine/repl.py +149 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/sweep/runner.py +85 -1
- alphaengine-1.1.0/src/alphaengine/sync.py +381 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/tui/app.py +8 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/tui/dispatch.py +208 -4
- alphaengine-1.1.0/src/alphaengine/watch.py +272 -0
- alphaengine-1.1.0/tests/test_project.py +920 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_sim.py +1 -1
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_tui.py +2 -2
- alphaengine-1.0.3/src/alphaengine/complete.py +0 -71
- alphaengine-1.0.3/src/alphaengine/repl.py +0 -80
- {alphaengine-1.0.3 → alphaengine-1.1.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/.github/ISSUE_TEMPLATE/data_shape.md +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/.github/ISSUE_TEMPLATE/method_request.md +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/.github/dependabot.yml +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/.github/workflows/ci.yml +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/.github/workflows/codeql.yml +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/.github/workflows/publish.yml +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/.gitignore +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/AGENTS.md +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/CODE_OF_CONDUCT.md +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/CONTRIBUTING.md +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/LICENSE +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/SECURITY.md +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/docs/assets/banner.png +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/docs/assets/data_boundary.png +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/docs/assets/session.png +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/docs/figure_contract.md +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/docs/workflows/evaluate_process.json +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/docs/workflows/research_week.json +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/docs/workflows/stress_study.json +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/scripts/gen_docs.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/__init__.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/__main__.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/agent/__init__.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/agent/answer.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/agent/bakeoff.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/agent/brief.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/agent/chart.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/agent/driver.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/agent/sim.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/auth.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/book.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/charts.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/client/__init__.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/client/agent.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/client/executor.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/client/session.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/connectors/__init__.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/context.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/__init__.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/active.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/allocate.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/backtest.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/bakeoff.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/covariance.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/cross_section.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/factors.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/market.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/options.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/pairs.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/panel.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/performance.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/portfolio.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/process.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/profile.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/rates.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/regime.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/relations.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/risk.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/screen.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/series_shapes.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/signals.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/stress.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/technical.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/trace.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/validation.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/core/walkforward.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/demo.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/demo_book.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/demo_returns.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/demo_signal.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/demo_universe.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/events.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/loaders.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/model.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/py.typed +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/study/__init__.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/study/report.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/study/schema.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/sweep/__init__.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/tui/__init__.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/tui/mark.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/tui/stage.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/src/alphaengine/tui/typeface.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_agent.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_answer.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_bakeoff.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_book.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_cli.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_client.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_commands.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_context.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_coverage_paths.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_events.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_executor_ops.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_goldens.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_io.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_loaders.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_math_audit.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_model.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_portfolio.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_process.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_quant_maths.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_relations.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_screen.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_signals.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_smoke.py +0 -0
- {alphaengine-1.0.3 → alphaengine-1.1.0}/tests/test_sweep.py +0 -0
- {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
|
+
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
|
-
| `
|
|
369
|
-
| `
|
|
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>` |
|
|
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
|
-
| `
|
|
322
|
-
| `
|
|
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>` |
|
|
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
|