Search code examples
pine-scriptpine-script-v5trading

How can I place labels at the end of a vertical seperator line?


I wrote an Indicator in Pinescript, which shows seperator lines for the weekdays and also for the weekend. Additional to that, its possible to show the weekday names.

What I'm having problems with, is the positioning of the Weekday-labels. I want to place them at the end of the vertical seperator lines. But the Problem is that there is always 1 label which is misplaced. So its always 1 label placed on the correct place, at the end of the seperator line, but then there's always 1 in between which is wrong. It looks like this: Label Problem

The code to display the weekday currently looks like this (complete code at the end):

low2 = hl2 - (syminfo.mintick) * i_Seplength     
label1 = label.new(x=time + 8, y=low2, text='TestMonday', xloc=xloc.bar_time, color=dot_color, textcolor=i_user_dow_color, style=label.style_circle, size=size.normal)     
array.push(createDays, label1)

Does anyone have an Idea where my failure is? Or is there another way to achieve that?

Here you can see the whole code:

//@version=5
indicator("Show Week and Day Seperator", overlay=true, max_lines_count=500, max_boxes_count=500)

// Constants and One-Time-Init Vars {
transpLine = 0

// }

// Inputs {
grpWeekLine = "================== Week Seperator Lines =================="
i_user_week_start = input.string(title='Week Separator on Day', defval='Sunday', options=['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], group=grpWeekLine)
i_user_week_toggle = input(title='Show Week Separator Line', defval=true, inline="Weekly Line", group=grpWeekLine)
i_WeekSepLookBack = input.int(title="Lookback", defval=5, minval=0, maxval=400, group=grpWeekLine)
i_weeklyLineCl =input.color(color.new(color.blue, transpLine), "", inline="Weekly Line", group=grpWeekLine)
i_weekLineWidth = input.int(title='Week Line Width', defval=4, minval=0, maxval=20, step=1, group=grpWeekLine)
i_user_week_line_style = input.string(title='Week Line Style', defval='dashed', options=['solid', 'dashed', 'dotted'], group=grpWeekLine)

grpDaykLine = "=================== Day Seperator Lines ==================="
i_user_day_toggle = input(title='Show Day Separator Line', defval=true, inline="Day Line", group=grpDaykLine)
i_daylyLineCl =input.color(color.new(color.blue, transpLine), "", inline="Day Line", group=grpDaykLine)
i_DaySepLookBack = input.int(title="Lookback", defval=5, minval=0, maxval=400, group=grpDaykLine)
i_dayLineWidth = input.int(title='Day Line Width', defval=4, minval=0, maxval=20, step=1, group=grpDaykLine)
i_user_day_line_style = input.string(title='Day Line Style', defval='dashed', options=['solid', 'dashed', 'dotted'], group=grpDaykLine)


// Alternative Lines using backcolours
grpWeekDayLineAdditional = "================== Additional Settings =================="
i_user_show_on_1hour = input(title='Show Day Separator and Days of Week on 1 hour Chart', defval=false, group=grpWeekDayLineAdditional)
i_user_show_on_updaily = input(title='Show Week Separator up to the Daily Chart', defval=false, group=grpWeekDayLineAdditional)
i_showDOW = input.bool(true, title='Show days of week', inline="i_ShowDow", group=grpWeekDayLineAdditional)
i_user_dow_color = input.color(color.new(color.blue, transpLine), "", inline="i_ShowDow", group=grpWeekDayLineAdditional)
i_isShortDayLabel = input.bool(false, "Use short names for days of week (Mon, Tue...)", group=grpWeekDayLineAdditional)
i_EndlessLines = input.bool(true, title="Reduce length of horizontal Seperators", group=grpWeekDayLineAdditional)
i_Seplength = input.int(title="Seperator Length", defval=800, group=grpWeekDayLineAdditional)

// }

week_line_style = i_user_week_line_style == 'solid' ? line.style_solid : i_user_week_line_style == 'dashed' ? line.style_dashed : i_user_week_line_style == 'dotted' ? line.style_dotted : line.style_solid
day_line_style = i_user_day_line_style == 'solid' ? line.style_solid : i_user_day_line_style == 'dashed' ? line.style_dashed : i_user_day_line_style == 'dotted' ? line.style_dotted : line.style_solid

tickerExchangeOffset = 5
int new_day_start_time = 17
int dayLabelStartTime = 1
week_start_day = i_user_week_start == 'Sunday' ? dayofweek.sunday : i_user_week_start == 'Monday' ? dayofweek.monday : i_user_week_start == 'Tuesday' ? dayofweek.tuesday : i_user_week_start == 'Wednesday' ? dayofweek.wednesday : i_user_week_start == 'Thursday' ? dayofweek.thursday : i_user_week_start == 'Friday' ? dayofweek.friday : i_user_week_start == 'Saturday' ? dayofweek.saturday : dayofweek.sunday

// Functions {

f_vline(Lookback, BarIndex, Color, LineStyle, LineWidth, LookBack) => 

    low_ = hl2 - (syminfo.mintick) * i_Seplength
    high_ = hl2 + (syminfo.mintick) * i_Seplength

    var createLines = array.new_line()

    array.push(createLines, line.new(time, low_, time, high_, xloc.bar_time, extend=extend.none, color=Color, style=LineStyle, width=LineWidth))

    if array.size(createLines) > Lookback
        ln = array.shift(createLines)
        line.delete(ln)


f_vlineEndless(Lookback, BarIndex, Color, LineStyle, LineWidth, LookBack) => 

    var createLines = array.new_line()

    array.push(createLines, line.new(BarIndex, 0, BarIndex, 1, extend=extend.both, color=Color, style=LineStyle, width=LineWidth))

    if array.size(createLines) > Lookback
        ln = array.shift(createLines)
        line.delete(ln)
// }

// Calcutations {

if syminfo.timezone == 'Etc/UTC'
    new_day_start_time += tickerExchangeOffset
    dayLabelStartTime += tickerExchangeOffset
    dayLabelStartTime
            
// Add the start of week line
isNewWeek() =>
    dayofweek == week_start_day ? 1 : 0
    
isStartTime() =>
    hour == new_day_start_time and minute == 0 ? 1 : 0
   
isValidDaySeparatorResolution() =>
    timeframe.isdwm == true or timeframe.period == '60' and not i_user_show_on_1hour or timeframe.in_seconds() >= timeframe.in_seconds("120")  ? 0 : 1

isValidWeekSeparatorResolution() =>
    i_user_show_on_updaily and timeframe.isdwm == false ? 1 : not i_user_show_on_updaily and timeframe.in_seconds() <= timeframe.in_seconds("59") ? 1 : 0

isValidDaySeparator = isValidDaySeparatorResolution()
isValidDayTextSeparator = isValidDaySeparatorResolution()
isValidWeekSeparator = isValidWeekSeparatorResolution()

if isValidWeekSeparator and i_user_week_toggle and isNewWeek() == 1 and isStartTime() == 1 and i_EndlessLines == true
    f_vline(i_WeekSepLookBack, bar_index, i_weeklyLineCl, week_line_style, i_weekLineWidth, i_WeekSepLookBack)

if isValidWeekSeparator and i_user_week_toggle and isNewWeek() == 1 and isStartTime() == 1 and not i_EndlessLines == true
    f_vlineEndless(i_WeekSepLookBack, bar_index, i_weeklyLineCl, week_line_style, i_weekLineWidth, i_WeekSepLookBack)
    
// Add daily separator
isNewDay() =>
    dayofweek != week_start_day ? 1 : 0

if isValidDaySeparator and i_user_day_toggle and isNewDay() == 1 and isStartTime() == 1 and i_EndlessLines == true
    f_vline(i_DaySepLookBack, bar_index, i_daylyLineCl, day_line_style, i_dayLineWidth, i_DaySepLookBack)

if isValidDaySeparator and i_user_day_toggle and isNewDay() == 1 and isStartTime() == 1 and not i_EndlessLines == true
    f_vlineEndless(i_DaySepLookBack, bar_index, i_daylyLineCl, day_line_style, i_dayLineWidth, i_DaySepLookBack)

// Display the days of week
dot_color = color.new(color.silver, 100)
dowtext_color = color.new(color.silver, 0)

//New Version of "Days of Week"
var createDays = array.new_label()

if (not i_isShortDayLabel and i_showDOW or i_showDOW and timeframe.period == '60' and i_user_show_on_1hour and not i_isShortDayLabel) and isValidDayTextSeparator ? hour == dayLabelStartTime and minute == 0 and dayofweek == dayofweek.monday : false
    low2 = hl2 - (syminfo.mintick) * i_Seplength     
    label1 = label.new(x=time + 8, y=low2, text='TestMonday', xloc=xloc.bar_time, color=dot_color, textcolor=i_user_dow_color, style=label.style_circle, size=size.normal)     
    array.push(createDays, label1)

if array.size(createDays) > i_DaySepLookBack
    size = array.size(createDays) - i_DaySepLookBack
    for i = 1 to size
        lb = array.get(createDays, i)
        label.delete(lb)

//Old Version of "Days of Week"
plotshape((not i_isShortDayLabel and i_showDOW or i_showDOW and timeframe.period == '60' and i_user_show_on_1hour and not i_isShortDayLabel) and isValidDayTextSeparator ? hour == dayLabelStartTime and minute == 0 and dayofweek == dayofweek.monday : false, text='Monday', color=dot_color, offset=8, style=shape.circle, location=location.bottom, textcolor=i_user_dow_color, size=size.tiny, editable=false)
plotshape((not i_isShortDayLabel and i_showDOW or i_showDOW and timeframe.period == '60' and i_user_show_on_1hour and not i_isShortDayLabel) and isValidDayTextSeparator ? hour == dayLabelStartTime and minute == 0 and dayofweek == dayofweek.tuesday : false, text='Tuesday', color=dot_color, offset=8, style=shape.circle, location=location.bottom, textcolor=i_user_dow_color, size=size.tiny, editable=false)
plotshape((not i_isShortDayLabel and i_showDOW or i_showDOW and timeframe.period == '60' and i_user_show_on_1hour and not i_isShortDayLabel) and isValidDayTextSeparator ? hour == dayLabelStartTime and minute == 0 and dayofweek == dayofweek.wednesday : false, text='Wednesday', color=dot_color, offset=8, style=shape.circle, location=location.bottom, textcolor=i_user_dow_color, size=size.tiny, editable=false)
plotshape((not i_isShortDayLabel and i_showDOW or i_showDOW and timeframe.period == '60' and i_user_show_on_1hour and not i_isShortDayLabel) and isValidDayTextSeparator ? hour == dayLabelStartTime and minute == 0 and dayofweek == dayofweek.thursday : false, text='Thursday', color=dot_color, offset=8, style=shape.circle, location=location.bottom, textcolor=i_user_dow_color, size=size.tiny, editable=false)
plotshape((not i_isShortDayLabel and i_showDOW or i_showDOW and timeframe.period == '60' and i_user_show_on_1hour and not i_isShortDayLabel) and isValidDayTextSeparator ? hour == dayLabelStartTime and minute == 0 and dayofweek == dayofweek.friday : false, text='Friday', color=dot_color, offset=8, style=shape.circle, location=location.bottom, textcolor=i_user_dow_color, size=size.tiny, editable=false)

plotshape((i_isShortDayLabel and i_showDOW or i_showDOW and timeframe.period == '60' and i_user_show_on_1hour and i_isShortDayLabel) and isValidDayTextSeparator ? hour == dayLabelStartTime and minute == 0 and dayofweek == dayofweek.monday : false, text='Mon', color=dot_color, offset=8, style=shape.circle, location=location.bottom, textcolor=i_user_dow_color, size=size.tiny, editable=false)
plotshape((i_isShortDayLabel and i_showDOW or i_showDOW and timeframe.period == '60' and i_user_show_on_1hour and i_isShortDayLabel) and isValidDayTextSeparator ? hour == dayLabelStartTime and minute == 0 and dayofweek == dayofweek.tuesday : false, text='Tue', color=dot_color, offset=8, style=shape.circle, location=location.bottom, textcolor=i_user_dow_color, size=size.tiny, editable=false)
plotshape((i_isShortDayLabel and i_showDOW or i_showDOW and timeframe.period == '60' and i_user_show_on_1hour and i_isShortDayLabel) and isValidDayTextSeparator ? hour == dayLabelStartTime and minute == 0 and dayofweek == dayofweek.wednesday : false, text='Wed', color=dot_color, offset=8, style=shape.circle, location=location.bottom, textcolor=i_user_dow_color, size=size.tiny, editable=false)
plotshape((i_isShortDayLabel and i_showDOW or i_showDOW and timeframe.period == '60' and i_user_show_on_1hour and i_isShortDayLabel) and isValidDayTextSeparator ? hour == dayLabelStartTime and minute == 0 and dayofweek == dayofweek.thursday : false, text='Thu', color=dot_color, offset=8, style=shape.circle, location=location.bottom, textcolor=i_user_dow_color, size=size.tiny, editable=false)
plotshape((i_isShortDayLabel and i_showDOW or i_showDOW and timeframe.period == '60' and i_user_show_on_1hour and i_isShortDayLabel) and isValidDayTextSeparator ? hour == dayLabelStartTime and minute == 0 and dayofweek == dayofweek.friday : false, text='Fri', color=dot_color, offset=8, style=shape.circle, location=location.bottom, textcolor=i_user_dow_color, size=size.tiny, editable=false)

// }

// Plots {

// }

EDIT 1: I corrected the part to reduce the day of week names to a defined minimum

if array.size(createDays) > i_DaySepLookBack
    size = array.size(createDays) - i_DaySepLookBack
    for i = 1 to size
        lb = array.get(createDays, i)
        label.delete(lb)

Solution

  • What you see and what the problem is:

    • You're plotting the weekdays with location.bottom so these are at the lowest visible row in the chart.
    • Then your "TestMonday" label conditions don't match those of the vertical lines. If you match these your labels will be printed correctly as well. To modify the y coordinate of your label, you can use the low of the line and multiply it eg. by 0.99
    • line 125 if array.size(createDays) > 5 here you delete all your labels in the loop. if you want to delete only the ones after 5 you'll have to alter your code:
    if array.size(createLines) > Lookback
        ln = array.shift(createLines) // remove 1st of eg. 5
        line.delete(ln) // delete it
    

    So make sure your conditionals for your label and line match to print it the correct way with the correct hl2 values for the required y value (height) and delete only the last added item from your array instead of everything.