Bitcoin Stalemate Indicator
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © DamonAndTheSea

//@version=5
indicator(title="Bitcoin Stalemate Indicator")

//Collect BTC volume from top exchanges
volBinance = request.security('BINANCE:BTCUSDT', timeframe.period, expression=volume)
volCoinbase = request.security('COINBASE:BTCUSD', timeframe.period, expression=volume)
volBitfinex = request.security('BITFINEX:BTCUSD', timeframe.period, expression=volume)
volGemini = request.security('GEMINI:BTCUSD', timeframe.period, expression=volume)
volHuobi = request.security('HUOBI:BTCUSDT', timeframe.period, expression=volume)
volOKX = request.security('OKX:BTCUSDT', timeframe.period, expression=volume)

//Populate array with all exchange volume values
float [] exchangeVol = array.new_float(0)
array.push(exchangeVol, volBinance)
array.push(exchangeVol, volCoinbase)
array.push(exchangeVol, volBitfinex)
array.push(exchangeVol, volGemini)
array.push(exchangeVol, volHuobi)
array.push(exchangeVol, volOKX)

//Create exchange bool checkbox inputs for UI
includesBinanceInput = input.bool(true, "Include Binance")
includesCoinbaseInput = input.bool(true, "Include Coinbase")
includesBitfinexInput = input.bool(true, "Include Bitfinex")
includesGeminiInput = input.bool(true, "Include Gemini")
includesHuobiInput = input.bool(true, "Include Huobi")
includesOKXInput = input.bool(true, "Include OKX")

//Populate array with all the checkbox bool values
bool [] exchangeInputs = array.new_bool(0)
array.push(exchangeInputs, includesBinanceInput)
array.push(exchangeInputs, includesCoinbaseInput)
array.push(exchangeInputs, includesBitfinexInput)
array.push(exchangeInputs, includesGeminiInput)
array.push(exchangeInputs, includesHuobiInput)
array.push(exchangeInputs, includesOKXInput)


//exchange and vol vars 
float avgVol = 0.0
int totalNumExchangesIncluded = 0

//loop through input checkbox array to combine volume from each selected exchange
for i = 0 to (array.size(exchangeInputs) - 1)
    input = array.get(exchangeInputs, i)
    if input == true
        totalNumExchangesIncluded := totalNumExchangesIncluded + 1
        avgVol := avgVol + array.get(exchangeVol, i)

    
//Divide by total included exchanges to average       
avgVol := avgVol/totalNumExchangesIncluded

//Get candle size as a percentage of close value
candleSizePct = (high - low)/close

//Stalemate amplitude is canlde volume over the candle size percentage. Divided by 100000 to scale down to more readable numbers
stalemateAmplitude = avgVol/candleSizePct/100000

//Create sma period input UI
periodInput = input.int(title="SMA Period", defval=5)

//Smooth stalemateAmplitude with SMA
stalemateSMA = ta.sma(stalemateAmplitude, periodInput)

//Convert timeframe to minutes float
f_resInMinutes() => 
    _resInMinutes = timeframe.multiplier * (
      timeframe.isseconds ? 1. / 60. :
      timeframe.isminutes ? 1.       :
      timeframe.isdaily   ? 1440.    :
      timeframe.isweekly  ? 10080.   :
      timeframe.ismonthly ? 43800.   : na)

//Chained ternary operator to smooth out heat map for different timeframes
numMin = f_resInMinutes()
targetThresh = (numMin <= 3 ? math.log10(numMin) :
     numMin <= 60 ? math.log10(numMin) * 1 :
     numMin <= 240 ? math.log10(numMin) * 1.25 : 
     numMin <= 720 ? math.log10(numMin) * 2 : 
     numMin <= 1440 ? math.log10(numMin) * 3 : 
     numMin <= 4320 ? math.log10(numMin) * 4 :
     numMin <= 10080 ? math.log10(numMin) * 5 :
     numMin <= 43800 ? math.log10(numMin) * 6.5 :
     numMin > 43800 ? math.log10(numMin) * 9 : na)

//Create input for heatmap checkbox
showsHeatmap = input.bool(true, "Show Heatmap")
//Check if all exchanges represented.  Heatmap is disabled unless all are selected
bool isAllExchanges = totalNumExchangesIncluded == array.size(exchangeInputs)
//Define the target threshold for the heatmap     
isTargetThresh = stalemateSMA > targetThresh
//Transparency value is keyed to strength of indicator value for readability
transparency_val = 100 - ((stalemateSMA - targetThresh) * 5)

//Plot UI
bgcolor(isTargetThresh and showsHeatmap and isAllExchanges ? color.new(color.lime, transparency_val) : na) 
plot(stalemateSMA, color=color.fuchsia)
