Squeeze Detector 3000
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © barnabygraham

//@version=5
indicator("Squeeze Detector 3000", overlay=true)
daysBack = input.int(5,'Pre/Post Market Volume Lookback Days #')


//WORKS FOR CURRENT DAY PREMARKET (LIVE)
//1.1 and 2.1 - Pre-market volume and RVOL
var tf1m = timeframe.isminutes and timeframe.period=='1'
var tf2m = timeframe.isminutes and timeframe.period=='2'
var tf5m = timeframe.isminutes and timeframe.period=='5'
var tf15m = timeframe.isminutes and timeframe.period=='15'
var tf30m = timeframe.isminutes and timeframe.period=='30'

tfTrigger = tf1m?not na(time('1', '1559-1959')):tf2m?not na(time('1', '1558-1959')):tf5m?not na(time('1', '1555-1959')):tf15m?not na(time('1', '1545-1959')):tf30m?not na(time('1', '1530-1959')):not na(time('1', '1500-1959')) 

trigger = tfTrigger                         //  WAS PREVIOUSLY >>>>> trigger = not na(time('1', '0930-1959'))
reset = trigger and not trigger[1]
preMarket = not na(time('1', '0400-0930')) 
var preMarketVolume = 0.
preMarketVolume := reset ? 0. : preMarket ? preMarketVolume + volume : preMarketVolume
float totalPreMarketVolume = na
totalPreMarketVolume := time('1', '0400-0929') ? preMarketVolume : na
fin = totalPreMarketVolume>-1 and na(totalPreMarketVolume[1]) ? totalPreMarketVolume : 0 
var temp = 0.
currentDayPMV = math.max(fin,preMarketVolume)
var a = array.new_float(daysBack+1)
// if (hour == 04) and (hour[1] != 04)
if not na(preMarket)
    temp := currentDayPMV
next = (temp != temp[1]) ? temp : na
if not na(next)
    array.push(a, next)
    array.shift(a)
var PMSMA = 0.
var avg = 0.
if barstate.islast
    avg:=0
    for i = 1 to daysBack
        PMSMA:=array.get(a,i)
        avg:=avg+PMSMA
        // labell=label.new(bar_index[i],close,str.tostring(array.get(a,i)))        // for testing and to see how the arrays work
avgFin=avg/daysBack
// plot(array.get(a,daysBack),color=color.purple)                                   // for testing and to see how the arrays work
// label6=label.new(bar_index[7],close,str.tostring(avgFin))                        // for testing and to see how the arrays work


// CURRENT SETUP WORKS PERFECTLY DURING PREMARKET (POSTMARKET WORKS WHEN PREMARKET) - DOESN'T WORK DURING INTRADY
//1.2 and 2.2 - Post-market volume and RVOL
trigger2 = not na(time('1', '0400-1559'))
reset2 = trigger and not trigger[1]
postMarket = not na(time('1', '1559-0400'))
var postMarketVolume = 0.
postMarketVolume := reset2 ? 0. : postMarket ? postMarketVolume + volume : postMarketVolume
float totalPostMarketVolume = na
totalPostMarketVolume := time('1', '1559-1959') ? postMarketVolume : na
fin2 = totalPostMarketVolume>-1 and na(totalPostMarketVolume[1]) ? totalPostMarketVolume : 0 
var temp2 = 0.
currentDayPMV2 = math.max(fin2,postMarketVolume)
// plot(currentDayPMV2,color=color.silver)
var b = array.new_float(daysBack+1)
if (hour == 04) and (hour[1] != 04)
    temp2 := currentDayPMV2
next2 = (temp2 != temp2[1]) ? temp2 : na
if not na(next2)
    array.push(b, next2)
    array.shift(b)
var PMSMA2 = 0.
var avg2 = 0.
if barstate.islast
    avg2:=0
    for i = 1 to daysBack
        PMSMA2:=array.get(b,i)
        avg2:=avg2+PMSMA2
avgFin2=avg2/daysBack

ETHchoice=input.string('Premarket',title='ETH Volume', options=['Premarket','Postmarket','Both'])
ETHvolume=ETHchoice=='Premarket'?array.get(a,daysBack):ETHchoice=='Postmarket'?postMarketVolume:array.get(a,daysBack)+postMarketVolume
ETHvolumeAvg=ETHchoice=='Premarket'?avgFin:ETHchoice=='Postmarket'?avgFin2:avgFin2+avgFin



//3. Range of day
// Range of the day. (high of day - low of day) (can change value int $, % or ATR) (if value is smaller than 1 ATR, display in green, if between 1-2 orange, 2+ red)
rangeTrigger = not na(time('1', '0400-0701')) //'1959-0701'))
rangeReset = rangeTrigger and not rangeTrigger[1]
oneDay = not na(time('1', '0400-2000'))
var HOD = open
var LOD = open
if oneDay and (high>HOD)
    HOD:=high
if oneDay and (low<LOD)
    LOD:=low
if rangeReset
    HOD:=open
    LOD:=open
var HODarray=array.new_float(1)
var LODarray=array.new_float(1)
var closeArray=array.new_float(1)
if (hour == 19) and (hour[1] != 19)//
    array.push(HODarray,HOD)
    array.push(LODarray,LOD)
    array.push(closeArray,close)
    array.shift(HODarray)
    array.shift(LODarray)
    array.shift(closeArray)
HOD2=(array.get(HODarray,0))
LOD2=(array.get(LODarray,0))
close2=(array.get(closeArray,0))
HOD3=HOD2==HOD2[1]?na:HOD2
LOD3=LOD2==LOD2[1]?na:LOD2
close3=close2==close2[1]?na:close2
daysBackRange=input.int(5,title="Range Lookback Days")
var HODarray2=array.new_float(daysBackRange+1)//
var LODarray2=array.new_float(daysBackRange+1)//
var closeArray2=array.new_float(daysBackRange+1)//
if (not na(HOD3)) and (not na(LOD3))
    array.push(HODarray2,HOD3)
    array.push(LODarray2,LOD3)
    array.push(closeArray2,close3)
array.insert(HODarray2,daysBackRange+1,HOD)
array.insert(LODarray2,daysBackRange+1,LOD)
array.insert(closeArray2,daysBackRange+1,close)
if (not na(HOD3)) and (not na(LOD3))
    array.shift(HODarray2)
    array.shift(LODarray2)
    array.shift(closeArray2)
var extRange = 0.
var extRangeAvg = 0.
var extRangeAvgFinal = 0.
var extRangeAvgPercent=0.
var extRangeAvgPercentFinal=0.


//4. Calculate the stocks ATR, then display the amount of times the ATR has turned over from yesterday's close price. 

//  = not na(time('1', '1600-0400'))
// reset = trigger and not trigger[1]




dayRange = request.security(syminfo.tickerid,'D',high)-request.security(syminfo.tickerid,'D',low)
dayRangePercent=(request.security(syminfo.tickerid,'D',high)/request.security(syminfo.tickerid,'D',low)-1)*100

// plot(dayRangePercent)
// plot(dayRange,color=color.red)


//ATR
atrLen=(input.int(14,title='ATR Length'))
atr=request.security(syminfo.tickerid,'D',ta.atr(atrLen))
atrToday=request.security(syminfo.tickerid,'D',ta.atr(1))
yDayClose=request.security(syminfo.tickerid,'D',math.abs(close-close[1]))
atrTurnover2=atrToday/atr
atrTurnover=yDayClose/atr
atrColor=color.from_gradient(atrTurnover,0.75,2.25,color.new(color.green,0),color.new(color.red,0)) // colored by gradient
//atrColor=atrTurnover<1?color.new(color.green,0):atrTurnover>2?color.new(color.red,0):color.new(color.orange,0) // Your way

//5. Short Float
shs_out = request.financial(syminfo.tickerid, 'TOTAL_SHARES_OUTSTANDING', 'FQ', barmerge.gaps_off)


shortTickerVol = request.security(str.tostring(syminfo.ticker) + "_SHORT_VOLUME", 'D', close)

quandl_ticker = 'QUANDL:FINRA/FNSQ_' + str.replace_all(syminfo.ticker, '.', '_')
shortFloat = (request.security(quandl_ticker, 'D', close))*10

daily_vol = request.security(syminfo.tickerid, 'D', volume)

float sh_vol_ratio = shortTickerVol / daily_vol //daily

dailyShortVolume=(hour==04) and (hour[1] != 04) ? shortFloat : na

var dailyShortVolumeTable=0.
var dailyShortVolumeRatio=0.
var test = array.new_float(11)
if not na(dailyShortVolume)
    dailyShortVolumeTable := dailyShortVolume
    dailyShortVolumeRatio := sh_vol_ratio
    array.push(test, dailyShortVolumeTable)
    array.shift(test)
shortFloatPercent=shortFloat/shs_out

// Plot variable on the chart
// plot(series=dailyShortVolume, linewidth=1, title='Selection', style=plot.style_histogram)
// ShortVolAvgLen = input.int(50,title='Short Volume Average Length')
// plot(ta.sma(dailyShortVolume,ShortVolAvgLen),color=color.green)

shortChoice=input.string('Volume', title='Short Volume or Float', options=['Volume','Float'])
shortChoice2=shortChoice=="Volume"?'Vol':'Float'
volOrFloat=shortChoice=="Volume"?shortTickerVol:shortFloat
volOrFloatPercent=shortChoice=='Volume'?math.round((shortTickerVol/(daily_vol[1]/100)),3):math.round(shortFloatPercent*100,1) 


formatChoice=input.string('$',title='Range Format', options=['$','%','ATR'])
percentRange=math.round((HOD-LOD)/(close/100),3)     //Day % Range
dollarRange=math.round(HOD-LOD,3)                   //day $ range
var averageRangeVar=0.
var averagePerRangeVar=0.
if barstate.islast
    for i = 0 to daysBackRange
        averageRangeVar := averageRangeVar + dayRange
        averagePerRangeVar := averagePerRangeVar + percentRange
averageRangeVar:=averageRangeVar/daysBackRange
averagePerRangeVar:=averagePerRangeVar/daysBackRange

RangeVar=formatChoice=='$'?dollarRange:formatChoice=='%'?percentRange:atrToday
RangeVarAvg=formatChoice=='$'?averageRangeVar:formatChoice=='%'?averagePerRangeVar:math.round(atr,3)

RTHVol=request.security(ticker.new(syminfo.prefix,syminfo.ticker,session.regular,adjustment.none),'D',volume)
ETHVol=request.security(ticker.new(syminfo.prefix,syminfo.ticker,session.extended,adjustment.none),'D',volume)
RTHandETH=RTHVol+ETHVol
dayVolumeChoice=input.string('RTH',title="Float Turnover Volume",options=['RTH','ETH','Both'])
dayVolume=dayVolumeChoice=='RTH'?RTHVol:dayVolumeChoice=='ETH'?ETHVol:RTHandETH
shareType=input.string('Total Shares Outstanding',title='Share Type', options=['Total Shares Outstanding', 'Float Shares Outstanding'])
float_shs_out = request.financial(syminfo.tickerid, 'FLOAT_SHARES_OUTSTANDING', 'FY', barmerge.gaps_off)
shareType2=shareType=='Total Shares Outstanding'?shs_out:float_shs_out
floatTurnover=dayVolume/shareType2




// RTH RVOL
int period = input.int(3, 'RVOL Lookback Period in Days',minval=1)
pastVolume = request.security(syminfo.tickerid, 'D', ta.sma(volume,period))
RVOLratio = daily_vol/pastVolume
RVOLcolor=color.from_gradient(RVOLratio,0.75,2.25,color.new(color.green,0),color.new(color.red,0)) // colored by gradient






// Table
sr1 = input.bool(true,'Show Row 1')
sr2 = input.bool(true,'Show Row 2')
sr3 = input.bool(true,'Show Row 3')
sr4 = input.bool(true,'Show Row 4')
sr5 = input.bool(true,'Show Row 5')
sr6 = input.bool(true,'Show Row 6')

tableTextColor=input.color(color.new(color.white,20),title='Table Text Color')
tableTitleTextColor=input.color(color.new(color.blue,20), title='Table Title Text Color')
var theTable = table.new(position.top_right, 17, 17, color.new(#ffffff, 100), frame_color=color.new(#ff0000, 75), frame_width = -3, border_color=color.new(#aaee55, 0), border_width = -3)
if barstate.islast and timeframe.period != "W" and timeframe.period != "M"
    table.cell(theTable, 0, 0, "", text_color=tableTextColor)
    if sr1
        table.cell(theTable, 1, 1, str.tostring(ETHvolume, '#,###,###.#'), text_color=tableTextColor)
        table.cell(theTable, 1, 0, ETHchoice, text_color=tableTitleTextColor)
        table.cell(theTable, 2, 1, str.tostring(ETHvolumeAvg, '#,###,###.#'), text_color=tableTextColor)
        table.cell(theTable, 2, 0, str.tostring(daysBack) + " Day Avg", text_color=tableTitleTextColor)
    if sr2
        table.cell(theTable, 0, 3, "", text_color=tableTextColor)
        table.cell(theTable, 1, 3, "Short " + str.tostring(shortChoice2), text_color=tableTitleTextColor)
        table.cell(theTable, 1, 4, str.tostring(volOrFloat, '#,###,###.#'), text_color=tableTextColor)
        table.cell(theTable, 2, 3, "Short " + str.tostring(shortChoice2) + " %", text_color=tableTitleTextColor)
        table.cell(theTable, 2, 4, str.tostring(volOrFloatPercent) + "%", text_color=tableTextColor) 
    if sr3
        table.cell(theTable, 1, 5, "RTH RVOL", text_color=tableTitleTextColor)    
        table.cell(theTable, 1, 6, str.tostring(RVOLratio,'#,###,###.##'), text_color=RVOLcolor)
        table.cell(theTable, 2, 5, str.tostring(period)+" Day RVOL", text_color=tableTitleTextColor)    
        table.cell(theTable, 2, 6, str.tostring(pastVolume,'#,###,###'), text_color=tableTextColor)   
    if sr4
        table.cell(theTable, 0, 7, "", text_color=tableTextColor)    
        table.cell(theTable, 1, 7, "Day's "+formatChoice+" Range", text_color=tableTitleTextColor)    
        table.cell(theTable, 1, 8, str.tostring(RangeVar), text_color=tableTextColor)      
        table.cell(theTable, 2, 7, str.tostring(daysBackRange)+" Day Avg", text_color=tableTitleTextColor)    
        table.cell(theTable, 2, 8, str.tostring(RangeVarAvg), text_color=tableTextColor)      
    if sr5
        table.cell(theTable, 0, 9, "", text_color=tableTextColor) 
        table.cell(theTable, 1, 9, str.tostring(atrLen)+" Day ATR", text_color=tableTitleTextColor)
        table.cell(theTable, 1, 10, str.tostring(math.round(atr,4)), text_color=tableTextColor) 
        table.cell(theTable, 2, 9, "ATR T/O", text_color=tableTitleTextColor) 
        table.cell(theTable, 2, 10, str.tostring(math.round(atrTurnover,2)), text_color=atrColor) 
    if sr6
        table.cell(theTable, 1, 11, "Today "+str.tostring(dayVolumeChoice)+" Vol", text_color=tableTitleTextColor) 
        table.cell(theTable, 1, 12, str.tostring(dayVolume,'#,###,###.#'), text_color=tableTextColor) 
        table.cell(theTable, 2, 11, "Float T/O", text_color=tableTitleTextColor) 
        table.cell(theTable, 2, 12, str.tostring(math.round(floatTurnover,3)), text_color=tableTextColor) 
    

    // table.cell(theTable, 3, 5, "Days To Cover", text_color=tableTextColor)    
    // table.cell(theTable, 3, 6, str.tostring(math.round(shortFloat/daily_vol,2)), text_color=tableTextColor)    
    // table.cell(theTable, 3, 8, "$"+str.tostring(math.round(extRangeAvgFinal,2)), text_color=tableTextColor)      
    // table.cell(theTable, 4, 8, str.tostring(math.round(extRangeAvgPercentFinal,3))+"%", text_color=tableTextColor)


    //extRangeAvgFinal
   
   
   
    //table.cell(theTable, 0, 0, preMarketVolume, text_color=XLUvol>0?color.new(color.green,0):color.new(color.red,0))


//  + str.tostring(ShortVolAvgLen)