Strategy · Pine Script v5 · On the chart

Breakout Trend Follower

by hasnocool

Breakout Trend Follower is a price-chart strategy that enters long when price breaks a recent swing high.

View on GitHub

Repaints

GitHub stars106on the repository
Pine versionv5runs as is
Lines of code130
Settings21inputs
LicenceGPL-3.0
Last update2 years ago18 Sep 2024

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

130 lines of Pine Script v5 from Breakout Trend Follower Strategy.pine, published under GPL-3.0. Keep the author's credit and licence lines when you reuse it.

Breakout Trend Follower Strategy.pine
//@version=5
// Revision:    3
// Author:      @millerrh
// Strategy:  Enter long when recent swing high breaks out, using recent swing low as stop level.  Move stops up as higher lows print to act
// as trailing stops.  Ride trend as long as it is there and the higher lows aren't breached.  
// Conditions/Variables 
//    1. Manually configure which dates to back test
//    2. Can add a filter to only take setups that are above (or below for shorts) user-defined moving average(s) (helps avoid trading counter trend) 
//    3. Can ignore signals that are too extended and not consolidating enough based on ADR and/or RSI.
//    4. Color background of trades - helps to easily see at a glance if the strategy should be long or not. 
// === CALL STRATEGY/STUDY, PROGRAMATICALLY ENTER STRATEGY PARAMETERS HERE SO YOU DON'T HAVE TO CHANGE THEM EVERY TIME YOU RUN A TEST ===
// (STRATEGY ONLY) - Comment out srategy() when in a study() 
strategy('Breakout Trend Follower', overlay=true, initial_capital=10000, currency='USD', calc_on_every_tick = true,
  default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.1)
// === BACKTEST RANGE ===
Start = input.time(defval=timestamp('01 Jan 2019 06:00 +0000'), title='Backtest Start Date', group = "backtest window")
Finish = input.time(defval=timestamp('01 Jan 2100 00:00 +0000'), title='Backtest End Date', group = "backtest window")
// === USER INPUTS ===
pvtLb = input.int(defval=3, title='Pivot Lookback', minval=1, group = "support & resistance levels",
  tooltip = "Number of bars to left and right to deterine local pivot.")
showPivotPoints = input.bool(title = "Show Historical Pivot Points?", defval = false, group = "support & resistance levels",
  tooltip = "Toggle this on to see the historical pivot points that were used.")
currentColorS = input.color(color.new(color.orange,50), title = "Current Range S/R Colors:    Support",group = "support & resistance levels", inline = "lineColor")
currentColorR = input.color(color.new(color.blue,50), title = " Resistance", group = "support & resistance levels", inline = "lineColor")
useMaFilter = input.bool(title='Use Current Timeframe Moving Average for Filtering?', defval=true, group = "moving average filters",
  tooltip='Signals will be ignored when price is under this moving average.  The intent is to keep you out of bear periods and only buying when  price is showing strength.')
maType = input.string(defval='SMA', options=['EMA', 'SMA'], group = "moving average filters",title='MA Type For Filtering')
maLength = input.int(defval=50, title='MA Period for Filtering', minval=1, group = "moving average filters", inline = "1ma")
ma1Color = input.color(color.new(color.purple, 60), title = " Color", group = "moving average filters", inline = "1ma")
useMaFilter2 = input.bool(title='Use Multi-Timeframe Moving Average for Filtering?', defval=false, group = "moving average filters",
  tooltip='Signals will be ignored when price is under this moving average.  The intent is to keep you out of bear periods and only buying when  price is showing strength. Other timeframe allows you to use Daily moving average for higher level view of market strength.')
tfSet = input.timeframe(defval='D', title='Moving Average Time Frame', group = "moving average filters",
  tooltip='Allows you to set a different time frame moving average to filter your signals by.')
ma2Type = input.string(defval='SMA', options=['EMA', 'SMA'], title='MA Type For Filtering', group = "moving average filters")
ma2Length = input.int(defval=50, title='MA Period for Filtering', minval=1, group = "moving average filters", inline = "2ma")
ma2Color = input.color(color.new(color.yellow, 60), title = " Color", group = "moving average filters", inline = "2ma")
// === MOVING AVERAGE CALCULATIONS === 
// Declare function to be able to swap out EMA/SMA
ma(maType, src, length) =>
    maType == 'EMA' ? ta.ema(src, length) : ta.sma(src, length)  //Ternary Operator (if maType equals EMA, then do ema calc, else do sma calc)
maFilter = ma(maType, close, maLength)
maFilter2 = request.security(syminfo.tickerid, tfSet, ma(ma2Type, close, ma2Length))
plot(useMaFilter ? maFilter : na, title='Trend Filter MA', color=ma1Color, linewidth=2, style=plot.style_line)
plot(useMaFilter2 ? maFilter2 : na, title='Trend Filter MA', color=ma2Color, linewidth=2, style=plot.style_line)
// === USE RSI FOR FILTERING ===
// The idea here is that you want to buy in a consolodating range for best risk/reward. With the RSI filter, you make sure that the previous bars' RSI 
// level is not overbought/overextended before deciding to take a position on.
useRsiFilter = input.bool(title='Use RSI for Filtering?', defval=false, group = "rsi filtering",
  tooltip='Signals will be ignored if the RSI level is above a user-defined level for overbought.  This allows the user to ensure they are not buying something that is too extended and instead focus on names that are consolidating more.')
rsiTf = input.timeframe(defval='', title='RSI Timeframe', group = "rsi filtering",
  tooltip='Allows you to set a different time frame for RSI to filter your signals by.')
rsiOB = input.int(defval=70, title='RSI Overbought Level', minval=1, group = "rsi filtering")
rsiVal = request.security(syminfo.tickerid, rsiTf, ta.rsi(close, 14))
// === PLOT SWING HIGH/LOW AND MOST RECENT LOW TO USE AS STOP LOSS EXIT POINT ===
// Get High and Low Pivot Points
ph = ta.pivothigh(high, pvtLb, pvtLb)
pl = ta.pivotlow(low, pvtLb, pvtLb)
highLevel = ta.valuewhen(ph, high[pvtLb], 0)
lowLevel = ta.valuewhen(pl, low[pvtLb], 0)
barsSinceHigh = ta.barssince(ph) + pvtLb
barsSinceLow = ta.barssince(pl) + pvtLb
timeSinceHigh = time[barsSinceHigh]
timeSinceLow = time[barsSinceLow]
//Removes color when there is a change to ensure only the levels are shown (i.e. no diagonal lines connecting the levels)
pvthis = fixnan(ph)
pvtlos = fixnan(pl)
hipc = ta.change(pvthis) != 0 ? na : color.maroon
lopc = ta.change(pvtlos) != 0 ? na : color.green
// Display Pivot lines
plot(showPivotPoints ? pvthis : na, color=hipc, linewidth=1, offset=-pvtLb, title="Top Levels")
plot(showPivotPoints ? pvthis : na, color=hipc, linewidth=1, offset=0, title="Top Levels 2")
plot(showPivotPoints ? pvtlos : na, color=lopc, linewidth=1, offset=-pvtLb, title="Bottom Levels")
plot(showPivotPoints ? pvtlos : na, color=lopc, linewidth=1, offset=0, title="Bottom Levels 2")
// == PLOT SUPPORT/RESISTANCE LINES FOR CURRENT CHART TIMEFRAME ==
// Use a function to define the lines
f_line(x1, y1, y2, _color) =>
    var line id = na
    line.delete(id)
    id := line.new(x1, y1, time, y2, xloc.bar_time, extend.right, _color)
highLine = f_line(timeSinceHigh, highLevel, highLevel, currentColorR)
lowLine = f_line(timeSinceLow, lowLevel, lowLevel, currentColorS)
// === USE ADR FOR FILTERING ===
// The idea here is that you want to buy in a consolodating range for best risk/reward. So here you can compare the current distance between 
// support/resistance vs. the ADR and make sure you aren't buying at a point that is too extended.
useAdrFilter = input.bool(title = "Use ADR for Filtering?", defval = false, group = "adr filtering",
  tooltip = "Signals will be ignored if the distance between support and resistance is larger than a user-defined percentage of ADR (or monthly volatility
  in the stock screener). This allows the user to ensure they are not buying something that is too extended and instead focus on names that are consolidating more.")
adrPerc = input.int(defval = 120, title = "% of ADR Value", minval = 1, group = "adr filtering")
tableLocation = input.string(defval="Bottom", options=["Top", "Bottom"], title = "ADR Table Visibility", group = "adr filtering",
  tooltip = "Place ADR table on the top of the pane, the bottom of the pane, or off.")
adrValue = request.security(syminfo.tickerid, "D", ta.sma((high-low)/math.abs(low) * 100, 21), barmerge.gaps_off, barmerge.lookahead_on) // Monthly Volatility in Stock Screener (also ADR)
adrCompare = (adrPerc * adrValue) / 100
// == ADR TABLE ==
tablePos = tableLocation == "Top" ? position.top_right : position.bottom_right
var table adrTable = table.new(tablePos, 2, 1, border_width = 3)
lightTransp = 90
avgTransp   = 80
heavyTransp = 70
posColor = color.rgb(38, 166, 154)
negColor = color.rgb(240, 83, 80)
volColor = color.new(#999999, 0)
f_fillCellVol(_table, _column, _row, _value) =>
    _transp = math.abs(_value) > 7 ? heavyTransp : math.abs(_value) > 4 ? avgTransp : lightTransp
    _cellText = str.tostring(_value, "0.00") + "%\n" + "ADR"
    table.cell(_table, _column, _row, _cellText, bgcolor = color.new(volColor, _transp), text_color = volColor, width = 6)
srDistance = (highLevel - lowLevel)/highLevel * 100
f_fillCellCalc(_table, _column, _row, _value) =>
    _c_color = _value >= adrCompare ? negColor : posColor
    _transp = _value >= adrCompare*0.8 and _value <= adrCompare*1.2 ? lightTransp : 
      _value >= adrCompare*0.5 and _value < adrCompare*0.8 ? avgTransp :
      _value < adrCompare*0.5 ? heavyTransp :
      _value > adrCompare*1.2 and _value <= adrCompare*1.5 ? avgTransp :
      _value > adrCompare*1.5 ? heavyTransp : na
    _cellText = str.tostring(_value, "0.00") + "%\n" + "Range"
    table.cell(_table, _column, _row, _cellText, bgcolor = color.new(_c_color, _transp), text_color = _c_color, width = 6)
if barstate.islast
    f_fillCellVol(adrTable, 0, 0, adrValue)
    f_fillCellCalc(adrTable, 1, 0, srDistance)
// Conditions for entry and exit
buyConditions = (useMaFilter ? highLevel > maFilter : true) and 
  (useMaFilter2 ? highLevel > maFilter2 : true) and 
  (useAdrFilter ? highLevel - lowLevel < adrValue : true) and 
  (useRsiFilter ? rsiVal[1] < rsiOB : true) and 
  time > Start and time < Finish
// (STRATEGY ONLY) Comment out for Study
strategy.entry('Long', strategy.long, stop=highLevel, when=buyConditions)
// strategy.entry("Long", strategy.long, stop = buyLevel2, when = time > Start and time < Finish and high > maFilterCheck)
strategy.exit('Exit Long', from_entry='Long', stop=lowLevel)
strategy.cancel('Long', when=not(buyConditions)) // Cancels resting orders when new swing high is printed below filters.
Expand (149 lines)

Overview

Breakout Trend Follower places the stop at the recent swing low and trails that stop upward as higher lows form, exiting when a higher low is breached. A pivot lookback sets how swings are found. Optional filters skip setups below a current-timeframe or higher-timeframe moving average, or when RSI or average daily range shows the move is too extended. Users set the backtest window and can show historical pivots. It recalculates on every tick, so signals can change on the live bar.

Details

Published by

hasnocool on GitHub

Type

Strategy, Pine Script v5

Draws

On the price chart

Category

Breakout, Trend, Support & resistance, Moving averages

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

  • Signals can change on the live bar or after it closes (repainting)

Topics

analysisbtcusdtcryptocurrencydatapandaspythonsimulationtradingtradingview

Settings

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

SettingTypeDefaultVariable
Backtest Start Datetimetimestamp('01 Jan 2019 06:00 +0000')Start
Backtest End Datetimetimestamp('01 Jan 2100 00:00 +0000')Finish
Pivot Lookbackint3pvtLb
Show Historical Pivot Points?boolfalseshowPivotPoints
Current Range S/R Colors:    Supportcolorcolor.new(color.orange,50)currentColorS
 Resistancecolorcolor.new(color.blue,50)currentColorR
Use Current Timeframe Moving Average for Filtering?booltrueuseMaFilter
MA Type For FilteringstringSMAmaType
MA Period for Filteringint50maLength
 Colorcolorcolor.new(color.purple, 60)ma1Color
Use Multi-Timeframe Moving Average for Filtering?boolfalseuseMaFilter2
Moving Average Time FrametimeframeDtfSet
Show all 21 settings
SettingTypeDefaultVariable
MA Type For FilteringstringSMAma2Type
MA Period for Filteringint50ma2Length
 Colorcolorcolor.new(color.yellow, 60)ma2Color
Use RSI for Filtering?boolfalseuseRsiFilter
RSI TimeframetimeframersiTf
RSI Overbought Levelint70rsiOB
Use ADR for Filtering?boolfalseuseAdrFilter
% of ADR Valueint120adrPerc
ADR Table VisibilitystringBottomtableLocation
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 running pivot highs as red R circles and pivot lows as blue S circles directly on the price chart. It computes an EMA 3 and a Cto trend line from close prices, then generates long signals on upward EMA-Cto crossovers combined with price pos

Strategy v6 TrendMoving averages Repaints
Updated 6 weeks ago · None stated GitHub repository of Best Chart 1m Strategy Candle Bar
43 stars

This strategy executes trades on short-term cryptocurrency charts using a combination of pivot support and resistance levels and a multi-pole smoothed trend filter. Entries trigger when price crosses the smoothed trend line and confirms above or below a short-

Strategy v5 TrendBreakout Repaints
Updated 2 years ago · None stated GitHub repository of SOL 1m - Strategy Candle Bar
8 stars

This strategy identifies trend retracements and breakout entries using an adjustable moving average ribbon alongside higher-timeframe anchored moving averages, fractal pivots, and support and resistance level extensions. Bar colors can be customized using a 3-

Strategy v5 TrendMoving averages
Updated 4 years ago · None stated GitHub repository of Pullback Trading Tool ALT

Pivot Trendlines

by g-moe
3 stars

The Pivot Trendlines strategy identifies swing pivots on the price chart using a configurable swing lookback period and draws trendlines connecting these pivots. It generates buy and sell signals based on three-move patterns with user-defined move sizes, filte

Strategy v5 TrendBreakout
Updated 5 months ago · None stated GitHub repository of Pivot Trendlines

RR Dangov

by IAMATOMIC001
3 stars

RR Dangov is a price-chart strategy that combines optional confluence modules for entries. The trader selects a primary and a secondary source from Guppy moving averages, VWAP, an opening-range breakout, Supertrend, or CPR, and can add WaveTrend, stochastic, a

Strategy v5 TrendMoving averages
Updated 12 months ago · None stated GitHub repository of RR Dangov

This trend-following strategy executes a classic Donchian channel breakout system designed to cross-validate backtest results against external framework benchmarks. It triggers a long entry when the closing price breaks above the highest high of the prior entr

Strategy v6 BreakoutTrend
Updated today · AGPL-3.0 GitHub repository of Forven S01509 - Simple Donchian 20/10 Breakout

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