// █▀▀▄ ──▀ █▀▀█ █▀▀█ █▀▀▀ █──█ █▀▄▀█
// █▀▀▄ ──█ █──█ █▄▄▀ █─▀█ █──█ █─▀─█
// ▀▀▀─ █▄█ ▀▀▀▀ ▀─▀▀ ▀▀▀▀ ─▀▀▀ ▀───▀
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Bjorgum
//@version=5
indicator ('Bjorgum Key Levels', 'Bj Key Levels', overlay= true, max_boxes_count= 500, max_labels_count= 500, max_lines_count=500)
import Bjorgum/BjCandlePatterns/2 as bj
// ================================== //
// ------------> Tips <-------------- //
// ================================== //
leftTip = "Look left for swing high/low in x number of bars to form pivot. The higher the number, the higher the script looks to the left for the highest/lowest point before drawing pivot"
rightTip = "Look right for swing high/low in x number of bars to form pivot. The higher the number, the higher the script looks to the right for the highest/lowest point before drawing pivot"
nPivTip = "This sets the array size, or the number of pivots to track at a time (x highs, and x number of lows)"
atrLenTip = "Number of bars to average. ATR is used to standardize zone width between assets and timeframes"
multTip = "ATR multiplier to set zone width. Default is half of one ATR from box bottom to box top"
perTip = "Max zone size as a percent of price. Some assets can be too volatile at low prices creating an unreasonably sized zone"
maxTip = "Number of boxes for candlestick patterns to track historically. Note: the higher the number the less pivot zones will be tracked when looking back in time due to the limitation on the number of box elements allowed at once"
futTip = "Number of bars to offset labels for price levels"
srcTip = "Source input for pivots. Default tracks the highest and lowest bodies of HA candles to average price action, which can result in a level that sits in the overlap of support and resistance"
alignZonesTip = "Aligns recurring zones who's edges overlap an existing zone creating a zone that ages in time and intensifies visually"
extendTip = "Extends current zones right"
lLabTip = "Show labels for price levels extended off Key Levels"
dhighsTip = "Disabling will prevent highs from being tracked"
dlowsTip = "Disabling will prevent lows from being tracked"
detectBOTip = "Show points that price action breaks above all pivots. An arrow from below is displayed"
detectBDTip = "Show points that price action breaks below all pivots. An arrow from above is displayed"
breakUpTip = "Show points that price action breaks above resistance. An arrow from below is displayed"
breakDnTip = "Show points that price action breaks below support. An arrow from above is displayed"
falseBullTip = "Show points that price action initially breaks below support before reversing. False moves can lead to fast moves in the opposite direction (bear trap). A large arrow from below is displayed"
falseBearTip = "Show points that price action initially breaks above resistance before reversing. False moves can lead to fast moves in the opposite direction (bull trap). A large arrow from above is displayed"
supPushTip = "Show up candles that are detected within a support zone. Can show points support is being respected. A triangle from below is displayed"
resPushTip = "Show down candles that are detected within a resistance zone. Can show points resistance is being respected. A triangle from above is displayed"
curlTip = "Show Bjorgum TSI 'curl' when candles are detected in the range of a key zone. Can show momentum shift at Key Levels. (Correlates to Bjorgum TSI indicator)"
repaintTip = "Wait for candles end before detecting patterns. False will show potential patterns forming before they are confirmed."
labelsTip = "Show a label for detected candle patterns"
sBoxTip = "Show a box around detected candle patterns"
dTip = "Detect Doji candle patterns"
beTip = "Detect Engulfing patterns"
hsTip = "Detect Hammers and Shooting Star patterns"
dgTip = "Detect Dragonfly Doji and Gravestone Doji patterns"
twTip = "Detect Tweezer Top and Tweezer Bottom patterns"
stTip = "Detect Spinning Top patterns"
pcTip = "Detect Piercing and Dark Cloud Cover patterns"
bhTip = "Detect Harami candle patterns"
lsTip = "Detect Long Upper Shadow and Long Lower Shadow patterns"
ecWickTip = "Determines if engulfing candles must engulf the wick or just the body of the preceding candle"
colorMatchTip = "Determines if hammers must be up candles and shooting stars must be down candles"
closeHalfTip = "Determines if Tweezer patterns must close beyond the half way point of the preceding candle"
atrMaxTip = "Maximum size of setup candles (as a multiplier of the current ATR)"
rejectWickTip = "The maximum wick size as a percentage of body size allowable for a rejection wick on the resolution candle of the pattern. 0 disables the filter"
hammerFibTip = "The relationship of body to candle size for hammers and stars. (ie. body is 33% of total candle size)."
hsShadowPercTip = "The maximum allowable opposing wick size as a percent of body size (ex. top wick for a hammer pattern etc.)"
hammerSizeTip = "The minimum size of hammers, stars, or long shadows as a multiplier of ATR. (To filter out tiny setups)"
dojiSizeTip = "The relationship of body to candle size (ie. body is 5% of total candle size)."
dojiWickSizeTip = "Maximum wick size comparative to the opposite wick. (eg. 2 = bottom wick must be less than or equal to 2x the top wick)."
luRatioTip = "A relationship of the upper wick to the overall candle size expressed as a percent."
lookbackTip = "Number of candles that can be included in a false break signal"
swingTip = "Swing detection is used to filter signals on breakout type signals. A higher number will mean more significant points, but less of them"
reflectTip = "Filter to ensure a setup is a significant swing point. Look back this far"
offsetTip = "Candle pattern high/low distance from absolute swing high/low. Example: 0 would filter patterns that are only the highest/lowest, 1 filters second highest over the significant length, etc."
bullPivotTip = "Color of bullish Key Levels\n(border, background)"
bearPivotTip = "Color of bearish Key Levels\n(border, background)"
breakoutTip = "Color of breakout arrows\n(bull, bear,)"
SnRTip = "Color of triangles for broken support or resistance\n(bull, bear)"
falseBreakTip = "Color of arrows for false breaks\n(bull, bear, arrow max height in pixels)"
moveTip = "Color of triangles for candles that are detected within zones\n(bull, bear)"
patTip = "Color of boxes that wrap candestick patterns\nBackgrounds: (bull, neutral, bear)\nBorders: (bull, neutral, bear)"
labTip = "Color of labels that mark candestick patterns\nText: (bull, neutral, bear)\nLabels: (bull, neutral, bear)"
stratTip = "TSI speed control presets. Both speeds correlate to the Bjorgum TSI indicator"
// ================================== //
// ---------> User Input <----------- //
// ================================== //
left = input.int (20 , "Look Left" , group= "Zones" , tooltip= leftTip )
right = input.int (15 , "Look Right" , group= "Zones" , tooltip= rightTip )
nPiv = input.int (4 , "Number of Pivots" , group= "Zones" , tooltip= nPivTip )
atrLen = input.int (30 , "ATR Length" , group= "Zones" , tooltip= atrLenTip )
mult = input.float (0.5 , "Zone Width (ATR)" , group= "Zones" , tooltip= multTip , step = 0.1)
per = input.float (5 , "Max Zone Percent" , group= "Zones" , tooltip= perTip )
max = input.float (10 , "Max Boxes for Patterns" , group= "Zones" , tooltip= maxTip )
fut = input.int (30 , "Offset For Labels" , group= "Zones" , tooltip= futTip )
src = input.string ("HA" , "Source For Pivots" , group= "Zones" , tooltip= srcTip , options= ["HA", "High/Low Body", "High/Low"])
alignZones = input.bool (true , "Align Zones" , group= "Zones" , tooltip= alignZonesTip )
extend = input.bool (false , "Extend Right" , group= "Zones" , tooltip= extendTip )
lLab = input.bool (false , "Show Level Labels" , group= "Zones" , tooltip= lLabTip )
dhighs = input.bool (true , "Detect Pivot Highs" , group= "Detection" , tooltip= dhighsTip )
dlows = input.bool (true , "Detect Pivot Lows" , group= "Detection" , tooltip= dlowsTip )
detectBO = input.bool (false , "Detect Breakout" , group= "Detection" , tooltip= detectBOTip )
detectBD = input.bool (false , "Detect Breakdown" , group= "Detection" , tooltip= detectBDTip )
breakUp = input.bool (false , "Detect Resistance Break" , group= "Detection" , tooltip= breakUpTip )
breakDn = input.bool (false , "Detect Support Break" , group= "Detection" , tooltip= breakDnTip )
falseBull = input.bool (false , "Detect False Breakdown" , group= "Detection" , tooltip= falseBullTip )
falseBear = input.bool (false , "Detect False Breakup" , group= "Detection" , tooltip= falseBearTip )
supPush = input.bool (false , "Detect Moves Off Support" , group= "Detection" , tooltip= supPushTip )
resPush = input.bool (false , "Detect Moves Off Resistance" , group= "Detection" , tooltip= resPushTip )
curl = input.bool (false , "Detect TSI Curl" , group= "Detection" , tooltip= curlTip )
repaint = input.bool (true , "Wait For Confirmed Bar" , group= "Candle Patterns" , tooltip= repaintTip )
labels = input.bool (false , "Show Label" , group= "Candle Patterns" , tooltip= labelsTip )
sBox = input.bool (false , "Show Boxes Around Patterns" , group= "Candle Patterns" , tooltip= sBoxTip )
d_ = input.bool (false , "Detect Doji" , group= "Candle Patterns" , tooltip= dTip )
be_ = input.bool (false , "Detect Engulfing" , group= "Candle Patterns" , tooltip= beTip )
hs_ = input.bool (false , "Detect Hammers and Stars" , group= "Candle Patterns" , tooltip= hsTip )
dg_ = input.bool (false , "Detect Dragons and Graves" , group= "Candle Patterns" , tooltip= dgTip )
tw_ = input.bool (false , "Detect Tweezers" , group= "Candle Patterns" , tooltip= twTip )
st_ = input.bool (false , "Detect Spinning Top" , group= "Candle Patterns" , tooltip= stTip )
pc_ = input.bool (false , "Detect Piercing and Clouds" , group= "Candle Patterns" , tooltip= pcTip )
bh_ = input.bool (false , "Detect Harami" , group= "Candle Patterns" , tooltip= bhTip )
ls_ = input.bool (false , "Detect Long Shadows" , group= "Candle Patterns" , tooltip= lsTip )
alertMode = input.string (alert.freq_once_per_bar_close , "Alerts Mode" , group = "Alert Frequency" , options= [alert.freq_once_per_bar, alert.freq_once_per_bar_close])
ecWick = input.bool (false , "Engulfing Must Engulf Wick" , group= "Candle Filters" , tooltip= ecWickTip )
colorMatch = input.bool (false , "H&S Must Match Color" , group= "Candle Filters" , tooltip= colorMatchTip )
closeHalf = input.bool (false , "Tweezer Close Over Half" , group= "Candle Filters" , tooltip= closeHalfTip )
atrMax = input.float (0.0 , "Max Candle Size (× ATR)" , group= "Candle Filters" , tooltip= atrMaxTip , step= 0.1 )
rejectWickMax = input.float (0.0 , "[EC] Max Reject Wick Size" , group= "Candle Filters" , tooltip= rejectWickTip , step= 1 )
hammerFib = input.float (33 , "[HS] H&S Ratio (%)" , group= "Candle Filters" , tooltip= hammerFibTip , step= 1 )
hsShadowPerc = input.float (5 , "[HS] H&S Opposing Shadow (%)" , group= "Candle Filters" , tooltip= hsShadowPercTip , step= 1 )
hammerSize = input.float (0.1 , "[HS] H&S Min Size (× ATR)" , group= "Candle Filters" , tooltip= hammerSizeTip , step= 0.1 )
dojiSize = input.float (5 , "[DJ] Doji Size (%)" , group= "Candle Filters" , tooltip= dojiSizeTip , step= 1 )
dojiWickSize = input.float (2 , "[DJ] Max Doji Wick Size" , group= "Candle Filters" , tooltip= dojiWickSizeTip , step= 1 )
luRatio = input.float (75 , "[LS] Long Shadow (%)" , group= "Candle Filters" , tooltip= luRatioTip , step= 1 )
lookback = input.int (2 , "Lookback For Breaks" , group= "Lookback" , tooltip= lookbackTip )
swing = input.int (5 , "swing High/Low" , group= "Lookback" , tooltip= swingTip )
reflect = input.int (10 , "Significant High/Low" , group= "Lookback" , tooltip= reflectTip )
offset = input.int (1 , "Consider Bar From High/Low" , group= "Lookback" , tooltip= offsetTip )
bullBorder = input.color (color.new (#64b5f6, 60), "", inline= "0" , group= "Pivot Color" )
bullBgCol = input.color (color.new (#64b5f6, 95), "", inline= "0" , group= "Pivot Color" , tooltip= bullPivotTip )
bearBorder = input.color (color.new (#ffeb3b, 60), "", inline= "1" , group= "Pivot Color" )
bearBgCol = input.color (color.new (#ffeb3b, 95), "", inline= "1" , group= "Pivot Color" , tooltip= bearPivotTip )
upCol = input.color (color.new (#ff6d00, 25), "", inline= "2" , group= "Breakout Color" )
dnCol = input.color (color.new (#ff00ff, 25), "", inline= "2" , group= "Breakout Color" , tooltip= breakoutTip )
supCol = input.color (color.new (#17ff00, 25), "", inline= "3" , group= "S&R Break Color" )
resCol = input.color (color.new (#ff0000, 25), "", inline= "3" , group= "S&R Break Color" , tooltip= SnRTip )
fBull = input.color (color.new (#17ff00, 25), "", inline= "4" , group= "False Break Color" )
fBear = input.color (color.new (#ff0000, 25), "", inline= "4" , group= "False Break Color" )
arrowMax = input.int (75 , "", inline= "4" , group= "False Break Color" , tooltip= falseBreakTip )
moveBullCol = input.color (color.new (#64b5f6, 25), "", inline= "5" , group= "Moves From S&R Color" )
moveBearCol = input.color (color.new (#ffeb3b, 25), "", inline= "5" , group= "Moves From S&R Color" , tooltip= moveTip )
curlBullCol = input.color (color.new (#17ff00, 40), "", inline= "6" , group= "Momentum Curl Color" )
curlBearCol = input.color (color.new (#f3ff00, 40), "", inline= "6" , group= "Momentum Curl Color" , tooltip= curlTip )
patBullBg = input.color (color.new (#17ff00, 90), "", inline= "7" , group= "Pattern Box Color" )
patNeutBg = input.color (color.new (#b2b5be, 90), "", inline= "7" , group= "Pattern Box Color" )
patBearBg = input.color (color.new (#ff0000, 90), "", inline= "7" , group= "Pattern Box Color" )
patBullBo = input.color (color.new (#17ff00, 80), "", inline= "8" , group= "Pattern Box Color" )
patNeutBo = input.color (color.new (#b2b5be, 80), "", inline= "8" , group= "Pattern Box Color" )
patBearBo = input.color (color.new (#ff0000, 80), "", inline= "8" , group= "Pattern Box Color" , tooltip= patTip )
textBullCol = input.color (color.new (#17ff00, 0), "", inline= "9" , group= "Label Color (Text/Bg)" )
textNeutCol = input.color (color.new (#b2b5be, 0), "", inline= "9" , group= "Label Color (Text/Bg)" )
textBearCol = input.color (color.new (#ff0000, 0), "", inline= "9" , group= "Label Color (Text/Bg)" )
labBullCol = input.color (color.new (#17ff00, 80), "", inline= "10" , group= "Label Color (Text/Bg)" )
labNeutCol = input.color (color.new (#b2b5be, 80), "", inline= "10" , group= "Label Color (Text/Bg)" )
labBearCol = input.color (color.new (#ff0000, 80), "", inline= "10" , group= "Label Color (Text/Bg)", tooltip= labTip )
strat = input.string ("Fast" , "Select a Speed" , group= "TSI Speed Control" , tooltip= stratTip , options= ["Fast", "Slow"])
longf = input.int (25 , "Long Length" , group= "TSI Fast Settings" )
shortf = input.int (5 , "Short Length" , group= "TSI Fast Settings" )
signalf = input.int (14 , "Signal Length" , group= "TSI Fast Settings" )
longs = input.int (25 , "Long Length" , group= "TSI Slow Settings" )
shorts = input.int (13 , "Short Length" , group= "TSI Slow Settings" )
signals = input.int (13 , "Signal Length" , group= "TSI Slow Settings" )
// ================================== //
// -----> Immutable Constants <------ //
// ================================== //
sync = bar_index
labUp = label.style_label_up
labDn = label.style_label_down
confirmed = barstate.isconfirmed
extrap = extend ? extend.right : extend.none
var pivotHigh = array.new_box (nPiv)
var pivotLows = array.new_box (nPiv)
var highBull = array.new_bool (nPiv)
var lowsBull = array.new_bool (nPiv)
var boxes = array.new_box ()
haSrc = src == "HA"
hiLoSrc = src == "High/Low"
tsifast = strat == "Fast"
tsislow = strat == "Slow"
// ================================== //
// ---> Functional Declarations <---- //
// ================================== //
atr = ta.atr (atrLen)
perMax = close* 0.02
min = math.min (perMax, atr*0.3)
_haBody() =>
haClose = (open + high + low + close) / 4
haOpen = float(na)
haOpen := na(haOpen[1]) ? (open + close) / 2 :
(nz(haOpen[1]) + nz(haClose[1])) / 2
[haOpen, haClose]
_extend(_x) =>
for i = 0 to array.size (_x)-1
box.set_right (array.get (_x, i), sync)
_arrayLoad(_x, _max, _val) =>
array.unshift (_x, _val)
if array.size (_x) > _max
array.pop (_x)
_arrayBox(_x, _max, _val) =>
array.unshift (_x, _val)
if array.size (_x) > _max
_b = array.pop (_x)
if extend
box.set_extend (_b, extend.none)
_arrayWrap(_x, _max, _val) =>
array.unshift (_x, _val)
if array.size (_x) > _max
box.delete(array.pop (_x))
_delLab(_x) =>
if array.size(_x) > 0
label.delete (array.pop (_x))
_delLine(_x) =>
if array.size(_x) > 0
line.delete (array.pop (_x))
_delLevels(_x, _y) =>
for i = 0 to array.size (_x)-1
_delLab (_x)
_delLine (_y)
_box(_x1, _t, _r, _b, _boCol, _bgCol, _e) =>
box.new( _x1, _t, _r, _b ,
xloc = xloc.bar_index ,
extend = _e ,
border_color= _boCol ,
bgcolor = _bgCol )
_wrap(_cond, _x, _bb, _bc, _bgc) =>
_t = ta.highest (high, _bb) + min
_b = ta.lowest (low , _bb) - min
_l = bar_index - _bb
_r = bar_index + 1
if _cond
_arrayWrap (_x, max, _box (_l, _t, _r, _b, _bc, _bgc, extend.none))
_getBox(_x,_i) =>
_box = array.get (_x,_i)
_t = box.get_top (_box)
_b = box.get_bottom (_box)
[_t, _b]
_align(_x,_y) =>
for i = 0 to array.size (_x) -1
[_T, _B] = _getBox (_y, 0)
[_t, _b] = _getBox (_x, i)
if _T > _b and _T < _t or
_B < _t and _B > _b or
_T > _t and _B < _b or
_B > _b and _T < _t
box.set_top (array.get (_y, 0), _t)
box.set_bottom (array.get (_y, 0), _b)
_color(_x, _y) =>
var int _track = nPiv
for i = 0 to array.size (_x) -1
[t_, b_] = _getBox (_x, i)
_isBull = array.get (_y, i)
if close > t_ and not _isBull
box.set_extend( array.get (_x, i), extend.none)
array.set(_x, i, _box (sync , t_, sync, b_, bullBorder, bullBgCol, extrap))
array.set(_y, i, true)
_track += 1
if close < b_ and _isBull
box.set_extend( array.get (_x, i), extend.none)
array.set(_x, i, _box (sync , t_, sync, b_, bearBorder, bearBgCol, extrap))
array.set(_y, i, false)
_track -= 1
_track
_detect(_x,_y) =>
int _i = 0
bool _found = false
bool _isBull = na
while (not _found and _i < array.size (_x) )
[t_, b_] = _getBox (_x,_i)
if low < t_ and high > b_
_isBull := array.get (_y,_i)
_found := true
_i += 1
[_found, _isBull]
_falseBreak(_l) =>
bool _d = false
bool _u = false
for i = 1 to lookback
if _l[i] < _l and _l[i+1] >= _l and _l[1] < _l
_d := true
if _l[i] > _l and _l[i+1] <= _l and _l[1] > _l
_u := true
[_d, _u]
_numLevel(_x,_y) =>
int _above = 0
int _fill = 0
for i = 0 to array.size (_x)-1
_isBull = array.get (_x,i)
if _isBull
_above += 1
if not na(_isBull)
_fill += 1
for i = 0 to array.size (_y)-1
_isBull = array.get (_y,i)
if _isBull
_above += 1
if not na(_isBull)
_fill += 1
[_above, _fill]
_check(_src,_l) =>
bool _check = false
for i = 0 to _l
if _src[i]
_check := true
_check
_count(_src, _l) =>
int _result = 0
for i = 0 to _l
if _src > _src[i]
_result += 1
_result
_label(_x, _y, y, _s, _col1, _col2) =>
transp = math.min (color.t(_col1), color.t(_col2))
array.unshift (_x, label.new (sync+fut, y ,
text = str.tostring(math.round_to_mintick(y) ),
color = color.new(_col1, transp) ,
style = _s ,
textcolor = color.white ))
if not extend and fut > 0
array.unshift (_y, line.new (sync, y, sync+fut, y, color= color.new(_col1, transp)))
_level(_x, _y) =>
var label [] lab = array.new_label (nPiv)
var line [] lines = array.new_line (nPiv)
if barstate.islast and lLab
_delLevels (lab, lines)
for i = 0 to array.size (_x)-1
[_t, _b] = _getBox (_x,i)
_isBull = array.get (_y,i)
_col1 = _isBull ? bullBgCol : bearBgCol
_col2 = _isBull ? bullBorder : bearBorder
if close > _t
_label (lab, lines, _t, labUp, _col1, _col2)
if close < _b
_label (lab, lines, _b, labDn, _col1, _col2)
if close < _t and close > _b
_label (lab, lines, _t, labDn, _col1, _col2)
_label (lab, lines, _b, labUp, _col1, _col2)
_alert(_x, _y) =>
if _x
alert (_y + timeframe.period + ' chart. Price is ' + str.tostring(close), alertMode)
// ================================== //
// ----> Variable Calculations <----- //
// ================================== //
shortvar = tsifast ? shortf : shorts
longvar = tsifast ? longf : longs
signalvar = tsifast ? signalf : signals
tsi = ta.tsi (close, shortvar, longvar)
tsl = ta.ema (tsi, signalvar)
highest = close == ta.highest (close, right)
lowest = close == ta.lowest (close, right)
closeLows = ta.lowest (close, swing)
closeHigh = ta.highest (close, swing)
numLows = _count (low, reflect)
numHigh = _count (high, reflect)
[open_, close_] = _haBody ()
hiHaBod = math.max (close_, open_)
loHaBod = math.min (close_, open_)
hiBod = math.max (close, open)
loBod = math.min (close, open)
srcHigh = haSrc ? hiHaBod : hiLoSrc ? high : hiBod
srcLow = haSrc ? loHaBod : hiLoSrc ? low : loBod
pivot_high = ta.pivothigh (srcHigh, left, right)
pivot_low = ta.pivotlow (srcLow, left, right)
perc = close* (per/100)
band = math.min (atr*mult, perc) [right] /2
HH = pivot_high+ band
HL = pivot_high- band
LH = pivot_low+ band
LL = pivot_low- band
coDiff = close - open
// ================================== //
// --------> Logical Order <--------- //
// ================================== //
if pivot_high and dhighs and confirmed
_arrayLoad (highBull , nPiv, false)
_arrayBox (pivotHigh, nPiv, _box(sync[right], HH, sync, HL, bearBorder, bearBgCol, extrap))
if pivot_low and dlows and confirmed
_arrayLoad (lowsBull , nPiv, true)
_arrayBox (pivotLows, nPiv, _box(sync[right], LH, sync, LL, bullBorder, bullBgCol, extrap))
if alignZones
_align (pivotHigh, pivotHigh)
_align (pivotHigh, pivotLows)
_align (pivotLows, pivotLows)
_align (pivotLows, pivotHigh)
_extend (pivotHigh)
_extend (pivotLows)
trackHigh = _color (pivotHigh, highBull)
trackLows = _color (pivotLows, lowsBull)
// ================================== //
// ----> Conditional Parameters <---- //
// ================================== //
isLows = closeLows == close
isHigh = closeHigh == close
wasLows = _check (isLows, lookback)
wasHigh = _check (isHigh, lookback)
[above, total] = _numLevel (highBull, lowsBull)
moveAbove = trackHigh > trackHigh[1]
moveBelow = trackLows < trackLows[1]
resBreak = (trackLows > trackLows[1] or moveAbove)
supBreak = (trackHigh < trackHigh[1] or moveBelow)
breakOut = moveAbove and highest and above == total
breakDwn = moveBelow and lowest and above == 0
[dh, uh] = _falseBreak (trackHigh)
[dl, ul] = _falseBreak (trackLows)
falseBreakBull = wasLows and (dh or dl)
falseBreakBear = wasHigh and (uh or ul)
[fh,hb] = _detect (pivotHigh, highBull)
[fl,lb] = _detect (pivotLows, lowsBull)
bull = (fh or fl) and (hb or lb)
bear = (fh or fl) and not (hb or lb)
bullCheck = not resBreak and not resBreak[1] and (fh or fl) and close > open and (hb or lb)
bearCheck = not supBreak and not supBreak[1] and (fh or fl) and close < open and not (hb or lb)
highrange = reflect-offset
lowsrange = offset
sigLows = numLows <= lowsrange
sigHigh = numHigh >= highrange
isBull1 = sigLows and bull
isBear1 = sigHigh and bear
isBull2 = (sigLows or sigLows[1]) and (bull or bull[1])
isBear2 = (sigHigh or sigHigh[1]) and (bear or bear[1])
data = tsi > tsi[1] and tsi < tsl
dtat = tsi < tsi[1] and tsi > tsl
hMatch = not colorMatch or close > open
sMatch = not colorMatch or close < open
hsFilter = bj.barRange() >= hammerSize * atr
atrMaxSize = bj.barRange() <= atrMax * atr or atrMax == 0.0
rp = confirmed or not repaint
// ================================== //
// -----> Pattern Recognition <------ //
// ================================== //
dw = isBull1 and rp and d_ and atrMaxSize and bj.doji (dojiSize = dojiSize, dojiWickSize = dojiWickSize)
db = isBear1 and rp and d_ and atrMaxSize and bj.doji (dojiSize = dojiSize, dojiWickSize = dojiWickSize)
bew = isBull2 and rp and be_ and atrMaxSize and bj.bullEngulf (maxRejectWick = rejectWickMax, mustEngulfWick = ecWick)
beb = isBear2 and rp and be_ and atrMaxSize and bj.bearEngulf (maxRejectWick = rejectWickMax, mustEngulfWick = ecWick)
h = isBull1 and rp and hs_ and atrMaxSize and bj.hammer (ratio = hammerFib, shadowPercent = hsShadowPerc) and hsFilter and hMatch
ss = isBear1 and rp and hs_ and atrMaxSize and bj.star (ratio = hammerFib, shadowPercent = hsShadowPerc) and hsFilter and sMatch
dd = isBull1 and rp and dg_ and atrMaxSize and bj.dragonflyDoji ()
gd = isBear1 and rp and dg_ and atrMaxSize and bj.gravestoneDoji ()
tb = isBull2 and rp and tw_ and atrMaxSize and bj.tweezerBottom (closeUpperHalf = closeHalf)
tt = isBear2 and rp and tw_ and atrMaxSize and bj.tweezerTop (closeLowerHalf = closeHalf)
stw = isBull1 and rp and st_ and atrMaxSize and bj.spinningTop ()
stb = isBear1 and rp and st_ and atrMaxSize and bj.spinningTop ()
p = isBull1 and rp and pc_ and atrMaxSize and bj.piercing ()
dcc = isBear1 and rp and pc_ and atrMaxSize and bj.darkCloudCover ()
bhw = isBull1 and rp and bh_ and atrMaxSize and bj.haramiBull ()
bhb = isBear1 and rp and bh_ and atrMaxSize and bj.haramiBear ()
ll = isBull1 and rp and ls_ and atrMaxSize and bj.lls (ratio = luRatio) and hsFilter
lu = isBear1 and rp and ls_ and atrMaxSize and bj.lus (ratio = luRatio) and hsFilter
// ================================== //
// ------> Graphical Display <------- //
// ================================== //
plotFalseDn = falseBull and falseBreakBull
plotFalseUp = falseBear and falseBreakBear
falseUpCol = plotFalseUp ? upCol : na
falseDnCol = plotFalseDn ? dnCol : na
plotBreakOut = breakOut and detectBO and not plotFalseDn
plotBreakDn = breakDwn and detectBD and not plotFalseUp
plotResBreak = resBreak and breakUp and not (plotBreakOut or plotFalseDn)
plotSupBreak = supBreak and breakDn and not (plotBreakDn or plotFalseUp)
plotBullCheck = bullCheck and supPush
plotBearCheck = bearCheck and resPush
plotCurlBull = curl and data and bull
plotCurlBear = curl and dtat and bear
plotarrow (plotFalseUp ? coDiff : na , colorup = fBull , colordown= fBear , maxheight= arrowMax)
plotarrow (plotFalseDn ? coDiff : na , colorup = fBull , colordown= fBear , maxheight= arrowMax)
plotshape (plotBreakOut , style=shape.arrowup , location=location.belowbar, color= upCol , size= size.small)
plotshape (plotBreakDn , style=shape.arrowdown , location=location.abovebar, color= dnCol , size= size.small)
plotshape (plotResBreak , style=shape.arrowup , location=location.belowbar, color= supCol, size= size.small)
plotshape (plotSupBreak , style=shape.arrowdown , location=location.abovebar, color= resCol, size= size.small)
plotshape (plotBullCheck , style=shape.triangleup , location=location.belowbar, color= moveBullCol)
plotshape (plotBearCheck , style=shape.triangledown, location=location.abovebar, color= moveBearCol)
plotshape (plotCurlBull , style=shape.triangleup , location=location.belowbar, color= curlBullCol)
plotshape (plotCurlBear , style=shape.triangledown, location=location.abovebar, color= curlBearCol)
bj.dLab (dw and labels, labNeutCol, textNeutCol), _wrap (dw and sBox, boxes, 1, patNeutBo, patNeutBg)
bj.bewLab (bew and labels, labBullCol, textBullCol), _wrap (bew and sBox, boxes, 2, patBullBo, patBullBg)
bj.hLab (h and labels, labBullCol, textBullCol), _wrap (h and sBox, boxes, 1, patBullBo, patBullBg)
bj.ddLab (dd and labels, labBullCol, textBullCol), _wrap (dd and sBox, boxes, 1, patBullBo, patBullBg)
bj.tbLab (tb and labels, labBullCol, textBullCol), _wrap (tb and sBox, boxes, 2, patBullBo, patBullBg)
bj.stwLab (stw and labels, labNeutCol, textNeutCol), _wrap (stw and sBox, boxes, 1, patBullBo, patNeutBg)
bj.pLab (p and labels, labBullCol, textBullCol), _wrap (p and sBox, boxes, 2, patBullBo, patBullBg)
bj.hwLab (bhw and labels, labBullCol, textBullCol), _wrap (bhw and sBox, boxes, 2, patBullBo, patBullBg)
bj.llsLab (ll and labels, labBullCol, textBullCol), _wrap (ll and sBox, boxes, 1, patBullBo, patBullBg)
bj.dLab (db and labels, labNeutCol, textNeutCol), _wrap (db and sBox, boxes, 1, patNeutBo, patNeutBg)
bj.bebLab (beb and labels, labBearCol, textBearCol), _wrap (beb and sBox, boxes, 2, patBearBo, patBearBg)
bj.ssLab (ss and labels, labBearCol, textBearCol), _wrap (ss and sBox, boxes, 1, patBearBo, patBearBg)
bj.gdLab (gd and labels, labBearCol, textBearCol), _wrap (gd and sBox, boxes, 1, patBearBo, patBearBg)
bj.ttLab (tt and labels, labBearCol, textBearCol), _wrap (tt and sBox, boxes, 2, patBearBo, patBearBg)
bj.stbLab (stb and labels, labNeutCol, textNeutCol), _wrap (stb and sBox, boxes, 1, patBearBo, patBearBg)
bj.dccLab (dcc and labels, labBearCol, textBearCol), _wrap (dcc and sBox, boxes, 2, patBearBo, patBearBg)
bj.hbLab (bhb and labels, labBearCol, textBearCol), _wrap (bhb and sBox, boxes, 2, patBearBo, patBearBg)
bj.lusLab (lu and labels, labBearCol, textBearCol), _wrap (lu and sBox, boxes, 1, patBearBo, patBearBg)
_level (pivotHigh, highBull)
_level (pivotLows, lowsBull)
// ================================== //
// -----> Alert Functionality <------ //
// ================================== //
alertcondition (resBreak , 'Resistance break' , 'Resistance broke on {{interval}} chart. Price is {{close}}' )
alertcondition (supBreak , 'Support break' , 'Support broke on {{interval}} chart. Price is {{close}}' )
alertcondition (bullCheck , 'Found support' , 'Pushing Off Key Level Support on {{interval}} chart. Price is {{close}}' )
alertcondition (bearCheck , 'Found resistance' , 'Pushing Off Key Level Resistance on {{interval}} chart. Price is {{close}}' )
alertcondition (falseBreakBull , 'False break down' , 'False Break Down on {{interval}} chart. Price is {{close}}' )
alertcondition (falseBreakBear , 'False break up' , 'False Break Up on {{interval}} chart. Price is {{close}}' )
alertcondition (breakOut , 'Breakout' , 'Breakout on {{interval}} chart. Price is {{close}}' )
alertcondition (breakDwn , 'Breakdown' , 'Breakdown on {{interval}} chart. Price is {{close}}' )
_alert (plotResBreak , 'Resistance broke on ' )
_alert (plotSupBreak , 'Support break ' )
_alert (plotBullCheck , 'Pushing off key level support on ' )
_alert (plotBearCheck , 'Pushing off key level resistance on ' )
_alert (plotFalseDn , 'False break down on ' )
_alert (plotFalseUp , 'False break up on ' )
_alert (plotBreakOut , 'Breakout on ' )
_alert (plotBreakDn , 'Breakdown on ' )
_alert (dw , 'Doji at support on ' )
_alert (db , 'Doji at resistance on ' )
_alert (bew , 'Bullish Engulfing on ' )
_alert (beb , 'Bearish Engulfing on ' )
_alert (h , 'Hammer candle on ' )
_alert (ss , 'Shooting star on ' )
_alert (dd , 'Dragonfly Doji on ' )
_alert (gd , 'Gravestone Doji on ' )
_alert (tb , 'Tweezer Bottom on ' )
_alert (tt , 'Tweezer Top on ' )
_alert (stw , 'White Spinning Top on ' )
_alert (stb , 'Black Spinning Top on ' )
_alert (p , 'Piercing on ' )
_alert (dcc , 'Dark Cloud Cover on ' )
_alert (bhw , 'Bullish Harami on ' )
_alert (bhb , 'Bearish Harami on ' )
_alert (ll , 'Long Lower Shadow on ' )
_alert (lu , 'Long Upper Shadow on ' )
// ____ __ _ ____
// ( __)( ( \( \
// ) _) / / ) D (
// (____)\_)__)(____/