⚠ Trading involves significant risk of loss. Everything on this site is for education only and is not financial advice.
Lesson 4 of 12 · Free

Building a simple backtest in a spreadsheet

Build a complete, column-by-column backtest of a moving-average rule in a spreadsheet and check it for errors.

Author: Moustafa HijaziContent reviewed: 2026-10-305 min readSelf-study course

What you will learn

  • The standard column layout of a spreadsheet backtest.
  • The formulas for signal, position, strategy return, equity curve and drawdown.
  • How to shift the position by one row to avoid look-ahead bias.
  • Five checks that catch most spreadsheet errors.

Explanation

A spreadsheet backtest is slow for large tests, but every number is visible, which makes it the best place to learn. You will test the moving-average rule from lesson 2, here with a 3-month simple moving average (SMA) so that the table stays short.

The column layout

Row 1 holds the headings; month 1 is in row 2, so month m is in row m+1. Cell K1 holds the cost per position change (here 0.2%).

Column Content Formula (row 5 = month 4)
A Month (or date) data
B Adjusted close data
C 3-month SMA =AVERAGE(B3:B5)
D Signal at the close (1 = invested, 0 = cash; tie keeps the previous signal) =IF(B5>C5,1,IF(B5<C5,0,D4))
E Position held during the month =D4
F Asset return =B5/B4-1
G Strategy return after costs =E5*F5-IF(E5<>E4,$K$1,0)
H Equity (start 100) =H4*(1+G5)
I Running peak =MAX($H$4:H5)
J Drawdown =H5/I5-1

In German-language spreadsheet versions, function names and separators differ, for example MITTELWERT instead of AVERAGE, WENN instead of IF, and semicolons instead of commas.

The key idea: the one-row shift

Column E copies the signal from the previous row. The signal is known only at the close of month m, so it can earn the return of month m+1 at the earliest. If you multiply the signal of the same row by the return of the same row, the test "knows" the month's result before it decides. This single mistake makes many spreadsheet backtests look far too good.

Equity and drawdown

The equity curve is the account value over time, here as an index starting at 100. Returns are compounded: each month multiplies the previous value. The drawdown is the percentage fall from the highest equity reached so far (the running peak); detailed drawdown and recovery maths were covered in the course "Risk & Trade Management".

Worked example

Hypothetical example: monthly closes €100, €104, €108, €106, €101, €97, €99, €104, €109, €112. Cost: 0.2% per position change (a simple stand-in for spread and fees, lesson 8). Taxes and cash interest are excluded. The equity starts at 100 at the close of month 3, the first month with an SMA; the position before that is 0.

Month Close SMA Signal Position Asset return Strategy return Equity Drawdown
3 108 104.00 1 0 – – 100.00 0.00%
4 106 106.00 1 (tie) 1 −1.85% −2.05% 97.95 −2.05%
5 101 105.00 0 1 −4.72% −4.72% 93.33 −6.67%
6 97 101.33 0 0 −3.96% −0.20% 93.14 −6.86%
7 99 99.00 0 (tie) 0 +2.06% 0.00% 93.14 −6.86%
8 104 100.00 1 0 +5.05% 0.00% 93.14 −6.86%
9 109 104.00 1 1 +4.81% +4.61% 97.43 −2.57%
10 112 108.33 1 1 +2.75% +2.75% 100.11 0.00%

Checks for three rows:

  • Month 4: position 1 (from month 3), entry cost applies: −1.85% − 0.20% = −2.05%. Equity: 100 × (1 − 0.0205) = 97.95.
  • Month 6: position changes to 0, exit cost only: −0.20%. Equity: 93.33 × 0.998 ≈ 93.14. Drawdown: 93.14 ÷ 100 − 1 = −6.86%.
  • Month 9: re-entry: +4.81% − 0.20% = +4.61%. Equity: 93.14 × 1.0461 ≈ 97.43.

Result: equity 100.11 (+0.11%) with 3 position changes and a maximum drawdown of −6.86%. Buy-and-hold from month 3 to 10: €112 ÷ €108 − 1 = +3.70%. With the simpler formula =IF(B5>C5,1,0), the tie in month 4 would have meant exiting one month earlier, and the result would have been about +5.07%. One edge case changed the outcome by about 5 percentage points. Eight months prove nothing about the rule; the purpose here is the mechanics.

Common mistake

Using the same row's signal and returnWriting =D5*F5 instead of =E5*F5 lets the strategy earn the return of the month in which the signal was formed. Always ask: "Was this cell known before the return it is multiplied with?"

Practice activity

Five checks for any spreadsheet backtest. Apply them on paper to the table above and write down what you would see if the test were correct.

  1. Count position changes and compare with the costs charged.
  2. Recalculate one random row by hand.
  3. Set the cost to 0 and the position to 1 everywhere: the result must equal buy-and-hold.
  4. Check that the first position row uses a signal from an earlier row.
  5. Check that the drawdown is never positive.
Show solution

1. Changes in months 4, 6 and 9 = 3; costs charged 3 × 0.20% = 0.60% in total. Matches.

2. Example month 5: position 1 × (€101 ÷ €106 − 1) = −4.72%, no change, so no cost; 97.95 × 0.9528 ≈ 93.33. Matches.

3. With position 1 and no cost, equity becomes 100 × 112 ÷ 108 ≈ 103.70, the buy-and-hold result of +3.70%.

4. Month 4's position (1) comes from month 3's signal. Correct.

5. All drawdowns are 0.00% or negative. Correct.

Limitations: the table assumes trading at the month-end close at a fixed cost; real fills happen at the next open with variable spreads and slippage (lesson 8).

Key takeaways

  • Use separate columns for signal and position, with the position shifted one row down.
  • Compound returns into an equity curve and calculate drawdown from the running peak.
  • Charge costs whenever the position changes, not every month.
  • Run the five checks before trusting any spreadsheet result.

Next step

In the next lesson you will turn an equity curve like this one into standard performance metrics: CAGR, drawdown, Sharpe ratio and profit factor.

Self-check

Answer the questions, then check your answers. You can retry as often as you like.

1. In a spreadsheet backtest, why does the position column copy the signal from the previous row?

2. Hypothetical example: equity is 120 at its peak and later falls to 102. What is the drawdown?

3. You set costs to zero and the position to 1 in every row, but the final equity differs from buy-and-hold. What does this tell you?

Automatic self-check for your own revision. Your answers are checked in your browser and are not seen or assessed by us. It is not an exam and not a qualification.

Your progress

“Complete” only means you marked the lesson as done. It is not a test of your understanding. Progress and notes are saved only in this browser on this device — not in an account.