CBDE Oscillator
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © kstrat2001

//@version=5
// Central Bank Dark Energy Oscillator
indicator(title = "CBDE Oscillator", shorttitle = "CBDEO", overlay = false)

oscillator_gradient_color(signal, high_color, low_color) =>
    signal_max = ta.max(signal)
    signal_min = ta.min(signal)
    bull_color = color.from_gradient(signal, 0, signal_max, color.new(high_color, 60), color.new(high_color, 0))
    bear_color = color.from_gradient(signal, signal_min, 0, color.new(low_color,   0), color.new(low_color, 60))
    osc_color  = signal < 0 ? bear_color : bull_color

to_billions(value) =>
    billions = value/1000000000

liquidity_sma_length  = input.int(12, "SMA length", 1, 1000, 1, tooltip = "The moving average duration used to determine the divergence in liquidity changes")

// CB Assets
include_cbs_group = "Assets To Include"
include_us = input.bool(true, "US Assets", group = include_cbs_group)
include_jpy = input.bool(true, "JPY Assets", group = include_cbs_group)
include_cny = input.bool(true, "CNY Assets", group = include_cbs_group)
include_uk = input.bool(true, "UK Assets", group = include_cbs_group)
include_snb = input.bool(true, "SNB Assets", group = include_cbs_group)
include_ecb = input.bool(true, "ECB Assets", group = include_cbs_group)
include_krc = input.bool(true, "KRC Assets", group = include_cbs_group)
include_cad = input.bool(true, "CAD Assets", group = include_cbs_group)

fed_bal_sheet_group_name = "Include Fed Balance Sheet Items"
include_wshoicl = input.bool(true, "Inflation Compensation (WSHOICL)", "Include Fed 'Inflation Compensation' (WSHOICL) from assets portion of balance sheet", group = fed_bal_sheet_group_name)
include_wupsho  = input.bool(true, "Unamortized Premiums (WUPSHO)", "Include Fed 'Unamortized Premiums' (WUPSHO) from assets portion of balance sheet", group = fed_bal_sheet_group_name)
include_wlcfll  = input.bool(true, "Loans (WLCFLL)", "Include Fed 'Loans' (WLCFLL) from assets portion of balance sheet", group = fed_bal_sheet_group_name)
include_wlad    = input.bool(true, "Other/Remittances (WLAD)", "Include Fed remittances (WLAD) from liabilities portion of balance sheet", group = fed_bal_sheet_group_name)

tga_override    = input.bool(false, "TGA Balance Override (Billions)", "Overrides the current balance of the Treasury General Accout.  This allows use of the daily balance data rather than waiting for the weekly data to update.", inline = "tga_override", group = fed_bal_sheet_group_name)
tga_override_value = input.float(0, "", 0, 10000000000, 1, inline = "tga_override", group = fed_bal_sheet_group_name)

// FOREIGN CENTRAL BANK ASSETS
line_japan       = request.security("FRED:JPNASSETS * FX_IDC:JPYUSD", "D", close, currency = currency.USD)
line_china       = request.security("CNCBBS          * FX_IDC:CNYUSD", "D", close, currency = currency.USD)
line_uk          = request.security("GBCBBS         * FX:GBPUSD",     "D", close, currency = currency.USD)
line_ecb         = request.security("ECBASSETSW     * FX:EURUSD",     "D", close, currency = currency.USD)
line_snb         = request.security("CHCBBS",                         "D", close, currency = currency.USD)
line_krc         = request.security("ECONOMICS:KRCBBS*FX_IDC:KRWUSD", "D", close, currency = currency.USD)
line_cad         = request.security("CACBBS         * CADUSD",        "D", close, currency = currency.USD)

line_fed_walcl   = request.security("FRED:WALCL",                     "D", close, currency = currency.USD)
line_fed_tga     = request.security("WDTGAL",                         "D", close, currency = currency.USD)
line_rrp         = request.security("RRPONTSYD",                      "D", close, currency = currency.USD)

// Optional factors on Fed balance sheet
line_fed_wshoicl   = request.security("WSHOICL",                        "D", close, currency = currency.USD)
line_fed_wupsho    = request.security("WUPSHO",                         "D", close, currency = currency.USD)
line_fed_wlcfll    = request.security("WLCFLL",                         "D", close, currency = currency.USD)
line_fed_wlad      = request.security("WLAD",                           "D", close, currency = currency.USD)

// conditionally determine which CB assets are used in the total liquidity pool based on user settings
jpy_final = (include_jpy ? line_japan : 0)
cny_final = (include_cny ? line_china : 0)
gbp_final = (include_uk  ? line_uk : 0)
snb_final = (include_snb ? line_snb : 0)
ecb_final = (include_ecb ? line_ecb : 0)
krc_final = (include_krc ? line_krc : 0)
cad_final = (include_cad ? line_cad : 0)

// Non-US central bank totals
non_us_total = jpy_final + cny_final + gbp_final + snb_final + ecb_final + krc_final + cad_final

// FED subtractions
wshoicl_final = (include_wshoicl ? 0 : line_fed_wshoicl)
wupsho_final  = (include_wupsho ? 0 : line_fed_wupsho)
wlcfll_final  = (include_wlcfll ? 0 : line_fed_wlcfll)
assets_subtractions = wlcfll_final + wupsho_final + wshoicl_final
assets_total = line_fed_walcl - assets_subtractions

// FED liabilities
tga_final = barstate.islast and tga_override ? tga_override_value * 1000000000 : line_fed_tga
wlad_final = (include_wlad ? line_fed_wlad : 0)
liabilities_total = tga_final + line_rrp + wlad_final
fed_total = assets_total - liabilities_total

// Total liquidity using a scale factor to get the value in billions
total_liquidity = to_billions((include_us ? fed_total : 0) + non_us_total)

// Delta Plot
liquidity_delta = total_liquidity - total_liquidity[1]
plot(liquidity_delta, color = oscillator_gradient_color(liquidity_delta, color.lime, color.red), linewidth = 4, title="Liquidity 1-Bar Delta", style = plot.style_columns)

// TGA vs RRP plot
tga_change_billions = to_billions(tga_final - tga_final[1])
rrp_change_billions = to_billions(line_rrp - line_rrp[1])
tga_rrp_delta =  tga_change_billions + rrp_change_billions
plot(tga_rrp_delta, color = oscillator_gradient_color(tga_rrp_delta, color.aqua, color.orange), linewidth = 4, title="TGA+RRP total 1-Bar Delta", style = plot.style_columns, display = display.none)

// SMA Divergence Plot
liquidity_ma = ta.sma(total_liquidity, liquidity_sma_length)

divergence_signal = (liquidity_ma - total_liquidity)*-1.0
plot(divergence_signal, color = oscillator_gradient_color(divergence_signal, color.aqua, color.yellow), linewidth = 2, title="Liquidity SMA Oscillator", display = display.none)
hline(0)