Indicator · Pine Script v4 · Own pane

[RS] Bar Pattern Statistics Tool

by ricardosantos79· code credited to RicardoSantos

Bar Pattern Statistics Tool evaluates sequential candlestick formations and displays historical occurrence statistics in a separate pane.

View on GitHub

GitHub stars261on the repository
Pine versionv4older, still runs
Lines of code179
Settings13inputs
LicenceNone statedfile: MPL-2.0
Last update4 years ago13 Nov 2021

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

179 lines of Pine Script v4 from test.pinescript, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

test.pinescript
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © RicardoSantos

//@version=4
study(title='[RS]Bar Pattern Statistics Tool', shorttitle='bst', overlay=false)

string op_type_01 = 'inside bar'
string op_type_02 = 'outside bar'
string op_type_03 = 'up bar'
string op_type_04 = 'down bar'
string op_type_05 = 'up pin bar'
string op_type_06 = 'down pin bar'
string op_type_07 = 'any type of bar'
f_enum_type(_str)=>(_str==op_type_01?1:(_str==op_type_02?2:(_str==op_type_03?3:(_str==op_type_04?4:(_str==op_type_05?5:(_str==op_type_06?6:(_str==op_type_07?7:na)))))))
f_enum_type_by_idx(_i)=>(_i==1?op_type_01:(_i==2?op_type_02:(_i==3?op_type_03:(_i==4?op_type_04:(_i==5?op_type_05:(_i==6?op_type_06:(_i==7?op_type_07:op_type_07)))))))

float body_range = abs(close - open)
float hl_range = high - low
float upperwick = high - max(close, open)
float lowerwick = min(close, open) - low
bool risinghigh = high > high[1]
bool fallinghigh = high < high[1]
bool risinglow = low > low[1]
bool fallinglow = low < low[1]

f_isHighUp(_pos)    => risinghigh[_pos]
f_isHighDown(_pos)  => fallinghigh[_pos]
f_isLowUp(_pos)     => risinglow[_pos]
f_isLowDown(_pos)   => fallinglow[_pos]

f_isInsideBar(_pos)     => f_isHighDown(_pos) and f_isLowUp(_pos)
f_isOutsideBar(_pos)    => f_isHighUp(_pos) and f_isLowDown(_pos)
f_isUpBar(_pos)         => f_isHighUp(_pos) and f_isLowUp(_pos)
f_isDownBar(_pos)       => f_isHighDown(_pos) and f_isLowDown(_pos)
f_isPinUp(_pos)         => risinghigh[_pos] and body_range[_pos] < (hl_range[_pos] * 0.33) and (upperwick[_pos] * 0.66) > lowerwick[_pos]
f_isPinDown(_pos)       => fallinglow[_pos] and body_range[_pos] < (hl_range[_pos] * 0.33) and (lowerwick[_pos] * 0.66) > upperwick[_pos]
f_isAny(_pos)           => true

f_enum_BarPattern(_i, _pos)=>
    _isInsideBar = f_isInsideBar(_pos)
    _isOutsideBar = f_isOutsideBar(_pos)
    _isUpBar = f_isUpBar(_pos)
    _isDownBar = f_isDownBar(_pos)
    _isPinUp = f_isPinUp(_pos)
    _isPinDown = f_isPinDown(_pos)
    _isAny = f_isAny(_pos)
    (_i==1?_isInsideBar:(_i==2?_isOutsideBar:(_i==3?_isUpBar:(_i==4?_isDownBar:(_i==5?_isPinUp:(_i==6?_isPinDown:(_i==7?_isAny:na)))))))

f_ident_bar(_pos)=>
    _isInsideBar = f_isInsideBar(_pos)
    _isOutsideBar = f_isOutsideBar(_pos)
    _isUpBar = f_isUpBar(_pos)
    _isDownBar = f_isDownBar(_pos)
    _isPinUp = f_isPinUp(_pos)
    _isPinDown = f_isPinDown(_pos)
    _isAny = f_isAny(_pos)
    _isInsideBar?1:(_isOutsideBar?2:(_isUpBar?3:(_isDownBar?4:(_isPinUp?5:(_isPinDown?6:(_isAny?7:7))))))

bool automatic_last_n_bars = input(false)
int n_bars_in_pattern = input(defval=3, title='How many bars pattern:', type=input.integer, minval=1, maxval=10)

string bar01_type = input(defval=op_type_01, title='#1 in pattern:', type=input.string, options=[op_type_01, op_type_02, op_type_03, op_type_04, op_type_05, op_type_06, op_type_07])
string bar02_type = input(defval=op_type_01, title='#2 in pattern:', type=input.string, options=[op_type_01, op_type_02, op_type_03, op_type_04, op_type_05, op_type_06, op_type_07])
string bar03_type = input(defval=op_type_01, title='#3 in pattern:', type=input.string, options=[op_type_01, op_type_02, op_type_03, op_type_04, op_type_05, op_type_06, op_type_07])
string bar04_type = input(defval=op_type_01, title='#4 in pattern:', type=input.string, options=[op_type_01, op_type_02, op_type_03, op_type_04, op_type_05, op_type_06, op_type_07])
string bar05_type = input(defval=op_type_01, title='#5 in pattern:', type=input.string, options=[op_type_01, op_type_02, op_type_03, op_type_04, op_type_05, op_type_06, op_type_07])
string bar06_type = input(defval=op_type_01, title='#6 in pattern:', type=input.string, options=[op_type_01, op_type_02, op_type_03, op_type_04, op_type_05, op_type_06, op_type_07])
string bar07_type = input(defval=op_type_01, title='#7 in pattern:', type=input.string, options=[op_type_01, op_type_02, op_type_03, op_type_04, op_type_05, op_type_06, op_type_07])
string bar08_type = input(defval=op_type_01, title='#8 in pattern:', type=input.string, options=[op_type_01, op_type_02, op_type_03, op_type_04, op_type_05, op_type_06, op_type_07])
string bar09_type = input(defval=op_type_01, title='#9 in pattern:', type=input.string, options=[op_type_01, op_type_02, op_type_03, op_type_04, op_type_05, op_type_06, op_type_07])
string bar10_type = input(defval=op_type_01, title='#10 in pattern:', type=input.string, options=[op_type_01, op_type_02, op_type_03, op_type_04, op_type_05, op_type_06, op_type_07])
 
automatic_last_n_bars_pre_eval_01 = f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-1)))
automatic_last_n_bars_pre_eval_02 = f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-2)))
automatic_last_n_bars_pre_eval_03 = f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-3)))
automatic_last_n_bars_pre_eval_04 = f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-4)))
automatic_last_n_bars_pre_eval_05 = f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-5)))
automatic_last_n_bars_pre_eval_06 = f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-6)))
automatic_last_n_bars_pre_eval_07 = f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-7)))
automatic_last_n_bars_pre_eval_08 = f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-8)))
automatic_last_n_bars_pre_eval_09 = f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-9)))
automatic_last_n_bars_pre_eval_10 = f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-10)))
if automatic_last_n_bars
    bar01_type := automatic_last_n_bars_pre_eval_01//f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-1)))
    bar02_type := automatic_last_n_bars_pre_eval_02//f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-2)))
    bar03_type := automatic_last_n_bars_pre_eval_03//f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-3)))
    bar04_type := automatic_last_n_bars_pre_eval_04//f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-4)))
    bar05_type := automatic_last_n_bars_pre_eval_05//f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-5)))
    bar06_type := automatic_last_n_bars_pre_eval_06//f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-6)))
    bar07_type := automatic_last_n_bars_pre_eval_07//f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-7)))
    bar08_type := automatic_last_n_bars_pre_eval_08//f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-8)))
    bar09_type := automatic_last_n_bars_pre_eval_09//f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-9)))
    bar10_type := automatic_last_n_bars_pre_eval_10//f_enum_type_by_idx(f_ident_bar(max(0, n_bars_in_pattern-10)))

f_get_nbar_type(_i)=>(_i==1?bar01_type:(_i==2?bar02_type:(_i==3?bar03_type:(_i==4?bar04_type:(_i==5?bar05_type:(_i==6?bar06_type:(_i==7?bar07_type:(_i==8?bar08_type:(_i==9?bar09_type:(_i==10?bar10_type:na))))))))))
f_check_nbar(_i, _pos)=>f_enum_BarPattern(f_enum_type(f_get_nbar_type(_i)), _pos)

f_get_pattern_as_text()=>
    string _t = ''
    for _i = 1 to n_bars_in_pattern
        _t := _t + '(' + tostring(x=_i, y='#') + ': ' + f_get_nbar_type(_i) + ')'
        if _i != n_bars_in_pattern
            _t := _t + ' > '
    _t


f_check_if_pattern(_length)=>
    int _count = 0
    bool _is_valid = false
    for _i = 1 to _length
        int _pos = _length - _i
        _count := _count + (f_check_nbar(_i, _pos) ? 1 : 0)
    if _count >= _length
        _is_valid := true
    _is_valid

t = f_check_if_pattern(n_bars_in_pattern) ? 1 : 0

var int total_bars = 0
total_bars := total_bars + 1

f_perc_of(_fraction, _total)=>(_fraction / _total) * 100

//stats:

var int n_detected = 0
var int n_bars_inside = 0
var int n_bars_outside = 0
var int n_bars_up = 0
var int n_bars_down = 0
var int n_bars_over_atr14x1 = 0
var int n_bars_over_atr14x2 = 0
var int n_bars_over_atr14x3 = 0

float atr = atr(14)
if t[1] > 0
    n_detected := n_detected + 1
    if f_isInsideBar(0)
        n_bars_inside := n_bars_inside + 1
    if f_isOutsideBar(0)
        n_bars_outside := n_bars_outside + 1
    if f_isUpBar(0)
        n_bars_up := n_bars_up + 1
    if f_isDownBar(0)
        n_bars_down := n_bars_down + 1
    if high-low > atr * 1
        n_bars_over_atr14x1 := n_bars_over_atr14x1 + 1
    if high-low > atr * 2
        n_bars_over_atr14x2 := n_bars_over_atr14x2 + 1
    if high-low > atr * 3
        n_bars_over_atr14x3 := n_bars_over_atr14x3 + 1

string tex_size = input(defval=size.normal, title='Text size:', type=input.string, options=[size.auto, size.tiny, size.small, size.normal, size.large, size.huge])

string tex = 'Statistics:\n' + 
     'Pattern: ' + f_get_pattern_as_text() + '\n' +
     'Nº of patterns:' + tostring(x=n_detected, y='#') + ' in ' + tostring(x=total_bars, y='#') + ' bars (' + tostring(x=f_perc_of(n_detected, total_bars), y='#.000') + '%)' + '\n' + 
     'Nº of next bars, that are:\n' +
     ' --- > Inside Bars: ' + tostring(x=n_bars_inside, y='#') + ' (' + tostring(x=f_perc_of(n_bars_inside, n_detected), y='#.000') + '%)' + '\n' +
     ' --- > Outside Bars: ' + tostring(x=n_bars_outside, y='#') + ' (' + tostring(x=f_perc_of(n_bars_outside, n_detected), y='#.000') + '%)' + '\n' +
     ' --- > Up Bars: ' + tostring(x=n_bars_up, y='#') + ' (' + tostring(x=f_perc_of(n_bars_up, n_detected), y='#.000') + '%)' + '\n' +
     ' --- > Down Bars: ' + tostring(x=n_bars_down, y='#') + ' (' + tostring(x=f_perc_of(n_bars_down, n_detected), y='#.000') + '%)' + '\n' +
     ' --- > Over ATR(14): ' + tostring(x=n_bars_over_atr14x1, y='#') + ' (' + tostring(x=f_perc_of(n_bars_over_atr14x1, n_detected), y='#.000') + '%)' + '\n' +
     ' --- > Over ATR(14) x 2: ' + tostring(x=n_bars_over_atr14x2, y='#') + ' (' + tostring(x=f_perc_of(n_bars_over_atr14x2, n_detected), y='#.000') + '%)' + '\n' +
     ' --- > Over ATR(14) x 3: ' + tostring(x=n_bars_over_atr14x3, y='#') + ' (' + tostring(x=f_perc_of(n_bars_over_atr14x3, n_detected), y='#.000') + '%)' + '\n'


var label la = label.new(
         x=bar_index, y=0.5, text='', 
         xloc=xloc.bar_index, yloc=yloc.price, 
         color=color.white, style=label.style_label_left, textcolor=color.black, 
         size=tex_size, textalign=text.align_left
         )

label.set_xy(id=la, x=bar_index, y=0.5)
label.set_text(id=la, text=tex)
plot(series=t, title='Event', color=color.black, style=plot.style_histogram, transp=0)
hline(0)
hline(1)

Overview

[RS] Bar Pattern Statistics Tool classifies individual price bars into types such as inside bars, outside bars, up bars, down bars, and directional pin bars. Users can specify a custom sequence of up to ten consecutive bar types or enable automatic detection based on recent historical bars. The indicator scans the chart for matching sequence conditions to calculate frequency and behavior, allowing traders to study statistical tendencies of multi-bar price action patterns.

Details

Published by

ricardosantos79 on GitHub

Code credit

RicardoSantos, as written in the script's header

Type

Indicator, Pine Script v4

Draws

Separate pane below the chart

Category

Candlestick patterns

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.

Settings

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

SettingTypeDefaultVariable
automatic_last_n_barsboolfalseautomatic_last_n_bars
How many bars pattern:int3n_bars_in_pattern
#1 in pattern:stringop_type_01bar01_type
#2 in pattern:stringop_type_01bar02_type
#3 in pattern:stringop_type_01bar03_type
#4 in pattern:stringop_type_01bar04_type
#5 in pattern:stringop_type_01bar05_type
#6 in pattern:stringop_type_01bar06_type
#7 in pattern:stringop_type_01bar07_type
#8 in pattern:stringop_type_01bar08_type
#9 in pattern:stringop_type_01bar09_type
#10 in pattern:stringop_type_01bar10_type
Show all 13 settings
SettingTypeDefaultVariable
Text size:stringsize.normaltex_size
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

The Bullish/Bearish Candle Series Distribution indicator calculates the length of the current streak of consecutive bullish or bearish candles based on user-selected mode. It tracks streak lengths from 2 to 59 and plots a histogram in a separate pane showing t

Indicator v4 Candlestick patterns
Updated 10 days ago · GPL-3.0 GitHub repository of Bullish/Bearish Candle Series Distribution

Commitment Gauge

by harryguiacorn
219 stars

This indicator measures directional momentum by evaluating candlestick body proportions and volume over a user-defined lookback window. It computes the ratio of candle body to total range, weights the cumulative value by volume and absolute body size, and dete

Indicator v4 VolumeCandlestick patterns
Updated 1 year ago · None stated GitHub repository of Commitment Gauge

Qstick Indicator

by mihakralj
99 stars

This indicator calculates the Qstick value as a simple or exponential moving average of the difference between a chosen close source and open source. It plots that oscillator in a separate pane as a yellow line, draws a dashed zero line, and shades the backgro

Indicator v6 Oscillators & momentumCandlestick patterns
Updated 4 weeks ago · Apache-2.0 GitHub repository of Qstick Indicator

Dual-color bars

by be-thomas
65 stars

This indicator draws a separate OHLC bar series in its own pane using plotbar. Each bar is colored lime when the close is greater than or equal to the open, and red when the close is below the open. It has no user inputs, no signals, and no entry, exit, stop,

Indicator v5 Candlestick patterns
Updated 4 days ago · GPL-3.0 GitHub repository of Dual-color bars
43 stars

This indicator builds a synthetic Heikin-Ashi series using only the current open and the opens of the previous three bars. It derives open, high, low, and close from those values, rounds each price to the symbol mintick, and plots the result as candles in a se

Indicator v5 Candlestick patterns
Updated 2 years ago · None stated GitHub repository of Heikin-Ashi Open Only
24 stars

This indicator plots a Cipher B-style oscillator in a separate pane and can source its calculations from Heikin Ashi candles when that option is on. It draws WaveTrend lines with optional buy, gold, sell, and divergence dots, plus overbought and oversold level

Indicator v5 Oscillators & momentumDivergence
Updated 4 years ago · MPL-2.0 GitHub repository of Cipher B Heikin Ashi

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