Spreadsheet Backtesting Framework: Build a Custom Excel Backtest
How to Build a Spreadsheet Backtesting Framework: Full Control, No Code
A spreadsheet backtest is the middle path: more control than charting software, faster than manual testing, and no coding required. You input historical OHLC data (open, high, low, close) and volume into rows, write formulas to detect entry signals, calculate position size and profit-loss, and watch the results compile automatically. A well-built spreadsheet backtest teaches you the mechanics of position management, drawdown, and equity curves while giving you complete transparency into every calculation.
This approach works best for swing traders, position traders, and beginners. Day traders and high-frequency traders need faster tools (the volume of data is overwhelming in Excel). But for testing breakout strategies, moving-average crossovers, support-and-resistance bounces, and other medium-term rules, a spreadsheet is powerful and educational.
Quick definition: A spreadsheet backtesting framework is an Excel or Google Sheets model where you input historical prices, write formulas to calculate entry signals and position management, and measure profit, loss, drawdown, and equity automatically.
Key takeaways
- A spreadsheet backtest requires historical OHLC data, a signal column (entry and exit rules), a position column (tracking open trades), and P&L columns.
- Use IF and conditional formulas to code your strategy logic: "If RSI <30, entry = 1; if price >= stop-loss, exit = 1."
- Calculate position size using your risk management rules: fixed dollar amount, percentage of account, or dynamic scaling based on volatility.
- Track cumulative equity (starting capital plus running profit/loss) to visualize performance and measure drawdown.
- A spreadsheet is more transparent and controllable than charting software but slower than automated code and impractical for testing thousands of variations.
Anatomy of a spreadsheet backtest
A minimal spreadsheet has these columns:
- Date and OHLC + Volume: Historical prices from a data provider (Yahoo Finance, Quandl, your broker's export).
- Technical indicators: 20-day MA, 50-day MA, RSI, MACD, volume average, or any rule you need.
- Entry signal: A 1 or 0 (or TRUE/FALSE) for whether your entry rule is met.
- Exit signal: A 1 or 0 for whether your exit rule is met.
- Position status: Are you in a trade? If so, what's your entry price, entry date, position size?
- Stop-loss and target: Where will you exit if the trade goes wrong or right?
- Current profit/loss: If in a trade, what's the mark-to-market P&L at today's close?
- Trade realized P&L: When the exit signal triggers, what's the actual profit or loss?
- Cumulative equity: Starting capital plus all closed trades' profit/loss.
- Drawdown: Peak-to-trough decline in equity.
A complete spreadsheet might have 20–30 columns and 1,000–2,000 rows (one per day over 4–8 years). Don't be intimidated; you'll build it column by column.
Step-by-step: Build a simple moving-average strategy backtest
Objective: Test a simple rule: "Buy when the close breaks above the 50-day moving average. Sell when the close drops below the 50-day MA or loss hits 10%, whichever first."
Starting capital: $10,000. Position size: 1 share per $100 of capital (starting at 100 shares). Slippage/commission: $10 per trade.
Step 1: Import historical data
In Excel or Google Sheets, import daily OHLC data for your symbol. Create columns:
- A: Date
- B: Open
- C: High
- D: Low
- E: Close
- F: Volume
For example, row 2 might be: 2022-01-03, 180.5, 182.1, 179.8, 181.3, 40000000
You can download data from Yahoo Finance (export as CSV) or your broker. For the backtest to start, you need at least 50 days of prior data to calculate the first 50-day moving average (column G).
Step 2: Calculate the 50-day moving average
In column G (starting at row 51, after 50 days of data):
=AVERAGE(E2:E51)
Copy this formula down for all rows. Each cell calculates the average of the prior 50 closes.
Step 3: Create entry and exit signals
In column H, create your entry signal:
=IF(E2>G2, 1, 0)
This returns 1 if today's close is above the 50-day MA, 0 otherwise.
In column I, create your exit signal:
=IF(E2<G2, 1, 0)
This returns 1 if today's close is below the 50-day MA, 0 otherwise.
Step 4: Track position status
This is trickier. You need to know: are you currently in a position? If so, since when? At what price?
In column J (position status), use a formula like:
=IF(H2=1, 1, IF(I2=1 AND J1=1, 0, J1))
Logic: If today's entry signal is 1, position = 1 (entering). If today's exit signal is 1 and you were in a position (J1=1), position = 0 (exiting). Otherwise, stay in the prior position state. Start J1 with 0 (no position before the backtest begins).
Step 5: Record entry price and date
In column K (entry price), use:
=IF(H2=1 AND J1=0, E2, IF(J2=1, K1, 0))
Logic: If today's entry signal triggered and you weren't in a position, entry price = today's close. If you're currently in a position, keep the prior entry price. If you're not in a position, entry price = 0.
Step 6: Calculate position size
In column L (position size in shares), use:
=IF(J2=1 AND K2<>0, ROUND(10000/K2, 0), 0)
This buys 100 shares when capital is $10,000 and entry price is $100. If capital grows, you can adjust this to scale position size.
Step 7: Calculate stop-loss
In column M (stop price), use:
=IF(J2=1, K2*0.9, 0)
This sets the stop-loss 10% below entry price.
Step 8: Calculate daily profit/loss
In column N (current P&L), use:
=IF(J2=1, (E2-K2)*L2-10, 0)
Logic: If you're in a position, multiply (today's close - entry price) by position size, then subtract $10 for commission/slippage.
Step 9: Record closed-trade P&L
In column O (trade result), use:
=IF(I2=1 AND J1=1, (E2-K1)*L1-10, 0)
Logic: If exit signal triggered and you were in a position, calculate profit = (exit price - entry price) × position size - $10.
Step 10: Track cumulative equity
In column P (cumulative equity), use:
=10000+SUM($O$2:O2)
This tracks your account balance: starting capital plus the sum of all closed-trade results up to the current row.
Step 11: Calculate drawdown
In column Q (drawdown), use:
=MIN(P2:P2)-MAX(P$2:P1)
This calculates the peak-to-trough decline: the worst it's been minus the best it was. You'll need to adjust the formula slightly to avoid errors in early rows, but the logic is: max_historical_equity - current_equity.
Step 12: Review results
At the bottom of your spreadsheet, create summary statistics:
- Total profit/loss:
=P[last_row] - 10000 - Total trades:
=COUNTIF(O:O, "<>0") - Winning trades:
=COUNTIF(O:O, ">0") - Losing trades:
=COUNTIF(O:O, "<0") - Win rate:
=winning_trades / total_trades - Average win:
=SUMIF(O:O, ">0") / winning_trades - Average loss:
=SUMIF(O:O, "<0") / losing_trades - Profit factor:
=ABS(SUMIF(O:O, ">0") / SUMIF(O:O, "<0")) - Maximum drawdown:
=MIN(Q:Q)
Step 13: Plot equity curve
Select column P (cumulative equity) and create a line chart. This shows visually how your account would have grown or declined over the backtest period. You can see when the strategy was in drawdown, how long recovery took, and whether the uptrend is consistent.
Common formulas and patterns
Moving average:
=AVERAGE(E2:E51) [50-day MA]
=AVERAGE(E2:E21) [20-day MA]
Exponential moving average:
=EMA(E2:E51, 50) [Google Sheets only; Excel requires custom formula]
RSI (14-period):
=RSI(E2:E15, 14) [Google Sheets; Excel requires complex formula]
MACD (12/26/9):
=12-day EMA - 26-day EMA [requires EMA calculations]
Crossover detection (MA1 crosses above MA2):
=IF(AND(G2>H2, G1<=H1), 1, 0) [if MA1 is now above and was below or equal]
Volatility-adjusted position size:
=ROUND(10000 * (account_risk / (stop_loss_percentage * entry_price)), 0)
Example: A complete spreadsheet backtest
Imagine you test on Apple (AAPL) from January 2020 to December 2024 (5 years, ~1,250 trading days). Your spreadsheet has 1,260 rows (including header) and 17 columns (A–Q as above).
Results:
- Total trades: 34
- Wins: 20, losses: 14
- Win rate: 58.8%
- Total profit: $4,230
- Total loss: $1,890
- Net profit: $2,340 (23.4% return over 5 years)
- Maximum drawdown: -$1,280 (or -12.8%)
- Profit factor: 2.24
The equity curve shows steady growth with drawdowns in March 2020 and December 2022, but recovery within 2–3 months each time.
You also note: "The strategy works well in trending markets but falters in consolidation periods. In 2020–2021 (bull market), it captured strong uptrends. In 2022 (bear + range), it did fine but with shorter hold times. In 2023–2024 (mixed), results were mixed."
This insight guides your next step: should you add a trend filter to avoid chop? Or accept that the strategy works across regimes?
Decision tree
Advantages and limitations
Advantages:
- Full transparency: you see every calculation, every entry, every exit.
- No coding required: formulas are simple IF statements and AVERAGE functions.
- Flexibility: you can adjust rules on the fly and see results instantly.
- Educational: building the spreadsheet forces you to think through every aspect of your strategy.
Limitations:
- Slow for large datasets: testing thousands of trades or high-frequency data is unwieldy.
- Formula complexity grows quickly: testing 10 different entry/exit combinations means 10 separate sets of formulas, which is tedious.
- Limited statistical tools: advanced metrics like Sharpe ratio, recovery factor, and win/loss ratio require custom formulas.
- Not suitable for optimization: if you want to test 100 variations of your strategy (MA period 20–120), you'd need 100 separate copies of your spreadsheet.
Real-world example: A dividend stock-trading spreadsheet
A trader backtested a dividend-capture strategy: "Buy dividend-paying stocks 30 days before ex-dividend date, hold through the ex-date, sell 5 days after. Track dividend income and capital gains."
She built a spreadsheet with:
- Column for dividend amount and ex-date (obtained from finviz.com)
- Entry signal: today's date = 30 days before ex-date
- Exit signal: today's date = 5 days after ex-date
- P&L: (sale price - purchase price) × shares + dividend income - commissions
Backtesting on 12 dividend stocks over 2023–2024:
- Total trades: 24
- Average holding period: 35 days
- Average return per trade: 2.3% (capital gain + dividend)
- Total profit: $7,890
- Maximum drawdown: -$980 (one trade during market volatility)
The spreadsheet's transparency revealed: "Stocks that cut dividends between ex-date and payout caused unexpected losses. I should screen for dividend-cut risk." This insight shaped her future trading.
Summary
A spreadsheet backtesting framework gives you full control and transparency without coding. Import historical OHLC data, calculate technical indicators, write IF formulas to detect entry and exit signals, and track position management, profit-loss, and equity automatically. Build summary statistics (win rate, average win, profit factor) and plot an equity curve to visualize performance. Spreadsheet backtests are ideal for swing traders and position traders testing medium-term strategies on daily data. The process is slow for thousands of trades and impractical for parameter optimization, but it's educational and flexible. Every trader should build at least one spreadsheet backtest to understand the mechanics of position sizing, drawdown, and equity curves.
Next
Ready to scale your testing? Learn Backtesting Software Platforms and discover dedicated platforms that test thousands of variations in seconds.