Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
- // © moondevonyt
- //@version=5
- indicator("Supply and Demand Zones |Moon Dev|", shorttitle="SDZ |Moon Dev|", overlay=true, max_boxes_count= 500, max_bars_back = 500)
- // settings
- thres = input.float(10, 'Threshold %', minval= 0, maxval=100)
- div = input.int(50, 'Resolution', minval=2, maxval=500)
- custom_timeframe = input.timeframe('', 'Intrabar Timeframe')
- // picking oour color
- supplysh0w = input(true, 'Supply Sh0w', inline='supply', group = 'Style')
- c0l0rsupply = input(#FF0000, 'Color', inline='supply', group='Stlye')
- supplyar3a = input(true, 'Show area', inline='supply', group = 'Style')
- supplyavg = input(true, 'Show avg', inline = 'supply', group = 'Style')
- supply_weighted_avg = input(true, 'Show weighted avg', inline = 'supply', group = 'Style')
- show3qualibr1un = input(true, 'show equalibrium', inline='equi', group='Style')
- c0lor3qual = input(color.gray, 'Color', inline= 'equi', group = 'Style')
- avg3qualib = input(true, 'equalibrium avg', inline='equi', group='Style')
- w3ight3d_avg_3qual = input(true, 'weighted avg equalibrium', inline='equi', group='Style')
- showd3mand = input(true, 'show demand', inline='demand', group='Style')
- c0lor_d3mand = input(#008000, 'Color', inline='demand', group='Style')
- d3mandar3a = input(true, 'show area', inline='demand', group='Style')
- d3mandavg = input(true, 'show average', inline='demand', group='Style')
- d3mand_w3ight3d_avg = input(true, 'show weighted avg', inline='demand', group='Style')
- // Custom types
- type DemandSupplyCrate
- float quantity
- float last_amount
- float total
- float previous_total
- float total_accumulated
- float average_quantity
- bool fulfilled
- type DemandSupplyZone
- box box_obj
- line avg_path
- line weighted_avg_line
- // operations
- n = bar_index
- fetch_data()=> [high, low, volume]
- method configure_section(DemandSupplyZone id, x1, top, bottom, avg_val, wavg_val, display_section, display_avg, display_wavg)=>
- if display_section
- id.box_obj.set_lefttop(x1, top)
- id.box_obj.set_rightbottom(n, bottom)
- if display_avg
- id.avg_path.set_xy1(x1, avg_val)
- id.avg_path.set_xy2(n, avg_val)
- if display_avg
- id.weighted_avg_line.set_xy1(x1, wavg_val)
- id.weighted_avg_line.set_xy2(n, wavg_val)
- // setting up variables
- var peak_amount = 0.
- var bottom_amount = 0.
- var x_init = 0
- var total_accumulated = 0.
- // intrabar info
- [high_amount, low_amount, volume_data] = request.security_lower_tf(syminfo.tickerid, custom_timeframe, fetch_data())
- // initiliazation on intial bar
- if time == chart.left_visible_bar_time
- peak_amount := high
- bottom_amount := low
- total_accumulated := volume
- x_init := n
- else // accumulation
- peak_amount := math.max(high, peak_amount)
- bottom_amount := math.min(low, bottom_amount)
- total_accumulated += volume
- // establish regions
- var region_A = DemandSupplyZone.new(box.new(na, na, na, na, na, bgcolor = color.new(c0l0rsupply, 80)), line.new(na, na, na, na , color = c0l0rsupply), line.new(na, na, na, na, color=c0l0rsupply, style=line.style_dashed))
- var region_B = DemandSupplyZone.new(box.new(na, na, na, na, na, bgcolor = color.new(c0lor_d3mand, 80)), line.new(na, na, na, na , color = c0lor_d3mand), line.new(na, na, na, na, color=c0lor_d3mand, style=line.style_dashed))
- var equalibrium_boundary = line.new(na, na, na, na, color = c0lor3qual)
- var weighted_equalibrium_boundary = line.new(na, na, na, na, color = c0lor3qual, style = line.style_dashed)
- var float A_weighted_avg = na
- var float B_weighted_avg = na
- if time == chart.right_visible_bar_time
- partition_size = (peak_amount - bottom_amount) / div
- A_section = DemandSupplyCrate.new(peak_amount, peak_amount, 0, 0, 0, 0, false) // A_secont == Supply B = Demand
- B_section = DemandSupplyCrate.new(bottom_amount, bottom_amount, 0, 0, 0, 0, false)
- // iterate through segments
- for i = 0 to div -1
- A_section.quantity -= partition_size
- B_section.quantity += partition_size
- // cumulative quntity column
- if not A_section.fulfilled and supplysh0w and supplyar3a
- box_obj = box.new(x_init, A_section.last_amount, x_init + int(A_section.total / total_accumulated * (n - x_init)), A_section.quantity, na, bgcolor=color.new(c0l0rsupply, 50))
- avg_path = line.new(na, na, na, na, color = c0l0rsupply)
- weighted_avg_line = line.new(na, na, na, na, color=c0l0rsupply, style=line.style_dotted)
- region_A := DemandSupplyZone.new(box_obj, avg_path, weighted_avg_line)
- if not B_section.fulfilled and showd3mand and d3mandar3a
- box_obj = box.new(x_init, B_section.quantity, x_init + int(B_section.total / total_accumulated * (n - x_init)), B_section.last_amount, na, bgcolor=color.new(c0lor_d3mand, 50))
- avg_path = line.new(na, na, na, na, color = c0lor_d3mand)
- weighted_avg_line = line.new(na, na, na, na, color=c0lor_d3mand, style=line.style_dotted)
- region_B := DemandSupplyZone.new(box_obj, avg_path, weighted_avg_line)
- // iterate thought steps
- for j = 0 to (n-x_init)-1
- // iterate through sub steps
- for k = 0 to (volume_data[j]).size()-1
- // accumulate if within upper range
- A_section.total += (high_amount[j]).get(k) > A_section.quantity and (high_amount[j]).get(k) < A_section.last_amount ? (volume_data[j]).get(k) : 0
- A_section.average_quantity += A_section.quantity * (A_section.total - A_section.previous_total)
- A_section.total_accumulated += A_section.total - A_section.previous_total
- A_section.previous_total := A_section.total
- // accumulate if within lower range
- B_section.total += (low_amount[j]).get(k) < B_section.quantity and (low_amount[j]).get(k) < B_section.last_amount ? (volume_data[j]).get(k) : 0
- B_section.average_quantity += B_section.quantity * (B_section.total - B_section.previous_total)
- B_section.total_accumulated += B_section.total - B_section.previous_total
- B_section.previous_total := B_section.total
- // check if a section accumualted amount exceed threshold and set
- if A_section.total / total_accumulated * 100 > thres and not A_section.fulfilled
- avg = math.avg(peak_amount, A_section.quantity)
- A_weighted_avg := A_section.average_quantity / A_section.total_accumulated
- // show box/level cordinates
- if supplysh0w
- region_A.configure_section(x_init, peak_amount, A_section.quantity, avg, A_weighted_avg, supplyar3a, supplyavg, supply_weighted_avg)
- A_section.fulfilled := true
- if B_section.total / total_accumulated * 100 > thres and not B_section.fulfilled
- avg = math.avg(bottom_amount, B_section.quantity)
- B_weighted_avg := B_section.average_quantity / B_section.total_accumulated
- // show box/level cordinates
- if showd3mand
- region_B.configure_section(x_init, B_section.quantity, bottom_amount, avg, B_weighted_avg, d3mandar3a, d3mandavg, d3mand_w3ight3d_avg)
- B_section.fulfilled := true
- if A_section.fulfilled and B_section.fulfilled
- break
- if A_section.fulfilled and B_section.fulfilled and show3qualibr1un
- // set equalibrium
- if avg3qualib
- avg = math.avg(peak_amount, bottom_amount)
- equalibrium_boundary.set_xy1(x_init, avg)
- equalibrium_boundary.set_xy2(n, avg)
- // weighted
- if w3ight3d_avg_3qual
- wavg = math.avg(A_weighted_avg, B_weighted_avg)
- weighted_equalibrium_boundary.set_xy1(x_init, wavg)
- weighted_equalibrium_boundary.set_xy2(n, wavg)
- break
- A_section.last_amount := A_section.quantity
- B_section.last_amount := B_section.quantity
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement