Open source / engineering
The code that produces every number on this site.
The strategies are well-documented academic families. What took the work is
the machinery that stops me fooling myself, and that machinery is public, tested and
pinned. 1,220 tests across 262 published files, all of it
byte-identical to the engine that publishes the live paper record.
What this is not. Open code is not a track record and
not a claim that the strategies make money. The paper record and its limits live on
status; the corrections live on corrections.
Three repositories
One system, plus two focused extractions of the parts most worth reading on their own.
The whole system: data lake, point-in-time reader, backtester, walk-forward harness, multiple-testing machinery, portfolio optimizer and live broker loop.
Public because the claim is not “this makes money.” It is
“every number published here can be checked, including the ones that embarrass me.”
That claim is worthless if the code is hidden.
- Files published
- 146
- Source / tests
- 40 / 48
- Tests passing
- 941 +12 deselected
- Strict type check
- 42 files, 0 issues
The 12 deselected are network tests, excluded by default.
Measured 2026-08-27 using benchmarks/lake_throughput.py
1,000,000 synthetic bars (50 instruments x 20,000 hourly), Apple silicon, single process
| write, validate then atomic promote | ~1.05M bars/s |
| read, everything visible | ~15M rows/s |
| read, as_of at the midpoint | ~14M rows/s |
| on disk, zstd-3 | 60.6 bytes/bar |
Re-run every gate yourself:
uv run pytest
uv run mypy
uv run ruff check .
uv run python tools/check_parity.py
1 engine test module read the private research corpus and cannot run here. It is removed rather than skipped, with the reason recorded in excluded_tests.json, so the suite has no silently-passing holes.
- Files published
- 116
- Source / tests
- 36 / 22
- Tests passing
- 279
- Strict type check
- 41 files, 0 issues
Measured 2026-08-27 using benchmarks/validation_throughput.py
Apple silicon, single process; the PBO case runs on pure noise so the result is also a correctness check
| PBO via CSCV, 2,000 x 100 configs, 5,000 sampled splits | 1.6 s |
| Deflated Sharpe, 1,260 daily returns | ~300 microseconds |
| PBO measured on pure noise (0.5 is correct) | 0.569 |
| One series, Sharpe +1.139, PSR against zero | 0.9828 |
| The same series deflated against 10 trials | 0.8408 |
| The same series deflated against 200 trials | 0.5608 |
Re-run every gate yourself:
uv run pytest
uv run mypy
uv run ruff check .
uv run python tools/check_parity.py
2 engine test modules read the private research corpus and cannot run here. They are removed rather than skipped, with the reason recorded in excluded_tests.json, so the suite has no silently-passing holes.
What is actually hard here
Three ways a quantitative result can be false while every test passes, and the structural
answer to each. Not conventions to remember, but things the code will not let you do.
Problem one
The backtest saw something it could not have seen.
Look-ahead is rarely a dramatic bug. It is an off-by-one on a timestamp, a feature
computed over a window that includes the present, a flag derived from tomorrow's reversion.
It never raises. It just makes the curve go up.
How it is prevented
A strategy decides at the close of bar t and fills at the open of bar
t+1. The fill model is handed only the t+1 bar, checks that bar opened
after the decision, and raises LookaheadError if it did not. The engine
re-checks every fill it gets back. The strategy reads history through a context whose
accessor is a point-in-time read fixed at the decision close, so there is no handle on the
future to grab even by accident.
src/alphaforge/backtest/fills.py ↗
Problem two
The data quietly knows how the story ended.
Today's index membership means the backtest only ever traded survivors. Today's split
factors mean 2015 trades at prices no screen showed in 2015. A restated earnings figure gets
treated as knowable on the original filing date.
How it is prevented
Every analytical read takes an explicit as_of and returns only records
available at that instant. There is deliberately no as_of=now default, so a
caller has to state its information time. Corporate actions filter on
available_at, meaning declaration plus publication lag, and never on
ex_date. A split declared one millisecond after your as_of is
therefore invisible. Quality flags carry per-bit availability lags, and a bit whose lag is undeclared
is never exposed at all.
src/alphaforge/data/store/reader.py ↗
Problem three
It was the best of two hundred tries, and one got published.
This is the harder lie and the more common one. Run enough variants and something looks
brilliant by luck alone. No amount of simulation fidelity fixes it.
How it is prevented
The answer is an honest denominator, not a better backtest. Deflated Sharpe measures
an observed Sharpe against the level luck alone reaches given how many configurations were
tried; a union trial ledger counts every hypothesis across every research ledger so filing
conventions cannot shrink the count. Hold one 1,260-day series fixed at an annualised Sharpe
of +1.139, a Probabilistic Sharpe against zero of 0.9828, and move only the trial count: the
Deflated Sharpe reads 0.9596 at two trials and 0.5608 at two hundred.
Nothing about the strategy changed. Against this project's 0.95 gate it is admissible if you
tried two things and inadmissible if you tried ten.
src/alphaforge/validation/dsr.py ↗
How the extractions stay honest
A published copy of code nobody checks is a screenshot.
The module set is derived, not curated
Each extraction ships the transitive import closure of its entry packages, computed by
walking the import graph. The test set is every engine test whose imports that closure
satisfies. Nobody chose the file list, so nobody could quietly leave an awkward file out.
Parity is a build failure, not a promise
Every shipped file's SHA-256 is recorded at extraction time.
tools/check_parity.py re-reads each one from the engine at the pinned commit
and fails if a single byte differs. It runs in CI on every push, and it is mutation-tested
three ways: a drifted file, a tampered manifest entry and a deleted file each turn it red.
Only what the engine publishes
The extraction reads the engine's tracked file set, not its working directory. That rule
exists because the first version did not have it and shipped 70 files the engine
deliberately gitignores. The parity check against GitHub caught them; a check against a
local copy never would have, because it was comparing those files against the very tree
they came from.
The toolchain is pinned too
Source that cannot be edited without breaking parity cannot be made to satisfy a newer
linter. So ruff, mypy, pandas and numpy are pinned to the versions the engine is verified
against. “Identical” asserted by a tool that disagrees with the one that
certified it is not identical.
If you have ten minutes
Four files, in this order. Each one is heavily commented with the reasoning, not just the
implementation.
-
-
-
-
tools/check_parity.py
canli-pit-lake
How these repositories prove they are the engine's code and not a fork that drifted.
About the lab
Canli Capital is not a fund and not a team. It is a one-person quantitative research
lab, engineered independently in Dubai since July 2024.
The order of the work is the argument. The point-in-time data layer, the cost authority,
the validation gauntlet and the crash-safe execution loop were built before any serious
effort went into chasing return, because a backtest only means something on top of a
process honest enough to produce it. That is why there are two years of engineering
behind a paper record measured in weeks, and not the other way around.
The distinction that matters. The engineering
began in July 2024. The public paper record began on 2026-08-07. Everything between those
dates is infrastructure and method, not performance. This site does not present it as a
track record, and neither should anyone citing it.
Notes on the engineering
Post-mortems on real incidents, the arithmetic behind the validation gates, and design
arguments about the parts that were hard. Written for the mechanism, not the summary.
Read the engineering notes
Authorship
Designed, written and maintained by
Arhan Canli, in Dubai. Development uses reviewed AI-assisted tooling;
ownership, research decisions, published claims and release responsibility are mine. Every
repository is MIT licensed and carries machine-readable citation metadata.
This page is generated from
engineering_open_source.json, whose counts are read out of
what the repositories publish. The build asserts that artifact's content hash reproduces, so a
number typed by hand fails the build instead of reaching this page.