Search the site

What are you looking for?

Enter a broker, tool or topic.

Orders & execution

Forex Backtesting: How to Test a Strategy Without Lookahead

Forex backtesting applies explicit trading rules to past prices and records the trades those rules would have produced under stated execution assumptions. A useful test makes its timing, data and costs visible. It does not establish what a broker would have filled or what a strategy will earn next.

Author · Editor

Reviewed

Parallel pale stone panels with a teal-framed glass panel in front and a smaller amber panel between the stone panels.
Follow a signal through the next tradable event

The essentials

  1. A signal can use a completed bar only after that bar closes. Execution must happen at a subsequent event allowed by the test.

  2. Spread, slippage and commission need a consistent accounting basis. Costs already included in fills must not be deducted again.

  3. A historical holdout loses its independence when its results influence further decisions. The fictional replay below is a teaching example, not validation.

What is forex backtesting?

Backtesting is a reconstruction: take a fixed rule, walk forward through available observations, and record decisions, assumed fills and results. For a forex strategy, that means defining the currency pair, price data, position size, entries, exits and transaction costs. The question is what those rules produced under that model, not whether attractive trades can be found afterward.

A manual test can do this with a chart replay and a ledger. An automated test delegates the same sequence to software. Automation makes repetition easier; it does not repair a rule that quietly uses future prices or a fill assumption the available data cannot support.

Imagine checking only whether price eventually reached a target. That leaves unanswered whether a stop was reached first, which side of the quote was tradable, and whether the signal existed at entry. A credible test records these decisions before interpreting its final number.

Keep three questions separate: what the rule observed, what the model assumed could execute, and what the resulting ledger contains.

Define the rules before looking at the result

Write a short specification that another person could follow without asking which trades you liked. “Buy when momentum improves” is not enough. State which prices define momentum, when they become available, and what happens when conditions conflict. Use a dated version so an amended rule does not silently replace the one originally tested.

  • Instrument and observations: symbol, timeframe, trading hours, time zone and permitted missing-data treatment.
  • Entry and exit: exact conditions, signal timing, eligible fill event and position state.
  • Sizing: fixed units or a fully specified sizing rule, including whether existing positions can be increased.
  • Execution and costs: price side, spread, commission, slippage and any overnight financing.
  • Boundaries: indicator warm-up, treatment of open positions and signals at the final observation.

The replay uses a deliberately simple, long-only rule. After each completed five-minute bar, compare its close with the simple average of the latest three closes, including that just-closed bar. If flat and close is above SMA3, queue a buy for the next bar’s open. If long and close is below SMA3, queue an exit for the next open. Equality changes nothing. A long position stays one position when another above-average close arrives.

This is an above/below rule, not a crossover requirement and not a strategy recommendation. Its position is always 10,000 EUR. Real research may use different rules, but changing several of them after seeing results creates a new experiment. The trading plan template helps separate the current specification from proposed revisions.

Choose data that can support the execution model

Start with the question the data can answer. An OHLC bar records open, high, low and close; those four values do not reveal every intermediate price or the order in which the high and low occurred. If both a stop and a target lie inside the same bar, the bar alone usually cannot decide which came first. Here midpoint means (Bid + Ask) / 2 at a given instant. SMA3 is the average of the midpoint closing prices of three consecutive bars.

Data or setting

What to establish before testing

Bid, Ask, midpoint or Last

Identify the recorded price basis. A midpoint is not itself a buy or sell quote.

Bars versus ticks

Match the resolution to the order logic. Do not invent a precise intrabar path from four prices.

Timestamps and sessions

Record the time zone, bar boundaries, weekend gaps and missing intervals.

Symbol specification

Check price increments, contract size, profit currency and the meaning of the quoted spread.

Scroll sideways to compare all columns ↔

The MetaTrader 5 documentation on ticks explains why chart prices and execution prices must be distinguished: buys and sells use different quote sides, while available charts need not display both. For a price-sensitive rule, that distinction can change whether an order qualifies and what it earns.

“Real ticks” also deserves a data check. The MQL5 testing documentation describes circumstances in which the tester generates ticks when real tick records are absent or inconsistent. Record the selected mode and investigate coverage warnings; a mode label alone does not describe every observation used.

Our replay contains 36 fictional EURUSD midpoint bars, five minutes apart, within one invented intraday session. They are not downloaded market history. There are no stop, limit or target orders to resolve inside a bar. The example teaches event order and cost accounting; it cannot tell you whether an SMA rule works on EURUSD.

Follow a signal through the next tradable event

Try it yourself

Replay a backtest, one decision at a time

Follow a fixed rule through 36 fictional five-minute EUR/USD bars. Their midpoint prices sit halfway between Bid and Ask. Change the assumed costs, then inspect the signal, the next opening price and the resulting ledger.

Illustrative data only. These bars are invented, not market history or evidence that this rule works.

The rule stays fixed

After a bar closes, compare its midpoint close with the average of that close and the previous two closes. Above SMA3: enter if flat. Below SMA3: exit if long. Equality leaves the position unchanged. Each position is 10,000 EUR; results are in USD.

A decision can fill only at the next opening inside the selected window. Repeated long signals do not add quantity. There are no short positions, stops, limits, overnight financing or parameter optimization.

Set the execution assumptions
0–20 pips. Half is added to a buy and half deducted from a sell. In this EUR/USD example, 1 pip = 0.0001 USD per EUR.
0–10 pips on each fill. This example assumes only adverse slippage.
0–100 USD for each execution of the whole 10,000 EUR position; not a per-lot tariff.
Each window starts flat. Only earlier closes warm up SMA3; warmup creates no trades or fees.
Cost examples

Bar 36 of the selected window (1–36) · 11:55

Reconcile the result

Closed trades · net P/L
-3.70 USD
Open position · marked P/L after its entry commission
16.25 USD
Total model P/L
12.55 USD

Closed net -3.70 USD + open marked net 16.25 USD = total 12.55 USD.

Closed positions: 4. Executions so far: 9.

The open long is marked at the last midpoint close minus half the assumed spread. Its paid entry commission is deducted once. No future exit commission or exit slippage is charged to this mark.

Sell signal at bar 36: still pending. The position remains open; no exit fee has been charged. There is no later opening inside this window, so the final signal is never filled here.

Where the costs appear
Closed P/L from the fill prices
-0.90 USD
Commissions on closed positions
2.80 USD
Open marked P/L before its entry commission
16.60 USD
Paid commission on the open entry
0.35 USD
All commissions paid so far
3.15 USD
Spread effect already included in fills
5.40 USD
Adverse slippage already included in fills
1.80 USD
Additional half-spread in the open mark
0.60 USD

Spread and slippage are already inside the fill prices; do not deduct these displayed effects again. Commission is the separate cash charge. The open mark is not an executed exit.

Early and late are separate temporal examples, not out-of-sample validation or a live forward test. The early open position is not silently closed or carried into the late window. Do not add their P/L as one continuous account history.

Closed midpoint, SMA3 and executions

Only bars reached by the replay are shown. The solid line joins midpoint closes; the dashed line is SMA3. Up and down triangles identify hypothetical buy and sell fills at that bar’s opening. The vertical axis is USD per EUR.

USD per EUR

Five-minute bar

  • Midpoint close
  • SMA3
  • Buy fill at open
  • Sell fill at open

Signal → next open → position

Read each row in time order: execute the preceding decision at the open, then evaluate the current close. A chart line between bars does not create an intermediate price or fill.

Signal → next open → position
Bar · session clockAt this openMidpoint close / SMA3At this closeAfter the closeTotal model P/L
109:00No execution1.10000—Fewer than three closes: no decisionFlat0.00 USD
209:05No execution1.10020—Fewer than three closes: no decisionFlat0.00 USD
309:10No execution1.100401.10020Above SMA3: buy at next openFlat0.00 USD
409:15Buy 1.10058; signal from bar 31.100801.1004667Above SMA3: keep the long; no new orderLong 10,000 EUR1.25 USD
509:20No execution1.101201.10080Above SMA3: keep the long; no new orderLong 10,000 EUR5.25 USD
609:25No execution1.101601.10120Above SMA3: keep the long; no new orderLong 10,000 EUR9.25 USD
709:30No execution1.101801.1015333Above SMA3: keep the long; no new orderLong 10,000 EUR11.25 USD
809:35No execution1.101601.1016667Below SMA3: sell at next openLong 10,000 EUR9.25 USD
909:40Sell 1.10142; signal from bar 81.101301.1015667Below SMA3: remain flatFlat7.70 USD
1009:45No execution1.101001.10130Below SMA3: remain flatFlat7.70 USD
1109:50No execution1.100801.1010333Below SMA3: remain flatFlat7.70 USD
1209:55No execution1.101001.1009333Above SMA3: buy at next openFlat7.70 USD
1310:00Buy 1.10118; signal from bar 121.101201.10100Above SMA3: keep the long; no new orderLong 10,000 EUR6.95 USD
1410:05No execution1.101001.1010667Below SMA3: sell at next openLong 10,000 EUR4.95 USD
1510:10Sell 1.10072; signal from bar 141.100701.1009667Below SMA3: remain flatFlat2.40 USD
1610:15No execution1.100901.1008667Above SMA3: buy at next openFlat2.40 USD
1710:20Buy 1.10108; signal from bar 161.101301.1009667Above SMA3: keep the long; no new orderLong 10,000 EUR3.65 USD
1810:25No execution1.101601.1012667Above SMA3: keep the long; no new orderLong 10,000 EUR6.65 USD
1910:30No execution1.101801.1015667Above SMA3: keep the long; no new orderLong 10,000 EUR8.65 USD
2010:35No execution1.101401.10160Below SMA3: sell at next openLong 10,000 EUR4.65 USD
2110:40Sell 1.10122; signal from bar 201.101001.10140Below SMA3: remain flatFlat3.10 USD
2210:45No execution1.101201.10120Equal to SMA3: remain flatFlat3.10 USD
2310:50No execution1.100801.10100Below SMA3: remain flatFlat3.10 USD
2410:55No execution1.100401.10080Below SMA3: remain flatFlat3.10 USD
2511:00No execution1.100601.10060Equal to SMA3: remain flatFlat3.10 USD
2611:05No execution1.100901.1006333Above SMA3: buy at next openFlat3.10 USD
2711:10Buy 1.10103; signal from bar 261.100601.10070Below SMA3: sell at next openLong 10,000 EUR-2.15 USD
2811:15Sell 1.10042; signal from bar 271.100301.10060Below SMA3: remain flatFlat-3.70 USD
2911:20No execution1.100601.10050Above SMA3: buy at next openFlat-3.70 USD
3011:25Buy 1.10078; signal from bar 291.101101.1006667Above SMA3: keep the long; no new orderLong 10,000 EUR-1.45 USD
3111:30No execution1.101501.1010667Above SMA3: keep the long; no new orderLong 10,000 EUR2.55 USD
3211:35No execution1.101901.10150Above SMA3: keep the long; no new orderLong 10,000 EUR6.55 USD
3311:40No execution1.102301.10190Above SMA3: keep the long; no new orderLong 10,000 EUR10.55 USD
3411:45No execution1.102701.10230Above SMA3: keep the long; no new orderLong 10,000 EUR14.55 USD
3511:50No execution1.103101.10270Above SMA3: keep the long; no new orderLong 10,000 EUR18.55 USD
3611:55No execution1.102501.1027667Below SMA3: sell at next openLong 10,000 EUR12.55 USD

Tables scroll horizontally. Focus a table region and use the arrow keys if needed.

Position ledger

A closed row includes both paid commissions. An open row includes only its entry commission and a Bid mark, not a fictional closing trade.

Position ledger
PositionEntry fillExit fill / open markMidpoint P/L before costsFill / marked P/LPaid commissionNet closed / marked P/L
1ClosedBar 4 · 1.10058Bar 9 · 1.1014210.00 USD8.40 USD0.70 USD7.70 USD
2ClosedBar 13 · 1.10118Bar 15 · 1.10072-3.00 USD-4.60 USD0.70 USD-5.30 USD
3ClosedBar 17 · 1.10108Bar 21 · 1.101223.00 USD1.40 USD0.70 USD0.70 USD
4ClosedBar 27 · 1.10103Bar 28 · 1.10042-4.50 USD-6.10 USD0.70 USD-6.80 USD
5Open · mark onlyBar 30 · 1.10078Bar 36 · 1.1024418.00 USD16.60 USD0.35 USD16.25 USD
Download this position ledger · CSV

The CSV contains only the currently valid replay through the selected bar. Stable English field names, decimal dots and full model precision make the arithmetic auditable. Display values are rounded; the model is not.

Tables scroll horizontally. Focus a table region and use the arrow keys if needed.

Inspect the fictional OHLC data

All prices below are midpoints, the average of Bid and Ask at that moment. High and low are provided for data inspection; this close-to-next-open rule does not use them to invent fills. Earlier warmup rows are labelled and create no trades.

Inspect the fictional OHLC data
Bar · session clockOpenHighLowClose
1 · 09:001.099801.100101.099701.10000
2 · 09:051.100001.100351.099801.10020
3 · 09:101.100201.100601.100051.10040
4 · 09:151.100501.100901.100401.10080
5 · 09:201.100801.101351.100601.10120
6 · 09:251.101201.101801.101051.10160
7 · 09:301.101601.101901.101501.10180
8 · 09:351.101801.101951.101401.10160
9 · 09:401.101501.101701.101151.10130
10 · 09:451.101301.101401.100901.10100
11 · 09:501.101001.101151.100601.10080
12 · 09:551.100801.101201.100651.10100
13 · 10:001.101101.101301.101001.10120
14 · 10:051.101201.101351.100801.10100
15 · 10:101.100801.101001.100551.10070
16 · 10:151.100701.101001.100601.10090
17 · 10:201.101001.101451.100801.10130
18 · 10:251.101301.101801.101151.10160
19 · 10:301.101651.101901.101551.10180
20 · 10:351.101751.101901.101201.10140
21 · 10:401.101301.101501.100851.10100
22 · 10:451.101001.101301.100901.10120
23 · 10:501.101201.101351.100601.10080
24 · 10:551.100801.101001.100251.10040
25 · 11:001.100401.100701.100301.10060
26 · 11:051.100601.101051.100401.10090
27 · 11:101.100951.101151.100451.10060
28 · 11:151.100501.100601.100201.10030
29 · 11:201.100301.100751.100101.10060
30 · 11:251.100701.101301.100551.10110
31 · 11:301.101101.101601.101001.10150
32 · 11:351.101501.102051.101301.10190
33 · 11:401.101901.102501.101751.10230
34 · 11:451.102301.102801.102201.10270
35 · 11:501.102701.103251.102501.10310
36 · 11:551.103101.103301.102351.10250

Tables scroll horizontally. Focus a table region and use the arrow keys if needed.

Download a research protocol

Use the editable text checklist to specify a separate experiment before looking at its results. It does not certify a test or turn this invented sequence into market evidence.

Download the protocol · TXT
Model boundaries

Fixed quantity, full fills, constant assumed spread/slippage/commission and no delay beyond the next open. No live prices, partial fills, leverage, margin liquidation, deposits, withdrawals or broker-specific execution rules. This is an explanation of sequencing and accounting, not a broker emulator or strategy optimizer.

This component calculates in this browser tab without sending inputs or saving them in browser storage. Files are created only when you choose to download them. This statement covers the lab, not other parts of the site.

Advance the replay one bar at a time. At a bar’s open, any eligible instruction queued after the previous close executes using that open and the chosen costs. Only afterward does the model observe the current bar’s close and calculate a new signal. No trade can use a close that has not yet occurred.

For example, a buy signal formed after bar 3 closes may fill at bar 4’s open. It cannot receive bar 3’s opening price. A gap between the two bars therefore matters. TradingView’s strategy documentation likewise distinguishes the creation of an order from the later tick on which its broker emulator can fill it under the default timing.

Compare the full window with the first or second half. Each selected window starts flat. Earlier closes may warm up the average, but they do not import a position, an earlier fee or a queued order. These are separate teaching runs: their results must not be added together and presented as one continuous account.

At the selected window’s end, a newly generated signal has no fill if its next open is outside that window. An existing position remains visible and is marked separately; the model does not invent an exit to make every trade look complete. Changing the window can therefore change both the trade count and the final open state.

The two halves are not an out-of-sample validation. Both belong to one small fictional example, and resetting positions changes the experiment.

Include costs once, on a consistent basis

For this midpoint-based model, a buy fills at midpoint open plus half the spread plus adverse slippage. An exit sell fills at midpoint open minus half the spread minus adverse slippage. Commission is a separate USD charge for each execution of the fixed 10,000-EUR position. In this EURUSD example, one pip is 0.0001 USD per EUR.

Worked round trip

Calculation

Midpoint entry / exit

1.10000 / 1.10200

Assumptions

1.2-pip spread; 0.2-pip adverse slippage per execution; $0.35 commission per execution

Entry / exit fills

1.10008 / 1.10192

Price P/L after spread and slippage

10,000 × (1.10192 − 1.10008) = $18.40

Net closed-trade P/L

$18.40 − $0.35 − $0.35 = $17.70

Scroll sideways to compare all columns ↔

The midpoint movement alone would produce $20.00. Do not subtract spread and slippage from $18.40 again: they are already inside the fills. With the same midpoint at entry and exit, these assumptions produce −$2.30. Adding one pip to the spread reduces this round trip by $1.00, because each side receives half of the extra spread.

If a position remains open, the replay marks it at the latest modeled Bid and includes the entry commission already paid. It does not charge a future exit commission or exit slippage before an exit occurs. The displayed total is modeled P/L, not a complete account-equity calculation.

Constant costs isolate their effect; they are not a promise about actual quotes. A real test may need changing spreads, different commissions and financing across rollover. This intraday example excludes overnight swap. Read the slippage guide for the distinction between a requested price, an available quote and an actual fill.

Separate development, historical holdout and future observation

Decide which historical observations may influence development before inspecting the evaluation period. A later period can challenge a rule that was chosen earlier, but only if its results remain outside the selection process. Repeatedly viewing the holdout and adjusting the strategy turns that period into development material.

Stage

Purpose

What it does not establish

Development

Build the rule and examine assumptions on permitted data.

That the selected version will generalize.

Historical holdout

Apply a frozen version to later, previously unused observations.

Actual broker fills or future profitability.

Forward observation

Observe new incoming prices after the rules are fixed.

That simulated fills equal live execution.

Scroll sideways to compare all columns ↔

The Forward setting in MetaTrader 5 uses a later part of the selected historical interval. Despite its name, that is not the same as waiting for future market data. Keep the platform label and the research method explicit in your notes.

Chronology also applies to indicator preparation. Earlier observations can provide the history needed to calculate an indicator at the start of an evaluation period. They should not leak a future close into the calculation or quietly create a position that the experiment was defined to start without.

If a holdout exposes a problem, document it. A revised strategy may be worth a new experiment, but the old holdout is now known data. Do not preserve the “unseen test” label simply by changing a file name or selecting another performance metric.

Inspect failures before interpreting returns

A favorable result is a reason to inspect the ledger, not to stop checking it. Choose several entries and exits, including an awkward boundary, and reconstruct what information was available at each decision. The most informative row may be an unfilled signal or an unattractive trade that a discretionary review would overlook.

  • Lookahead: a decision uses a later close, a future-confirmed pattern or a value that was not available at the stated time.
  • Overfitting: many settings are tried and only the winner is retained without recording the search.
  • Selection bias: favorable dates, instruments or trades are kept while inconvenient observations disappear.
  • Execution mismatch: bar data are asked to prove an intrabar fill sequence they do not contain.
  • Accounting errors: repeated signals add unintended positions, costs are charged twice, or an open trade vanishes at the boundary.

TradingView’s lookahead examples show how access to future information can produce implausible historical results. A practical question is whether the same signal could have been recorded while observations arrived one at a time. If later data change an earlier decision, investigate the dependency before trusting the performance report.

Vary assumptions deliberately, not until the result looks acceptable. For example, compare the same fixed rule under several stated costs. If a small cost change reverses the result, report that sensitivity. It is information about the experiment, not a reason to hide the more demanding scenario.

Record a reproducible test

Download the experiment protocol from the replay after selecting a window and costs. Keep it with the displayed scenario and ledger. Its fictional-data label matters: sharing the numbers without that context would turn a teaching exercise into a misleading performance claim.

For your own research, a protocol should let you return a month later and understand what was actually tested. A screenshot of the final profit is insufficient when the data, signal timing or cost basis has changed.

  • Record the rule version, intended question and any changes made since the previous run.
  • Identify the dataset, price basis, time zone, interval, omissions and preparation steps.
  • Write down signal timing, fill assumptions, sizing, costs and treatment of the final open position.
  • Separate development dates from evaluation dates and record whether evaluation results have already influenced choices.
  • Save trade counts, the execution ledger, open-state details and failed checks alongside the summary.

The trading journal template can organize individual observations, while the protocol describes the experiment that produced them. Preserve a disappointing run as carefully as an attractive one; otherwise your research history itself becomes a selected sample.

Read metrics in context

Begin with counts: observations available, completed trades, executions charged and positions still open. A percentage without its denominator can make a tiny sample look more persuasive than it is. A queued terminal signal is not a completed trade, and an open position is not a closed win or loss.

Next reconcile closed net results with open marked results and fees already paid. Inspect where losses occur and how dependent the outcome is on a few trades. The replay contains no deposit, margin model or withdrawals, so its P/L path should not be read as a broker account balance.

Use the profit factor guide, equity curve simulator and Calmar ratio guide for the definitions and limitations of those measures. A favorable ratio cannot repair lookahead or an unrealistic fill. Nor does a few hours of fictional observations justify an annualized return or a claim about long-term drawdown.

A useful conclusion describes the conditions: which rule was tested, on what data, under which assumptions, and what remains uncertain. “This version lost money when costs increased” is a clearer research result than an unsupported promise that the next version will be profitable.

Frequently asked questions

Can I backtest a forex strategy manually?

Yes. Reveal observations in chronological order, apply written rules, and record every eligible trade and assumption. Avoid moving through a finished chart and selecting only recognizable setups. Manual work needs the same cost and boundary rules as an automated test.

Should I use MetaTrader 5 or TradingView?

Choose according to the rule, data and execution behavior you need to examine. Read the relevant tester or broker-emulator settings and inspect individual fills. Different defaults can produce different results without either platform demonstrating that a strategy is profitable.

Are real ticks always necessary?

The necessary detail depends on the rule. A strategy sensitive to events within a bar needs evidence those bars may not provide. Tick data can add detail, but you still need to check quote coverage, price sides and execution assumptions. More rows do not eliminate model limitations.

How many trades make a backtest reliable?

There is no universal number that validates every strategy. Frequency, dependence between trades, market conditions and the number of variants tried all affect interpretation. Report the sample and its limitations. The small fictional replay here is deliberately unsuitable for a statistical performance claim.

Why can live results differ from a backtest?

Prices, timing, spread, available liquidity, fees and order handling may differ from the model. A test also cannot contain market conditions that have not occurred in its data. Historical results remain conditional evidence; forward observation and actual execution should be recorded separately.

Does a profitable backtest prove an edge?

No. First rule out information leakage and accounting errors, then assess how the strategy was selected and tested. A result can be internally consistent and still depend on a small or unrepresentative period. Backtesting supports an investigation; it does not guarantee a future outcome.

Sources & further reading

  1. TradingView — StrategiesChecked
Orders & execution
Trading plan templateWrite the rules and version changes before comparing results.Trading journal templateKeep individual trades and observations with their original context.Slippage explainedSeparate a model assumption from a quote and an actual execution.Profit factorInterpret a summary ratio without losing the underlying sample.Equity curve simulatorExplore why trade order and assumptions change a result path.Calmar ratioUnderstand the period and drawdown choices behind the metric.
All guides