alphaengine 1.0.2__tar.gz → 1.0.3__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/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
- alphaengine-1.0.3/.github/ISSUE_TEMPLATE/data_shape.md +24 -0
- alphaengine-1.0.3/.github/ISSUE_TEMPLATE/method_request.md +29 -0
- alphaengine-1.0.3/.github/dependabot.yml +13 -0
- alphaengine-1.0.3/.github/workflows/codeql.yml +29 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/.github/workflows/publish.yml +3 -0
- alphaengine-1.0.3/CHANGELOG.md +49 -0
- alphaengine-1.0.3/CODE_OF_CONDUCT.md +49 -0
- alphaengine-1.0.3/CONTRIBUTING.md +39 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/PKG-INFO +104 -36
- {alphaengine-1.0.2 → alphaengine-1.0.3}/README.md +102 -34
- {alphaengine-1.0.2 → alphaengine-1.0.3}/SECURITY.md +2 -2
- {alphaengine-1.0.2 → alphaengine-1.0.3}/pyproject.toml +1 -1
- {alphaengine-1.0.2 → alphaengine-1.0.3}/scripts/gen_docs.py +1 -1
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/__init__.py +6 -1
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/_version.py +25 -20
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/agent/bakeoff.py +74 -20
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/agent/brief.py +93 -30
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/agent/chart.py +53 -23
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/agent/sim.py +22 -4
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/auth.py +56 -6
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/cli.py +247 -22
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/client/executor.py +12 -2
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/client/session.py +104 -13
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/commands.py +63 -5
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/__init__.py +2 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/backtest.py +8 -3
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/bakeoff.py +7 -3
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/pairs.py +4 -1
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/validation.py +83 -30
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/demo.py +20 -6
- alphaengine-1.0.3/src/alphaengine/io.py +381 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/model.py +44 -1
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/study/__init__.py +22 -2
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/study/report.py +77 -10
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/study/schema.py +84 -3
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/sweep/runner.py +47 -6
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/tui/app.py +33 -8
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/tui/dispatch.py +89 -12
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/tui/mark.py +2 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_bakeoff.py +4 -1
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_cli.py +46 -3
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_client.py +93 -4
- alphaengine-1.0.3/tests/test_coverage_paths.py +600 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_goldens.py +4 -1
- alphaengine-1.0.3/tests/test_io.py +116 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_math_audit.py +49 -4
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_sweep.py +228 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/.github/workflows/ci.yml +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/.gitignore +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/AGENTS.md +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/LICENSE +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/docs/assets/banner.png +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/docs/assets/data_boundary.png +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/docs/assets/session.png +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/docs/figure_contract.md +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/docs/workflows/evaluate_process.json +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/docs/workflows/research_week.json +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/docs/workflows/stress_study.json +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/__main__.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/agent/__init__.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/agent/answer.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/agent/driver.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/book.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/charts.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/client/__init__.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/client/agent.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/complete.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/connectors/__init__.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/context.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/active.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/allocate.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/covariance.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/cross_section.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/factors.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/market.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/options.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/panel.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/performance.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/portfolio.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/process.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/profile.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/rates.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/regime.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/relations.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/risk.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/screen.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/series_shapes.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/signals.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/stress.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/technical.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/trace.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/core/walkforward.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/demo_book.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/demo_returns.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/demo_signal.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/demo_universe.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/events.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/loaders.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/py.typed +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/repl.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/sweep/__init__.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/tui/__init__.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/tui/stage.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/src/alphaengine/tui/typeface.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_agent.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_answer.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_book.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_commands.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_context.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_events.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_executor_ops.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_loaders.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_model.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_portfolio.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_process.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_quant_maths.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_relations.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_screen.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_signals.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_sim.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_smoke.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_trace.py +0 -0
- {alphaengine-1.0.2 → alphaengine-1.0.3}/tests/test_tui.py +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Report a reproducible bug in AlphaEngine
|
|
4
|
+
title: "[Bug]: "
|
|
5
|
+
labels: ["bug"]
|
|
6
|
+
assignees: []
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
A clear and concise description of what went wrong.
|
|
12
|
+
|
|
13
|
+
## Reproduction
|
|
14
|
+
|
|
15
|
+
Minimal Python snippet or CLI command that reproduces the issue (using synthetic data or `alphaengine demo`):
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
import alphaengine
|
|
19
|
+
# ...
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Expected vs. actual behavior
|
|
23
|
+
|
|
24
|
+
- **Expected:**
|
|
25
|
+
- **Actual:**
|
|
26
|
+
|
|
27
|
+
## Environment
|
|
28
|
+
|
|
29
|
+
- `alphaengine` version (`alphaengine version`):
|
|
30
|
+
- Python version:
|
|
31
|
+
- OS:
|
|
32
|
+
- `numpy` / `scipy` versions:
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Data shape / loader issue
|
|
3
|
+
about: Report a CSV, Parquet, or interop data-shape edge case
|
|
4
|
+
title: "[Data shape]: "
|
|
5
|
+
labels: ["data-shape"]
|
|
6
|
+
assignees: []
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Data source / format
|
|
10
|
+
|
|
11
|
+
Which loader or flag was used (`--data`, `load_panel`, `alphaengine.io.from_quantconnect`, `alphaengine.io.from_vectorbt`, etc.)?
|
|
12
|
+
|
|
13
|
+
## Anonymized header and sample rows
|
|
14
|
+
|
|
15
|
+
Please paste 3–5 anonymized rows showing the header and column types (never paste proprietary price history):
|
|
16
|
+
|
|
17
|
+
```csv
|
|
18
|
+
date,symbol,close
|
|
19
|
+
2026-01-02,AAA,100.00
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Current behavior / error message
|
|
23
|
+
|
|
24
|
+
Paste the `DataShapeError` or unexpected behavior observed:
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Method request
|
|
3
|
+
about: Propose a published quantitative or statistical method for alphaengine.core
|
|
4
|
+
title: "[Method]: "
|
|
5
|
+
labels: ["enhancement", "methods"]
|
|
6
|
+
assignees: []
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Published reference
|
|
10
|
+
|
|
11
|
+
Everything in `alphaengine.core` comes from peer-reviewed literature. Please cite the paper or textbook:
|
|
12
|
+
|
|
13
|
+
- **Citation (authors, year, title, venue):**
|
|
14
|
+
- **DOI / URL:**
|
|
15
|
+
|
|
16
|
+
## What question does it answer?
|
|
17
|
+
|
|
18
|
+
Describe the statistical or risk question this primitive answers and how it fits into the validation/research loop.
|
|
19
|
+
|
|
20
|
+
## Proposed signature and inputs/outputs
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
def proposed_method(returns, ...):
|
|
24
|
+
...
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Dependencies
|
|
28
|
+
|
|
29
|
+
Does this method run on `numpy` + `scipy` alone, or does it require an optional extra (e.g. `statsmodels`)?
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
open-pull-requests-limit: 5
|
|
8
|
+
|
|
9
|
+
- package-ecosystem: "github-actions"
|
|
10
|
+
directory: "/"
|
|
11
|
+
schedule:
|
|
12
|
+
interval: "weekly"
|
|
13
|
+
open-pull-requests-limit: 5
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: codeql
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: "20 6 * * 1"
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
security-events: write
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
analyze:
|
|
17
|
+
name: Analyze (python)
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- name: Checkout repository
|
|
21
|
+
uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Initialize CodeQL
|
|
24
|
+
uses: github/codeql-action/init@v3
|
|
25
|
+
with:
|
|
26
|
+
languages: python
|
|
27
|
+
|
|
28
|
+
- name: Perform CodeQL Analysis
|
|
29
|
+
uses: github/codeql-action/analyze@v3
|
|
@@ -33,6 +33,9 @@ jobs:
|
|
|
33
33
|
- uses: actions/setup-python@v5
|
|
34
34
|
with:
|
|
35
35
|
python-version: "3.12"
|
|
36
|
+
- name: Verify git tag matches __version__
|
|
37
|
+
run: |
|
|
38
|
+
python -c "import os, runpy, sys; v = runpy.run_path('src/alphaengine/_version.py')['__version__']; ref = os.environ.get('GITHUB_REF_NAME') or os.environ.get('GITHUB_REF', '').removeprefix('refs/tags/'); exp = f'v{v}'; sys.exit(f'Tag {ref!r} != {exp!r}' if ref != exp else 0)"
|
|
36
39
|
- run: python -m pip install --upgrade build
|
|
37
40
|
- run: python -m build
|
|
38
41
|
- uses: actions/upload-artifact@v4
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `alphaengine` are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to Semantic Versioning (with computed golden values
|
|
7
|
+
treated as part of the public contract).
|
|
8
|
+
|
|
9
|
+
## [1.0.3] - 2026-10-24
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- **Sealed studies (Schema 1.2):** Canonical-JSON SHA-256 content hash (`content_sha256` with sorted keys and fixed 8-decimal float formatting), full 64-hex `data_hash`, and optional per-trial ledger export (`SweepResult.ledger()`, `include_ledger=True`).
|
|
13
|
+
- **CLI study verbs:** `alphaengine seal <study.json>` (writes `content_sha256` and verifies on re-run) and `alphaengine report <study.json> [--retail]` (reports to `/api/me/runs/ingest` by default or `/api/retail/ledger/import` with `--retail`).
|
|
14
|
+
- **Complete study ingest payload:** `study/report.py` `_payload()` now includes `selection` (PBO), `psr_vs_zero`, `sr0_expected_max`, `min_track_record_length`, `grid_keys`, `n_failed_trials`, `content_sha256`, and optional `assignment_id` and `thesis_id`.
|
|
15
|
+
- **Interop loaders (`alphaengine.io`):** `from_quantconnect(path)` and `from_vectorbt(portfolio_or_csv)` construct a `Study` with returns, performance metrics, data hash, and trial-count provenance (`"asserted"` when provided/present, `"not_recorded"` with verdict refusal when absent).
|
|
16
|
+
- **Credentials purge:** `alphaengine logout --purge` removes `~/.config/alphaengine/credentials.json`, cleans up its config directory, and clears managed keys from the current process.
|
|
17
|
+
- **API URL override:** `ALPHAENGINE_API_URL` environment variable and unified `DEFAULT_API_URL` constant across CLI and study reporting.
|
|
18
|
+
- **Security & governance:** Weekly Dependabot configuration (pip + GitHub Actions), Python CodeQL workflow, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, and GitHub issue templates.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
- **Opt-in series sharing on `/traces`:** `_report_trace` sends scalar figures only by default. Uploading full series to `/api/harness/runs/{id}/traces` requires `--share-series` or `ALPHAENGINE_SHARE_SERIES=1`; any payload sent without opt-in is guarded at most 512 elements.
|
|
22
|
+
- **Deliberate math & golden updates:**
|
|
23
|
+
- `deflated_sharpe(..., n_trials=1)` no longer silently deflates as `N=2`. At `n_trials=1`, `sr0_expected_max` is `0.0` (was `0.037` on the `rets(9, 200)` golden) and `deflated_sharpe` equals `psr_vs_zero` (`0.8434`, was `0.6875` on the golden), with an explicit note that no multiple-testing deflation applies.
|
|
24
|
+
- `SweepResult.verdict()` passes the cross-trial Sharpe dispersion across valid grid trials into `deflated_sharpe` per Bailey & López de Prado (2014), falling back to single-series sampling error only when fewer than 2 valid trials exist.
|
|
25
|
+
- Renamed `cpcv_score` to `combinatorial_oos_stability` (keeping `cpcv_score` as a deprecated alias) to accurately describe single-stream purged/embargoed sub-sample stability.
|
|
26
|
+
- `pbo_cscv` validates `n_splits` (even integer $\ge 2$) and raises a clear `ValueError`.
|
|
27
|
+
- **Neutral framing:** Added *"Research tool, not investment advice"* disclaimer to README, `--help`, and the boot screen; renamed user-facing bakeoff `survivor` / `survivor_weights` to `top_ranked_config` / `model_weights` while preserving backward-compatible dictionary keys.
|
|
28
|
+
- **Release guard:** `.github/workflows/publish.yml` verifies that the git tag matches `v{__version__}` before building.
|
|
29
|
+
|
|
30
|
+
## [1.0.2] - 2026-10-20
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
- **Four-pass adversarial GAN bakeoff:** `run_bakeoff` and `core.bakeoff.referee` run four passes (eight candidate proposals across `equal`, `hrp`, `risk_parity`, `inverse_vol`, `var_sorted`, `low_vol`, `momentum`, and `reversion` against eight regime, tail, rate, and crash-cluster attacks) under a hard 12-call, 60-second ceiling.
|
|
34
|
+
- **Multi-pass bakeoff scorecard in PDF reports:** Cumulative wealth across passes, in-sample vs. post-attack Sharpe comparison, and candidate scorecard table.
|
|
35
|
+
|
|
36
|
+
## [1.0.1] - 2026-10-19
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
- **Harness simulation tools:** Added `monte_carlo` and `scenarios` to the local session tool stack.
|
|
40
|
+
- **Multi-page PDF & text reports:** Accepted session traces render multi-panel portfolio, scenario stress, Monte Carlo fan, and bakeoff reports to the user's `Downloads` folder.
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
- **Ledoit-Wolf sample-count divisor:** Fixed sample covariance scaling in `ledoit_wolf_cov` so `hrp_weights` and `risk_parity_weights` differentiate weights across wide panels.
|
|
44
|
+
|
|
45
|
+
## [1.0.0] - 2026-10-18
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
- **Interactive terminal simulator (`alphaengine`):** Full-screen Textual session where plain-English questions execute as a deterministic stack of local tool calls (`profile`, `align`, `regime`, `price`, `reprice`, `correlation`, `covariance`, `cointegration`, `portfolio`, `overlap`, `performance`, `var`, `process`, `workflow`, `bakeoff`) with citation guarding.
|
|
49
|
+
- **Pinned cash rate & statistical refinements:** Default risk-free rate pinned to the H.15 3-month Treasury constant maturity (`4.21%` as of `2026-10-06`, `DGS3MO`; pass `0` for excess of zero), automatic Newey-West HAC lag selection in factor regressions, and Benjamini-Hochberg FDR survivors in cointegration screening.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, caste, color, religion, or sexual
|
|
10
|
+
identity and orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment for our
|
|
18
|
+
community include:
|
|
19
|
+
|
|
20
|
+
* Demonstrating empathy and kindness toward other people
|
|
21
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
|
22
|
+
* Giving and gracefully accepting constructive feedback
|
|
23
|
+
* Accepting responsibility and apologizing to those affected by our mistakes,
|
|
24
|
+
and learning from the experience
|
|
25
|
+
* Focusing on what is best not just for us as individuals, but for the overall
|
|
26
|
+
community
|
|
27
|
+
|
|
28
|
+
Examples of unacceptable behavior include:
|
|
29
|
+
|
|
30
|
+
* The use of sexualized language or imagery, and sexual attention or advances of
|
|
31
|
+
any kind
|
|
32
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
33
|
+
* Public or private harassment
|
|
34
|
+
* Publishing others' private information, such as a physical or email address,
|
|
35
|
+
without their explicit permission
|
|
36
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
|
37
|
+
professional setting
|
|
38
|
+
|
|
39
|
+
## Enforcement
|
|
40
|
+
|
|
41
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
42
|
+
reported to the project maintainers at **wfe818@gmail.com**. All complaints will
|
|
43
|
+
be reviewed and investigated promptly and fairly.
|
|
44
|
+
|
|
45
|
+
## Attribution
|
|
46
|
+
|
|
47
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
|
|
48
|
+
version 2.1, available at
|
|
49
|
+
<https://www.contributor-covenant.org/version/2/1/code_of_conduct.html>.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Contributing to AlphaEngine
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to AlphaEngine.
|
|
4
|
+
|
|
5
|
+
## Core design constraints
|
|
6
|
+
|
|
7
|
+
Before opening a pull request, please keep these architectural rules in mind:
|
|
8
|
+
|
|
9
|
+
1. **Two runtime dependencies (`numpy` and `scipy`).** Optional extras (`factors`, `agents`, `connectors`, `tui`) are lazy-imported so `import alphaengine` never requires network clients, LLM SDKs, or UI frameworks.
|
|
10
|
+
2. **Goldens are a public contract.** Computed values in `tests/test_goldens.py` are pinned so saved studies remain reproducible. Never modify a golden value simply to make a test pass; deliberate mathematical corrections require a version bump and a `CHANGELOG.md` entry explaining what changed and why.
|
|
11
|
+
3. **Data boundary.** Computation runs locally. Without explicit opt-in (`--share-series` or `ALPHAENGINE_SHARE_SERIES=1`), no list longer than 512 elements may leave the machine.
|
|
12
|
+
4. **Trial-count honesty.** Trial counts must be derived from the executed grid (`derived_from_grid`), explicitly marked (`asserted`), or `not_recorded` (which refuses an `edge` verdict).
|
|
13
|
+
|
|
14
|
+
## Local development setup
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
python -m venv .venv
|
|
18
|
+
source .venv/bin/activate # Windows PowerShell: .\.venv\Scripts\Activate.ps1
|
|
19
|
+
pip install -e ".[dev,factors]"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Required checks before submitting
|
|
23
|
+
|
|
24
|
+
Run all five CI gates locally before pushing:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
python -m ruff check src tests
|
|
28
|
+
python -m ruff format --check src tests
|
|
29
|
+
python -m mypy src
|
|
30
|
+
python -m pytest
|
|
31
|
+
python -m pytest tests -m golden -q
|
|
32
|
+
python scripts/gen_docs.py --check
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
If you add or modify CLI commands or flags in `src/alphaengine/commands.py`, regenerate the README command table with:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
python scripts/gen_docs.py --write
|
|
39
|
+
```
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: alphaengine
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
4
4
|
Summary: Validated research tooling for investment strategies: deflation, overfitting detection, and honest trial counts.
|
|
5
|
-
Project-URL: Homepage, https://
|
|
5
|
+
Project-URL: Homepage, https://qosai.app
|
|
6
6
|
Project-URL: Documentation, https://github.com/quantOSC/alphaengine#readme
|
|
7
7
|
Project-URL: Source, https://github.com/quantOSC/alphaengine
|
|
8
8
|
Project-URL: Issues, https://github.com/quantOSC/alphaengine/issues
|
|
@@ -53,8 +53,10 @@ Description-Content-Type: text/markdown
|
|
|
53
53
|
|
|
54
54
|
<p align="center">
|
|
55
55
|
<strong>The research loop, on your machine.</strong><br>
|
|
56
|
-
Ask what is worth looking at, whether it holds up,
|
|
57
|
-
and whether anything has crossed a line
|
|
56
|
+
Ask what is worth looking at, whether it holds up, what sizing the risk model implies,<br>
|
|
57
|
+
and whether anything has crossed a line.<br>
|
|
58
|
+
Computation runs locally; when you are signed in to quantOS, summary figures are reported to your account; full series are shared only if you opt in.<br>
|
|
59
|
+
<em>Research tool, not investment advice.</em>
|
|
58
60
|
</p>
|
|
59
61
|
|
|
60
62
|
<p align="center">
|
|
@@ -84,7 +86,7 @@ python -m alphaengine
|
|
|
84
86
|
┌──────────┬─────────────────────────────────────┬──────────────────┐
|
|
85
87
|
│ ● maths │ Ask in plain English. │ sharpe │
|
|
86
88
|
│ always │ │ mean / std √252 │
|
|
87
|
-
│ ○ flows │ > which names
|
|
89
|
+
│ ○ flows │ > which names rank highest on RSI? │ ▁▂▃▅▇█▇▅▃ │
|
|
88
90
|
│ ○ ask │ │ 0 0.0012 │
|
|
89
91
|
│ │ chose screen_universe │ 1 -0.0040 │
|
|
90
92
|
│ loaded │ │ │
|
|
@@ -103,8 +105,19 @@ alphaengine
|
|
|
103
105
|
> screen
|
|
104
106
|
```
|
|
105
107
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
+
Computation runs locally on this machine. When you are signed in to quantOS,
|
|
109
|
+
summary figures are reported to your account; full series are shared on
|
|
110
|
+
`/traces` only if you opt in (`--share-series` or `ALPHAENGINE_SHARE_SERIES=1`).
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Where this sits
|
|
115
|
+
|
|
116
|
+
AlphaEngine computes locally on your machine against your own data.
|
|
117
|
+
[quantOS](https://qosai.app) is the hosted research workspace that keeps the
|
|
118
|
+
record and writes committee reports. Everything in AlphaEngine's math and sweep
|
|
119
|
+
layer runs offline with no account; signing in connects local runs and sealed
|
|
120
|
+
studies to your quantOS workspace.
|
|
108
121
|
|
|
109
122
|
---
|
|
110
123
|
|
|
@@ -121,7 +134,7 @@ IS the question; only two of them need code of yours.
|
|
|
121
134
|
| Is this real, once you count the tries? | `validate` | `validate_study` | prices + your backtest |
|
|
122
135
|
| Where does it break? | `stress` | `stress_study` | a return series |
|
|
123
136
|
| Is it new, or my book again? | `overlap` | `check_overlap` | the candidate + the book |
|
|
124
|
-
|
|
|
137
|
+
| What sizing does the risk model imply? | `size` | `size_position` | a return series |
|
|
125
138
|
| Still inside the lines? | `monitor` | `monitor_sleeve` | a return series |
|
|
126
139
|
|
|
127
140
|
```bash
|
|
@@ -141,7 +154,7 @@ Or say it in plain English and let your own model pick:
|
|
|
141
154
|
|
|
142
155
|
```bash
|
|
143
156
|
alphaengine
|
|
144
|
-
❯ which of my names
|
|
157
|
+
❯ which of my names rank highest on RSI?
|
|
145
158
|
```
|
|
146
159
|
|
|
147
160
|
That second path is EXPLORATORY: the model chooses a workflow and then chooses
|
|
@@ -157,12 +170,28 @@ Each is useful without the one above it. `login` lights the next one.
|
|
|
157
170
|
|
|
158
171
|
| Rung | What you need | What you get |
|
|
159
172
|
|---|---|---|
|
|
160
|
-
| **The maths** | nothing |
|
|
161
|
-
| **Workflows** | a
|
|
173
|
+
| **The maths** | nothing | `alphaengine demo`, `alphaengine process`, and the full Python API (`import alphaengine`, `sweep`, `core`), offline, forever. No account. |
|
|
174
|
+
| **Workflows** | a portal-issued `ae_live_` key (`login` or `QUANTOS_API_KEY`; request access at [https://qosai.app/access](https://qosai.app/access)) | The eight workflow commands (`diagnose`, `screen`, `signal`, `validate`, `stress`, `overlap`, `size`, `monitor`) plus `workflows`, `runs`, `gaps`, `tonight`, and `run <workflow>`. |
|
|
162
175
|
| **Ask anything** | your OWN model key (`login anthropic`) | Plain English in. Runs under your account, not ours. |
|
|
163
176
|
|
|
164
|
-
|
|
165
|
-
|
|
177
|
+
The eight workflow commands (`diagnose`, `screen`, `signal`, `validate`,
|
|
178
|
+
`stress`, `overlap`, `size`, `monitor`) and `workflows` / `runs` require a
|
|
179
|
+
portal-issued `ae_live_` key because the workflow graph and account record live
|
|
180
|
+
on the server (request access at [https://qosai.app/access](https://qosai.app/access)).
|
|
181
|
+
`alphaengine demo`, `alphaengine process`, and the Python library (`import alphaengine`)
|
|
182
|
+
work completely offline without an account or key.
|
|
183
|
+
|
|
184
|
+
**How credentials are handled.** QuantOS never receives your LLM provider key:
|
|
185
|
+
it goes directly from this process to your chosen provider. By default, keys can
|
|
186
|
+
be supplied via environment variables (`QUANTOS_API_KEY`, `ANTHROPIC_API_KEY`,
|
|
187
|
+
`OPENAI_API_KEY`, etc.), which touches nothing on disk. If you run `login` and
|
|
188
|
+
say **yes** to *"Stay signed in on this machine?"*, `auth.py` writes an optional
|
|
189
|
+
`~/.config/alphaengine/credentials.json` (`0600` permissions;
|
|
190
|
+
`%APPDATA%\alphaengine\credentials.json` on Windows) so you do not have to
|
|
191
|
+
re-paste in every terminal. Environment variables always win over that file.
|
|
192
|
+
To avoid disk storage entirely, set environment variables only (or answer `n`
|
|
193
|
+
at `login`). To delete the stored file at any time, run
|
|
194
|
+
`alphaengine logout --purge` (or `alphaengine logout`).
|
|
166
195
|
|
|
167
196
|
```mermaid
|
|
168
197
|
flowchart LR
|
|
@@ -220,6 +249,15 @@ distinction is the whole of the data boundary below.
|
|
|
220
249
|
|
|
221
250
|
---
|
|
222
251
|
|
|
252
|
+
## What's new in 1.0.3
|
|
253
|
+
|
|
254
|
+
- **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`.
|
|
255
|
+
- **Sealed studies (schema 1.2) & CLI reporting:** Studies now carry a canonical-JSON SHA-256 seal (`content_sha256`), a full 64-hex `data_hash`, and an optional per-trial ledger (`include_ledger=True`). Use `alphaengine seal <study.json>` to seal or verify a study file, and `alphaengine report <study.json> [--retail]` to ingest into quantOS or the retail experiment ledger.
|
|
256
|
+
- **Math fixes:** `SweepResult.verdict()` passes cross-trial Sharpe dispersion into `deflated_sharpe` per Bailey & López de Prado (2014); `deflated_sharpe(n_trials=1)` returns `psr_vs_zero` with `sr0_expected_max = 0.0` instead of deflating as `N=2`; `combinatorial_oos_stability` replaces `cpcv_score` (kept as a deprecated alias); and `pbo_cscv` validates that `n_splits` is an even integer $\ge 2$.
|
|
257
|
+
- **Interop loaders (`alphaengine.io`):** `from_quantconnect(path)` and `from_vectorbt(portfolio_or_csv)` build a `Study` with returns and preserve trial-count provenance (`"asserted"` vs. `"not_recorded"`).
|
|
258
|
+
|
|
259
|
+
See [CHANGELOG.md](CHANGELOG.md) for 1.0.0–1.0.3 release notes.
|
|
260
|
+
|
|
223
261
|
## What's new in 0.9.0
|
|
224
262
|
|
|
225
263
|
`next_open` fills wait for a prior close. The first bar of a next-open backtest
|
|
@@ -227,9 +265,10 @@ no longer trades that bar's own signal at that bar's open. Close fills are
|
|
|
227
265
|
unchanged, and the published goldens do not move.
|
|
228
266
|
|
|
229
267
|
The session is the full-screen terminal (`pip install "alphaengine[tui]"`).
|
|
230
|
-
Each statistic keeps its formula, inputs, and series.
|
|
231
|
-
`/api/harness/runs/{id}/traces
|
|
232
|
-
|
|
268
|
+
Each statistic keeps its formula, inputs, and series locally. By default,
|
|
269
|
+
`/api/harness/runs/{id}/traces` receives scalar figures only; full series are
|
|
270
|
+
uploaded only when you opt in (`--share-series` or `ALPHAENGINE_SHARE_SERIES=1`).
|
|
271
|
+
A portal that rejects the trace does not fail the run.
|
|
233
272
|
|
|
234
273
|
## What's new in 0.8.0
|
|
235
274
|
|
|
@@ -246,8 +285,8 @@ are a public contract from this release. The study schema is **1.1**: optional
|
|
|
246
285
|
| Figures that already travel | `{kind, key, title}` hints a portal maps to a chart | `charts`, [figure contract](docs/figure_contract.md) |
|
|
247
286
|
|
|
248
287
|
The terminal boot is the README banner: tracked `ALPHAENGINE`, the subtitle,
|
|
249
|
-
a teal-left / amber-right mesh (plateau, valley, knife-edge ridge), and
|
|
250
|
-
|
|
288
|
+
a teal-left / amber-right mesh (plateau, valley, knife-edge ridge), and the
|
|
289
|
+
local-computation notice. `alphaengine process` fits a DGP offline, no account.
|
|
251
290
|
|
|
252
291
|
```python
|
|
253
292
|
from alphaengine.core import ou_calibrate, garch_calibrate, dgp_stress, grinold_alpha
|
|
@@ -323,9 +362,11 @@ w = hrp_weights(cov, names=names) # no matrix inverse; weights sum to one
|
|
|
323
362
|
| `validate` | is this real? | shell + session |
|
|
324
363
|
| `stress` | where does it break? | shell + session |
|
|
325
364
|
| `overlap` | is it new, or my book again? | shell + session |
|
|
326
|
-
| `size` |
|
|
365
|
+
| `size` | what sizing does the risk model imply? | shell + session |
|
|
327
366
|
| `monitor` | still inside the lines? | shell + session |
|
|
328
367
|
| `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 |
|
|
329
370
|
| `<anything else>` | ask in plain English; your model picks a workflow and drives it | session |
|
|
330
371
|
| `status` | the current run, and what is loaded | session |
|
|
331
372
|
|
|
@@ -348,7 +389,7 @@ w = hrp_weights(cov, names=names) # no matrix inverse; weights sum to one
|
|
|
348
389
|
|
|
349
390
|
| Command | Does | Where |
|
|
350
391
|
|---|---|---|
|
|
351
|
-
| `logout` | remove stored credentials from this machine | shell + session |
|
|
392
|
+
| `logout [--purge]` | remove stored credentials from this machine | shell + session |
|
|
352
393
|
| `version` | print the version | shell |
|
|
353
394
|
| `help` | the short list: demo, login, load, then a question | session |
|
|
354
395
|
| `quit` | leave the session | session |
|
|
@@ -376,8 +417,11 @@ w = hrp_weights(cov, names=names) # no matrix inverse; weights sum to one
|
|
|
376
417
|
| `--input K=V` | a workflow input; repeatable |
|
|
377
418
|
| `--quiet` | only the result, no step narration |
|
|
378
419
|
| `--stream` | print the answer once the citation guard has passed |
|
|
420
|
+
| `--share-series` | opt in to uploading full series on run traces (default off; or $ALPHAENGINE_SHARE_SERIES=1) |
|
|
379
421
|
| `--limit N` | how many rows to show (default 25) |
|
|
380
422
|
| `--budget N` | how many runs a night is worth (default 3) |
|
|
423
|
+
| `--purge` | remove ~/.config/alphaengine/credentials.json and clean up its config directory |
|
|
424
|
+
| `--retail` | send the study to the retail experiment ledger (/api/retail/ledger/import) |
|
|
381
425
|
|
|
382
426
|
### Examples
|
|
383
427
|
|
|
@@ -404,10 +448,14 @@ alphaengine commands
|
|
|
404
448
|
alphaengine run screen_universe --universe sp500
|
|
405
449
|
alphaengine run size_position --data returns.csv
|
|
406
450
|
alphaengine run validate_study --project research.momentum
|
|
451
|
+
alphaengine seal study.json
|
|
452
|
+
alphaengine report study.json
|
|
453
|
+
alphaengine report study.json --retail
|
|
407
454
|
alphaengine models
|
|
408
455
|
alphaengine trace
|
|
409
456
|
alphaengine run screen_universe --thesis momentum
|
|
410
457
|
alphaengine logout
|
|
458
|
+
alphaengine logout --purge
|
|
411
459
|
alphaengine version
|
|
412
460
|
```
|
|
413
461
|
|
|
@@ -461,7 +509,7 @@ def backtest_fn(*, data, fast, slow):
|
|
|
461
509
|
```
|
|
462
510
|
|
|
463
511
|
`data` is whatever you want it to be — a DataFrame, a dict of series, an array.
|
|
464
|
-
The package never inspects it
|
|
512
|
+
The package never inspects it; computation runs locally on your machine.
|
|
465
513
|
|
|
466
514
|
## What it does
|
|
467
515
|
|
|
@@ -531,8 +579,10 @@ Study.from_sweep(r, label="momentum, 9 configs").report()
|
|
|
531
579
|
|
|
532
580
|
What crosses is an explicit allowlist: the trial count and how it was obtained,
|
|
533
581
|
a content hash of the data, the verdict, the shape of the neighbourhood, the
|
|
534
|
-
performance figures.
|
|
535
|
-
|
|
582
|
+
performance figures. Computation runs locally; when you are signed in to
|
|
583
|
+
quantOS, summary figures are reported to your account, and full series are
|
|
584
|
+
shared only if you opt in (`--share-series` or `ALPHAENGINE_SHARE_SERIES=1`).
|
|
585
|
+
Without opt-in, a guard keyed on length (at most 512 elements) refuses to send
|
|
536
586
|
anything series-shaped whatever it is called.
|
|
537
587
|
|
|
538
588
|
Reporting is the only part of this package that touches a network, so it is the
|
|
@@ -541,15 +591,16 @@ makes no network call.
|
|
|
541
591
|
|
|
542
592
|
## Where this sits in QuantOS
|
|
543
593
|
|
|
544
|
-
AlphaEngine is the open research layer of
|
|
545
|
-
|
|
546
|
-
is complete on its own: everything above works
|
|
594
|
+
AlphaEngine is the open research layer of [quantOS](https://qosai.app)
|
|
595
|
+
([GitHub](https://github.com/quantOSC)). AlphaEngine computes locally on your
|
|
596
|
+
machine, against your data, and is complete on its own: everything above works
|
|
597
|
+
offline and forever, at no cost.
|
|
547
598
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
599
|
+
quantOS ([https://qosai.app](https://qosai.app)) is the hosted research workspace
|
|
600
|
+
that keeps the record and writes committee reports. Studies produced here can be
|
|
601
|
+
persisted to a firm's record, referenced when an idea becomes a position, and
|
|
602
|
+
assembled into the reports that go to an investment committee or an allocator.
|
|
603
|
+
The library computes; the platform remembers and reports.
|
|
553
604
|
|
|
554
605
|
## The methods
|
|
555
606
|
|
|
@@ -563,19 +614,35 @@ Frontier." *Journal of Risk* 15(2), 3 to 44.
|
|
|
563
614
|
Bailey, D. H., and López de Prado, M. (2014). "The Deflated Sharpe Ratio:
|
|
564
615
|
Correcting for Selection Bias, Backtest Overfitting, and Non-Normality."
|
|
565
616
|
*Journal of Portfolio Management* 40(5), 94 to 107.
|
|
617
|
+
*Implementation notes:* Grid trials are treated as independent (`N = len(grid)`
|
|
618
|
+
with no effective-$N$ clustering adjustment). Cross-trial Sharpe dispersion
|
|
619
|
+
($\sigma_{\text{SR}}$) is computed across valid grid trials when at least two
|
|
620
|
+
exist, falling back to single-series Lo (2002) sampling error otherwise. At
|
|
621
|
+
`n_trials=1`, no multiple-testing deflation applies (`sr0_expected_max = 0.0`,
|
|
622
|
+
`deflated_sharpe = psr_vs_zero`). Verdict thresholds on `deflated_sharpe`:
|
|
623
|
+
`< 0.5` is `likely_noise`, `0.5` to `< 0.9` is `marginal`, and `DSR >= 0.9` is
|
|
624
|
+
`robust`.
|
|
566
625
|
|
|
567
626
|
**Probability of Backtest Overfitting via CSCV**
|
|
568
627
|
Bailey, D. H., Borwein, J., López de Prado, M., and Zhu, Q. J. (2017). "The
|
|
569
628
|
Probability of Backtest Overfitting." *Journal of Computational Finance* 20(4),
|
|
570
629
|
39 to 69.
|
|
571
630
|
|
|
572
|
-
**Combinatorial
|
|
631
|
+
**Combinatorial out-of-sample stability (`combinatorial_oos_stability`)**
|
|
573
632
|
López de Prado, M. (2018). *Advances in Financial Machine Learning.* Wiley,
|
|
574
633
|
chapters 7 and 12.
|
|
634
|
+
*Implementation note:* Evaluates a single pre-computed return stream across all
|
|
635
|
+
$\binom{G}{k}$ held-out block combinations with `purge` and `embargo` trimmed
|
|
636
|
+
from each test block (no model re-fitting or stitched training predictions).
|
|
637
|
+
`cpcv_score` is retained as a deprecated alias.
|
|
575
638
|
|
|
576
639
|
**Hierarchical Risk Parity**
|
|
577
640
|
López de Prado, M. (2016). "Building Diversified Portfolios that Outperform
|
|
578
641
|
Out of Sample." *Journal of Portfolio Management* 42(4), 59 to 69.
|
|
642
|
+
*Implementation note:* `hrp_weights` uses the correlation metric distance
|
|
643
|
+
$d_{ij} = \sqrt{\frac{1}{2}(1 - \rho_{ij})}$ with single-linkage hierarchical
|
|
644
|
+
clustering (`scipy.cluster.hierarchy.linkage(..., method="single")`), followed
|
|
645
|
+
by quasi-diagonalization and recursive inverse-variance bisection.
|
|
579
646
|
|
|
580
647
|
**Covariance shrinkage and spectral denoising**
|
|
581
648
|
Ledoit, O., and Wolf, M. (2004). "A Well-Conditioned Estimator for
|
|
@@ -690,10 +757,11 @@ controls switched off. Only a run that could not execute a step exits non-zero.
|
|
|
690
757
|
> CLI, is the one thing that cannot work here. You cannot have isolation and
|
|
691
758
|
> in-process data access, and your data not moving is the point.
|
|
692
759
|
|
|
693
|
-
**No LLM dependency
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
760
|
+
**No LLM dependency in the core.** `AgentDriver` takes a callable, so you bring
|
|
761
|
+
your own model by passing a function or setting your provider's environment
|
|
762
|
+
variable. LLM keys are never sent to QuantOS; if you choose to persist keys
|
|
763
|
+
locally at `login`, they live in `~/.config/alphaengine/credentials.json`
|
|
764
|
+
(mode `0600`) and are removed by `alphaengine logout --purge`.
|
|
697
765
|
|
|
698
766
|
## Development
|
|
699
767
|
|