backtest-audit
Static analysis for Python backtesting code.
Catches look-ahead bias, data leakage, and statistical errors — before they invalidate your results.
pip install backtest-audit
backtest-audit check ./strategies/
Why
A backtest that looks profitable is often built on data the strategy could never have had.
Look-ahead bias, data leakage, and missing transaction costs are the three most common ways
a backtest lies to you. backtest-audit catches these at the code level, without running
your strategy.
Output
── strategies/mean_reversion.py ─────────────────────── 2 issues ──
[LAB001] Negative shift — future data pulled into current timestep line 34
df['signal'] = df['close'].shift(-5)
↳ Replace shift(-n) with shift(n). Negative periods reference future rows, invalidating the backtest.
[LEAK002] fit_transform() detected — ensure this is called only on training data line 61
X_scaled = scaler.fit_transform(X)
↳ Replace fit_transform(X) with fit(X_train).transform(X_train), then transform(X_test) separately.
──────────────────────────────────────────────────────────────────────
1 error, 1 warning
Rules
| Code | Category | Description |
|---|---|---|
| LAB001 | Look-Ahead Bias | shift(-n) pulls future prices into current signal |
| LAB002 | Look-Ahead Bias | pct_change(-n) computes forward returns |
| LEAK001 | Data Leakage | fit() called with no train_test_split detected |
| LEAK002 | Data Leakage | fit_transform() may be called on unsplit data |
| STAT001 | Statistical Malpractice | Sharpe ratio assigned without annualization factor |
| STAT002 | Statistical Malpractice | No transaction cost or slippage variable detected |
Full documentation with explanations and code examples: docs/rules/
Usage
# Check a single file
backtest-audit check my_backtest.py
# Check a directory
backtest-audit check ./strategies/
# Output as JSON (for CI pipelines)
backtest-audit check ./strategies/ --format json
# Ignore specific rules
backtest-audit check ./strategies/ --ignore LAB002,STAT002
# List all rules
backtest-audit rules
Installation
pip install backtest-audit
Requires Python 3.8+. The only dependency is click.
How It Works
backtest-audit parses your Python source files into an abstract syntax tree (AST)
and walks the tree looking for known problematic patterns. It does not execute your code.
Each rule is a pattern matcher — it looks for a specific construct that is known to
produce invalid backtest results.
This means it is fast, safe to run on any codebase, and produces no false positives from runtime behavior.
Limitations
- Does not run your backtest or evaluate strategy profitability
- Cannot detect all forms of look-ahead bias — only statically visible patterns
- LEAK001 checks for
train_test_splitpresence in the file, not correct application - Manual chronological splits (e.g.,
df[:split_date]) are not yet recognized - Does not support non-Python backtesting frameworks
License
MIT
Release files for backtest-audit 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| backtest_audit-1.0.0.tar.gz | 14.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| backtest_audit-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.7 kB
Release files / backtest_audit-1.0.0.tar.gz
| Download URL | backtest_audit-1.0.0.tar.gz |
|---|---|
| Size | 14.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7db5b3cb6aa251ea01513983d7482b59489d24dde49afe998149f744d704f0e5
|
|
BLAKE2b-256 checksum How to use checksums |
c1e0cf6a71b14fdd7e3ce5b8393e02ef6abe8392f034524e7e73085e4364db52
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Release files / backtest_audit-1.0.0-py3-none-any.whl
| Download URL | backtest_audit-1.0.0-py3-none-any.whl |
|---|---|
| Size | 14.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d38db58ef15db35c5545191824e32a970423310ac53a64c248b79d71e6cbf42c
|
|
BLAKE2b-256 checksum How to use checksums |
7c4d67108f6349d9bae74859a8714c68f77d9463a72c5bc96b0789d4cbf4a187
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|