Gherkinit Futures Cycle
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © TheWinterDev

//@version=5
indicator(title="Gherkinit Futures Cycle", shorttitle="GFC", overlay=true)

//--Constants
unix_day = 86400000
cycle_length = 34 + 34 + 15 + 8 // Equals: 91 Calendar Days

main_opacity = 50
extra_opacity = 85

visibility_group = "Enable Draw"
color_group = "Date Colors"
extended_cycle_group = "Extended Cycle Data"
extended_cycle_custom_group = "Extended Cycle Customization"

doExposure = input(true, "ETF Exposure Dates", group=visibility_group)
doRoll = input(true, "CME Roll Dates", group=visibility_group)
doExpiration = input(true, "CME Expiration Dates", group=visibility_group)
doTPlus = input(true, "T+ From Fail Dates", group=visibility_group)

//------------------------- Drawing the past and present -------------------------
//-- Functions
getDateInCycle(time_data) =>
    unix_day_offset = time_data - time_tradingday
    days_elapsed = unix_day_offset / unix_day
    is_cycle_date = (days_elapsed % cycle_length) == 0

    is_cycle_date ? (time >= time_tradingday) and (time <= time_tradingday + unix_day) : na

getColoredData(time_data, range_color) =>
    getDateInCycle(time_data) ? range_color : color.new(na, 100)

//-- Exposure
exposure_color = doExposure ? input(color.new(color.yellow, main_opacity), "Exposure", group=color_group) : color.new(na, 100)

exposure_date = timestamp("UTC+11", 2020, 11, 24, 0, 0, 0) // Date of a known exposure date
bgcolor(getColoredData(exposure_date, exposure_color))

//-- Roll
roll_color = doRoll ? input(color.new(color.orange, main_opacity), "Roll", group=color_group) : color.new(na, 100)

roll_date = timestamp("UTC+11", 2020, 12, 10, 0, 0, 0) // Date of a known roll date
bgcolor(getColoredData(roll_date, roll_color))

//-- Expiration
expiration_color = doExpiration ? input(color.new(color.red, main_opacity), "Expiration", group=color_group) : color.new(na, 100)

expiration_date = timestamp("UTC+11", 2020, 12, 18, 0, 0, 0) // Date of a known expiration date
bgcolor(getColoredData(expiration_date, expiration_color))

//-- T+ From Fail
tplus_color = doTPlus ? input(color.new(color.green, extra_opacity), "T+ From Fail", group=color_group) : color.new(na, 100)

tplus1_date = timestamp("UTC+11", 2020, 12, 28, 0, 0, 0) // Date of a known T+ date
bgcolor(getColoredData(tplus1_date, tplus_color))

tplus2_date = timestamp("UTC+11", 2021, 1, 13, 0, 0, 0) // Date of a known T+ date
bgcolor(getColoredData(tplus2_date, tplus_color))
tplus3_date = timestamp("UTC+11", 2021, 1, 21, 0, 0, 0) // Date of a known T+ date
bgcolor(getColoredData(tplus3_date, tplus_color))
tplus4_date = timestamp("UTC+11", 2021, 1, 29, 0, 0, 0) // Date of a known T+ date
bgcolor(getColoredData(tplus4_date, tplus_color))

//-------------------- Drawing The Future ;) -------------------------
//-- Variables
last_cycle_id = math.floor(((time_tradingday - exposure_date) / unix_day) / cycle_length)
extended_cycle_id = input(1, "Future Cycle ID", group=extended_cycle_group)

isInfinite = input(true, "Is Line Infinite", group=extended_cycle_custom_group)

line_width = input(3, "Line width", group=extended_cycle_custom_group)
line_mult = input(1, "Line height multiplier", group=extended_cycle_custom_group)
line_height = input(1000, "Line height ($)", group=extended_cycle_custom_group) * line_mult

//-- Functions
get_extended_date(base_date, extended_id) =>
    base_date + (unix_day * cycle_length) * (last_cycle_id + extended_id)
    
draw_vertical_line(line_date, line_color) =>
    var line ln = isInfinite ? line.new(line_date, low, line_date, high, xloc=xloc.bar_time, color=line_color, width=line_width, extend=extend.both)
                             : line.new(line_date, low-line_height, line_date, high+line_height, xloc=xloc.bar_time, color=line_color, width=line_width)
    
    line.set_x1(ln, line_date)
    line.set_x2(ln, line_date)

//-- Drawing
if extended_cycle_id != 0
    if barstate.islast
        draw_vertical_line(get_extended_date(exposure_date, extended_cycle_id), exposure_color)
        draw_vertical_line(get_extended_date(roll_date, extended_cycle_id), roll_color)
        draw_vertical_line(get_extended_date(expiration_date, extended_cycle_id), expiration_color)
        
        draw_vertical_line(get_extended_date(tplus1_date, extended_cycle_id), tplus_color)
        draw_vertical_line(get_extended_date(tplus2_date, extended_cycle_id), tplus_color)
        draw_vertical_line(get_extended_date(tplus3_date, extended_cycle_id), tplus_color)


// -----------------
// - Pickle 4 Life -
// -----------------
