Indicator · Pine Script v5 · On the chart

N Pattern

by itmakesyousick· code credited to boitoki

This indicator searches recent pivots for an N-shaped pattern of points A, B and C and projects a future point D on the price chart.

View on GitHub

Repaints

GitHub stars1on the repository
Pine versionv5runs as is
Lines of code544
Settings39inputs
LicenceNone statedfile: MPL-2.0
Last update3 years ago30 Nov 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

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

N-Pattern.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('N Pattern', 'N-Pattern', overlay=true, max_lines_count=500, max_labels_count=500, max_boxes_count=500, max_bars_back=500)

///////////////////
// Inputs
///////////////////
MT_ATR_LENGTH = 10
MY_ATR = ta.atr(MT_ATR_LENGTH)
EMOJI_BULL = '🐮'
EMOJI_BEAR = '🐻'
EMOJI_V = '✅'
EMOJI_X = '❌'
P = 9
A = 0
B = 1
C = 2
D = 3
OP = 4
COP = 5
XOP = 6
E = 7  // Entry zone
A_INDEX_NOT_CHANGED = 0
B_INDEX_NOT_CHANGED = 1

// Basic
// ====================
rightbar = input.int(1, 'Pivot Right bar', group='Basic', minval=1)
leftbar = input.int(7, 'Pivot Left bar', group='Basic', minval=1)
lookback = input.int(100, 'Lookback', group='Basic', minval=10)
nearest_count = input.int(1, 'Nearest bars count', group='Basic', minval=0, tooltip='Hide if too near.')
show_sides = input.string('Both', 'Limit the display side', options=['Both', 'Bull only', 'Bear only'], group='Basic')
show_history = input.bool(false, 'Show History', group='Basic')
show_nearest = nearest_count == 0

// Validation
// ===================
valid_bc = input.int(80, 'Valid BC volume/%', group='Validation', step=1, minval=0, tooltip='`(BC / AB * 100) <= X%` is valid') / 100
valid_ab = input.int(5, 'Valid AB volume/ATR', group='Validation', tooltip='`AB >= ATR*X` is valid')
valid_ab_loger = input.int(500, 'Valid AB longer', group='Validation', minval=0, tooltip='`AB / BC * 100 < X` is valid') / 100
a_threshold = input.float(0.0, 'A Point Threshold/ATR', group='Validation', minval=0, step=0.1) * MY_ATR

// Styles
// ====================
line_A_width = input.int(2, 'A-B line width', group='Styles', minval=1)
line_B_width = input.int(4, 'B-C line width', group='Styles', minval=1)
line_C_width = input.int(1, 'C-D line width', group='Styles', minval=1)
line_C_style = input.string(line.style_dotted, 'C-D line Style', group='Styles', options=[line.style_dotted, line.style_dashed, line.style_solid, line.style_arrow_right])
colorBull = input.color(#3cad99, 'Color bull', group='Styles')
colorBear = input.color(#e0457f, 'Color bear', group='Styles')

// Objectives
// ====================
show_op = input.bool(true, 'Objective Point (OP)', group='Objectives', tooltip='OP = (B - A) + C')
show_cop = input.bool(false, 'Contracted Objective Point (COP)', group='Objectives', tooltip='COP = 0.618 * (B - A) + C')
show_xop = input.bool(false, 'Expanded Objective Point (XOP)', group='Objectives', tooltip='XOP = 1.618 * (B - A) + C')

// P point
// ====================
P_IS = input.string('Yes', 'Point P', options=['Yes', 'P with Support/Resistance', 'No'], group='P point')
show_cp = input.string('Yes', "P-C", options=['Yes', 'No'], group="P point") == 'Yes'
show_p = P_IS != 'No'
show_pb = P_IS == 'P with Support/Resistance'

// Support/Resistance
// ====================
show_sr = input.bool(true, 'Show Support/Resistance', group='Support/Resistance')
show_srHistory = show_history
line_SR_width = input.int(1, 'Line SR width', group='Support/Resistance')
line_SR_style = input.string(line.style_dashed, 'Line SR style', options=[line.style_dashed, line.style_dotted, line.style_solid, line.style_arrow_right], group='Support/Resistance')
line_SR_length = input.float(1.618, 'Line SR length', step=0.01, group='Support/Resistance')

// Fibonacci
// ====================
show_fib = input.bool(false, 'Show Fibonacci lines', group='Fibonacci')
show_fibhistory = show_history

// Pullbacks entry zone
// ====================
show_zone = input.bool(false, 'Show Pullbacks line', group='Pullbacks')
show_zonehistory = show_history
zone_label = 'TRADING'

// Labels
// ====================
show_label_a = input.bool(true, 'Label A', group='Labels')
show_label_b = input.bool(true, 'Label B', group='Labels')
show_label_c = input.bool(true, 'Label C', group='Labels')
show_label_p = input.bool(false, 'Label P', group='Labels')
label_c_bull = input.string('C', 'C Label (Bull)', options=['C', 'Buy', 'Bull', 'Long', 'L', EMOJI_BULL], group='Labels')
label_c_bear = input.string('C', 'C Label (Bear)', options=['C', 'Sell', 'Bear', 'Short', 'S', EMOJI_BEAR], group='Labels')
show_label_op = input.bool(true, 'Label OP', group='Labels')
show_label_cop = input.bool(false, 'Label COP', group='Labels')
show_label_xop = input.bool(false, 'Label XOP', group='Labels')


// Options
// ====================
TRIGGER_OFFSET = input.string('No', 'Re-Paint', options=['Yes', 'No'], group='Options') == 'Yes' ? 0 : 1
DEBUG = input.string('No', 'Debug Messages', options=['Yes', 'No'], group='Options') == 'Yes' ? true : false
show_pivot = input.bool(false, 'Show Pivots', group='Options')

///////////////////
// Defined
///////////////////
my_linestyle = line.style_solid
noneColor = color.new(color.black, 100)


///////////////////
// Functions
///////////////////
validate_index(i) =>
    i > 0 and not na(i)

validate_ab_longer(a, b, c) =>
    (math.abs(b - a) / math.abs(c - b)) < valid_ab_loger

validate_ab(a, b) =>
    math.abs(a - b) >= MY_ATR * valid_ab

validate_bc(a, b, c) =>
    if valid_bc == 0
        true
    else
        (math.abs(c - b) / math.abs(a - b)) <= valid_bc

get_xtime_by_bar(bar_count) =>
    timeframe.multiplier * bar_count * 60 * 1000

get_c_time() =>
    time - get_xtime_by_bar(rightbar + TRIGGER_OFFSET)

draw_fibonacci(index_list, price_list, my_linecolor, should_delete_history) =>
    x = array.get(index_list, A)
    a_price = array.get(price_list, A)
    b_price = array.get(price_list, B)

    f5 = (b_price - a_price) * 0.500 + a_price
    f3 = (b_price - a_price) * 0.382 + a_price
    f6 = (b_price - a_price) * 0.618 + a_price
    f8 = (b_price - a_price) * 0.786 + a_price
    f2 = (b_price - a_price) * 0.236 + a_price

    line_fib_0500 = line.new(x, f5, bar_index, f5, width=2, color=color.new(my_linecolor, 30))
    line_fib_0382 = line.new(x, f3, bar_index, f3, width=1, color=color.new(my_linecolor, 30), style=line.style_dashed)
    line_fib_0618 = line.new(x, f6, bar_index, f6, width=1, color=color.new(my_linecolor, 30), style=line.style_dashed)
    line_fib_0786 = line.new(x, f8, bar_index, f8, width=1, color=color.new(my_linecolor, 30), style=line.style_dotted)
    line_fib_0236 = line.new(x, f2, bar_index, f2, width=1, color=color.new(my_linecolor, 30), style=line.style_dotted)

    if should_delete_history or not show_fibhistory
        line.delete(line_fib_0500[1])
        line.delete(line_fib_0382[1])
        line.delete(line_fib_0618[1])
        line.delete(line_fib_0786[1])
        line.delete(line_fib_0236[1])

draw_sr(index_list, price_list, my_linecolor, should_delete_history) =>
    a_index = array.get(index_list, A)
    b_index = array.get(index_list, B)
    c_index = array.get(index_list, C)
    b_price = array.get(price_list, B)

    start_offset = TRIGGER_OFFSET + rightbar
    ab = math.abs(b_index - a_index)
    bc = math.abs(c_index - b_index)
    ac = math.abs(c_index - a_index)
    x1 = time - get_xtime_by_bar(math.abs(c_index - b_index + start_offset))
    x2 = time + get_xtime_by_bar(math.round(ac * line_SR_length))

    line my_line = line.new(x1, b_price, x2, b_price, style=line_SR_style, color=my_linecolor, width=line_SR_width, xloc=xloc.bar_time)

    if should_delete_history or not show_srHistory
        line.delete(my_line[1])

draw_labels(index_list, price_list, col, should_delete_history, direction) =>
    a_index = array.get(index_list, A)
    b_index = array.get(index_list, B)
    c_index = array.get(index_list, C)
    p_index = array.get(index_list, P)
    d_time = array.get(index_list, D)

    a_price = array.get(price_list, A)
    b_price = array.get(price_list, B)
    c_price = array.get(price_list, C)
    p_price = array.get(price_list, P)
    op_price = array.get(price_list, OP)
    cop_price = array.get(price_list, COP)
    xop_price = array.get(price_list, XOP)

    label_a_style = direction == 1 ? label.style_label_up : label.style_label_down
    label label_a = show_label_a ? label.new(a_index, a_price, 'A', style=label_a_style, color=noneColor, textcolor=col, size=size.normal) : na

    label_b_style = direction == 1 ? label.style_label_down : label.style_label_up
    label label_b = show_label_b ? label.new(b_index, b_price, 'B', style=label_b_style, color=noneColor, textcolor=col, size=size.normal) : na

    label_p_style = direction == 1 ? label.style_label_down : label.style_label_up
    label label_p = show_label_p ? label.new(p_index, p_price, 'P', style=label_p_style, color=noneColor, textcolor=col, size=size.normal) : na

    label_c_style = direction == 1 ? label.style_label_up : label.style_label_down
    label_c_text = direction == 1 ? label_c_bull : label_c_bear
    label label_c = show_label_c ? label.new(c_index, c_price, label_c_text, style=label_c_style, color=col, textcolor=color.white, size=size.small) : na

    label_op_style = label.style_label_left
    label label_op = show_label_op ? label.new(d_time, op_price, 'OP', style=label_op_style, color=noneColor, textcolor=col, xloc=xloc.bar_time, size=size.normal) : na
    label label_cop = show_label_cop ? label.new(d_time, cop_price, 'COP', style=label_op_style, color=noneColor, textcolor=col, xloc=xloc.bar_time, size=size.normal) : na
    label label_xop = show_label_xop ? label.new(d_time, xop_price, 'XOP', style=label_op_style, color=noneColor, textcolor=col, xloc=xloc.bar_time, size=size.normal) : na

    if should_delete_history or not show_history
        label.delete(label_a[1])
        label.delete(label_b[1])
        label.delete(label_c[1])
        label.delete(label_p[1])
        label.delete(label_op[1])
        label.delete(label_cop[1])
        label.delete(label_xop[1])

draw_pullbacks(index_list, price_list, my_linecolor, should_delete_history, direction) =>
    c_index = array.get(index_list, C)
    c_price = array.get(price_list, C)

    x1 = get_c_time()
    x2 = array.get(index_list, E)
    x3 = (math.abs(x2 - x1) / 2) + x1
    y1 = c_price + MY_ATR * (direction == 1 ? 0.0 : 0.4)
    y2 = c_price - MY_ATR * (direction == 1 ? 0.4 : 0.0)
    y3 = (math.abs(y1 - y2) / 2) + y2
    my_box = box.new(x1, y1, x2, y2, border_color=noneColor, bgcolor=color.new(my_linecolor, 76), xloc=xloc.bar_time)
    my_labelyloc = direction == 1 ? yloc.belowbar : yloc.abovebar
    my_labeltext = direction == 1 ? "BUY" : "SELL"
    my_label = label.new(x3, y2, zone_label, textcolor=color.new(my_linecolor, 20), xloc=xloc.bar_time, size=size.normal, style=label.style_none)

    if should_delete_history or not show_zonehistory
        box.delete(my_box[1])
        label.delete(my_label[1])

draw_past(index_list, price_list, my_linecolor, should_delete_history, direction) =>
    a_index = array.get(index_list, A)
    c_index = array.get(index_list, C)
    p_index = array.get(index_list, P)
    a_price = array.get(price_list, A)
    c_price = array.get(price_list, C)
    p_price = array.get(price_list, P)
    p_index_valid = validate_index(p_index)
    my_color = (direction == 1 and p_price > c_price or direction == -1 and p_price < c_price) ? color.yellow : my_linecolor
    my_color := my_linecolor

    line line_pa = show_p  and p_index_valid ? line.new(p_index, p_price, a_index, a_price, style=line.style_dotted, color=color.new(my_color, 30), width=2) : na
    line line_pb = show_pb and p_index_valid ? line.new(p_index, p_price, a_index, p_price, style=line.style_dashed, color=color.new(my_color, 30), width=1) : na
    line line_cp = show_cp and p_index_valid ? line.new(p_index, c_price, c_index, c_price, style=line.style_dotted, color=color.new(my_linecolor, 30), width=2) : na

    box box_pa = na

    if show_pb and p_index_valid
        box_pa := box.new(p_index, a_price, a_index, p_price, bgcolor=color.new(my_color, 86), border_color=noneColor, border_style=line.style_dashed)
        box_pa

    if should_delete_history or not show_history
        line.delete(line_pa[1])
        line.delete(line_pb[1])
        line.delete(line_cp[1])
        box.delete(box_pa[1])

draw(index_list, price_list, found_list, flags_list, my_linecolor, should_delete_history, direction) =>
    a_price = array.get(price_list, A)
    b_price = array.get(price_list, B)
    c_price = array.get(price_list, C)
    p_price = array.get(price_list, P)
    a_found = array.get(found_list, A)
    b_found = array.get(found_list, B)

    a_index = array.get(index_list, A)
    b_index = array.get(index_list, B)
    c_index = bar_index - (rightbar + TRIGGER_OFFSET)
    p_index = array.get(index_list, P)

    a_b = b_index - a_index
    b_c = c_index - b_index
    a_b_ratio = a_b / b_c * 100

    op_price = math.abs(a_price - b_price) * 1.000 * direction + c_price
    cop_price = math.abs(a_price - b_price) * 0.618 * direction + c_price
    xop_price = math.abs(a_price - b_price) * 1.618 * direction + c_price

    c_time = get_c_time()
    d_time = time + get_xtime_by_bar(math.abs(a_index - b_index))
    e_time = time + get_xtime_by_bar(math.abs(b_index - c_index))

    line line_ab = line.new(a_index, a_price, b_index, b_price, style=my_linestyle, color=my_linecolor, width=line_A_width)
    line line_bc = line.new(b_index, b_price, c_index, c_price, style=my_linestyle, color=my_linecolor, width=line_B_width)
    line line_c_op = show_op ? line.new(c_time, c_price, d_time, op_price, style=line_C_style, color=my_linecolor, width=line_C_width, xloc=xloc.bar_time) : na
    line line_c_cop = show_cop ? line.new(c_time, c_price, d_time, cop_price, style=line_C_style, color=my_linecolor, width=line_C_width, xloc=xloc.bar_time) : na
    line line_c_xop = show_xop ? line.new(c_time, c_price, d_time, xop_price, style=line_C_style, color=my_linecolor, width=line_C_width, xloc=xloc.bar_time) : na

    array.set(price_list, OP, op_price)
    array.set(price_list, COP, cop_price)
    array.set(price_list, XOP, xop_price)
    array.set(index_list, D, d_time)
    array.set(index_list, E, e_time)

    if should_delete_history or not show_history
        line.delete(line_ab[1])
        line.delete(line_bc[1])
        line.delete(line_c_op[1])
        line.delete(line_c_cop[1])
        line.delete(line_c_xop[1])

    draw_labels(index_list, price_list, my_linecolor, should_delete_history, direction)

    draw_past(index_list, price_list, my_linecolor, should_delete_history, direction)

    if show_sr
        draw_sr(index_list, price_list, my_linecolor, should_delete_history)

    if show_fib
        draw_fibonacci(index_list, price_list, my_linecolor, should_delete_history)

    if show_zone
        draw_pullbacks(index_list, price_list, my_linecolor, should_delete_history, direction)

ans (valid) => valid ? '◯' : '×'

d (index_list, price_list, found_list, should_be_drawing, direction) => 
    string[] my_messages = array.new_string()
    
    a_price = array.get(price_list, A)
    b_price = array.get(price_list, B)
    c_price = array.get(price_list, C)
    a_index = array.get(index_list, A)
    b_index = array.get(index_list, B)
    c_index = array.get(index_list, C)
    a_found = array.get(found_list, A)
    b_found = array.get(found_list, B)
    bc_percent = str.format('{0,number,percent}', math.abs(c_price - b_price) / math.abs(b_price - a_price))
    ab_div = str.format('{0,number,#.#}', math.abs(a_price - b_price))
    ab_percent = str.format('{0,number,percent}', math.abs(b_index - a_index) / math.abs(c_index - b_index))

    array.push(my_messages, ans(a_found) + ' ' + (a_found ? "A found" : 'A not found'))
    array.push(my_messages, ans(b_found) + ' ' + (b_found ? "B found" : 'B not found'))
    array.push(my_messages, ans(validate_bc(a_price, b_price, c_price)) + ' BC(Ret): ' + bc_percent + ' <= ' + str.format('{0,number,percent}', valid_bc))
    array.push(my_messages, ans(validate_ab_longer(a_index, b_index, c_index)) + ' AB(Longer):' + ab_percent  + ' < ' + str.format('{0,number,percent}', valid_ab_loger))
    array.push(my_messages, ans(validate_ab(a_price, b_price)) + ' AB: ' + ab_div + ' >= ' + str.format('{0,number,#.#}', MY_ATR * valid_ab) + '('+ str.tostring(valid_ab)+'ATR)')
    array.push(my_messages, should_be_drawing ? "It should be drawing" : "Not drawing")

    labelstyle = direction == 1 ? label.style_label_up : label.style_label_down
    labelcolor = direction == 1 ? color.blue : color.red
    labelyloc = direction == 1 ? yloc.belowbar : yloc.abovebar
    label.new(bar_index - rightbar, na, array.join(my_messages, '\n'), yloc=labelyloc, size=size.small, style=labelstyle, color=labelcolor, textalign=text.align_left)


///////////////////
// Calc
///////////////////
ph = ta.pivothigh(leftbar, rightbar)
pl = ta.pivotlow(leftbar, rightbar)

start_index = rightbar + TRIGGER_OFFSET
end_index = lookback
next_index = 0
p_lookback_times = 3

current_index = bar_index - rightbar
counter = 0
count_max = 20
should_delete_history = false
should_be_drawing = false

a_price = 0.0
b_price = 0.0
c_price = 0.0
p_price = 0.0
a_found = false
b_found = false
a_not_changed = false
b_not_changed = false
a_index = 0
b_index = 0
c_index = 0
p_index = 0
p_count = 0
p_max = 3

var int[] index_bull = array.new_int(10)
var int[] index_bear = array.new_int(10)
var float[] price_bull = array.new_float(10, 0)
var float[] price_bear = array.new_float(10, 0)
var bool[] found_bull = array.new_bool(5)
var bool[] found_bear = array.new_bool(5)
var bool[] flags_bull = array.new_bool(10)
var bool[] flags_bear = array.new_bool(10)

///////////////////
// Plotting
///////////////////

// Bull
// ============
if pl[TRIGGER_OFFSET] and show_sides != 'Bear only'
    c_price := low[start_index]
    messages = array.new_string()

    for i = start_index to end_index by 1
        next_index := i

        if counter > count_max
            break

        if pl[i]
            counter += 1

            if low - a_threshold > low[i] and b_found
                a_price := low[i + rightbar]
                a_index := current_index - i
                c_index := bar_index - start_index
                a_found := true
                a_not_changed := a_index - array.get(index_bull, A) == 0
                is_nearest = c_index - array.get(index_bull, C) < nearest_count

                if not show_nearest and is_nearest
                    should_delete_history := true
                    should_delete_history

                if nearest_count == 1 and (a_not_changed or b_not_changed)
                    should_delete_history := true
                    should_delete_history

                break

        if ph[i]
            if high[i + rightbar] > b_price or b_price == 0.0
                b_index := current_index - i
                b_price := high[i + rightbar]
                b_found := true
                b_not_changed := b_index - array.get(index_bull, B) == 0
                b_not_changed

    if (a_found and b_found)
        p_lookback = math.abs(a_index - c_index)
        for i = next_index to next_index + p_lookback by 1
            if ph[i]
                if high[i + rightbar] > p_price or p_price == 0.0
                    p_index := current_index - i
                    p_price := high[i + rightbar]
                    p_count += 1
                    
                    if (p_count > p_max)
                        break

    should_be_drawing := a_found and b_found and validate_bc(a_price, b_price, c_price) and validate_ab(a_price, b_price) and validate_ab_longer(a_index, b_index, c_index)

    array.set(index_bull, A, a_index)
    array.set(index_bull, B, b_index)
    array.set(index_bull, C, c_index)
    array.set(index_bull, P, p_index == 0 ? na : p_index)
    array.set(price_bull, A, a_price)
    array.set(price_bull, B, b_price)
    array.set(price_bull, C, c_price)
    array.set(price_bull, P, p_price)
    array.set(flags_bull, A_INDEX_NOT_CHANGED, a_not_changed)
    array.set(flags_bull, B_INDEX_NOT_CHANGED, b_not_changed)
    array.set(found_bull, A, a_found)
    array.set(found_bull, B, b_found)

    if should_be_drawing
        draw(index_bull, price_bull, found_bull, flags_bull, colorBull, should_delete_history, 1)

    if DEBUG
        d(index_bull, price_bull, found_bull, should_be_drawing, 1)

if ph[TRIGGER_OFFSET] and show_sides != 'Bull only'
    c_price := high[start_index]

    for i = start_index to end_index by 1
        next_index := i

        if counter > count_max
            break

        if ph[i]
            counter += 1

            if high + a_threshold < high[i] and b_found
                a_price := high[i + rightbar]
                a_index := current_index - i
                c_index := bar_index - start_index
                a_found := true
                a_not_changed := a_index - array.get(index_bear, A) == 0
                is_nearest = c_index - array.get(index_bear, C) < nearest_count

                if not show_nearest and is_nearest
                    should_delete_history := true
                    should_delete_history

                if nearest_count == 1 and (a_not_changed or b_not_changed)
                    should_delete_history := true
                    should_delete_history

                break

        if pl[i]
            if low[i + rightbar] < b_price or b_price == 0.0
                b_index := current_index - i
                b_price := low[i + rightbar]
                b_found := true
                b_not_changed := b_index - array.get(index_bear, B) == 0
                b_not_changed

    if a_found and b_found
        p_lookback = math.abs(a_index - c_index)
        for i = next_index to next_index + p_lookback by 1
            if pl[i]
                if low[i + rightbar] < p_price or p_price == 0.0
                    p_index := current_index - i
                    p_price := low[i + rightbar]
                    p_count += 1

                    if (p_count > p_max)
                        break

    should_be_drawing := a_found and b_found and validate_bc(a_price, b_price, c_price) and validate_ab(a_price, b_price) and validate_ab_longer(a_index, b_index, c_index)

    array.set(index_bear, A, a_index)
    array.set(index_bear, B, b_index)
    array.set(index_bear, C, c_index)
    array.set(index_bear, P, p_index == 0 ? na : p_index)
    array.set(price_bear, A, a_price)
    array.set(price_bear, B, b_price)
    array.set(price_bear, C, c_price)
    array.set(price_bear, P, p_price)
    array.set(flags_bear, A_INDEX_NOT_CHANGED, a_not_changed)
    array.set(flags_bear, B_INDEX_NOT_CHANGED, b_not_changed)
    array.set(found_bear, A, a_found)
    array.set(found_bear, B, b_found)

    if should_be_drawing
        draw(index_bear, price_bear, found_bear, flags_bear, colorBear, should_delete_history, -1)

    if DEBUG
        d(index_bear, price_bear, found_bear, should_be_drawing, -1)

plotshape(show_pivot and ph, style=shape.labeldown, text='PH', location=location.abovebar, size=size.tiny, color=color.new(color.orange, 0), textcolor=color.new(color.white, 0), offset=-rightbar)
plotshape(show_pivot and pl, style=shape.labelup, text='PL', location=location.belowbar, size=size.tiny, color=color.new(color.blue, 0), textcolor=color.new(color.white, 0), offset=-rightbar)

Overview

Pivot left and right bars, lookback, and validation rules based on ATR and leg volume control which patterns qualify. Projected targets include the objective point and optional contracted and expanded versions, with optional support and resistance extensions, Fibonacci lines and labels. It can show bullish, bearish or both patterns, plus history. Pivots are only confirmed after later bars form.

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

Support & resistance, Breakout

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

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

Topics

pinescript

Settings

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

SettingTypeDefaultVariable
Pivot Right barint1rightbar
Pivot Left barint7leftbar
Lookbackint100lookback
Nearest bars countint1nearest_count
Limit the display sidestringBothshow_sides
Show Historyboolfalseshow_history
Valid BC volume/%int80valid_bc
Valid AB volume/ATRint5valid_ab
Valid AB longerint500valid_ab_loger
A Point Threshold/ATRfloat0.0a_threshold
A-B line widthint2line_A_width
B-C line widthint4line_B_width
Show all 39 settings
SettingTypeDefaultVariable
C-D line widthint1line_C_width
C-D line Stylestringline.style_dottedline_C_style
Color bullcolor#3cad99colorBull
Color bearcolor#e0457fcolorBear
Objective Point (OP)booltrueshow_op
Contracted Objective Point (COP)boolfalseshow_cop
Expanded Objective Point (XOP)boolfalseshow_xop
Point PstringYesP_IS
P-CstringYesshow_cp
Show Support/Resistancebooltrueshow_sr
Line SR widthint1line_SR_width
Line SR stylestringline.style_dashedline_SR_style
Line SR lengthfloat1.618line_SR_length
Show Fibonacci linesboolfalseshow_fib
Show Pullbacks lineboolfalseshow_zone
Label Abooltrueshow_label_a
Label Bbooltrueshow_label_b
Label Cbooltrueshow_label_c
Label Pboolfalseshow_label_p
C Label (Bull)stringClabel_c_bull
C Label (Bear)stringClabel_c_bear
Label OPbooltrueshow_label_op
Label COPboolfalseshow_label_cop
Label XOPboolfalseshow_label_xop
Re-PaintstringNoTRIGGER_OFFSET
Debug MessagesstringNoDEBUG
Show Pivotsboolfalseshow_pivot
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

Sideway Zones Live

by dearvn
257 stars

Sideway Zones Live is an overlay indicator that estimates inner and outer sideways bands from recent highs and lows with a rational quadratic kernel. It tracks swing pivots over a loopback period and counts bars that remain between the outer high and low. Afte

Indicator v5 TrendSupport & resistance
Updated 6 weeks ago · None stated GitHub repository of Sideway Zones Live
219 stars

This indicator identifies High Of Low Price (HOLP) and Low Of High Price (LOHP) candlestick setups based on price extremes over a specified lookback period. A HOLP signal triggers when the current bar closes above the high of a recent session low, whereas a LO

Indicator v5 Candlestick patternsBreakout
Updated 1 year ago · None stated GitHub repository of Candlestick Patterns - HOLP-LOHP
218 stars

This indicator plots dynamic support and resistance levels on the price chart. It detects pivot highs and lows using the pivot length and tracks touches to build strength-based levels. Support and resistance zones appear as colored boxes while lines mark key l

Indicator v6 Support & resistanceBreakout
Updated 3 months ago · None stated GitHub repository of Dynamic Support & Resistance

Donchian Channels (DC)

by mihakralj
99 stars

This indicator calculates and plots Donchian Channels directly on the price chart. It determines the highest high and lowest low over a user-selected lookback period using an optimized monotonic deque algorithm, as well as a middle basis line computed as their

Indicator v6 Volatility & bandsSupport & resistance
Updated 4 weeks ago · Apache-2.0 GitHub repository of Donchian Channels (DC)

Lows from New Highs

by be-thomas
65 stars

This indicator tracks bar lows during consecutive rising highs using Pine Script arrays. When at least four lows accumulate or the price breaches the minimum low in the stack, the script sorts the recorded lows in ascending order and flushes them. It plots up

Indicator v4 Support & resistanceBreakout
Updated 5 days ago · GPL-3.0 GitHub repository of Lows from New Highs

This indicator tracks smart money market structure directly on the price chart. It calculates dual-period swing highs and swing lows to detect Changes of Character (CHoCH), Breaks of Structure (BOS), inducements, and liquidity sweeps. When structural levels ar

Indicator v5 SMC / ICT / price actionSupport & resistance
Updated 1 year ago · Apache-2.0 GitHub repository of Market Structure with Inducements & Sweeps [LuxAlgo]

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