Verdict
Fair value gap (FVG)
By Thomas Jamais (Backtestd) · Published · Updated
Does fair value gap (FVG) work?
No, not in our test. We coded the rule, tested 772 versions of it on 24 markets from 2022 to 2025, fees, slippage and funding included. 50% of the versions lost money. The best version did not survive older data it had never seen (2020–2022).
Key facts
| Versions tested | 772 |
|---|---|
| Markets | 24 |
| Period | 2022-11-10 → 2025-07-09 |
| Candles | 1d |
| Costs | fees, slippage and funding on every trade |
| Versions that lost money | 50% |
| Verdict | No edge after costs |
In short
We coded the rule, tested 772 versions of it on 24 markets from 2022 to 2025, fees, slippage and funding included. 50% of the versions lost money. The best version did not survive older data it had never seen (2020–2022).
The rule people share
As it is usually explained:
Explained: the terms
- Look at three candles — Look at three candles.
- A strong candle: displacement — The middle one is huge. Traders call it displacement.
- The gap it leaves — Between the first candle's high and the third candle's low, price left a gap. That's the Fair Value Gap.
- Price comes back… — The idea: price comes back to fill the gap…
- …and bounces: buy — …and bounces. You buy inside the gap, with a stop just below it.
How we tested it
Data
1d candles of 24 markets (APR, ARB, BAT, BTC, BZ, DOGE, ETH, FIL, HYPE, NEAR, PEPE, PUMP, QQQ, SOL, SPY, STRK, SUI, TIA, UNI, WLD, XAG, XAU, XRP, ZEC), from 2022-11-10 to 2025-07-09. Crypto prices come from OKX perpetual futures; the 2020–2022 check uses Binance's public archive (median price gap to OKX: 0.06%). US index data comes from HistData.
Costs
Every trade pays a 0.05% taker fee per side, 2–5 basis points of slippage per side, and funding every 8 hours at each market's measured average rate. Results are in R: 1 R is the amount risked on one trade (entry to stop), so strategies with different stops compare fairly.
Versions
A rule shared online is never fully specified (which stop? which holding time? which timeframe?). So we test every reasonable reading: each combination of the settings below is one version.
Two halves
The data is split in two halves (a rising market, then a flatter one). A real edge should work in both.
Against the market
A long trade in a rising market makes money without any skill. We subtract what simply holding the crypto market (an equal-weight basket) on the same side over the same days would have made: what remains is what the rule adds.
Older data, never seen
The best version is then run, unchanged, on 2020–2022 data that played no part in choosing it (a crash, a bull market and a bear market).
Results
All 772 versions
Each bar counts versions by their average result per trade after costs (clipped to ±1 R). Green: made money; red: lost money.
The best of 772 versions
76 trades, 45% winners, +0.839 R per trade on average, +63.8 R in total, worst drawdown −10.6 R.
Cumulative result after costs, trade after trade (dashed line: start of the second half).
- First half: +0.962 R per trade. Second half: +0.729 R per trade.
- Against holding the market over the same days: +0.932 R per trade (week-clustered t = 3.0).
- Same settings on 2020–2022: 47 trades, +0.157 R per trade, −0.205 R per trade against the market.
Why “the best version” misleads
With 772 versions, some look good by luck alone. The typical version made +0.000 R per trade; the best made +0.839. If the rule had no edge at all, the spread of results would look like this anyway: the best of many random tries always looks impressive. That is why we never trust the best version until it works on data it was not chosen on.
Verify it yourself
- Write the rule exactly (below: our specification and every setting we tried).
- Get free data: Binance's public archive (data.binance.vision) has years of candles; OKX and most exchanges offer an API.
- Include costs: fees on both sides, slippage, and funding for perpetual futures.
- Count results in R (risk per trade), not in %, and look at the typical version, not the best one.
- Split your data in two and keep a part you never look at until the end.
- Compare with simply holding the market over the same days.
Our exact specification (the lab's own words, in English)
SMC: fair value gap (FVG) retest. What it does: a bullish fair value gap is a three-candle pattern where the third candle's low stays above the first candle's high, leaving a price gap that the strong middle candle jumped over. SMC traders expect price to come back into that gap and bounce. Bearish is the mirror image. Rules (fixed a priori, not tuned on results): - Gap: low[i] > high[i-2] (bullish) or high[i] < low[i-2] (bearish), gap height >= min_gap_atr x ATR, and the middle candle's body >= disp_mult x ATR (a "displacement" candle, not drift). - Zone: between high[i-2] and low[i] (bullish). Only the newest gap of each side is watched. - Entry long: the first later candle (within max_wait candles) whose low reaches the zone top and that closes above the zone bottom. A close below the bottom before that kills the zone. - Stop: zone bottom - stop_buf x ATR, but at least min_stop_adr x average daily range away. Target: target_r x stop distance (0 = none). Time stop after hold_bars. Source: common ICT / "smart money concepts" teaching (TradingView, YouTube); idea only.
Settings tried
| Setting | Values |
|---|---|
disp_mult | 1.0, 1.5 |
min_gap_atr | 0.2, 0.5 |
max_wait | 192, 672 |
stop_buf | 0.25, 1.0 |
min_stop_adr | 0, 0.5 |
target_r | 0, 2, 3 |
hold_bars | 288, 960 |
timeframe | 1d, 1h, 4h |
atr_len | 14 |
entry_mode | at_stop, market, pullback |
entry_stop | 0.25, 0.5, 1 |
entry_wait | 3 |
exit_scale | —, 1:0.33,2:0.33, 1:0.5 |
exit_scale_be | 0, 1 |
entry_pull | 0.25, 0.5 |
avg_down | 0, 2 |
avg_stop | 0.5, 1, 2 |
avg_exit | breakeven, strategy |
sent_weight | 0, 0.5, 1 |
sent_mode | contrarian, follow |
sent_block | 0, 0.5 |
session | any, asia, london, london_ny, ny, outside |
Settings of the version shown
atr_len | 14 |
disp_mult | 1.5 |
min_gap_atr | 0.5 |
max_wait | 672 |
stop_buf | 1.0 |
min_stop_adr | 0 |
target_r | 3 |
hold_bars | 960 |
entry_mode | pullback |
entry_pull | 0.5 |
entry_wait | 3 |
timeframe | 1d |
Download every trade of the version shown (CSV, 76 rows)
Limitations
- A backtest is not live trading: fills, outages and your own discipline differ.
- We test the rule as written; a trader's discretion is not testable.
- Markets change. A rule that failed here could work elsewhere, and the reverse.
- Costs depend on your exchange and size; ours are typical retail perpetual-futures costs.
Questions
Did you include fees?
Yes: fees, slippage and funding on every trade, from real exchange schedules.
Maybe it works on another timeframe?
We tested several timeframes and holding times: see “Settings tried”. The result does not depend on one choice.
Maybe it works with better risk management?
We tried stops of different widths, targets, trailing stops and partial exits. Risk management changes the shape of the results, not the sign of the edge.
Why should I trust you?
You should not: verify. The rule, every setting and every trade are on this page.
Does this mean nobody makes money with it?
Some traders will, by skill elsewhere or by luck. This test only says the rule itself does not give an edge after costs.
Disclaimer
Educational content based on historical backtests. Not financial advice. Past results do not predict future results. Trading leveraged products can lose more than you invest.