Cash Gaps on a Future/CFD-Chart
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © NgUTech
// extended based on the original version by NgUTech
// *****Purpose of the script is to polot the cash-index gaps into the future (or CFD) chart in order to fade gaps of the cash-index
//@version=4
study(title="Mind the Gap GM", shorttitle="Gaps", overlay=true, max_bars_back=5000)

//threshold set to zero to show all gaps
threshold = input(title="Threshold Percentage", type=input.float, defval=0.000, minval=0, maxval=1, step=0.001)
background_color = input(title="Background Color", type=input.color, defval=color.rgb(156, 39, 176, 80))
border_color = input(title="Border Color", type=input.color, defval=color.purple)
border_width = input(title="Border Width", type=input.integer, defval=0, minval=0)
max_box_length = input(title="Maximum Box Length (bars) - reduce this if getting an error about 'left' being too far or whatever", type=input.integer, defval=10000, minval=0)
//the Symbol of the underlying cash index
cashIndex = input(title="Cash-Index Symbol", type=input.string, defval="DAX")
// current spread between the cash-index and the future/cfd
Spread = input(title="Spread Cash-Future", type=input.integer, defval=10)


var gap_top = array.new_float(0)
var gap_bottom = array.new_float(0)
var gap_bar = array.new_int(0)


[CILow,CIHigh]=security(cashIndex,"D",[low, high])
[CIOpen,CIClose]=security(cashIndex,"D",[open, close])

gap_down = CIOpen < CIClose[1]
gap_up = CIOpen > CIClose[1]

if gap_down
    array.push(gap_top, CIClose[1])
    array.push(gap_bottom, CIOpen[0])
    array.push(gap_bar, bar_index - 1)

if gap_up
    array.push(gap_top, CIOpen[0])
    array.push(gap_bottom, CIClose[1])
    array.push(gap_bar, bar_index - 1)

num_removed = 0
size = array.size(gap_top)

if size > 0
    for i = 0 to size - 1
        g_top = array.get(gap_top, i - num_removed)
        g_bottom = array.get(gap_bottom, i - num_removed)
        
        if CIHigh >= g_top and CILow < g_top
            array.set(gap_top, i - num_removed, CILow[0])
            g_top := CILow[0]
        else if CIHigh > g_bottom and CILow <= g_bottom
            array.set(gap_bottom, i - num_removed, CIHigh[0])
            g_bottom := CIHigh[0]
        else if CIHigh < g_top and CILow > g_bottom
            if CIClose[1] < g_bottom
                array.set(gap_bottom, i - num_removed, CIHigh[0])
                g_bottom := CIHigh[0]
            else
                array.set(gap_top, i - num_removed, CILow[0])
                g_top := CILow[0]
        
        if (g_top <= CIHigh and g_bottom >= CILow) or ((g_top - g_bottom)/g_bottom < threshold) or (((CILow[1] < g_bottom and CIHigh > g_top) or (CIHigh[1] > g_top and CILow < g_bottom)) and not ((gap_up or gap_down) and i == size - 1))
            array.remove(gap_top, i - num_removed)
            array.remove(gap_bottom, i - num_removed)
            array.remove(gap_bar, i - num_removed)
            num_removed += 1

if barstate.islast
    if array.size(gap_top) > 0
        for i = 0 to array.size(gap_top) - 1
            if bar_index - array.get(gap_bar, i) < max_box_length
                box.new(left=array.get(gap_bar, i), top=array.get(gap_top, i) - Spread, right=bar_index, bottom=array.get(gap_bottom, i) - Spread , border_color=border_color, border_width=border_width, extend=extend.right, xloc=xloc.bar_index, bgcolor=background_color)//border_style, extend, xloc
