# Backtesting pitfalls: biases that fake strategy profits

URL: https://fincodelabs.com/en/blog/backtesting-trading-strategy-pitfalls · Publisher: Fincode (Fincode Yazılım ve Teknoloji A.Ş.), Istanbul, Turkey · Category: Backtesting and risk · Published: 2026-10-24 · Updated: 2026-11-05

Backtesting pitfalls explained: look-ahead bias, survivorship bias, overfitting, unrealistic costs and small samples, with walk-forward and other remedies.

**Short answer:** The most common backtesting pitfalls are look-ahead bias, survivorship bias, overfitting through many trials, and unrealistic fills and costs; each makes a strategy look more profitable on history than it can be in live trading. The remedies are out-of-sample and walk-forward testing, counting and reporting every trial, conservative cost assumptions and a period of paper trading before real money is committed.

A backtest replays a strategy's rules over historical data as if each decision had been taken with only the information available at that moment. Every pitfall below breaks that assumption in a direction that flatters the strategy, which is why a backtest that looks too good usually is.

The examples use synthetic data and hypothetical numbers. Regulators are wary too: US rules for commodity pool operators and trading advisors (17 CFR 4.41) require a prominent statement that simulated results have inherent limitations and do not represent actual trading. Related guides are collected under [backtesting and risk](https://fincodelabs.com/en/blog/backtesting-and-risk).

## Look-ahead bias: trading on information you did not have

Look-ahead bias occurs when a backtest uses a value before it could have been known, and it can make a strategy with no edge look spectacular.

Typical forms: filling at a bar's open or close on a signal computed from that bar's close, timing an entry with the day's high or low, using financial statements from their period end instead of their publication date, and, in TradingView, requesting higher-timeframe data with lookahead_on and no offset. The Pine Script documentation also warns that timenow and order-fill recalculation can leak future data, and notes that forward testing on live data exposes such bugs because there is no future to leak.

The test below generates ten years of random daily returns, so no rule can have a real edge, and trades a five-day momentum rule twice: once correctly and once with a missing shift.

```python
import numpy as np
import pandas as pd

rng = np.random.default_rng(1)
ret = pd.Series(rng.normal(0, 0.01, 2520))     # 10 hypothetical years of daily returns, no edge
signal = np.sign(ret.rolling(5).sum())         # long after a 5-day rise, short after a fall

def report(name, r):
    r = r.dropna()
    sharpe = r.mean() / r.std() * np.sqrt(252)
    print(f"{name}: Sharpe {sharpe:5.2f}, winning days {(r > 0).mean():.0%}")

report("correct", signal.shift(1) * ret)  # decide at today's close, earn tomorrow's return
report("look-ahead bug", signal * ret)    # signal already contains the return it trades
```

```
correct: Sharpe  0.05, winning days 49%
look-ahead bug: Sharpe  6.25, winning days 65%
```

> **What the bug does (hypothetical data).** Without shift(1), each day's signal includes that day's return, so the rule partly bets on a result it already knows. A Sharpe ratio of 6.25 on pure noise, with 65% winning days, is the signature of look-ahead bias. Results that good call for a code review.

## Survivorship bias in backtest data

Survivorship bias appears when the test universe contains only assets that still exist today.

Testing a stock strategy on today's index members over the past ten years excludes companies that were delisted, went bankrupt or dropped out of the index, and the survivors are partly in the index because they did well. Crypto has the same problem: delisted coins and pairs, and closed exchanges, disappear from current symbol lists. The fix is point-in-time data, meaning index membership as it was on each date and price histories of delisted assets, which often requires a paid data source. Unadjusted splits and dividends belong to the same family of data errors, creating price gaps that never happened, as discussed in the [BIST backtesting platform](https://fincodelabs.com/en/projects/bist-strategy-backtesting-platform) scenario.

## Overfitting a trading strategy: the multiple-trials problem

Overfitting means tuning a strategy until it fits the noise of one historical sample, and research shows how few trials that takes.

Bailey, Borwein, López de Prado and Zhu (Notices of the AMS, 2014) show that when a researcher tries N independent configurations with zero true edge, the best one's in-sample Sharpe ratio rises with N while its expected out-of-sample Sharpe ratio stays at zero. With 10 configurations on one year of data, the expected best annualized Sharpe ratio is about 1.57. Their minimum backtest length (MinBTL): with five years of data, no more than 45 independent configurations should be tried, or an in-sample Sharpe ratio of 1 is almost guaranteed from luck alone; with two years, 7 trials suffice. The sketch below reproduces these figures from the paper's formulas.

```python
from math import e
from statistics import NormalDist

def expected_max_sharpe(trials):          # Bailey et al. (2014), Proposition 2.1
    z = NormalDist().inv_cdf
    gamma = 0.5772156649                  # Euler-Mascheroni constant
    return (1 - gamma) * z(1 - 1 / trials) + gamma * z(1 - 1 / (trials * e))

for trials in (7, 10, 45, 1000):
    best = expected_max_sharpe(trials)    # best Sharpe of skill-less strategies, 1 year
    print(f"{trials:5d} trials: expected best Sharpe {best:.2f}, "
          f"MinBTL for Sharpe 1: {best ** 2:.1f} years")
```

```
    7 trials: expected best Sharpe 1.39, MinBTL for Sharpe 1: 1.9 years
   10 trials: expected best Sharpe 1.57, MinBTL for Sharpe 1: 2.5 years
   45 trials: expected best Sharpe 2.24, MinBTL for Sharpe 1: 5.0 years
 1000 trials: expected best Sharpe 3.26, MinBTL for Sharpe 1: 10.6 years
```

The authors stress that MinBTL is necessary but not sufficient, and that a backtest which does not report its number of trials cannot be assessed for overfitting. Follow-up work quantifies the problem further:

- The **probability of backtest overfitting** (PBO), estimated with combinatorially symmetric cross-validation, is the probability that the configuration that is best in-sample performs below the median out-of-sample.
- The **deflated Sharpe ratio** of Bailey and López de Prado corrects a Sharpe ratio for selection bias under multiple testing and for non-normal returns.
- Harvey and Liu (Journal of Portfolio Management, 2015) call the common 50% Sharpe haircut only a rule of thumb: the correct multiple-testing haircut is nonlinear, mild for the highest Sharpe ratios and severe for marginal ones. Harvey, Liu and Zhu, who catalog 316 factors proposed to explain equity returns, argue that a new factor needs a t-statistic above 3.0.

## Unrealistic fills, costs, slippage and funding

A backtest that fills every order at the signal price and pays nothing for trading measures a market that does not exist.

- **Cost-free defaults.** TradingView's Pine Script strategies apply no commission unless one is specified and default to zero slippage (as of October 2026).
- **Fill timing.** A signal computed on a bar's close can usually be executed only afterwards, at the next open or later.
- **Limit orders.** Filling a limit whenever price touches it ignores the queue; Pine's backtest_fill_limits_assumption can require price to trade through the level.
- **Spread and market impact.** Market orders cross the spread, and large orders move the price.
- **Funding.** On perpetual futures, funding moves between longs and shorts. On Binance, for example, longs pay shorts when the rate is positive and shorts pay longs when it is negative, by default every eight hours, though some contracts settle more often (as of October 2026). Strategies that hold positions for days must include it; see [how funding rates work](https://fincodelabs.com/en/blog/perpetual-futures-funding-rate).

> **Hypothetical cost check.** A strategy earns a gross 0.15% per round trip and trades 400 times a year: +60% a year as a simple sum. With 0.1% commission and an estimated 0.05% slippage per side, each round trip costs 0.30%, so the net result is about −60% a year. Trading less often does not fix a negative net edge per trade; only a gross edge larger than costs does.

## Regime change and small samples

A strategy tested in one market regime is untested in the others, and a short record cannot separate skill from luck.

A trend rule built in a long bull market, or a mean-reversion rule tested only in a sideways period, may simply describe that period. Use data with rising, falling and sideways phases and stress episodes, and read results per year and regime. On sample size, Harvey and Liu note that the Sharpe ratio equals the t-ratio divided by the square root of the number of observations; in annual terms, the t-ratio is roughly the annualized Sharpe ratio times the square root of the number of years. A Sharpe ratio of 1 over four years therefore gives a t-ratio of only about 2, borderline for a single test and below the 3.0 hurdle once many ideas have been tried. There is no universal minimum number of trades.

## Walk-forward analysis and other remedies

No single test proves a strategy works, but tests that each try to break it expose most of the pitfalls above.

**Remedies and what they catch**

| Remedy | How it works | Main target |
| --- | --- | --- |
| Out-of-sample hold-out | Keep the latest data untouched until the design is final; it is spent once you change the strategy after looking | Overfitting |
| Walk-forward analysis | Optimize on a window, test unchanged on the next period, roll forward, report only the stitched test periods | Overfitting, regime change |
| Parameter stability | Neighboring values (45, 50, 55 bars) should give similar results; one sharp peak is a warning | Overfitting |
| Monte Carlo resampling | Reshuffle or bootstrap trades, or block-resample returns, to see the range of drawdowns the same edge could produce | Small samples, path luck |
| Trial log and deflated Sharpe ratio | Record every variant tested and adjust the headline statistic for the count | Data snooping |
| Paper trading | Run the final version on live data without real money | Look-ahead, fills, operations |

A walk-forward example on hypothetical 2016 to 2025 data: fit on 2016 to 2018 and test on 2019, fit on 2017 to 2019 and test on 2020, and so on; scikit-learn's TimeSeriesSplit generates forward-only splits, expanding unless max_train_size caps the window. A simple hold-out ignores how many trials preceded it, Bailey and co-authors note, so pair it with a trial log. TradingView's documentation adds that forward testing avoids lookahead bias but, with limited data, is not typically used on its own.

A pre-launch review of these points is part of a [project and product analysis](https://fincodelabs.com/en/services/project-and-product-analysis). Strategies ported from TradingView need the fill-rule checks in [Pine Script to Python](https://fincodelabs.com/en/blog/pine-script-to-python), and live systems need the limits in [trading bot risk management](https://fincodelabs.com/en/blog/trading-bot-risk-management) and the safeguards in [trading bot development](https://fincodelabs.com/en/blog/trading-bot-development). Code for walk-forward and Monte Carlo tests is in [backtesting libraries in Python](https://fincodelabs.com/en/blog/backtesting-python-libraries). Even a backtest that survives every test does not guarantee future results; markets change and automated strategies can lose money.

## Frequently asked questions

### What is look-ahead bias in backtesting?

It is using information in a simulated decision before it was available, such as trading at a bar's open on a signal from the same bar's close. A single missing shift in the code can cause it.

### What is walk-forward analysis?

A test in which parameters are optimized on one window of data, applied unchanged to the following period, and both windows are rolled forward. Only the combined out-of-sample periods are reported, which approximates running the strategy in real time.

### How many years of data does a backtest need?

There is no universal number, and more trials require more data. Bailey and co-authors estimate that with five years of data no more than 45 independent configurations should be tried before a Sharpe ratio of 1 is expected from luck alone.

### What is the deflated Sharpe ratio?

A statistic by Bailey and López de Prado that adjusts a Sharpe ratio for the number of trials behind it, the length of the sample and non-normal returns, so a result found after many attempts must clear a higher bar.

### Does a good backtest mean a strategy will make money?

No. A backtest shows how rules would have behaved on past data under its assumptions; even a carefully tested strategy can lose money live because of costs, execution and changing markets.

## Sources

- [Bailey, Borwein, López de Prado, Zhu: Pseudo-Mathematics and Financial Charlatanism (preprint; published in Notices of the AMS 61(5), May 2014)](https://www.davidhbailey.com/dhbpapers/backtest-pseudo.pdf)
- [Bailey, Borwein, López de Prado, Zhu: The Probability of Backtest Overfitting (revised working paper, February 2015)](https://www.davidhbailey.com/dhbpapers/backtest-prob.pdf)
- [Bailey, López de Prado: The Deflated Sharpe Ratio (Journal of Portfolio Management, 2014)](https://www.davidhbailey.com/dhbpapers/deflated-sharpe.pdf)
- [Harvey, Liu: Backtesting (Journal of Portfolio Management, Fall 2015)](https://people.duke.edu/~charvey/Research/Published_Papers/P120_Backtesting.PDF)
- [Harvey, Liu, Zhu: ...and the Cross-Section of Expected Returns (Review of Financial Studies 29(1), 2016)](https://people.duke.edu/~charvey/Research/Published_Papers/P118_and_the_cross.PDF)
- [TradingView Pine Script v6 User Manual: Strategies (costs, fills, lookahead bias, forward testing)](https://www.tradingview.com/pine-script-docs/concepts/strategies/)
- [TradingView Pine Script v6 User Manual: Other timeframes and data (lookahead)](https://www.tradingview.com/pine-script-docs/concepts/other-timeframes-and-data/)
- [Binance: Introduction to Binance Futures Funding Rates](https://www.binance.com/en/support/faq/introduction-to-binance-futures-funding-rates-360033525031)
- [17 CFR 4.41: Advertising by commodity pool operators and commodity trading advisors (Cornell LII)](https://www.law.cornell.edu/cfr/text/17/4.41)
- [scikit-learn: TimeSeriesSplit](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.TimeSeriesSplit.html)
- [pandas documentation: Series.shift](https://pandas.pydata.org/docs/reference/api/pandas.Series.shift.html)

> This guide is general information about software and markets, not investment, legal or tax advice. Automated trading can lose money, past or backtested performance does not guarantee future results, and the rules that apply depend on your jurisdiction and your exchange's terms. Sources, checks and corrections: see the [editorial policy](https://fincodelabs.com/en/editorial-policy).

---

Published by Fincode (Fincode Yazılım ve Teknoloji A.Ş.), a software company in Istanbul, Turkey: https://fincodelabs.com/en/blog/backtesting-trading-strategy-pitfalls

Cite as: Fincode, "Backtesting pitfalls: biases that fake strategy profits", updated November 5, 2026, https://fincodelabs.com/en/blog/backtesting-trading-strategy-pitfalls
