Strategy · Pine Script v5 · On the chart

Range Percent Breakout Strategy

by g-moe· code credited to goodgains

The Range Percent Breakout Strategy identifies range contraction and inside bar patterns where the current bar's range is within a specified percentage threshold of the previous bar.

View on GitHub

GitHub stars3on the repository
Pine versionv5runs as is
Lines of code154
Settings5inputs
LicenceNone statedfile: MPL-2.0
Last update5 months ago27 May 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new strategy, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart. The trades and results appear in the Strategy Tester tab; adjust the settings with the gear icon.

Source Code

154 lines of Pine Script v5 from Tradingview/range-percent-breakout-strategy.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

range-percent-breakout-strategy.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © goodgains


//@version=5
strategy("Range Percent Breakout Strategy", overlay=true, margin_long=100, margin_short=100, calc_on_order_fills = true, default_qty_value = 100, initial_capital = 100000000)

// @keywords: percent-range-breakout, dual-entry-levels, long-short-strategy, opposite-stop-type, prior-close-stop, prior-open-stop, scaled-take-profit, tp1-tp2-percent, trading-day-counter, range-trigger-percent, bar-delay-entry, stop-price-tracking, intraday-breakout, position-flip, equity-sizing, breakout-threshold, session-range, entry-level-memory, risk-reward-scaling, automated-exits

// settings
_pct_range      = input.float(50.00, title = '% Range Trigger', group = 'Settings', minval = 0.01)
_bars_for_entry = 1
_stop_type      = input.string('Opposite', title = 'Stop Type', group = 'Settings',
 options = ['Opposite', 'Previous Close', 'Previous Open'])

_tp1            = input.float(84.00, title = 'TP1 %', group = 'Settings', minval = 0.01, maxval = 100)
_tp2            = input.float(65.00, title = 'TP2 %', group = 'Settings', minval = 0.01, maxval = 100)

_days_for_trade = input.int(4, title = 'Trading Days', group = 'Settings')


// calculate
var bool entered_signal = false
var float long_entry_lvl = 0.00
var float short_entry_lvl = 0.00

var float long_stop_lvl = 0.00
var float short_stop_lvl = 0.00

var float long_stop     = 0.00
var float short_stop    = 0.00

var float tp_amount     = 0.00

var float long_tp1      = 0.00
var float long_tp2      = 0.00
var float long_tp3      = 0.00

var float short_tp1      = 0.00
var float short_tp2      = 0.00
var float short_tp3      = 0.00

var bool long_tp1_hit       = false
var bool long_tp2_hit       = false

var bool short_tp1_hit      = false
var bool short_tp2_hit      = false

var int bars_since_cond = 0
var int bars_since_entry = 0


range_pct      = (high - low) / (high[1] - low[1]) * 100
cond_lh_and_hl = (high < high[1]) and (low > low[1])
cond_range     = range_pct <= _pct_range
cond_inside    = (math.max(close[1], open[1]) >= math.max(close, open) and math.min(close[1], open[1]) <= math.min(close, open))
condition      = cond_lh_and_hl and cond_range and cond_inside and strategy.position_size == 0
bars_since_cond:= condition ? 1 : bars_since_cond[1] + 1

long_entry_lvl  := condition ? high + 0.01 : bars_since_cond > _bars_for_entry or strategy.position_size != 0 ? na : long_entry_lvl[1]
short_entry_lvl := condition ? low - 0.01 : bars_since_cond > _bars_for_entry or strategy.position_size != 0 ? na : short_entry_lvl[1]

long_stop_lvl   := condition ? 
 (_stop_type == 'Opposite' ? short_entry_lvl : _stop_type == 'Previous Close' ? close : _stop_type == 'Previous Open' ? open : na)
 : bars_since_cond > _bars_for_entry or strategy.position_size > 0 ? na 
 : long_stop_lvl[1]
 
short_stop_lvl  := condition ? 
 (_stop_type == 'Opposite' ? long_entry_lvl : _stop_type == 'Previous Close' ? close : _stop_type == 'Previous Open' ? open : na)
 : bars_since_cond > _bars_for_entry or strategy.position_size > 0 ? na 
 : short_stop_lvl[1]

tp_amount       := na(long_entry_lvl - short_entry_lvl) ? tp_amount[1] : (long_entry_lvl - short_entry_lvl)

long_tp1        := math.max(strategy.position_avg_price, nz(long_entry_lvl,0)) + (1*tp_amount)
long_tp2        := math.max(strategy.position_avg_price, nz(long_entry_lvl,0)) + (2*tp_amount)
long_tp3        := math.max(strategy.position_avg_price, nz(long_entry_lvl,0)) + (3*tp_amount)

short_tp1       :=  math.min(strategy.position_avg_price, nz(short_stop_lvl,9999999)) - (1*tp_amount)
short_tp2       :=  math.min(strategy.position_avg_price, nz(short_stop_lvl,9999999)) - (2*tp_amount)
short_tp3       :=  math.min(strategy.position_avg_price, nz(short_stop_lvl,9999999)) - (3*tp_amount)

long_tp1_hit    := condition ? false : long_tp1_hit[1] == false and high > long_tp1 ? true : long_tp1_hit[1]
long_tp2_hit    := condition ? false : long_tp2_hit[1] == false and high > long_tp2 ? true : long_tp2_hit[1]

short_tp1_hit    := condition ? false : short_tp1_hit[1] == false and low < short_tp1 ? true : short_tp1_hit[1]
short_tp2_hit    := condition ? false : short_tp2_hit[1] == false and low < short_tp2 ? true : short_tp2_hit[1]

long_stop       := condition ? long_stop_lvl
 : (long_tp1_hit and not long_tp1_hit[1]) and (long_tp2_hit and not long_tp2_hit[1]) ? long_stop[1] + tp_amount*2
 : (long_tp1_hit and not long_tp1_hit[1]) ? long_stop[1] + tp_amount 
 : (long_tp2_hit and not long_tp2_hit[1]) ? long_stop[1] + tp_amount 
 : long_stop[1]

short_stop      := condition ? short_stop_lvl 
 : (short_tp1_hit and not short_tp1_hit[1]) and (short_tp2_hit and not short_tp2_hit[1]) ? short_stop[1] - tp_amount*2
 : (short_tp1_hit and not short_tp1_hit[1]) ? short_stop[1] - tp_amount 
 : (short_tp2_hit and not short_tp2_hit[1]) ? short_stop[1] - tp_amount 
 : short_stop[1]


entered_signal  := strategy.position_size != 0 and strategy.position_size[1] == 0 ? true
 : condition ? false : entered_signal[1]

bars_since_entry := condition ? 1 : bars_since_entry[1] + 1
plot(bars_since_entry)


// send entry orders
if bars_since_cond <= _bars_for_entry and strategy.position_size == 0 and not entered_signal
    strategy.entry('LE', strategy.long, stop = long_entry_lvl)
    strategy.entry('SS_E', strategy.short, stop = short_entry_lvl)
else if strategy.position_size == 0
    strategy.cancel_all()


// long management
if strategy.position_size > 0
    strategy.cancel('SS_E')
    strategy.exit('LX1', 'LE', limit = long_tp1, stop = long_stop, comment_loss = 'L_SL', comment_profit = 'L_TP1', qty = strategy.position_size * (_tp1/100))
    strategy.exit('LX2', 'LE', limit = long_tp2, stop = long_stop, comment_loss = 'L_SL', comment_profit = 'L_TP2', qty = strategy.position_size * (_tp2/100))
    strategy.exit('LX3', 'LE', limit = long_tp3, stop = long_stop, comment_loss = 'L_SL', comment_profit = 'L_TP3')


// short management
if strategy.position_size < 0
    strategy.cancel('LE')
    strategy.exit('SS_X1', 'SS_E', limit = short_tp1, stop = short_stop, comment_loss = 'SS_SL', comment_profit = 'SS_TP1', qty = strategy.position_size * (_tp1/100))
    strategy.exit('SS_X2', 'SS_E', limit = short_tp2, stop = short_stop, comment_loss = 'SS_SL', comment_profit = 'SS_TP2', qty = strategy.position_size * (_tp2/100))
    strategy.exit('SS_X3', 'SS_E', limit = short_tp3, stop = short_stop, comment_loss = 'SS_SL', comment_profit = 'SS_TP3')


if _days_for_trade == bars_since_entry
    strategy.close_all('TX', 'Time Exit', immediately = true)


// visual
plotshape(condition, title = 'True Conditions', style = shape.circle, color = color.yellow, location = location.abovebar, size = size.tiny)
plotshape(condition, title = 'True Conditions', style = shape.circle, color = color.yellow, location = location.belowbar, size = size.tiny)

plot(long_entry_lvl, title = 'Long Entry Level', color = color.new(color.green, 75), style = plot.style_linebr)
plot(short_entry_lvl, title = 'Short Entry Level', color = color.new(color.red, 75), style = plot.style_linebr)

plot(strategy.position_avg_price, title = 'Entry Price', color = color.blue, style = plot.style_circles)

plot(strategy.position_size > 0 ? long_stop : strategy.position_size < 0 ? short_stop : na,
 title = 'Stop Price', color = color.fuchsia, style = plot.style_circles)

plot(strategy.position_size > 0 ? long_tp1 : strategy.position_size < 0 ? short_tp1 : na,
 title = 'TP1 Price', color = color.teal, style = plot.style_circles)
plot(strategy.position_size > 0 ? long_tp2 : strategy.position_size < 0 ? short_tp2 : na,
 title = 'TP2 Price', color = color.teal, style = plot.style_circles)
plot(strategy.position_size > 0 ? long_tp3 : strategy.position_size < 0 ? short_tp3 : na,
 title = 'TP3 Price', color = color.teal, style = plot.style_circles)

Overview

When this condition is met while flat, breakout levels are established above the high and below the low. Stop losses can be configured based on the opposite breakout level, previous close, or previous open, while target prices scale based on the breakout range. The strategy plots directly on the main price chart.

Details

Published by

g-moe on GitHub

Code credit

goodgains, as written in the script's header

Type

Strategy, Pine Script v5

Draws

On the price chart

Category

Breakout, Volatility & bands, Support & resistance

Markets

Any symbol

Timeframes

M15-H1, H4 and above

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
% Range Triggerfloat50.00_pct_range
Stop TypestringOpposite_stop_type
TP1 %float84.00_tp1
TP2 %float65.00_tp2
Trading Daysint4_days_for_trade
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

257 stars

This strategy plots VWMA-based Bollinger bands on the 1-minute ES futures price chart for volatility analysis and potential breakout identification. It calculates dynamic long and short stop loss and take profit levels using percentage inputs relative to entry

Strategy v6 Volatility & bandsSupport & resistance
Updated 6 weeks ago · None stated GitHub repository of V1.6 ES - Futures 1M No Repaint
16 stars

This strategy trades Donchian breakouts measured on weekly bars while orders execute on the chart timeframe. It allows long and short entries when price breaks the prior weekly channel and exits against the shorter weekly channel. Position size risks a set per

Strategy v6 TrendBreakout
Updated 11 months ago · None stated GitHub repository of Seykota Alt 4: Weekly Donchian
11 stars

Calculates upper and lower Donchian Channel bands over a customizable lookback length and plots them on the main price chart. At a specified exchange hour, the strategy places a long buy stop order at the upper Donchian Channel level. Unfilled pending orders a

Strategy v6 BreakoutSupport & resistance
Updated 5 months ago · Apache-2.0 GitHub repository of Estrategia Donchian Breakout
6 stars

This overlay strategy builds independent timed session ranges and marks range, trendline, mean, VWAP, and high-low levels when those displays are enabled. It enters on range breakouts and exits with strategy exits, choosing among range, ATR, fixed-point, and r

Strategy v5 Sessions & timeBreakout
Updated 7 months ago · None stated GitHub repository of MSG Enhanced LEGO System Strategy
3 stars

Donchian Channel Breakout is a Pine Script v5 strategy drawn on the price chart. It enters long when close crosses above the previous upper Donchian band and short when close crosses below the previous lower band, reversing with the opposite signal. An ATR tra

Strategy v5 BreakoutVolatility & bands
Updated 7 months ago · MIT GitHub repository of Donchian Channel Breakout

Breakout Strategy

by Web3Degenerate
2 stars

This strategy detects price breakouts beyond the high or low of a higher timeframe (default Daily) on an intraday chart. When the close crosses above the higher-timeframe high or below its low, it enters long or short, limiting execution to one breakout per di

Strategy v5 BreakoutSupport & resistance
Updated 2 years ago · None stated GitHub repository of Breakout Strategy

More strategys

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers