The rules at a glance
- Market: XAUUSD on the 15-minute chart
- Structure: a candle closes above the most recent swing high (a high with 5 lower highs on each side): a break of structure (BOS)
- Order block: the last bearish candle before the break, within the 10 candles before it
- Fair value gap: a three-candle gap whose first candle is the order block or a later one, starting inside the block or no more than one ATR above its high; the earliest one counts
- Entry: a buy limit at the bottom of that gap, which on many setups is the order block's high
- Stop loss: a quarter of an ATR below the order block's low
- Target: 2R; an order that hasn't filled within 30 candles is cancelled
Why combine a gap and a block
An order block is the last opposite candle before a strong move; the idea is that unfilled orders were left there and the price may come back to them. A fair value gap is a three-candle pattern where the middle candle moves so fast that the first and third candles don't overlap. Each one on its own marks a lot of zones, and most of them don't lead anywhere.
Putting them together is a filter. A gap that starts at the order block shows the move away from the block was fast, what SMC traders call displacement, not a slow drift. A break of the last swing high shows the move changed the structure. When all three line up, the setup is cleaner and rarer. Whether it's also better is a question for your backtest: run this script and the two single-concept scripts on the same dates and compare.
| Order block strategy | Fair value gap strategy | This strategy | |
|---|---|---|---|
| Needs a break of structure | Yes | No (200 EMA trend filter) | Yes |
| Needs a gap | No | Yes | Yes, starting at, inside or just above the block |
| Entry | Top of the block | Edge of the gap | Bottom of the gap, at or near the block's high |
| Stop | Below the block | Below the gap | Below the block |
How to spot the setup on a gold chart
- Find the last swing high: a candle whose high is above the five candles on each side of it.
- Wait for a candle to close above it. That's the break of structure.
- Look back from the break for the last bearish candle. That's the order block.
- Look forward from the block for a gap: a candle whose low is above the high of the candle two before it. The first such gap whose first candle is the block or a later one, and that starts inside the block or no more than one ATR above its high, is the one that counts.
The bottom of the gap is the entry. When the gap's first candle is the order block itself, as it often is, the bottom of the gap is exactly the block's high. The BOS and CHoCH guide covers swing highs and breaks of structure in more detail.
The rules, step by step
1. Break of structure
A 15-minute candle closes above the latest swing high, after the candle before it closed at or below it. Each swing high can only be broken once.
2. Order block and gap
On that candle, find the last bearish candle within the previous 10 candles: the order block. Then find the earliest bullish fair value gap that starts at the block or after it, at least a tenth of an ATR tall, and starting inside the block or no more than one ATR above its high. No block or no gap, no trade.
3. Limit order at the gap's bottom
Place a buy limit at the bottom of the gap. The stop goes a quarter of the 14-period ATR below the order block's low, so the price has to go through the whole block to stop you out. The target is twice the risk.
4. Cancel if it doesn't come back
The order stays for 30 candles (seven and a half hours on the 15-minute chart). If no fill comes by then, cancel it: the move has gone without you. Shorts are the mirror image, after a break of a swing low.
Worked example: XAUUSD, 15-minute chart
Gold makes a swing high at 4,303.40 and drifts lower. The last bearish candle of the drift runs from 4,286.80 to 4,291.50: that's the order block. The next candle is a big bullish one, and the candle after it has a low of 4,293.40, above the block's high, leaving a gap from 4,291.50 to 4,293.40. One candle later gold closes at 4,305.10, above the swing high: the break of structure.
| XAUUSD long | |
|---|---|
| Entry (buy limit at the gap's bottom) | 4,291.50 |
| Stop loss (a quarter of an ATR below the block) | 4,285.82, $5.68 away |
| Target (2R) | 4,302.86, $11.36 away |
| Account and risk | $10,000, risking 1% = $100 |
| Lot size | $100 ÷ ($5.68 × 100 ounces) = 0.176, rounded down to 0.17 lots |
| Loss if the stop is hit | $96.56 |
| Profit at the target | $193.12 |
Gold pulls back 10 candles after the break and fills the limit order at the block's high, then turns up and reaches the target 6 candles later. Notice that the target sits just under the old swing high: a 2R target from a tight entry doesn't always reach new highs. Some SMC traders aim for the next swing high instead; that's a setting worth testing.
SMC on gold: points to keep in mind
- Time of day. Many SMC traders only take setups in the London and New York kill zones. The script doesn't filter by time; the ICT kill zone guide has the hours in IST if you want to add that rule yourself.
- Volatility changes through the day. A 15-minute gold candle in the Asian session can be a third of the size of one at the New York open. Because the gap size, the stop buffer and the "within one ATR" rule are all in ATR terms, they adjust automatically.
- Higher timeframe. A bullish setup against a falling 4-hour trend is a counter-trend trade. Check the bigger picture, or test adding a trend filter.
Risk management
- Size from the stop. Stops below a 15-minute block on gold are often $4 to $8, which means lot sizes of 0.12 to 0.25 at 1% of $10,000. Work it out every time with the gold lot size calculator.
- One live order at a time. A new setup replaces the old one only when no trade is open.
- Limit orders and news. A waiting limit order can be filled by a news spike that runs straight through the block to the stop. Cancel orders before big US releases.
Common mistakes
- Calling every candle an order block. Without the break of structure and the gap, it's just a candle.
- Moving the stop inside the block. A wick into the block is normal; the stop sits beyond its far side for that reason.
- Chasing a missed fill. If the price never came back, there was no trade. Don't buy at the market three candles later.
- Trading every setup in the Asian session. Quiet hours produce small, frequent structures. Test with a time filter before trading them.
Backtest it yourself on TradingView
This page doesn't quote a win rate or a profit figure, and you should be wary of anyone who does without showing the test. Results change with the market, the dates, the data feed and the costs you put in. The honest way is to run the test yourself, and the free script below does the work in a couple of minutes.
- Open the chart. On TradingView, open XAUUSD on the 15-minute chart.
- Add the script. Open the Pine Editor from the Pine icon in the panel on the right of the chart (older layouts have it as a tab under the chart), delete the code that's already there, paste this strategy's code and click "Add to chart".
- Put in your costs. Open the strategy's settings and go to Properties. Enter your broker's commission and a little slippage. A test without costs flatters every strategy, and short-term ones most of all.
- Read the Strategy Tester. The panel under the chart shows the net profit, the maximum drawdown, the profit factor, the number of trades and a list of every trade. Click a few trades and check on the chart that each one follows the rules. Trade sizes are shown in units rather than lots: 100,000 units is one lot of a forex pair, and 100 ounces is one lot of gold.
- Change one setting at a time. Compare the swing strength (3 to 8 candles), the distance allowed between the gap and the block (0 to 2 × ATR), how long the order stays (10 to 50 candles) and the 2R target against 1.5R and 3R. Then run the order block and fair value gap scripts on the same dates to see what the combination changes.
As a rough guide, don't trust a result with fewer than 100 trades, a profit factor under 1 once costs are in, or a drawdown you couldn't sit through with real money. Settings tuned to look good on one stretch of history often fail on the next, so check the same settings on dates you didn't tune them on, then demo trade the strategy for a few weeks. How much history you can test depends on your TradingView plan: the free plan loads 5,000 candles, which is a few months of 15-minute candles but years of daily ones.
The script sizes each trade from the stop loss and your risk percentage, starts with $10,000 and assumes 1:100 leverage (a 1% margin setting), so the tester doesn't flag margin calls on normal forex trade sizes. Change these under Properties to match your account. By default TradingView fills orders at the open of the candle after the signal, so the fill can differ a little from the signal candle's close.
Download the free Pine Script and PDF
The script is written in Pine Script version 6 for this guide and follows the rules above. It can't read the economic calendar, so skipping news days is up to you. It's free to use, change and share. The PDF is a one-page cheat sheet with the rules, the four-step setup, a worked example and a checklist, to keep next to your chart.
Show the code (Pine Script v6, 124 lines)
//@version=6
// XAUUSD FVG + Order Block strategy by PipLedger (https://pipledgerfx.com/xauusd-fvg-order-block-strategy)
// After a break of structure, looks for the order block (the last opposite candle before the move) and a fair value gap that starts at or just beyond it. A limit order waits at the gap's far edge, with the stop beyond the block.
// Free to use and change. For education and backtesting only; not financial advice.
strategy("PipLedger: XAUUSD FVG + Order Block", shorttitle="Gold FVG+OB", overlay=true, initial_capital=10000, pyramiding=0, default_qty_type=strategy.fixed, default_qty_value=1, margin_long=1, margin_short=1, currency=currency.USD)
// ---------- Inputs
swingLen = input.int(5, "Swing strength (bars on each side)", minval=2)
lookback = input.int(10, "Bars to search back for the order block candle", minval=3, maxval=50)
minGap = input.float(0.1, "Minimum gap size (x ATR 14)", minval=0.0, step=0.05)
maxDist = input.float(1.0, "The gap must start within (x ATR) of the block", minval=0.0, step=0.1)
validFor = input.int(30, "Candles the setup stays valid", minval=1)
stopBuf = input.float(0.25, "Stop buffer beyond the block (x ATR)", minval=0.0, step=0.05)
rr = input.float(2.0, "Target (R multiple)", minval=0.5, step=0.25)
riskPct = input.float(1.0, "Risk per trade (% of equity)", minval=0.1, maxval=5.0, step=0.1)
// ---------- Helpers
fx = strategy.convert_to_account(1.0) // one unit of the chart's quote currency in account currency (1 on USD-quoted charts)
calcQty(float entry, float stop) =>
float dist = math.abs(entry - stop)
dist > 0 and not na(fx) ? strategy.equity * riskPct / 100 / (dist * syminfo.pointvalue * fx) : 0.0
atr = ta.atr(14)
// dir = 1: the last bearish candle (bullish order block), then the earliest bullish gap that starts at it or after it
// dir = -1: the last bullish candle (bearish order block), then the earliest bearish gap
// returns the block's high and low and the gap edge nearest the block (na when there is no setup)
findSetup(int dir) =>
float obH = na
float obL = na
float edge = na
int k = 0
for i = 1 to lookback
if (dir == 1 and close[i] < open[i]) or (dir == -1 and close[i] > open[i])
obH := high[i]
obL := low[i]
k := i
break
if k >= 2
// a three-candle gap whose first candle is the block or a later one: candles j + 2, j + 1 and j
for j = k - 2 to 0
if dir == 1 and low[j] > high[j + 2] and close[j + 1] > open[j + 1] and low[j] - high[j + 2] >= minGap * atr and high[j + 2] > obL and high[j + 2] - obH <= maxDist * atr
edge := high[j + 2]
break
if dir == -1 and high[j] < low[j + 2] and close[j + 1] < open[j + 1] and low[j + 2] - high[j] >= minGap * atr and low[j + 2] < obH and obL - low[j + 2] <= maxDist * atr
edge := low[j + 2]
break
[obH, obL, edge]
ph = ta.pivothigh(high, swingLen, swingLen)
pl = ta.pivotlow(low, swingLen, swingLen)
[bH, bL, bEdge] = findSetup(1)
[sH, sL, sEdge] = findSetup(-1)
// ---------- Structure
var float swHi = na
var float swLo = na
if not na(ph)
swHi := ph
if not na(pl)
swLo := pl
bosUp = not na(swHi) and close > swHi and close[1] <= swHi
bosDn = not na(swLo) and close < swLo and close[1] >= swLo
if bosUp
swHi := na // each swing level breaks once
if bosDn
swLo := na
var float zTop = na
var float zBot = na
var float zEdge = na
var int zDir = 0 // 1 = a buy order waits, -1 = a sell order waits
var int zBar = na
flat = strategy.position_size == 0
// a waiting order is dropped once a trade is open or after validFor candles
// (a close beyond the block can't come first: the price would have to pass the entry, which fills the order)
if not flat
zDir := 0
if zDir == 1 and bar_index - zBar >= validFor
strategy.cancel("Long")
zDir := 0
if zDir == -1 and bar_index - zBar >= validFor
strategy.cancel("Short")
zDir := 0
newLong = flat and bosUp and not na(bEdge) and bEdge < close
newShort = flat and bosDn and not na(sEdge) and sEdge > close
// ---------- Orders: limit at the gap edge next to the block, stop beyond the far side of the block
if newLong
strategy.cancel("Short")
zTop := bH
zBot := bL
zEdge := bEdge
zDir := 1
zBar := bar_index
float sl = bL - atr * stopBuf
float q = calcQty(bEdge, sl)
if q > 0
strategy.entry("Long", strategy.long, qty=q, limit=bEdge)
strategy.exit("Long exit", "Long", stop=sl, limit=bEdge + (bEdge - sl) * rr)
else if newShort
strategy.cancel("Long")
zTop := sH
zBot := sL
zEdge := sEdge
zDir := -1
zBar := bar_index
float sl = sH + atr * stopBuf
float q = calcQty(sEdge, sl)
if q > 0
strategy.entry("Short", strategy.short, qty=q, limit=sEdge)
strategy.exit("Short exit", "Short", stop=sl, limit=sEdge - (sl - sEdge) * rr)
// ---------- Chart
plot(swHi, "Swing high", color=color.new(color.gray, 40), style=plot.style_linebr)
plot(swLo, "Swing low", color=color.new(color.gray, 40), style=plot.style_linebr)
plot(zDir != 0 ? zTop : na, "Block top", color=color.new(color.orange, 0), linewidth=2, style=plot.style_linebr)
plot(zDir != 0 ? zBot : na, "Block bottom", color=color.new(color.orange, 40), linewidth=2, style=plot.style_linebr)
plot(zDir != 0 ? zEdge : na, "Entry (gap edge)", color=color.new(color.blue, 0), style=plot.style_linebr)
plotshape(newLong, "Bullish setup", shape.triangleup, location.belowbar, color.teal, size=size.small)
plotshape(newShort, "Bearish setup", shape.triangledown, location.abovebar, color.red, size=size.small)Trading this from India
The rules work on any gold chart, and TradingView's XAUUSD chart is a fine place to learn and backtest them. To trade gold legally from India, though, use MCX gold futures, including the smaller Gold Mini and Gold Petal contracts, through a SEBI-registered broker. Trading XAUUSD as a CFD with an offshore forex platform isn't allowed for residents under FEMA. MCX gold trades from 9 a.m. to 11:30 p.m. IST while the US is on daylight saving time and to 11:55 p.m. in the US winter, which covers the London session and the New York morning. The contract is priced in rupees, and the script works in ATR rather than pips, so it needs no pip setting. The full picture is in is forex trading legal in India and XAUUSD market timings in India.
Related strategies: liquidity sweep, fair value gap, order block, BOS and CHoCH, ICT kill zones, XAUUSD intraday pivots, XAUUSD London session. All 34 strategies are compared on one page in forex trading strategies.