Strategy · Pine Script v5 · On the chart

BBPullback

by hasnocool· code credited to westofpluto

This strategy executes pullback trades based on internally computed Bollinger Bands and candle price action directly on the main price chart.

View on GitHub

GitHub stars106on the repository
Pine versionv5runs as is
Lines of code239
Settings3inputs
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

239 lines of Pine Script v5 from BBPullback1.0.2.pine, published under GPL-3.0. Keep the author's credit and licence lines when you reuse it.

BBPullback1.0.2.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © westofpluto
//@version=5
strategy("BBPullback", overlay=true, margin_long=100, margin_short=100,process_orders_on_close=true)
TAKE_PROFIT_HILO = 0
TAKE_PROFIT_CLOSE = 1
TAKE_PROFIT_BB = 2
OPTION0 = "high crosses MA"
OPTION1 = "closes beyond MA"
OPTION2 = "high crosses opposite band"
tpoption=input.string(OPTION0,title="Take Proft trigger",options=[OPTION0,OPTION1,OPTION2])
i_from = input.time(defval = timestamp("23 Feb 2023 00:00 +0000"), title = "From")
i_thru = input.time(defval = timestamp("09 Apr 2023 00:00 +0000"), title = "Thru")
var take_profit_option=TAKE_PROFIT_HILO
if tpoption == OPTION0
    take_profit_option := TAKE_PROFIT_HILO
else if tpoption == OPTION1
    take_profit_option := TAKE_PROFIT_CLOSE
else
    take_profit_option := TAKE_PROFIT_BB
//
// COMPUTE BOLLINGER BANDS INTERNALLY    
//
source = close
length = 20
mult = 2.0
basis = ta.sma(source, length)
dev = mult * ta.stdev(source, length)
upperBBValue = basis + dev
lowerBBValue = basis - dev
NO_SETUP = 0
BB_BREAK_DOWN = 1
RETRACE_BAR_UP = 2
PENDING_ENTRY_LONG = 3
ENTRY_LONG = 4
BB_BREAK_UP = 5
RETRACE_BAR_DOWN = 6
PENDING_ENTRY_SHORT = 7
ENTRY_SHORT = 8
ID_STATE = 0
ID_BUY_ENTRY = 0
ID_SELL_ENTRY = 1
ID_BUY_STOPLOSS = 2
ID_SELL_STOPLOSS = 3
ID_SWING_HIGH = 4
ID_SWING_LOW = 5
LARGE_NUMBER = 99999999.9
var state = NO_SETUP
var buy_entry_price = 0.0
var sell_entry_price = 0.0
var buy_stoploss_price = 0.0
var sell_stoploss_price = 0.0
var swing_low = LARGE_NUMBER
var swing_high = 0.0
var themax = 0.0
var themin = 99999999.0
//global_float = array.new_bool(1)
//array.set(global_bool,ID_TRENDMODEON,trendMode)
global_int = array.new_int(1)
array.set(global_int,ID_STATE,state)
global_float = array.new_float(6)
array.set(global_float,ID_BUY_ENTRY,buy_entry_price)
array.set(global_float,ID_SELL_ENTRY,sell_entry_price)
array.set(global_float,ID_BUY_STOPLOSS,buy_stoploss_price)
array.set(global_float,ID_SELL_STOPLOSS,sell_stoploss_price)
array.set(global_float,ID_SWING_HIGH,swing_high)
array.set(global_float,ID_SWING_LOW,swing_low)
//
// Main code starts here, executes every bar
//
dateok() => 
    time >= i_from and time <= i_thru 
minval(x, y) =>
    (x < y ? x : y)
maxval(x, y) =>
    (x > y ? x : y)
IsFlat() =>
    strategy.position_size == 0
HasPosition() =>
    strategy.position_size != 0
PullbackCandleLong() =>
    close >= open or low > low[1]
PullbackCandleShort() =>
    close <= open or high < high[1]
isUpCandle() =>
    close >= open
isDownCandle() =>
    open > close
StateInTrade() =>
    array.get(global_int,ID_STATE) == ENTRY_LONG or array.get(global_int,ID_STATE) == ENTRY_SHORT
StatePendingLong() =>
    array.get(global_int,ID_STATE) == PENDING_ENTRY_LONG
StatePendingShort() =>
    array.get(global_int,ID_STATE) == PENDING_ENTRY_SHORT
StateInLongTrade() =>
    array.get(global_int,ID_STATE) == ENTRY_LONG
StateInShortTrade() =>
    array.get(global_int,ID_STATE) == ENTRY_SHORT
LongTakeProfitHigh() =>
    high > basis
ShortTakeProfitLow() =>
    low < basis
LongTakeProfitClose() =>
    close > basis
ShortTakeProfitClose() =>
    close < basis
LongTakeProfitBB() =>
    high > upperBBValue
ShortTakeProfitBB() =>
    low < lowerBBValue
LongTakeProfitHit() =>
    if take_profit_option == TAKE_PROFIT_HILO
        LongTakeProfitHigh()
    else if take_profit_option == TAKE_PROFIT_CLOSE
        LongTakeProfitClose()
    else
        LongTakeProfitBB()
ShortTakeProfitHit() =>
    if take_profit_option == TAKE_PROFIT_HILO
        ShortTakeProfitLow()
    else if take_profit_option == TAKE_PROFIT_CLOSE
        ShortTakeProfitClose()
    else
        ShortTakeProfitBB()
LongTriggerCondition() =>
    if (dateok() and isUpCandle() and minval(open,close) < lowerBBValue and high < basis and high > lowerBBValue) 
        true
    else
        false
ShortTriggerCondition() =>
    if (dateok() and isDownCandle() and maxval(open,close) > upperBBValue and low > basis and low < upperBBValue) 
        true
    else
        false
if (HasPosition() and StatePendingLong())
    array.set(global_int,ID_STATE,ENTRY_LONG)
else if (HasPosition() and StatePendingShort())
    array.set(global_int,ID_STATE,ENTRY_SHORT)
else if (IsFlat() and StateInTrade()) 
    array.set(global_int,ID_STATE,NO_SETUP)
//
// If an order didn't trigger this bar then cancel it
//
var cancel_long=false
var cancel_short=false
if IsFlat()
    if (array.get(global_int,ID_STATE) == PENDING_ENTRY_LONG)
        cancel_long := true
        strategy.cancel("Enter Long")
        array.set(global_int,ID_STATE,NO_SETUP)
    else if (array.get(global_int,ID_STATE) == PENDING_ENTRY_SHORT)
        cancel_short := true
        strategy.cancel("Enter Short")
        array.set(global_int,ID_STATE,NO_SETUP)
//
// Trading logic long
//
if IsFlat()
    if (array.get(global_int,ID_STATE) == NO_SETUP) 
        if (LongTriggerCondition()) 
            //array.set(global_int,ID_STATE,BB_BREAK_DOWN)
            array.set(global_float,ID_BUY_ENTRY,high)
            if (cancel_long) 
                array.set(global_float,ID_SWING_LOW,minval(low,array.get(global_float,ID_SWING_LOW)))
            else
                array.set(global_float,ID_SWING_LOW,low)
            
            array.set(global_float,ID_SWING_HIGH,0.0)
            //array.set(global_float,ID_BUY_STOPLOSS,array.get(global_float,ID_SWING_LOW))
            array.set(global_float,ID_BUY_STOPLOSS,low)
            strategy.entry("Enter Long", strategy.long,stop=array.get(global_float,ID_BUY_ENTRY),limit=array.get(global_float,ID_BUY_ENTRY))
            array.set(global_int,ID_STATE,PENDING_ENTRY_LONG)
            strategy.exit("Stop Out",from_entry="Enter Long",stop=array.get(global_float,ID_BUY_STOPLOSS))
    else if (array.get(global_int,ID_STATE) == BB_BREAK_DOWN) 
        if (PullbackCandleLong())
            array.set(global_float,ID_BUY_ENTRY,high)
            array.set(global_float,ID_BUY_STOPLOSS,low)
            strategy.entry("Enter Long", strategy.long,stop=array.get(global_float,ID_BUY_ENTRY),limit=array.get(global_float,ID_BUY_ENTRY))
            array.set(global_int,ID_STATE,PENDING_ENTRY_LONG)
    else if (array.get(global_int,ID_STATE) == PENDING_ENTRY_LONG) 
        strategy.cancel("Enter Long")
        array.set(global_int,ID_STATE,NO_SETUP)
//if (array.get(global_int,ID_STATE) == PENDING_ENTRY_LONG) 
//    strategy.exit("Stop Out",from_entry="Enter Long",stop=array.get(global_float,ID_BUY_STOPLOSS))
//
// Trading logic short
//
if IsFlat()
    if (array.get(global_int,ID_STATE) == NO_SETUP) 
        if (ShortTriggerCondition())
            //array.set(global_int,ID_STATE,BB_BREAK_UP)
            array.set(global_float,ID_SELL_ENTRY,low)
            if (cancel_short) 
                array.set(global_float,ID_SWING_HIGH,maxval(high,array.get(global_float,ID_SWING_HIGH)))
            else
                array.set(global_float,ID_SWING_HIGH,high)
            array.set(global_float,ID_SWING_LOW,LARGE_NUMBER)
            //array.set(global_float,ID_SELL_STOPLOSS,array.get(global_float,ID_SWING_HIGH))
            array.set(global_float,ID_SELL_STOPLOSS,high)
            strategy.entry("Enter Short", strategy.short,stop=array.get(global_float,ID_SELL_ENTRY))
            array.set(global_int,ID_STATE,PENDING_ENTRY_SHORT)
            strategy.exit("Stop Out",from_entry="Enter Short",stop=array.get(global_float,ID_SELL_STOPLOSS))
    else if (array.get(global_int,ID_STATE) == BB_BREAK_UP)
        if (PullbackCandleShort())
            //array.set(global_int,ID_STATE,RETRACE_BAR_DOWN)
            array.set(global_float,ID_SELL_ENTRY,low)
            array.set(global_float,ID_SELL_STOPLOSS,high)
            strategy.entry("Enter Short", strategy.short,stop=array.get(global_float,ID_SELL_ENTRY))
            array.set(global_int,ID_STATE,PENDING_ENTRY_SHORT)
    else if (array.get(global_int,ID_STATE) == PENDING_ENTRY_SHORT) 
        strategy.cancel("Enter Short")
        array.set(global_int,ID_STATE,NO_SETUP)
//if (array.get(global_int,ID_STATE) == PENDING_ENTRY_SHORT) 
//    strategy.exit("Stop Out",from_entry="Enter Short",stop=array.get(global_float,ID_SELL_STOPLOSS))
if StateInLongTrade()
    if (LongTakeProfitHit()) 
        strategy.close("Enter Long",comment="Take Profit")
        array.set(global_int,ID_STATE,NO_SETUP)
else if StateInShortTrade()
    if (ShortTakeProfitHit())
        strategy.close("Enter Short",comment="Take Profit")
        array.set(global_int,ID_STATE,NO_SETUP)
state := array.get(global_int,ID_STATE)
buy_entry_price := array.get(global_float,ID_BUY_ENTRY)
sell_entry_price := array.get(global_float,ID_SELL_ENTRY)
buy_stoploss_price := array.get(global_float,ID_BUY_STOPLOSS)
sell_stoploss_price := array.get(global_float,ID_SELL_STOPLOSS)
themin := minval(open,close)
themax := maxval(open,close)
plotchar(state, "State", "", location = location.top)
plotchar(themin, "TheMin", "", location = location.top)
plotchar(themax, "TheMax", "", location = location.top)
plotchar(upperBBValue, "UpperBB", "", location = location.top)
plotchar(lowerBBValue, "LowerBB", "", location = location.top)
plotchar(buy_stoploss_price, "buy stoploss", "", location = location.top)
plotchar(sell_stoploss_price, "sell stoploss", "", location = location.top)
swing_low := array.get(global_float,ID_SWING_LOW)
plotchar(swing_low, "SwingLow", "", location = location.top)
Expand (293 lines)

Overview

BBPullback tracks breakout and pullback states to trigger long and short entries. Users can select among three distinct take profit exit options, including moving average crossovers, bar closes beyond the moving average, or band touches, alongside dedicated swing-based stop loss levels. Key settings let traders customize the take profit mechanism and filter trade execution by a specific date window. Execution is restricted to the chosen date range.

Details

Published by

hasnocool on GitHub

Code credit

westofpluto, as written in the script's header

Type

Strategy, Pine Script v5

Draws

On the price chart

Category

Volatility & bands, Mean reversion, Breakout

Markets

Crypto

Timeframes

M1-M5

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.

Topics

analysisbtcusdtcryptocurrencydatapandaspythonsimulationtradingtradingview

Settings

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

SettingTypeDefaultVariable
Take Proft triggerstringOPTION0tpoption
Fromtimetimestamp("23 Feb 2023 00:00 +0000")i_from
Thrutimetimestamp("09 Apr 2023 00:00 +0000")i_thru
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
218 stars

This strategy detects price breakouts above rolling highest highs or below lowest lows over a customizable lookback period. It includes optional volume spike and ATR volatility threshold filters, along with bar confirmation rules. Positions are taken upon conf

Strategy v6 BreakoutVolatility & bands
Updated 3 months ago · None stated GitHub repository of Breakout Strategy Template

Bollinger Breakout

by hackingthemarkets
189 stars

This price-chart strategy plots a simple moving average and upper and lower bands built from the standard deviation of close, scaled by separate offset inputs. It enters a fixed quantity long when close crosses above the upper band and a fixed quantity short w

Strategy v4 Volatility & bandsBreakout
Updated 3 years ago · None stated GitHub repository of Bollinger Breakout

Bollinger Bands Strategy

by cklose2000
105 stars

This strategy generates buy and sell signals based on Bollinger Band crossovers combined with a simple moving average trend filter. It enters a long position when price crosses above the lower band while trading above the SMA filter line, and enters a short po

Strategy v5 Volatility & bandsMoving averages
Updated 1 year ago · None stated GitHub repository of Bollinger Bands Strategy
104 stars

This strategy combines Bollinger Bands with a short RSI to fade moves that leave the bands and then return. A long requires the prior bar below the lower band and oversold, then a close back inside the band while RSI is between 30 and 50. Shorts mirror that at

Strategy v5 Oscillators & momentumVolatility & bands
Updated 3 years ago · MIT GitHub repository of Bollinger Bands and RSI 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