Indicator · Pine Script v5 · On the chart

Barbwire v3.0.0

by itmakesyousick· code credited to boitoki

Detects barbwire zones, runs of bars with unusually small size, and boxes them on the price chart.

View on GitHub

GitHub stars1on the repository
Pine versionv5runs as is
Lines of code423
Settings17inputs
LicenceNone statedfile: MPL-2.0
Last update4 years ago9 Jul 2022

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 indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

423 lines of Pine Script v5 from 3.0.0.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

3.0.0.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © boitoki

//@version=5
indicator("Barbwire", overlay=true, precision=2, max_boxes_count=300, max_lines_count=500)

import boitoki/AwesomeColor/5 as ac
import boitoki/ma_function/3 as ma
import boitoki/RCI/4 as rci_func

[hopen, hclose]         = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, [open, close])
hoc2                    = math.avg(math.max(hopen, hclose), math.min(hopen, hclose))
oc2                     = math.avg(math.max(open, close), math.min(open, close))

////////////
// DEFINE //

option_source1          = 'Open-Close Heikin-Ashi'
option_source4          = 'Open-Close'
option_source2          = 'High-Low'
option_source3          = 'Hybrid'
sign                    = 'Display'
GP1                     = sign
GP2                     = sign
GP3                     = sign
color_red               = #D93611
color_blue              = #1D5A73

//////////////
// FUNCTION //

//
f_HR (_open, _close) =>  math.abs(_open - _close)

// 
f_source (_type) => 
    switch _type
        option_source1      => f_HR(hopen, hlc3)
        option_source2      => f_HR(high, low)
        option_source3      => math.avg(f_HR(hopen, hlc3) * 0.6, f_HR(open, close) * 0.3, f_HR(high, low) * 0.1)
        option_source4      => f_HR(open, close)
        => f_HR(high, low)

//
f_get_data (_source, _len) =>
    data = array.new<float>()

    for i = 1 to _len
        array.push(data, _source[i])
    
    data

f_remove_boxes (_arr, _max) =>
    if array.size(_arr) > _max
        for i = _max to array.size(_arr)
            box.delete(array.shift(_arr))

f_get_width_by_box (_id) => math.abs(box.get_right(_id) - box.get_left(_id))

//
f_renderBox (_start, _processing, _end, _min, _border_width, _border_color, _bgcolor, _drawing_max, _show) =>
    start_notif     = false
    end_notif       = false
    count           = 0

    if _show
        var box barb_box    = na
        var label txt       = na
        var line top        = na
        var line bot        = na
        var float y1        = na
        var float y2        = na
        var int x1          = na
        line_style          = line.style_dotted
        var boxes           = array.new<box>()
        
        count              := f_get_width_by_box(barb_box)
    
        if _start
            x1 := bar_index
            y1 := high
            y2 := low
            barb_box := box.new(x1, y1, x1, y2, _border_color, _border_width, line.style_solid, bgcolor=_bgcolor)
            txt := label.new(x1, y1, '•', color=color.new(_border_color, 5), textcolor=ac.panda('verydarkgray'), size=size.tiny)
    
        if _processing
            y1 := math.max(y1, high)
            y2 := math.min(y2, low)
            box.set_top(barb_box, y1)
            box.set_bottom(barb_box, y2)
            box.set_right(barb_box, bar_index)
            label.set_y(txt, y1)
            label.set_text(txt, '•••')
            
            if count == _min
                start_notif := true
        
        if _end
            box.set_right(barb_box, bar_index)

            label.delete(txt)
    
            if count < _min
                box.delete(barb_box)
            else
                array.push(boxes, barb_box)
                
                f_remove_boxes(boxes, _drawing_max)
                end_notif := true
    
            y1 := na, y2 := na

    [start_notif, end_notif, count]

//
//
f_barb_start (in_barb)  => in_barb and (not in_barb[1])

f_barb_end (in_barb)    => (not in_barb) and in_barb[1]

//
//
f_dir_by_roc (_src, _len, _scale=2.0) =>
    roc_arr     = array.new<float>(_len)
    roc         = ta.roc(_src, 2)
    roc_moved   = math.abs(roc - roc[3])
    
    for i = 1 to _len
        array.push(roc_arr, roc_moved[i])

    min_roc_value   = array.min(roc_arr)
    min_roc_value  := array.stdev(roc_arr) * _scale
    
    roc_moved <= min_roc_value

// 
f_barb_roc (_len) =>
    height = math.max(hopen, hclose) - math.min(hopen, hclose)
    roc = ta.roc(height, _len)
    
    roc <= 0

//
f_barb_stoch (_source1, _source2, _len, _lv) =>
    v1 = ta.stoch(_source1, _source1, _source1, _len)
    v2 = ta.stoch(_source2, _source2, _source2, math.round(_len * 0.5))
    (v1 <= _lv) and (v2 <= _lv)

//
f_barb_rank (_source, _len, _sens) =>
    arr = array.new<float>(_len)
    new_arr = array.new<float>()

    for i = 1 to _len
        array.push(arr, _source[i])

    min_value = array.min(arr)
    min_value := array.percentile_nearest_rank(arr, _sens)
    min_value := math.max(min_value, syminfo.mintick * 2)

    in_barb = _source <= (min_value)

    in_barb

f_le (_v, _std, _malt) => _v <= _std * _malt
f_ge (_v, _std, _malt) => _v >= _std * _malt
f_id (_v, _arr) => array.indexof(_arr, array.min(_arr)) < _v

////////////
// INPUTS //

i_source_type           = input.string(option_source3, 'Source', options=[option_source1, option_source4, option_source2, option_source3])
i_min                   = input.int(4, 'Num. of minimum bars', minval=0)

i_show_barb             = input.bool(true, 'Mixed', group=GP1)

i_show_barb_stoch       = input.bool(false, 'Stochastic', group=GP1, tooltip='Length • Level %')
i_stoch_length          = input.int(50, '↔', inline='stoch_param', group=GP1)
i_stoch_level           = input.int(18, '/ ≤', inline='stoch_param', group=GP1)

i_show_barb_rank        = input.bool(false, 'Rank %', group=GP2, tooltip='Length • Level %')
i_len                   = input.int(100, '↔', inline='rank_param', group=GP2)
i_rank_level            = input.int(5, '/ ≤', minval=0, inline='rank_param', group=GP2)

i_show_barb_stdev       = false     //input.bool(false, '• Stdev', inline='stdev', group=GP3, tooltip='Level')
i_stdev_mult            = 0.20      //input.float(0.20, '', minval=0.0, step=0.01, inline='stdev', group=GP3)


// FILTER
i_dir_roc_sens          = 2.0       // input.float(2.0, '', minval=0, step=0.1, group='FILTER')
i_filter_stdev5         = true      // input.bool(true, 'Filtered ">5STDEV"', group='Filter')


// STYLE
i_border_width          = input.int(2, '', minval=0, group='style', inline='style', tooltip='Border width / color / bgcolor')
i_boxcolor              = input.color(color.new(#F2A341, 20), '', group='style', inline='style')
i_bgcolor               = input.color(color.new(#F4C58B, 84), '', group='style', inline='style')

i_barcolor              = input.bool(false, "Bar colors", group='OPTIONS')
i_spot_smallest         = input.bool(false, 'Smallest bar', inline='smallest_bar', group='OPTIONS')
i_smallest_color        = input.color(#F2A341, '', inline='smallest_bar', group='OPTIONS')
i_spot_largest          = input.bool(false, 'Largest bar', inline='largest_bar', group='OPTIONS')
i_largest_color         = input.color(#0C74A6, '', inline='largest_bar', group='OPTIONS')

i_spot_priceflip        = false     //input.bool(false, 'Price flip', group='OPTIONS')

i_memory_cleaning       = false     //input.bool(false, 'Memory cleaning', group='OPTIONS')
i_drawing_max           = i_memory_cleaning ? 5 : 200

//////////
// DATA //
HR                      = f_source(i_source_type)

data_len                = i_len

all_data                = f_get_data(HR, data_len)
all_stdev               = array.stdev(all_data)
a_data                  = array.new<float>()

if i_filter_stdev5 and array.size(all_data) > 0
    for i = 0 to array.size(all_data) - 1
        my_value = array.get(all_data, i)
        if my_value < all_stdev * 5
            array.push(a_data, my_value)
else
    a_data     := array.copy(all_data)

v_std                   = array.stdev(a_data)
v_avg                   = array.avg(a_data)

i_stdev_xs              = 0.18
i_stdev_s               = 0.50
i_stdev_l               = 4.00
i_stdev_xl              = 5.00

is_le030                = f_le(HR, v_std, i_stdev_s)
is_le005                = f_le(HR, v_std, i_stdev_xs)
is_small                = f_le(HR, v_std, i_stdev_xs)
is_geL                  = f_ge(HR, v_std, i_stdev_l)
is_geXL                 = f_ge(HR, v_std, i_stdev_xl)
is_largest              = is_geXL
is_smallest             = (f_id(1, a_data) or f_le(HR, v_std, i_stdev_xs))

if is_smallest[1]
    is_smallest        := false


//////////
// CALC //

// FILTER //
is_dir_by_roc           = f_dir_by_roc(hoc2, i_len, i_dir_roc_sens)

in_barb_by_stoch        = f_barb_stoch(f_HR(hopen, ohlc4), f_HR(high, low), i_stoch_length, i_stoch_level)
in_barb_by_rank         = f_barb_rank(HR, i_len, i_rank_level)  and is_dir_by_roc
in_barb_by_stdev        = f_le(HR, v_std, i_stdev_mult)         and is_dir_by_roc
in_barb_by_roc          = f_barb_roc(16)

in_barb                 = in_barb_by_stoch or in_barb_by_rank or in_barb_by_stdev


///////////////////
// Conditions
///////////////////


//////////////
// BARBWIRE //

//if i_filter_roc
//    is_barb := is_barb and is_dir_by_roc


stoch_barb_start        = f_barb_start(in_barb_by_stoch)
stoch_barb_end          = f_barb_end(in_barb_by_stoch)

rank_barb_start         = f_barb_start(in_barb_by_rank)
rank_barb_end           = f_barb_end(in_barb_by_rank)

stdev_barb_start        = f_barb_start(in_barb_by_stdev)
stdev_barb_end          = f_barb_end(in_barb_by_stdev)

barb_start              = f_barb_start(in_barb)
barb_end                = f_barb_end(in_barb)

// RENDERING //
f_renderBox(stoch_barb_start, in_barb_by_stoch, stoch_barb_end, i_min, i_border_width, i_boxcolor, i_bgcolor, i_drawing_max, i_show_barb_stoch and barstate.isconfirmed)
    
f_renderBox(rank_barb_start, in_barb_by_rank, rank_barb_end, i_min, i_border_width, i_boxcolor, i_bgcolor, i_drawing_max, i_show_barb_rank and barstate.isconfirmed)
    
f_renderBox(stdev_barb_start, in_barb_by_stdev, stdev_barb_end, i_min, i_border_width, i_boxcolor, i_bgcolor, i_drawing_max, i_show_barb_stdev and barstate.isconfirmed)
    
[start_notif, end_notif, barb_count] = f_renderBox(barb_start, in_barb, barb_end, i_min, i_border_width, i_boxcolor, i_bgcolor, i_drawing_max, i_show_barb and barstate.isconfirmed)

if in_barb and barb_count >= i_min
    is_smallest        := false

////////////////
// CONDITIONS //
bar_type                = close > open  ? 1 : -1
hbar_type               = ohlc4 > hopen ? 1 : -1

// TD Sequence
var TD                  = 0
var TS                  = 0
TD                     := ohlc4 > ohlc4[4] ? nz(TD[1])+1 : 0
TS                     := ohlc4 < ohlc4[4] ? nz(TS[1])+1 : 0
TDUp                    = TD - ta.valuewhen(TD < TD[1], TD , 1)
TDDn                    = TS - ta.valuewhen(TS < TS[1], TS , 1)

is_priceflip            = hbar_type != hbar_type[1]

///////////////
// RENDERING //



//////////////
// PLOTTING //
color bar_color = na

if i_barcolor
    if is_largest
        bar_color := i_largest_color
    else if is_smallest
        bar_color := i_smallest_color
    else 
        bar_color := na

barcolor(i_barcolor ? bar_color : na)
plotshape(i_spot_smallest and is_smallest ? oc2[1] : na, 'Smallest bar', text="Smallest bar", style=shape.diamond, color=color.new(i_smallest_color, 30), location=location.absolute, size=size.tiny , textcolor=color.new(color.white, 100), offset=-1)
plotshape(i_spot_largest  and is_largest  ? oc2[0] : na, 'Largest bar' , text="Largest bar" , style=shape.diamond, color=color.new(i_largest_color , 30), location=location.absolute, size=size.tiny , textcolor=color.new(color.white, 100))

plotshape(is_priceflip and hbar_type == -1 and TDUp and TD >= 12, 'Price flip sell', text="⌁", color=color_red , textcolor=color.white, style=shape.labeldown, location=location.abovebar, size=size.tiny, display=display.none)
plotshape(is_priceflip and hbar_type ==  1 and TDDn and TS >= 12, 'Price flip buy', text="⌁", color=color_blue, textcolor=color.white, style=shape.labelup  , location=location.belowbar, size=size.tiny, display=display.none)


///////////
// ALERT //
alertcondition(start_notif, "Barbwire start", "Barbwire start")
alertcondition(end_notif  , "Barbwire end"  , "Barbwire end"  )
alertcondition(is_smallest, "The smallest bar", "The smallest bar appeared")





//////////////
// ANALYSIS //

i_analysis_show         = false//input.bool(false, 'Analysis', group='ANALYSIS')
i_analysis_asc          = false//input.bool(false, 'Order ascending', group='ANALYSIS')

verticalAdj             = 0.6
lookbackLength          = i_len//input.int(200, 'Length', group='ANALYSIS')
priceHighest            = ta.highest(high, lookbackLength)
priceLowest             = ta.lowest (low , lookbackLength)
priceChangeRate         = (priceHighest - priceLowest) / priceHighest
oscTop                  = priceLowest  * (1 - priceChangeRate * 0.2)
oscBottom               = priceLowest  * (1 - priceChangeRate * verticalAdj)
priceHighest           := priceHighest * (1 + priceChangeRate * verticalAdj)
barIndex                = 0

oscHeight               = oscTop - oscBottom
oscHighest              = array.max(a_data)

analysis_data_          = f_get_data(HR, lookbackLength)
analysis_data           = array.new<float>()
analysis_stdev          = array.stdev(analysis_data_)

if i_filter_stdev5 and array.size(analysis_data_) > 0
    for i = 0 to array.size(analysis_data_) - 1
        my_value = array.get(analysis_data_, i)
    
        if my_value < analysis_stdev * 5
            array.push(analysis_data, my_value)
else
    analysis_data := array.copy(analysis_data_)    

var a_line = array.new<line>()
var a_labels = array.new<label>()

if barstate.islast and i_analysis_show and array.size(analysis_data) > 0

    if (array.size(a_line) > 0)
        for i = 0 to array.size(a_line) - 1
            line.delete(array.shift(a_line))
    
    if (array.size(a_labels) > 0)
        for i = 0 to array.size(a_labels) - 1
            label.delete(array.shift(a_labels))

    hightAdj = oscHeight / oscHighest

    rank        = array.percentile_nearest_rank(analysis_data, i_rank_level)
    stdev       = array.stdev(analysis_data)

    stdev_xs    = stdev * i_stdev_xs
    stdev_s     = stdev * i_stdev_s
    stdev_l     = stdev * i_stdev_l
    
    if i_analysis_asc
        array.sort(analysis_data, order.ascending)

    array.push(a_line, line.new(bar_index, oscTop,  bar_index - lookbackLength, oscTop,  width=1, color=color.new(color.blue, 75)))
    array.push(a_line, line.new(bar_index, oscBottom,  bar_index - lookbackLength, oscBottom,  width=1))
    array.push(a_line, line.new(bar_index, oscBottom,  bar_index - lookbackLength, oscBottom,  width=1))
    array.push(a_line, line.new(bar_index, oscBottom + (rank     * hightAdj), bar_index - lookbackLength, oscBottom + (rank     * hightAdj), style=line.style_dotted, width=1, color=color.new(color.orange, 30)))
    array.push(a_line, line.new(bar_index, oscBottom + (stdev_xs * hightAdj), bar_index - lookbackLength, oscBottom + (stdev_xs * hightAdj), style=line.style_dotted, width=1, color=color.new(color.purple, 30)))
    array.push(a_line, line.new(bar_index, oscBottom + (stdev_l  * hightAdj), bar_index - lookbackLength, oscBottom + (stdev_l  * hightAdj), style=line.style_dotted, width=1))
    array.push(a_labels, label.new(bar_index + 1, oscBottom + (rank     * hightAdj), 'Rank',     color=color.new(color.orange, 30), style=label.style_label_left, textcolor=color.white, size=size.tiny))
    array.push(a_labels, label.new(bar_index + 1, oscBottom + (stdev_xs * hightAdj), 'Stdev XS', color=color.new(color.purple, 30), style=label.style_label_left, textcolor=color.white, size=size.tiny))
    array.push(a_labels, label.new(bar_index + 1, oscBottom + (stdev_l  * hightAdj), 'Stdev L' , color=color.new(color.blue  , 30), style=label.style_label_left, textcolor=color.white, size=size.tiny))

    xc = int(math.avg(bar_index, bar_index - lookbackLength))
    array.push(a_line, line.new(xc, oscBottom, xc, oscBottom + oscHeight, style=line.style_dotted))

    for i = 0 to array.size(analysis_data) - 1
        y2 = array.get(analysis_data, i)
        color_bar   = y2 < (rank)   ? color.orange : y2 < (stdev) ? color.blue : color.from_gradient(50, 0, 100, color.blue, color.black)
        color_bar  := y2 < stdev_xs ? color.purple : color_bar

        array.push(a_line, line.new(bar_index - i, oscBottom, bar_index - i, oscBottom + (y2 * hightAdj), color=color.new(color_bar, 40), width=2) )

Overview

Bar size defaults to a hybrid blend of Heikin-Ashi, open-close and high-low measures. A mixed method is on by default, with optional stochastic and percent-rank methods that each have their own length and level. It can colour bars and flag the smallest and largest bars in a zone. A minimum bar count removes short zones.

Details

Published by

itmakesyousick on GitHub

Code credit

boitoki, as written in the script's header

Type

Indicator, Pine Script v5

Draws

On the price chart

Category

Candlestick patterns, Volatility & bands

Markets

Any symbol

Timeframes

Any timeframe

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

pinescript

Settings

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

SettingTypeDefaultVariable
Sourcestringoption_source3i_source_type
Num. of minimum barsint4i_min
Mixedbooltruei_show_barb
Stochasticboolfalsei_show_barb_stoch
↔int50i_stoch_length
/ ≤int18i_stoch_level
Rank %boolfalsei_show_barb_rank
↔int100i_len
/ ≤int5i_rank_level
i_border_widthint2i_border_width
i_boxcolorcolorcolor.new(#F2A341, 20)i_boxcolor
i_bgcolorcolorcolor.new(#F4C58B, 84)i_bgcolor
Show all 17 settings
SettingTypeDefaultVariable
Bar colorsboolfalsei_barcolor
Smallest barboolfalsei_spot_smallest
i_smallest_colorcolor#F2A341i_smallest_color
Largest barboolfalsei_spot_largest
i_largest_colorcolor#0C74A6i_largest_color
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

Body Mass Indicator

by harryguiacorn
219 stars

The Body Mass Indicator highlights candles with exceptionally large body ranges relative to recent price movement. It calculates the absolute distance between open and close prices. When enabled, it identifies bars where the body range achieves a new high over

Indicator v5 Volatility & bandsCandlestick patterns
Updated 1 year ago · None stated GitHub repository of Body Mass Indicator

Raschke Patterns

by TradersPost
218 stars

This overlay indicator marks Linda Raschke short-term bar setups on the price chart. It flags Turtle Soup and Turtle Soup plus one false breakouts of a prior extreme, 80-20 bars, inside bars, failed inside-bar breakouts, outside up and down bars, NR4 and NR7 c

Indicator v6 Candlestick patternsBreakout Repaints
Updated 3 months ago · None stated GitHub repository of Raschke Patterns

Five-in-one Strategy

by capissimo
114 stars

Five-in-one Strategy combines five analytical tools into a single price chart overlay: the Dual Thrust Trading Algorithm (DTTA), Semafore, HalfTrend, Nick Rypock Trailing Reverse, and Tweezer or Kangaroo Tail candlestick patterns. It generates trade signals us

Indicator v4 TrendBreakout Repaints
Updated 1 year ago · None stated GitHub repository of Five-in-one Strategy

Force Bar

by milocaetano
48 stars

Force Bar highlights candlesticks directly on the price chart using three distinct body and range criteria: widest range (Biggest), extreme body relative to historical average (Exhaustion), and moderate body relative to historical average (Force). Colors apply

Indicator v5 Candlestick patternsVolatility & bands
Updated 2 days ago · MIT GitHub repository of Force Bar

Zen Z Bars V1

by Zen-Tim
29 stars

Zen Z Bars V1 analyzes bar-by-bar price action, candle range expansion, and internal bar strength (IBS). It identifies breakouts, inside and outside bars, climax candles based on range expansion factors, and tiered range multiple bars. The indicator draws brea

Indicator v5 Candlestick patternsBreakout
Updated 2 weeks ago · MIT GitHub repository of Zen Z Bars V1
15 stars

This indicator plots Bollinger Bands and smoothed HAMA candles on the price chart. It builds each candle from separate moving averages of open, high, low and close, using selectable EMA, SMA or WMA lengths. A simple moving average forms the band basis, and an

Indicator v5 Candlestick patternsMoving averages
Updated 4 months ago · Apache-2.0 GitHub repository of NSDT HAMA Candles with Bollinger Bands

More indicators

Trade Your Charts With a Regulated Broker

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

Compare brokers