Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ PYTHONPATH=. .venv/bin/python scripts/generate_report.py \
--prices-csv local_data/published_rotation_prices.csv \
--cash-proxy-symbol SHV
scripts/build_paper.sh
scripts/release_expansion_artifacts.sh local_data/expansion
```

Install from `requirements/dev.lock`. Scripts need `PYTHONPATH=.` unless
Expand Down Expand Up @@ -68,8 +69,8 @@ update regression tests.
Never commit `.env`, credentials, broker account data, local state, market-data
snapshots, or executed notebook outputs. Published performance and paper
artifacts require owner approval, adjacent provenance, an input digest, and
artifact hashes; release them from a clean commit with
`scripts/release_paper_artifacts.sh`. Ordinary reports remain ignored. Use
artifact hashes; release them from a clean commit with the release wrappers.
Ordinary reports remain ignored. Use
`.env.example`.
Synthetic data is limited to tests and clearly labeled dry runs. Preserve
pre-trade risk checks, paper-mode defaults, and point-in-time data discipline.
8 changes: 8 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ the development lock with `pip install -r requirements/dev.lock`, then run
`generate_report.py --live-yfinance`; `validate_performance.py` requires
`--live-yfinance`; `survivorship_demo.py` requires `--live-yfinance`;
`paper_trade_cycle.py` requires either `--offline` or `--live-yfinance`.
- Expansion release: freeze and commit the protocol before provider requests;
keep both matrices under ignored `local_data/expansion/`. After committing
source, run `scripts/release_expansion_artifacts.sh local_data/expansion`.
A first or changed release requires a fixed UTC
`QUANTCORTEX_EXPANSION_GENERATED_AT`. Never edit aggregate tables, generated
LaTeX, manifests, or figures by hand.
- Paper release: commit source changes, then run
`scripts/release_paper_artifacts.sh local_data/published_rotation_prices.csv`.
The wrapper regenerates `docs/img/` and the paper from a detached clean
Expand Down Expand Up @@ -126,6 +132,8 @@ or vol-scaled book is NOT required to sum to 1. Violations raise
may be published only with explicit owner approval, adjacent provenance, an
input digest, and artifact hashes. The same rule applies to reviewed paper
aggregates and figures under `paper/`; raw provider matrices remain local.
Repository freezing reduces post-data discretion but is not external
preregistration or a temporal holdout, and documentation must not imply it is.
Synthetic fixtures remain appropriate for tests and the clearly labeled
`paper_trade_cycle.py --offline` dry run.

Expand Down
56 changes: 52 additions & 4 deletions PERFORMANCE.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Performance Evaluation

This repository publishes one owner-authorized reference run as derived chart
artifacts. The raw market data remains uncommitted. Ordinary generated reports
and executed notebook outputs remain excluded unless publication is explicitly
approved and accompanied by complete provenance and artifact hashes.
This repository publishes one owner-authorized reference audit and one
repository-frozen multi-panel expansion as derived artifacts. Raw market data
remains uncommitted. Ordinary generated reports and executed notebook outputs
remain excluded unless publication is explicitly approved and accompanied by
complete provenance and artifact hashes.

## Published Reference Run

Expand Down Expand Up @@ -101,6 +102,46 @@ never an executable path. Assigning zero return to residual cash lowers the
consistently measured SHV-excess Sharpe to -0.42. See
`paper/results/protocol_switches.csv`.

## Repository-Frozen Expansion

The expansion protocol was frozen in public commit
`4018f4063f46889f41d6981db5a71079e1dbd713` before the two provider requests.
It was not externally registered, and the 2018-2025 evaluation interval had
already occurred. The design therefore limits researcher degrees of freedom
relative to this run but is not a temporal out-of-sample test.

The evaluation covers time-series momentum, cross-sectional momentum,
short-term reversal, and a walk-forward gradient-boosted model across U.S.
sector and country-equity ETF panels. Each family uses monthly mature signals,
next-bar event accounting, SHV residual cash, and the same 13 bps proportional
cost. The learned family reports all five frozen seeds.

| Panel | Strategy family | Arithmetic return | SHV-excess Sharpe |
|---|---|---:|---:|
| U.S. sectors | Time-series momentum | 11.44% | 0.49 |
| U.S. sectors | Cross-sectional momentum | 14.19% | 0.60 |
| U.S. sectors | Short-term reversal | 11.02% | 0.44 |
| U.S. sectors | Learned GBRT | 13.66% | 0.53 |
| Country equities | Time-series momentum | 2.18% | -0.02 |
| Country equities | Cross-sectional momentum | 8.84% | 0.33 |
| Country equities | Short-term reversal | 6.03% | 0.20 |
| Country equities | Learned GBRT | 7.84% | 0.31 |

These baselines are inputs to the audit, not discoveries. Under the primary
21-session circular-block analysis, removing modeled cost raises annualized
return by 0.57-1.81 percentage points and has an interval above zero in all
eight family-panel cells. Invalid same-close assignment is below zero in three
cells and overlaps zero in five; zero residual-cash return is below zero in
five and overlaps zero in three. The maximum one-day vectorized-versus-event
difference is 93.21 bps and the largest absolute terminal-wealth gap is 3.89%.
The engine result reflects different documented holding conventions, not an
external-engine conformance claim.

All intervals are unstudentized, pointwise, and conditional on the selected
historical paths. They are not multiplicity-adjusted evidence of future alpha.
See `paper/expansion/results/`, the plots under `paper/expansion/figures/`, and
the frozen design in `paper/preregistration.md`.

## Generate a Report

Use a licensed or otherwise permitted wide adjusted-close CSV:
Expand Down Expand Up @@ -188,6 +229,13 @@ capacity and slippage curves only with spread, volume, and order-size inputs;
factor attribution only with validated factor returns/exposures; and fill
quality only from authenticated order and execution records.

The expansion release is separate from the general report. From a clean source
commit, `scripts/release_expansion_artifacts.sh local_data/expansion` regenerates
the six aggregate CSVs, target-tape and data-provenance JSON, generated LaTeX,
and five figures in a detached worktree. Its manifest binds the frozen protocol,
both input hashes, source tree, environment, and every output hash. The paper
release requires expansion artifacts from the same clean source commit.

## Reporting Requirements

- Report the data provider, license or permission basis, retrieval date, date
Expand Down
40 changes: 37 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,41 @@ chart hashes and provenance are recorded in
That owner-supplied authorization does not independently establish that the
provider's terms permit publication.

## Repository-Frozen Expansion

The paper also evaluates four fixed strategy families across U.S. sector and
country-equity ETF panels from 2018 through 2025. The protocol was committed
before either panel was requested, but it was not externally registered and the
historical interval is not a temporal holdout. All models use mature features,
next-bar execution, SHV residual cash, 13 bps per dollar traded, and 5,000 joint
circular-block draws.

![After-cost baseline outcomes across the frozen strategy-panel cells](paper/expansion/figures/baseline_performance.png)

Seven of eight baseline sample Sharpes are positive, but these descriptive
outcomes are not alpha claims. The central result is sensitivity to evaluation
semantics:

| 21-session pointwise interval result | Cells out of 8 |
|---|---:|
| Removing modeled cost: above zero | 8 |
| Invalid same-close assignment: below / overlaps / above | 3 / 5 / 0 |
| Zero cash return: below / overlaps / above | 5 / 3 / 0 |
| Strategy minus costed exposure comparator: below / overlaps / above | 1 / 7 / 0 |

![Paired annualized-return effects under each contract switch](paper/expansion/figures/contract_effects_return.png)

The intervals are pointwise, conditional on two selected panels, and not
multiplicity adjusted. Raw matrices are not distributed; panel digests, target
tape hashes, aggregate tables, source fingerprints, and figure hashes are in
[`paper/expansion/results/manifest.json`](paper/expansion/results/manifest.json).

## Research Paper

The [NeurIPS 2026-format public preprint](paper/quantcortex_audit_neurips2026.pdf)
formalizes the executable contracts, exact attribution, controlled protocol
diagnostics, fixed negative result, uncertainty, limitations, and provenance.
diagnostics, the retrospective negative result, the repository-frozen expansion,
uncertainty, limitations, and provenance.
It is not represented as accepted by or submitted to NeurIPS.
An [anonymized preprint build](paper/quantcortex_audit_anonymous.pdf) is generated
from the same source and omits author and repository identifiers.
Expand All @@ -141,7 +171,7 @@ from the same source and omits author and repository identifiers.

See [paper/README.md](paper/README.md) for the build and reproduction workflow.
Aggregate tables, generated paper values, source fingerprints, and artifact
hashes are committed under `paper/results/`.
hashes are committed under `paper/results/` and `paper/expansion/results/`.

## Quick Start

Expand Down Expand Up @@ -190,6 +220,9 @@ PYTHONPATH=. python scripts/generate_report.py \
scripts/release_paper_artifacts.sh \
local_data/published_rotation_prices.csv

# Regenerate the reviewed expansion aggregates and figures from a clean commit.
scripts/release_expansion_artifacts.sh local_data/expansion

# Explicit live-data diagnostics; review the provider's terms first.
python scripts/validate_performance.py --live-yfinance
python scripts/survivorship_demo.py --live-yfinance
Expand Down Expand Up @@ -254,7 +287,8 @@ before using production capital. Security reporting is documented in
- [docs/data-source-due-diligence.md](docs/data-source-due-diligence.md): publication-data acceptance rules
- [docs/production-readiness.md](docs/production-readiness.md): external release gates
- [paper/README.md](paper/README.md): paper reproduction and submission constraints
- [paper/preregistration.md](paper/preregistration.md): prospective expansion protocol, not yet registered
- [paper/COMPUTE.md](paper/COMPUTE.md): reviewed host and release wall times
- [paper/preregistration.md](paper/preregistration.md): repository-frozen expansion protocol; not an external registry entry
- [local_data/README.md](local_data/README.md): accepted local-data schemas and provenance
- [CONTRIBUTING.md](CONTRIBUTING.md): contribution workflow
- [AGENTS.md](AGENTS.md): concise repository guidance for coding agents
Expand Down
31 changes: 17 additions & 14 deletions docs/data-source-due-diligence.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,26 @@ new empirical panel becomes publication evidence, record the provider, dataset,
contracting party, permitted uses, redistribution terms, reviewer-access path,
retrieval timestamp, adjustment method, symbol mapping, and content digest.

## Current Historical Case
## Current Historical Evidence

The fixed 2018-2025 case was computed from an owner-supplied Yahoo Finance
adjusted-close matrix retrieved through yfinance. The raw matrix is ignored and
not distributed. The repository publishes derived aggregates and records the
input SHA-256, while explicitly stating that provider authorization for public
publication has not been independently verified.
The fixed 2018-2025 case and the two-panel expansion were computed from
owner-supplied Yahoo Finance adjusted-close matrices retrieved through
yfinance. The raw matrices are ignored and not distributed. The repository
publishes derived aggregates and records each input SHA-256, while explicitly
stating that provider authorization for public publication has not been
independently verified.

This case is retained as historical negative evidence. It is not an acceptable
source for a new confirmatory panel unless the author documents an applicable
permission basis. The open code and conformance fixtures reproduce software
semantics, not the unavailable observations.
The first case is retained as historical negative evidence. The expansion was
repository-frozen before retrieval but was not externally registered and is not
a temporal holdout. Neither is represented as reviewer-reproducible empirical
evidence. The open code and conformance fixtures reproduce software semantics,
not the unavailable observations.

## Acceptance Criteria for New Panels

A panel may enter a preregistered evaluation only when all of the following are
documented before results are inspected:
A panel may be represented as publication-ready, independently reproducible
empirical evidence only when all of the following are documented before results
are inspected:

1. Lawful research use and publication of derived results are permitted.
2. Adjustment, calendar, timestamp, and survivorship policies are explicit.
Expand All @@ -43,5 +46,5 @@ performance.

For each candidate source, create a dated record under ignored local research
notes before acquisition. Do not add provider files to Git. If the permission
basis is ambiguous, exclude the panel from publication evidence and report the
scope reduction.
basis is ambiguous, disclose that limitation and do not claim the panel is open,
independently reproducible, or submission-ready.
7 changes: 4 additions & 3 deletions docs/evaluation-contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ the complete symbol set and gross limit:
and primitive constraints for other engines. Runtime validation additionally
enforces cross-record portfolio invariants: no duplicate timestamp-symbol rows,
the declared symbol universe at every decision, and the per-decision gross
limit. The paper experiment round-trips each variant through this boundary
before backtesting and publishes canonical payload hashes in
`paper/results/target_tape_hashes.json`.
limit. The paper experiments round-trip each variant through this boundary
before backtesting and publish canonical payload hashes in
`paper/results/target_tape_hashes.json` and
`paper/expansion/results/target_tape_hashes.json`.

The evaluation contract also records post-overlay exposure rules and the
paper-trading order-state policy: persist intent before submission, block
Expand Down
Binary file modified docs/img/allocation_and_exposure.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/drawdown.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/equity_vs_benchmarks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/monthly_returns.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/performance_attribution.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 18 additions & 16 deletions docs/img/performance_manifest.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
{
"schema_version": 4,
"generated_at": "2026-06-18T22:06:35Z",
"generated_at": "2026-06-18T23:53:33Z",
"generator": {
"path": "scripts/generate_report.py",
"script_sha256": "b536aa7fc5e4fe7df6c7ff28c0992629a489869eaec46486db7aff1cb946099b",
"git": {
"source_commit": "ef6e7e3414aed0ae9b77d50748a22823529486af",
"source_commit": "e0443b8f77cd23aee8f1fa64a2bc237e47626c47",
"worktree_clean_at_start": true
},
"source_tree": {
"sha256": "f964d653b5e645e1efe97889e8acb43fbb0c2c8ddeb0835803f07c299abff5a0",
"file_count": 107,
"sha256": "441586b7f43e68245a94a797d291fa80f51bb413c3174651d2e3dada17f56d3a",
"file_count": 109,
"files": {
"poetry.lock": "abce2cd132651851d81034dea085d7dbfbe5e44321f2e13997db69f46d7f080b",
"poetry.lock": "c0fd02871263d959522bb3d3d4717cffa1b89bfa047f584c68b81c7ad7cbbb5b",
"pyproject.toml": "eaeeb454c28bf7f6d9e530002bb7e88624b56b6c3e1fcb71e6414045cb9c42a0",
"quantcortex/__init__.py": "14bf1ebdacd054c3738e4704d33da6709a39206463df8b8ced5376da342c4036",
"quantcortex/alpha/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
Expand Down Expand Up @@ -100,6 +100,8 @@
"quantcortex/portfolio/mean_variance.py": "235a8917e107ab6274ee68891a489a130ae61fe36d359dc43e049d256453d80d",
"quantcortex/portfolio/minimum_variance.py": "253a9d80fe6dc6e4c95219b76a8965230b408093d1521a72587505ae0ddfc739",
"quantcortex/portfolio/risk_parity.py": "ed371437655ae980fabfc4ae450ca2100d90f304d9ce225c306f904ce1e32e91",
"quantcortex/research/__init__.py": "46e11b28979db5adfbe08f946e59b8e858de7d2a1feca714be5b0bd7cce1c32f",
"quantcortex/research/expansion.py": "a4cde375dcd650a1bd367d07da11e20e5b770a34496ccf3c82ba8e0c7467ed2a",
"quantcortex/risk/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"quantcortex/risk/circuit_breaker.py": "65cf205e7303cff5ce4785a64fadc6b29ba8b85e31913e001330fb084e502ff1",
"quantcortex/risk/factor_exposure.py": "5503426c590338b57512adf409e873751929464459d464f2b6940db8cadbf0ad",
Expand Down Expand Up @@ -128,7 +130,7 @@
"pandas": "3.0.3",
"scipy": "1.17.1",
"scikit-learn": "1.9.0",
"matplotlib": "3.10.9",
"matplotlib": "3.11.0",
"threadpoolctl": "3.6.0",
"yfinance": "1.4.1"
}
Expand Down Expand Up @@ -231,15 +233,15 @@
"exposure_matched_equal_weight_cash_excess_sharpe_gross": 0.7984966497852871
},
"artifacts": {
"allocation_and_exposure.png": "4f88060765153f436a0fb54bbd7399a9a82117acc84497bee7495b6398ba72cc",
"drawdown.png": "5a4f8e7c4f8a5a1fa3f18b9916f47015582323d66697344216846f8992dc10f2",
"equity_vs_benchmarks.png": "d94d2afc0502a6b061324637bf80312f5ff243384471c06d00f16bfcfe770350",
"monthly_returns.png": "abcb5de3ba5cbb9acf2caf5996564547d8398841b23f4edd2ae2834b3d9d61ad",
"performance_attribution.png": "ab1113f4645d2a7e70eb7bbf4ee432e76430a3d3fbf3d06189114fe62127bb30",
"report_overview.png": "18f4548523b2ed6bfb520c7b5cdc764641b93f9e87d3f4e544ad8a47bc02e892",
"return_distribution.png": "7c40d473e63c8b5a54e8aba7ac8c048e1fe77a9d741020d58281315970dc3fb5",
"rolling_risk.png": "e8a97664c425f341d340e590f290e5464be679cc9294f58fb23eace0dde4bd36",
"rolling_sharpe.png": "a1b4fa535aa12185763fd7ef8f6b77e5b83644a02b6f945474f53ca9fa4d2ff0",
"turnover_and_costs.png": "a405e4b8231b8183c2e66c652afb8208fd60c0a092fe7cb6a91e2f97d79c7f57"
"allocation_and_exposure.png": "e310e33a2fe36793eb1724e09cd7132de9cee64e171005b12dc1dce674c84d7a",
"drawdown.png": "277868c7b4b59fe5bddf29005e8707d028ee97440c7f23c96ecf83142da1ea1f",
"equity_vs_benchmarks.png": "61794487a4649c4747a05c6c3990b176668c8205ccbe957923875a41eb089d15",
"monthly_returns.png": "18d04ab0f2a16ecd48780cddb4849c5c034a3093262c88b48d173801580ca9bc",
"performance_attribution.png": "ef13a1714481f52712e0038eb025d10a30ce0ff1031296355d2ab7165e362f20",
"report_overview.png": "f06aa32a4c2b51c9b32a0513caeea4edca16429f222938254f068241af5330ea",
"return_distribution.png": "6cfa64dfeb0051478e85264db720ed1121c05bf00ebed5931a827e0a856b8ecf",
"rolling_risk.png": "257b9a1a1706a8d52b3bdb707a3149b1c60b4f779fa530950b80acec3ef10f8b",
"rolling_sharpe.png": "8dbbabb64f9e049155f9e5cfd3fed083eb2e71a3662b5092c0847e26418ade89",
"turnover_and_costs.png": "f4034abbaacb2a04c852f2cf4f36d0794a9e048490ca96f4e1eb2b80215836d2"
}
}
Binary file modified docs/img/report_overview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/return_distribution.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/rolling_risk.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/rolling_sharpe.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/turnover_and_costs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 19 additions & 2 deletions local_data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ outside the CSV.

## Wide Adjusted-Close CSV

`scripts/generate_report.py`, `scripts/run_paper_experiments.py`, and all
research notebooks accept a date-by-symbol matrix:
`scripts/generate_report.py`, `scripts/run_paper_experiments.py`,
`scripts/run_expansion_experiments.py`, and all research notebooks accept a
date-by-symbol matrix:

```csv
date,QQQ,VGT,GLD,TLT,SPY,VIG,SHV
Expand Down Expand Up @@ -42,6 +43,22 @@ record the owner's provenance assertions but do not independently establish
that redistribution is permitted. Pass `--manifest-out` as well so the input,
source tree, settings, and generated artifacts are hash-bound.

The expansion uses two separate complete matrices plus metadata sidecars under
`local_data/expansion/`:

- `us_sector_etfs.csv`: `date`, XLB, XLE, XLF, XLI, XLK, XLP, XLU, XLV, XLY,
and SHV.
- `country_equity_etfs.csv`: `date`, EWA, EWC, EWG, EWH, EWJ, EWL, EWP, EWQ,
EWS, EWU, and SHV.

Each `.metadata.json` records the exact request, provider version, retrieval
timestamp, protocol digest, row coverage, missingness, and CSV SHA-256. The
frozen expansion requires complete rows from 2014-01-02 through 2025-12-31,
performs no forward fill, and rejects a missing evaluation month or hash
mismatch. `scripts/fetch_expansion_data.py` can create these files through the
explicit provider adapter; using it does not establish permission to publish or
redistribute the observations.

## Single-Symbol OHLCV CSV

Notebook 02 also requires actual OHLCV data when using local files:
Expand Down
Loading