Forex Trading Sessions
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © EmpiricalFX

//@version=4
study("Forex Sessions",overlay=true)
//## Forex Trading Session
gp1 = "Forex Trading Sessions"
gp3 = "Session Configuration"
gp2 = "Additional Settings"
///Sessions
london = input(title="London Session", type=input.session, defval="0300-1200",group=gp1)
ny = input(title="New York Session", type=input.session, defval="0800-1700",group=gp1)
tokyo = input(title="Tokyo Session", type=input.session, defval="2000-0400",group=gp1)
sydney = input(title="Sydney Session", type=input.session, defval="1700-0200",group=gp1)
//Config
show_bg = input(true,"Show Background Colors",input.bool,group=gp2)
London = input(title="Show London Session", type=input.bool, defval=true,group=gp3)
LondonColor = input(color.new(color.green,95),"London Color",input.color,group=gp3)
NY = input(title="Show New York Session", type=input.bool, defval=true,group=gp3)
NYColor = input(color.new(color.red,95),"New York Color",input.color,group=gp3)
Tokyo = input(title="Show Tokyo Session", type=input.bool, defval=false,group=gp3)
AsiaColor = input(color.new(color.yellow,95),"Tokyo Color", input.color,group=gp3)
Sydney = input(title="Show Sydney Session", type=input.bool, defval=false,group=gp3)
SydneyColor = input(color.new(color.navy,95),"Sydney Color",input.color,group=gp3)
//Additional
auto = input(false,"Automatic Pair Detection",input.bool,group=gp2,tooltip="If succesful, will override manual settings below.\nLondon = CHF, EUR, GBP\nNew York = CAD, USD, XAU\nTokyo = JPY\nSydney = AUD, NZD")


//Find target substring using slices
indexOf2(str, target) =>
    // 0..n-1
    arr = str.split(str, "")
    // n
    len1 = array.size(arr)
    len2 = str.length(target)
    res = len2 > 0 ? -1 : 0
    // both arr, target are not empty
    if len1 >= len2 and len2 > 0
        // can't use array.indexof(arr, target) because there are multiple chars in target string
        for i = 0 to len1 - len2
            // compare each substring of str of target length with target string
            // arr slice from start_pos to end_pos, not including end_pos, start_pos < end_pos otherwise error!
            slice = array.slice(arr, i, i + len2)
            if array.join(slice, "") == target
                res := i
                break

    res
    
//Detection of bar within session
is_session(sess) =>
    not na(time("D", sess))
    
//Create a Vertical Line
vline(BarIndex, Color, LineStyle, LineWidth) => // Verticle Line Function, ≈50-54 lines maximum allowable per indicator
    // return = line.new(BarIndex,   0.0, BarIndex,     100.0, xloc.bar_index, extend.both, Color, LineStyle, LineWidth) // Suitable for study(overlay=false) and RSI, Stochastic, etc...
    // return = line.new(BarIndex,  -1.0, BarIndex,       1.0, xloc.bar_index, extend.both, Color, LineStyle, LineWidth) // Suitable for study(overlay=false) and +/-1.0 oscillators
    return = line.new(BarIndex, low - tr, BarIndex, high + tr, xloc.bar_index, extend.both, color.new(Color,0), LineStyle, LineWidth) // Suitable for study(overlay=true)
    
if(auto)
    pair = syminfo.ticker
    AUD = indexOf2(pair,"AUD")!= -1
    CAD = indexOf2(pair,"CAD")!= -1
    CHF = indexOf2(pair,"CHF")!= -1
    EUR = indexOf2(pair,"EUR")!= -1
    GBP = indexOf2(pair,"GBP")!= -1
    JPY = indexOf2(pair,"JPY")!= -1
    NZD = indexOf2(pair,"NZD")!= -1
    USD = indexOf2(pair,"USD")!= -1
    XAU = indexOf2(pair,"XAU")!= -1
    
    if(AUD or CAD or CHF or EUR or GBP or JPY or USD or XAU)
        London := (GBP or EUR or CHF) and London
        NY := (USD or CAD or XAU) and NY
        Tokyo := (JPY) and Tokyo
        Sydney := (AUD or NZD) and Sydney
    
//London
londonSession = is_session(london)
if(London)
    if(londonSession and not londonSession[1])
        vline(bar_index,LondonColor,line.style_dashed,1)
    if(not londonSession and londonSession[1])
        vline(bar_index,LondonColor,line.style_solid,1)
bgcolor((londonSession and London and show_bg)?LondonColor:na,title="London Session",editable=false)

//New York
nySession = is_session(ny)
if(NY)
    if(nySession and not nySession[1])
        vline(bar_index,NYColor,line.style_dashed,1)
    if(not nySession and nySession[1])
        vline(bar_index,NYColor,line.style_solid,1)
bgcolor((nySession and NY and show_bg)?NYColor:na,title="NY Session",editable=false)

//Tokyo
tokyoSession = is_session(tokyo)
if(Tokyo)
    if( tokyoSession and not tokyoSession[1])
        vline(bar_index,AsiaColor,line.style_dashed,1)
    if(not tokyoSession and tokyoSession[1])
        vline(bar_index,AsiaColor,line.style_solid,1)
bgcolor((tokyoSession and Tokyo and show_bg)?AsiaColor:na,title="Tokyo Session",editable=false)

//Sydney
sydneySession = is_session(sydney)
if(Sydney)
    if(sydneySession and not sydneySession[1])
        vline(bar_index,SydneyColor,line.style_dashed,1)
    if(not sydneySession and sydneySession[1])
        vline(bar_index,SydneyColor,line.style_solid,1)
bgcolor((sydneySession and Sydney and show_bg)?SydneyColor:na,title="Sydney Session",editable=false)