Latticework

Command Palette

Search for a command to run...

Quantitative Finance Fundamentals

Backtesting

20 min

Explanation

Backtesting simulates how a trading strategy would have performed on historical data — before risking real money on it. The moving average crossover is one of the oldest, simplest strategies: compute a short-window and long-window average of price, and treat the SHORT average crossing above the LONG average as a "buy" signal (recent prices are outpacing the longer trend — momentum is picking up).

def moving_average(prices, window):
    result = []
    for i in range(window - 1, len(prices)):
        avg = sum(prices[i - window + 1 : i + 1]) / window
        result.append(avg)
    return result

print(moving_average([10, 11, 12, 13, 14], 3))   # [11.0, 12.0, 13.0]
Try it

The short MA reacts to recent price moves faster than the long MA does -- that lag difference is exactly what a crossover strategy is trying to detect and trade on.

Loading editor…
Explanation

A crossover strategy generates a trading signal by comparing the two:

def sma_crossover_signal(prices, short_window, long_window):
    short_ma = sum(prices[-short_window:]) / short_window
    long_ma = sum(prices[-long_window:]) / long_window
    if short_ma > long_ma:
        return 1    # "golden cross" -- bullish signal
    elif short_ma < long_ma:
        return -1   # "death cross" -- bearish signal
    return 0

Backtesting this kind of strategy across years of historical data tells you how it WOULD have performed — but a strategy that looks great on history isn't automatically great going forward. The real risk is overfitting: tuning window sizes and rules so precisely to historical noise that the strategy has essentially memorized the past rather than capturing a real, persistent pattern — the same overfitting risk you'll see again in the Model Evaluation course, applied to trading instead of machine learning.

Exercise

Write `moving_average(prices, window)`: return a list of simple moving averages — one for every position where a full `window` of prices is available — each rounded to 4 decimals.

Exercise

Write `sma_crossover_signal(prices, short_window, long_window)`: compute the short-window and long-window moving averages over the MOST RECENT prices, and return 1 if short > long, -1 if short < long, 0 if equal.

Quiz

What is the main danger of 'overfitting' a backtested trading strategy?

Checkpoint

You can compute moving averages and implement a basic crossover trading signal, and understand backtesting's central risk: overfitting a strategy to historical noise.