Skip to content

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.

alphac

The whole system

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.

canli-pit-lake

Byte-identical to alphac@612d2af81844

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-360.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.

canli-backtest

Byte-identical to alphac@612d2af81844

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 splits1.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 zero0.9828
The same series deflated against 10 trials0.8408
The same series deflated against 200 trials0.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.

  1. src/alphaforge/data/store/reader.py canli-pit-lake

    The point-in-time rule, and the comment explaining why it lives in exactly one place.

  2. src/alphaforge/backtest/engine.py canli-backtest

    The event loop: corporate actions, funding, marks, decision, fill, and the re-check after it.

  3. src/alphaforge/validation/pbo.py canli-backtest

    Combinatorially symmetric cross-validation, written out step by step against the 2017 paper.

  4. 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.