How to Backtest a Crypto Trading Bot in Python

How to Backtest a Crypto Trading Bot in Python

Backtesting is not optional — it is the only way to evaluate a strategy before putting real capital at risk. But a backtest is only as good as its inputs. Most backtests that work in development fail in production not because the strategy was wrong, but because the backtest was wrong.

The Minimal Correct Backtest Structure

import polars as pl

df = pl.read_parquet("BTC_OHLCV_1h.parquet").sort("candle_time")

df = df.with_columns([
    pl.col("close").rolling_mean(20).alias("sma_20"),
    pl.col("close").rolling_mean(50).alias("sma_50"),
])

# Shift by 1 to avoid look-ahead bias
df = df.with_columns([
    (pl.col("sma_20") > pl.col("sma_50")).cast(pl.Int8).shift(1).alias("position")
])

df = df.with_columns([
    pl.col("close").pct_change().alias("returns"),
])
df = df.with_columns([
    (pl.col("position") * pl.col("returns")).alias("strategy_returns")
])

total = (1 + df["strategy_returns"].drop_nulls()).product() - 1
print(f"Total return: {total:.2%}")

The Three Mistakes That Destroy Backtest Results

  • Look-ahead bias: always shift signals by one period with .shift(1)
  • Survivorship bias: testing only on assets that still exist overstates performance
  • Overfitting: split data — train 70%, validate 15%, test 15% untouched

Why Data Quality Matters More Than the Strategy

A strategy backtested on data with timestamp errors or missing candles can appear profitable due to data artifacts. The backtest is optimizing around bugs, not market structure. Audited data with documented anomalies is a prerequisite for results you can trust.

Audited OHLCV data for backtesting — BTC, ETH, XRP, SOL, LINK, LTC, ADA. 6 timeframes, Last Year (rolling 12 months). → Browse the catalog

Summary

A correct backtest requires clean data, proper signal shifting, an out-of-sample test set, and realistic execution assumptions. Most backtests fail not because the strategy is wrong but because one of these four requirements is violated.