Carrey's Structure Supply and Demand
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © CarreyTrades

//@version=5
indicator("Carrey's Structure Supply and Demand", shorttitle="Structure S/D", overlay=true)

// Inputs

bigbar   = input.int(68, title="Big Bar Body Size", minval=0, maxval=100, tooltip="This is the percentage of the full candle size that the body must be to consider it a Big Bar")
smallbar = input.int(20, title="Big Bar Body Size", minval=0, maxval=100, tooltip="This is the percentage of the full candle size that the body must be to consider it a Small Bar")
Offset   = input.int(25, title="Box Width", minval=0)

eRBR = input.bool(true, "Rally Base Rally")
eDBD = input.bool(true, "Drop Base Drop")
eDBR = input.bool(true, "Drop Base Rally")
eRBD = input.bool(true, "Rally Base Drop")

labels          = input.bool(false, title="Enable Labels")
var extendRight = input(false, 'Extend Boxes Right', inline="extend", group="BB Course Indicators")

// Calculations

bigb    = bigbar / 100   // Convert input to decimal
smallb  = smallbar / 100 // Convert input to decimal

rng  = high - low
body = math.abs(open - close)
size = body / rng

bull = open < close
bear = close < open

big   = size >= bigb ? true : false
small = size <= smallb ? true : false
up    = high[1] < high
dn    = low[1] > low

rallyc = bull and big and up ? true : false
dropc  = bear and big and dn ? true : false
basec  = small ? true : false

//plotshape(rallyc, title="Rally Bar", style=shape.labelup, location=location.belowbar, color=color.green, text="Rally", textcolor=color.white)
//plotshape(basec, title="Base Bar", style=shape.labelup, location=location.belowbar, color=color.yellow, text="Base", textcolor=color.white)
//plotshape(dropc, title="Drop Bar", style=shape.labeldown, location=location.abovebar, color=color.red, text="Drop", textcolor=color.white)


// Base Rules

bullret = (high[1] - (rng[1] / 2)) > low
bearret = (low[1] + (rng[1] / 2)) < high

bullext = (high[1] + (rng[1] / 4)) < high
bearext = (low[1] - (rng[1] / 4)) > low

bubase = small and not(bullret or bullext) ? true : false
bebase = small and not(bearret or bearext) ? true : false
base1  = bubase or bebase ? true : false

bui   = high[1] > high and not(bullret) ? true : false
bei   = low[1] < low and not(bearret) ? true : false
base2 = bui or bei ? true : false

base3 = base1[1] or base2[1] ? basec ? true : false : false
base4 = base3[1] ? basec ? true : false : false
base5 = base4[1] ? basec ? true : false : false

base = base1 or base2 or base3 or base4 or base5

// Structure Logic

Rally = rallyc ? true : false
Drop  = dropc ? true : false

BaseUp = (Rally[1] and base) or (Rally[2] and base and base[1]) or (Rally[3] and base and base[1] and base[2]) or (Rally[4] and base and base[1] and base[2] and base[3]) ? true : false
BaseDn = (Drop[1]  and base) or (Drop[2] and base and base[1]) or (Drop[3] and base and base[1] and base[2]) or (Drop[4] and base and base[1] and base[2] and base[3]) ? true : false

RBR = eRBR ? (BaseUp[1] and rallyc ? true : false) : na
DBD = eDBD ? (BaseDn[1] and dropc ? true : false) : na
DBR = eDBR ? (BaseDn[1] and rallyc ? true : false) : na
RBD = eRBD ? (BaseUp[1] and dropc ? true : false) : na

// Plot Structures

plotshape(labels ? RBR : na, title="RBR", style=shape.labelup, location=location.belowbar, color=color.green, text="RBR", textcolor=color.white)
plotshape(labels ? DBD : na, title="DBD", style=shape.labeldown, location=location.abovebar, color=color.red, text="DBD", textcolor=color.white)
plotshape(labels ? DBR : na, title="DBR", style=shape.labelup, location=location.belowbar, color=color.orange, text="DBR", textcolor=color.white)
plotshape(labels ? RBD : na, title="RBD", style=shape.labeldown, location=location.abovebar, color=color.orange, text="RBD", textcolor=color.white)


var extending = extend.none
if extendRight
    extending := extend.right

if RBR or DBR
    box.new(bar_index - 1 , high[1], bar_index + Offset, low[1], border_color = color.green, bgcolor = color.new(color.green, 60), extend=extending)

if DBD or RBD
    box.new(bar_index - 1 , low[1], bar_index + Offset, high[1], border_color = color.red, bgcolor = color.new(color.red, 60), extend=extending) 

