Meats: Backwardation/Cantango
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//@version=5

// MEATS: Live Cattle; Feeder Cattle; Lean Hogs (LE, GF, HE)
// Quickly visualize carrying charge market vs backwardized market by comparing the price of the next 2 years of futures contracts.
// Carrying charge (contract prices increasing into the future) = normal, representing the costs of carrying/storage of a commodity. When this is flipped to Backwardation (contract prices decreasing into the future): it's a bullish sign: Buyers want this commodity, and they want it NOW.

// Note: indicator does NOT map to time axis in the same way as price; it simply plots the progression of contract months out into the future; left to right; so timeframe doesn't matter for this plot
// There's likely some more efficient way to write this; e.g. when plotting for Live Cattle (LE); 8 of the security requests are redundant; but they are still made; and can make this slower to load
// TO UPDATE: in REQUEST CONTRACTS section, delete old contracts (top) and add new ones (bottom). Then in PLOTTING section, Delete old [expired] contract labels (bottom); add new [distant future] contract labels (top); adjust the X in 'bar_index-(X+_historical)' numbers accordingly

// This is one of three similar indicators: Meats | Metals | Grains
// -If you want to build from this; to work on other commodities; be aware that Tradingview limits the number of contract calls to 40 (hence the 3 seperate indicators)

// Tips:
// -Right click and reset chart if you can't see the plot; or if you have trouble with the scaling.
// -Right click and add to new scale if you prefer this not to overlay directly on price. Or move to new pane below.

// --Added historical input: input days back in time; to see the historical shape of the Futures curve via selecting 'days back' snapshot
// updated contracts 30th Jan 2023
// © twingall

indicator("Meats: Backwardation/Cantango", overlay = true, scale = scale.right)
_historical = input(0, "time travel back; days")
_adr = ta.atr(5)
colorNone= color.new(color.white, 100)

//Function to test if contract is expired
int oneWeek = 5*24*60*60*1000 // 5 or more days since last reported closing price => expired
isExp (int _timeClose)=>
    expired = _timeClose <= (last_bar_time-oneWeek) 

///REQUEST CONTRACTS---
//shared contracts and/or All Live Cattle Contracts.
[dec22, dec22t]= request.security(syminfo.root + "Z2022", "D", [close[_historical], time_close], ignore_invalid_symbol=true)
[feb23, feb23t]= request.security(syminfo.root + "G2023", "D",  [close[_historical], time_close], ignore_invalid_symbol=true)
[apr23, apr23t]= request.security(syminfo.root + "J2023", "D", [close[_historical], time_close], ignore_invalid_symbol=true)
[jun23,jun23t]= request.security(syminfo.root + "M2023", "D", [close[_historical],time_close], ignore_invalid_symbol=true)
[aug23,aug23t]= request.security(syminfo.root + "Q2023", "D", [close[_historical],time_close], ignore_invalid_symbol=true)
[oct23,oct23t]=request.security(syminfo.root + "V2023", "D", [close[_historical],time_close], ignore_invalid_symbol=true)
[dec23,dec23t]= request.security(syminfo.root + "Z2023", "D", [close[_historical],time_close], ignore_invalid_symbol=true)
[feb24,feb24t]=request.security(syminfo.root + "G2024", "D", [close[_historical],time_close], ignore_invalid_symbol=true)
[apr24,apr24t]=request.security(syminfo.root + "J2024", "D", [close[_historical],time_close], ignore_invalid_symbol=true)
[jun24,jun24t]=request.security(syminfo.root + "M2024", "D", [close[_historical],time_close], ignore_invalid_symbol=true)

//additional contracts for Feeder Cattle
[jan23,jan23t]=request.security(syminfo.root + "F2023", "D", [close[_historical],time_close], ignore_invalid_symbol=true)
[mar23,mar23t]=request.security(syminfo.root + "H2023", "D", [close[_historical],time_close], ignore_invalid_symbol=true)
[may23,may23t]=request.security(syminfo.root + "K2023", "D", [close[_historical],time_close], ignore_invalid_symbol=true)
[sept23,sept23t]=request.security(syminfo.root + "U2023", "D", [close[_historical],time_close], ignore_invalid_symbol=true)
[nov23,nov23t]=request.security(syminfo.root + "X2023", "D", [close[_historical],time_close], ignore_invalid_symbol=true)
[jan24,jan24t]=request.security(syminfo.root + "F2024", "D", [close[_historical],time_close], ignore_invalid_symbol=true)

//additional contracts for Lean Hogs
[jul23,jul23t]=request.security(syminfo.root + "N2023", "D", [close[_historical],time_close], ignore_invalid_symbol=true)
[may24,may24t]=request.security(syminfo.root + "K2024", "D", [close[_historical],time_close], ignore_invalid_symbol=true)

//PLOTTING----
//
//Live Cattle plotting
if barstate.islast and syminfo.root=='LE'
    label.new(bar_index-(_historical), close[_historical]+ 2*_adr, text = 'S\nN\nA\nP\nS\nH\nO\nT', textcolor = color.red, style=label.style_arrowdown, color= color.red, size = size.tiny)

    label.new(bar_index-(2+_historical), isExp(jun24t)?0:jun24, text = 'Jun24', textcolor =isExp(jun24t)?colorNone: color.red, style=isExp(jun24t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(4+_historical), isExp(apr24t)?0:apr24, text = 'Apr24', textcolor =isExp(apr24t)?colorNone: color.red, style=isExp(apr24t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(6+_historical), isExp(feb24t)?0:feb24, text = 'Feb24', textcolor =isExp(feb24t)?colorNone: color.red, style=isExp(feb24t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(8+_historical), isExp(dec23t)?0:dec23, text = 'Dec23', textcolor =isExp(dec23t)?colorNone: color.red, style=isExp(dec23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(10+_historical), isExp(oct23t)?0:oct23, text = 'Oct23', textcolor =isExp(oct23t)?colorNone: color.red, style=isExp(oct23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(12+_historical), isExp(aug23t)?0:aug23, text = 'Aug23', textcolor =isExp(aug23t)?colorNone: color.red, style=isExp(aug23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(14+_historical), isExp(jun23t)?0:jun23, text = 'Jun23', textcolor = isExp(jun23t)?colorNone:color.red, style=isExp(jun23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(16+_historical), isExp(apr23t)?0:apr23, text = 'Apr23', textcolor = isExp(apr23t)?colorNone:color.red, style=isExp(apr23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(18+_historical), isExp(feb23t)?0:feb23, text = 'Feb23', textcolor =isExp(feb23t)?colorNone: color.red, style=isExp(feb23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(20+_historical), isExp(dec22t)?0:dec22, text = 'Dec22', textcolor =isExp(dec22t)?colorNone: color.red, style=isExp(dec22t)?label.style_none:label.style_diamond, size = size.tiny)

//Feeder Cattle plotting
if barstate.islast and  syminfo.root == 'GF'
    label.new(bar_index-(_historical), close[_historical]+ 2*_adr, text = 'S\nN\nA\nP\nS\nH\nO\nT', textcolor = color.red, style=label.style_arrowdown, color= color.red, size = size.tiny)

    label.new(bar_index-(2+_historical), isExp(jan24t)?0:jan24, text = 'Jan24', textcolor = isExp(jan24t)?colorNone:color.red, style=isExp(jan24t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(4+_historical), isExp(nov23t)?0:nov23, text = 'Nov23', textcolor =isExp(nov23t)?colorNone: color.red, style=isExp(nov23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(6+_historical), isExp(oct23t)?0:oct23, text = 'Oct23', textcolor =isExp(oct23t)?colorNone: color.red, style=isExp(oct23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(8+_historical), isExp(sept23t)?0:sept23,text ='Sept23',textcolor =isExp(sept23t)?colorNone: color.red, style=isExp(sept23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(10+_historical), isExp(aug23t)?0:aug23, text = 'Aug23', textcolor =isExp(aug23t)?colorNone: color.red, style=isExp(aug23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(12+_historical), isExp(may23t)?0:may23, text = 'May23', textcolor =isExp(may23t)?colorNone: color.red, style=isExp(may23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(14+_historical), isExp(apr23t)?0:apr23, text = 'Apr23', textcolor =isExp(apr23t)?colorNone: color.red, style= isExp(apr23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(16+_historical), isExp(mar23t)?0:mar23, text = 'Mar23', textcolor = isExp(mar23t)?colorNone:color.red, style=isExp(mar23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(18+_historical), isExp(jan23t)?0:jan23, text = 'Jan23', textcolor = isExp(jan23t)?colorNone:color.red, style=isExp(jan23t)?label.style_none:label.style_diamond, size = size.tiny)

//Lean Hogs plotting    
if barstate.islast and syminfo.root == 'HE'
    label.new(bar_index-(_historical), close[_historical]+ 2*_adr, text = 'S\nN\nA\nP\nS\nH\nO\nT', textcolor = color.red, style=label.style_arrowdown, color= color.red, size = size.tiny)

    label.new(bar_index-(2+_historical), isExp(jun24t)?0:jun24, text = 'Jun24', textcolor =isExp(jun24t)?colorNone: color.red, style=isExp(jun24t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(4+_historical), isExp(may24t)?0:may24, text = 'May24', textcolor =isExp(may24t)?colorNone: color.red, style=isExp(may24t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(6+_historical), isExp(apr24t)?0:apr24, text = 'Apr24', textcolor =isExp(apr24t)?colorNone: color.red, style=isExp(apr24t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(8+_historical), isExp(feb24t)?0:feb24, text = 'Feb24', textcolor =isExp(feb24t)?colorNone: color.red, style=isExp(feb24t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(10+_historical), isExp(dec23t)?0:dec23 , text = 'Dec23', textcolor =isExp(dec23t)?colorNone: color.red, style=isExp(dec23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(12+_historical), isExp(oct23t)?0:oct23, text = 'Oct23', textcolor = isExp(oct23t)?colorNone:color.red, style=isExp(oct23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(14+_historical), isExp(aug23t)?0:aug23, text = 'Aug23', textcolor =isExp(aug23t)?colorNone:color.red, style=isExp(aug23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(16+_historical), isExp(jul23t)?0:jul23, text = 'Jul23', textcolor =isExp(jul23t)?colorNone: color.red, style=isExp(jul23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(18+_historical), isExp(jun23t)?0:jun23, text = 'Jun23', textcolor = isExp(jun23t)?colorNone:color.red, style=isExp(jun23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(20+_historical), isExp(may23t)?0:may23, text = 'May23', textcolor = isExp(may23t)?colorNone:color.red, style=isExp(may23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(22+_historical), isExp(apr23t)?0:apr23, text = 'Apr23', textcolor =isExp(apr23t)?colorNone: color.red, style=isExp(apr23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(24+_historical), isExp(feb23t)?0:feb23, text = 'Feb23', textcolor =isExp(feb23t)?colorNone: color.red, style=isExp(apr23t)?label.style_none:label.style_diamond, size = size.tiny)
    label.new(bar_index-(26+_historical), isExp(dec22t)?0:dec22, text = 'Dec22', textcolor =isExp(dec22t)?colorNone: color.red, style=isExp(dec22t)?label.style_none:label.style_diamond, size = size.tiny)

