@tk · spectral
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © gabrielrtakeda

//@version=5

// <declaration_statement>

indicator("@tk · spectral", overlay=true)

// <import_statements>

import gabrielrtakeda/tk/1 as tk

// <constant_declarations>

string DEFAULT_TEXT_SIZE = size.normal
string DEFAULT_POSITION = position.bottom_right
string DEFAULT_PAIR_OPERATOR = 'USDT'
color DEFAULT_SPECTRUM_COLOR = #434651

// hints
string HINT_PAIR_QUOTE = 'e.g. BTCUSDT. Which BTC is the "base" and USDT is the "quote".'

// <inputs>

string GROUP_GENERAL = 'General'
string textSizeInput = input.string(DEFAULT_TEXT_SIZE, 'Text Size', [size.tiny, size.small, size.normal, size.large], group=GROUP_GENERAL)
string positionInput = input.string(DEFAULT_POSITION, 'Position', [position.top_left, position.top_center, position.top_right, position.middle_left, position.middle_center, position.middle_right, position.bottom_left, position.bottom_center, position.bottom_right], group=GROUP_GENERAL)
string pairQuoteInput = input.string(DEFAULT_PAIR_OPERATOR, 'Pair Quote', tooltip=HINT_PAIR_QUOTE, group=GROUP_GENERAL)
color spectrumColorInput = input.color(DEFAULT_SPECTRUM_COLOR, 'Spectrum Color', group=GROUP_GENERAL)

note = input.bool(true, 'v0.1.37')

// <function_declarations>

stripStarts(src, str) =>
    strRegex = str.format('^{0}', str)
    strMatch = str.match(src, strRegex)
    strStripped = str.replace(src, strMatch, '')
    strStripped

// <calculations>

isCrypto = syminfo.type == 'crypto'
hasPerpRoot = str.length(str.match(syminfo.root, '^[\\w]+\.[P|PERP]$')) > 0
hasPerpDesc = str.contains(syminfo.description, 'Perpetual')
isFutures = hasPerpRoot or hasPerpDesc

posUsdtPair = str.pos(syminfo.ticker, pairQuoteInput) // e.g. BTC(USDT.P)
posInstrumentSep = str.pos(syminfo.ticker, ":") // e.g. (BINANCE:)BTCUSDT.P
symbolSubstr = str.substring(syminfo.ticker, posInstrumentSep+1, posUsdtPair)
symbolStripped = stripStarts(stripStarts(stripStarts(symbolSubstr, '100000'), '10000'), '1000')
symbol = symbolStripped
ticker = str.format('{0}{1}{2}', symbol, pairQuoteInput, isFutures ? '' : '.P')
is100kMult = str.startswith(symbolSubstr, '100000')
is10kMult = str.startswith(symbolSubstr, '10000')
is1kMult = str.startswith(symbolSubstr, '1000')
multplier = is100kMult ? 100000 : is10kMult ? 10000 : is1kMult ? 1000 : 1

otherMarketClose = request.security(ticker, timeframe.period, close, gaps=barmerge.gaps_off)
higherClose = math.max(close, otherMarketClose)
priceDiff = (close - otherMarketClose) * -1
priceDiffNeg = priceDiff < 0
priceDiffPerc = math.abs(priceDiff) / higherClose * 100 / multplier
priceDiffPercStr = str.format('{1}{0,number,0.00}%', priceDiffPerc, priceDiffNeg ? '-' : '+')


// 
// plot spectrum bars
// 

// TODO: refactor
// Use gaps to only return data when the 1D timeframe completes, `na` otherwise.
[o, h, l, c] = request.security(ticker, timeframe.period, [open, high, low, close], gaps = barmerge.gaps_on)

// Only plot candles on intraday timeframes,
// and when non `na` values are returned by `request.security()` because a HTF has completed.
plotcandle(timeframe.isintraday ? o : na, h, l, c, "Spectrum Candles", color=spectrumColorInput, wickcolor=spectrumColorInput, bordercolor=spectrumColorInput, display=display.pane)

var line1 = line.new(bar_index, c, bar_index, c, extend=extend.both, color=spectrumColorInput, style=line.style_dotted, width=1)
line.set_y1(line1, c)
line.set_y2(line1, c)
line.set_x1(line1, bar_index)
line.set_x2(line1, bar_index+1)
// line.set_xloc(line1, time, time + 60 * 60 * 24, xloc.bar_time)

// <strategy_calls>
// <visuals>

hudInstance = tk.hudInit(positionInput, columns=2, bgcolor=chart.bg_color, textSize=textSizeInput, textColor=chart.fg_color)

if tk.isHudReady() and barstate.isrealtime
    tk.hud(hudInstance, array.from(isFutures ? 'spot' : 'futures', str.tostring(priceDiffPercStr)))

// <alerts>