permutalpha 0.9.1__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.
- permutalpha-0.9.1/CHANGELOG.md +180 -0
- permutalpha-0.9.1/LICENSE +21 -0
- permutalpha-0.9.1/MANIFEST.in +7 -0
- permutalpha-0.9.1/NOTICE.md +9 -0
- permutalpha-0.9.1/PKG-INFO +187 -0
- permutalpha-0.9.1/README.md +147 -0
- permutalpha-0.9.1/demo/check_parity.py +94 -0
- permutalpha-0.9.1/deploy/README.md +22 -0
- permutalpha-0.9.1/deploy/oql-collect.service +15 -0
- permutalpha-0.9.1/deploy/oql-collect.timer +9 -0
- permutalpha-0.9.1/deploy/oql-paper.service +14 -0
- permutalpha-0.9.1/deploy/oql-paper.timer +9 -0
- permutalpha-0.9.1/docs/AGENTS.md +75 -0
- permutalpha-0.9.1/docs/CALIBRATION.md +87 -0
- permutalpha-0.9.1/docs/DEVELOPING.md +83 -0
- permutalpha-0.9.1/docs/EFFICIENCY.md +87 -0
- permutalpha-0.9.1/docs/block_results.json +1 -0
- permutalpha-0.9.1/docs/calibration_results.json +1 -0
- permutalpha-0.9.1/docs/large_search_results.json +1 -0
- permutalpha-0.9.1/docs/power_results.json +1 -0
- permutalpha-0.9.1/examples/demo_lab.py +48 -0
- permutalpha-0.9.1/examples/quickstart.py +51 -0
- permutalpha-0.9.1/oql/__init__.py +2 -0
- permutalpha-0.9.1/oql/__main__.py +4 -0
- permutalpha-0.9.1/oql/agent_tools.py +495 -0
- permutalpha-0.9.1/oql/board.py +504 -0
- permutalpha-0.9.1/oql/calibration.py +135 -0
- permutalpha-0.9.1/oql/catalog.py +259 -0
- permutalpha-0.9.1/oql/cli.py +299 -0
- permutalpha-0.9.1/oql/collect.py +273 -0
- permutalpha-0.9.1/oql/demo.py +45 -0
- permutalpha-0.9.1/oql/efficiency.py +666 -0
- permutalpha-0.9.1/oql/engine.py +118 -0
- permutalpha-0.9.1/oql/experiment.py +133 -0
- permutalpha-0.9.1/oql/gate.py +129 -0
- permutalpha-0.9.1/oql/gates.py +122 -0
- permutalpha-0.9.1/oql/ledger.py +102 -0
- permutalpha-0.9.1/oql/live.py +156 -0
- permutalpha-0.9.1/oql/locks.py +87 -0
- permutalpha-0.9.1/oql/market.py +208 -0
- permutalpha-0.9.1/oql/mcp_server.py +79 -0
- permutalpha-0.9.1/oql/paper.py +294 -0
- permutalpha-0.9.1/oql/permute.py +120 -0
- permutalpha-0.9.1/oql/projects/__init__.py +62 -0
- permutalpha-0.9.1/oql/projects/_util.py +156 -0
- permutalpha-0.9.1/oql/projects/hawkes.py +70 -0
- permutalpha-0.9.1/oql/projects/p01_tail_index.py +82 -0
- permutalpha-0.9.1/oql/projects/p02_intraday_seasonality.py +81 -0
- permutalpha-0.9.1/oql/projects/p03_overfitting_detector.py +84 -0
- permutalpha-0.9.1/oql/projects/p04_momentum_regimes.py +81 -0
- permutalpha-0.9.1/oql/projects/p05_factor_neutrality.py +85 -0
- permutalpha-0.9.1/oql/projects/p06_american_put.py +116 -0
- permutalpha-0.9.1/oql/projects/p07_autodiff_greeks.py +118 -0
- permutalpha-0.9.1/oql/projects/p08_implied_distribution.py +123 -0
- permutalpha-0.9.1/oql/projects/p09_hawkes_trades.py +76 -0
- permutalpha-0.9.1/oql/projects/p10_news_diffusion.py +170 -0
- permutalpha-0.9.1/oql/projects/p11_large_search.py +99 -0
- permutalpha-0.9.1/oql/search.py +116 -0
- permutalpha-0.9.1/oql/server.py +272 -0
- permutalpha-0.9.1/oql/sources.py +340 -0
- permutalpha-0.9.1/oql/stats.py +103 -0
- permutalpha-0.9.1/oql/strategies.py +97 -0
- permutalpha-0.9.1/oql/synthetic.py +39 -0
- permutalpha-0.9.1/oql/web/index.html +393 -0
- permutalpha-0.9.1/oql/web/live.js +352 -0
- permutalpha-0.9.1/permutalpha.egg-info/PKG-INFO +187 -0
- permutalpha-0.9.1/permutalpha.egg-info/SOURCES.txt +77 -0
- permutalpha-0.9.1/permutalpha.egg-info/dependency_links.txt +1 -0
- permutalpha-0.9.1/permutalpha.egg-info/entry_points.txt +3 -0
- permutalpha-0.9.1/permutalpha.egg-info/requires.txt +14 -0
- permutalpha-0.9.1/permutalpha.egg-info/top_level.txt +1 -0
- permutalpha-0.9.1/pyproject.toml +53 -0
- permutalpha-0.9.1/requirements.txt +4 -0
- permutalpha-0.9.1/setup.cfg +4 -0
- permutalpha-0.9.1/tests/test_block.py +57 -0
- permutalpha-0.9.1/tests/test_efficiency.py +261 -0
- permutalpha-0.9.1/tests/test_lab.py +524 -0
- permutalpha-0.9.1/tests/test_nulls.py +152 -0
- permutalpha-0.9.1/tests/test_robust.py +233 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Changes that can alter what a test measures are marked **(affects results)**. A frozen card records the lab
|
|
4
|
+
version it was frozen with, and its gate report shows both versions if they differ.
|
|
5
|
+
|
|
6
|
+
## 0.9.1
|
|
7
|
+
- Published on PyPI as **permutalpha** (`pip install permutalpha`; the import name and the `oql` command are
|
|
8
|
+
unchanged, and `permutalpha` works as a command too). Extras: `[trees]`, `[paper]`, `[all]`.
|
|
9
|
+
- `oql demo [DIR]`: a ready lab on synthetic markets with two frozen cards, so a fresh install shows a PASS and a
|
|
10
|
+
FAIL in minutes.
|
|
11
|
+
|
|
12
|
+
## 0.9.0: bulletproofing
|
|
13
|
+
- **(affects results)** No position without a trustworthy volatility estimate. A flat or stale stretch (half of
|
|
14
|
+
the last 20 moves exactly zero: a pegged currency, a frozen feed) had a tiny measured volatility, and dividing by it
|
|
15
|
+
put the market at the 10x leverage cap. Such bars now get no position; normal markets are unaffected.
|
|
16
|
+
- **Frozen data means the data at the freeze.** The freeze records each dataset's last timestamp and a fingerprint
|
|
17
|
+
of its rows up to then. Gate and holdout read only those rows, so the daily collector appending new data no longer
|
|
18
|
+
blocks a frozen card, while any change to an existing row (a vendor revision, an edit) is still refused. Cards
|
|
19
|
+
frozen before 0.9 keep the old whole-file check.
|
|
20
|
+
- **Tests that cannot work are refused at the freeze:** n_perm too small to reach p < alpha, alpha above 0.2,
|
|
21
|
+
negative costs, a development share outside 30-95%, a fill delay outside [0, 1), unknown rules or gates, a
|
|
22
|
+
dataset listed twice, an experiment.py that does not load.
|
|
23
|
+
- **Tamper-evident ledger.** Every row carries a hash chained to the row before; `oql ledger verify` reports any
|
|
24
|
+
edited, removed or reordered row, and `oql ledger head` prints the latest hash to publish (e.g. in a commit
|
|
25
|
+
message). An existing ledger is sealed as it stands the first time a row is added.
|
|
26
|
+
- **Safe with several processes.** Board changes happen under a lab lock; a gate or holdout records its result on a
|
|
27
|
+
fresh copy of the board, so cards created or edited while a long gate ran are no longer overwritten; two gate
|
|
28
|
+
runs of the same card cannot overlap; ledger appends cannot fork the chain.
|
|
29
|
+
- New test suite `tests/test_robust.py`: no look-ahead across every rule, side and gate setting; engine invariants on
|
|
30
|
+
messy markets (gaps, frozen feeds, fat tails); costs only ever reduce returns; the gate is deterministic across
|
|
31
|
+
process counts; frozen-data and validation behaviour; ledger tampering; concurrency.
|
|
32
|
+
- Continuous integration (`.github/workflows/tests.yml`): the full suite on Python 3.10 with pandas 2 and Python
|
|
33
|
+
3.12 with pandas 3, on every push.
|
|
34
|
+
- Removed deprecated `Timestamp.utcnow` calls (gone in a future pandas); live volatility ignores zero prices.
|
|
35
|
+
|
|
36
|
+
## 0.8.0
|
|
37
|
+
- **Third null model: block bootstrap** (`nulls=["block"]`). The history is cut into 20-bar blocks (random grid
|
|
38
|
+
offset) and the blocks are shuffled, one order for all markets: volatility clustering, short-term persistence and
|
|
39
|
+
cross-market co-movement survive inside each block; longer patterns are broken.
|
|
40
|
+
- Calibration (docs/CALIBRATION.md): false alarms 3% and 2% on no-edge markets; it catches 88% of planted trend
|
|
41
|
+
edges against 96-98% for the other two nulls, because 20-bar blocks keep part of each ~67-bar trend. It is the
|
|
42
|
+
strictest test for trend strategies and only credits structure longer than a block.
|
|
43
|
+
|
|
44
|
+
## 0.7.1
|
|
45
|
+
- **Holdout power analysis.** A holdout FAIL only means something if the holdout could have seen the edge. Every
|
|
46
|
+
holdout now writes `holdout.md` with: the Sharpe's 95% interval, the bar it had to beat, the smallest true Sharpe
|
|
47
|
+
it detects 80% of the time, the chance it would have passed if the edge were as strong as in development, and a
|
|
48
|
+
test of whether the edge shrank. `oql card holdout-power ID` writes the same report for a holdout already run
|
|
49
|
+
(it recomputes the shuffles for the frozen finalist; the recorded verdict, ledger and stage are unchanged).
|
|
50
|
+
|
|
51
|
+
## 0.7.0
|
|
52
|
+
- **Project 11, large search** (Projects tab): the lab's search loop at growing sizes, up to about 3,000 distinct
|
|
53
|
+
strategies from dense grids, on a synthetic book with a known truth. For each size it compares a naive t-test of
|
|
54
|
+
the winner, the Deflated Sharpe Ratio, and the gate. On a no-edge book the naive test calls a ~700-strategy winner
|
|
55
|
+
significant (p 0.03) while the gate does not (p 0.55); on a planted edge the gate passes at every size.
|
|
56
|
+
- Power study (docs/CALIBRATION.md): with about 11 years of data, edges whose best strategy shows a Sharpe near 0.4
|
|
57
|
+
are caught 8-15% of the time; edges near Sharpe 1 over decades pass reliably.
|
|
58
|
+
- Calibration can run the large-search space (`--kinds big1000-noise`).
|
|
59
|
+
|
|
60
|
+
## 0.6.2
|
|
61
|
+
- `oql data pull-long-history-excess` **(fixes a data flaw found by card 0003)**: the long histories as returns a
|
|
62
|
+
financed position actually earns, under `fred-xs/`. Treasuries earn yield minus the 3-month T-bill rate (the
|
|
63
|
+
0.6.1 bond indexes credited the full yield, so a leveraged low-volatility bond looked like a riskless trend);
|
|
64
|
+
currencies earn the spot move plus the interest-rate difference (OECD 3-month rates, used one month late), and
|
|
65
|
+
start when that rate is known. Oil is left out: its tradable futures return cannot be built from the spot price.
|
|
66
|
+
The 0.6.1 `fred-bars/` datasets are kept unchanged, because card 0003 was frozen on them.
|
|
67
|
+
|
|
68
|
+
## 0.6.1
|
|
69
|
+
- `oql data pull-long-history`: free FRED daily series turned into tradable bars under `fred-bars/`: 12 currencies
|
|
70
|
+
(from 1971, as the foreign currency's price in dollars), constant-maturity Treasuries as total-return indexes
|
|
71
|
+
(from 1962; -duration x yield change + carry) and WTI oil (from 1986). Close-only, so open = previous close.
|
|
72
|
+
Decades of history give tests the statistical power that 2010-onward data cannot.
|
|
73
|
+
- Calibration can run power studies on weaker planted trends (`--kinds drift0.0001,...`).
|
|
74
|
+
|
|
75
|
+
## 0.6.0
|
|
76
|
+
- **Second null model** (`Experiment(nulls=["bars", "vol_matched"])`; `write_experiment(nulls=...)`). The
|
|
77
|
+
volatility-matched null divides each bar by the market's volatility at its time, shuffles the standardized bars,
|
|
78
|
+
and multiplies each by the volatility of the slot it lands in: calm periods stay calm and crises stay at their
|
|
79
|
+
dates, and only the order of the moves is destroyed. With several nulls declared, the gate and the holdout PASS
|
|
80
|
+
only if p < alpha under every one; the report shows each. Default stays `["bars"]`, so existing cards are unchanged.
|
|
81
|
+
- **Calibration study** (`python -m oql.calibration`, docs/CALIBRATION.md): 300 full gates on synthetic books with a
|
|
82
|
+
known truth. Both nulls keep false positives at or below 5% (3-4%; 1% under strong volatility clustering) and pass
|
|
83
|
+
96-98% of real edges. Under strong clustering the bar shuffle is too strict (p-values pile up near 1); the
|
|
84
|
+
volatility-matched null is better calibrated there.
|
|
85
|
+
|
|
86
|
+
## 0.5.2
|
|
87
|
+
- **Rebalance band** (opt-in, `Experiment(rebalance_band=0.25)`; `write_experiment(rebalance_band=...)` for the
|
|
88
|
+
assistant; "Resizing" in the gate check). A position keeps its size until the volatility-based target has moved more
|
|
89
|
+
than the band away, then jumps to the target, so a strategy stops paying to resize every bar while staying within
|
|
90
|
+
the band of its risk target. Paper trading puts the catalog's history in front of the live bars so its sizes match
|
|
91
|
+
the backtest's. On synthetic hourly data a 25% band cut the cost bill of a slow rule (250-hour momentum) by about
|
|
92
|
+
30% and of a fast one (20-hour) by about 8%: for fast rules most of the cost is direction changes, not resizing.
|
|
93
|
+
Experiments without it are unchanged.
|
|
94
|
+
|
|
95
|
+
## 0.5.1
|
|
96
|
+
- The gate report counts efficiency studies and gate checks on the card's datasets made before its freeze
|
|
97
|
+
("Efficiency-lab explorations on these datasets before the freeze"). They shape which ideas get proposed, so they
|
|
98
|
+
belong next to the result. Recorded at the freeze; cards frozen earlier say "not recorded".
|
|
99
|
+
- A project whose data is not in the catalog says what is missing and how to add it, instead of failing.
|
|
100
|
+
- `oql serve` on a port already in use says so (it was reported as a network error).
|
|
101
|
+
- No more "All-NaN slice" warning when a feature has no values yet early in a study.
|
|
102
|
+
|
|
103
|
+
## 0.5.0
|
|
104
|
+
- **Efficiency lab** (`oql/efficiency.py`, `oql efficiency study`, the dashboard's Efficiency tab, the assistant's
|
|
105
|
+
`efficiency_study` tool). Is the next day's (hourly bars) or hour's (minute bars) efficiency ratio predictable?
|
|
106
|
+
Walk-forward ridge (or boosted trees) on development data only, from price features plus optional calendar,
|
|
107
|
+
funding, perp-spot basis, VIX and yield slope, CFTC positioning and Pi order-book groups, all joined as of the
|
|
108
|
+
period start. The order-book data from the micro study's lock date on stays sealed. Each run first checks itself on
|
|
109
|
+
a synthetic market with planted efficiency regimes and on a random walk, and is counted in the ledger.
|
|
110
|
+
- **Efficiency gates in the search** (`oql/gates.py`). An experiment can declare `gates=["none", "er_trailing",
|
|
111
|
+
"er_forecast"]`; the search may then switch any strategy on only in the top (or bottom) third or half of trailing
|
|
112
|
+
efficiency or of the efficiency forecast. Gates are computed from the bars inside the search, so the gate test
|
|
113
|
+
reruns them on every shuffled copy. Switching pays costs. Paper trading computes the gate the same way, with the
|
|
114
|
+
catalog's history in front of the live journal. Experiments without `gates` are unchanged.
|
|
115
|
+
- **Gate check** (`oql efficiency gates`, the Efficiency tab): all 21 gate settings on one strategy, P&L by forecast
|
|
116
|
+
third, and a simulation of how strong a forecast would need to be. Counted in the ledger as 21 explorations.
|
|
117
|
+
- New rule `orb` (opening-range breakout on intraday bars), available by name; not in the default search.
|
|
118
|
+
- Assistant tools: `explore` and `permutation_check` take an optional gate; `write_experiment` takes `gates` and
|
|
119
|
+
`gate_features` and counts gate settings in the search size; new `efficiency_study`.
|
|
120
|
+
- Ledger counts (command line, dashboard, assistant) add up the settings a row stands for, so a gate check counts 21.
|
|
121
|
+
- Charts: ranked horizontal bars for long category names.
|
|
122
|
+
|
|
123
|
+
## 0.4.0
|
|
124
|
+
- **Live dashboard.** `oql serve` can run any computation in the background and stream its results to the page as they
|
|
125
|
+
arrive (`oql/live.py`, Server-Sent Events); charts redraw as the work happens, with hover readouts and a validated
|
|
126
|
+
colour palette for light and dark mode (`oql/web/live.js`).
|
|
127
|
+
- **Projects tab.** The ten quant mini-projects (tail index, intraday seasonality, overfitting detector, momentum
|
|
128
|
+
crashes, factor neutrality, American put, autodiff Greeks, implied distribution, Hawkes trades, news diffusion) run
|
|
129
|
+
live on the lab's catalog data (`oql/projects/`). Each runs its known-answer checks first and shows them passing or
|
|
130
|
+
failing; the four projects with published real-data results reproduce them.
|
|
131
|
+
- **Live market tab.** Public exchange data (Kraken, Coinbase, Binance.US; no account) polled by the server: price,
|
|
132
|
+
the rolling one-hour efficiency ratio, realized volatility and the bid-ask spread, updating on their own
|
|
133
|
+
(`oql/market.py`).
|
|
134
|
+
- New data commands: `oql data pull-french` (Fama-French factor tables) and `oql data import-projects DIR` (the
|
|
135
|
+
projects' SPY option chain, licensed and kept local, and a day of Binance.US trades).
|
|
136
|
+
- The ledger tab counts tests (gate and holdout runs) separately from explorations.
|
|
137
|
+
- Packaging includes the `oql.projects` package and the page script, so a regular `pip install` works.
|
|
138
|
+
|
|
139
|
+
## 0.3.4
|
|
140
|
+
Found in the first dry run with an AI assistant connected over MCP:
|
|
141
|
+
- `write_experiment` and `explore` now say that every strategy trades all of an experiment's datasets together as one
|
|
142
|
+
equal-risk portfolio. The assistant had counted 4 lookbacks on 2 coins as 8 strategies.
|
|
143
|
+
- Editing a card after asking for review marks the review summary as out of date, on the card and on the dashboard,
|
|
144
|
+
until the assistant sends a fresh one.
|
|
145
|
+
- The gate report explains a result worse than every shuffled run: the signal pointed the wrong way more often than
|
|
146
|
+
chance, and testing the opposite idea would be a new card and a new counted test.
|
|
147
|
+
|
|
148
|
+
## 0.3.3
|
|
149
|
+
- `oql data check` compares prices with a relative tolerance. Prices stored as decimals round slightly, and at large
|
|
150
|
+
levels (Nikkei futures in the tens of thousands) that rounding was being reported as broken bars.
|
|
151
|
+
- Large one-bar moves are split in two: spikes that reverse on the next bar (the mark of a bad price) and moves that
|
|
152
|
+
stick (real events, or an unadjusted futures roll). Each warning names a date to look at, as does the gap warning.
|
|
153
|
+
This does not change any test result.
|
|
154
|
+
|
|
155
|
+
## 0.3.2
|
|
156
|
+
- **(affects results)** A trade is now a change of direction (enter, exit or flip). Positions are resized every
|
|
157
|
+
bar to hold volatility steady; those resizes are still charged as costs, but they were also being counted as
|
|
158
|
+
trades, so every strategy "traded" every bar and the minimum-trades rule never rejected anything. The minimum
|
|
159
|
+
is now 1 direction change per year per market (`min_trades_per_year=1.0`): it rejects strategies that almost
|
|
160
|
+
never change position, and keeps slow trend systems such as 12-month momentum on daily data.
|
|
161
|
+
- Exploration (`explore`, `permutation_check`) now uses the costs and fill delay declared in the card's
|
|
162
|
+
`experiment.py`, so an AI assistant sees what the gate will see. Results report `cost_bps` and
|
|
163
|
+
`direction_changes_per_year`.
|
|
164
|
+
- `oql card freeze` records the lab version; the gate report shows the version at the freeze and at the gate.
|
|
165
|
+
- `oql ledger` separates tests (gate, holdout) from explorations in its summary.
|
|
166
|
+
- `oql data check` warns about bars that are not on the dataset's time grid (found in real Binance data: 43 hourly
|
|
167
|
+
bars after the February 2018 outage opened 28 minutes past the hour).
|
|
168
|
+
- The code repository ignores lab state (`cards/`, `board.json`, `LEDGER.csv`): run a lab in its own folder.
|
|
169
|
+
- `demo/check_parity.py` checks that the live demo page computes the same numbers as this code.
|
|
170
|
+
|
|
171
|
+
## 0.3.1
|
|
172
|
+
- Binance futures files start with a header row; the parser now reads them, and number columns stored as text
|
|
173
|
+
are converted before saving.
|
|
174
|
+
|
|
175
|
+
## 0.3.0
|
|
176
|
+
- Phase 5: `oql mcp`, an MCP server for AI research assistants. Every exploration is counted and reported in the
|
|
177
|
+
gate report.
|
|
178
|
+
|
|
179
|
+
## 0.2.0
|
|
180
|
+
- Data catalog, validation gate, research board, dashboard (`oql serve`), collector, paper trading.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 David DeConti
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Credits
|
|
2
|
+
|
|
3
|
+
- **Bar permutation** (`oql/permute.py`, `permute_ohlc`) is adapted from
|
|
4
|
+
[neurotrader888/mcpt](https://github.com/neurotrader888/mcpt) `bar_permute.py`, MIT License, (c) 2025 neurotrader888,
|
|
5
|
+
by way of the author's earlier project mcpt-lab.
|
|
6
|
+
- **Deflated Sharpe ratio**: Bailey, D. H. and López de Prado, M. (2014), "The Deflated Sharpe Ratio".
|
|
7
|
+
- **Pipeline shape**: inspired by QuantConnect's Research Pipeline. No QuantConnect code is used.
|
|
8
|
+
- Data from FRED (Federal Reserve Bank of St. Louis), Binance public data, the U.S. Bureau of Labor Statistics and the
|
|
9
|
+
Federal Reserve are public. Databento data is licensed and is never included in this repository.
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: permutalpha
|
|
3
|
+
Version: 0.9.1
|
|
4
|
+
Summary: A trading-research pipeline where every result must beat the same search on shuffled markets: pre-registration, permutation gates, one-shot holdouts, a tamper-evident ledger, and an AI assistant that can explore but never test
|
|
5
|
+
Author: David DeConti
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/dnd8639-byte/permutalpha-quant
|
|
8
|
+
Project-URL: Source, https://github.com/dnd8639-byte/permutalpha-quant/tree/main/lab
|
|
9
|
+
Project-URL: Documentation, https://github.com/dnd8639-byte/permutalpha-quant/tree/main/lab/docs
|
|
10
|
+
Project-URL: Changelog, https://github.com/dnd8639-byte/permutalpha-quant/blob/main/lab/CHANGELOG.md
|
|
11
|
+
Project-URL: Live demo, https://dnd8639-byte.github.io/open-quant-lab/
|
|
12
|
+
Keywords: quantitative finance,backtesting,permutation test,overfitting,pre-registration,trading,research,mcp,ai agents
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
License-File: NOTICE.md
|
|
28
|
+
Requires-Dist: numpy>=1.24
|
|
29
|
+
Requires-Dist: pandas>=2.0
|
|
30
|
+
Requires-Dist: pyarrow>=12
|
|
31
|
+
Requires-Dist: certifi
|
|
32
|
+
Provides-Extra: trees
|
|
33
|
+
Requires-Dist: scikit-learn>=1.2; extra == "trees"
|
|
34
|
+
Provides-Extra: paper
|
|
35
|
+
Requires-Dist: ccxt>=4; extra == "paper"
|
|
36
|
+
Provides-Extra: all
|
|
37
|
+
Requires-Dist: scikit-learn>=1.2; extra == "all"
|
|
38
|
+
Requires-Dist: ccxt>=4; extra == "all"
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
# permutalpha (Open Quant Lab)
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install permutalpha
|
|
45
|
+
oql demo && OQL_LAB=oql-demo OQL_CATALOG=oql-demo/catalog oql serve
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
A fully open research pipeline for trading strategies: a data catalog, a backtest engine with costs and delays, and a validation gate that the strategy has to pass before anything else happens. The rules of every test are enforced by code, not by good intentions.
|
|
49
|
+
|
|
50
|
+
Designed and directed by David DeConti, with much of the code written with an AI assistant (Claude). MIT licence. Inspired by the shape of QuantConnect's research pipeline (Ideas → Research → Backtest → Paper → Live), rebuilt so that no part of it is paid, and so that a strategy cannot be promoted by trying things until one looks good.
|
|
51
|
+
|
|
52
|
+
**Live demo:** the validation gate runs in your browser at [dnd8639-byte.github.io/open-quant-lab](https://dnd8639-byte.github.io/open-quant-lab/).
|
|
53
|
+
It is a JavaScript port of the engine, rules and search; `python demo/check_parity.py` confirms that it computes the same
|
|
54
|
+
numbers as this code.
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
idea ──> research ──> preregistered ──> gate ──> holdout ──> paper
|
|
58
|
+
explore freely rules fingerprinted whole-search one-shot Raspberry Pi
|
|
59
|
+
(SHA-256) permutation test (locked) paper trader
|
|
60
|
+
FAIL ─> archive FAIL ─> archive
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## What makes it different
|
|
64
|
+
|
|
65
|
+
| Rule | How the code enforces it |
|
|
66
|
+
|---|---|
|
|
67
|
+
| Decide the test before seeing the result | `oql card freeze` fingerprints `PREREGISTRATION.md`, `experiment.py` and every dataset (SHA-256). The gate and the holdout refuse to run if any of them changed. |
|
|
68
|
+
| Judge the best of many tries as the best of many tries | The gate reruns the **entire search**, every round, on shuffled copies of the data. p = how often luck alone finds something as good. |
|
|
69
|
+
| Count every attempt | Every gate and holdout run goes into `LEDGER.csv`, pass or fail. Changing a tested idea means `oql card revise`: a new card in the same family, and the family's trial count keeps adding up. |
|
|
70
|
+
| Look at the holdout once | `oql card holdout` writes its lock file before it computes anything. A second run is refused, even if someone edits `board.json`. |
|
|
71
|
+
| No skipping | Cards move one stage at a time; a failed gate or holdout sends the card to the archive. |
|
|
72
|
+
| Licensed data never leaks | Every dataset carries a licence tag (`public`, `own`, `licensed`); the whole catalog is git-ignored. |
|
|
73
|
+
|
|
74
|
+
The lab checks itself: on fake markets with a planted, real edge the gate passes (p = 0.025, the smallest possible with 39 permutations, in 5 of 5 draws); on pure noise it fails (p between 0.30 and 0.85 in 5 of 5 draws). Run `python examples/quickstart.py` to watch both happen.
|
|
75
|
+
|
|
76
|
+
## Install
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pip install permutalpha # numpy, pandas, pyarrow
|
|
80
|
+
pip install "permutalpha[all]" # + scikit-learn (tree forecasts) and ccxt (live paper trading)
|
|
81
|
+
oql demo # a lab on synthetic markets, two cards frozen and ready for their gate
|
|
82
|
+
OQL_LAB=oql-demo OQL_CATALOG=oql-demo/catalog oql serve
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Run both gates from the Research board: the planted edge passes and the pure noise fails. From source:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
git clone https://github.com/dnd8639-byte/permutalpha-quant && cd permutalpha-quant/lab
|
|
89
|
+
pip install -e . && python -m unittest discover tests
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## An AI research assistant that cannot cheat
|
|
93
|
+
|
|
94
|
+
`oql mcp` serves the lab to any Model Context Protocol client (Claude Desktop, Claude Code, or a local model). The
|
|
95
|
+
assistant can read the board and data, propose ideas, write pre-registrations and experiments from validated fields
|
|
96
|
+
(never code), explore development data and run efficiency studies. It cannot freeze a card, run the gate or the
|
|
97
|
+
holdout, or deploy: those stay with a person. Every exploration it makes is logged and printed next to the final
|
|
98
|
+
result. Setup: [docs/AGENTS.md](https://github.com/dnd8639-byte/permutalpha-quant/blob/main/lab/docs/AGENTS.md).
|
|
99
|
+
|
|
100
|
+
## Use
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
oql data pull-fred DGS10 CPIAUCSL # free, no key
|
|
104
|
+
oql data pull-binance BTCUSDT --interval 1h --start 2018-01
|
|
105
|
+
oql data import-databento ../state/v3/contracts --roots ES,CL,GC # licensed: stays local
|
|
106
|
+
oql data pull-french # Fama-French factors, for the projects
|
|
107
|
+
oql data import-projects ../quant-projects/data # the projects' option chain (licensed) and trades
|
|
108
|
+
oql data list
|
|
109
|
+
oql data check
|
|
110
|
+
|
|
111
|
+
oql card new "Time-series momentum on CME futures" --mechanism "Slow-moving capital and hedging demand make trends persist."
|
|
112
|
+
# edit cards/0001-.../PREREGISTRATION.md and experiment.py
|
|
113
|
+
oql card start 1
|
|
114
|
+
oql card freeze 1 # then commit and push: the commit time proves the rules came first
|
|
115
|
+
oql card gate 1 # search + whole-search permutation test -> cards/0001-.../gate.md
|
|
116
|
+
oql card holdout 1 # one shot
|
|
117
|
+
oql board --html board.html
|
|
118
|
+
oql ledger
|
|
119
|
+
oql serve # the dashboard: live gate runs, the permutation lab, data, ledger
|
|
120
|
+
oql efficiency study binance/BTCUSDT/1h --groups funding,basis,macro # is efficiency predictable? (dev data, logged)
|
|
121
|
+
oql efficiency gates binance/BTCUSDT/1h "momentum lookback=20" # does an efficiency gate help this strategy?
|
|
122
|
+
oql paper deploy 1 --feed binance/BTCUSDT/1h=binanceus:BTC/USDT:1h # after a holdout PASS
|
|
123
|
+
oql collect init && oql collect run # keep free data current (Pi)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## The dashboard
|
|
127
|
+
|
|
128
|
+
`oql serve` opens a local web app (nothing leaves your machine):
|
|
129
|
+
|
|
130
|
+
- **Research board**: every card by stage. Run a preregistered card's gate from the page and watch the shuffled
|
|
131
|
+
reruns arrive one by one, the null histogram fill in, and the p-value settle.
|
|
132
|
+
- **Permutation lab**: pick a market and a strategy; the lab shuffles the market in front of you and builds the
|
|
133
|
+
distribution of luck one permutation at a time. Switch to "best of the whole search" to see selection bias.
|
|
134
|
+
Uses only the first 70% of each dataset, so it never touches a holdout.
|
|
135
|
+
- **Data** and **Ledger**: the catalog with quality checks, and every test ever run.
|
|
136
|
+
- **Projects**: ten quant mini-projects (tail risk, seasonality, overfitting, momentum crashes, factor neutrality,
|
|
137
|
+
American options, autodiff Greeks, implied distributions, Hawkes processes, news diffusion) running live on the
|
|
138
|
+
catalog's data. Each runs its known-answer checks first; charts fill in as the work happens.
|
|
139
|
+
- **Live market**: price, the rolling one-hour efficiency ratio, volatility and the spread from public exchange data
|
|
140
|
+
(Kraken, Coinbase, Binance.US), updating every few seconds. No account or key.
|
|
141
|
+
- **Efficiency**: can the next day's (or hour's) efficiency be forecast from price, calendar, funding, basis, macro,
|
|
142
|
+
positioning and order-book data, walk-forward on development data? And does switching a strategy on and off by
|
|
143
|
+
efficiency help it, and how strong would the forecast need to be? Every run checks itself on synthetic markets
|
|
144
|
+
first and is counted in the ledger. Gates found here are tested for real by declaring them in a card's experiment
|
|
145
|
+
(`gates=[...]`), where the gate test reruns them on shuffled data. See [docs/EFFICIENCY.md](https://github.com/dnd8639-byte/permutalpha-quant/blob/main/lab/docs/EFFICIENCY.md).
|
|
146
|
+
|
|
147
|
+
Holdouts are deliberately not runnable from the page: they are one-shot, so they need a typed command.
|
|
148
|
+
|
|
149
|
+
## Layout
|
|
150
|
+
|
|
151
|
+
| Path | What it is |
|
|
152
|
+
|---|---|
|
|
153
|
+
| `oql/catalog.py` | Parquet catalog with metadata, licence tags, SHA-256 and quality checks |
|
|
154
|
+
| `oql/sources.py` | FRED, Binance public files, CSV, release calendar, Pi order-book features, Databento front contracts (roll-safe) |
|
|
155
|
+
| `oql/engine.py` | Bar engine: decisions at the close, fills a fraction into the next bar, costs per change, equal-risk sizing |
|
|
156
|
+
| `oql/strategies.py` | Rule library (breakout, moving-average cross, momentum, reversal, opening-range breakout); add your own per experiment |
|
|
157
|
+
| `oql/gates.py` | Efficiency gates a search can add to any strategy (trailing efficiency, or the efficiency forecast) |
|
|
158
|
+
| `oql/efficiency.py` | The efficiency lab: targets, look-ahead-free features, walk-forward forecasts, gate checks |
|
|
159
|
+
| `oql/search.py` | The safe search loop: fixed rounds, elites survive, every strategy logged |
|
|
160
|
+
| `oql/permute.py` | Joint bar permutation across markets (adapted from neurotrader888's MIT-licensed method), plus a volatility-matched null |
|
|
161
|
+
| `oql/calibration.py` | Measures the gate's own false-positive rate and power on synthetic books (docs/CALIBRATION.md) |
|
|
162
|
+
| `oql/gate.py` | The gate and the holdout |
|
|
163
|
+
| `oql/stats.py` | Deflated Sharpe, cost and delay Monte Carlo, long/short split, beta |
|
|
164
|
+
| `oql/board.py` | Cards, stages, enforced moves, reports, the HTML board |
|
|
165
|
+
| `oql/server.py`, `oql/web/` | The `oql serve` dashboard (standard library only) |
|
|
166
|
+
| `oql/live.py`, `oql/web/live.js` | Background jobs streamed to the page; the shared live chart renderer |
|
|
167
|
+
| `oql/projects/` | The ten mini-projects, each with its known-answer checks |
|
|
168
|
+
| `oql/market.py` | Live public exchange data for the Live market tab |
|
|
169
|
+
| `oql/collect.py` | Scheduled, incremental, checksum-verified downloads |
|
|
170
|
+
| `oql/paper.py` | Paper trading: journal, revisions, reconciliation |
|
|
171
|
+
| `oql/agent_tools.py`, `oql/mcp_server.py` | What an AI assistant may do, served over MCP |
|
|
172
|
+
| `oql/ledger.py`, `oql/locks.py` | Every test counted; freeze fingerprints and one-shot locks |
|
|
173
|
+
| `demo/check_parity.py` | Checks that the live demo page computes the same numbers as the Python lab |
|
|
174
|
+
|
|
175
|
+
## Roadmap
|
|
176
|
+
|
|
177
|
+
- [x] Phase 1: data catalog and loaders, plus `oql collect` for scheduled downloads on a Raspberry Pi
|
|
178
|
+
- [x] Phase 2: paper trading with the same code as the backtest (`oql paper`), with replay, data and returns
|
|
179
|
+
reconciliation; a NautilusTrader adapter remains optional
|
|
180
|
+
- [x] Phase 3: validation gate
|
|
181
|
+
- [x] Phase 4: pipeline board (command line + HTML)
|
|
182
|
+
- [x] Phase 5: an MCP server (`oql mcp`) so an AI assistant can propose cards, write pre-registrations and
|
|
183
|
+
experiments, and explore development data; it cannot freeze, run the gate or holdout, or deploy, and every
|
|
184
|
+
exploration it makes is counted in the gate report. See [docs/AGENTS.md](https://github.com/dnd8639-byte/permutalpha-quant/blob/main/lab/docs/AGENTS.md)
|
|
185
|
+
|
|
186
|
+
Building on it: [docs/DEVELOPING.md](https://github.com/dnd8639-byte/permutalpha-quant/blob/main/lab/docs/DEVELOPING.md). Running it on a Pi: [deploy/README.md](https://github.com/dnd8639-byte/permutalpha-quant/blob/main/lab/deploy/README.md).
|
|
187
|
+
See [NOTICE.md](https://github.com/dnd8639-byte/permutalpha-quant/blob/main/lab/NOTICE.md) for credits.
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# permutalpha (Open Quant Lab)
|
|
2
|
+
|
|
3
|
+
```bash
|
|
4
|
+
pip install permutalpha
|
|
5
|
+
oql demo && OQL_LAB=oql-demo OQL_CATALOG=oql-demo/catalog oql serve
|
|
6
|
+
```
|
|
7
|
+
|
|
8
|
+
A fully open research pipeline for trading strategies: a data catalog, a backtest engine with costs and delays, and a validation gate that the strategy has to pass before anything else happens. The rules of every test are enforced by code, not by good intentions.
|
|
9
|
+
|
|
10
|
+
Designed and directed by David DeConti, with much of the code written with an AI assistant (Claude). MIT licence. Inspired by the shape of QuantConnect's research pipeline (Ideas → Research → Backtest → Paper → Live), rebuilt so that no part of it is paid, and so that a strategy cannot be promoted by trying things until one looks good.
|
|
11
|
+
|
|
12
|
+
**Live demo:** the validation gate runs in your browser at [dnd8639-byte.github.io/open-quant-lab](https://dnd8639-byte.github.io/open-quant-lab/).
|
|
13
|
+
It is a JavaScript port of the engine, rules and search; `python demo/check_parity.py` confirms that it computes the same
|
|
14
|
+
numbers as this code.
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
idea ──> research ──> preregistered ──> gate ──> holdout ──> paper
|
|
18
|
+
explore freely rules fingerprinted whole-search one-shot Raspberry Pi
|
|
19
|
+
(SHA-256) permutation test (locked) paper trader
|
|
20
|
+
FAIL ─> archive FAIL ─> archive
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## What makes it different
|
|
24
|
+
|
|
25
|
+
| Rule | How the code enforces it |
|
|
26
|
+
|---|---|
|
|
27
|
+
| Decide the test before seeing the result | `oql card freeze` fingerprints `PREREGISTRATION.md`, `experiment.py` and every dataset (SHA-256). The gate and the holdout refuse to run if any of them changed. |
|
|
28
|
+
| Judge the best of many tries as the best of many tries | The gate reruns the **entire search**, every round, on shuffled copies of the data. p = how often luck alone finds something as good. |
|
|
29
|
+
| Count every attempt | Every gate and holdout run goes into `LEDGER.csv`, pass or fail. Changing a tested idea means `oql card revise`: a new card in the same family, and the family's trial count keeps adding up. |
|
|
30
|
+
| Look at the holdout once | `oql card holdout` writes its lock file before it computes anything. A second run is refused, even if someone edits `board.json`. |
|
|
31
|
+
| No skipping | Cards move one stage at a time; a failed gate or holdout sends the card to the archive. |
|
|
32
|
+
| Licensed data never leaks | Every dataset carries a licence tag (`public`, `own`, `licensed`); the whole catalog is git-ignored. |
|
|
33
|
+
|
|
34
|
+
The lab checks itself: on fake markets with a planted, real edge the gate passes (p = 0.025, the smallest possible with 39 permutations, in 5 of 5 draws); on pure noise it fails (p between 0.30 and 0.85 in 5 of 5 draws). Run `python examples/quickstart.py` to watch both happen.
|
|
35
|
+
|
|
36
|
+
## Install
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install permutalpha # numpy, pandas, pyarrow
|
|
40
|
+
pip install "permutalpha[all]" # + scikit-learn (tree forecasts) and ccxt (live paper trading)
|
|
41
|
+
oql demo # a lab on synthetic markets, two cards frozen and ready for their gate
|
|
42
|
+
OQL_LAB=oql-demo OQL_CATALOG=oql-demo/catalog oql serve
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Run both gates from the Research board: the planted edge passes and the pure noise fails. From source:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
git clone https://github.com/dnd8639-byte/permutalpha-quant && cd permutalpha-quant/lab
|
|
49
|
+
pip install -e . && python -m unittest discover tests
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## An AI research assistant that cannot cheat
|
|
53
|
+
|
|
54
|
+
`oql mcp` serves the lab to any Model Context Protocol client (Claude Desktop, Claude Code, or a local model). The
|
|
55
|
+
assistant can read the board and data, propose ideas, write pre-registrations and experiments from validated fields
|
|
56
|
+
(never code), explore development data and run efficiency studies. It cannot freeze a card, run the gate or the
|
|
57
|
+
holdout, or deploy: those stay with a person. Every exploration it makes is logged and printed next to the final
|
|
58
|
+
result. Setup: [docs/AGENTS.md](https://github.com/dnd8639-byte/permutalpha-quant/blob/main/lab/docs/AGENTS.md).
|
|
59
|
+
|
|
60
|
+
## Use
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
oql data pull-fred DGS10 CPIAUCSL # free, no key
|
|
64
|
+
oql data pull-binance BTCUSDT --interval 1h --start 2018-01
|
|
65
|
+
oql data import-databento ../state/v3/contracts --roots ES,CL,GC # licensed: stays local
|
|
66
|
+
oql data pull-french # Fama-French factors, for the projects
|
|
67
|
+
oql data import-projects ../quant-projects/data # the projects' option chain (licensed) and trades
|
|
68
|
+
oql data list
|
|
69
|
+
oql data check
|
|
70
|
+
|
|
71
|
+
oql card new "Time-series momentum on CME futures" --mechanism "Slow-moving capital and hedging demand make trends persist."
|
|
72
|
+
# edit cards/0001-.../PREREGISTRATION.md and experiment.py
|
|
73
|
+
oql card start 1
|
|
74
|
+
oql card freeze 1 # then commit and push: the commit time proves the rules came first
|
|
75
|
+
oql card gate 1 # search + whole-search permutation test -> cards/0001-.../gate.md
|
|
76
|
+
oql card holdout 1 # one shot
|
|
77
|
+
oql board --html board.html
|
|
78
|
+
oql ledger
|
|
79
|
+
oql serve # the dashboard: live gate runs, the permutation lab, data, ledger
|
|
80
|
+
oql efficiency study binance/BTCUSDT/1h --groups funding,basis,macro # is efficiency predictable? (dev data, logged)
|
|
81
|
+
oql efficiency gates binance/BTCUSDT/1h "momentum lookback=20" # does an efficiency gate help this strategy?
|
|
82
|
+
oql paper deploy 1 --feed binance/BTCUSDT/1h=binanceus:BTC/USDT:1h # after a holdout PASS
|
|
83
|
+
oql collect init && oql collect run # keep free data current (Pi)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## The dashboard
|
|
87
|
+
|
|
88
|
+
`oql serve` opens a local web app (nothing leaves your machine):
|
|
89
|
+
|
|
90
|
+
- **Research board**: every card by stage. Run a preregistered card's gate from the page and watch the shuffled
|
|
91
|
+
reruns arrive one by one, the null histogram fill in, and the p-value settle.
|
|
92
|
+
- **Permutation lab**: pick a market and a strategy; the lab shuffles the market in front of you and builds the
|
|
93
|
+
distribution of luck one permutation at a time. Switch to "best of the whole search" to see selection bias.
|
|
94
|
+
Uses only the first 70% of each dataset, so it never touches a holdout.
|
|
95
|
+
- **Data** and **Ledger**: the catalog with quality checks, and every test ever run.
|
|
96
|
+
- **Projects**: ten quant mini-projects (tail risk, seasonality, overfitting, momentum crashes, factor neutrality,
|
|
97
|
+
American options, autodiff Greeks, implied distributions, Hawkes processes, news diffusion) running live on the
|
|
98
|
+
catalog's data. Each runs its known-answer checks first; charts fill in as the work happens.
|
|
99
|
+
- **Live market**: price, the rolling one-hour efficiency ratio, volatility and the spread from public exchange data
|
|
100
|
+
(Kraken, Coinbase, Binance.US), updating every few seconds. No account or key.
|
|
101
|
+
- **Efficiency**: can the next day's (or hour's) efficiency be forecast from price, calendar, funding, basis, macro,
|
|
102
|
+
positioning and order-book data, walk-forward on development data? And does switching a strategy on and off by
|
|
103
|
+
efficiency help it, and how strong would the forecast need to be? Every run checks itself on synthetic markets
|
|
104
|
+
first and is counted in the ledger. Gates found here are tested for real by declaring them in a card's experiment
|
|
105
|
+
(`gates=[...]`), where the gate test reruns them on shuffled data. See [docs/EFFICIENCY.md](https://github.com/dnd8639-byte/permutalpha-quant/blob/main/lab/docs/EFFICIENCY.md).
|
|
106
|
+
|
|
107
|
+
Holdouts are deliberately not runnable from the page: they are one-shot, so they need a typed command.
|
|
108
|
+
|
|
109
|
+
## Layout
|
|
110
|
+
|
|
111
|
+
| Path | What it is |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `oql/catalog.py` | Parquet catalog with metadata, licence tags, SHA-256 and quality checks |
|
|
114
|
+
| `oql/sources.py` | FRED, Binance public files, CSV, release calendar, Pi order-book features, Databento front contracts (roll-safe) |
|
|
115
|
+
| `oql/engine.py` | Bar engine: decisions at the close, fills a fraction into the next bar, costs per change, equal-risk sizing |
|
|
116
|
+
| `oql/strategies.py` | Rule library (breakout, moving-average cross, momentum, reversal, opening-range breakout); add your own per experiment |
|
|
117
|
+
| `oql/gates.py` | Efficiency gates a search can add to any strategy (trailing efficiency, or the efficiency forecast) |
|
|
118
|
+
| `oql/efficiency.py` | The efficiency lab: targets, look-ahead-free features, walk-forward forecasts, gate checks |
|
|
119
|
+
| `oql/search.py` | The safe search loop: fixed rounds, elites survive, every strategy logged |
|
|
120
|
+
| `oql/permute.py` | Joint bar permutation across markets (adapted from neurotrader888's MIT-licensed method), plus a volatility-matched null |
|
|
121
|
+
| `oql/calibration.py` | Measures the gate's own false-positive rate and power on synthetic books (docs/CALIBRATION.md) |
|
|
122
|
+
| `oql/gate.py` | The gate and the holdout |
|
|
123
|
+
| `oql/stats.py` | Deflated Sharpe, cost and delay Monte Carlo, long/short split, beta |
|
|
124
|
+
| `oql/board.py` | Cards, stages, enforced moves, reports, the HTML board |
|
|
125
|
+
| `oql/server.py`, `oql/web/` | The `oql serve` dashboard (standard library only) |
|
|
126
|
+
| `oql/live.py`, `oql/web/live.js` | Background jobs streamed to the page; the shared live chart renderer |
|
|
127
|
+
| `oql/projects/` | The ten mini-projects, each with its known-answer checks |
|
|
128
|
+
| `oql/market.py` | Live public exchange data for the Live market tab |
|
|
129
|
+
| `oql/collect.py` | Scheduled, incremental, checksum-verified downloads |
|
|
130
|
+
| `oql/paper.py` | Paper trading: journal, revisions, reconciliation |
|
|
131
|
+
| `oql/agent_tools.py`, `oql/mcp_server.py` | What an AI assistant may do, served over MCP |
|
|
132
|
+
| `oql/ledger.py`, `oql/locks.py` | Every test counted; freeze fingerprints and one-shot locks |
|
|
133
|
+
| `demo/check_parity.py` | Checks that the live demo page computes the same numbers as the Python lab |
|
|
134
|
+
|
|
135
|
+
## Roadmap
|
|
136
|
+
|
|
137
|
+
- [x] Phase 1: data catalog and loaders, plus `oql collect` for scheduled downloads on a Raspberry Pi
|
|
138
|
+
- [x] Phase 2: paper trading with the same code as the backtest (`oql paper`), with replay, data and returns
|
|
139
|
+
reconciliation; a NautilusTrader adapter remains optional
|
|
140
|
+
- [x] Phase 3: validation gate
|
|
141
|
+
- [x] Phase 4: pipeline board (command line + HTML)
|
|
142
|
+
- [x] Phase 5: an MCP server (`oql mcp`) so an AI assistant can propose cards, write pre-registrations and
|
|
143
|
+
experiments, and explore development data; it cannot freeze, run the gate or holdout, or deploy, and every
|
|
144
|
+
exploration it makes is counted in the gate report. See [docs/AGENTS.md](https://github.com/dnd8639-byte/permutalpha-quant/blob/main/lab/docs/AGENTS.md)
|
|
145
|
+
|
|
146
|
+
Building on it: [docs/DEVELOPING.md](https://github.com/dnd8639-byte/permutalpha-quant/blob/main/lab/docs/DEVELOPING.md). Running it on a Pi: [deploy/README.md](https://github.com/dnd8639-byte/permutalpha-quant/blob/main/lab/deploy/README.md).
|
|
147
|
+
See [NOTICE.md](https://github.com/dnd8639-byte/permutalpha-quant/blob/main/lab/NOTICE.md) for credits.
|