HTF Candles & Pivots
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © boitoki
//
// 🛟 https://boitoki.gitbook.io/htf-candles-and-pivots/
// =====================================================
//@version=5
indicator('HTF Candles & Pivots', 'HTF', overlay=true, max_lines_count=300, max_labels_count=100, max_boxes_count=300, max_bars_back=1000)

import boitoki/AwesomeColor/8 as ac
import boitoki/Pivots/9 as f
import boitoki/Utilities/5 as util

//////////////////////
// Define
//////////////////////
GP1                 = '〈 〉PIVOTS'
GP2                 = '〈 〉GENERAL'
GP3                 = '〈 〉HTF CANDLE'
GP5                 = '〈 〉RIGHT BAR'
GP6                 = '〈 〉RIGHT BAR 〉EXPECTED PRICE RANGE'
GP7                 = '〈 〉OPTIONS'
GP8                 = '〈 〉HTF CANDLE 〉LABEL'
GP9                 = '〈 〉EXPERIMENTAL'
GP10                = '〈 〉MESSAGE PANEL'
GP11                = '〈 〉RIGHT BAR 〉DOUBLE ZERO 00'

t_PP                = 'PP'
t_R5                = 'R ⁵'
t_R4                = 'R ⁴'
t_R3                = 'R ³'
t_R2                = 'R ²'
t_R1                = 'R ¹'
t_S1                = 'S ¹'
t_S2                = 'S ²'
t_S3                = 'S ³'
t_S4                = 'S ⁴'
t_S5                = 'S ⁵'
t_BC                = 'BC'
t_TC                = 'TC'

f_pip               = '{0,number,#.#}'

max_bars_count      = 500
maximum_x           = bar_index + max_bars_count
icon_paint          = '🎨'
icon_clock          = '⏱️'
icon_notif          = '📢'
icon_calendar       = '🗓'
icon_cross          = '⚔️'
icon_danger         = '⚠️'
icon_jp             = '🇯🇵'
icon_en             = '🇺🇸'
icon_talk           = '💬'
separator_dot       = ' • '
separator_br        = '\n'
option_new          = 'New only'
option_all          = 'All'
option_shifted      = "Shifted forward"
option_hide         = '⊗ Hide'
option_lang1        = icon_en + ' English'
option_lang2        = icon_jp + ' 日本語'
is_1min             = timeframe.isintraday and timeframe.multiplier <= 1

TRANSPARENT         = color.new(color.black, 100)

//////////////////////
// Types 
//////////////////////
// Message
type Message
    string en = ''
    string ja = ''

method get (Message this, int index) =>
    array.get(array.from(this.en, this.ja), index)

// Position
type Position
    int x1
    int x2
    float y1
    float y2

// DayOfWeek
type DayOfWeek
    string[] ja
    string[] en

method get (DayOfWeek this, int dayIndex, int langIndex) =>
    switch langIndex
        0 => array.get(this.en, dayIndex)
        1 => array.get(this.ja, dayIndex)
        => array.get(this.en, dayIndex)

var dayOfWeek = DayOfWeek.new(
  array.from('', '日', '月', '火', '水', '木', '金', '土'), 
  array.from('', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'))

//////////////////////
// Functions
//////////////////////
f_color (_package, _color, _vecna, _mono, _custom) =>
    switch _package
        'vecna'             => _vecna
        'mono'              => _mono
        'custom'            => _custom
        => ac.package(_package, _color)

f_color (_name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _v, _z) =>
    switch _name
        'monokai'           => _a
        'monokaipro'        => _b
        'panda'             => _c
        'gruvbox'           => _d
        'spacemacs light'   => _e
        'spacemacs dark'    => _f
        'guardians'         => _g
        'tradingview'       => _h
        'vecna'             => _i
        'mono'              => _v
        'custom'            => _z
        => _i

f_pricerange_avg (_avg, _lookback) =>
    x2 = math.min(_lookback*2, 4000)
    x3 = math.min(_lookback*3, 4000)
    math.avg(_avg, _avg[_lookback], _avg[x2], _avg[x3])

f_candle (_x1, _y1, _x2, _y2, _border_color, _bgcolor, _width, _style, _xloc) =>
    box.new(_x1, _y1, _x2, _y2, _border_color, _width, _style, extend.none, _xloc, _bgcolor)

f_dz_freq_select (_type, _autovalue) =>
    switch _type
        'Auto' => _autovalue
        => str.tonumber(_type)

f_lang_index (_type) =>
    switch _type
        option_lang1 => 0
        option_lang2 => 1
        => 0

//////////////////////
// Inputs
//////////////////////
i_htf_type                  = input.string('Auto', icon_clock + ' ', options=['Auto', '15', '30', '60', '120', '240', '360', '720', 'D', 'W', 'M', '2M', '3M', '4M', '6M', '12M'], inline='time', group=GP2)
i_color_name                = str.replace_all(str.lower(input.string('monokai', icon_paint + ' ', options=['TradingView', 'monokai', 'monokaipro', 'panda', 'Gruvbox', 'Spacemacs light', 'Spacemacs dark', 'Guardians', 'st3', 'st4', 'mono', 'custom'], inline='color', group=GP2)), ' ', '_')
i_color_1                   = input.color(color.green   , '|', inline='color', group=GP2)
i_color_2                   = input.color(color.red     , '',  inline='color', group=GP2)
i_color_3                   = input.color(color.purple  , '',  inline='color', group=GP2)
i_color_4                   = input.color(color.orange  , '',  inline='color', group=GP2)
i_color_5                   = input.color(color.blue    , '',  inline='color', group=GP2)
i_color_6                   = input.color(color.yellow  , '',  inline='color', group=GP2)
i_msg_lang                  = input.string(option_lang1, icon_talk + ' ', options=[option_lang1, option_lang2], group=GP2, inline='lang')
langIndex                   = f_lang_index(i_msg_lang)

// HTF Candle
// =============
option_display1             = 'Both'
option_display2             = 'Open-Close'
option_display3             = 'High-Low'
i_candle_display            = input.string(option_display1, 'Display ', options=[option_display1, option_display2, option_display3, option_hide], group=GP3, inline='htf_display')
i_candle_show               = i_candle_display != option_hide
i_candle_thickness          = input.int(1, '', minval=0, group=GP3, inline='htf_display')
i_candle_line_transp        = 10
i_candle_bg_transp          = 96
i_candle_show_wick          = input.bool(false, "Wick", group=GP3, inline='htf_display') and i_candle_show
i_candle_show_fill          = input.bool(false, 'Hollow candles', group=GP3, inline='htf_display')
i_candle_show_wick         := i_candle_display == option_display3 ? false : i_candle_show_wick
i_candle_access             = input.string(option_shifted, "History ", options=[option_all, option_new, option_shifted], group=GP3, inline='htf_history')
i_candle_show_hl            = i_candle_display == option_display3 or i_candle_display == option_display1
i_candle_show_oc            = i_candle_display == option_display2 or i_candle_display == option_display1
i_candle_show_today         = not input.bool(true, 'Don\'t show Today when Shifted', group=GP3, inline='htf_history')

var access_newonly          = i_candle_access == option_new
var access_all              = i_candle_access == option_all
var access_shifted          = i_candle_access == option_shifted
var shift                   = access_shifted ? 1 : 0

// Wick style
var i_candle_wick_thickness = i_candle_thickness
var i_candle_wick_transp    = 3

// Time division
i_tdiv_number               = input.int(0, 'Divisions', options=[0, 2, 3, 4, 5, 6, 7, 8], group=GP3, inline='divisions_display', tooltip='Num. of divisions / Extend / Thickness')
i_tdiv_extend               = input.string('None', '', options=['None', 'Both'], group=GP3, inline='divisions_display')
i_tdiv_extend              := i_tdiv_extend == 'None' ? extend.none : extend.both
i_tdiv_thickness            = input.int(1, '', minval=0, maxval=10, group=GP3, inline='divisions_display')
var i_tdiv_show             = i_tdiv_number > 1
var i_tdiv_style            = line.style_dotted


// Labels
// =============
option_candle_label1        = 'Price'
option_candle_label2        = 'Pips'
option_sep1                 = 'dot'
option_sep2                 = 'br'
i_candle_label              = input.string(option_hide, 'Display ', options=[option_candle_label1, option_candle_label2, option_hide], inline='candle_labels', group=GP8)
i_candle_label_show         = i_candle_label != option_hide 
i_candle_label_size         = input.string(size.small, '', options=[size.auto, size.tiny, size.small, size.normal, size.large, size.huge], inline='candle_labels', group=GP8)
i_candle_label_sep          = input.string(option_sep1, '', options=[option_sep1, option_sep2], inline='candle_labels', group=GP8)
i_candle_label_position     = label.style_label_upper_left
i_candle_label_tz           = 'GMT+3'
i_labels_show_price         = i_candle_label == option_candle_label1
i_labels_show_pips          = i_candle_label == option_candle_label2
i_labels_show_htf           = input.bool(true , 'TF'     , inline='labels_options', group=GP8)
i_labels_show_avg           = input.bool(false, 'Avg'    , inline='labels_options', group=GP8)
i_labels_show_day           = input.bool(false, 'Day'    , inline='labels_options', group=GP8)
i_labels_show_tds           = input.bool(false, 'TD Seq.', inline='labels_options', group=GP8)
i_label_transp              = 10


// Right bar
// =====================
i_show_info_bar             = input.bool(true, '', group=GP5, inline='rightbar_display')
i_info_bar_placement        = input.int(2, 'Placement', group=GP5, inline='rightbar_display')
i_info_bar_color            = input.color(#757575, '', group=GP5, inline='rightbar_display')
i_info_bar_show_prev_day    = input.bool(true, 'Previous', group=GP5, inline='rightbar_items')
i_info_bar_show_prev_week   = input.bool(false, 'Previous week', group=GP5, inline='rightbar_items')
i_info_bar_labels           = input.bool(true, 'Labels', group=GP5)
i_info_bar_extend_lines     = input.bool(false, 'Lines extended', group=GP5) and (not i_candle_show)

// Expected price range
// =====================
option_epr3                 = 'Predict next'
option_epr4                 = 'Developing'
i_epr_rightbar              = input.bool(true, 'In Rightbar', group=GP6)
i_epr_history               = input.string(option_hide, 'Chart plotting', options=[option_all, option_new, option_epr3, option_epr4,  option_hide], group=GP6)
i_epr_show                  = i_epr_history !=  option_hide
i_epr_next                  = i_epr_history == option_epr3
i_epr_shifted               = i_epr_next
i_epr_developing            = i_epr_history == option_epr4
i_epr_transp                = 98
i_epr_plot_base             = input.string('open', 'Pivot', options=['open', 'hl2'], group=GP6)

// Double zero
// ============
i_00_rightbar               = input.bool(true, 'In Rightbar', group=GP11)
i_00_freq                   = input.string('Auto', 'Freqency', options=['50', '100', '150', '200', '300', '400', '500', '1000', 'Auto'], group=GP11)
i_00_labels                 = input.bool(true, 'Labels', group=GP11)
i_00_extend                 = input.bool(false, 'Lines extended', group=GP11)
i_00_lines_count            = 10

// Pivots
// =============
option_pivot_label1         = 'Levels'
option_pivot_label2         = 'Levels & Price'
option_pivot_label3         = 'Price'
i_pivots_type               = input.string('Traditional', 'Display ', options=['Traditional', 'Fibonacci', 'Woodie', 'Classic', 'DM', 'Camarilla', 'Floor', 'Expected Pivot Points', 'PP only'], inline='pivots_display', group=GP1)
i_pivots_show_cpr           = input.bool(false, 'CPR', inline='pivots_display', group=GP1)
i_pivots_history            = input.string(option_hide, 'History ', options=[option_all, option_new, option_hide], inline='pivot_history', group=GP1)
i_pivots_show               = i_pivots_history != option_hide
i_pivots_show_cpr          := i_pivots_show_cpr and i_pivots_show
i_pivots_show_forecast      = input.bool(false, 'Forecast', inline='pivot_history', group=GP1)
i_pivots_line_style         = input.string(line.style_dotted, 'Line  ', options=[line.style_solid, line.style_dotted, line.style_dashed], inline='pivot_line_style', group=GP1)
i_pivots_show_zone          = input.bool(true, 'BG', inline='pivot_line_style', group=GP1) and not (i_pivots_type == 'Traditional' or i_pivots_type == 'DM')
i_pivots_show_zone         := i_pivots_type == 'Expected Pivot Points' ? false : i_pivots_show_zone
i_pivots_line_thickness     = 1
i_pivots_line_transp        = 30
i_pivots_label_position     = input.string(option_hide, 'Labels ', options=['Right', 'Left', option_hide], inline='pivot_label', group=GP1)
i_pivots_label_show         = option_hide != i_pivots_label_position
i_pivots_label              = input.string(option_pivot_label1, '', options=[option_pivot_label1, option_pivot_label3, option_pivot_label2], inline='pivot_label', group=GP1)
i_pivots_label_size         = input.string(size.normal, '', options=[size.auto, size.tiny, size.small, size.normal, size.large, size.huge], inline='pivot_label', group=GP1)
i_pivots_zone_transp        = 96
i_pivots_show_history       = i_pivots_history == option_all


// Message panel
// ==============
i_show_messagebox           = input.bool(true, 'Message panel', group=GP10, inline='message_text')
i_msg_size                  = input.string(size.normal, '', options=[size.auto, size.tiny, size.small, size.normal, size.large, size.huge], group=GP10, inline='message_text')
i_msg_color                 = input.color(color.gray, '', group=GP10, inline='message_text')
i_msg_tz                    = input.string('GMT+1', 'Time zone', options=['GMT-11', 'GMT-10', 'GMT-9', 'GMT-8', 'GMT-7', 'GMT-6', 'GMT-5', 'GMT-4', 'GMT-3', 'GMT-2', 'GMT-1', 'GMT', 'GMT+1', 'GMT+2', 'GMT+3', 'GMT+4', 'GMT+5', 'GMT+6', 'GMT+7', 'GMT+8', 'GMT+9', 'GMT+10', 'GMT+11', 'GMT+12'], group=GP10, inline='message_tz')
i_placement_y               = input.string('bottom', 'Placement', options=['top', 'middle', 'bottom'], group=GP10, inline='message_placement')
i_placement_x               = input.string('left', '', options=['left', 'center', 'right'], group=GP10, inline='message_placement')
i_placement                 = i_placement_y + '_' + i_placement_x
i_msg_thres                 = input.float(0.05, 'Threshold %', minval=0, step=0.05, group=GP10) / 100
i_msg_dot                   = true//input.bool(false, 'Display the dots', group=GP10)
i_msg_show_cal              = input.bool(true, icon_calendar + ' Calendar', group=GP10)
i_msg_show_info             = input.bool(false, icon_notif + ' Info', group=GP10)
i_msg_show_warn             = input.bool(false, icon_danger + ' Warning', group=GP10)

// Options & Experimental
// ======================
i_clean_memory              = input.bool(false, 'Memory saving', group=GP9)
i_labels_day_kanji          = i_msg_lang == option_lang2

i_drawing_max               = i_clean_memory ? 5 : 200

//////////////////////
// Colors
//////////////////////
c_none                      = color.new(color.black, 100)
c_bull                      = f_color(i_color_name, 'green'     , #024873, ac.panda('light-gray')   , i_color_1)
c_bear                      = f_color(i_color_name, 'red'       , #730E0E, ac.panda('dark-gray')    , i_color_2)
c_PP                        = f_color(i_color_name, 'purple'    , #FD7CC2, ac.panda('dark-gray')    , i_color_3), c_CPR     = c_PP
c_RX                        = f_color(i_color_name, 'orange'    , #FB9787, ac.panda('gray')         , i_color_4), c_SX      = c_RX
c_epr                       = f_color(i_color_name, 'blue'      , #6EA2FA, ac.panda('light-gray')   , i_color_5)
c_cur                       = f_color(i_color_name, 'orange'    , #FB9787, ac.panda('gray')         , i_color_6)

//////////////////////
// Messages / Text
//////////////////////
var message_expected_high = Message.new('Expected range high', '予想値幅高値')
var message_expected_low = Message.new('Expected range low', '予想値幅安値')
var message_prev_open = Message.new('Preivous open', '前日始値')
var message_prev_high = Message.new('Preivous high', '前日高値')
var message_prev_low  = Message.new('Preivous low', '前日安値')
var message_prev_close = Message.new('Preivous close', '前日終値')
var message_prev_week_open = Message.new('Preivous week open', '先週始値')
var message_prev_week_high = Message.new('Preivous week high', '先週高値')
var message_prev_week_low = Message.new('Preivous week low', '先週安値')
var message_prev_week_close = Message.new('Preivous week close', '先週終値')
var text_w = Message.new('W', '週目')
var text_previous = Message.new('previous', '前日')

//////////////////////
// CALCULATIONS
//////////////////////
htf                         = i_htf_type == 'Auto' ? util.auto_htf() : i_htf_type
htf_changed                 = ta.change(time(htf))
htf_is_intraday             = htf != 'W' and htf != 'M' and htf != '6M' and htf != '12M'

[O1, H1, L1, C1, O0, H0, L0, C0] = f.htf_ohlc(htf)

var counter = 0

if htf_changed
    counter := 0
else
    counter := counter + 1

////////////////////////
// RENDERING FUNCTIONS
////////////////////////
f_lang (_select, _opt1, _opt2) =>
    switch _select
        option_lang1    => _opt1
        option_lang2    => _opt2

f_render_pivots_label (_x, _y, _text, _color, _style, _show) =>
    label id = na
    
    if _show
        v_price = str.tostring(_y, format.mintick)
        v_text = ''

        if i_pivots_label == option_pivot_label1
            v_text := _text
        else if i_pivots_label == option_pivot_label2
            v_text := _text + ' (' + v_price + ')'
        else if i_pivots_label == option_pivot_label3
            v_text := v_price

        id := label.new(_x, _y, v_text, textcolor=_color, color=c_none, style=_style, size=i_pivots_label_size)

    id
    
f_render_pivots_line (_x1, _y, _x2, _width, _color, _style, _show) =>
    id = (_show and _y > 0) ? line.new(_x1, _y, _x2, _y, width=_width, color=color.new(_color, i_pivots_line_transp), style=_style) : na

    id

f_render_pivots_box (_x1, _y1, _x2, _y2, _color, _show) =>
    id = _show ? box.new(_x1, _y1, _x2, _y2, bgcolor=color.new(_color, i_pivots_zone_transp), border_color=c_none) : na

    id

f_render_pivots (_show, _show_history, _next, _x1, _x2, _shift, _lines, _labels, _boxes, _should_delete) =>
    if _show
        O = _next ? O0 : O1
        H = _next ? H0 : H1
        L = _next ? L0 : L1
        C = _next ? C0 : C1

        [PP, R1, S1, R2, S2, R3, S3, R4, S4, R5, S5] = f.pivots(i_pivots_type, O, H, L, C)
        [BC, TC, CPR] = f.cpr(H, L, C)

        lines_start     = array.size(_lines)
        boxes_start     = array.size(_boxes)
        labels_start    = array.size(_labels)
        
        if (not _show_history) or _should_delete
            util.clear_lines(_lines, 0)
            util.clear_labels(_labels, 0)
            util.clear_boxes(_boxes, 0)

        // Lines
        array.push(_lines, f_render_pivots_line(_x1, PP[_shift], _x2, math.max(2, i_pivots_line_thickness), c_PP, line.style_solid, true) )
        array.push(_lines, f_render_pivots_line(_x1, R1[_shift], _x2, i_pivots_line_thickness, c_RX, i_pivots_line_style, true) )
        array.push(_lines, f_render_pivots_line(_x1, R2[_shift], _x2, i_pivots_line_thickness, c_RX, i_pivots_line_style, true) )
        array.push(_lines, f_render_pivots_line(_x1, R3[_shift], _x2, i_pivots_line_thickness, c_RX, i_pivots_line_style, true) )
        array.push(_lines, f_render_pivots_line(_x1, R4[_shift], _x2, i_pivots_line_thickness, c_RX, i_pivots_line_style, true) )
        array.push(_lines, f_render_pivots_line(_x1, R5[_shift], _x2, i_pivots_line_thickness, c_RX, i_pivots_line_style, true) )
        array.push(_lines, f_render_pivots_line(_x1, S1[_shift], _x2, i_pivots_line_thickness, c_SX, i_pivots_line_style, true) )
        array.push(_lines, f_render_pivots_line(_x1, S2[_shift], _x2, i_pivots_line_thickness, c_SX, i_pivots_line_style, true) )
        array.push(_lines, f_render_pivots_line(_x1, S3[_shift], _x2, i_pivots_line_thickness, c_SX, i_pivots_line_style, true) )
        array.push(_lines, f_render_pivots_line(_x1, S4[_shift], _x2, i_pivots_line_thickness, c_SX, i_pivots_line_style, true) )
        array.push(_lines, f_render_pivots_line(_x1, S5[_shift], _x2, i_pivots_line_thickness, c_SX, i_pivots_line_style, true) )
        array.push(_lines, f_render_pivots_line(_x1, BC[_shift], _x2, 1, c_CPR, line.style_dotted, i_pivots_show_cpr) )
        array.push(_lines, f_render_pivots_line(_x1, TC[_shift], _x2, 1, c_CPR, line.style_dotted, i_pivots_show_cpr) )

        // Boxes
        array.push(_boxes, f_render_pivots_box(_x1, R1[_shift], _x2, R2, c_RX , i_pivots_show_zone) )
        array.push(_boxes, f_render_pivots_box(_x1, R3[_shift], _x2, R4, c_RX , i_pivots_show_zone) )
        array.push(_boxes, f_render_pivots_box(_x1, S1[_shift], _x2, S2, c_SX , i_pivots_show_zone) )
        array.push(_boxes, f_render_pivots_box(_x1, S3[_shift], _x2, S4, c_SX , i_pivots_show_zone) )
        array.push(_boxes, f_render_pivots_box(_x1, BC[_shift], _x2, TC, c_CPR, i_pivots_show_zone and i_pivots_show_cpr) )

        // Labels
        label_x     = i_pivots_label_position == 'Left' ? _x1 : _x2
        label_style = i_pivots_label_position == 'Left' ? label.style_label_right : label.style_label_left
        array.push(_labels, f_render_pivots_label(label_x, PP[_shift], t_PP, color.new(c_PP , 20), label_style, i_pivots_label_show) )
        array.push(_labels, f_render_pivots_label(label_x, R5[_shift], t_R5, color.new(c_RX , 30), label_style, i_pivots_label_show) )
        array.push(_labels, f_render_pivots_label(label_x, R4[_shift], t_R4, color.new(c_RX , 30), label_style, i_pivots_label_show) )
        array.push(_labels, f_render_pivots_label(label_x, R3[_shift], t_R3, color.new(c_RX , 30), label_style, i_pivots_label_show) )
        array.push(_labels, f_render_pivots_label(label_x, R2[_shift], t_R2, color.new(c_RX , 30), label_style, i_pivots_label_show) )
        array.push(_labels, f_render_pivots_label(label_x, R1[_shift], t_R1, color.new(c_RX , 30), label_style, i_pivots_label_show) )
        array.push(_labels, f_render_pivots_label(label_x, S1[_shift], t_S1, color.new(c_SX , 30), label_style, i_pivots_label_show) )
        array.push(_labels, f_render_pivots_label(label_x, S2[_shift], t_S2, color.new(c_SX , 30), label_style, i_pivots_label_show) )
        array.push(_labels, f_render_pivots_label(label_x, S3[_shift], t_S3, color.new(c_SX , 30), label_style, i_pivots_label_show) )
        array.push(_labels, f_render_pivots_label(label_x, S4[_shift], t_S4, color.new(c_SX , 30), label_style, i_pivots_label_show) )
        array.push(_labels, f_render_pivots_label(label_x, S5[_shift], t_S5, color.new(c_SX , 30), label_style, i_pivots_label_show) )
        array.push(_labels, f_render_pivots_label(label_x, BC[_shift], t_BC, color.new(c_CPR, 30), label_style, i_pivots_label_show and i_pivots_show_cpr) )
        array.push(_labels, f_render_pivots_label(label_x, TC[_shift], t_TC, color.new(c_CPR, 30), label_style, i_pivots_label_show and i_pivots_show_cpr) )

        if _show_history and (not _should_delete)
            lines_step      = array.size(_lines)  - lines_start
            boxes_step      = array.size(_boxes)  - boxes_start
            labels_step     = array.size(_labels) - labels_start

            util.remove_lines(_lines  , i_drawing_max, lines_start , lines_step)
            util.remove_boxes(_boxes  , i_drawing_max, boxes_start , boxes_step)
            util.remove_labels(_labels, i_drawing_max, labels_start, labels_step)


///////////////
// HTF Candle
///////////////
f_render_tdiv (_x, _y1, _y2, _color, _transp, _show) =>
    id = _show ? line.new(_x, _y1, _x, _y2, color=color.new(_color, _transp), width=i_tdiv_thickness, style=i_tdiv_style, extend=i_tdiv_extend) : na
    id

f_get_div_x (_x1, _x2, _x3, _num) =>
    math.round((_x2 - _x1) * (1/i_tdiv_number*_num)) + _x3

// Divisions:
f_render_divs (x1, x2, px1, px2, nx1, nx2, color01, color11, wick_transp, _show, _show_today) =>
    if _show
        var line split_1 = na, var line split_2 = na
        var line split_3 = na, var line split_4 = na
        var line split_5 = na, var line split_6 = na
        var line split_7 = na
        var line forecast_split_1 = na, var line forecast_split_2 = na
        var line forecast_split_3 = na, var line forecast_split_4 = na
        var line forecast_split_5 = na, var line forecast_split_6 = na
        var line forecast_split_7 = na
        var a_lines = array.new<line>()
        

        if htf_changed
            line.delete(split_1)
            line.delete(split_2)
            line.delete(split_3)
            line.delete(split_4)
            line.delete(split_5)
            line.delete(split_6)
            line.delete(split_7)
            
            if access_newonly or access_all or access_shifted
                split_x1 = f_get_div_x(x1, x2, x1, 1)
                split_x2 = f_get_div_x(x1, x2, x1, 2)
                split_x3 = f_get_div_x(x1, x2, x1, 3)
                split_x4 = f_get_div_x(x1, x2, x1, 4)
                split_x5 = f_get_div_x(x1, x2, x1, 5)
                split_x6 = f_get_div_x(x1, x2, x1, 6)
                split_x7 = f_get_div_x(x1, x2, x1, 7)
                split_1 := f_render_tdiv(split_x1, H0[shift], L0[shift], color01[shift], wick_transp, i_tdiv_number > 1)
                split_2 := f_render_tdiv(split_x2, H0[shift], L0[shift], color01[shift], wick_transp, i_tdiv_number > 2)
                split_3 := f_render_tdiv(split_x3, H0[shift], L0[shift], color01[shift], wick_transp, i_tdiv_number > 3)
                split_4 := f_render_tdiv(split_x4, H0[shift], L0[shift], color01[shift], wick_transp, i_tdiv_number > 4)
                split_5 := f_render_tdiv(split_x5, H0[shift], L0[shift], color01[shift], wick_transp, i_tdiv_number > 5)
                split_6 := f_render_tdiv(split_x6, H0[shift], L0[shift], color01[shift], wick_transp, i_tdiv_number > 6)
                split_7 := f_render_tdiv(split_x7, H0[shift], L0[shift], color01[shift], wick_transp, i_tdiv_number > 7)

            if access_all or access_shifted
                split_x1 = f_get_div_x(px1, px2, px1, 1)
                split_x2 = f_get_div_x(px1, px2, px1, 2)
                split_x3 = f_get_div_x(px1, px2, px1, 3)
                split_x4 = f_get_div_x(px1, px2, px1, 4)
                split_x5 = f_get_div_x(px1, px2, px1, 5)
                split_x6 = f_get_div_x(px1, px2, px1, 6)
                split_x7 = f_get_div_x(px1, px2, px1, 7)
                a_start  = array.size(a_lines)
                array.push(a_lines, f_render_tdiv(split_x1, H1[shift], L1[shift], color11[shift], wick_transp, i_tdiv_number > 1) )
                array.push(a_lines, f_render_tdiv(split_x2, H1[shift], L1[shift], color11[shift], wick_transp, i_tdiv_number > 2) )
                array.push(a_lines, f_render_tdiv(split_x3, H1[shift], L1[shift], color11[shift], wick_transp, i_tdiv_number > 3) )
                array.push(a_lines, f_render_tdiv(split_x4, H1[shift], L1[shift], color11[shift], wick_transp, i_tdiv_number > 4) )
                array.push(a_lines, f_render_tdiv(split_x5, H1[shift], L1[shift], color11[shift], wick_transp, i_tdiv_number > 5) )
                array.push(a_lines, f_render_tdiv(split_x6, H1[shift], L1[shift], color11[shift], wick_transp, i_tdiv_number > 6) )
                array.push(a_lines, f_render_tdiv(split_x7, H1[shift], L1[shift], color11[shift], wick_transp, i_tdiv_number > 7) )
                util.remove_lines(a_lines, i_drawing_max, a_start, array.size(a_lines) - a_start)

            if access_shifted and _show_today
                split_x1 = math.min(maximum_x, f_get_div_x(x1, x2, nx1, 1))
                split_x2 = math.min(maximum_x, f_get_div_x(x1, x2, nx1, 2))
                split_x3 = math.min(maximum_x, f_get_div_x(x1, x2, nx1, 3))
                split_x4 = math.min(maximum_x, f_get_div_x(x1, x2, nx1, 4))
                split_x5 = math.min(maximum_x, f_get_div_x(x1, x2, nx1, 5))
                split_x6 = math.min(maximum_x, f_get_div_x(x1, x2, nx1, 6))
                split_x7 = math.min(maximum_x, f_get_div_x(x1, x2, nx1, 7))
                forecast_split_1 := f_render_tdiv(split_x1, H0, L0, color01, wick_transp, i_tdiv_number > 1), line.delete(forecast_split_1[1])
                forecast_split_2 := f_render_tdiv(split_x2, H0, L0, color01, wick_transp, i_tdiv_number > 2), line.delete(forecast_split_2[1])
                forecast_split_3 := f_render_tdiv(split_x3, H0, L0, color01, wick_transp, i_tdiv_number > 3), line.delete(forecast_split_3[1])
                forecast_split_4 := f_render_tdiv(split_x4, H0, L0, color01, wick_transp, i_tdiv_number > 4), line.delete(forecast_split_4[1])
                forecast_split_5 := f_render_tdiv(split_x5, H0, L0, color01, wick_transp, i_tdiv_number > 5), line.delete(forecast_split_5[1])
                forecast_split_6 := f_render_tdiv(split_x6, H0, L0, color01, wick_transp, i_tdiv_number > 6), line.delete(forecast_split_6[1])
                forecast_split_7 := f_render_tdiv(split_x7, H0, L0, color01, wick_transp, i_tdiv_number > 7), line.delete(forecast_split_7[1])

        else
            if access_newonly or access_all
                line.set_y1(split_1, H0), line.set_y2(split_1, L0)
                line.set_y1(split_2, H0), line.set_y2(split_2, L0)
                line.set_y1(split_3, H0), line.set_y2(split_3, L0)
                line.set_y1(split_4, H0), line.set_y2(split_4, L0)
                line.set_y1(split_5, H0), line.set_y2(split_5, L0)
                line.set_y1(split_6, H0), line.set_y2(split_6, L0)
                line.set_y1(split_7, H0), line.set_y2(split_7, L0)

            if access_shifted and _show_today
                line.set_y1(forecast_split_1, H0), line.set_y2(forecast_split_1, L0), line.set_color(forecast_split_1, color.new(color01, wick_transp))
                line.set_y1(forecast_split_2, H0), line.set_y2(forecast_split_2, L0), line.set_color(forecast_split_2, color.new(color01, wick_transp))
                line.set_y1(forecast_split_3, H0), line.set_y2(forecast_split_3, L0), line.set_color(forecast_split_3, color.new(color01, wick_transp))
                line.set_y1(forecast_split_4, H0), line.set_y2(forecast_split_4, L0), line.set_color(forecast_split_4, color.new(color01, wick_transp))
                line.set_y1(forecast_split_5, H0), line.set_y2(forecast_split_5, L0), line.set_color(forecast_split_5, color.new(color01, wick_transp))
                line.set_y1(forecast_split_6, H0), line.set_y2(forecast_split_6, L0), line.set_color(forecast_split_6, color.new(color01, wick_transp))
                line.set_y1(forecast_split_7, H0), line.set_y2(forecast_split_7, L0), line.set_color(forecast_split_7, color.new(color01, wick_transp))
    true    

//////////////
// Info Bar //
INFO_BAR_X1 = bar_index + i_info_bar_placement

f_render_info_bar (x1) =>
    x2 = x1 + 4
    col = color.new(i_info_bar_color, 30)

    r = line.new(x1, high, x1, low, extend=extend.both, color=col, width=1), line.delete(r[1])
    l = line.new(x2, high, x2, low, extend=extend.both, color=TRANSPARENT, width=1), line.delete(l[1])
    true

f_render_info_bar_today (x1, o, h, l, c, _color) =>
    x2 = x1 + 4

    a = box.new(x1, h, x2, l, bgcolor=color.new(_color, 90), border_color=color.new(_color, 40), border_style=line.style_dotted), box.delete(a[1])
    b = box.new(x1, o, x2, c, bgcolor=color.new(_color, 90), border_color=color.new(_color, 40)), box.delete(b[1])

f_render_info_bar_epr (x1, y1, y2, y3, y4) =>
    if i_epr_rightbar
        col1 = color.new(c_epr, 80)
        col2 = color.new(c_epr, 50)
        col3 = color.new(c_epr, 30)
        x2 = x1 + 2
        a = box.new(x1, y1, x2, y2, bgcolor=col1, border_color=col2, border_width=1), box.delete(a[1])
        R2 = line.new(x1, y3, x2, y3, color=col3, width=5), line.delete(R2[1])
        S2 = line.new(x1, y4, x2, y4, color=col3, width=5), line.delete(S2[1])

        if i_info_bar_labels
            b = label.new(x2, y1, message_expected_high.get(langIndex), color=TRANSPARENT, textcolor=col2, style=label.style_label_left), label.delete(b[1])
            c = label.new(x2, y2, message_expected_low.get(langIndex), color=TRANSPARENT, textcolor=col2, style=label.style_label_left), label.delete(c[1])

f_render_info_bar_prev (x1, _o, _h, _l, _c, _labels, _show) =>
    col1 = color.new(c_cur, 20)
    col2 = color.new(c_cur, 70)
    x2 = x1 + 2

    if _show
        o = line.new(x1, _o, x2, _o, color=col1, width=5), line.delete(o[1])
        h = line.new(x1, _h, x2, _h, color=col2, width=5), line.delete(h[1])
        l = line.new(x1, _l, x2, _l, color=col2, width=5), line.delete(l[1])
        c = line.new(x1, _c, x2, _c, color=col1, width=5), line.delete(c[1])

        if i_info_bar_extend_lines
            o2 = line.new(x1, _o, x2, _o, color=col1, width=1, extend=extend.left), line.delete(o2[1])
            h2 = line.new(x1, _h, x2, _h, color=col2, width=1, extend=extend.left), line.delete(h2[1])
            l2 = line.new(x1, _l, x2, _l, color=col2, width=1, extend=extend.left), line.delete(l2[1])
            c2 = line.new(x1, _c, x2, _c, color=col1, width=1, extend=extend.left), line.delete(c2[1])

        if i_info_bar_labels
            lo = label.new(x2, _o, array.get(_labels, 0), color=TRANSPARENT, textcolor=col1, style=label.style_label_left), label.delete(lo[1])
            lh = label.new(x2, _h, array.get(_labels, 1), color=TRANSPARENT, textcolor=col2, style=label.style_label_left), label.delete(lh[1])
            ll = label.new(x2, _l, array.get(_labels, 2), color=TRANSPARENT, textcolor=col2, style=label.style_label_left), label.delete(ll[1])
            lc = label.new(x2, _c, array.get(_labels, 3), color=TRANSPARENT, textcolor=col1, style=label.style_label_left), label.delete(lc[1])


f_00_line (_y,  x1, _width = 1, _style = line.style_dotted, _lines, _labels) =>
    x2 = x1 + 4

    col = i_info_bar_color
    array.push(_lines, line.new(x1, _y, x2, _y, width=_width, color=col, style=_style) )

    if i_00_extend
        array.push(_lines, line.new(x1 - 1, _y, x1, _y, width=_width, color=color.new(col, 30), style=_style, extend=extend.left) )

    if i_00_labels
        array.push(_labels, label.new(x2, _y, str.tostring(_y, format.mintick), style=label.style_label_left, size=size.small, textcolor=color.new(col, 30), color=TRANSPARENT) )

f_render_info_bar_00 (x1, _range_avg, _pivot) =>
    var dz_lines = array.new<line>()
    var dz_labels = array.new<label>()


    if i_00_rightbar
        auto_freq_value = math.round(((_range_avg / syminfo.mintick) / 5) / 100) * 100
        dz_freq = f_dz_freq_select(i_00_freq, auto_freq_value)

        util.clear_lines(dz_lines)
        util.clear_labels(dz_labels)

        pivot = math.round(_pivot / syminfo.mintick / dz_freq) * syminfo.mintick * dz_freq
        f_00_line(pivot, x1, 2, line.style_solid, dz_lines, dz_labels)

        for i = 1 to i_00_lines_count
            float upper = pivot + (syminfo.mintick * dz_freq * i)
            float lower = pivot - (syminfo.mintick * dz_freq * i)
            f_00_line(upper, x1, 1, line.style_dotted, dz_lines, dz_labels)
            f_00_line(lower, x1, 1, line.style_dotted, dz_lines, dz_labels)
    true

//////////////////////////
// Expected Price Range //
f_epr_pivot () =>
    switch i_epr_plot_base
        'open' => O0
        'close' => C0
        'hl2' => math.avg(H0, L0)
        'hlc3' => math.avg(H0, L0, C0)
        'ohl3' => math.avg(O0, H0, L0)

f_render_EPR (_x1, _x2, _px1, _px2, _nx1, _nx2, _avg, _show) =>
    var a_arr       = array.new<line>()
    var b_arr       = array.new<linefill>()

    x1              = i_epr_shifted ? _nx1 : _x1
    x2              = i_epr_shifted ? _nx2 : _x2
    yc              = f_epr_pivot()
    R1              = yc + (_avg * 0.5)
    S1              = yc - (_avg * 0.5)
    R2              = yc + (_avg * 0.25)
    S2              = yc - (_avg * 0.25)
    color_alert     = color.gray
    is_over         = H0 > R1 and L0 < S1

    if _show and (not i_epr_developing)
        var line epr_upper          = na, var line epr_upper2 = na,
        var line epr_lower          = na, var line epr_lower2 = na
        var linefill epr_fill       = na

        if htf_changed
            if access_shifted
                epr_upper       := line.new(x1, R1, x2, R1, width=1, color=c_epr, style=line.style_dotted)
                epr_upper2      := line.new(x1, R2, x2, R2, width=1, color=c_epr, style=line.style_dotted)
                epr_lower       := line.new(x1, S1, x2, S1, width=1, color=c_epr, style=line.style_dotted)
                epr_lower2      := line.new(x1, S2, x2, S2, width=1, color=c_epr, style=line.style_dotted)
                epr_fill        := linefill.new(epr_lower, epr_upper, color.new(c_epr, i_epr_transp))
                
                a_start         = array.size(a_arr)
                b_start         = array.size(b_arr)
                array.push(a_arr, epr_upper), array.push(a_arr, epr_upper2)
                array.push(a_arr, epr_lower), array.push(a_arr, epr_lower2)
                array.push(b_arr, epr_fill)

                if i_epr_history == option_new or i_epr_history == option_epr3
                    line.delete(epr_upper[1]), line.delete(epr_upper2[1])
                    line.delete(epr_lower[1]), line.delete(epr_lower2[1]) 
                    linefill.delete(epr_fill[1])

                util.remove_lines    (a_arr, i_drawing_max + 1, a_start, array.size(a_arr) - a_start)
                util.remove_linefills(b_arr, i_drawing_max + 1, b_start, array.size(b_arr) - b_start)
        else
            if access_shifted
                line.set_y1(epr_upper, R1), line.set_y2(epr_upper, R1)
                line.set_x1(epr_upper, x1), line.set_x2(epr_upper, x2)
                line.set_y1(epr_upper2, R2), line.set_y2(epr_upper2, R2)
                line.set_x1(epr_upper2, x1), line.set_x2(epr_upper2, x2)

                line.set_y1(epr_lower, S1), line.set_y2(epr_lower, S1)
                line.set_x1(epr_lower, x1), line.set_x2(epr_lower, x2)
                line.set_y1(epr_lower2, S2), line.set_y2(epr_lower2, S2)
                line.set_x1(epr_lower2, x1), line.set_x2(epr_lower2, x2)

    [R1, S1, R2, S2, is_over]

////////////
// Labels //
f_label (_htf, _chg, _avg, _day, _td, _ts, _offset = 0) =>
    t = array.new<string>()

    offset = math.min(_offset, 500)

    //if _day != 0
    //    label.new(bar_index, na, str.tostring(day), yloc=yloc.abovebar, size=size.tiny, color=c_none, textcolor=color.gray)

    if i_labels_show_htf
        array.push(t, _htf)

    if i_labels_show_day and (not na(_day))        
        array.push(t, dayOfWeek.get(_day[offset], langIndex))

    if i_labels_show_price and i_labels_show_avg
        array.push(t, str.tostring(_chg, format.mintick) + '(' + str.tostring(_avg, format.mintick) + ')')
    else if i_labels_show_price
        array.push(t, str.tostring(_chg, format.mintick))

    if i_labels_show_pips and i_labels_show_avg
        array.push(t, str.format(f_pip, util.toPips(_chg)) + str.format(' ('+ f_pip +')', util.toPips(_avg)))
    else if i_labels_show_pips
        array.push(t, str.format(f_pip, util.toPips(_chg)))

    // 1分足以下ではTDSの計算が行えません
    if (not is_1min) and i_labels_show_tds and (_td > 0 or _ts > 0)
        t_td = _td > 0 ? '▲'+str.tostring(_td) : ''
        t_ts = _ts > 0 ? '▼'+str.tostring(_ts) : ''

        array.push(t, t_td + t_ts)
    
    array.join(t, i_candle_label_sep == option_sep1 ? separator_dot : separator_br)

f_render_labels (_htf, x1, x2, px1, px2, nx1, nx2, color01, color11, _avg, _day, _td0, _ts0, _td1, _ts1, _show, _show_today) =>
    if _show
        var label note      = na
        var label n_note    = na
        var a_labels        = array.new<label>()

        p_offset            = 0
        c_offset            = 0

        if access_all
            p_offset := (x1 - px1) * 1  // 1 day  ago
        else if access_shifted
            p_offset := (x1 - px1) * 2  // 2 days ago
            c_offset := (x1 - px1) * 1  // 1 day  ago

        v_note_n    = f_label(_htf, H0[shift] - L0[shift], _avg, _day, _td1, _ts1)
        v_note_c    = f_label(_htf, H1[shift] - L1[shift], _avg, _day, _td0[0], _ts0[0], c_offset)
        v_note_p    = f_label(_htf, H1[shift] - L1[shift], _avg, _day, _td0[shift], _ts0[shift], p_offset)

        if htf_changed
            label.delete(note)
            label.delete(n_note)

            if access_newonly or access_all or access_shifted
                note := label.new(x1, L0[shift], v_note_c, style=i_candle_label_position, color=c_none, textcolor=color.new(color01[shift], i_label_transp), size=i_candle_label_size, textalign=text.align_left)

                true

            if access_all or access_shifted
                a_start = array.size(a_labels)
                array.push(a_labels, label.new(px1, L1[shift], v_note_p, style=i_candle_label_position, color=c_none, textcolor=color.new(color11[shift], i_label_transp), size=i_candle_label_size, textalign=text.align_left))
                util.remove_labels(a_labels, i_drawing_max, a_start, 1)

                true

            if access_shifted and _show_today
                n_note := label.new(nx1, L0, v_note_n, style=i_candle_label_position, color=c_none, textcolor=color.new(color01, i_label_transp), size=i_candle_label_size, textalign=text.align_left)

                true
            
            true
        else
            if access_newonly or access_all
                label.set_y(note, L0)
                label.set_text(note, v_note_n)
                label.set_textcolor(note, color.new(color01, i_label_transp))
                true

            else if access_shifted and _show_today
                label.set_text(note, v_note_c)

                label.set_y(n_note, L0)
                label.set_text(n_note, v_note_n)
                label.set_textcolor(n_note, color.new(color01, i_label_transp))
                true

            true
    true


//////////
// Wick //
f_render_wick (_x1, _x2, _xc, _px1, _px2, _pxc, _nx1, _nx2, _nxc, color01, color11, _show, _show_today) =>
    if _show
        var line h = na
        var line l = na
        var line n_h = na
        var line n_l = na
        var a_lines = array.new<line>()

        if htf_changed
            line.delete(h)
            line.delete(l)
            line.delete(n_h)
            line.delete(n_l)

            if access_newonly or access_all or access_shifted
                x = _xc
                h := line.new(x, H0[shift], x, math.max(O0[shift], C0[shift]), color=color.new(color01[shift], i_candle_wick_transp), width=i_candle_wick_thickness)
                l := line.new(x, L0[shift], x, math.min(O0[shift], C0[shift]), color=color.new(color01[shift], i_candle_wick_transp), width=i_candle_wick_thickness)

            if access_all or access_shifted
                a_start = array.size(a_lines)
                x = _pxc
                array.push(a_lines, line.new(x, H1[shift], x, math.max(O1[shift], C1[shift]), color=color.new(color11[shift], i_candle_wick_transp), width=i_candle_wick_thickness) )
                array.push(a_lines, line.new(x, L1[shift], x, math.min(O1[shift], C1[shift]), color=color.new(color11[shift], i_candle_wick_transp), width=i_candle_wick_thickness) )
                util.remove_lines(a_lines, i_drawing_max, a_start, array.size(a_lines) - a_start)

            if access_shifted and _show_today
                x = _nxc
                n_h := line.new(x, H0, x, math.max(O0, C0), color=color.new(color01, i_candle_wick_transp), width=i_candle_wick_thickness), line.delete(n_l[1])
                n_l := line.new(x, L0, x, math.min(O0, C0), color=color.new(color01, i_candle_wick_transp), width=i_candle_wick_thickness), line.delete(n_h[1])
                true
                
        else
            if access_newonly or access_all
                line.set_y1(h, H0)
                line.set_y2(h, math.max(O0, C0))
                line.set_color(h, color.new(color01, i_candle_wick_transp))
                
                line.set_y1(l, L0)
                line.set_y2(l, math.min(O0, C0))
                line.set_color(l, color.new(color01, i_candle_wick_transp))

            if access_shifted and _show_today
                x = _nxc - math.round(i_candle_wick_thickness / 2)
                line.set_x1(n_h, x), line.set_x2(n_h, x)
                line.set_y1(n_h, H0)
                line.set_y2(n_h, math.max(O0, C0))
                line.set_color(n_h, color.new(color01, i_candle_wick_transp))
                
                line.set_x1(n_l, x), line.set_x2(n_l, x)
                line.set_y1(n_l, L0)
                line.set_y2(n_l, math.min(O0, C0))
                line.set_color(n_l, color.new(color01, i_candle_wick_transp))
        true
    true

/////////////
// CANDLES //

f_render_candles (_x1, _x2, _px1, _px2, _nx1, _nx2, color0, color01, color1, color11, _show, _show_today) =>
    if _show
        var box hl      = na
        var box oc      = na
        var box p_hl    = na
        var box p_oc    = na
        var box n_oc    = na
        var box n_hl    = na
        var a = array.new<box>()

        i_hl_bg_transp      = (i_candle_thickness == 0 and i_candle_show_hl) ? 90  : 96
        i_oc0_bg_transp     = (i_candle_thickness == 0 and i_candle_show_hl) ? 100 : (i_candle_thickness == 0) ? 90 : 94
        i_oc1_bg_transp     = (i_candle_thickness == 0 and i_candle_show_hl) ? 100 : (i_candle_thickness == 0) ? 90 : 94
        _width = i_candle_thickness

        if i_candle_show_fill
            i_oc0_bg_transp := O0[shift] > C0[shift] ? 0 : i_oc0_bg_transp
            i_oc1_bg_transp := O1[shift] > C1[shift] ? 0 : i_oc1_bg_transp

        if htf_changed
            box.delete(hl)
            box.delete(oc)
            box.delete(n_oc)
            box.delete(n_hl)

            if access_newonly or access_all or access_shifted
                if i_candle_show_hl
                    hl := f_candle(_x1, H0[shift], _x2, L0[shift], color01[shift], color.new(color0[shift], i_hl_bg_transp), _width, line.style_dotted, xloc.bar_index)
                if i_candle_show_oc
                    oc := f_candle(_x1, O0[shift], _x2, C0[shift], color01[shift], color.new(color0[shift], i_oc0_bg_transp), _width, line.style_solid, xloc.bar_index)

            if access_all or access_shifted
                a_start = array.size(a)

                if i_candle_show_hl
                    array.push(a, f_candle(_px1, H1[shift], _px2, L1[shift], color11[shift], color.new(color1[shift], i_hl_bg_transp), _width, line.style_dotted, xloc.bar_index))
                if i_candle_show_oc
                    array.push(a, f_candle(_px1, O1[shift], _px2, C1[shift], color11[shift], color.new(color1[shift], i_oc1_bg_transp), _width, line.style_solid, xloc.bar_index))
                
                util.remove_boxes(a, i_drawing_max, a_start, array.size(a) - a_start)

            if access_shifted and _show_today
                if i_candle_show_hl
                    n_hl := f_candle(_nx1, H0, _nx2, L0, color01, color0, _width, line.style_dotted, xloc.bar_index), box.delete(n_hl[1])
                if i_candle_show_oc
                    n_oc := f_candle(_nx1, O0, _nx2, C0, color01, color0, _width, line.style_solid, xloc.bar_index), box.delete(n_oc[1])

        else
            if access_newonly or access_all
                box.set_top(hl, H0)
                box.set_bottom(hl, L0)
                box.set_bgcolor(hl, color.new(color0, i_hl_bg_transp))
                box.set_border_color(hl, color01)
            
                box.set_top(oc, math.max(O0, C0))
                box.set_bottom(oc, math.min(O0, C0))
                box.set_bgcolor(oc, color.new(color0, i_oc0_bg_transp))
                box.set_border_color(oc, color01)

            if access_shifted and _show_today
                box.set_right(oc, _x2)
                box.set_right(hl, _x2)

                box.set_left(n_oc, _nx1)
                box.set_right(n_oc, _nx2)
                box.set_top(n_oc, math.max(O0, C0))
                box.set_bottom(n_oc, math.min(O0, C0))
                box.set_bgcolor(n_oc, color.new(color0, i_oc0_bg_transp))
                box.set_border_color(n_oc, color01)

                box.set_left(n_hl, _nx1)
                box.set_right(n_hl, _nx2)
                box.set_top(n_hl, H0)
                box.set_bottom(n_hl, L0)
                box.set_bgcolor(n_hl, color.new(color0, i_hl_bg_transp))
                box.set_border_color(n_hl, color01)

//////////
// MAIN //
[wopen, whigh, wlow, wclose] = request.security(syminfo.tickerid, '1W', [open[1], high[1], low[1], close[1]])

f_render_main (_htf, _trans, _btransp) =>
    // for exports variables
    var plot_o = 0.0, var plot_o0 = 0.0
    var plot_c = 0.0, var plot_c0 = 0.0
    var plot_h = 0.0, var plot_h0 = 0.0
    var plot_l = 0.0, var plot_l0 = 0.0
    var price_range     = 0.0
    var day             = 0
    var TD0             = 0
    var TS0             = 0
    var pvt_lines       = array.new<line>(), var pvt_labels         = array.new<label>(), var pvt_boxes         = array.new<box>()
    var pvt_lines_next  = array.new<line>(), var pvt_labels_next    = array.new<label>(), var pvt_boxes_next    = array.new<box>()
    var pvt_lines_past  = array.new<line>(), var pvt_labels_past    = array.new<label>(), var pvt_boxes_past    = array.new<box>()

    color0  = O0 < C0 ? color.new(c_bull, _trans)   : color.new(c_bear, _trans)
    color01 = O0 < C0 ? color.new(c_bull, _btransp) : color.new(c_bear, _btransp)
    color1  = O1 < C1 ? color.new(c_bull, _trans)   : color.new(c_bear, _trans)
    color11 = O1 < C1 ? color.new(c_bull, _btransp) : color.new(c_bear, _btransp)

    // Positions
    // 
    // |----P----| |--------|  |----N----|
    // px1     px2 x1      x2 nx1       nx2
    //     pxc         xc          nxc

    px1     = ta.valuewhen(htf_changed, bar_index, 1)
    x1      = ta.valuewhen(htf_changed, bar_index, 0)
    px2     = x1 - 1
    pxc     = math.round(math.avg(px2, px1))
    x2      = (px2 - px1) + x1
    xc      = math.round(math.avg(x2, x1))
    nx1     = (2 * x1) - px1
    nx2     = (x2 - x1) + nx1

    x2     := math.min(x2,  bar_index + max_bars_count)
    nx1    := math.min(nx1, bar_index + max_bars_count)
    nx2    := math.min(nx2, bar_index + max_bars_count)
    nxc     = math.round(math.avg(nx2, nx1))

    // t = Position.new(x1 , x2 )
    // p = Position.new(px1, px2)
    // n = Position.new(nx1, nx2)

    four_days_ago = is_1min ? 0 : ((x1 - px1) * 4)

    price_range_avg = f_pricerange_avg(price_range, x2 - x1)

    //a = label.new(px1, close, 'px1', yloc=yloc.price), label.delete(a[1])
    //b = label.new( x1, close,  'x1', yloc=yloc.price), label.delete(b[1])
    //d = label.new( x2, close,  'x2', yloc=yloc.price), label.delete(d[1])
    //c = label.new(nx1, close, 'nx1', yloc=yloc.price , style=label.style_label_up), label.delete(c[1])
    //e = label.new(nx2, close, 'nx2', yloc=yloc.price), label.delete(e[1])

    if htf_changed
        price_range := (H1 - L1)
        day         := htf_is_intraday ? dayofweek(time, i_candle_label_tz) : na
        TD0         := C0 > C0[four_days_ago] ? TD0 + 1 : 0
        TS0         := C0 < C0[four_days_ago] ? TS0 + 1 : 0

        if access_newonly or access_all or access_shifted
            plot_o := O0[shift], plot_c := C0[shift]
            plot_h := H0[shift], plot_l := L0[shift]
            plot_o0 := O0, plot_c0 := C0
            plot_h0 := H0, plot_l0 := L0
            f_render_pivots(i_pivots_show, false, false, x1 , x2 , 0, pvt_lines, pvt_labels, pvt_boxes, false)
            f_render_pivots(i_pivots_show and i_pivots_show_history, i_pivots_show_history, false, px1, px2, 1, pvt_lines_past, pvt_labels_past, pvt_boxes_past, false)

            true

        if (not i_candle_show)
            line.new(px2, high, px2, low, extend=extend.both, color=color.new(ac.panda('lightgray'), 30), style=line.style_dotted)

    else
        if access_newonly or access_all
            plot_o := O0, plot_c := C0
            plot_h := H0, plot_l := L0

        if access_shifted
            f_render_pivots(i_pivots_show_forecast, false, true, nx1, nx2, 0, pvt_lines_next, pvt_labels_next, pvt_boxes_next, true)

            true

    TD1 = (C0 > C0[four_days_ago] ? TD0 + 1 : 0)
    TS1 = (C0 < C0[four_days_ago] ? TS0 + 1 : 0)

    f_render_wick(x1, x2, xc, px1, px2, pxc, nx1, nx2, nxc, color01, color11, i_candle_show_wick, i_candle_show_today)
    f_render_divs(x1, x2, px1, px2, nx1, nx2, color01, color11, i_candle_wick_transp, i_tdiv_show, i_candle_show_today)
    f_render_candles(x1, x2, px1, px2, nx1, nx2, color0, color01, color1, color11, i_candle_show, i_candle_show_today)
    f_render_labels(_htf, x1, x2, px1, px2, nx1, nx2, color01, color11, price_range_avg, day, TD0, TS0, TD1, TS1, i_candle_label_show, i_candle_show_today)
    [plot_epr_R1, plot_epr_S1, plot_epr_R2, plot_epr_S2, epr_over] = f_render_EPR(x1, x2, px1, px2, nx1, nx2, price_range_avg, i_epr_show)

    if i_show_info_bar
        info_bar_x = i_candle_show ? x2 + i_info_bar_placement : INFO_BAR_X1

        info_bar_labels_1 = array.from(message_prev_open.get(langIndex), message_prev_high.get(langIndex), message_prev_low.get(langIndex), message_prev_close.get(langIndex))
        info_bar_labels_2 = array.from(message_prev_week_open.get(langIndex), message_prev_week_high.get(langIndex), message_prev_week_low.get(langIndex), message_prev_week_close.get(langIndex))

        f_render_info_bar(info_bar_x)
        f_render_info_bar_00(info_bar_x, plot_epr_R1 - plot_epr_S1, math.avg(H0, L0))
        f_render_info_bar_prev(info_bar_x, O1, H1, L1, C1, info_bar_labels_1, i_info_bar_show_prev_day)
        f_render_info_bar_prev(info_bar_x, wopen, whigh, wlow, wclose, info_bar_labels_2, i_info_bar_show_prev_week)
        f_render_info_bar_epr(info_bar_x, plot_epr_R1, plot_epr_S1, plot_epr_R2, plot_epr_S2)
        f_render_info_bar_today(info_bar_x, O0, H0, L0, C0, color0)

    [plot_o, plot_h, plot_l, plot_c, plot_o0, plot_h0, plot_l0, plot_c0, plot_epr_R1, plot_epr_S1, plot_epr_R2, plot_epr_S2, epr_over]

[o, h, l, c, o0, h0, l0, c0, R1, S1, R2, S2, epr_over] = f_render_main(htf, i_candle_bg_transp, i_candle_line_transp)
pp = math.avg(h, l, c)

///////////////
// Plotting
///////////////
plot(o, 'HTF Open'  , linewidth=2, display=display.none)
plot(h, 'HTF High'  , linewidth=2, display=display.none)
plot(l, 'HTF Low'   , linewidth=2, display=display.none)
plot(c, 'HTF Close' , linewidth=2, display=display.none)
plot(i_epr_show and i_epr_developing ? math.avg(H0, L0) : na, 'EPR middle', linewidth=1, color=c_epr)
plot(i_epr_show and i_epr_developing ? R1 : na, 'EPR top'    , linewidth=2, color=c_epr)
plot(i_epr_show and i_epr_developing ? S1 : na, 'EPR bottom' , linewidth=2, color=c_epr)
plotshape((not htf_changed) and ta.cross(o, close) ? o : na, 'Crossed open' , color=color.orange, style=shape.xcross, location=location.absolute, size=size.tiny, display=display.none)
plotshape((not htf_changed) and ta.cross(h, close) ? h : na, 'Crossed high' , color=color.orange, style=shape.xcross, location=location.absolute, size=size.tiny, display=display.none)
plotshape((not htf_changed) and ta.cross(l, close) ? l : na, 'Crossed low'  , color=color.orange, style=shape.xcross, location=location.absolute, size=size.tiny, display=display.none)
plotshape((not htf_changed) and ta.cross(c, close) ? c : na, 'Crossed close', color=color.orange, style=shape.xcross, location=location.absolute, size=size.tiny, display=display.none)
plotshape((not htf_changed) and (i_candle_access == option_new or i_candle_access == option_all) and ta.change(h) > 0, 'New high', style=shape.labelup, color=color.blue, location=location.bottom, size=size.tiny, display=display.none)  // Work on 'new only' or 'All'
plotshape((not htf_changed) and (i_candle_access == option_new or i_candle_access == option_all) and ta.change(l) < 0, 'New low', style=shape.labeldown, color=color.red, location=location.bottom, size=size.tiny, display=display.none)   // Work on 'new only' or 'All'


///////////////////
// Message panel //

f_emojicolor (_v) =>
    switch _v
        icon_danger => ac.package(i_color_name, 'yellow')
        => i_msg_color

f_get_cal (_time, _lang, _tz) =>
    mydate = dayofmonth(_time, _tz)
    mydayofweek = dayofweek(_time, _tz)
    myweekofmonth = str.tostring(math.floor((mydate + (6 - mydayofweek)) / 7 + 1))    
    
    en = dayOfWeek.get(mydayofweek, 0) + '. ' + str.format_time(_time, 'dd/MM/yyyy', _tz)  + ' ' + myweekofmonth + text_w.get(0)
    ja = str.format_time(_time, 'yyyy年MM月dd日', _tz) +  '（' + dayOfWeek.get(mydayofweek, 1) + '）' + ' ' + myweekofmonth + text_w.get(1)

    text_cal = Message.new(en, ja)
    text_cal.get(langIndex)

a_table         = array.new<string>()
a_icons         = array.new<string>()

is_muted_info   = counter < 10
msg_price       = math.avg(open, close, hlc3)

var msg_prefix          = access_shifted ? text_previous.get(langIndex) : ''
var msg_cross_high      = Message.new('Price is crossing '+ msg_prefix +' High.', msg_prefix + '高値とクロス')
var msg_approach_high   = Message.new('Price is approaching '+ msg_prefix + ' High.', msg_prefix + '高値にアプローチ')
var msg_cross_open      = Message.new('Price is crossing '+ msg_prefix + ' Open.', msg_prefix + '始値とクロス')
var msg_approach_open   = Message.new('Price is approaching '+ msg_prefix + ' Open.', msg_prefix + '始値にアプローチ')
var msg_cross_low       = Message.new('Price is crossing '+ msg_prefix + ' Low.', msg_prefix + '安値とクロス')
var msg_approach_low    = Message.new('Price is approaching '+ msg_prefix + ' Low.', msg_prefix + '安値にアプローチ')
var msg_cross_close     = Message.new('Price is crossing '+ msg_prefix + ' Close.', msg_prefix + '終値とクロス')
var msg_approach_close  = Message.new('Price is approaching '+ msg_prefix + ' Close.', msg_prefix + '終値にアプローチ')
var msg_cross_pp        = Message.new('Price is crossing PP.', 'PPとクロス')
var msg_approach_pp     = Message.new('Price is approaching PP.', 'PPにアプローチ')
var msg_epr             = Message.new('The expected price range was broken.', '予想値幅を超えました')

if i_msg_show_info
    if ta.cross(msg_price, h) 
        array.push(a_table, msg_cross_high.get(langIndex))
        array.push(a_icons, icon_cross)
    else if math.abs((h - msg_price) / msg_price) <= i_msg_thres
        array.push(a_table, msg_approach_high.get(langIndex))
        array.push(a_icons, icon_notif)
    
    if ta.cross(msg_price, o)
        array.push(a_table, msg_cross_open.get(langIndex))
        array.push(a_icons, icon_cross)
    else if math.abs((o - msg_price) / msg_price) <= i_msg_thres
        array.push(a_table, msg_approach_open.get(langIndex))
        array.push(a_icons, icon_notif)
    
    if ta.cross(msg_price, l)
        array.push(a_table, msg_cross_low.get(langIndex))
        array.push(a_icons, icon_cross)
    else if math.abs((l - msg_price) / msg_price) <= i_msg_thres
        array.push(a_table, msg_approach_low.get(langIndex))
        array.push(a_icons, icon_notif)

    if (not is_muted_info) and ta.cross(msg_price, c)
        array.push(a_table, msg_cross_close.get(langIndex))
        array.push(a_icons, icon_cross)
    else if (not is_muted_info) and math.abs((c - msg_price) / msg_price) <= i_msg_thres
        array.push(a_table, msg_approach_close.get(langIndex))
        array.push(a_icons, icon_notif)
    
    if ta.cross(msg_price, pp)
        array.push(a_table, msg_cross_pp.get(langIndex))
        array.push(a_icons, icon_cross)
    else if math.abs((pp - msg_price) / msg_price) <= i_msg_thres
        array.push(a_table, msg_approach_pp.get(langIndex))
        array.push(a_icons, icon_notif)

if i_msg_show_warn
    if epr_over
        array.push(a_table, msg_epr.get(langIndex))
        array.push(a_icons, icon_danger)

tbl = table.new(i_placement, 3, 4)

f_timeformat (_v) => _v > 9 ? str.tostring(_v) : '0'+str.tostring(_v)

f_insert_row (_tbl, _y, _msg, _text_color, _bgcolor) =>
    table.cell(_tbl, 0, _y, _msg, text_color=_text_color, text_size=i_msg_size, text_valign=text.align_top, text_halign=text.align_left, bgcolor=_bgcolor)
    table.merge_cells(_tbl, 0, _y, 2, _y)

if i_show_messagebox and barstate.islast
    y = 0

    if array.size(a_table) > 0
        for i = 0 to array.size(a_table) - 1
            y      := i
            msg     = array.get(a_table, i)
            icon    = array.get(a_icons, i)
            mytime  = icon == icon_calendar ? timenow : time
            now     = f_timeformat(hour(mytime, i_msg_tz)) + ':' + f_timeformat(minute(mytime, i_msg_tz))
            now    := icon == icon_calendar ? '' : now

            table.cell(tbl, 0, y, now,  text_color=i_msg_color,         text_size=i_msg_size, text_valign=text.align_top)
            table.cell(tbl, 1, y, icon, text_color=f_emojicolor(icon),  text_size=i_msg_size, text_valign=text.align_top)
            table.cell(tbl, 2, y, msg,  text_color=i_msg_color,         text_size=i_msg_size, text_valign=text.align_top, text_halign=text.align_left)

    if i_msg_show_cal
        y      := y + 1
        msg     = f_get_cal(timenow, i_msg_lang, i_msg_tz)
        f_insert_row(tbl, y, msg, i_msg_color, c_none)

    if is_1min
        y      := y + 1
        msg     = icon_danger + ' ' + f_lang(i_msg_lang, 'It doesn\'t display correctly on the 1 min.', '1分足では正常に表示できません')
        f_insert_row(tbl, y, msg, ac.package(i_color_name, 'red'), color.new(ac.package(i_color_name, 'black'), 10))

plotshape(i_msg_dot and math.abs((o - msg_price) / msg_price) <= i_msg_thres ? o : na, 'Message test (Open)',   color=ac.tradingview('orange'), style=shape.circle, size=size.tiny, location=location.absolute, display=display.none)
plotshape(i_msg_dot and math.abs((h - msg_price) / msg_price) <= i_msg_thres ? h : na, 'Message test (High)',   color=ac.tradingview('orange'), style=shape.circle, size=size.tiny, location=location.absolute, display=display.none)
plotshape(i_msg_dot and math.abs((l - msg_price) / msg_price) <= i_msg_thres ? l : na, 'Message test (Low)',    color=ac.tradingview('orange'), style=shape.circle, size=size.tiny, location=location.absolute, display=display.none)
plotshape(i_msg_dot and math.abs((c - msg_price) / msg_price) <= i_msg_thres and (not is_muted_info) ? c : na, 'Message test (Close)',  color=ac.tradingview('orange'), style=shape.circle, size=size.tiny, location=location.absolute, display=display.none)
plotshape(i_msg_dot and math.abs((pp- msg_price) / msg_price) <= i_msg_thres ? pp: na, 'Message test (PP)',     color=ac.tradingview('orange'), style=shape.circle, size=size.tiny, location=location.absolute, display=display.none)
plot(h + (msg_price * i_msg_thres), display=display.none, editable=false)
