crowding-model-bullvision.pine
Copy
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// BullVisionCapital
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%+=#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*==+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@*===+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@#====+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@==#@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@#=====+%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*===#@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@#========*#%%%@@%%%%%%%%%%%@@@@@@@@@%#+====+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@#==============*+===========*%@#+========+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%*=============+=============#@*======+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%#+========================#@%==+#%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%##+==================+%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+===============================@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%==================*@@@*=======@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@@@%#*=============++*%#=====%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#==========================+=====*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*==================================+%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@*==========++=========================*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@#==========+@%+====================#+====#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@%+=========+@@@@#===================#@%+==%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@#=========+@@@@@@@@@%%%%%%%*==============@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@#========+@@@@@@@@@@@@@@@@@@@@@#========+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@%+=======%@@@@@@@@@@@@+@@@@@@@@@@@%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@%+=====*@@@@@@@%@@@%+==#@@@@@@#%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+====#@@@@@@@=@@@%+==#@@@@@===#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#===#@@@@@%*=*%@%+==#@@@@@==*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%*=#@@@@@#+==%@%+==#@@@@+=#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@@@@@@#+==%@%+==#@@@+=%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+==%@@@=@@@@**@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+==%@@@#@@@#%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%=%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@version=6
indicator(" Crowding model ║ BullVision",shorttitle = "👥 Crowding Model ║ BullVision👥", overlay=false)
// ==================== INPUTS ====================
group1 = '🎨 Visual Settings'
int BarScale = input.int(150, 'Bar Scale', group = group1)
bool showMainAssets = input.bool(true, 'Show TOTAL, BTC, ETH, OTHERS', group = group1)
bool showGradientBg = input.bool(true, 'Show Gradient Background', group = group1)
bool showCrowdingPanel = input.bool(true, 'Show Crowding Analytics Panel', group = group1)
group2 = '📊 Indicator Parameters'
int rsi_length = input.int(14, 'RSI Length', minval = 5, maxval = 50, group = group2)
int Z_score_L = input.int(90, 'Z-score lookback', minval = 20, maxval = 200, group = group2)
float crowdingThreshold = input.float(40.0, 'Crowding Alert Threshold %', minval = 20, maxval = 60, group = group2)
group3 = '🎯 Zone Settings'
bool showQuadrantLabels = input.bool(true, 'Show Quadrant Labels', group = group3)
bool showDangerZones = input.bool(true, 'Highlight Danger Zones', group = group3)
float dangerRSIHigh = input.float(70.0, 'Danger RSI High', minval = 60, maxval = 90, group = group3)
float dangerRSILow = input.float(30.0, 'Danger RSI Low', minval = 10, maxval = 40, group = group3)
// ==================== ASSET TICKERS ====================
groupAssets = '📈 Asset Tickers'
symbolINDEX = input.symbol('CRYPTOCAP:TOTAL', 'MARKET INDEX', group = groupAssets)
symbolINDEX2 = input.symbol('CRYPTOCAP:OTHERS', 'SECONDARY INDEX', group = groupAssets)
symbolMAIN = input.symbol('INDEX:BTCUSD', 'MAIN ASSET ', group = groupAssets)
symbolMAIN2 = input.symbol('INDEX:ETHUSD', 'SECOND MAIN ASSET', group = groupAssets)
// Editable symbols for all 36 coins
symbol1 = input.symbol('CRYPTO:BNBUSD', 'Asset 1', group = groupAssets)
symbol2 = input.symbol('CRYPTO:SOLUSD', 'Asset 2 ', group = groupAssets)
symbol3 = input.symbol('CRYPTO:XRPUSD', 'Asset 3 ', group = groupAssets)
symbol4 = input.symbol('CRYPTO:ADAUSD', 'Asset 4 ', group = groupAssets)
symbol5 = input.symbol('CRYPTO:DOGEUSD', 'Asset 5 ', group = groupAssets)
symbol6 = input.symbol('CRYPTO:AVAXUSD', 'Asset 6 ', group = groupAssets)
symbol7 = input.symbol('CRYPTO:SHIBUSD', 'Asset 7 ', group = groupAssets)
symbol8 = input.symbol('CRYPTO:TRXUSD', 'Asset 8 ', group = groupAssets)
symbol9 = input.symbol('CRYPTO:DOTUSD', 'Asset 9 ', group = groupAssets)
symbol10 = input.symbol('CRYPTO:LINKUSD', 'Asset 10 ', group = groupAssets)
symbol11 = input.symbol('CRYPTO:MATICUSD', 'Asset 11 ', group = groupAssets)
symbol12 = input.symbol('CRYPTO:UNIUSD', 'Asset 12 ', group = groupAssets)
symbol13 = input.symbol('CRYPTO:TONUSD', 'Asset 13 ', group = groupAssets)
symbol14 = input.symbol('CRYPTO:BCHUSD', 'Asset 14 ', group = groupAssets)
symbol15 = input.symbol('CRYPTO:LTCUSD', 'Asset 15 ', group = groupAssets)
symbol16 = input.symbol('CRYPTO:ICPUSD', 'Asset 16 ', group = groupAssets)
symbol17 = input.symbol('CRYPTO:FILUSD', 'Asset 17 ', group = groupAssets)
symbol18 = input.symbol('CRYPTO:ETCUSD', 'Asset 18 ', group = groupAssets)
symbol19 = input.symbol('CRYPTO:ATOMUSD', 'Asset 19 ', group = groupAssets)
symbol20 = input.symbol('CRYPTO:IMXUSD', 'Asset 20 ', group = groupAssets)
symbol21 = input.symbol('CRYPTO:NEARUSD', 'Asset 21 ', group = groupAssets)
symbol22 = input.symbol('CRYPTO:LEOUSD', 'Asset 22 ', group = groupAssets)
symbol23 = input.symbol('COINBASE:STXUSD', 'Asset 23 ', group = groupAssets)
symbol24 = input.symbol('COINBASE:APTUSD', 'Asset 24 ', group = groupAssets)
symbol25 = input.symbol('KUCOIN:TAOUSDT', 'Asset 25 ', group = groupAssets)
symbol26 = input.symbol('CRYPTO:OPUSD', 'Asset 26 ', group = groupAssets)
symbol27 = input.symbol('CRYPTO:XLMUSD', 'Asset 27 ', group = groupAssets)
symbol28 = input.symbol('CRYPTO:KASUSD', 'Asset 28 ', group = groupAssets)
symbol29 = input.symbol('CRYPTO:HBARUSD', 'Asset 29 ', group = groupAssets)
symbol30 = input.symbol('CRYPTO:CROUSD', 'Asset 30 ', group = groupAssets)
symbol31 = input.symbol('CRYPTO:INJUSD', 'Asset 31 ', group = groupAssets)
symbol32 = input.symbol('CRYPTO:VETUSD', 'Asset 32 ', group = groupAssets)
symbol33 = input.symbol('CRYPTO:OKBUSD', 'Asset 33 ', group = groupAssets)
symbol34 = input.symbol('CRYPTO:GRTUSD', 'Asset 34 ', group = groupAssets)
symbol35 = input.symbol('CRYPTO:LDOUSD', 'Asset 35 ', group = groupAssets)
symbol36 = input.symbol('CRYPTO:RNDRUSD', 'Asset 36 ', group = groupAssets)
// ==================== ASSET DEFINITIONS ====================
total = request.security(symbolINDEX, 'D', close)
others = request.security(symbolINDEX2, 'D', close)
btc = request.security(symbolMAIN, 'D', close)
eth = request.security(symbolMAIN2, 'D', close)
asset1 = request.security(symbol1, 'D', close)
asset2 = request.security(symbol2, 'D', close)
asset3 = request.security(symbol3, 'D', close)
asset4 = request.security(symbol4, 'D', close)
asset5 = request.security(symbol5, 'D', close)
asset6 = request.security(symbol6, 'D', close)
asset7 = request.security(symbol7, 'D', close)
asset8 = request.security(symbol8, 'D', close)
asset9 = request.security(symbol9, 'D', close)
asset10 = request.security(symbol10, 'D', close)
asset11 = request.security(symbol11, 'D', close)
asset12 = request.security(symbol12, 'D', close)
asset13 = request.security(symbol13, 'D', close)
asset14 = request.security(symbol14, 'D', close)
asset15 = request.security(symbol15, 'D', close)
asset16 = request.security(symbol16, 'D', close)
asset17 = request.security(symbol17, 'D', close)
asset18 = request.security(symbol18, 'D', close)
asset19 = request.security(symbol19, 'D', close)
asset20 = request.security(symbol20, 'D', close)
asset21 = request.security(symbol21, 'D', close)
asset22 = request.security(symbol22, 'D', close)
asset23 = request.security(symbol23, 'D', close)
asset24 = request.security(symbol24, 'D', close)
asset25 = request.security(symbol25, 'D', close)
asset26 = request.security(symbol26, 'D', close)
asset27 = request.security(symbol27, 'D', close)
asset28 = request.security(symbol28, 'D', close)
asset29 = request.security(symbol29, 'D', close)
asset30 = request.security(symbol30, 'D', close)
asset31 = request.security(symbol31, 'D', close)
asset32 = request.security(symbol32, 'D', close)
asset33 = request.security(symbol33, 'D', close)
asset34 = request.security(symbol34, 'D', close)
asset35 = request.security(symbol35, 'D', close)
asset36 = request.security(symbol36, 'D', close)
// ==================== REST OF SCRIPT ====================
mainDisplayNames = array.from(str.replace_all(str.substring(symbolINDEX, str.pos(symbolINDEX, ":") + 1), "USD", ""), str.replace_all(str.substring(symbolINDEX2, str.pos(symbolINDEX2, ":") + 1), "USD", ""), str.replace_all(str.substring(symbolMAIN, str.pos(symbolMAIN, ":") + 1), "USD", ""), str.replace_all(str.substring(symbolMAIN2, str.pos(symbolMAIN2, ":") + 1), "USD", ""))
displayNames = array.from(str.replace_all(str.substring(symbol1, str.pos(symbol1, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol2, str.pos(symbol2, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol3, str.pos(symbol3, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol4, str.pos(symbol4, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol5, str.pos(symbol5, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol6, str.pos(symbol6, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol7, str.pos(symbol7, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol8, str.pos(symbol8, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol9, str.pos(symbol9, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol10, str.pos(symbol10, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol11, str.pos(symbol11, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol12, str.pos(symbol12, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol13, str.pos(symbol13, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol14, str.pos(symbol14, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol15, str.pos(symbol15, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol16, str.pos(symbol16, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol17, str.pos(symbol17, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol18, str.pos(symbol18, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol19, str.pos(symbol19, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol20, str.pos(symbol20, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol21, str.pos(symbol21, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol22, str.pos(symbol22, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol23, str.pos(symbol23, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol24, str.pos(symbol24, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol25, str.pos(symbol25, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol26, str.pos(symbol26, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol27, str.pos(symbol27, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol28, str.pos(symbol28, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol29, str.pos(symbol29, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol30, str.pos(symbol30, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol31, str.pos(symbol31, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol32, str.pos(symbol32, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol33, str.pos(symbol33, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol34, str.pos(symbol34, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol35, str.pos(symbol35, ":") + 1), "USD", ""), str.replace_all(str.substring(symbol36, str.pos(symbol36, ":") + 1), "USD", ""))
// ==================== CALCULATION FUNCTIONS ====================
calcZScore(source, lookback) =>
mean = ta.sma(source, lookback)
stdDev = ta.stdev(source, lookback)
zScore = stdDev > 0 ? (source - mean) / stdDev : 0
math.max(-3, math.min(3, zScore))
// ==================== RSI CALCULATIONS ====================
// Main assets
rsiINDEX = ta.rsi(total, rsi_length)
rsiINDEX2 = ta.rsi(others, rsi_length)
rsiMAIN1 = ta.rsi(btc, rsi_length)
rsiMAIN2 = ta.rsi(eth, rsi_length)
// All crypto RSIs
rsi_1 = ta.rsi(asset1, rsi_length)
rsi_2 = ta.rsi(asset2, rsi_length)
rsi_3 = ta.rsi(asset3, rsi_length)
rsi_4 = ta.rsi(asset4, rsi_length)
rsi_5 = ta.rsi(asset5, rsi_length)
rsi_6 = ta.rsi(asset6, rsi_length)
rsi_7 = ta.rsi(asset7, rsi_length)
rsi_8 = ta.rsi(asset8, rsi_length)
rsi_9 = ta.rsi(asset9, rsi_length)
rsi_10 = ta.rsi(asset10, rsi_length)
rsi_11 = ta.rsi(asset11, rsi_length)
rsi_12 = ta.rsi(asset12, rsi_length)
rsi_13 = ta.rsi(asset13, rsi_length)
rsi_14 = ta.rsi(asset14, rsi_length)
rsi_15 = ta.rsi(asset15, rsi_length)
rsi_16 = ta.rsi(asset16, rsi_length)
rsi_17 = ta.rsi(asset17, rsi_length)
rsi_18 = ta.rsi(asset18, rsi_length)
rsi_19 = ta.rsi(asset19, rsi_length)
rsi_20 = ta.rsi(asset20, rsi_length)
rsi_21 = ta.rsi(asset21, rsi_length)
rsi_22 = ta.rsi(asset22, rsi_length)
rsi_23 = ta.rsi(asset23, rsi_length)
rsi_24 = ta.rsi(asset24, rsi_length)
rsi_25 = ta.rsi(asset25, rsi_length)
rsi_26 = ta.rsi(asset26, rsi_length)
rsi_27 = ta.rsi(asset27, rsi_length)
rsi_28 = ta.rsi(asset28, rsi_length)
rsi_29 = ta.rsi(asset29, rsi_length)
rsi_30 = ta.rsi(asset30, rsi_length)
rsi_31 = ta.rsi(asset31, rsi_length)
rsi_32 = ta.rsi(asset32, rsi_length)
rsi_33 = ta.rsi(asset33, rsi_length)
rsi_34 = ta.rsi(asset34, rsi_length)
rsi_35 = ta.rsi(asset35, rsi_length)
rsi_36 = ta.rsi(asset36, rsi_length)
// ==================== Z-SCORE CALCULATIONS ====================
// Main assets
zScoreINDEX = calcZScore(total, Z_score_L)
zScoreINDEX2 = calcZScore(others, Z_score_L)
zScoreMAIN1 = calcZScore(btc, Z_score_L)
zScoreMAIN2 = calcZScore(eth, Z_score_L)
// All crypto Z-scores
zScore_1 = calcZScore(asset1, Z_score_L)
zScore_2 = calcZScore(asset2, Z_score_L)
zScore_3 = calcZScore(asset3, Z_score_L)
zScore_4 = calcZScore(asset4, Z_score_L)
zScore_5 = calcZScore(asset5, Z_score_L)
zScore_6 = calcZScore(asset6, Z_score_L)
zScore_7 = calcZScore(asset7, Z_score_L)
zScore_8 = calcZScore(asset8, Z_score_L)
zScore_9 = calcZScore(asset9, Z_score_L)
zScore_10 = calcZScore(asset10, Z_score_L)
zScore_11 = calcZScore(asset11, Z_score_L)
zScore_12 = calcZScore(asset12, Z_score_L)
zScore_13 = calcZScore(asset13, Z_score_L)
zScore_14 = calcZScore(asset14, Z_score_L)
zScore_15 = calcZScore(asset15, Z_score_L)
zScore_16 = calcZScore(asset16, Z_score_L)
zScore_17 = calcZScore(asset17, Z_score_L)
zScore_18 = calcZScore(asset18, Z_score_L)
zScore_19 = calcZScore(asset19, Z_score_L)
zScore_20 = calcZScore(asset20, Z_score_L)
zScore_21 = calcZScore(asset21, Z_score_L)
zScore_22 = calcZScore(asset22, Z_score_L)
zScore_23 = calcZScore(asset23, Z_score_L)
zScore_24 = calcZScore(asset24, Z_score_L)
zScore_25 = calcZScore(asset25, Z_score_L)
zScore_26 = calcZScore(asset26, Z_score_L)
zScore_27 = calcZScore(asset27, Z_score_L)
zScore_28 = calcZScore(asset28, Z_score_L)
zScore_29 = calcZScore(asset29, Z_score_L)
zScore_30 = calcZScore(asset30, Z_score_L)
zScore_31 = calcZScore(asset31, Z_score_L)
zScore_32 = calcZScore(asset32, Z_score_L)
zScore_33 = calcZScore(asset33, Z_score_L)
zScore_34 = calcZScore(asset34, Z_score_L)
zScore_35 = calcZScore(asset35, Z_score_L)
zScore_36 = calcZScore(asset36, Z_score_L)
// ==================== ENHANCED SCATTER FUNCTION ====================
scatter(float rsiValue, float zScore, color clr, string symbol, int scale, string category = 'other') =>
if barstate.islast
int xPosition = bar_index - math.round(100 - rsiValue)
float yPosition = zScore
labelStyle = category == 'INDEX' ? label.style_circle : category == 'MAIN' ? label.style_diamond : label.style_label_center
labelSize = category == 'INDEX' ? size.large : category == 'MAIN' ? size.normal : size.small
var label rsiLabel = label.new(x = xPosition, y = yPosition, text = symbol, color = clr, style = labelStyle, size = labelSize)
emoji = rsiValue > 80 ? '🔥' : rsiValue < 20 ? '❄️' : ''
labelText = emoji + symbol + '\n' + 'RSI: ' + str.tostring(math.round(rsiValue, 1)) + '\nZ: ' + str.tostring(math.round(zScore, 1))
label.set_text(rsiLabel, labelText)
label.set_x(rsiLabel, xPosition)
label.set_y(rsiLabel, yPosition)
label.set_color(rsiLabel, clr)
label.set_textcolor(rsiLabel, color.white)
// ==================== BACKGROUND VISUALIZATION ====================
float zScoreMin = -3
float zScoreMax = 3
int xFirstBar = bar_index[1] - 100
int xLastBar = bar_index[1]
int xMidBar = bar_index[1] - 50
var box gradientBox1 = na
var box gradientBox2 = na
var box gradientBox3 = na
var box gradientBox4 = na
var box bgBox = na
if showGradientBg
box.delete(gradientBox1[1])
box.delete(gradientBox2[1])
box.delete(gradientBox3[1])
box.delete(gradientBox4[1])
box.delete(bgBox[1])
// Redraw gradient boxes
gradientBox1 := box.new(left = xFirstBar, top = zScoreMax, right = xLastBar, bottom = zScoreMax * 0.5, bgcolor = color.new(#1a1f2e, 80), border_color = na)
gradientBox2 := box.new(left = xFirstBar, top = zScoreMax * 0.5, right = xLastBar, bottom = 0, bgcolor = color.new(#151923, 80), border_color = na)
gradientBox3 := box.new(left = xFirstBar, top = 0, right = xLastBar, bottom = zScoreMin * 0.5, bgcolor = color.new(#11141c, 80), border_color = na)
gradientBox4 := box.new(left = xFirstBar, top = zScoreMin * 0.5, right = xLastBar, bottom = zScoreMin, bgcolor = color.new(#0d0f15, 80), border_color = na)
gradientBox4
else
box.delete(gradientBox1[1])
box.delete(gradientBox2[1])
box.delete(gradientBox3[1])
box.delete(gradientBox4[1])
box.delete(bgBox[1])
bgBox := box.new(left = xFirstBar, top = zScoreMax, right = xLastBar, bottom = zScoreMin, bgcolor = color.new(#0a0a0a, 95), border_color = color.new(#2a2a2a, 80))
bgBox
// Professional grid lines
var line hMidline = line.new(x1 = xFirstBar, y1 = 0, x2 = xLastBar, y2 = 0, width = 1, color = color.new(#404040, 50), style = line.style_solid)
var line vMidline = line.new(x1 = xMidBar, y1 = zScoreMin, x2 = xMidBar, y2 = zScoreMax, width = 1, color = color.new(#404040, 50), style = line.style_solid)
// Subtle additional grid lines
var line hLine1 = line.new(x1 = xFirstBar, y1 = 1.5, x2 = xLastBar, y2 = 1.5, width = 1, color = color.new(#303030, 80), style = line.style_dotted)
var line hLine2 = line.new(x1 = xFirstBar, y1 = -1.5, x2 = xLastBar, y2 = -1.5, width = 1, color = color.new(#303030, 80), style = line.style_dotted)
var line vLine1 = line.new(x1 = bar_index[1] - 25, y1 = zScoreMin, x2 = bar_index[1] - 25, y2 = zScoreMax, width = 1, color = color.new(#303030, 80), style = line.style_dotted)
var line vLine2 = line.new(x1 = bar_index[1] - 75, y1 = zScoreMin, x2 = bar_index[1] - 75, y2 = zScoreMax, width = 1, color = color.new(#303030, 80), style = line.style_dotted)
// Update all lines
line.set_x1(hMidline, xFirstBar)
line.set_x2(hMidline, xLastBar)
line.set_x1(vMidline, xMidBar)
line.set_x2(vMidline, xMidBar)
line.set_x1(hLine1, xFirstBar)
line.set_x2(hLine1, xLastBar)
line.set_x1(hLine2, xFirstBar)
line.set_x2(hLine2, xLastBar)
line.set_x1(vLine1, bar_index[1] - 25)
line.set_x2(vLine1, bar_index[1] - 25)
line.set_x1(vLine2, bar_index[1] - 75)
line.set_x2(vLine2, bar_index[1] - 75)
// ==================== DANGER ZONES ====================
if showDangerZones
var box dangerZone1 = box.new(left = bar_index[1] - math.round(100 - dangerRSIHigh), top = zScoreMax, right = xLastBar, bottom = 1, bgcolor = color.new(#cc2936, 94), border_color = color.new(#cc2936, 85))
var box dangerZone2 = box.new(left = xFirstBar, top = -1, right = bar_index[1] - math.round(100 - dangerRSILow), bottom = zScoreMin, bgcolor = color.new(#26a653, 94), border_color = color.new(#26a653, 85))
box.set_left(dangerZone1, bar_index[1] - math.round(100 - dangerRSIHigh))
box.set_right(dangerZone1, xLastBar)
box.set_right(dangerZone2, bar_index[1] - math.round(100 - dangerRSILow))
box.set_left(dangerZone2, xFirstBar)
// ==================== QUADRANT LABELS ====================
var label overboughtLabel = na
var label recoveryLabel = na
var label oversoldLabel = na
var label consolidationLabel = na
// Quadrant labels
if showQuadrantLabels and barstate.islast
// Delete previous quadrant labels to avoid overlap
label.delete(overboughtLabel[1])
label.delete(recoveryLabel[1])
label.delete(oversoldLabel[1])
label.delete(consolidationLabel[1])
overboughtLabel := label.new(x = bar_index[1] - 5, y = 2.7, text = 'Overbought\nExtended', style = label.style_label_center, color = color.new(#cc2936, 85), textcolor = color.new(color.white, 20), size = size.normal)
recoveryLabel := label.new(x = bar_index[1] - 94, y = 2.7, text = 'Recovery\nPhase', style = label.style_label_center, color = color.new(#ff9800, 85), textcolor = color.new(color.white, 20), size = size.normal)
oversoldLabel := label.new(x = bar_index[1] - 94, y = -2.7, text = 'Oversold\nCompressed', style = label.style_label_center, color = color.new(#2196f3, 85), textcolor = color.new(color.white, 20), size = size.normal)
consolidationLabel := label.new(x = bar_index[1] - 5, y = -2.7, text = 'Strong\nConsolidation', style = label.style_label_center, color = color.new(#26a653, 85), textcolor = color.new(color.white, 20), size = size.normal)
consolidationLabel
// ==================== SCATTER PLOT ====================
if barstate.islast
if showMainAssets
scatter(rsiINDEX[1], zScoreINDEX[1], color.new(#7c3aed, 5),array.get(mainDisplayNames,0), BarScale, 'INDEX')
scatter(rsiINDEX2[1], zScoreINDEX2[1], color.new(#ea580c, 5),array.get(mainDisplayNames,1), BarScale, 'INDEX')
scatter(rsiMAIN1[1], zScoreMAIN1[1], color.new(#f59e0b, 20),array.get(mainDisplayNames,2), BarScale, 'MAIN')
scatter(rsiMAIN2[1], zScoreMAIN2[1], color.new(#3b82f6, 20),array.get(mainDisplayNames,3), BarScale, 'MAIN')
scatter(rsi_1[1], zScore_1[1], color.new(#6366f1, 30), array.get(displayNames, 0), BarScale)
scatter(rsi_2[1], zScore_2[1], color.new(#8b5cf6, 30), array.get(displayNames, 1), BarScale)
scatter(rsi_3[1], zScore_3[1], color.new(#06b6d4, 30), array.get(displayNames, 2), BarScale)
scatter(rsi_4[1], zScore_4[1], color.new(#0891b2, 30), array.get(displayNames, 3), BarScale)
scatter(rsi_5[1], zScore_5[1], color.new(#d97706, 30), array.get(displayNames, 4), BarScale)
scatter(rsi_6[1], zScore_6[1], color.new(#dc2626, 30), array.get(displayNames, 5), BarScale)
scatter(rsi_7[1], zScore_7[1], color.new(#c2410c, 30), array.get(displayNames, 6), BarScale)
scatter(rsi_8[1], zScore_8[1], color.new(#be123c, 30), array.get(displayNames, 7), BarScale)
scatter(rsi_9[1], zScore_9[1], color.new(#be185d, 30), array.get(displayNames, 8), BarScale)
scatter(rsi_10[1], zScore_10[1], color.new(#4f46e5, 30), array.get(displayNames, 9), BarScale)
scatter(rsi_11[1], zScore_11[1], color.new(#7c3aed, 30), array.get(displayNames, 10), BarScale)
scatter(rsi_12[1], zScore_12[1], color.new(#e11d48, 30), array.get(displayNames, 11), BarScale)
scatter(rsi_13[1], zScore_13[1], color.new(#0ea5e9, 30), array.get(displayNames, 12), BarScale)
scatter(rsi_14[1], zScore_14[1], color.new(#16a34a, 30), array.get(displayNames, 13), BarScale)
scatter(rsi_15[1], zScore_15[1], color.new(#64748b, 40), array.get(displayNames, 14), BarScale)
scatter(rsi_16[1], zScore_16[1], color.new(#475569, 40), array.get(displayNames, 15), BarScale)
scatter(rsi_17[1], zScore_17[1], color.new(#334155, 40), array.get(displayNames, 16), BarScale)
scatter(rsi_18[1], zScore_18[1], color.new(#1e293b, 40), array.get(displayNames, 17), BarScale)
scatter(rsi_19[1], zScore_19[1], color.new(#0f172a, 40), array.get(displayNames, 18), BarScale)
scatter(rsi_20[1], zScore_20[1], color.new(#581c87, 40), array.get(displayNames, 19), BarScale)
scatter(rsi_21[1], zScore_21[1], color.new(#6b21a8, 40), array.get(displayNames, 20), BarScale)
scatter(rsi_22[1], zScore_22[1], color.new(#86198f, 40), array.get(displayNames, 21), BarScale)
scatter(rsi_23[1], zScore_23[1], color.new(#a21caf, 40), array.get(displayNames, 22), BarScale)
scatter(rsi_24[1], zScore_24[1], color.new(#134e4a, 40), array.get(displayNames, 23), BarScale)
scatter(rsi_25[1], zScore_25[1], color.new(#115e59, 40), array.get(displayNames, 24), BarScale)
scatter(rsi_26[1], zScore_26[1], color.new(#0f766e, 40), array.get(displayNames, 25), BarScale)
scatter(rsi_27[1], zScore_27[1], color.new(#0d9488, 40), array.get(displayNames, 26), BarScale)
scatter(rsi_28[1], zScore_28[1], color.new(#14b8a6, 40), array.get(displayNames, 27), BarScale)
scatter(rsi_29[1], zScore_29[1], color.new(#1e3a8a, 40), array.get(displayNames, 28), BarScale)
scatter(rsi_30[1], zScore_30[1], color.new(#1e40af, 40), array.get(displayNames, 29), BarScale)
scatter(rsi_31[1], zScore_31[1], color.new(#2563eb, 40), array.get(displayNames, 30), BarScale)
scatter(rsi_32[1], zScore_32[1], color.new(#0284c7, 40), array.get(displayNames, 31), BarScale)
scatter(rsi_33[1], zScore_33[1], color.new(#0369a1, 40), array.get(displayNames, 32), BarScale)
scatter(rsi_34[1], zScore_34[1], color.new(#075985, 40), array.get(displayNames, 33), BarScale)
scatter(rsi_35[1], zScore_35[1], color.new(#0c4a6e, 40), array.get(displayNames, 34), BarScale)
scatter(rsi_36[1], zScore_36[1], color.new(#164e63, 40), array.get(displayNames, 35), BarScale)
scatter(rsi_30[1], zScore_30[1], color.new(#003b84, 20), array.get(displayNames, 29), BarScale)
scatter(rsi_31[1], zScore_31[1], color.new(#00f0ff, 20), array.get(displayNames, 30), BarScale)
scatter(rsi_32[1], zScore_32[1], color.new(#3ac1d0, 20), array.get(displayNames, 31), BarScale)
scatter(rsi_33[1], zScore_33[1], color.new(#000000, 20), array.get(displayNames, 32), BarScale)
scatter(rsi_34[1], zScore_34[1], color.new(#6f4cff, 20), array.get(displayNames, 33), BarScale)
scatter(rsi_35[1], zScore_35[1], color.new(#22a1f0, 20), array.get(displayNames, 34), BarScale)
scatter(rsi_36[1], zScore_36[1], color.new(#000000, 20), array.get(displayNames, 35), BarScale)
// ==================== CROWDING ANALYTICS PANEL ====================
totalAssets = (showMainAssets ? 4 : 0) + 36
fomoCount = 0
fearCount = 0
recoveryCount = 0
strengthCount = 0
if showCrowdingPanel
var table panel = table.new(position.top_right, 3, 8, bgcolor = color.new(#0d1117, 80), border_width = 1, border_color = color.new(#30363d, 50))
if barstate.islast
// Title
table.cell(panel, 0, 0, '🎯 CROWDING ANALYTICS', text_color = #58a6ff, text_size = size.normal, bgcolor = color.new(#161b22, 50))
table.merge_cells(panel, 0, 0, 2, 0)
// Count main assets
if showMainAssets
// BTC
if rsiMAIN1 > 50 and zScoreMAIN1 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsiMAIN1 <= 50 and zScoreMAIN1 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsiMAIN1 <= 50 and zScoreMAIN1 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
// ETH
if rsiMAIN2 > 50 and zScoreMAIN2 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsiMAIN2 <= 50 and zScoreMAIN2 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsiMAIN2 <= 50 and zScoreMAIN2 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
// TOTAL
if rsiINDEX > 50 and zScoreINDEX > 0
fomoCount := fomoCount + 1
fomoCount
else if rsiINDEX <= 50 and zScoreINDEX > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsiINDEX <= 50 and zScoreINDEX <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
// OTHERS
if rsiINDEX2 > 50 and zScoreINDEX2 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsiINDEX2 <= 50 and zScoreINDEX2 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsiINDEX2 <= 50 and zScoreINDEX2 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
if rsi_1 > 50 and zScore_1 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsi_1 <= 50 and zScore_1 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsi_1 <= 50 and zScore_1 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
if rsi_2 > 50 and zScore_2 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsi_2 <= 50 and zScore_2 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsi_2 <= 50 and zScore_2 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
if rsi_3 > 50 and zScore_3 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsi_3 <= 50 and zScore_3 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsi_3 <= 50 and zScore_3 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
if rsi_4 > 50 and zScore_4 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsi_4 <= 50 and zScore_4 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsi_4 <= 50 and zScore_4 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
if rsi_5 > 50 and zScore_5 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsi_5 <= 50 and zScore_5 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsi_5 <= 50 and zScore_5 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
if rsi_6 > 50 and zScore_6 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsi_6 <= 50 and zScore_6 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsi_6 <= 50 and zScore_6 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
if rsi_7 > 50 and zScore_7 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsi_7 <= 50 and zScore_7 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsi_7 <= 50 and zScore_7 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
if rsi_8 > 50 and zScore_8 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsi_8 <= 50 and zScore_8 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsi_8 <= 50 and zScore_8 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
if rsi_9 > 50 and zScore_9 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsi_9 <= 50 and zScore_9 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsi_9 <= 50 and zScore_9 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
if rsi_10 > 50 and zScore_10 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsi_10 <= 50 and zScore_10 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsi_10 <= 50 and zScore_10 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
if rsi_11 > 50 and zScore_11 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsi_11 <= 50 and zScore_11 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsi_11 <= 50 and zScore_11 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
if rsi_12 > 50 and zScore_12 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsi_12 <= 50 and zScore_12 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsi_12 <= 50 and zScore_12 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
if rsi_13 > 50 and zScore_13 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsi_13 <= 50 and zScore_13 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsi_13 <= 50 and zScore_13 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
if rsi_14 > 50 and zScore_14 > 0
fomoCount := fomoCount + 1
fomoCount
else if rsi_14 <= 50 and zScore_14 > 0
recoveryCount := recoveryCount + 1
recoveryCount
else if rsi_14 <= 50 and zScore_14 <= 0
fearCount := fearCount + 1
fearCount
else
strengthCount := strengthCount + 1
strengthCount
// Calculate percentages
fomoPct = totalAssets > 0 ? fomoCount / totalAssets * 100 : 0
fearPct = totalAssets > 0 ? fearCount / totalAssets * 100 : 0
recoveryPct = totalAssets > 0 ? recoveryCount / totalAssets * 100 : 0
strengthPct = totalAssets > 0 ? strengthCount / totalAssets * 100 : 0
// Find dominant zone
maxPct = math.max(fomoPct, fearPct, recoveryPct, strengthPct)
dominantZone = fomoPct == maxPct ? 'FOMO' : fearPct == maxPct ? 'FEAR' : recoveryPct == maxPct ? 'RECOVERY' : 'STRENGTH'
// Overall market score (0-100)
marketScore = strengthPct * 2 + recoveryPct - fearPct - fomoPct * 2 + 50
marketScore := math.max(0, math.min(100, marketScore))
// Display metrics
table.cell(panel, 0, 1, 'Market Score', text_color = #c9d1d9, text_size = size.normal)
scoreColor = marketScore > 70 ? #00ff88 : marketScore > 30 ? #ffa500 : #ff4444
table.cell(panel, 1, 1, str.tostring(math.round(marketScore)) + '/100', text_color = scoreColor, text_size = size.large)
table.merge_cells(panel, 1, 1, 2, 1)
table.cell(panel, 0, 2, 'Dominant Zone', text_color = #c9d1d9, text_size = size.normal)
table.cell(panel, 1, 2, dominantZone, text_color = #58a6ff, text_size = size.normal)
table.merge_cells(panel, 1, 2, 2, 2)
// Zone distribution
table.cell(panel, 0, 3, 'Zone Distribution', text_color = #c9d1d9, text_size = size.normal)
table.merge_cells(panel, 0, 3, 2, 3)
table.cell(panel, 0, 4, '🔥 FOMO', text_color = #ff4444, text_size = size.small)
table.cell(panel, 1, 4, str.tostring(math.round(fomoPct, 1)) + '%', text_color = #ff4444, text_size = size.small)
table.cell(panel, 2, 4, '(' + str.tostring(fomoCount) + ')', text_color = #8b949e, text_size = size.small)
table.cell(panel, 0, 5, '📈 Recovery', text_color = #ffa500, text_size = size.small)
table.cell(panel, 1, 5, str.tostring(math.round(recoveryPct, 1)) + '%', text_color = #ffa500, text_size = size.small)
table.cell(panel, 2, 5, '(' + str.tostring(recoveryCount) + ')', text_color = #8b949e, text_size = size.small)
table.cell(panel, 0, 6, '❄️ Fear', text_color = #2196f3, text_size = size.small)
table.cell(panel, 1, 6, str.tostring(math.round(fearPct, 1)) + '%', text_color = #2196f3, text_size = size.small)
table.cell(panel, 2, 6, '(' + str.tostring(fearCount) + ')', text_color = #8b949e, text_size = size.small)
table.cell(panel, 0, 7, '💪 Strength', text_color = #00ff88, text_size = size.small)
table.cell(panel, 1, 7, str.tostring(math.round(strengthPct, 1)) + '%', text_color = #00ff88, text_size = size.small)
table.cell(panel, 2, 7, '(' + str.tostring(strengthCount) + ')', text_color = #8b949e, text_size = size.small)
// ==================== ALERTS ====================
// Calculate percentages
fomoPct = totalAssets > 0 ? (fomoCount / totalAssets) * 100 : 0
fearPct = totalAssets > 0 ? (fearCount / totalAssets) * 100 : 0
recoveryPct = totalAssets > 0 ? (recoveryCount / totalAssets) * 100 : 0
strengthPct = totalAssets > 0 ? (strengthCount / totalAssets) * 100 : 0
// ==================== ALERTS ====================
if barstate.isconfirmed
if fomoPct >= crowdingThreshold
alert("🔥 Crowding Alert: FOMO levels have reached " + str.tostring(math.round(fomoPct, 1)) + "%.", alert.freq_once_per_bar_close)
if fearPct >= crowdingThreshold
alert("❄️ Crowding Alert: Fear levels have reached " + str.tostring(math.round(fearPct, 1)) + "%.", alert.freq_once_per_bar_close)
if recoveryPct >= crowdingThreshold
alert("📈 Crowding Alert: Recovery levels have reached " + str.tostring(math.round(recoveryPct, 1)) + "%.", alert.freq_once_per_bar_close)
if strengthPct >= crowdingThreshold
alert("💪 Crowding Alert: Strength levels have reached " + str.tostring(math.round(strengthPct, 1)) + "%.", alert.freq_once_per_bar_close)
Show all 752 lines