Divergences Refurbished
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// @Thanks and credits:
//      © LonesomeTheBlue
// Modified by © andre_007
// @description This is a script forked from LonesomeTheBlue's Divergence for Many Indicators v4.
//              It is a script that checks for divergence between price and many indicators.
//              in this version, I added more indicators to check for divergence.
//              I also added 40 symbols to check for divergence.
//              More info on the original script can be found here:
//              https://www.tradingview.com/script/n8AGnIZd-Divergence-for-Many-Indicators-v4/

//@version=5
indicator('Divergences Refurbished', overlay=true, max_bars_back=1000, max_lines_count=400, max_labels_count=400)

import andre_007/MomentumIndicators/2 as MI
import andre_007/VolumeIndicators/3 as VI
import andre_007/TrendIndicators/3 as TI
import andre_007/VolatilityIndicators/8 as VOL

// Constants
// -------------------------------------------------------------------------------------------------------------- {
// Groups
var string GROUP_DIV = 'Divergence Settings'
var string GROUP_IND = 'Indicators to Check'
var string GROUP_SYM = 'Symbols to Check'
var string GROUP_STYLE = 'Colors and Styles'

var string GROUP_MACD_PARAM = 'MACD Parameters'
var string GROUP_RSI_PARAM = 'RSI Parameters'
var string GROUP_STOC_PARAM = 'Stochastic Parameters'
var string GROUP_CCI_PARAM = 'CCI Parameters'
var string GROUP_MOM_PARAM = 'Momentum Parameters'
var string GROUP_CMF_PARAM = 'Chaikin Money Flow Parameters'
var string GROUP_OBV_PARAM = 'OBV Parameters'
var string GROUP_MFI_PARAM = 'Money Flow Index Parameters'
var string GROUP_VOLUMEOSC_PARAM = 'Volume Oscillator Parameters'
var string GROUP_PVT_PARAM = 'Price Volume Trend Parameters'
var string GROUP_ULTOSC_PARAM = 'Ultimate Oscillator Parameters'
var string GROUP_FISHER_PARAM = 'Fisher Transform Parameters'
var string GROUP_ZSCORE_PARAM = 'Z-Score/T-Score Parameters'

// Moving Average Types
var string TYPE_MA_TOOLTIP = '1 - Simple Moving Average\n' +
 '2 - Exponential Moving Average\n' +
 '3 - Weighted Moving Average\n' +
 '4 - Volume Weighted Moving Average\n' +
 '5 - Arnaud Legoux Moving Average\n' +
 '6 - Hull Moving Average\n' +
 '7 - Least Squares Moving Average\n' +
 '8 - Relative Moving Average\n' +
 '9 - Median'
// -------------------------------------------------------------------------------------------------------------- }

// Divergence settings
// -------------------------------------------------------------------------------------------------------------- {
prd = input.int(defval=5, title='Pivot Period', minval=1, maxval=50, group=GROUP_DIV)

source = input.string(defval='High/Low', title='Source for Pivot Points', options=['Close', 'High/Low'], group=GROUP_DIV)

searchdiv = input.string(defval='Regular/Hidden', title='Divergence Type', options=['Regular', 'Hidden', 'Regular/Hidden'], group=GROUP_DIV)

showindis = input.string(defval='Don\'t Show', title='Show Indicator Names', options=['Full', 'Abbreviation', 'Don\'t Show'], group=GROUP_DIV)

showlimit = input.int(1, title='Minimum Number of Divergence', minval=1, maxval=11, group=GROUP_DIV)
maxpp = input.int(defval=3, title='Maximum Pivot Points to Check', minval=1, maxval=20, group=GROUP_DIV)
maxbars = input.int(defval=100, title='Maximum Bars to Check', minval=30, maxval=200, group=GROUP_DIV)

shownum = input(defval=true, title='Show Divergence Number', group=GROUP_DIV)
showlast = input(defval=false, title='Show Only Last Divergence', group=GROUP_DIV)

dontconfirm = input(defval=true, title='Don\'t Wait for Confirmation', group=GROUP_DIV)

showlines = input(defval=true, title='Show Divergence Lines', group=GROUP_DIV)
showpivot = input(defval=false, title='Show Pivot Points', group=GROUP_DIV)

show_support_resistance = input(defval=true, title='Show Support/Resistance', group=GROUP_DIV, inline='1', tooltip='Show Support/Resistance for each divergence.')
support_resistance_bars = input.int(defval=13, title='Support/Resistance Length', minval=1, group=GROUP_DIV,
  inline='2', tooltip='Number of bars to plot Support/Resistance lines.')
support_resistance_extend = input.string(defval='None', title='Extend Support/Resistance', options=['None', 'Left', 'Right', 'Both'], group=GROUP_DIV,
  inline='2', tooltip='Extend Support/Resistance lines to the left, right, both or none.')
// -------------------------------------------------------------------------------------------------------------- }

// Style settings
// -------------------------------------------------------------------------------------------------------------- {
pos_reg_div_col = input(defval=#009606, title='Positive Regular Divergence', group=GROUP_STYLE)
neg_reg_div_col = input(defval=#f23645, title='Negative Regular Divergence', group=GROUP_STYLE)
pos_hid_div_col = input(defval=#2962ff, title='Positive Hidden Divergence', group=GROUP_STYLE)
neg_hid_div_col = input(defval=#9c27b0, title='Negative Hidden Divergence', group=GROUP_STYLE)

pos_div_text_col = input(defval=#000000, title='Positive Divergence Text Color', group=GROUP_STYLE)
neg_div_text_col = input(defval=#000000, title='Negative Divergence Text Color', group=GROUP_STYLE)
reg_div_l_style_ = input.string(defval='Solid', title='Regular Divergence Line Style', options=['Solid', 'Dashed', 'Dotted'], group=GROUP_STYLE)
hid_div_l_style_ = input.string(defval='Dashed', title='Hdden Divergence Line Style', options=['Solid', 'Dashed', 'Dotted'], group=GROUP_STYLE)

reg_div_l_width = input.int(defval=2, title='Regular Divergence Line Width', minval=1, maxval=5, group=GROUP_STYLE)
hid_div_l_width = input.int(defval=1, title='Hidden Divergence Line Width', minval=1, maxval=5, group=GROUP_STYLE)

char_separator = input.string(defval='\n', title='Character Separator', group=GROUP_STYLE)
show_tooltip = input(defval=true, title='Show Tooltip', group=GROUP_STYLE)
yShiftPercent = input(defval=0.0, title='Shift labels in y-axis (%)', group=GROUP_STYLE)
// -------------------------------------------------------------------------------------------------------------- }

// Indicator to check
// -------------------------------------------------------------------------------------------------------------- {
calcmacd = input(defval=true, title='MACD', group=GROUP_IND, inline='macd')
calcmacd_text = input.string(defval='🤥', title='', inline='macd', group=GROUP_IND)

calcmacda = input(defval=true, title='MACD Histogram', group=GROUP_IND, inline='macda')
calcmacda_text = input.string(defval='🤥', title='', inline='macda', group=GROUP_IND)

calcvwmacd = input(true, title='Volume Weighted  MACD', group=GROUP_IND, inline='vwmacd')
calcvwmacd_text = input.string(defval='🤥', title='', inline='vwmacd', group=GROUP_IND)

calcrsi = input(defval=true, title='RSI', group=GROUP_IND, inline='rsi')
calcrsi_text = input.string(defval='🤥', title='', inline='rsi', group=GROUP_IND)

calcstoc = input(defval=true, title='Stochastic', group=GROUP_IND, inline='stoc')
calcstoc_text = input.string(defval='🤥', title='', inline='stoc', group=GROUP_IND)

calccci = input(defval=true, title='CCI', group=GROUP_IND, inline='cci')
calccci_text = input.string(defval='🤥', title='', inline='cci', group=GROUP_IND)

calcmom = input(defval=true, title='Momentum', group=GROUP_IND, inline='mom')
calcmom_text = input.string(defval='🤥', title='', inline='mom', group=GROUP_IND)

calcobv = input(defval=true, title='OBV', group=GROUP_IND, inline='obv')
calcobv_text = input.string(defval='🤥', title='', inline='obv', group=GROUP_IND)

calccmf = input(true, title='Chaikin Money Flow', group=GROUP_IND, inline='cmf')
calccmf_text = input.string(defval='🤥', title='', inline='cmf', group=GROUP_IND)

calcmfi = input(true, title='Money Flow Index', group=GROUP_IND, inline='mfi')
calcmfi_text = input.string(defval='🤥', title='', inline='mfi', group=GROUP_IND)

calcStochRSI = input(true, title='Stochastic RSI', group=GROUP_IND, inline='stochrsi')
calcStochRSI_text = input.string(defval='🤥', title='', inline='stochrsi', group=GROUP_IND)

calcVolumeOsc = input(true, title='Volume Oscillator', group=GROUP_IND, inline='volumeosc')
calcVolumeOsc_text = input.string(defval='🤥', title='', inline='volumeosc', group=GROUP_IND)

calcPVT = input(true, title='Price Volume Trend', group=GROUP_IND, inline='pvt')
calcPVT_text = input.string(defval='🤥', title='', inline='pvt', group=GROUP_IND)

calcUltimateOsc = input(true, title='Ultimate Oscillator', group=GROUP_IND, inline='ultosc')
calcUltimateOsc_text = input.string(defval='🤥', title='', inline='ultosc', group=GROUP_IND)

calcFisherTransform = input(true, title='Fisher Transform', group=GROUP_IND, inline='fisher')
calcFisherTransform_text = input.string(defval='🤥', title='', inline='fisher', group=GROUP_IND)

calcZscore = input(true, title='Z-Score/T-Score', group=GROUP_IND, inline='zscore')
calcZscore_text = input.string(defval='🤥', title='', inline='zscore', group=GROUP_IND)

calcExt_1 = input(false, title='', group=GROUP_IND, inline='ext1')
externalIndicator_1 = input(defval=close, title='External Indicator 1', group=GROUP_IND, inline='ext1')
externalIndicator_1_text = input.string(defval='External Indicator 1🔎', title='', inline='ext1', group=GROUP_IND)

calcExt_2 = input(false, title='', group=GROUP_IND, inline='ext2')
externalIndicator_2 = input(defval=close, title='External Indicator 2', group=GROUP_IND, inline='ext2')
externalIndicator_2_text = input.string(defval='External Indicator 2🔎', title='', inline='ext2', group=GROUP_IND)

calcExt_3 = input(false, title='', group=GROUP_IND, inline='ext3')
externalIndicator_3 = input(defval=close, title='External Indicator 3', group=GROUP_IND, inline='ext3')
externalIndicator_3_text = input.string(defval='External Indicator 3🔎', title='', inline='ext3', group=GROUP_IND)

calcExt_4 = input(false, title='', group=GROUP_IND, inline='ext4')
externalIndicator_4 = input(defval=close, title='External Indicator 4', group=GROUP_IND, inline='ext4')
externalIndicator_4_text = input.string(defval='External Indicator 4🔎', title='', inline='ext4', group=GROUP_IND)
// -------------------------------------------------------------------------------------------------------------- }

// Indicator parameters
// -------------------------------------------------------------------------------------------------------------- {
// MACD
macd_source = input.source(defval=close, title='MACD Source', group=GROUP_MACD_PARAM)
macd_fast = input.int(defval=12, title='MACD Fast Length', minval=1, maxval=50, group=GROUP_MACD_PARAM)
macd_slow = input.int(defval=26, title='MACD Slow Length', minval=1, maxval=50, group=GROUP_MACD_PARAM)
macd_signal = input.int(defval=9, title='MACD Signal Length', minval=1, maxval=50, group=GROUP_MACD_PARAM)
macd_type_ma = input.int(defval=1, title='MACD Type of Moving Average', minval=1, maxval=9, tooltip=TYPE_MA_TOOLTIP, group=GROUP_MACD_PARAM)

// RSI
rsi_source = input.source(defval=close, title='RSI Source', group=GROUP_RSI_PARAM)
rsi_length = input.int(defval=14, title='RSI Length', minval=1, maxval=50, group=GROUP_RSI_PARAM)

// Stochastic
stoc_source = input.source(defval=close, title='Stochastic Source', group=GROUP_STOC_PARAM)
stoc_k = input.int(defval=14, title='Stochastic K', minval=1, maxval=50, group=GROUP_STOC_PARAM)
stoc_d = input.int(defval=3, title='Stochastic D', minval=1, maxval=50, group=GROUP_STOC_PARAM)
stoc_dSmoothing = input.int(defval=3, title='Stochastic D Smoothing', minval=1, maxval=50, group=GROUP_STOC_PARAM)
stoc_type_ma = input.int(defval=1, title='Stochastic Type of Moving Average', minval=1, maxval=9, tooltip=TYPE_MA_TOOLTIP, group=GROUP_STOC_PARAM)

// CCI
cci_source = input.source(defval=close, title='CCI Source', group=GROUP_CCI_PARAM)
cci_length = input.int(defval=10, title='CCI Length', minval=1, maxval=50, group=GROUP_CCI_PARAM)
cci_type_ma = input.int(defval=1, title='CCI Type of Moving Average', minval=1, maxval=9, tooltip=TYPE_MA_TOOLTIP, group=GROUP_CCI_PARAM)

// Momentum
mom_source = input.source(defval=close, title='Momentum Source', group=GROUP_MOM_PARAM)
mom_length = input.int(defval=10, title='Momentum Length', minval=1, maxval=50, group=GROUP_MOM_PARAM)

// Chaikin Money Flow
cmf_length = input.int(defval=21, title='Chaikin Money Flow Length', minval=1, maxval=50, group=GROUP_CMF_PARAM)

// OBV
obv_source = input.source(defval=close, title='OBV Source', group=GROUP_OBV_PARAM)

// Money Flow Index
mfi_source = input.source(defval=close, title='Money Flow Index Source', group=GROUP_MFI_PARAM)
mfi_length = input.int(defval=14, title='Money Flow Index Length', minval=1, maxval=50, group=GROUP_MFI_PARAM)

// Volume Oscillator
sourceVolumeOsc = input(close, title='Volume Oscillator Source', group=GROUP_VOLUMEOSC_PARAM)
shortLengthVolumeOsc = input.int(5, title='Volume Oscillator Short Length', minval=1, group=GROUP_VOLUMEOSC_PARAM)
longLengthVolumeOsc = input.int(10, title='Volume Oscillator Long Length', minval=1, group=GROUP_VOLUMEOSC_PARAM)

// PVT
sourcePVT = input(close, title='Price Volume Trend Source', group=GROUP_PVT_PARAM)

// Ultimate Oscillator
ultosc_source = input.source(defval=close, title='Ultimate Oscillator Source', group=GROUP_ULTOSC_PARAM)
ultosc_length1 = input.int(defval=7, title='Ultimate Oscillator Fast Length', minval=1, maxval=50, group=GROUP_ULTOSC_PARAM)
ultosc_length2 = input.int(defval=14, title='Ultimate Oscillator Middle Length', minval=1, maxval=50, group=GROUP_ULTOSC_PARAM)
ultosc_length3 = input.int(defval=28, title='Ultimate Oscillator Slow Length', minval=1, maxval=50, group=GROUP_ULTOSC_PARAM)

// Fisher Transform
fisher_source = input.string(defval='High/Low', title='Fisher Transform Source', options=['Close', 'High/Low'], group=GROUP_FISHER_PARAM)
fisher_length = input.int(defval=10, title='Fisher Transform Length', minval=1, maxval=50, group=GROUP_FISHER_PARAM)

// Z-Score/T-Score
zscore_source = input.source(defval=hl2, title='Z-Score/T-Score Source', group=GROUP_ZSCORE_PARAM)
zscore_length = input.int(defval=21, title='Z-Score/T-Score Length for Standard Deviation', minval=1, maxval=50, group=GROUP_ZSCORE_PARAM)
zscore_mean_length = input.int(defval=21, title='Z-Score/T-Score Length for Mean', group=GROUP_ZSCORE_PARAM)
zscore_mean_type = input.int(defval=2, title='Z-Score/T-Score Type of Moving Average for Mean', minval=1, maxval=9, tooltip=TYPE_MA_TOOLTIP, group=GROUP_ZSCORE_PARAM)
// -------------------------------------------------------------------------------------------------------------- }

// Symbols to check
// -------------------------------------------------------------------------------------------------------------- {
sourceSymbols = input.string(defval='High/Low', title='Source for Pivot Points', options=['Close', 'High/Low'], group=GROUP_SYM)

// -----------------
// U.S. Market
// -----------------
// Russell 3000
useSym1 = input(true, '', inline = 'sym1', group=GROUP_SYM)
sym1    = input.symbol('AMEX:IWV', '', inline = 'sym1', group=GROUP_SYM)
sym1_text = input.string(defval = '📈', title = '', inline = 'sym1', group=GROUP_SYM)

// Nasdaq
useSym2 = input(true, '', inline = 'sym2', group=GROUP_SYM)
sym2   = input.symbol('NASDAQ:QQQ', '', inline = 'sym2', group=GROUP_SYM)
sym2_text = input.string(defval = '📈', title = '', inline = 'sym2', group=GROUP_SYM)

// S&P 500 Equal Weight
useSym3 = input(true, '', inline = 'sym3', group=GROUP_SYM)
sym3   = input.symbol('AMEX:RSP', '', inline = 'sym3', group=GROUP_SYM)
sym3_text = input.string(defval = '📈', title = '', inline = 'sym3', group=GROUP_SYM)

// -----------------
// Europe Market
// -----------------
// Germany 40
useSym4 = input(true, '', inline = 'sym4', group=GROUP_SYM)
sym4   = input.symbol('CAPITALCOM:DE40', '', inline = 'sym4', group=GROUP_SYM)
sym4_text = input.string(defval ='📉', title = '', inline = 'sym4', group=GROUP_SYM)

// UK 100
useSym5 = input(true, '', inline = 'sym5', group=GROUP_SYM)
sym5   = input.symbol('TVC:UKX', '', inline = 'sym5', group=GROUP_SYM)
sym5_text = input.string(defval = '📉', title = '', inline = 'sym5', group=GROUP_SYM)

// Euro Stoxx 600
useSym6 = input(true, '', inline = 'sym6', group=GROUP_SYM)
sym6   = input.symbol('TVC:SXXP', '', inline = 'sym6', group=GROUP_SYM)
sym6_text = input.string(defval = '📉', title = '', inline = 'sym6', group=GROUP_SYM)

// -----------------
// Asia Market
// -----------------
// Japan
useSym7 = input(true, '', inline = 'sym7', group=GROUP_SYM)
sym7   = input.symbol('TVC:NI225', '', inline = 'sym7', group=GROUP_SYM)
sym7_text = input.string(defval = '📉', title = '', inline = 'sym7', group=GROUP_SYM)

// China (Hong Kong)
useSym8 = input(true, '', inline = 'sym8', group=GROUP_SYM)
sym8   = input.symbol('TVC:HSI', '', inline = 'sym8', group=GROUP_SYM)
sym8_text = input.string(defval = '📉', title = '', inline = 'sym8', group=GROUP_SYM)

// -----------------
// Oceanic Market
// -----------------
// Australia
useSym9 = input(true, '', inline = 'sym9', group=GROUP_SYM)
sym9   = input.symbol('EIGHTCAP:ASX200', '', inline = 'sym9', group=GROUP_SYM)
sym9_text = input.string(defval = '📉', title = '', inline = 'sym9', group=GROUP_SYM)

// -----------------
// Latin America
// -----------------
// Brazil
useSym10 = input(true, '', inline = 'sym10', group=GROUP_SYM)
sym10   = input.symbol('AMEX:EWZ', '', inline = 'sym10', group=GROUP_SYM)
sym10_text = input.string(defval = '📉', title = '', inline = 'sym10', group=GROUP_SYM)

// -----------------
// World
// -----------------
useSym11 = input(true, '', inline = 'sym11', group=GROUP_SYM)
sym11   = input.symbol('AMEX:VT', '', inline = 'sym11', group=GROUP_SYM)
sym11_text = input.string(defval = '🌎', title = '', inline = 'sym11', group=GROUP_SYM)

// -----------------
// Commodities: Metals
// -----------------
// Gold
useSym12 = input(true, '', inline = 'sym12', group=GROUP_SYM)
sym12   = input.symbol('TVC:GOLD', '', inline = 'sym12', group=GROUP_SYM)
sym12_text = input.string(defval = '🥇', title = '', inline = 'sym12', group=GROUP_SYM)

// Silver
useSym13 = input(true, '', inline = 'sym13', group=GROUP_SYM)
sym13   = input.symbol('TVC:SILVER', '', inline = 'sym13', group=GROUP_SYM)
sym13_text = input.string(defval = '🥈', title = '', inline = 'sym13', group=GROUP_SYM)

// Copper
useSym14 = input(true, '', inline = 'sym14', group=GROUP_SYM)
sym14   = input.symbol('CAPITALCOM:COPPER', '', inline = 'sym14', group=GROUP_SYM)
sym14_text = input.string(defval = '🏭', title = '', inline = 'sym14', group=GROUP_SYM)

//---------------------------------------
// Commodities: Energy
//---------------------------------------
// Crude Oil
useSym15 = input(true, '', inline = 'sym15', group=GROUP_SYM)
sym15   = input.symbol('TVC:USOIL', '', inline = 'sym15', group=GROUP_SYM)
sym15_text = input.string(defval = '🛢️', title = '', inline = 'sym15', group=GROUP_SYM)

// Natural Gas
useSym16 = input(true, '', inline = 'sym16', group=GROUP_SYM)
sym16   = input.symbol('PEPPERSTONE:NATGAS', '', inline = 'sym16', group=GROUP_SYM)
sym16_text = input.string(defval ='🔥', title = '', inline = 'sym16', group=GROUP_SYM)

// Uranium
useSym17 = input(true, '', inline = 'sym17', group=GROUP_SYM)
sym17   = input.symbol('AMEX:URA', '', inline = 'sym17', group=GROUP_SYM)
sym17_text = input.string(defval ='☢️', title = '', inline = 'sym17', group=GROUP_SYM)

// -----------------
// Commodities: Agriculture and Livestock
// -----------------
// Corn
useSym18 = input(true, '', inline = 'sym18', group=GROUP_SYM)
sym18   = input.symbol('AMEX:CORN', '', inline = 'sym18', group=GROUP_SYM)
sym18_text = input.string(defval = '🌽', title = '', inline = 'sym18', group=GROUP_SYM)

// Wheat
useSym19 = input(true, '', inline = 'sym19', group=GROUP_SYM)
sym19   = input.symbol('PEPPERSTONE:WHEAT', '', inline = 'sym19', group=GROUP_SYM)
sym19_text = input.string(defval = '🌾', title = '', inline = 'sym19', group=GROUP_SYM)

// Cattle
useSym20 = input(true, '', inline = 'sym20', group=GROUP_SYM)
sym20   = input.symbol('PEPPERSTONE:CATTLE', '', inline = 'sym20', group=GROUP_SYM)
sym20_text = input.string(defval = '🐂', title = '', inline = 'sym20', group=GROUP_SYM)

// -----------------
// FOREX
// -----------------
// U.S. Dollar Index (inverted)
// Currencies in DXY:
// 1. Euro (EUR) 57.6% weight
// 2. Japanese yen (JPY) 13.6% weight
// 3. Pound sterling (GBP) 11.9% weight
// 4. Canadian dollar (CAD) 9.1% weight
// 5. Swedish krona (SEK) 4.2% weight
// 6. Swiss franc (CHF) 3.6% weight
useSym21 = input(true, '', inline = 'sym21', group=GROUP_SYM)
sym21   = input.symbol('1/TVC:DXY', '', inline = 'sym21', group=GROUP_SYM)
sym21_text = input.string(defval ='💵 (inverse)', title = '', inline = 'sym21', group=GROUP_SYM)

// Taiwan Dollar
useSym22 = input(true, '', inline = 'sym22', group=GROUP_SYM)
sym22   = input.symbol('FX_IDC:TWDUSD', '', inline = 'sym22', group=GROUP_SYM)
sym22_text = input.string(defval = ' 🇹🇼', title = '', inline = 'sym22', group=GROUP_SYM)

// South Korean Won
useSym23 = input(true, '', inline = 'sym23', group=GROUP_SYM)
sym23   = input.symbol('FX_IDC:KRWUSD', '', inline = 'sym23', group=GROUP_SYM)
sym23_text = input.string(defval = ' 🇰🇷', title = '', inline = 'sym23', group=GROUP_SYM)

// Chinese Yuan
useSym24 = input(true, '', inline = 'sym24', group=GROUP_SYM)
sym24   = input.symbol('FX_IDC:CNYUSD', '', inline = 'sym24', group=GROUP_SYM)
sym24_text = input.string(defval = ' 🇨🇳', title = '', inline = 'sym24', group=GROUP_SYM)

// Indian Rupee
useSym25 = input(true, '', inline = 'sym25', group=GROUP_SYM)
sym25   = input.symbol('FX_IDC:INRUSD', '', inline = 'sym25', group=GROUP_SYM)
sym25_text = input.string(defval = ' 🇮🇳', title = '', inline = 'sym25', group=GROUP_SYM)

// Brazilian Real
useSym26 = input(true, '', inline = 'sym26', group=GROUP_SYM)
sym26   = input.symbol('FX_IDC:BRLUSD', '', inline = 'sym26', group=GROUP_SYM)
sym26_text = input.string(defval = ' 🇧🇷', title = '', inline = 'sym26', group=GROUP_SYM)

// -----------------
// Treasuries Bonds
// -----------------
// USA 1-Year Treasury Note Yield
useSym27 = input(true, '', inline = 'sym27', group=GROUP_SYM)
sym27   = input.symbol('TVC:US01Y', '', inline = 'sym27', group=GROUP_SYM)
sym27_text = input.string(defval ='🏦', title = '', inline = 'sym27', group=GROUP_SYM)

// USA 10-Year Treasury Note Yield
useSym28 = input(true, '', inline = 'sym28', group=GROUP_SYM)
sym28   = input.symbol('TVC:US10Y', '', inline = 'sym28', group=GROUP_SYM)
sym28_text = input.string(defval = '🏦', title = '', inline = 'sym28', group=GROUP_SYM)

// Japan 10-Year Treasury Note Yield
useSym29 = input(true, '', inline = 'sym29', group=GROUP_SYM)
sym29   = input.symbol('TVC:JP10Y', '', inline = 'sym29', group=GROUP_SYM)
sym29_text = input.string(defval = '🏦', title = '', inline = 'sym29', group=GROUP_SYM)

// Brazil 10-Year Treasury Note Yield
useSym30 = input(true, '', inline = 'sym30', group=GROUP_SYM)
sym30   = input.symbol('TVC:BR10Y', '', inline = 'sym30', group=GROUP_SYM)
sym30_text = input.string(defval = '🏦', title = '', inline = 'sym30', group=GROUP_SYM)

// -----------------
// Misc: Volatility and Fear
// -----------------
// VIX: CBOE Volatility Index (inverted)
useSym31 = input(true, '', inline = 'sym31', group=GROUP_SYM)
sym31   = input.symbol('1/TVC:VIX', '', inline = 'sym31', group=GROUP_SYM)
sym31_text = input.string(defval = '😱 (inverse)', title = '', inline = 'sym31', group=GROUP_SYM)

// -----------------
// Cryptocurrencies
// -----------------
// Total Market Cap
useSym32 = input(true, '', inline = 'sym32', group=GROUP_SYM)
sym32   = input.symbol('CRYPTOCAP:TOTAL', '', inline = 'sym32', group=GROUP_SYM)
sym32_text = input.string(defval = '🚀', title = '', inline = 'sym32', group=GROUP_SYM)

// TOTAL2: Market capitalization of the top-125 cryptocurrencies, excluding BTC
useSym33 = input(true, '', inline = 'sym33', group=GROUP_SYM)
sym33   = input.symbol('CRYPTOCAP:TOTAL2', '', inline = 'sym33', group=GROUP_SYM)
sym33_text = input.string(defval = '🚀', title = '', inline = 'sym33', group=GROUP_SYM)

// TOTAL3: Market capitalization of the top-125 cryptocurrencies, excluding BTC and ETH
useSym34 = input(true, '', inline = 'sym34', group=GROUP_SYM)
sym34   = input.symbol('CRYPTOCAP:TOTAL3', '', inline = 'sym34', group=GROUP_SYM)
sym34_text = input.string(defval = '🚀', title = '', inline = 'sym34', group=GROUP_SYM)

// OTHERS: Market capitalization of the top-125 cryptocurrencies, excluding top 11 listed on
// https://www.tradingview.com/markets/cryptocurrencies/global-charts/
useSym35 = input(true, '', inline = 'sym35', group=GROUP_SYM)
sym35   = input.symbol('CRYPTOCAP:OTHERS', '', inline = 'sym35', group=GROUP_SYM)
sym35_text = input.string(defval = '🚀', title = '', inline = 'sym35', group=GROUP_SYM)

// Market Cap in DeFi
useSym36 = input(true, '', inline = 'sym36', group=GROUP_SYM)
sym36   = input.symbol('CRYPTOCAP:TOTALDEFI', '', inline = 'sym36', group=GROUP_SYM)
sym36_text = input.string(defval = '🚀', title = '', inline = 'sym36', group=GROUP_SYM)

// BTC INDEX: perpetual contract
useSym37 = input(true, '', inline = 'sym37', group=GROUP_SYM)
sym37   = input.symbol('BITFINEX:BTCUSDLONGS', '', inline = 'sym37', group=GROUP_SYM)
sym37_text = input.string(defval = '🚀', title = '', inline = 'sym37', group=GROUP_SYM)

// BTC INDEX: futures contract
useSym38 = input(true, '', inline = 'sym38', group=GROUP_SYM)
sym38   = input.symbol('BITFINEX:BTCF0USTF0LONGS', '', inline = 'sym38', group=GROUP_SYM)
sym38_text = input.string(defval = '🚀', title = '', inline = 'sym38', group=GROUP_SYM)

// ARK Innovation ETF
// Top 10 holdings:
// 1. Tesla (TSLA)
// 2. Roku (ROKU)
// 3. Coinbase (COIN)
// 4. Zoom (ZM)
// 5. Path (UIPATH INC - CLASS A)
// 6. Block Inc (SQ)
// 7. DRAFTKINGS INC-CL A (DKNG UW)
// 8. TWILIO INC - A (TWLO)
// 9. Unity Software (U)
// 10. Shopfy (SHOP)
useSym39 = input(true, '', inline = 'sym39', group=GROUP_SYM)
sym39   = input.symbol('AMEX:ARKK', '', inline = 'sym39', group=GROUP_SYM)
sym39_text = input.string(defval = '🚀', title = '', inline = 'sym39', group=GROUP_SYM)

// Amplify Transformational Data Sharing ETF
// Top 10 holdings:
// 1. Coinbase (COIN)
// 2. MicroStrategy (MSTR)
// 3. SBI HOLDINGS INC (8473 JT)
// 4. ACCENTURE PLC IRELAND CLASS A (ACN)
// 5. GALAXY DIGITAL HOLDINGS LTD (GLXY CN)
// 6. CLEANSPARK INC (CLSK UW)
// 7. GMO INTERNET GROUP (9449 JT)
// 8. PAYPAL HLDGS INC (PYPL UW)
// 9. RIOT PLATFORMS INC (RIOT UW)
// 10. OVERSTOCK COM INC DEL (OSTK UW)
useSym40 = input(true, '', inline = 'sym40', group=GROUP_SYM)
sym40   = input.symbol('AMEX:BLOK', '', inline = 'sym40', group=GROUP_SYM)
sym40_text = input.string(defval = '🚀', title = '', inline = 'sym40', group=GROUP_SYM)
// -------------------------------------------------------------------------------------------------------------- }


//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
// Begin Calculations
//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

// Set line styles
// -------------------------------------------------------------------------------------------------------------- {
var reg_div_l_style = reg_div_l_style_ == 'Solid' ? line.style_solid : reg_div_l_style_ == 'Dashed' ? line.style_dashed : line.style_dotted
var hid_div_l_style = hid_div_l_style_ == 'Solid' ? line.style_solid : hid_div_l_style_ == 'Dashed' ? line.style_dashed : line.style_dotted
// -------------------------------------------------------------------------------------------------------------- }

// Get indicators
// -------------------------------------------------------------------------------------------------------------- {
// RSI
rsi = MI.rsi(source=rsi_source, length=rsi_length)

// MACD
[macd, signalMACD, deltamacd] = MI.macd(source=macd_source, fastLength=macd_fast, slowLength=macd_slow,
  signalLength=macd_signal, maTypeFast=macd_type_ma, maTypeSlow=macd_type_ma, maTypeMACD=macd_type_ma)

// Volume weighted MACD
[vwmacd, vwsignalMACD, vwmacdHistogram] = MI.macd(source=macd_source, fastLength=macd_fast, slowLength=macd_slow,
  signalLength=macd_signal, maTypeFast=macd_type_ma, maTypeSlow=macd_type_ma, maTypeMACD=4)

// Momentum
moment = ta.mom(mom_source, mom_length)

// CCI
cci = MI.cci(source=cci_source, length=cci_length, maType=cci_type_ma)

// OBV
obv = VI.obv(source=obv_source)

// Stoch
[stk, signalStoch] = MI.stoch(source=stoc_source, kLength=stoc_k, kSmoothing=stoc_d, dSmoothing=stoc_dSmoothing, maTypeK=stoc_type_ma, maTypeD=stoc_type_ma)

// Chaikin money flow
cmf = VI.cmf(length=cmf_length)

// Moneyt Flow Index
mfi = VI.mfi(source=mfi_source, length=mfi_length)

// Stochastic RSI
[stochRSI, signalStochRSI] = MI.stoch(source=rsi, kLength=stoc_k, kSmoothing=stoc_d, dSmoothing=stoc_dSmoothing, maTypeK=stoc_type_ma, maTypeD=stoc_type_ma)

// Volume Oscillator
volumeOsc = VI.vo(shortLen=shortLengthVolumeOsc, longLen=longLengthVolumeOsc)

// Price Volume Trend
pvt = VI.pvt(source=sourcePVT)

// Ultimate Oscillator
ultosc = MI.ultimateOscillator(source=ultosc_source, fastLength=ultosc_length1, middleLength=ultosc_length2, slowLength=ultosc_length3)

// Fisher Transform
[fisher, fisher_signal] = if fisher_source == 'Close'
    MI.fisher(length=fisher_length)
else
    MI.fisher(sourceHigh=high, sourceLow=low, length=fisher_length)

// Z-Score/T-Score
mean_zscore = switch zscore_mean_type
    1 => ta.sma(zscore_source, zscore_mean_length)
    2 => ta.ema(zscore_source, zscore_mean_length)
    3 => ta.wma(zscore_source, zscore_mean_length)
    4 => ta.vwma(zscore_source, zscore_mean_length)
    5 => ta.alma(zscore_source, zscore_mean_length, 0.85, 6)
    6 => ta.hma(zscore_source, zscore_mean_length)
    7 => ta.linreg(zscore_source, zscore_mean_length, na)
    8 => ta.rma(zscore_source, zscore_mean_length)
    9 => ta.median(zscore_source, zscore_mean_length)

zt_score = if zscore_length < 30
    VOL.tscore(src=zscore_source, mean=mean_zscore, length=zscore_length, degreesOfFreedom=zscore_length-1)
else
    VOL.zscore(src=zscore_source, mean=mean_zscore, length=zscore_length)
// -------------------------------------------------------------------------------------------------------------- }

// Get symbols
// -------------------------------------------------------------------------------------------------------------- {
get_hl() => sourceSymbols == 'Close' ? close : hl2

// Symbols
sym_1 = request.security(sym1, timeframe.period, get_hl())
sym_2 = request.security(sym2, timeframe.period, get_hl())
sym_3 = request.security(sym3, timeframe.period, get_hl())
sym_4 = request.security(sym4, timeframe.period, get_hl())
sym_5 = request.security(sym5, timeframe.period, get_hl())
sym_6 = request.security(sym6, timeframe.period, get_hl())
sym_7 = request.security(sym7, timeframe.period, get_hl())
sym_8 = request.security(sym8, timeframe.period, get_hl())
sym_9 = request.security(sym9, timeframe.period, get_hl())
sym_10 = request.security(sym10, timeframe.period, get_hl())
sym_11 = request.security(sym11, timeframe.period, get_hl())
sym_12 = request.security(sym12, timeframe.period, get_hl())
sym_13 = request.security(sym13, timeframe.period, get_hl())
sym_14 = request.security(sym14, timeframe.period, get_hl())
sym_15 = request.security(sym15, timeframe.period, get_hl())
sym_16 = request.security(sym16, timeframe.period, get_hl())
sym_17 = request.security(sym17, timeframe.period, get_hl())
sym_18 = request.security(sym18, timeframe.period, get_hl())
sym_19 = request.security(sym19, timeframe.period, get_hl())
sym_20 = request.security(sym20, timeframe.period, get_hl())
sym_21 = request.security(sym21, timeframe.period, get_hl())
sym_22 = request.security(sym22, timeframe.period, get_hl())
sym_23 = request.security(sym23, timeframe.period, get_hl())
sym_24 = request.security(sym24, timeframe.period, get_hl())
sym_25 = request.security(sym25, timeframe.period, get_hl())
sym_26 = request.security(sym26, timeframe.period, get_hl())
sym_27 = request.security(sym27, timeframe.period, get_hl())
sym_28 = request.security(sym28, timeframe.period, get_hl())
sym_29 = request.security(sym29, timeframe.period, get_hl())
sym_30 = request.security(sym30, timeframe.period, get_hl())
sym_31 = request.security(sym31, timeframe.period, get_hl())
sym_32 = request.security(sym32, timeframe.period, get_hl())
sym_33 = request.security(sym33, timeframe.period, get_hl())
sym_34 = request.security(sym34, timeframe.period, get_hl())
sym_35 = request.security(sym35, timeframe.period, get_hl())
sym_36 = request.security(sym36, timeframe.period, get_hl())
sym_37 = request.security(sym37, timeframe.period, get_hl())
sym_38 = request.security(sym38, timeframe.period, get_hl())
sym_39 = request.security(sym39, timeframe.period, get_hl())
sym_40 = request.security(sym40, timeframe.period, get_hl())
// -------------------------------------------------------------------------------------------------------------- }

// Keep indicators names and colors in arrays
// -------------------------------------------------------------------------------------------------------------- {
var indicators_name = array.new_string(60)
var div_colors = array.new_color(4)
var tooltip_names = array.new_string(60)

if barstate.isfirst
    // Names
    array.set(indicators_name, 0, showindis == 'Full' ? 'MACD' + calcmacd_text : 'MACD')
    array.set(indicators_name, 1, showindis == 'Full' ? 'MACD Histogram' + calcmacda_text : 'HIS')
    array.set(indicators_name, 2, showindis == 'Full' ? 'RSI' + calcrsi_text : 'RSI')
    array.set(indicators_name, 3, showindis == 'Full' ? 'Stochastic' + calcstoc_text : 'STOC')
    array.set(indicators_name, 4, showindis == 'Full' ? 'CCI' + calccci_text : 'CCI')
    array.set(indicators_name, 5, showindis == 'Full' ? 'Momentum' + calcmom_text : 'MOM')
    array.set(indicators_name, 6, showindis == 'Full' ? 'On Balance Volume' + calcobv_text: 'OBV')
    array.set(indicators_name, 7, showindis == 'Full' ? 'Volume Weighted MACD' + calcvwmacd_text : 'VMACD')
    array.set(indicators_name, 8, showindis == 'Full' ? 'Chaikin Money Flow' + calccmf_text : 'CMF')
    array.set(indicators_name, 9, showindis == 'Full' ? 'Money Flow Index' + calcmfi_text : 'MFI')
    array.set(indicators_name, 10, showindis == 'Full' ? 'Stochastic RSI' + calcStochRSI_text : 'SRSI')
    array.set(indicators_name, 11, showindis == 'Full' ? 'Volume Oscillator' + calcVolumeOsc_text : 'VO')
    array.set(indicators_name, 12, showindis == 'Full' ? 'Price Volume Trend' + calcPVT_text : 'PVT')
    array.set(indicators_name, 13, showindis == 'Full' ? 'Ultimate Oscillator' + calcUltimateOsc_text : 'UO')
    array.set(indicators_name, 14, showindis == 'Full' ? 'Fisher Transform' + calcFisherTransform_text : 'FT')
    array.set(indicators_name, 15, showindis == 'Full' ? (zscore_length < 30 ? 'T-Score' : 'Z-Score') + calcZscore_text : 'ZSC')
    array.set(indicators_name, 16, showindis == 'Full' ? externalIndicator_1_text : 'EX1')
    array.set(indicators_name, 17, showindis == 'Full' ? externalIndicator_2_text : 'EX2')
    array.set(indicators_name, 18, showindis == 'Full' ? externalIndicator_3_text : 'EX3')
    array.set(indicators_name, 19, showindis == 'Full' ? externalIndicator_4_text : 'EX4')
    array.set(indicators_name, 20, showindis == 'Full' ? syminfo.ticker(sym1) + sym1_text : 'S1')
    array.set(indicators_name, 21, showindis == 'Full' ? syminfo.ticker(sym2) + sym2_text: 'S2')
    array.set(indicators_name, 22, showindis == 'Full' ? syminfo.ticker(sym3) + sym3_text: 'S3')
    array.set(indicators_name, 23, showindis == 'Full' ? syminfo.ticker(sym4) + sym4_text: 'S4')
    array.set(indicators_name, 24, showindis == 'Full' ? syminfo.ticker(sym5) + sym5_text: 'S5')
    array.set(indicators_name, 25, showindis == 'Full' ? syminfo.ticker(sym6) + sym6_text: 'S6')
    array.set(indicators_name, 26, showindis == 'Full' ? syminfo.ticker(sym7) + sym7_text: 'S7')
    array.set(indicators_name, 27, showindis == 'Full' ? syminfo.ticker(sym8) + sym8_text: 'S8')
    array.set(indicators_name, 28, showindis == 'Full' ? syminfo.ticker(sym9) + sym9_text: 'S9')
    array.set(indicators_name, 29, showindis == 'Full' ? syminfo.ticker(sym10) + sym10_text : 'S10')
    array.set(indicators_name, 30, showindis == 'Full' ? syminfo.ticker(sym11) + sym11_text : 'S11')
    array.set(indicators_name, 31, showindis == 'Full' ? syminfo.ticker(sym12) + sym12_text : 'S12')
    array.set(indicators_name, 32, showindis == 'Full' ? syminfo.ticker(sym13) + sym13_text : 'S13')
    array.set(indicators_name, 33, showindis == 'Full' ? syminfo.ticker(sym14) + sym14_text : 'S14')
    array.set(indicators_name, 34, showindis == 'Full' ? syminfo.ticker(sym15) + sym15_text : 'S15')
    array.set(indicators_name, 35, showindis == 'Full' ? syminfo.ticker(sym16) + sym16_text : 'S16')
    array.set(indicators_name, 36, showindis == 'Full' ? syminfo.ticker(sym17) + sym17_text : 'S17')
    array.set(indicators_name, 37, showindis == 'Full' ? syminfo.ticker(sym18) + sym18_text : 'S18')
    array.set(indicators_name, 38, showindis == 'Full' ? syminfo.ticker(sym19) + sym19_text : 'S19')
    array.set(indicators_name, 39, showindis == 'Full' ? syminfo.ticker(sym20) + sym20_text : 'S20')
    array.set(indicators_name, 40, showindis == 'Full' ? syminfo.ticker(sym21) + sym21_text : 'S21')
    array.set(indicators_name, 41, showindis == 'Full' ? syminfo.ticker(sym22) + sym22_text : 'S22')
    array.set(indicators_name, 42, showindis == 'Full' ? syminfo.ticker(sym23) + sym23_text : 'S23')
    array.set(indicators_name, 43, showindis == 'Full' ? syminfo.ticker(sym24) + sym24_text : 'S24')
    array.set(indicators_name, 44, showindis == 'Full' ? syminfo.ticker(sym25) + sym25_text : 'S25')
    array.set(indicators_name, 45, showindis == 'Full' ? syminfo.ticker(sym26) + sym26_text : 'S26')
    array.set(indicators_name, 46, showindis == 'Full' ? syminfo.ticker(sym27) + sym27_text : 'S27')
    array.set(indicators_name, 47, showindis == 'Full' ? syminfo.ticker(sym28) + sym28_text : 'S28')
    array.set(indicators_name, 48, showindis == 'Full' ? syminfo.ticker(sym29) + sym29_text : 'S29')
    array.set(indicators_name, 49, showindis == 'Full' ? syminfo.ticker(sym30) + sym30_text : 'S30')
    array.set(indicators_name, 50, showindis == 'Full' ? syminfo.ticker(sym31) + sym31_text : 'S31')
    array.set(indicators_name, 51, showindis == 'Full' ? syminfo.ticker(sym32) + sym32_text : 'S32')
    array.set(indicators_name, 52, showindis == 'Full' ? syminfo.ticker(sym33) + sym33_text : 'S33')
    array.set(indicators_name, 53, showindis == 'Full' ? syminfo.ticker(sym34) + sym34_text : 'S34')
    array.set(indicators_name, 54, showindis == 'Full' ? syminfo.ticker(sym35) + sym35_text : 'S35')
    array.set(indicators_name, 55, showindis == 'Full' ? syminfo.ticker(sym36) + sym36_text : 'S36')
    array.set(indicators_name, 56, showindis == 'Full' ? syminfo.ticker(sym37) + sym37_text : 'S37')
    array.set(indicators_name, 57, showindis == 'Full' ? syminfo.ticker(sym38) + sym38_text : 'S38')
    array.set(indicators_name, 58, showindis == 'Full' ? syminfo.ticker(sym39) + sym39_text : 'S39')
    array.set(indicators_name, 59, showindis == 'Full' ? syminfo.ticker(sym40) + sym40_text : 'S40')

    // Tooltips
    array.set(tooltip_names, 0, 'MACD' + calcmacd_text)
    array.set(tooltip_names, 1, 'MACD Histogram' + calcmacda_text)
    array.set(tooltip_names, 2, 'RSI' + calcrsi_text)
    array.set(tooltip_names, 3, 'Stochastic' + calcstoc_text)
    array.set(tooltip_names, 4, 'CCI' + calccci_text)
    array.set(tooltip_names, 5, 'Momentum' + calcmom_text)
    array.set(tooltip_names, 6, 'On Balance Volume' + calcobv_text)
    array.set(tooltip_names, 7, 'Volume Weighted MACD' + calcvwmacd_text)
    array.set(tooltip_names, 8, 'Chaikin Money Flow' + calccmf_text)
    array.set(tooltip_names, 9, 'Money Flow Index' + calcmfi_text)
    array.set(tooltip_names, 10, 'Stochastic RSI' + calcStochRSI_text)
    array.set(tooltip_names, 11, 'Volume Oscillator' + calcVolumeOsc_text)
    array.set(tooltip_names, 12, 'Price Volume Trend' + calcPVT_text)
    array.set(tooltip_names, 13, 'Ultimate Oscillator' + calcUltimateOsc_text)
    array.set(tooltip_names, 14, 'Fisher Transform' + calcFisherTransform_text)
    array.set(tooltip_names, 15, (zscore_length < 30 ? 'T-Score' : 'Z-Score') + calcZscore_text)
    array.set(tooltip_names, 16, externalIndicator_1_text)
    array.set(tooltip_names, 17, externalIndicator_2_text)
    array.set(tooltip_names, 18, externalIndicator_3_text)
    array.set(tooltip_names, 19, externalIndicator_4_text)
    array.set(tooltip_names, 20, syminfo.ticker(sym1) + sym1_text)
    array.set(tooltip_names, 21, syminfo.ticker(sym2) + sym2_text)
    array.set(tooltip_names, 22, syminfo.ticker(sym3) + sym3_text)
    array.set(tooltip_names, 23, syminfo.ticker(sym4) + sym4_text)
    array.set(tooltip_names, 24, syminfo.ticker(sym5) + sym5_text)
    array.set(tooltip_names, 25, syminfo.ticker(sym6) + sym6_text)
    array.set(tooltip_names, 26, syminfo.ticker(sym7) + sym7_text)
    array.set(tooltip_names, 27, syminfo.ticker(sym8) + sym8_text)
    array.set(tooltip_names, 28, syminfo.ticker(sym9) + sym9_text)
    array.set(tooltip_names, 29, syminfo.ticker(sym10) + sym10_text)
    array.set(tooltip_names, 30, syminfo.ticker(sym11) + sym11_text)
    array.set(tooltip_names, 31, syminfo.ticker(sym12) + sym12_text)
    array.set(tooltip_names, 32, syminfo.ticker(sym13) + sym13_text)
    array.set(tooltip_names, 33, syminfo.ticker(sym14) + sym14_text)
    array.set(tooltip_names, 34, syminfo.ticker(sym15) + sym15_text)
    array.set(tooltip_names, 35, syminfo.ticker(sym16) + sym16_text)
    array.set(tooltip_names, 36, syminfo.ticker(sym17) + sym17_text)
    array.set(tooltip_names, 37, syminfo.ticker(sym18) + sym18_text)
    array.set(tooltip_names, 38, syminfo.ticker(sym19) + sym19_text)
    array.set(tooltip_names, 39, syminfo.ticker(sym20) + sym20_text)
    array.set(tooltip_names, 40, syminfo.ticker(sym21) + sym21_text)
    array.set(tooltip_names, 41, syminfo.ticker(sym22) + sym22_text)
    array.set(tooltip_names, 42, syminfo.ticker(sym23) + sym23_text)
    array.set(tooltip_names, 43, syminfo.ticker(sym24) + sym24_text)
    array.set(tooltip_names, 44, syminfo.ticker(sym25) + sym25_text)
    array.set(tooltip_names, 45, syminfo.ticker(sym26) + sym26_text)
    array.set(tooltip_names, 46, syminfo.ticker(sym27) + sym27_text)
    array.set(tooltip_names, 47, syminfo.ticker(sym28) + sym28_text)
    array.set(tooltip_names, 48, syminfo.ticker(sym29) + sym29_text)
    array.set(tooltip_names, 49, syminfo.ticker(sym30) + sym30_text)
    array.set(tooltip_names, 50, syminfo.ticker(sym31) + sym31_text)
    array.set(tooltip_names, 51, syminfo.ticker(sym32) + sym32_text)
    array.set(tooltip_names, 52, syminfo.ticker(sym33) + sym33_text)
    array.set(tooltip_names, 53, syminfo.ticker(sym34) + sym34_text)
    array.set(tooltip_names, 54, syminfo.ticker(sym35) + sym35_text)
    array.set(tooltip_names, 55, syminfo.ticker(sym36) + sym36_text)
    array.set(tooltip_names, 56, syminfo.ticker(sym37) + sym37_text)
    array.set(tooltip_names, 57, syminfo.ticker(sym38) + sym38_text)
    array.set(tooltip_names, 58, syminfo.ticker(sym39) + sym39_text)
    array.set(tooltip_names, 59, syminfo.ticker(sym40) + sym40_text)

    // Colors
    array.set(div_colors, 0, pos_reg_div_col)
    array.set(div_colors, 1, neg_reg_div_col)
    array.set(div_colors, 2, pos_hid_div_col)
    array.set(div_colors, 3, neg_hid_div_col)
// -------------------------------------------------------------------------------------------------------------- }

// Pivots Highs and Lows
// -------------------------------------------------------------------------------------------------------------- {
// Check if we get new Pivot High Or Pivot Low
float ph = ta.pivothigh(source == 'Close' ? close : high, prd, prd)
float pl = ta.pivotlow(source == 'Close' ? close : low, prd, prd)
plotshape(ph and showpivot, text='H', style=shape.labeldown, color=color.new(color.white, 100), textcolor=color.new(color.red, 0),
  location=location.abovebar, offset=-prd, size=size.small, editable=true)
plotshape(pl and showpivot, text='L', style=shape.labelup, color=color.new(color.white, 100), textcolor=color.new(color.lime, 0),
  location=location.belowbar, offset=-prd, size=size.small, editable=true)

// keep values and positions of Pivot Highs/Lows in the arrays
var int maxarraysize = 20
var ph_positions = array.new_int(maxarraysize, 0)
var pl_positions = array.new_int(maxarraysize, 0)
var ph_vals = array.new_float(maxarraysize, 0.)
var pl_vals = array.new_float(maxarraysize, 0.)

// add PHs to the array
if ph
    array.unshift(ph_positions, bar_index)
    array.unshift(ph_vals, ph)
    if array.size(ph_positions) > maxarraysize
        array.pop(ph_positions)
        array.pop(ph_vals)

// add PLs to the array
if pl
    array.unshift(pl_positions, bar_index)
    array.unshift(pl_vals, pl)
    if array.size(pl_positions) > maxarraysize
        array.pop(pl_positions)
        array.pop(pl_vals)
// -------------------------------------------------------------------------------------------------------------- }

// Functions to check Regular Divergences and Hidden Divergences
// -------------------------------------------------------------------------------------------------------------- {

// @function Check positive regular or negative hidden divergence
// @param {float} src - source value
// @param {int} cond - condition. 1 => positive regular, 2 => negative hidden
// @returns {int} divergence length
positive_regular_positive_hidden_divergence(src, cond) =>
    divlen = 0
    prsc = source == 'Close' ? close : low
    // if indicators higher than last value and close price is higher than las close
    if dontconfirm or src > src[1] or close > close[1]
        startpoint = dontconfirm ? 0 : 1  // don't check last candle
        // we search last 15 PPs
        for x = 0 to maxpp - 1
            len = bar_index - array.get(pl_positions, x) + prd
            // if we reach non valued array element or arrived 101. or previous bars then we don't search more
            if array.get(pl_positions, x) == 0 or len > maxbars
                break
            if len > 5 and
               ((cond == 1 and src[startpoint] > src[len] and prsc[startpoint] < nz(array.get(pl_vals, x))) or
               (cond == 2 and src[startpoint] < src[len] and prsc[startpoint] > nz(array.get(pl_vals, x))))
                slope1 = (src[startpoint] - src[len]) / (len - startpoint)
                virtual_line1 = src[startpoint] - slope1
                slope2 = (close[startpoint] - close[len]) / (len - startpoint)
                virtual_line2 = close[startpoint] - slope2
                arrived = true
                for y = 1 + startpoint to len - 1
                    if src[y] < virtual_line1 or nz(close[y]) < virtual_line2
                        arrived := false
                        break
                    virtual_line1 := virtual_line1 - slope1
                    virtual_line2 := virtual_line2 - slope2

                if arrived
                    divlen := len
                    break
    divlen

// @function Check negative regular or positive hidden divergence
// @param {float} src - source value
// @param {int} cond - condition. 1 => negative regular, 2 => positive hidden
// @returns {int} divergence length
negative_regular_negative_hidden_divergence(src, cond) =>
    divlen = 0
    prsc = source == 'Close' ? close : high
    // if indicators higher than last value and close price is higher than las close
    if dontconfirm or src < src[1] or close < close[1]
        startpoint = dontconfirm ? 0 : 1 // don't check last candle
        // we search last 15 PPs
        for x = 0 to maxpp - 1
            len = bar_index - array.get(ph_positions, x) + prd
            // if we reach non valued array element or arrived 101. or previous bars then we don't search more
            if array.get(ph_positions, x) == 0 or len > maxbars
                break
            if len > 5 and
               ((cond == 1 and src[startpoint] < src[len] and prsc[startpoint] > nz(array.get(ph_vals, x))) or
               (cond == 2 and src[startpoint] > src[len] and prsc[startpoint] < nz(array.get(ph_vals, x))))
                slope1 = (src[startpoint] - src[len]) / (len - startpoint)
                virtual_line1 = src[startpoint] - slope1
                slope2 = (close[startpoint] - nz(close[len])) / (len - startpoint)
                virtual_line2 = close[startpoint] - slope2
                arrived = true
                for y = 1 + startpoint to len - 1
                    if src[y] > virtual_line1 or nz(close[y]) > virtual_line2
                        arrived := false
                        break
                    virtual_line1 := virtual_line1 - slope1
                    virtual_line2 := virtual_line2 - slope2

                if arrived
                    divlen := len
                    break
    divlen
// -------------------------------------------------------------------------------------------------------------- }

// Start to check divergences
// -------------------------------------------------------------------------------------------------------------- {

// @function Calculate 4 types of divergence if enabled in the options and return divergences in an array
// @param {bool} cond - condition to check divergence
// @param {float} indicator - indicator value
calculate_divs(cond, indicator)=>
    divs = array.new_int(4, 0)
    array.set(divs, 0, cond and (searchdiv == 'Regular' or searchdiv == 'Regular/Hidden') ? positive_regular_positive_hidden_divergence(indicator, 1) : 0)
    array.set(divs, 1, cond and (searchdiv == 'Regular' or searchdiv == 'Regular/Hidden') ? negative_regular_negative_hidden_divergence(indicator, 1) : 0)
    array.set(divs, 2, cond and (searchdiv == 'Hidden' or searchdiv == 'Regular/Hidden') ? positive_regular_positive_hidden_divergence(indicator, 2) : 0)
    array.set(divs, 3, cond and (searchdiv == 'Hidden' or searchdiv == 'Regular/Hidden') ? negative_regular_negative_hidden_divergence(indicator, 2) : 0)
    divs

// array to keep all divergences
var all_divergences = array.new_int(240)  // 60 indicators * 4 divergence = 240
// set related array elements
array_set_divs(div_pointer, index) =>
    for x = 0 to 3 by 1
        array.set(all_divergences, index * 4 + x, array.get(div_pointer, x))

// set divergences array
array_set_divs(calculate_divs(calcmacd, macd), 0)
array_set_divs(calculate_divs(calcmacda, deltamacd), 1)
array_set_divs(calculate_divs(calcrsi, rsi), 2)
array_set_divs(calculate_divs(calcstoc, stk), 3)
array_set_divs(calculate_divs(calccci, cci), 4)
array_set_divs(calculate_divs(calcmom, moment), 5)
array_set_divs(calculate_divs(calcobv, obv), 6)
array_set_divs(calculate_divs(calcvwmacd, vwmacd), 7)
array_set_divs(calculate_divs(calccmf, cmf), 8)
array_set_divs(calculate_divs(calcmfi, mfi), 9)
array_set_divs(calculate_divs(calcStochRSI, stochRSI), 10)
array_set_divs(calculate_divs(calcVolumeOsc, volumeOsc), 11)
array_set_divs(calculate_divs(calcPVT, pvt), 12)
array_set_divs(calculate_divs(calcUltimateOsc, ultosc), 13)
array_set_divs(calculate_divs(calcFisherTransform, fisher), 14)
array_set_divs(calculate_divs(calcZscore, zt_score), 15)
array_set_divs(calculate_divs(calcExt_1, externalIndicator_1), 16)
array_set_divs(calculate_divs(calcExt_2, externalIndicator_2), 17)
array_set_divs(calculate_divs(calcExt_3, externalIndicator_3), 18)
array_set_divs(calculate_divs(calcExt_4, externalIndicator_4), 19)
array_set_divs(calculate_divs(useSym1, sym_1), 20)
array_set_divs(calculate_divs(useSym2, sym_2), 21)
array_set_divs(calculate_divs(useSym3, sym_3), 22)
array_set_divs(calculate_divs(useSym4, sym_4), 23)
array_set_divs(calculate_divs(useSym5, sym_5), 24)
array_set_divs(calculate_divs(useSym6, sym_6), 25)
array_set_divs(calculate_divs(useSym7, sym_7), 26)
array_set_divs(calculate_divs(useSym8, sym_8), 27)
array_set_divs(calculate_divs(useSym9, sym_9), 28)
array_set_divs(calculate_divs(useSym10, sym_10), 29)
array_set_divs(calculate_divs(useSym11, sym_11), 30)
array_set_divs(calculate_divs(useSym12, sym_12), 31)
array_set_divs(calculate_divs(useSym13, sym_13), 32)
array_set_divs(calculate_divs(useSym14, sym_14), 33)
array_set_divs(calculate_divs(useSym15, sym_15), 34)
array_set_divs(calculate_divs(useSym16, sym_16), 35)
array_set_divs(calculate_divs(useSym17, sym_17), 36)
array_set_divs(calculate_divs(useSym18, sym_18), 37)
array_set_divs(calculate_divs(useSym19, sym_19), 38)
array_set_divs(calculate_divs(useSym20, sym_20), 39)
array_set_divs(calculate_divs(useSym21, sym_21), 40)
array_set_divs(calculate_divs(useSym22, sym_22), 41)
array_set_divs(calculate_divs(useSym23, sym_23), 42)
array_set_divs(calculate_divs(useSym24, sym_24), 43)
array_set_divs(calculate_divs(useSym25, sym_25), 44)
array_set_divs(calculate_divs(useSym26, sym_26), 45)
array_set_divs(calculate_divs(useSym27, sym_27), 46)
array_set_divs(calculate_divs(useSym28, sym_28), 47)
array_set_divs(calculate_divs(useSym29, sym_29), 48)
array_set_divs(calculate_divs(useSym30, sym_30), 49)
array_set_divs(calculate_divs(useSym31, sym_31), 50)
array_set_divs(calculate_divs(useSym32, sym_32), 51)
array_set_divs(calculate_divs(useSym33, sym_33), 52)
array_set_divs(calculate_divs(useSym34, sym_34), 53)
array_set_divs(calculate_divs(useSym35, sym_35), 54)
array_set_divs(calculate_divs(useSym36, sym_36), 55)
array_set_divs(calculate_divs(useSym37, sym_37), 56)
array_set_divs(calculate_divs(useSym38, sym_38), 57)
array_set_divs(calculate_divs(useSym39, sym_39), 58)
array_set_divs(calculate_divs(useSym40, sym_40), 59)

// check minimum number of divergence, if less than showlimit then delete all divergence
total_div = 0
for x = 0 to array.size(all_divergences) - 1
    total_div += math.round(math.sign(array.get(all_divergences, x)))
    total_div

if total_div < showlimit
    array.fill(all_divergences, 0)

// keep line in an array
var pos_div_lines = array.new_line(0)
var neg_div_lines = array.new_line(0)
var pos_div_labels = array.new_label(0)
var neg_div_labels = array.new_label(0)
var pos_div_support_resistance = array.new_line(0)
var neg_div_support_resistance = array.new_line(0)

// remove old lines and labels if showlast option is enabled
delete_old_pos_div_lines() =>
    if array.size(pos_div_lines) > 0
        for j = 0 to array.size(pos_div_lines) - 1
            line.delete(array.get(pos_div_lines, j))
        array.clear(pos_div_lines)

delete_old_neg_div_lines() =>
    if array.size(neg_div_lines) > 0
        for j = 0 to array.size(neg_div_lines) - 1
            line.delete(array.get(neg_div_lines, j))
        array.clear(neg_div_lines)

delete_old_pos_div_labels() =>
    if array.size(pos_div_labels) > 0
        for j = 0 to array.size(pos_div_labels) - 1
            label.delete(array.get(pos_div_labels, j))
        array.clear(pos_div_labels)
delete_old_pos_div_support_resistance() =>
    if array.size(pos_div_support_resistance) > 0
        for j = 0 to array.size(pos_div_support_resistance) - 1
            line.delete(array.get(pos_div_support_resistance, j))
        array.clear(pos_div_support_resistance)

delete_old_neg_div_labels() =>
    if array.size(neg_div_labels) > 0
        for j = 0 to array.size(neg_div_labels) - 1
            label.delete(array.get(neg_div_labels, j))
        array.clear(neg_div_labels)
delete_old_neg_div_support_resistance() =>
    if array.size(neg_div_support_resistance) > 0
        for j = 0 to array.size(neg_div_support_resistance) - 1
            line.delete(array.get(neg_div_support_resistance, j))
        array.clear(neg_div_support_resistance)

// delete last creted lines and labels until we met new PH/PV
delete_last_pos_div_lines_label(n) =>
    if n > 0 and array.size(pos_div_lines) >= n
        asz = array.size(pos_div_lines)
        for j = 1 to n
            line.delete(array.get(pos_div_lines, asz - j))
            array.pop(pos_div_lines)
        if array.size(pos_div_labels) > 0
            label.delete(array.get(pos_div_labels, array.size(pos_div_labels) - 1))
            array.pop(pos_div_labels)

delete_last_neg_div_lines_label(n) =>
    if n > 0 and array.size(neg_div_lines) >= n
        asz = array.size(neg_div_lines)
        for j = 1 to n
            line.delete(array.get(neg_div_lines, asz - j))
            array.pop(neg_div_lines)
        if array.size(neg_div_labels) > 0
            label.delete(array.get(neg_div_labels, array.size(neg_div_labels) - 1))
            array.pop(neg_div_labels)

delete_last_pos_div_support_resistance(n) =>
    if n > 0 and array.size(pos_div_support_resistance) >= n
        asz = array.size(pos_div_support_resistance)
        for j = 1 to n
            line.delete(array.get(pos_div_support_resistance, asz - j))
            array.pop(pos_div_support_resistance)

delete_last_neg_div_support_resistance(n) =>
    if n > 0 and array.size(neg_div_support_resistance) >= n
        asz = array.size(neg_div_support_resistance)
        for j = 1 to n
            line.delete(array.get(neg_div_support_resistance, asz - j))
            array.pop(neg_div_support_resistance)

// variables for Alerts
pos_reg_div_detected = false
neg_reg_div_detected = false
pos_hid_div_detected = false
neg_hid_div_detected = false

// to remove lines/labels until we met new // PH/PL
var last_pos_div_lines = 0
var last_neg_div_lines = 0
var remove_last_pos_divs = false
var remove_last_neg_divs = false
if pl
    remove_last_pos_divs := false
    last_pos_div_lines := 0
if ph
    remove_last_neg_divs := false
    last_neg_div_lines := 0

// draw divergences lines and labels
divergence_text_top = ''
divergence_text_bottom = ''
divergence_tooltip_top = ''
divergence_tooltip_bottom = ''
distances = array.new_int(0)
dnumdiv_top = 0
dnumdiv_bottom = 0
top_label_col = color.white
bottom_label_col = color.white
old_pos_divs_can_be_removed = true
old_neg_divs_can_be_removed = true

_extend = switch support_resistance_extend
    'Both' => extend.both
    'Right' => extend.right
    'Left' => extend.left
    'None' => extend.none

for x = 0 to 59 by 1
    div_type = -1
    for y = 0 to 3
        if array.get(all_divergences, x * 4 + y) > 0 // any divergence?
            div_type := y
            if (y % 2) == 1
                dnumdiv_top := dnumdiv_top + 1
                top_label_col := array.get(div_colors, y)
            if (y % 2) == 0
                dnumdiv_bottom := dnumdiv_bottom + 1
                bottom_label_col := array.get(div_colors, y)
            if not array.includes(distances, array.get(all_divergences, x * 4 + y))  // line not exist ?
                array.push(distances, array.get(all_divergences, x * 4 + y))
                new_line = if showlines
                    line.new(
                      x1 = bar_index - array.get(all_divergences, x * 4 + y),
                      y1 = (source == "Close" ? close[array.get(all_divergences, x * 4 + y)] : (y % 2) == 0 ? low[array.get(all_divergences, x * 4 + y)] : high[array.get(all_divergences, x * 4 + y)]),
                      x2 = bar_index,
                      y2 = (source == "Close" ? close : (y % 2) == 0 ? low : high),
                      color = array.get(div_colors, y),
                      style = y < 2 ? reg_div_l_style : hid_div_l_style,
                      width = y < 2 ? reg_div_l_width : hid_div_l_width)
                else
                    na

                new_support_resistance = if show_support_resistance
                    _new_support_resistance = line.new(
                      x1 = bar_index,
                      y1 = (source == "Close" ? close : (y % 2) == 0 ? low : high),
                      x2 = bar_index+support_resistance_bars,
                      y2 = (source == "Close" ? close : (y % 2) == 0 ? low : high),
                      extend = _extend,
                      color = array.get(div_colors, y),
                      style = y < 2 ? reg_div_l_style : hid_div_l_style,
                      width = y < 2 ? reg_div_l_width : hid_div_l_width)
                else
                    na

                if (y % 2) == 0
                    if old_pos_divs_can_be_removed
                        old_pos_divs_can_be_removed := false
                        if not showlast and remove_last_pos_divs
                            delete_last_pos_div_lines_label(last_pos_div_lines)
                            if show_support_resistance
                                delete_last_pos_div_support_resistance(last_pos_div_lines)
                            last_pos_div_lines := 0
                        if showlast
                            delete_old_pos_div_lines()
                            if show_support_resistance
                                delete_old_pos_div_support_resistance()
                    array.push(pos_div_lines, new_line)
                    array.push(pos_div_support_resistance, new_support_resistance)
                    last_pos_div_lines := last_pos_div_lines + 1
                    remove_last_pos_divs := true

                if (y % 2) == 1
                    if old_neg_divs_can_be_removed
                        old_neg_divs_can_be_removed := false
                        if not showlast and remove_last_neg_divs
                            delete_last_neg_div_lines_label(last_neg_div_lines)
                            if show_support_resistance
                                delete_last_neg_div_support_resistance(last_neg_div_lines)
                            last_neg_div_lines := 0
                        if showlast
                            delete_old_neg_div_lines()
                            if show_support_resistance
                                delete_old_neg_div_support_resistance()
                    array.push(neg_div_lines, new_line)
                    array.push(neg_div_support_resistance, new_support_resistance)
                    last_neg_div_lines := last_neg_div_lines + 1
                    remove_last_neg_divs := true

            // set variables for alerts
            if y == 0
                pos_reg_div_detected := true
            if y == 1
                neg_reg_div_detected := true
            if y == 2
                pos_hid_div_detected := true
            if y == 3
                neg_hid_div_detected := true

    // Get text for labels
    if div_type >= 0
        _char_separator_top = str.length(divergence_text_top) > 0 ? char_separator : ''
        _char_separator_bottom = str.length(divergence_text_bottom) > 0 ? char_separator : ''

        // Labels
        divergence_text_top += (div_type % 2 == 1 ? showindis != 'Don\'t Show' ? _char_separator_top + array.get(indicators_name, x) : '' : '')
        divergence_text_bottom += (div_type % 2 == 0 ? showindis != 'Don\'t Show' ? _char_separator_bottom + array.get(indicators_name, x) : '' : '')

        // Tooltips
        _tooltip_separator_top = str.length(divergence_tooltip_top) > 0 ? char_separator : ''
        _tooltip_separator_bottom = str.length(divergence_tooltip_bottom) > 0 ? char_separator : ''
        divergence_tooltip_top += (div_type % 2 == 1 ? _tooltip_separator_top + array.get(tooltip_names, x) : '')
        divergence_tooltip_bottom += (div_type % 2 == 0 ? _tooltip_separator_bottom + array.get(tooltip_names, x) : '')

// Plot labels and tooltips
if showindis != 'Don\'t Show' or shownum

    // Concatenate number of divergences
    if shownum and dnumdiv_top > 0
        divergence_text_top := divergence_text_top + (showindis=='Full' or showindis=='Abbreviation' ? '\n' : '') + str.tostring(dnumdiv_top)
    if shownum and dnumdiv_bottom > 0
        divergence_text_bottom := divergence_text_bottom + (showindis=='Full' or showindis=='Abbreviation' ? '\n' : '') + str.tostring(dnumdiv_bottom)

    // Draw labels and tooltips (top)
    if divergence_text_top != ''
        if showlast
            delete_old_neg_div_labels()

        yShift = yShiftPercent/100 * high
        label_top = label.new(x = bar_index, y = math.max(high, high[1]) + yShift, text = divergence_text_top, color = top_label_col,
          textcolor = neg_div_text_col, style = label.style_label_down)
        array.push(neg_div_labels, label_top)

        if show_tooltip
            label.set_tooltip(id=label_top, tooltip=divergence_tooltip_top)

    // Draw labels and tooltips (bottom)
    if divergence_text_bottom != ''
        if showlast
            delete_old_pos_div_labels()

        yShift = yShiftPercent/100 * low
        label_bottom = label.new(x = bar_index, y = math.min(low, low[1]) - yShift, text = divergence_text_bottom, color = bottom_label_col,
          textcolor = pos_div_text_col, style = label.style_label_up)
        array.push(pos_div_labels, label_bottom)

        if show_tooltip
            label.set_tooltip(id=label_bottom, tooltip=divergence_tooltip_bottom)
// -------------------------------------------------------------------------------------------------------------- }

// Alerts
// -------------------------------------------------------------------------------------------------------------- {
// Individual Divergence Alerts
alertcondition(pos_reg_div_detected, title='Positive Regular Divergence Detected', message='Positive Regular Divergence Detected')
alertcondition(neg_reg_div_detected, title='Negative Regular Divergence Detected', message='Negative Regular Divergence Detected')
alertcondition(pos_hid_div_detected, title='Positive Hidden Divergence Detected', message='Positive Hidden Divergence Detected')
alertcondition(neg_hid_div_detected, title='Negative Hidden Divergence Detected', message='Negative Hidden Divergence Detected')

// Combined Divergence Alerts
alertcondition(pos_reg_div_detected or pos_hid_div_detected, title='Positive Divergence Detected', message='Positive Divergence Detected')
alertcondition(neg_reg_div_detected or neg_hid_div_detected, title='Negative Divergence Detected', message='Negative Divergence Detected')

// All Divergence Alerts
alertcondition(pos_reg_div_detected or neg_reg_div_detected or pos_hid_div_detected or neg_hid_div_detected, title='Divergence Detected', message='Divergence Detected')
// -------------------------------------------------------------------------------------------------------------- }
