6.2.7Backtesting Frameworks

Understand in-sample vs out-of-sample testing

2,228 words10 min readdifficulty · medium1 backlinks

What are In-Sample and Out-of-Sample?

WHY this split? Because strategies are built by trial-and-error. Every tweak you make to improve in-sample performance risks fitting random noise. Out-of-sample is your reality check: does the edge persist when the strategy faces new data?

WHAT happens without it? You get curve-fitting: a strategy with 15 parameters, 80% win-rate in-sample, that loses money the moment you trade it live. The classic quant graveyard.

HOW to split? Common approaches:

  1. Chronological split: First 70% = IS, last 30% = OOS (respects time-series nature)
  2. Walk-forward: Rolling IS/OOS windows (more robust, covered in advanced backtesting)
  3. Leave-out segments: Hold out specific market regimes (e.g., 2008 crisis) as OOS

The Math: Why Overfitting Happens

Let's derive why more parameters → higher overfitting risk.

Setup: You have NN data points (e.g., daily returns). You fit a model with pp parameters.

Degrees of Freedom: The model "uses up" pp degrees of freedom to fit data. Remaining degrees of freedom for genuine signal: DoF=Np\text{DoF} = N - p.

Signal vs Noise: Assume returns = signal + noise, rt=st+ϵtr_t = s_t + \epsilon_t, where ϵtN(0,σ2)\epsilon_t \sim \mathcal{N}(0, \sigma^2) is random.

When you optimize pp parameters over NN points:

  • Expected in-sample error: Your optimizer finds the best fit to st+ϵts_t + \epsilon_t, including fitting some noise.
  • Expected out-of-sample error: OS data has different noise ϵt\epsilon_t', so the noise-fitted parts fail.

Example numbers:

  • IS period: 252 days (1 year), N=252N = 252
  • Strategy has 10 parameters (moving average lengths, thresholds, stop-losses, etc.), p=10p = 10
  • Ratio: p/N=10/2524%p/N = 10/252 \approx 4\%. Borderline acceptable.
  • If p=50p = 50, ratio = 20% → severe overfitting risk. You're fitting noise.

Worked Example: Moving Average Crossover

Strategy: Buy when 20-day MA crosses above 50-day MA. Sell when it crosses below.

Step 1: In-Sample Optimization

You have 5 years of SPY data (2017-2021, ~1260 days). You test all combinations:

  • Short MA: 10, 15, 20, 25, 30 days
  • Long MA: 40, 50, 60, 70, 80 days

That's 5×5=255 \times 5 = 25 combinations (25 parameters tested).

Result: Best IS combo is (15, 70) with 18% annual return.

Why this step? You're searching for the parameter set that maximizes IS performance. This is standard optimization.

Step 2: Out-of-Sample Test

Reserve 2022-2023 (~500 days) as OOS. You never touched this data during optimization.

Run the (15, 70) strategy on OS data.

Result: OS return is 3% annualized.

Why the drop? The (15, 70) combo likely exploited random SPY fluctuations in 2017-2021 that didn't repeat in 2022-2023. Classic overfitting.

HOW to interpret?

Metric In-Sample Out-of-Sample Gap
Annual Return 18% 3% 15%
Sharpe Ratio 1.2 0.3 0.9

Large gap = overfitting. The strategy has no real edge; it memorized IS noise.

What if OS was similar to IS? Say OS return = 14%. Gap = 4%. Still some overfitting, but the edge is real. A 20-30% degradation is typical (parameters are never perfectly tuned). A 80% collapse (18% → 3%) screams overfitting.


Worked Example 2: Mean Reversion with Multiple Filters

Strategy: Buy when RSI < 30 AND price < 200-day MA AND volume > 1.5× average.

Parameters:

  • RSI threshold: θ1{20,25,30,35}\theta_1 \in \{20, 25, 30, 35\}
  • MA length: θ2{150,200,250}\theta_2 \in \{150, 200, 250\}
  • Volume multiplier: θ3{1.2,1.5,2.0}\theta_3 \in \{1.2, 1.5, 2.0\}

Total combinations: 4×3=364 \times 3 = 36 parameter sets.

Data: 10 years AAPL (2013-2022), split 70/30 → IS: 2013-2019 (7 years), OOS: 2020-2022 (3 years).

Step 1: In-Sample Grid Search

Test all 36 combos. Best IS: RSI=25, MA=150, Vol=2.0 → 22% annual return, Sharpe 1.5.

Why this step? You're doing hyperparameter optimization (aka parameter tuning). Every backtest platform does this.

Step 2: Out-of-Sample Reality Check

Run (25, 150, 2.0) on OOS 2020-2022.

Result: 8% return, Sharpe 0.6.

Why the drop?

  • 2020 had COVID crash (regime change)
  • The (25, 150, 2.0) combo was tuned to 2013-2019's "normal" volatility
  • Volume spike behavior changed in pandemic trading

HOW to fix?

  1. Walk-forward testing (re-optimize every year using a rolling IS window)
  2. Regularization: Penalize complex strategies (fewer parameters)
  3. Ensemble: Average multiple parameter sets instead of picking the "best"

Key insight: Even with a 70/30 split, if OS includes a regime shift (2020 pandemic), your strategy will struggle. OS must be representative and unseen.


Common Mistakes (Steel-man)




Practical Implementation

HOW to split in Python (pandas):

import pandas as pd
 
df = pd.read_csv('AAPL_daily.csv', parse_dates=['Date'])
df = df.sort_values('Date')
 
split_date = '2020-01-01'
is_data = df['Date'] < split_date]  # In-sample
oos_data = df[df['Date'] >= split_date]  # Out-of-sample
 
print(f"IS: {len(is_data)} days, OOS: {len(oos_data)} days")

WHY chronological? Time-series data has temporal dependencies. Shuffling (like in ML) breaks this—you'd be training on "future" data to predict the "past." Chronological split respects causality.

WHAT about walk-forward?

# Pseudo-code for walk-forward
results = []
for start in range(0, len(df), 252):  # Roll every year
    is_window = df[start : start+756]  # 3 years IS
    oos_window = df[start+756 : start+1008]  # 1 year OOS
    
    best_params = optimize(strategy, is_window)
    oos_perf = backtest(strategy, oos_window, best_params)
    results.append(oos_perf)
 
avg_oos = np.mean(results)  # Aggregate OOS performance

WHY better? Multiple OOS periods reduce luck. If strategy works across 5 OS windows, it's more robust than one lucky OS period.


The 80/20 Core

20% of concepts that explain 80% of IS/OOS testing:

  1. IS = where you optimize, OOS = where you validate. Never mix them.
  2. Overfitting grows with p/Np/N ratio (parameters / data points). Keep p/N<5%p/N < 5\%.
  3. Large IS/OOS performance gap (>40% drop) = overfitting. Discard the strategy.
  4. Walk-forward > single split for robust validation (multiple OOS tests).

If you remember these four, you'll avoid 80% of backtesting disasters.


Diagram

What the diagram shows:

  • Top panel: Equity curve in IS (blue) vs OOS (red). Notice IS is smooth (overfit), OOS is noisy (reality).
  • Bottom panel: Parameter sensitivity. Optimal param in IS (green dot) gives poor OOS performance (red dot). Overfit.

Recall Feynman Technique: Explain to a 12-year-old

Imagine you're studying for a test. You get 100 practice problems (in-sample). You try every trick, memorize patterns, and score 95%. But then real test (out-of-sample) has different problems—similar, but not identical. You only score 60%. Why? You memorized the practice problems instead of learning the underlying math. Trading strategies are the same. In-sample is your practice set where you tune the strategy. Out-of-sample is the real test with new data. If your strategy scores 95% in-sample but 60% out-of-sample, it memorized random noise (like memorizing practice problems word-for-word). A good strategy learns the real patterns and scores 80% on both—not perfect, but consistent.

The rule: Never look at the out-of-sample "test answers" while practicing. Once you peek, you can't un-see it, and your practice becomes contaminated.


Concept Map

split into

reserves

used to

risks

fits

validates

fails on

increases

decreases

widens

includes

applied to

Historical Data

In-Sample / Training Set

Out-of-Sample / Test Set

Develop and Optimize Strategy

Overfitting / Curve-Fitting

Random Noise not Signal

Does Edge Generalize?

More Parameters p

Overfit Risk ~ p over N

More Data N

IS vs OOS Gap

Split Methods

Chronological, Walk-Forward, Leave-Out

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Dekho yaar, is note ka core idea bahut simple hai — jab aap koi trading strategy banate ho, toh aap use kisi purane data par test karte ho. Lekin agar aap wahi data baar-baar use karke apni strategy ko tweak karte raho, toh strategy uss data ke patterns ko "yaad" kar leti hai, seekhti nahi. Ye bilkul waisa hai jaise aap 100 chess games ratta maar lo aur khud ko grandmaster samajh lo — asli test toh nayi game mein hota hai na? Isiliye hum data ko do parts mein todte hain: in-sample (jahan aap strategy banate aur tune karte ho, yani practice set) aur out-of-sample (fresh, untouched data jahan aap check karte ho ki strategy naye data par bhi kaam karti hai ya nahi — yani exam).

Ab why-it-matters: agar aapki strategy in-sample par 80% win-rate deti hai but out-of-sample par paisa doobo deti hai, toh matlab aapne signal nahi, sirf noise (random shor) ko fit kar liya — isko overfitting ya curve-fitting kehte hain. Aur ek zaroori intuition yaad rakhna: overfitting ka risk roughly p/N ke proportional hota hai, jahan p = number of parameters aur N = data points. Iska matlab jitne zyada "knobs" (moving averages, thresholds, stop-losses) aap add karoge, aur jitna kam data hoga, utna zyada aap noise ko fit karoge. Jaise 252 din ke data par 10 parameters (4%) thik hai, lekin 50 parameters (20%) toh disaster hai.

Toh bhai, seedhi baat — real trading mein paisa isi galti se doobta hai. Log apni strategy ko in-sample par itna chamka dete hain ki wo "perfect" lagti hai, phir live market mein utar dete hain aur loss ho jaata hai. Isiliye hamesha thoda data (jaise last 30%, ya 2008 crisis wala period) alag rakho, use kabhi mat chhuo development ke time, aur end mein usi par apni strategy ka asli imtihaan lo. Yahi discipline aapko quant graveyard se bachaata hai.

Test yourself — Backtesting Frameworks

Connections