> ## Documentation Index
> Fetch the complete documentation index at: https://uncoded.ch/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Common Backtesting Mistakes

> The pitfalls that turn good backtests into bad live performance. Curve-fitting, look-ahead bias, survivorship bias, fee underestimation, and more.

<Info>
  **Most failed backtests fail in predictable ways.** The same mistakes show up across operators learning the discipline. This guide walks through the common pitfalls and how to avoid them — saving you live-capital tuition.
</Info>

## The 10 most common backtesting mistakes

<AccordionGroup>
  <Accordion title="1. Curve-fitting / overfitting" icon="bullseye">
    Tuning parameters until they produce great results on a specific historical window. The "tuned" parameters are overfit to the noise of that window, not to a generalizable market characteristic.

    **Symptom**: backtest looks great. Live underperforms substantially.

    **Mitigation**: walk-forward testing. Tune on in-sample, validate on out-of-sample. Never peek at out-of-sample during tuning.

    **Red flags**: you "optimized" by sweeping `>3` parameters; you tuned until you got the result you wanted; you can't explain *why* the tuned parameters work.
  </Accordion>

  <Accordion title="2. Look-ahead bias" icon="eye">
    Your strategy accidentally uses information that wouldn't have been available at the decision moment.

    **Common form**: an indicator's "current value" is computed using data that hadn't yet arrived in real time. Closing-bar values, end-of-period statistics, or post-hoc adjustments leaked into a "real-time" signal.

    **Symptom**: results that seem too good to be true. `+200%` annual return with `-2%` max drawdown is almost certainly look-ahead-biased.

    **Mitigation**: the unCoded Backtester handles this carefully — every decision uses only data up to the candle close. But if you're computing custom indicators or doing post-hoc analysis, the bias can re-emerge.
  </Accordion>

  <Accordion title="3. Survivorship bias" icon="skull">
    Backtesting only on symbols that exist today. The symbols that delisted (because their projects failed) aren't in your universe — but in 2021, you might have allocated to them.

    **Symptom**: backtest results that look great because you're testing on a "winner" universe.

    **Mitigation**: backtest on majors only. `BTCUSDT`, `ETHUSDT`, `SOLUSDT`, `BNBUSDT` — symbols whose continued existence is high-confidence. Don't extrapolate from major-symbol backtests to long-tail altcoins.
  </Accordion>

  <Accordion title="4. Ignoring max drawdown for total return" icon="chart-line">
    `+50%` total return looks great. The same backtest with `-40%` max drawdown is terrible — most operators capitulate during a `-40%` drawdown and crystallize the loss.

    **Symptom**: optimizing for total return without checking drawdown. Live operator panic-closes at the bottom and never realizes the "good" return.

    **Mitigation**: always read total return AND max drawdown together. Ask "could I emotionally hold through this drawdown for the recovery?" If no, the strategy is wrong for you regardless of total return.
  </Accordion>

  <Accordion title="5. Fee underestimation" icon="coins">
    Backtesting with unrealistic fee assumptions (`0.025%` instead of `0.075%`, or no fees). Reported return is much higher than live would be.

    **Symptom**: live performance is `5-10%` worse than backtest predicted, attributed to "bad luck" or "different regime" when actually it's just realistic fees eating P\&L.

    **Mitigation**: use the realistic fee for your venue. Binance with BNB: `0.075%`. Binance without: `0.10%`. Coinbase small account: `0.40%-0.60%`. Check your venue, your tier.
  </Accordion>

  <Accordion title="6. Slippage underestimation" icon="weight-scale">
    Backtesting assuming zero slippage on every order. Reported returns higher than reality, especially on illiquid symbols or large position sizes.

    **Symptom**: backtest claims `+30%` annual; live produces `+22%`. Difference is largely slippage on real fills.

    **Mitigation**: use a non-zero slippage parameter. For majors at moderate size, `0.05%` slippage is reasonable. For altcoins or large size, `0.2%` or more.
  </Accordion>

  <Accordion title="7. Insufficient sample size" icon="hashtag">
    A backtest with `<20` trades is not statistically meaningful. The result could be coincidence.

    **Symptom**: confident decision-making based on `5-10 trades`. Live performance diverges wildly from "expectations."

    **Mitigation**: aim for `>50 trades` in any backtest segment. Lengthen the window or pick a higher-frequency mode if you're not getting there.
  </Accordion>

  <Accordion title="8. Single-window testing" icon="calendar">
    Backtesting only on one historical window (e.g., recent 12 months). Strategy is regime-fit to that specific window, not validated for robustness.

    **Symptom**: strategy that worked in 2023 fails in 2026.

    **Mitigation**: test multiple windows: bull (e.g., 2020-21), bear (2022), chop (2023), recent. If the strategy survives all, you have evidence of robustness. If it fails on some, decide whether you can stomach those regimes.
  </Accordion>

  <Accordion title="9. Wrong fees / fee tier assumptions" icon="circle-info">
    Using "BNB-discounted Binance" fees when you don't actually have BNB top-up. Or using "VIP 4" fees when you're at VIP 0.

    **Mitigation**: be specific. Match the fee assumption to your actual operator state.
  </Accordion>

  <Accordion title="10. Not accounting for operator behavior" icon="user">
    Backtest assumes a perfectly disciplined operator who never deviates. Live operators panic, override, change settings, take vacations.

    **Symptom**: live performance is consistently worse than backtest because operator-induced deviations subtract from returns.

    **Mitigation**: simulate worst-case operator behavior. "What if I panic-close half my positions during a `-15%` drawdown?" Stress-test your psychology, not just your strategy.
  </Accordion>
</AccordionGroup>

## More subtle mistakes

<AccordionGroup>
  <Accordion title="11. Backtest data quality issues" icon="circle-question">
    Historical candle data may have gaps, anomalies, or rounding artifacts that bias the backtest.

    **Mitigation**: use venue-source historical data (the Backtester pulls from venues directly). Avoid third-party aggregated feeds that may have data quality problems.
  </Accordion>

  <Accordion title="12. Time-of-day mismatches" icon="clock-rotate-left">
    Backtest uses UTC timestamps; your live operation experiences your local timezone. Time-window conditions (e.g., "trade only during US market hours") need consistent timezone handling.

    **Mitigation**: be explicit about timezone assumptions in time-based conditions. Verify backtest and live use the same timezone reference.
  </Accordion>

  <Accordion title="13. Different exchange behavior than backtest assumes" icon="building-columns">
    Each exchange has its own quirks — partial fills, retry behavior, error codes. Backtests typically assume idealized exchange behavior.

    **Mitigation**: forward-test on the same venue you'll deploy live. Backtest predicts the strategy logic; forward-test catches venue-specific frictions.
  </Accordion>

  <Accordion title="14. Comparing strategies with different costs as if equivalent" icon="balance-scale">
    "BasicMode shows +25% annual; Tsl2Sell shows +30%." But BasicMode has 200 trades; Tsl2Sell has 8. After fees and slippage, the comparison shifts.

    **Mitigation**: compare strategies after fees and slippage are deducted. Trade-frequency-aware comparison.
  </Accordion>

  <Accordion title="15. Not running the full validation pipeline" icon="forward">
    Backtest → walk-forward → shadow → forward-test → scale up. Operators who skip steps end up paying tuition with real capital.

    **Mitigation**: discipline. Each step has its purpose.
  </Accordion>
</AccordionGroup>

## How to avoid these mistakes — the discipline

<Steps>
  <Step title="Define what 'good' looks like before running backtests">
    Decide what max drawdown you can stomach, what total return makes the strategy worth running, what win rate range is acceptable. **Before** you see backtest results.

    Defining criteria before testing prevents post-hoc rationalization.
  </Step>

  <Step title="Use realistic fees and slippage">
    Match your venue, your tier, your typical order size. Don't optimize away realistic frictions.
  </Step>

  <Step title="Test on multiple windows">
    Bear, chop, bull, recent. Same parameters across all windows. Look for regime robustness.
  </Step>

  <Step title="Walk-forward when tuning">
    If you're adjusting parameters, walk-forward catches curve-fitting. Don't peek at out-of-sample.
  </Step>

  <Step title="Major-symbol-only backtesting">
    Avoid survivorship bias. Test on `BTCUSDT`, `ETHUSDT`, `SOLUSDT`, etc.
  </Step>

  <Step title="Sample size matters">
    Aim for `>50 trades` per segment. Lengthen the window if you're not getting there.
  </Step>

  <Step title="Drawdown over total return">
    Focus on max drawdown more than total return. Total return is the headline; drawdown is what kills operators.
  </Step>

  <Step title="Forward-test on small live capital after backtest">
    Even after extensive backtesting, forward-test on `$1,500-$3,000` for 2-4 weeks before scaling up. Real fills, real frictions, real operator emotions.
  </Step>

  <Step title="Document everything">
    Backtest configurations, results, decisions, validation pipeline steps. Future-you will thank present-you.
  </Step>

  <Step title="Be honest about your psychology">
    A strategy that's mathematically optimal but causes you to panic-close during drawdowns is a strategy that's wrong for you. Match strategies to your actual stress tolerance, not to theoretical optimum.
  </Step>
</Steps>

## Best practices

<Tip>
  * ✅ **Define success criteria before testing** — prevents post-hoc rationalization.
  * ✅ **Realistic fees and slippage** — don't optimize away friction.
  * ✅ **Multi-window testing** — bear, chop, bull, recent.
  * ✅ **Walk-forward when tuning parameters** — catches curve-fitting.
  * ✅ **Aim for `>50 trades per segment`** — statistical meaningfulness.
  * ✅ **Read drawdown alongside total return** — never in isolation.
  * ✅ **Major symbols only** — avoid survivorship bias.
  * ✅ **Forward-test on small live capital** — full validation pipeline.
  * ✅ **Document the validation chain** — operator runbook entries.
  * ✅ **Be honest about your stress tolerance** — psychology matters.
  * ✅ **Don't trust single-window results** — robustness needs multiple regimes.
  * ✅ **Don't trust `>3.0` profit factors or Sharpe `>3`** — likely overfitting.
  * ✅ **Don't peek at out-of-sample data** during tuning — discipline is the value.
</Tip>

## What's next

<CardGroup cols={2}>
  <Card title="Why backtest" icon="circle-question" href="/backtesting/why-backtest">
    The fundamental motivation for backtesting.
  </Card>

  <Card title="Reading results" icon="chart-bar" href="/backtesting/reading-results">
    What each metric means.
  </Card>

  <Card title="Walk-forward" icon="timeline" href="/backtesting/walk-forward">
    The technique that catches curve-fitting.
  </Card>

  <Card title="Shadow mode" icon="masks-theater" href="/backtesting/shadow-mode">
    Forward-testing without real capital.
  </Card>

  <Card title="Backtester module" icon="flask" href="/modules/backtester">
    The module that runs your tests.
  </Card>

  <Card title="Risk management" icon="shield" href="/risk-management/overview">
    Risk discipline as the partner to backtesting.
  </Card>
</CardGroup>
