1st Gray Cross Signals ━ Histogram SQZMOM [whvntr][LazyBear]
//This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//@version=5
// ─© whvntr (Tyler Ray) 
indicator(title='1st Gray Cross Signals ━ Histogram SQZMOM [whvntr][LazyBear]', shorttitle='SQZMOM_whvntr'
     , overlay = false, scale = scale.right)
// With all due credit @ user LazyBear & John F. Carter's book: Chapter 11 of "Mastering the Trade". 
//             LazyBear wrote: "Mr.Carter suggests waiting till the first gray after a black cross, 
//      ✓      and taking a position in the direction of the momentum (for ex., if momentum value 
//             is above zero, go long). Exit the position when the momentum changes 
//             (increase or decrease --- signified by a color change)."
// I have done just that. Now at each "first gray after a black cross", there are now Bearish and 
// Bullish highights.. The highlights only appear in the direction of the momentum.


color INVS = #00000000 


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// ℹ️ Multiple Sources ─© whvntr
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
changeSource = input.source(title='ℹ️'
     , defval = close
     , group = "Alternate Source")  
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 🗓️ Timeframe ─© whvntr
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
keepFrame = true
keepFrameFor = keepFrame ? timeframe.period : timeframe.period 
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// ╍╍ Lengths ─ LazyBear ©
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
length = input(20
     , title ='┅', group = 'Bollinger Bands Length'
     , tooltip = 'Bollinger Bands consist of a middle 
     band (which is a moving average) and an upper and 
     lower band. These upper and lower bands are set 
     above and below the moving average by a certain 
     number of standard deviations of price, thus 
     incorporating volatility')
mult = input(2.0
     , title = '×', group = 'Bollinger Bands MultFactor')
lengthKC = input(20
     , title = '┅', group = 'Keltner Channel Length'
     , tooltip = "Keltner Channels are volatility-based 
     bands that are placed on either side of an asset's 
     price and can aid in determining the direction of 
     a trend. The Keltner channel uses the average-true 
     range (ATR) or volatility, with breaks above or 
     below the top and bottom barriers signaling a 
     continuation")
multKC = input(1.5
     , title ='×', group ='Keltner Channel MultFactor')
trueRange = input.bool(true
     , title = ''
     , group = '☑ True Range (Keltner Channel)'
     , tooltip = 'Average-true range (ATR) with breaks 
     above or below the top and bottom barriers signaling 
     a continuation')
kc__tr =  trueRange ? true : na  
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 


//%%%%%%%%%%%%%%%%%%%%%%%%%CSS%%%%%%%%%%%%%%%%%%%%%%%%%
//  CSS Menu ─© whvntr 
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
bg_bear_css = input.color(color.rgb(120, 123, 134, 64)
     , '‎
     ‎ '
     , group = 'Highlights'
     , inline = 'exit')
bg_bull_css = input.color(color.rgb(120, 123, 134, 64)
     ,'‎
     ‎ '
     , group = 'Highlights'
     , inline = 'take')
sqz_pos_mom_css = input(#00ff00b2,'⌟'
     , group = "Positive Momentum")
sqz_pos_mom_rev_css = input(#008000ae,'⌞'
     , group = "Positive Momentum Reversing")
sqz_neg_mom_css = input(#ff0000ae,'⌝'
     , group = "Negative Momentum")
sqz_neg_mom_rev_css = input(#800000a7,'⌜'
     , group = "Negative Momentum Reversing")
sqz_no_css = input(#0023a1,'∅'
     , group = "No Squeeze")
sqz_ON_css = input(color.rgb(0, 0, 0),'⏳'
     , group = "Squeeze Entered (Preparing)"
     , tooltip = '"Black crosses on the midline show 
     that the market just entered a squeeze 
     (Bollinger Bands are within Keltner Channel). 
     This signifies low volatility, market preparing 
     itself for an explosive move (up or down)"')
sqz_released_css = input(color.gray,'🌋'
     , tooltip = '"Gray crosses signify 
     "Squeeze release""' 
     , group = "Squeeze Release (Released)") 
// New - Set visibility based on input
var hlines_visibility = input.bool(false, title="Toggle", group = 'Bands', inline = 'switch')
var upperline_css = input.color(color.white
      , title = '☱'
      , group = 'Bands'
      , inline = 'upperline')
var midline_css = input.color(INVS
      , title = '☲'
      , group = 'Bands'
      , inline = 'midline') 
var lowline_css = input.color(color.white
      , title = '☴'
      , group = 'Bands'
      , inline = 'lowerline')
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 


//%%%%%%%%%%%%%%%%%%%%%%%%%%BOLL%%%%%%%%%%%%%%%%%%%%%%%%
// 🎳 Bollinger Bands ─ LazyBear ©
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
basis = ta.sma(changeSource, length)
dev = multKC * ta.stdev(changeSource, length)
upperBB = basis + dev
lowerBB = basis - dev
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// ☶ Keltner Channel ─ LazyBear ©
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ma = ta.sma(changeSource, lengthKC)
range_1 = kc__tr ? ta.tr : high - low
rangema = ta.sma(range_1, lengthKC)
upperKC = ma + rangema * multKC
lowerKC = ma - rangema * multKC
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 🍋 Squeeze Indication ─ LazyBear ©
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
sqzOn = lowerBB > lowerKC and upperBB < upperKC
sqzOff = lowerBB < lowerKC and upperBB > upperKC
noSqz = sqzOn == false and sqzOff == false
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 📊 Histogram ─ LazyBear ©
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
val = ta.linreg(changeSource - math.avg(math.avg(ta.highest(high, 
      lengthKC), ta.lowest(low, lengthKC)), ta.sma(close, 
      lengthKC)), lengthKC, 0)
iff_1 = val > nz(val[1]) ? sqz_pos_mom_css : sqz_pos_mom_rev_css 
iff_2 = val < nz(val[1]) ? sqz_neg_mom_css : sqz_neg_mom_rev_css
bcolor = val > 0 ? iff_1 : iff_2
scolor = noSqz ? sqz_no_css : sqzOn ? sqz_ON_css : 
           sqz_released_css
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// ─© whvntr  
//%%%%%%%%%%%%%%%%%%%%%%%%%INT%%%%%%%%%%%%%%%%%%%%%%%%%
plot_hist = input.bool(true
     , group = '☑ LazyBear Histogram'
     , tooltip = 'LazyBear Histogram'
     , title = '')
plot_cross = input.bool(true
     , group ='☑ LazyBear Crosses'
     , tooltip = 'LazyBear Crosses'
     , title = '')
zero_line = 0
var string plotStyle = input.string('Columns'
     , title='🛞'
     , options=['Histogram', 'Columns']
     , group = 'Bands')
lineStyle = plotStyle == 'Histogram' ? plot.style_histogram : plot.style_columns
plot(plot_hist ? val : na, color = bcolor
     , title = 'Use Condition: SQZ_MULT..'
     , style= plotStyle == 'Histogram' ? plot.style_histogram : plot.style_columns
     , linewidth=4
     , offset = 0
     , editable = false)
plot(plot_cross ? zero_line : na, color=scolor
     , title = 'Use Condition: SQZ_MULT..'
     , style=plot.style_cross,linewidth=2 ,offset = 0
     , editable = false)
show_bg_exit = input.bool(true
      , title = '‎ 𝑺𝒉𝒐𝒓𝒕𝒔'
      , group = 'Highlights'
      , inline = 'exit')
hide_bg_exit =  show_bg_exit ? true : na  
show_bg_take = input.bool(true
      , title = '‎ 𝑳𝒐𝒏𝒈𝒔'
      , group = 'Highlights'
      , inline = 'take')
hide_bg_take =  show_bg_take ? true : na 
float upperint = input.float(2
      , title = ''
      , group = 'Bands'
      , inline = 'upperline'
      , step = 0.05
      , minval = 0)
float midint = input.float(0
      , title = ''
      , group = 'Bands'
      , inline = 'midline'
      , step = 0.05)
float lowerint = input.float(-2
      , title = ''
      , group = 'Bands'
      , inline = 'lowerline'
      , step = 0.05
      , maxval = 0)
//%%%%%%%%%%%%%%%%%%%%%%%%%PLOT%%%%%%%%%%%%%%%%%%%%%%%% 
//%%%%%%%%%%%%%%%%%%%%%%%%%%HLINE%%%%%%%%%%%%%%%%%%%%%% 
hline(hlines_visibility ? upperint : na, 'Upperline'
      , linestyle = hline.style_dashed
      , linewidth = 1
      , color = upperline_css
      , editable = false)
hline(hlines_visibility ? midint : na, 'Midline'
      , linestyle = hline.style_solid
      , linewidth = 1
      , color = midline_css
      , editable = false)
hline(hlines_visibility ? lowerint : na, 'Lowerline'
      , linestyle = hline.style_dashed
      , linewidth = 1
      , color = lowline_css
      , editable = false)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


non_repainting = barstate.isconfirmed == true


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// ✛ First Gray EXIT Position ─© whvntr  
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pos = val > nz(val[1])
not_pos = not pos
exit_pos = scolor == sqz_released_css
bear_sqz_bg = request.security(syminfo.tickerid
     , keepFrameFor
     , exit_pos[0] and not exit_pos[1] and not_pos 
     and non_repainting) 
bear_sqz_alert = request.security(syminfo.tickerid
     , keepFrameFor
     , exit_pos[0] and not exit_pos[1] and not_pos 
     and non_repainting) 
bear_bg_pick = bear_sqz_bg[0] and not bear_sqz_bg[1]
bear_alert = bear_sqz_alert[0] and not bear_sqz_alert[1]
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// ✛ First Gray TAKE Position ─© whvntr
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
neg = val < nz(val[1])
not_neg = not neg
take_pos = scolor == sqz_released_css
bull_sqz_bg = request.security(syminfo.tickerid
     , keepFrameFor
     , take_pos[0] and not take_pos[1] and not_neg 
     and non_repainting) 
bull_sqz_alert = request.security(syminfo.tickerid
     , keepFrameFor
     , take_pos[0] and not take_pos[1] and not_neg 
     and non_repainting) 
bull_bg_pick = bull_sqz_bg[0] and not bull_sqz_bg[1]
bull_alert = bull_sqz_alert[0] and not bull_sqz_alert[1]
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//  ║ Highlight ─© whvntr  
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bg_bear = bear_bg_pick
bgcolor(bg_bear and hide_bg_exit ? bg_bear_css 
      : INVS
      , title = '𝘚𝘩𝘰𝘳𝘵𝘴'
      , editable = false)
bg_bull = bull_bg_pick
bgcolor(bg_bull and hide_bg_take ? bg_bull_css 
      : INVS
      , title = '𝘓𝘰𝘯𝘨𝘴'
      , editable = false)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//  🌙 Alerts ─© whvntr  
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
if bear_alert == true and close[1] == bear_alert
    alert("➖ 𝙂𝙤 𝙎𝙝𝙤𝙧𝙩",  alert.freq_once_per_bar_close)
alertcondition(bear_alert
      , title= "➖ 𝑺𝒉𝒐𝒓𝒕𝒔"
      , message = '➖ SQZ_MULT ━ whvntr')
  
if bull_alert == true and close[1] == bull_alert
    alert("➕ 𝙂𝙤 𝙇𝙤𝙣𝙜",  alert.freq_once_per_bar_close)
alertcondition(bull_alert
      , title= "➕ 𝑳𝒐𝒏𝒈𝒔"
      , message = '➕ SQZ_MULT ━ whvntr')
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//  🌙 Alerts ─© whvntr  
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$