Bond Yeild Curve
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © morzor61


// Reference : 
// # ⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑
// # Purpose : 
// # 
// # History : 
// #        Rev 3 : 128 
// #        Rev 4 : from 128 》 
// #                - Add 2-10 Spread.
// #                - Change to User Defined Type. 
// # 
// # Reference : 
// #        - 10-2 Year Treasury Yield Spread by zdmre : https://www.tradingview.com/v/JN82lVEA/
// #        - Historical US Bond Yield Curve, BarefootJoey : https://www.tradingview.com/script/faurpTxW-Historical-US-Bond-Yield-Curve/
// # 
// # ⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑⁑
//@version=5
indicator("Treasury Yield")

//#region User Defined Type 
type Yields
    float TTM03MY  
    float TTM01Y 
    float TTM02Y 
    float TTM03Y 
    float TTM05Y 
    float TTM07Y 
    float TTM10Y 
    float TTM20Y 


//----------------------------------------------------------------------------------------
//#region Constant ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
// Country 
// SEA 
THAILAND = 'Thailand'   ,VIETNAM = 'Vietnam'        ,INDONESIA = 'Indonesia' ,MALAYSIA = 'Malaysia'  ,  PHILIPPINES = 'Philippines'   ,SINGAPORE = 'Singapore'  

// ASIA
JAPAN = 'Japan'     ,CHINA = 'China'        ,SOUTH_KOREA = 'South Korea'  ,INDIA = 'India', TAIWAN = 'Taiwan' 

// EAST ASIA
// AMERICA
USA    =   'US'     ,CANADA    =   'Canada'
// SOUTH AMERIA 
BRAZIL   =   'Brazil'
// EU
UK  =   'UK'         ,GERMANY  =   'Germany'    ,FRANCE  =   'France'      ,RUSSIA  =   'Russia'     , AUSTRALIA  =   'Australia'   ,EU  =   'EU'         

// TTM [TTM_03MY, TTM_06MY, TTM_01Y, TTM_02Y, TTM_03Y, TTM_05Y, TTM_07Y, TTM_10Y, TTM_15Y, TTM_20Y]
TTM_03MY    = '03MY' , TTM_01Y     = '01Y'     ,TTM_02Y    = '02Y',    TTM_03Y  = '03Y',      TTM_05Y     = '05Y'     ,TTM_07Y    = '07Y',    TTM_10Y  = '10Y',   TTM_20Y = '20Y'        

//#endregion
//--------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------
//#region INPUT 
MAIN_GROUP  = "Base"
MAIN_GROUP_PERIOD = "Time"
COMPARE_GROUP  = 'COMPARE BY COUNTRY'

ALL_TTM = "Line Chart for All TTM" , COMPARE_BY_PERIOD = "Compare by time", 
COMPARE_BY_COUNTRY  = "Compare by country", SPREAD_02_10 = "2-10 Spread" 

data_type = input.string(title = "Data Type", defval = COMPARE_BY_PERIOD, options = [
      COMPARE_BY_PERIOD, COMPARE_BY_COUNTRY, ALL_TTM, SPREAD_02_10])

country01     =   input.string(USA, 'Base Country',   options = [
     '--- AMERICA ---',      USA, CANADA, 
     '--- EUROPE ----',      UK, GERMANY, FRANCE, RUSSIA, AUSTRALIA, EU, 
     '--- ASIA ------',      JAPAN, CHINA, SOUTH_KOREA, INDIA, TAIWAN, 
     '--- SEA -------',      THAILAND, VIETNAM, INDONESIA, MALAYSIA, PHILIPPINES, SINGAPORE], 
     inline="Base Country", group = MAIN_GROUP)

compare_period_01 = input.int(title = "Compare Period", defval = 30, inline = MAIN_GROUP_PERIOD, group = MAIN_GROUP)
compare_period_02 = input.int(title = "", defval = 252, inline = MAIN_GROUP_PERIOD, group = MAIN_GROUP)

country02     =   input.string(CHINA, 'Compare Country',   options = [
     '--- AMERICA ---',      USA, CANADA, 
     '--- EUROPE ----',      UK, GERMANY, FRANCE, RUSSIA, AUSTRALIA, EU, 
     '--- ASIA ------',      JAPAN, CHINA, SOUTH_KOREA, INDIA, TAIWAN, 
     '--- SEA -------',      THAILAND, VIETNAM, INDONESIA, MALAYSIA, PHILIPPINES, SINGAPORE], 
     inline=COMPARE_GROUP, group = COMPARE_GROUP)
country03     =   input.string(UK, '',   options = [
     '--- AMERICA ---',      USA, CANADA, 
     '--- EUROPE ----',      UK, GERMANY, FRANCE, RUSSIA, AUSTRALIA, EU, 
     '--- ASIA ------',      JAPAN, CHINA, SOUTH_KOREA, INDIA, TAIWAN, 
     '--- SEA -------',      THAILAND, VIETNAM, INDONESIA, MALAYSIA, PHILIPPINES, SINGAPORE], 
     inline=COMPARE_GROUP, group = COMPARE_GROUP)

locFactor = input.int(defval = 40, title = "Location Factor", minval = 1, step = 5)
//#endregion 

//#region FUNCTION ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――

get_bond_ticker(_country, _ttm)=> 
    // Function : Get ticker of treasury bond from each country from TVC. 
    // param : _country ==> Country 
    // param : _per ==> Time to maturity of treasury bond
//     country_code = ''
    country_code = switch _country
    // SEA
        THAILAND      => 'TH'
        VIETNAM       => 'VN'    
        INDONESIA     => 'ID'   
        MALAYSIA      => 'MY'
        'Philippines'   => 'PH'
        'Singapore'     => 'SG'
    // Asia
        JAPAN         => 'JP'
        CHINA         => 'CN'
        'S Korea'       => 'KR'
        INDIA         => 'IN'
        'Taiwan'        => 'TW'
    // East Asia
    // America
        USA            => 'US'
        'Canada'        => 'CA'
    // South America
        'Brazil'        =>  'BR'
        // 'Argentina'     => 
    // EU
        UK            => 'GB'
        GERMANY       => 'DE'
        'France'        => 'FR'
        'Russia'        => 'RU'
        'Australia'     => 'AU'
        'EU'            => 'EU'
    // Not show
        => ''

    // Bond Ticker based on selected country and TTM
    bond_ticker  = 'TVC:' + country_code + _ttm
    bond_ticker

//
get_ttm(country, ttm)=> 
    tickerSymbol = get_bond_ticker(country, ttm)
    yield = nz(request.security(tickerSymbol, timeframe.period, close, ignore_invalid_symbol = true))

get_all_ttm(country)=> 
    ttm_03my = get_ttm(country, TTM_03MY)
    ttm_01y  = get_ttm(country, TTM_01Y )
    ttm_02y  = get_ttm(country, TTM_02Y )
    ttm_03y  = get_ttm(country, TTM_03Y )
    ttm_05y  = get_ttm(country, TTM_05Y )
    ttm_07y  = get_ttm(country, TTM_07Y )
    ttm_10y  = get_ttm(country, TTM_10Y )
    ttm_20y  = get_ttm(country, TTM_20Y )
    data =  Yields.new(ttm_03my, ttm_01y, ttm_02y, ttm_03y, ttm_05y, ttm_07y, ttm_10y, ttm_20y)

line_position(x)=> 
    int number_of_ttm = 8
    factor = (number_of_ttm-x) * locFactor
    x_position = bar_index - (x == 9 ?  factor + 7 : factor )

draw_label(x, y, txt, label_order)=> 
    var label ttm_label = na
    lable_style = x==9 ? label.style_label_left: label.style_label_up
    label.delete(ttm_label)
    txt_color = label_order == 1 ? color.rgb(255, 136, 0) : label_order == 2 ? color.new(#5eff00, 0) :color.new(#3bf2ff, 0) 
    
    ttm_label := label.new(
         line_position(x), y, text= txt, 
         color=color.new(#35a4ff, 100), 
         textcolor = txt_color,
         style=lable_style)

// @function Draw line of yield.
// ___
// #### Usage 
// ```
// draw_line(x1, y1, x2, y2, line_order)
// ```
// ___
// @param y1    start location value
// @param x1    start location
// @returns     `Line plot of 2 locatoin`
draw_line(x1, y1, x2, y2, line_order)=> 
    
    var color   line_color = na 
    var string  line_style = na
    var int     line_width = na
    
    if line_order == 1 
        line_color :=  color.rgb(255, 136, 0)
        line_style := line.style_solid
        line_width := 3
    else if line_order == 2 
        line_color := color.new(#5eff00, 0)
        line_style := line.style_dotted
        line_width := 2
    else
        line_style := line.style_dotted
        line_color := color.new(#3bf2ff, 0)
        line_width := 1

    var line value_line = na
    line.delete(value_line)
    value_line := line.new(
         line_position(x1), y1, line_position(x2), y2, width=line_width, color = line_color)
    value_line

//#endregion

//#region CALCULATION ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――v

c1Data = get_all_ttm(country01)
c2Data = get_all_ttm(country02)
c3Data = get_all_ttm(country03)

if data_type == COMPARE_BY_COUNTRY
    draw_line(1, c1Data.TTM03MY,     2, c1Data.TTM01Y , 2)
    draw_line(2, c1Data.TTM01Y,      3, c1Data.TTM02Y , 2)
    draw_line(3, c1Data.TTM02Y,      4, c1Data.TTM03Y , 2)
    draw_line(4, c1Data.TTM03Y,      5, c1Data.TTM05Y , 2)
    draw_line(5, c1Data.TTM05Y,      6, c1Data.TTM07Y , 2)
    draw_line(6, c1Data.TTM07Y,      7, c1Data.TTM10Y , 2)
    draw_line(7, c1Data.TTM10Y,      8, c1Data.TTM20Y , 2)

    draw_label(9, c1Data.TTM20Y, str.tostring(country01), 1)

    draw_line(1, c2Data.TTM03MY,     2, c2Data.TTM01Y, 1)
    draw_line(2, c2Data.TTM01Y,      3, c2Data.TTM02Y, 1)
    draw_line(3, c2Data.TTM02Y,      4, c2Data.TTM03Y, 1)
    draw_line(4, c2Data.TTM03Y,      5, c2Data.TTM05Y, 1)
    draw_line(5, c2Data.TTM05Y,      6, c2Data.TTM07Y, 1)
    draw_line(6, c2Data.TTM07Y,      7, c2Data.TTM10Y, 1)
    draw_line(7, c2Data.TTM10Y,      8, c2Data.TTM20Y, 1)
    draw_label(9, c2Data.TTM20Y, str.tostring(country02), 2)

    draw_line(1, c3Data.TTM03MY,     2, c3Data.TTM01Y , 3)
    draw_line(2, c3Data.TTM01Y,      3, c3Data.TTM02Y , 3)
    draw_line(3, c3Data.TTM02Y,      4, c3Data.TTM03Y , 3)
    draw_line(4, c3Data.TTM03Y,      5, c3Data.TTM05Y , 3)
    draw_line(5, c3Data.TTM05Y,      6, c3Data.TTM07Y , 3)
    draw_line(6, c3Data.TTM07Y,      7, c3Data.TTM10Y , 3)
    draw_line(7, c3Data.TTM10Y,      8, c3Data.TTM20Y , 3)
    draw_label(9, c3Data.TTM20Y, str.tostring(country03), 3)

    draw_label(1, c1Data.TTM03MY , '3M' , 1)
    draw_label(2, c1Data.TTM01Y  , '1Y' , 1)
    draw_label(3, c1Data.TTM02Y  , '2Y' , 1)
    draw_label(4, c1Data.TTM03Y  , '3Y' , 1)
    draw_label(5, c1Data.TTM05Y  , '5Y' , 1)
    draw_label(6, c1Data.TTM07Y  , '7Y' , 1)
    draw_label(7, c1Data.TTM10Y  , '10Y', 1)
    draw_label(8, c1Data.TTM20Y  , '20Y', 1)
    draw_label(9, c1Data.TTM20Y,  data_type == COMPARE_BY_PERIOD ? 'Current' : country01, 1)

if data_type == COMPARE_BY_PERIOD
    draw_line(1,  c1Data.TTM03MY                    ,      2, c1Data.TTM01Y,  1)
    draw_line(2,  c1Data.TTM01Y                     ,      3, c1Data.TTM02Y,  1)
    draw_line(3,  c1Data.TTM02Y                     ,      4, c1Data.TTM03Y,  1)
    draw_line(4,  c1Data.TTM03Y                     ,      5, c1Data.TTM05Y,  1)
    draw_line(5,  c1Data.TTM05Y                     ,      6, c1Data.TTM07Y,  1)
    draw_line(6,  c1Data.TTM07Y                     ,      7, c1Data.TTM10Y,  1)
    draw_line(7,  c1Data.TTM10Y                     ,      8, c1Data.TTM20Y,  1)

    draw_line(1,  c1Data.TTM03MY[compare_period_01],     2, c1Data.TTM01Y[compare_period_01],  2)
    draw_line(2,  c1Data.TTM01Y[compare_period_01],      3, c1Data.TTM02Y[compare_period_01],  2)
    draw_line(3,  c1Data.TTM02Y[compare_period_01],      4, c1Data.TTM03Y[compare_period_01],  2)
    draw_line(4,  c1Data.TTM03Y[compare_period_01],      5, c1Data.TTM05Y[compare_period_01],  2)
    draw_line(5,  c1Data.TTM05Y[compare_period_01],      6, c1Data.TTM07Y[compare_period_01],  2)
    draw_line(6,  c1Data.TTM07Y[compare_period_01],      7, c1Data.TTM10Y[compare_period_01],  2)
    draw_line(7,  c1Data.TTM10Y[compare_period_01],      8, c1Data.TTM20Y[compare_period_01],  2)

    draw_line(1,  c1Data.TTM03MY[compare_period_02],     2, c1Data.TTM01Y[compare_period_02],  3)
    draw_line(2,  c1Data.TTM01Y[compare_period_02],      3, c1Data.TTM02Y[compare_period_02],  3)
    draw_line(3,  c1Data.TTM02Y[compare_period_02],      4, c1Data.TTM03Y[compare_period_02],  3)
    draw_line(4,  c1Data.TTM03Y[compare_period_02],      5, c1Data.TTM05Y[compare_period_02],  3)
    draw_line(5,  c1Data.TTM05Y[compare_period_02],      6, c1Data.TTM07Y[compare_period_02],  3)
    draw_line(6,  c1Data.TTM07Y[compare_period_02],      7, c1Data.TTM10Y[compare_period_02],  3)
    draw_line(7,  c1Data.TTM10Y[compare_period_02],      8, c1Data.TTM20Y[compare_period_02],  3)

    _suffix = timeframe.period == "D" ? " days ago" : timeframe.period == "W" ? " weeks ago" : timeframe.period == "M" ? " month ago" : na
    draw_label(9, c1Data.TTM20Y,  'Current', 1)
    draw_label(9, c1Data.TTM20Y[compare_period_01], str.tostring(compare_period_01)+_suffix, 2)
    draw_label(9, c1Data.TTM20Y[compare_period_02], str.tostring(compare_period_02)+_suffix, 3)

    draw_label(1, c1Data.TTM03MY , '3M' , 1)
    draw_label(2, c1Data.TTM01Y  , '1Y' , 1)
    draw_label(3, c1Data.TTM02Y  , '2Y' , 1)
    draw_label(4, c1Data.TTM03Y  , '3Y' , 1)
    draw_label(5, c1Data.TTM05Y  , '5Y' , 1)
    draw_label(6, c1Data.TTM07Y  , '7Y' , 1)
    draw_label(7, c1Data.TTM10Y  , '10Y', 1)
    draw_label(8, c1Data.TTM20Y  , '20Y', 1)
//
float spread = na 
if data_type == SPREAD_02_10
    spread := c1Data.TTM10Y - c1Data.TTM02Y

bearish = ta.cross(spread, 0) == 1 and spread < 0
bullish = ta.cross(spread, 2.6) == 1 and spread > 2.6

if bearish
    label1 = label.new(bar_index, 0 , text='|\n'+ str.format("{0,date, y\nMMM-d}", time), style=label.style_label_up, color=color.new(color.red,100))
    label.set_size(label1, size.small)
    label.set_textcolor(label1, color.red)
if bullish
    label2 = label.new(bar_index, 2.6 , text=str.format("{0,date, y\nMMM-d\n}", time)+'|', style=label.style_label_down, color=color.new(color.green,100))
    label.set_size(label2, size.small)
    label.set_textcolor(label2, color.green)

plot(data_type == SPREAD_02_10 ? spread : na, title = "2-10 Spread", color = color.orange)

upperBand   = hline(data_type == SPREAD_02_10 ? 2.6 : na , title = 'Upper Band')
centerBand  = hline(data_type == SPREAD_02_10 ? 1.3 : na , title = 'Center Band')
lowerBand   = hline(data_type == SPREAD_02_10 ? 0   : na , title = 'Lower Band')

fill(upperBand, lowerBand, color=color.rgb(126, 87, 194, 90), title="Background")

// data_type == All ttm. 
plot(series = data_type == ALL_TTM ? c1Data.TTM03MY  : na,     title = "3M", color = color.rgb(75, 75, 75), linewidth = 1)
plot(series = data_type == ALL_TTM ? c1Data.TTM01Y  : na,     title = "1Y", color = color.rgb(75, 75, 75), linewidth = 1)
plot(series = data_type == ALL_TTM ? c1Data.TTM02Y  : na,     title = "2Y", color = color.rgb(50, 248, 0), linewidth = 2)
plot(series = data_type == ALL_TTM ? c1Data.TTM03Y  : na,     title = "3Y", color = color.rgb(75, 75, 75), linewidth = 1)
plot(series = data_type == ALL_TTM ? c1Data.TTM05Y  : na,     title = "5Y", color = color.rgb(255, 6, 201), linewidth = 2)
plot(series = data_type == ALL_TTM ? c1Data.TTM07Y  : na,     title = "7Y", color = color.rgb(75, 75, 75), linewidth = 1)
plot(series = data_type == ALL_TTM ? c1Data.TTM10Y  : na,     title = "10Y", color = color.rgb(253, 0, 0), linewidth = 2)
plot(series = data_type == ALL_TTM ? c1Data.TTM20Y  : na,     title = "20Y", color = color.rgb(75, 75, 75), linewidth = 1)
//


