SPX overnight
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © domsito
//@version=5
//purpose of this script is to display estimate of SPX and SPY ticker values in the period while the market is closed. 
//it's meant to be used only with ES1! ticker (S&P 500 E-MINI FUTURES)

indicator("SPY SPX overnight", "", true)
max_bars_back(time, 5000)

var bool showDailyChange = input.bool(true, "Show change since previous day close", group = "General")
var bool showPrevDayLine = input.bool(true, "Mark prevous day close with horizontal line", group = "line")
var bool showPrevWeekCloseLine = input.bool(true, "Mark prevous week close with horizontal line", group = "line")

var lineStyle = input.string(line.style_solid, title="Line style", options=[line.style_solid, line.style_dashed, line.style_dotted], inline = "1", group = "line")
var lineColor = input(color.blue, "Line color", inline = "1", group = "line")
var lineColor2 = input(color.lime, "Line2 color", inline = "1", group = "line")

var table spxTable = table.new(position.top_right, 1, 4, frame_color= color.blue)

table.cell_set_width(spxTable,0,0, 15)
table.cell_set_width(spxTable,0,1, 15)
table.cell_set_width(spxTable,0,2, 15)
table.cell_set_width(spxTable,0,3, 15)

var simbol1 = "spx"
var simbol2 = "spy"

var bool error = true 

if barstate.isfirst
    // script will not work for timeframes < 120min and will display an error message in top right corner in that case 
    if timeframe.isintraday and timeframe.in_seconds(timeframe.period) <= 120*60
        table.cell_set_text(spxTable,0,0, simbol1)
        table.cell_set_text(spxTable,0,2, simbol2)
        error := false
    else
        table.cell_set_text(spxTable,0,0, "Timeframe needs to be <= 120 min")

    if syminfo.ticker != "ES1!" 
        error := true
        table.cell_set_text(spxTable,0,0, "Works only with ES1! ticker")
    
var lbl = label.new(na, na, na, style = label.style_label_left)
var lineDay = line.new(na, na, na, na, color = lineColor, style = lineStyle, width = 2)
var lineWeek = line.new(na, na, na, na, color = lineColor2, style = lineStyle, width = 2)
var float spxAdjusted = 0
var float spyAdjusted = 0

var float prevDayClose = 0.0
var float prevWeekClose = 0.0

var int bar_time_prev_day_close = 0
var int bar_time_prev_week_close = 0

var string sessionInput = "0830-1500" //input.session("0830-1500", "Trading hours")

// InSession() returns 'true' when the current bar happens inside
// the specified session, and 'false' when the bar isn't inside
// that time period (or when the chart's time frame is 1 day or higher).
InSession(sessionTimes) =>
    not na(time(timeframe.period, sessionTimes))

inSession = InSession(sessionInput)

spx = inSession ? request.security(simbol1, '1D',close[1]) : request.security(simbol1, '1D',close)
spy = inSession ? request.security(simbol2, '1D',close[1]) : request.security(simbol2, '1D',close)

//delta percentage between v1 and v2
delta(float v1, float v2) => 
    (((v2 / v1)-1) * 100.0)

if (ta.change(inSession)) and not error
    if inSession == false  
        prevDayClose := close[1] //previous bar close is previous day's closing price, since we just entered after hours        
        bar_time_prev_day_close := bar_index[1]
        if (dayofweek == dayofweek.friday)
            bar_time_prev_week_close := bar_index[1]
            prevWeekClose := close[1]

if (barstate.islast) and not error
    change = delta(prevDayClose, close)
    spxAdjusted := spx * (1.0 + change/100) 
    spyAdjusted := spy * (1.0 + change/100)
    backColor = change < 0.0 ? color.red : color.green  
    if showPrevDayLine
        line.set_x1(lineDay, bar_time_prev_day_close )
        line.set_x2(lineDay, bar_index)
        line.set_y1(lineDay, prevDayClose) 
        line.set_y2(lineDay, prevDayClose)
    if showPrevWeekCloseLine
        line.set_x1(lineWeek, bar_time_prev_week_close)
        line.set_x2(lineWeek, bar_index)
        line.set_y1(lineWeek, prevWeekClose)
        line.set_y2(lineWeek, prevWeekClose)
    if showDailyChange
        label.set_text(lbl, str.tostring(change, "0.00") + "% ")
        table.cell_set_text(spxTable,0,1, str.tostring(spxAdjusted, "0.0"))
        table.cell_set_text(spxTable,0,3, str.tostring(spyAdjusted, "0.0"))
        label.set_color(lbl, backColor)
        label.set_x(lbl, bar_index+1)
        label.set_y(lbl, close)