Custom HTF candle overlay, ICT True Day
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/

// Set custom higher time frame session from which to overlay higher time frame candles and wicks
// Currently set to ICT's 'True Day' as HTF Custom candle overlay 
//added Wick CE midlines
//added option to plot 2x session htf candles in a day
//added option to plot weekly candle overlay
//added border color options 

//@twingall

//@version=5
indicator(title='Custom HTF candle overlay, ICT True Day', shorttitle="True Day - Overlay", overlay=true, max_boxes_count = 250, max_lines_count = 500)
_inputSession = input.session('0000-1500', title='custom HTF range', group = "custom range")
showHTFoverlay = input.bool(true, "show HTF candle overlay",group = "custom range")
showOpenPrice = input.bool(false, "show opening price",group = "custom range")

twoSessions = input.bool(false, "show two sessions in day", group = "_____two sessions [override]")
inputSessionA = input.session('0830-0930', title='(session#1)', group = "_____two sessions [override]")
inputSessionB = input.session('1400-1600', title='(session#2)', group = "_____two sessions [override]")
htfWeeklyCandle = input.bool(false, "Weekly candle overlay", group = "_____weekly candle overlay [override]", tooltip="this is week-long session is mon-friday, midnight-midnight; does not include Sunday's price action")
inputSessionC =  '0000-0000:234567'
inputSession = htfWeeklyCandle?inputSessionC:_inputSession
days =input.int(250, "days lookback", group="~~~ options ~~~")
lookbackTime = 1000*60*60*24*(days+1) 
visible = time >= timenow - lookbackTime

colorBull = input.color(color.new(color.green, 70), "bull body", group="~~~ options ~~~", inline = "3")
colorBear = input.color(color.new(color.red, 70), "bear body", group="~~~ options ~~~", inline = "3")
colBorderBull = input.color(color.new(color.green, 100), "bull border", group="~~~ options ~~~", inline = "4", tooltip = "Default is invisible.\n\nIncrease transparency from 0 to make borders visible")
colBorderBear = input.color(color.new(color.red, 100), "bear border", group="~~~ options ~~~", inline = "4")
borderWidth   = input.int(2, "width", options = [1,2,3,4,5,6,7,8,9,10], inline = "4", group="~~~ options ~~~")

wickColor =input.color(color.new(color.purple, 70), "wick", inline = "5", group="~~~ options ~~~")
wickWidth = input.int(5, "wick width", options = [1,2,3,4,5,6,7,8,9,10], inline = "5", group="~~~ options ~~~")

showWickCE =input.bool(false, "Wick midpoint lines", inline = "5", group = "midlines", tooltip="Ignores small wicks, based on their length as a fraction of high-low range; tweak this fraction filter by editing the number in lines 110-111") 

wickCEcolor = input.color(color.gray, "",inline = "5", group = "midlines")
showBodyCE =input.bool(false, "Body midpoint lines", inline = "6", group = "midlines") 
BodyCEcolor = input.color(color.gray, "",inline = "6", group = "midlines")
wickCEbarsExtend = input.int(0, "Extend line(bars):", inline = "7", group = "midlines" , tooltip = "This can be inconsistent across timeframes; especially when using weekly candle overlay (try 2000 if using ltf charts with weekly overlay)")

colorNone = color.new(color.white, 100)

inSession = twoSessions and not htfWeeklyCandle ?not na(time(timeframe.period,inputSessionA +","+ inputSessionB+":23456", "America/New_York")):not na(time(timeframe.period, str.tostring(inputSession), "America/New_York")) 

/// ~~FUNCTIONS~~
open()=>
    var float result =na
    if inSession and not inSession[1]
        result:=open
    result

close()=>
    var float result =na
    if inSession
        result:=close
    result

high() => 
    var float result = na
    if inSession and not inSession[1]
        result:=high
    else if inSession   
        result:=math.max(result, high)
    result

low() => 
    var float result = na
    if inSession and not inSession[1]
        result:=low
    else if inSession   
        result:=math.min(result, low)
    result

closeTime()=>
    var int   closeTime  = na
    if inSession[1] and not inSession
        closeTime   := time[1]
    int result = closeTime

openTime()=>
    var int  _openTime  = na
    if inSession and not inSession[1]
        _openTime   := time
    int result = _openTime

float htfOpen = open()
float htfHigh = high()
float htfLow = low()
int htfHighTime = ta.valuewhen(high==htfHigh and inSession,time,0)
int htfLowTime = ta.valuewhen(low==htfLow and inSession,time,0)
float htfClose =close()
int htfCloseTime = ta.valuewhen(close==htfClose and inSession,time,0)
int htfOpenTime = openTime()
int htfMidTime = htfOpenTime + ((htfCloseTime-htfOpenTime)/2)
int half_x_body = (htfCloseTime-htfOpenTime)/2
// Plots opening price of the custom range
plot(inSession and showOpenPrice and visible ? htfOpen : na, title='open line', color=color.new(color.red, 0), linewidth=1, style=plot.style_linebr)

////////
// ~~Draw overlay candle bodies and wicks~~

    //initialize variables
bodyBox = box (na)
wickLine = line (na)
BodyMidLine = line (na)
tailLine = line (na)
wickCEline = line(na)
tailCEline = line(na)

isBull = htfOpen>=htfClose?false:true 
bodyHigh = isBull?htfClose:htfOpen
bodyLow = isBull?htfOpen:htfClose
wickCE = bodyHigh+(htfHigh-bodyHigh)/2
tailCE = bodyLow-(bodyLow-htfLow)/2
isWickSignificant = (htfHigh-bodyHigh)>= (htfHigh-htfLow)/6 //change denominator: make it smaller to filter out smaller wicks
isTailSignificant = (bodyLow-htfLow)>= (htfHigh-htfLow)/6  //change denominator: make it smaller to filter out smaller wicks
extTime = wickCEbarsExtend * 1000* timeframe.in_seconds(timeframe.period)

if  inSession and showHTFoverlay and visible
    if inSession [1] 
        box.delete(bodyBox[1])
        line.delete(wickLine[1])
        line.delete(tailLine[1])
        line.delete(BodyMidLine[1])
    bodyBox := box.new(htfOpenTime, htfOpen, htfCloseTime, htfClose, xloc = xloc.bar_time, border_color = isBull?colBorderBull:colBorderBear, bgcolor = isBull?colorBull:colorBear, border_width = borderWidth)
    wickLine:= line.new(htfMidTime, htfHigh, htfMidTime, bodyHigh, xloc=xloc.bar_time, color = wickColor, width = wickWidth)
    tailLine:= line.new(htfMidTime, bodyLow, htfMidTime, htfLow, xloc=xloc.bar_time, color = wickColor, width = wickWidth)
    BodyMidLine:= line.new(htfOpenTime, isBull?htfClose-((htfClose-htfOpen)/2):htfOpen-((htfOpen-htfClose)/2),  
     htfCloseTime,isBull?htfClose-((htfClose-htfOpen)/2):htfOpen-((htfOpen-htfClose)/2), xloc=xloc.bar_time, color = showBodyCE?BodyCEcolor: colorNone )
//wick midlines
if  inSession and showHTFoverlay and visible and showWickCE
    if inSession [1] 
        line.delete(wickCEline[1])
        line.delete(tailCEline[1])
    wickCEline := line.new(htfMidTime, wickCE, (htfCloseTime+extTime), wickCE, xloc=xloc.bar_time,color =isWickSignificant? wickCEcolor:colorNone, width = 1, style = line.style_dotted)
    tailCEline := line.new(htfMidTime, tailCE, (htfCloseTime+extTime) ,tailCE, xloc=xloc.bar_time,color =isTailSignificant? wickCEcolor:colorNone, width = 1,style = line.style_dotted)
