The rules at a glance
- Level: a recent swing high (resistance) or swing low (support); the script uses 5-candle swing points
- Break: a candle closes beyond the level
- Retest: within 15 candles, the price comes back to within 3 pips of the level and a candle closes back on the breakout side, in the breakout direction
- Entry: at the close of that retest candle
- Stop loss: beyond the level or the retest candle, whichever is further, plus half the 14-period ATR
- Target: twice the risk (2R)
- Filter: longs only above the 200 EMA, shorts only below it (on by default in the script; you can switch it off)
What a break and retest is
Price often stalls at the same level more than once. Each time it gets there, sellers win and it drops back: that level is resistance. When a candle finally closes above it, the level is broken. What traders watch for next is the retest: the price pulls back to the old resistance, and this time it holds as support. Technical analysts have called this "role reversal" for decades. The same thing works the other way round, with broken support turning into resistance.
The break and retest strategy doesn't buy the breakout itself. It waits for the pullback, and buys only if the level holds. You give up the trades that never come back, and in return you get an entry close to the level, with a stop just beyond it.
Why old resistance can turn into support
There's no law that makes it happen, but three things push in that direction:
- Trapped sellers. Traders who sold at resistance are losing money after the break. When the price comes back to where they sold, some close their trades to get out at break-even, and closing a short trade means buying.
- Buyers who missed the break. Traders who saw the breakout too late use the pullback as their second chance to buy.
- Everyone can see the level. A price that stopped the market twice is on thousands of charts, so buy orders and stops cluster around it.
None of this is guaranteed, which is why the rules need a candle to close back on the breakout side before you enter. A touch of the level isn't enough.
Three ways a retest can play out
| What the price does | What it means | What to do |
|---|---|---|
| Dips to the level, then a candle closes back above it | The level held: the classic retest | Enter at the close (this is the strategy's signal) |
| Closes back below the level | The breakout failed | No trade, and the setup is cancelled |
| Never comes back to the level | A strong breakout | No trade. You'll miss some of the best moves; that's the price of waiting |
The third row is the one that frustrates people. Some of the strongest breakouts never look back, and watching them go without you is part of this strategy. Chasing them breaks the rules that give you the tight stop.
The rules, step by step
1. Find a level that matters
Use a recent swing high or swing low: a candle with a higher high (or lower low) than the five candles on each side. Levels the price has turned at more than once, and levels from a higher timeframe, are worth more than a single touch. The price action guide covers how to mark them.
2. Wait for a candle to close beyond it
A wick through the level doesn't count. The break is a full candle close above resistance, or below support.
3. Wait for the retest
Within the next 15 candles, the price has to come back to within 3 pips of the level. The retest candle must close back on the breakout side, and in the breakout's direction: a bullish candle for a long, a bearish one for a short. If a candle closes back through the level first, or 15 candles pass, the setup is cancelled.
4. Enter, with the stop beyond the level
Enter at the close of the retest candle. Put the stop below the level or the retest candle's low, whichever is lower, plus half of the 14-period ATR, so a normal wick doesn't take you out. For a short, mirror it above the high.
5. Target twice the risk
The target is 2R. With the trend filter on, which is the script's default, take longs only when the price is above the 200 EMA and shorts only when it's below, so you're trading retests in the direction of the bigger move.
Worked example: EURUSD, 1-hour chart
EURUSD stalls at 1.1650 twice. Then a candle closes at 1.1668, clearly above it. Seven hours later the price drifts back down to 1.1652, 2 pips above the old resistance and inside the 3-pip tolerance, and that candle closes higher at 1.1664. That's the retest signal, assuming the price is above the 200 EMA as the default setting requires. The ATR at that moment is about 14 pips, so half of it puts the stop at 1.1643, just under the level.
| EURUSD long | |
|---|---|
| Entry | 1.1664 |
| Stop loss | 1.1643 (level 1.1650 minus half the ATR), 21 pips away |
| Target (2R) | 1.1706, 42 pips away |
| Account and risk | $10,000, risking 1% = $100 |
| Lot size | $100 ÷ (21 pips × $10) = 0.47 lots |
| Loss if the stop is hit | $98.70 |
| Profit at the target | $197.40 |
In this example the target is reached 13 hours after the entry. Compare it with buying the breakout candle at 1.1668: the stop would have had to go below the breakout's start, about 39 pips away instead of 21, so the same $100 risk would have bought about half the position. That's the trade-off the retest buys you.
Which timeframe works best?
There's no single answer. The 1-hour chart suits traders who check the market a few times a day, and the 15-minute chart gives more setups with smaller stops but more false breaks. A common approach is to mark the level on a higher timeframe, such as the 4-hour or daily chart, and time the retest on a lower one. Many traders find that levels from higher timeframes hold more often because more people are watching them, but test it rather than take it on trust.
Risk management
- Size from the stop. The stop distance changes with every level, so the lot size has to change with it. Risk the same 0.5% to 1% each time.
- One retest per level. If the first retest fails, the level is damaged. The script stops watching a level once it has traded it or the setup has expired.
- Mind the news. A data release can blow straight through a level that was holding. Check the economic calendar before entering.
- Know your break-even win rate. At 2R you break even at a win rate of about 33% before costs. The risk-reward calculator shows it for any ratio.
Common mistakes
- Calling a wick a break. Without a close beyond the level, there's nothing to retest.
- Entering on the touch. The price touching the level isn't a signal. The candle closing back on the breakout side is.
- Waiting for ever. A retest that comes days later is a new setup, not a retest. The 15-candle limit keeps the idea fresh.
- Stops exactly on the level. Retests often wick a few pips through the level before turning. The ATR buffer is there for that.
- Trading against the trend without knowing it. A retest against the 200 EMA is a counter-trend trade. Try the filter on and off in the backtest and see the difference for yourself.
Candlestick signals such as a hammer or an engulfing candle at the level can strengthen a retest; the candlestick patterns guide shows 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 EURUSD on the 1-hour 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. Try the swing strength (3 to 10 candles), the number of candles allowed for the retest (5 to 30), the retest tolerance, and the 200 EMA filter on and off. Run the same settings on the 15-minute chart too, and on gold, where you'd raise the tolerance.
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.
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, a worked example, the lot size maths and a checklist, to keep next to your chart.
Show the code (Pine Script v6, 100 lines)
//@version=6
// Break and Retest strategy by PipLedger (https://pipledgerfx.com/break-and-retest-strategy)
// Waits for a close through the last swing high or low, then enters when price comes back to test it and rejects.
// Free to use and change. For education and backtesting only; not financial advice.
strategy("PipLedger: Break and Retest", shorttitle="Break & Retest", 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)
retestBars = input.int(15, "Bars allowed for the retest", minval=2)
tolPips = input.float(3.0, "Retest tolerance (pips)", minval=0.0, step=0.5)
atrLen = input.int(14, "ATR length", minval=1)
atrBuf = input.float(0.5, "Stop buffer (x ATR)", minval=0.0, step=0.1)
rr = input.float(2.0, "Target (R multiple)", minval=0.5, step=0.25)
useTrend = input.bool(true, "Only trade in the direction of the 200 EMA")
pipSize = input.float(0.0, "Pip size (0 = automatic)", minval=0.0, step=0.00001)
riskPct = input.float(1.0, "Risk per trade (% of equity)", minval=0.1, maxval=5.0, step=0.1)
// ---------- Helpers
isGold = syminfo.currency == "USD" and syminfo.type != "stock" and (str.contains(syminfo.ticker, "XAU") or str.contains(syminfo.ticker, "GOLD"))
autoPip = isGold ? 0.1 : syminfo.type == "forex" ? (syminfo.currency == "JPY" ? 0.01 : 0.0001) : syminfo.mintick * 10
pip = pipSize > 0 ? pipSize : autoPip // 0.0001 on EURUSD, 0.01 on USDJPY, 0.10 on XAUUSD
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(atrLen)
ema200 = ta.ema(close, 200)
ph = ta.pivothigh(high, swingLen, swingLen)
pl = ta.pivotlow(low, swingLen, swingLen)
// ---------- Levels
var float resLevel = na
var float supLevel = na
var float brokeUp = na
var int brokeUpBar = na
var float brokeDn = na
var int brokeDnBar = na
if not na(ph)
resLevel := ph
if not na(pl)
supLevel := pl
breakUp = not na(resLevel) and close > resLevel and close[1] <= resLevel
breakDn = not na(supLevel) and close < supLevel and close[1] >= supLevel
if breakUp
brokeUp := resLevel
brokeUpBar := bar_index
resLevel := na
if breakDn
brokeDn := supLevel
brokeDnBar := bar_index
supLevel := na
// a setup ends when the retest window runs out, or when a candle closes back through the level (failed breakout)
if not na(brokeUpBar) and (bar_index - brokeUpBar > retestBars or (bar_index > brokeUpBar and close < brokeUp))
brokeUp := na
brokeUpBar := na
if not na(brokeDnBar) and (bar_index - brokeDnBar > retestBars or (bar_index > brokeDnBar and close > brokeDn))
brokeDn := na
brokeDnBar := na
// ---------- Retest signals
trendLongOk = not useTrend or close > ema200
trendShortOk = not useTrend or close < ema200
longSig = not na(brokeUp) and bar_index > brokeUpBar and low <= brokeUp + tolPips * pip and close > brokeUp and close > open and trendLongOk and strategy.position_size == 0
shortSig = not na(brokeDn) and bar_index > brokeDnBar and high >= brokeDn - tolPips * pip and close < brokeDn and close < open and trendShortOk and strategy.position_size == 0
// ---------- Orders
if longSig
float sl = math.min(low, brokeUp) - atr * atrBuf
float tp = close + (close - sl) * rr
float q = calcQty(close, sl)
if q > 0
strategy.entry("Long", strategy.long, qty=q)
strategy.exit("Long exit", "Long", stop=sl, limit=tp)
brokeUp := na
brokeUpBar := na
if shortSig
float sl = math.max(high, brokeDn) + atr * atrBuf
float tp = close - (sl - close) * rr
float q = calcQty(close, sl)
if q > 0
strategy.entry("Short", strategy.short, qty=q)
strategy.exit("Short exit", "Short", stop=sl, limit=tp)
brokeDn := na
brokeDnBar := na
// ---------- Chart
plot(resLevel, "Resistance (last swing high)", color=color.new(color.red, 30), style=plot.style_linebr)
plot(supLevel, "Support (last swing low)", color=color.new(color.teal, 30), style=plot.style_linebr)
plot(brokeUp, "Broken resistance, waiting for retest", color=color.new(color.teal, 0), linewidth=2, style=plot.style_linebr)
plot(brokeDn, "Broken support, waiting for retest", color=color.new(color.red, 0), linewidth=2, style=plot.style_linebr)
plot(useTrend ? ema200 : na, "200 EMA", color=color.new(color.gray, 0))
plotshape(longSig, "Long retest", shape.triangleup, location.belowbar, color.teal, size=size.small)
plotshape(shortSig, "Short retest", shape.triangledown, location.abovebar, color.red, size=size.small)Trading this from India
Residents can trade EURUSD, GBPUSD and USDJPY futures and options on NSE and BSE through a SEBI-registered broker. The contracts are quoted the same way as the spot pair, one lot is 1,000 units of the base currency, and they're cash-settled in rupees. They trade only from 9 a.m. to 7:30 p.m. IST, volumes are thin and not every broker offers them, so check the hours and the spread first. On those charts, set the script's pip size to 0.0001 (0.01 for USDJPY). Trading forex or CFDs with offshore online platforms isn't allowed for residents under FEMA, even if the app is easy to download. Details are in is forex trading legal in India.
More strategies with free Pine Scripts: London breakout, liquidity sweep, 9 and 21 EMA crossover, XAUUSD scalping.