Daily Network Value to Transactions Signal (NVTS)
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © weak_hand

//@version=5
indicator("Daily Network Value to Transactions Signal (NVTS)", "NVTS", false, format.volume)

if timeframe.isintraday
    runtime.error("The timeframe is to low. It has to be at least one day.")

// ----------------------------------------------}
// EXCLUDED CURRENCIES
// ----------------------------------------------{

var CoinMetrics_MARKETCAPFF = array.new<string>()
if bar_index == 0
    CoinMetrics_MARKETCAPFF.push("ALPHA")
    CoinMetrics_MARKETCAPFF.push("BNB")
    CoinMetrics_MARKETCAPFF.push("KNC")
    CoinMetrics_MARKETCAPFF.push("TXZ")

var CoinMetrics_TXVOLUMEUSD = array.new<string>()
if bar_index == 0
    CoinMetrics_TXVOLUMEUSD.push("ANT")
    CoinMetrics_TXVOLUMEUSD.push("BNB")
    CoinMetrics_TXVOLUMEUSD.push("BTC")
    CoinMetrics_TXVOLUMEUSD.push("DOGE")
    CoinMetrics_TXVOLUMEUSD.push("DOT")
    CoinMetrics_TXVOLUMEUSD.push("LTC")
    CoinMetrics_TXVOLUMEUSD.push("WTC")
    CoinMetrics_TXVOLUMEUSD.push("XTZ")

var GlassNode_TOTALVOLUMEUSD = array.new<string>()
if bar_index == 0
    GlassNode_TOTALVOLUMEUSD.push("ELF")
    GlassNode_TOTALVOLUMEUSD.push("ETH")
    GlassNode_TOTALVOLUMEUSD.push("MATIC")
    GlassNode_TOTALVOLUMEUSD.push("MKR")
    GlassNode_TOTALVOLUMEUSD.push("OMG")
    GlassNode_TOTALVOLUMEUSD.push("WTC")

var IntoTheBlock_TXVOLUMEUSD = array.new<string>()
if bar_index == 0
    IntoTheBlock_TXVOLUMEUSD.push("ADA")
    IntoTheBlock_TXVOLUMEUSD.push("ANT")
    IntoTheBlock_TXVOLUMEUSD.push("FUN")
    IntoTheBlock_TXVOLUMEUSD.push("FXS")
    IntoTheBlock_TXVOLUMEUSD.push("HOT")
    IntoTheBlock_TXVOLUMEUSD.push("STX")
    IntoTheBlock_TXVOLUMEUSD.push("WTC")
    IntoTheBlock_TXVOLUMEUSD.push("ZEC")

// ----------------------------------------------}
// PREDEFINED TICKER IDs
// ----------------------------------------------{

string my_token = syminfo.basecurrency

string symbol_marketcap_cryptocap = ticker.standard(str.format("CRYPTOCAP:{0}", my_token))

string symbol_volumeusd_intotheblock = ticker.standard(str.format("INTOTHEBLOCK:{0}_TXVOLUMEUSD", my_token))

string symbol_marketcap_coinmetrics = ticker.standard(str.format("COINMETRICS:{0}_MARKETCAPFF", my_token))
string symbol_volumeusd_coinmetrics = ticker.standard(str.format("COINMETRICS:{0}_TXVOLUMEUSD", my_token))

string symbol_marketcap_glassnode = ticker.standard(str.format("GLASSNODE:{0}_MARKETCAP"     , my_token))
string symbol_volumeusd_glassnode = ticker.standard(str.format("GLASSNODE:{0}_TOTALVOLUMEUSD", my_token))

// ----------------------------------------------}
// FETCHING DATA 
// ----------------------------------------------{

string my_timeframe = timeframe.period
float  my_source    = close

float marketcap_cryptocap   = request.security(symbol_marketcap_cryptocap,   my_timeframe, my_source[1], ignore_invalid_symbol = true)
float marketcap_glassnode   = request.security(symbol_marketcap_glassnode,   my_timeframe, my_source,    ignore_invalid_symbol = true)
float marketcap_coinmetrics = request.security(symbol_marketcap_coinmetrics, my_timeframe, my_source,    ignore_invalid_symbol = true)

float volume_intotheblock = request.security(symbol_volumeusd_intotheblock, my_timeframe, my_source, ignore_invalid_symbol = true)
float volume_coinmetrics  = request.security(symbol_volumeusd_coinmetrics,  my_timeframe, my_source, ignore_invalid_symbol = true)
float volume_glassnode    = request.security(symbol_volumeusd_glassnode,    my_timeframe, my_source, ignore_invalid_symbol = true)

// ----------------------------------------------}
// FILTER
// ----------------------------------------------{

float marketcap = na

// CryptoCap > GlassNode > CoinMetrics
if not na(marketcap_cryptocap)
    marketcap := marketcap_cryptocap
else if not na(marketcap_glassnode)
    marketcap := marketcap_glassnode
else if not na(marketcap_coinmetrics) and not CoinMetrics_MARKETCAPFF.includes(my_token)
    marketcap := marketcap_coinmetrics
else
    if barstate.islastconfirmedhistory
        runtime.error(str.format("Market Cap of {0} is not available.", my_token))

float volume_usd = na

// IntoTheBlock > CoinMetrics > GlassNode
if not na(volume_intotheblock) and not IntoTheBlock_TXVOLUMEUSD.includes(my_token)
    volume_usd := volume_intotheblock
else if not na(volume_coinmetrics) and not CoinMetrics_TXVOLUMEUSD.includes(my_token)
    volume_usd := volume_coinmetrics
else if not na(volume_glassnode) and not GlassNode_TOTALVOLUMEUSD.includes(my_token)
    volume_usd := volume_glassnode
else
    if barstate.islastconfirmedhistory
        runtime.error(str.format("Transactions volume of {0} is not available.", my_token))

// ----------------------------------------------}
// MOVING AVERAGE
// ----------------------------------------------{

string ma_grp  = "Daily Moving Average..."
int ma_length  = input.int(90, "Length", minval = 2, group = ma_grp)
string tooltip =
 "
 DEMA = Double Moving Average Exponential\n\n
 EMA = Moving Average Exponential\n\n
 SMA = Simple Moving Average\n\n
 TEMA = Tripple Moving Average Exponential
 "
string ma_type = input.string("SMA", "Type", ["DEMA", "EMA", "SMA", "TEMA"], tooltip, group = ma_grp)

dema(source, length) =>
    float ema1 = ta.ema(source, length)
    float ema2 = ta.ema(ema1, length)
    2 * ema1 - ema2

tema(source, length) =>
    float ema3 = ta.ema(source, length)
    float ema4 = ta.ema(ema3, length)
    float ema5 = ta.ema(ema4, length)
    3 * (ema3 - ema4) + ema5

mean(source, length, ma_type) =>
    switch ma_type
        "DEMA" => dema(source, length)
        "EMA"  => ta.ema(source, length)
        "TEMA" => tema(source, length)
        => ta.sma(source, length)

// ----------------------------------------------}
// CALCULATIONS
// ----------------------------------------------{


float volume_ma = mean(volume_usd, ma_length, ma_type)
float nvts = marketcap / volume_ma

float nvt = marketcap / volume_usd

// ----------------------------------------------}
// COLORS
// ----------------------------------------------{

//import weak_hand/colors/17 as colors
//colors.theme color_auto = colors.find(syminfo.basecurrency)
color my_color = input.color(#f7931a, "Color")
//if input.bool(false, "Use Color Theme of the Token")
    //my_color := color_auto.bg

// ----------------------------------------------}
// OUTPUT
// ----------------------------------------------{

plot(nvts, "NVTS", my_color, 2, editable = false, offset = -1)
//plot(nvt, "NVT", color.gray, 1, plot.style_columns, editable = false)
