Last active
April 8, 2025 20:39
-
-
Save allen-munsch/5e5cd0d81d52e3148338e6b18e317b1a to your computer and use it in GitHub Desktop.
tradingview all in one MA ribbon and volume profile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//@version=6 | |
indicator(title="All-in-One MA Ribbon + Volume Profile", shorttitle="AIO-MAR-VP", overlay=true, max_boxes_count=500, max_bars_back=1000) | |
//============================================================================= | |
// Input Parameters | |
//============================================================================= | |
tab_selection = input.string("MA Ribbon", "Settings", options=["MA Ribbon", "Volume Profile", "Visual Settings"]) | |
//----------------------------------------------------------------------------- | |
// MA Ribbon Settings | |
//----------------------------------------------------------------------------- | |
ma_type = input.string(defval="EMA", title="MA Type", options=["SMA", "EMA", "WMA", "VWMA", "HMA", "RMA"], group="MA Ribbon Settings", inline="ma_type") | |
source = input.source(close, title="Source", group="MA Ribbon Settings", inline="ma_type") | |
ribbon_preset = input.string("Standard", "Ribbon Preset", options=["Standard", "Fast", "Slow", "Extra-Slow", "Major Cycles", "Custom"], group="MA Ribbon Settings") | |
use_gradient_colors = input.bool(false, title="Use Gradient Color Scheme", group="MA Ribbon Settings") | |
use_different_timeframe = input.bool(false, title="Use Different Timeframe for MAs", group="MA Ribbon Settings") | |
ma_timeframe = input.timeframe("", "MA Timeframe", group="MA Ribbon Settings", tooltip="Leave empty to use current timeframe") | |
custom_start = input.int(5, "Custom Start Period", minval=1, group="MA Ribbon Settings", inline="custom") | |
custom_end = input.int(200, "Custom End Period", minval=5, group="MA Ribbon Settings", inline="custom") | |
custom_count = input.int(8, "Custom Ribbon Count", minval=2, maxval=15, group="MA Ribbon Settings", inline="custom") | |
//----------------------------------------------------------------------------- | |
// Volume Profile Settings | |
//----------------------------------------------------------------------------- | |
show_vp = input.bool(true, "Show Volume Profile", group="Volume Profile Settings") | |
vp_lookback = input.string("Auto", "Profile Timeframe", options=["Auto", "Custom", "1 minute", "5 minutes", "15 minutes", "1 hour", "4 hours", "1 day", "1 week", "1 month"], group="Volume Profile Settings") | |
vp_custom_bars = input.int(150, "Custom Bars Lookback", minval=10, maxval=1000, group="Volume Profile Settings", inline="vp_custom") | |
vp_rows = input.int(24, "Row Size", minval=5, maxval=100, group="Volume Profile Settings") | |
vp_percent = input.float(70., "Value Area Volume %", minval=0, maxval=100, group="Volume Profile Settings") | |
show_poc = input.bool(true, "Show POC Line", group="Volume Profile Settings") | |
show_poc_label = input.bool(true, "Show POC Label", group="Volume Profile Settings") | |
//----------------------------------------------------------------------------- | |
// Visual Settings | |
//----------------------------------------------------------------------------- | |
ma_transparency = input.int(0, "MA Transparency", minval=0, maxval=100, group="Visual Settings", inline="ma_visual") | |
first_last_width = input.int(2, "First/Last Line Width", minval=1, maxval=5, group="Visual Settings", inline="ma_visual") | |
poc_color = input.color(defval=#ff0000, title="POC Color", group="Visual Settings", inline="poc") | |
poc_width = input.int(defval=2, title="POC Width", minval=1, maxval=5, group="Visual Settings", inline="poc") | |
vup_color = input(defval=color.new(color.blue, 30), title="Value Area Up", group="Visual Settings", inline="vp_colors1") | |
vdown_color = input(defval=color.new(color.orange, 30), title="Value Area Down", group="Visual Settings", inline="vp_colors1") | |
up_color = input(defval=color.new(color.blue, 75), title="Up Volume", group="Visual Settings", inline="vp_colors2") | |
down_color = input(defval=color.new(color.orange, 75), title="Down Volume", group="Visual Settings", inline="vp_colors2") | |
//============================================================================= | |
// MA Periods - Using simple ints, not series | |
//============================================================================= | |
// Define preset periods (all using simple int values) | |
int p1 = 0, int p2 = 0, int p3 = 0, int p4 = 0, int p5 = 0 | |
int p6 = 0, int p7 = 0, int p8 = 0, int p9 = 0, int p10 = 0 | |
int p11 = 0, int p12 = 0, int p13 = 0, int p14 = 0, int p15 = 0 | |
if ribbon_preset == "Standard" | |
p1 := 10 | |
p2 := 20 | |
p3 := 50 | |
p4 := 100 | |
p5 := 200 | |
else if ribbon_preset == "Fast" | |
p1 := 5 | |
p2 := 10 | |
p3 := 21 | |
p4 := 55 | |
p5 := 89 | |
else if ribbon_preset == "Slow" | |
p1 := 50 | |
p2 := 100 | |
p3 := 150 | |
p4 := 200 | |
p5 := 250 | |
else if ribbon_preset == "Extra-Slow" | |
p1 := 100 | |
p2 := 200 | |
p3 := 300 | |
p4 := 400 | |
p5 := 500 | |
else if ribbon_preset == "Major Cycles" | |
p1 := 200 | |
p2 := 300 | |
p3 := 500 | |
p4 := 750 | |
p5 := 1000 | |
else // Custom | |
float step = (custom_end - custom_start) / math.max(1, custom_count - 1) | |
p1 := custom_start | |
if custom_count > 1 | |
p2 := math.round(custom_start + step) | |
if custom_count > 2 | |
p3 := math.round(custom_start + 2 * step) | |
if custom_count > 3 | |
p4 := math.round(custom_start + 3 * step) | |
if custom_count > 4 | |
p5 := math.round(custom_start + 4 * step) | |
if custom_count > 5 | |
p6 := math.round(custom_start + 5 * step) | |
if custom_count > 6 | |
p7 := math.round(custom_start + 6 * step) | |
if custom_count > 7 | |
p8 := math.round(custom_start + 7 * step) | |
if custom_count > 8 | |
p9 := math.round(custom_start + 8 * step) | |
if custom_count > 9 | |
p10 := math.round(custom_start + 9 * step) | |
if custom_count > 10 | |
p11 := math.round(custom_start + 10 * step) | |
if custom_count > 11 | |
p12 := math.round(custom_start + 11 * step) | |
if custom_count > 12 | |
p13 := math.round(custom_start + 12 * step) | |
if custom_count > 13 | |
p14 := math.round(custom_start + 13 * step) | |
if custom_count > 14 | |
p15 := math.round(custom_start + 14 * step) | |
// Store all periods in an array (for UI logic only, not for calculations) | |
var int[] periods = array.new_int(15, 0) | |
array.set(periods, 0, p1) | |
array.set(periods, 1, p2) | |
array.set(periods, 2, p3) | |
array.set(periods, 3, p4) | |
array.set(periods, 4, p5) | |
array.set(periods, 5, p6) | |
array.set(periods, 6, p7) | |
array.set(periods, 7, p8) | |
array.set(periods, 8, p9) | |
array.set(periods, 9, p10) | |
array.set(periods, 10, p11) | |
array.set(periods, 11, p12) | |
array.set(periods, 12, p13) | |
array.set(periods, 13, p14) | |
array.set(periods, 14, p15) | |
active_count = ribbon_preset == "Custom" ? custom_count : 5 | |
// Find min/max periods for gradient coloring | |
min_period = ribbon_preset == "Custom" ? custom_start : | |
ribbon_preset == "Fast" ? 5 : | |
ribbon_preset == "Slow" ? 50 : | |
ribbon_preset == "Extra-Slow" ? 100 : | |
ribbon_preset == "Major Cycles" ? 200 : 10 | |
max_period = ribbon_preset == "Custom" ? custom_end : | |
ribbon_preset == "Fast" ? 89 : | |
ribbon_preset == "Slow" ? 250 : | |
ribbon_preset == "Extra-Slow" ? 500 : | |
ribbon_preset == "Major Cycles" ? 1000 : 200 | |
//============================================================================= | |
// MA Calculation - Calculate MAs using simple int values | |
//============================================================================= | |
// Request all data for source | |
tf = ma_timeframe != "" and use_different_timeframe ? ma_timeframe : timeframe.period | |
src_data = request.security(syminfo.tickerid, tf, source) | |
// Calculate all MAs directly with simple ints | |
float ma1 = na | |
float ma2 = na | |
float ma3 = na | |
float ma4 = na | |
float ma5 = na | |
float ma6 = na | |
float ma7 = na | |
float ma8 = na | |
float ma9 = na | |
float ma10 = na | |
float ma11 = na | |
float ma12 = na | |
float ma13 = na | |
float ma14 = na | |
float ma15 = na | |
// Calculate MAs based on type | |
if ma_type == "SMA" | |
ma1 := p1 > 0 ? ta.sma(src_data, p1) : na | |
ma2 := p2 > 0 ? ta.sma(src_data, p2) : na | |
ma3 := p3 > 0 ? ta.sma(src_data, p3) : na | |
ma4 := p4 > 0 ? ta.sma(src_data, p4) : na | |
ma5 := p5 > 0 ? ta.sma(src_data, p5) : na | |
ma6 := p6 > 0 ? ta.sma(src_data, p6) : na | |
ma7 := p7 > 0 ? ta.sma(src_data, p7) : na | |
ma8 := p8 > 0 ? ta.sma(src_data, p8) : na | |
ma9 := p9 > 0 ? ta.sma(src_data, p9) : na | |
ma10 := p10 > 0 ? ta.sma(src_data, p10) : na | |
ma11 := p11 > 0 ? ta.sma(src_data, p11) : na | |
ma12 := p12 > 0 ? ta.sma(src_data, p12) : na | |
ma13 := p13 > 0 ? ta.sma(src_data, p13) : na | |
ma14 := p14 > 0 ? ta.sma(src_data, p14) : na | |
ma15 := p15 > 0 ? ta.sma(src_data, p15) : na | |
else if ma_type == "EMA" | |
ma1 := p1 > 0 ? ta.ema(src_data, p1) : na | |
ma2 := p2 > 0 ? ta.ema(src_data, p2) : na | |
ma3 := p3 > 0 ? ta.ema(src_data, p3) : na | |
ma4 := p4 > 0 ? ta.ema(src_data, p4) : na | |
ma5 := p5 > 0 ? ta.ema(src_data, p5) : na | |
ma6 := p6 > 0 ? ta.ema(src_data, p6) : na | |
ma7 := p7 > 0 ? ta.ema(src_data, p7) : na | |
ma8 := p8 > 0 ? ta.ema(src_data, p8) : na | |
ma9 := p9 > 0 ? ta.ema(src_data, p9) : na | |
ma10 := p10 > 0 ? ta.ema(src_data, p10) : na | |
ma11 := p11 > 0 ? ta.ema(src_data, p11) : na | |
ma12 := p12 > 0 ? ta.ema(src_data, p12) : na | |
ma13 := p13 > 0 ? ta.ema(src_data, p13) : na | |
ma14 := p14 > 0 ? ta.ema(src_data, p14) : na | |
ma15 := p15 > 0 ? ta.ema(src_data, p15) : na | |
else if ma_type == "WMA" | |
ma1 := p1 > 0 ? ta.wma(src_data, p1) : na | |
ma2 := p2 > 0 ? ta.wma(src_data, p2) : na | |
ma3 := p3 > 0 ? ta.wma(src_data, p3) : na | |
ma4 := p4 > 0 ? ta.wma(src_data, p4) : na | |
ma5 := p5 > 0 ? ta.wma(src_data, p5) : na | |
ma6 := p6 > 0 ? ta.wma(src_data, p6) : na | |
ma7 := p7 > 0 ? ta.wma(src_data, p7) : na | |
ma8 := p8 > 0 ? ta.wma(src_data, p8) : na | |
ma9 := p9 > 0 ? ta.wma(src_data, p9) : na | |
ma10 := p10 > 0 ? ta.wma(src_data, p10) : na | |
ma11 := p11 > 0 ? ta.wma(src_data, p11) : na | |
ma12 := p12 > 0 ? ta.wma(src_data, p12) : na | |
ma13 := p13 > 0 ? ta.wma(src_data, p13) : na | |
ma14 := p14 > 0 ? ta.wma(src_data, p14) : na | |
ma15 := p15 > 0 ? ta.wma(src_data, p15) : na | |
else if ma_type == "VWMA" | |
ma1 := p1 > 0 ? ta.vwma(src_data, p1) : na | |
ma2 := p2 > 0 ? ta.vwma(src_data, p2) : na | |
ma3 := p3 > 0 ? ta.vwma(src_data, p3) : na | |
ma4 := p4 > 0 ? ta.vwma(src_data, p4) : na | |
ma5 := p5 > 0 ? ta.vwma(src_data, p5) : na | |
ma6 := p6 > 0 ? ta.vwma(src_data, p6) : na | |
ma7 := p7 > 0 ? ta.vwma(src_data, p7) : na | |
ma8 := p8 > 0 ? ta.vwma(src_data, p8) : na | |
ma9 := p9 > 0 ? ta.vwma(src_data, p9) : na | |
ma10 := p10 > 0 ? ta.vwma(src_data, p10) : na | |
ma11 := p11 > 0 ? ta.vwma(src_data, p11) : na | |
ma12 := p12 > 0 ? ta.vwma(src_data, p12) : na | |
ma13 := p13 > 0 ? ta.vwma(src_data, p13) : na | |
ma14 := p14 > 0 ? ta.vwma(src_data, p14) : na | |
ma15 := p15 > 0 ? ta.vwma(src_data, p15) : na | |
else if ma_type == "HMA" | |
ma1 := p1 > 0 ? ta.hma(src_data, p1) : na | |
ma2 := p2 > 0 ? ta.hma(src_data, p2) : na | |
ma3 := p3 > 0 ? ta.hma(src_data, p3) : na | |
ma4 := p4 > 0 ? ta.hma(src_data, p4) : na | |
ma5 := p5 > 0 ? ta.hma(src_data, p5) : na | |
ma6 := p6 > 0 ? ta.hma(src_data, p6) : na | |
ma7 := p7 > 0 ? ta.hma(src_data, p7) : na | |
ma8 := p8 > 0 ? ta.hma(src_data, p8) : na | |
ma9 := p9 > 0 ? ta.hma(src_data, p9) : na | |
ma10 := p10 > 0 ? ta.hma(src_data, p10) : na | |
ma11 := p11 > 0 ? ta.hma(src_data, p11) : na | |
ma12 := p12 > 0 ? ta.hma(src_data, p12) : na | |
ma13 := p13 > 0 ? ta.hma(src_data, p13) : na | |
ma14 := p14 > 0 ? ta.hma(src_data, p14) : na | |
ma15 := p15 > 0 ? ta.hma(src_data, p15) : na | |
else // RMA | |
ma1 := p1 > 0 ? ta.rma(src_data, p1) : na | |
ma2 := p2 > 0 ? ta.rma(src_data, p2) : na | |
ma3 := p3 > 0 ? ta.rma(src_data, p3) : na | |
ma4 := p4 > 0 ? ta.rma(src_data, p4) : na | |
ma5 := p5 > 0 ? ta.rma(src_data, p5) : na | |
ma6 := p6 > 0 ? ta.rma(src_data, p6) : na | |
ma7 := p7 > 0 ? ta.rma(src_data, p7) : na | |
ma8 := p8 > 0 ? ta.rma(src_data, p8) : na | |
ma9 := p9 > 0 ? ta.rma(src_data, p9) : na | |
ma10 := p10 > 0 ? ta.rma(src_data, p10) : na | |
ma11 := p11 > 0 ? ta.rma(src_data, p11) : na | |
ma12 := p12 > 0 ? ta.rma(src_data, p12) : na | |
ma13 := p13 > 0 ? ta.rma(src_data, p13) : na | |
ma14 := p14 > 0 ? ta.rma(src_data, p14) : na | |
ma15 := p15 > 0 ? ta.rma(src_data, p15) : na | |
// Determine reference MA for coloring | |
ref_ma = ribbon_preset != "Custom" ? ma5 : | |
active_count == 1 ? ma1 : | |
active_count == 2 ? ma2 : | |
active_count == 3 ? ma3 : | |
active_count == 4 ? ma4 : | |
active_count == 5 ? ma5 : | |
active_count == 6 ? ma6 : | |
active_count == 7 ? ma7 : | |
active_count == 8 ? ma8 : | |
active_count == 9 ? ma9 : | |
active_count == 10 ? ma10 : | |
active_count == 11 ? ma11 : | |
active_count == 12 ? ma12 : | |
active_count == 13 ? ma13 : | |
active_count == 14 ? ma14 : ma15 | |
// Function to get gradient color | |
get_gradient_color(period) => | |
color result = color.gray | |
float normalize = (period - min_period) / math.max(1, max_period - min_period) | |
if normalize < 0.25 | |
result := color.new(color.rgb(255, 0, 0), ma_transparency) // Red | |
else if normalize < 0.5 | |
result := color.new(color.rgb(255, 128, 0), ma_transparency) // Orange | |
else if normalize < 0.75 | |
result := color.new(color.rgb(180, 255, 0), ma_transparency) // Yellow-Green | |
else | |
result := color.new(color.rgb(0, 255, 0), ma_transparency) // Green | |
result | |
// Function for MA color based on trend | |
get_ma_color(ma_val, ref_ma_val) => | |
color result = color.gray | |
if not na(ma_val) and not na(ref_ma_val) | |
bool ma_rising = ta.change(ma_val) >= 0 | |
bool ma_above_ref = ma_val > ref_ma_val | |
if ma_rising and ma_above_ref | |
result := color.new(color.lime, ma_transparency) | |
else if not ma_rising and ma_above_ref | |
result := color.new(color.maroon, ma_transparency) | |
else if not ma_rising and not ma_above_ref | |
result := color.new(color.red, ma_transparency) | |
else if ma_rising and not ma_above_ref | |
result := color.new(color.green, ma_transparency) | |
else | |
result := color.new(color.gray, ma_transparency) | |
result | |
//============================================================================= | |
// Volume Profile Functions | |
//============================================================================= | |
// Get number of bars to use for volume profile | |
get_vp_bars() => | |
int bars = vp_custom_bars | |
if vp_lookback == "Auto" | |
bars := 150 | |
else if vp_lookback == "1 minute" | |
bars := 60 | |
else if vp_lookback == "5 minutes" | |
bars := 60 | |
else if vp_lookback == "15 minutes" | |
bars := 100 | |
else if vp_lookback == "1 hour" | |
bars := 150 | |
else if vp_lookback == "4 hours" | |
bars := 180 | |
else if vp_lookback == "1 day" | |
bars := 200 | |
else if vp_lookback == "1 week" | |
bars := 250 | |
else if vp_lookback == "1 month" | |
bars := 300 | |
math.min(bars, 500) | |
get_vol(y11, y12, y21, y22, height, vol) => | |
nz(math.max(math.min(math.max(y11, y12), math.max(y21, y22)) - math.max(math.min(y11, y12), math.min(y21, y22)), 0) * vol / height) | |
// Pre-calculate these values for use later | |
vp_bars_count = get_vp_bars() | |
// Calculate the highest/lowest values on each bar (will be used later in the conditional block) | |
var float top_level = na | |
var float bot_level = na | |
// Update these values on each bar | |
top_level := ta.highest(high, vp_bars_count) | |
bot_level := ta.lowest(low, vp_bars_count) | |
//============================================================================= | |
// Plotting | |
//============================================================================= | |
// Get the colors for each MA | |
color1 = use_gradient_colors ? get_gradient_color(p1) : get_ma_color(ma1, ref_ma) | |
color2 = use_gradient_colors ? get_gradient_color(p2) : get_ma_color(ma2, ref_ma) | |
color3 = use_gradient_colors ? get_gradient_color(p3) : get_ma_color(ma3, ref_ma) | |
color4 = use_gradient_colors ? get_gradient_color(p4) : get_ma_color(ma4, ref_ma) | |
color5 = use_gradient_colors ? get_gradient_color(p5) : get_ma_color(ma5, ref_ma) | |
color6 = use_gradient_colors ? get_gradient_color(p6) : get_ma_color(ma6, ref_ma) | |
color7 = use_gradient_colors ? get_gradient_color(p7) : get_ma_color(ma7, ref_ma) | |
color8 = use_gradient_colors ? get_gradient_color(p8) : get_ma_color(ma8, ref_ma) | |
color9 = use_gradient_colors ? get_gradient_color(p9) : get_ma_color(ma9, ref_ma) | |
color10 = use_gradient_colors ? get_gradient_color(p10) : get_ma_color(ma10, ref_ma) | |
color11 = use_gradient_colors ? get_gradient_color(p11) : get_ma_color(ma11, ref_ma) | |
color12 = use_gradient_colors ? get_gradient_color(p12) : get_ma_color(ma12, ref_ma) | |
color13 = use_gradient_colors ? get_gradient_color(p13) : get_ma_color(ma13, ref_ma) | |
color14 = use_gradient_colors ? get_gradient_color(p14) : get_ma_color(ma14, ref_ma) | |
color15 = use_gradient_colors ? get_gradient_color(p15) : get_ma_color(ma15, ref_ma) | |
// Get the line widths | |
int width1 = ribbon_preset != "Custom" ? (active_count > 0 ? first_last_width : 1) : (active_count > 0 ? first_last_width : 1) | |
int width2 = 1 | |
int width3 = 1 | |
int width4 = 1 | |
int width5 = ribbon_preset != "Custom" ? (active_count > 4 ? first_last_width : 1) : 1 | |
int width6 = 1 | |
int width7 = 1 | |
int width8 = 1 | |
int width9 = 1 | |
int width10 = 1 | |
int width11 = 1 | |
int width12 = 1 | |
int width13 = 1 | |
int width14 = 1 | |
int width15 = ribbon_preset == "Custom" ? (active_count == 15 ? first_last_width : 1) : 1 | |
// Plot MAs | |
plot(ma1, title="MA1", color=color1, linewidth=width1) | |
plot(ma2, title="MA2", color=color2, linewidth=width2) | |
plot(ma3, title="MA3", color=color3, linewidth=width3) | |
plot(ma4, title="MA4", color=color4, linewidth=width4) | |
plot(ma5, title="MA5", color=color5, linewidth=width5) | |
plot(ma6, title="MA6", color=color6, linewidth=width6) | |
plot(ma7, title="MA7", color=color7, linewidth=width7) | |
plot(ma8, title="MA8", color=color8, linewidth=width8) | |
plot(ma9, title="MA9", color=color9, linewidth=width9) | |
plot(ma10, title="MA10", color=color10, linewidth=width10) | |
plot(ma11, title="MA11", color=color11, linewidth=width11) | |
plot(ma12, title="MA12", color=color12, linewidth=width12) | |
plot(ma13, title="MA13", color=color13, linewidth=width13) | |
plot(ma14, title="MA14", color=color14, linewidth=width14) | |
plot(ma15, title="MA15", color=color15, linewidth=width15) | |
// Volume Profile Rendering | |
if show_vp and barstate.islast | |
cnum = vp_rows | |
// Use the pre-calculated price ranges | |
dist = (top_level - bot_level) / 500 | |
step = (top_level - bot_level) / cnum | |
// Create levels array | |
levels = array.new_float(cnum + 1, 0) | |
for x = 0 to cnum | |
array.set(levels, x, bot_level + step * x) | |
// Calculate volume for each channel | |
volumes = array.new_float(cnum * 2, 0) | |
// Process each bar for volume distribution | |
for bar_idx = 0 to vp_bars_count - 1 | |
body_top = math.max(close[bar_idx], open[bar_idx]) | |
body_bot = math.min(close[bar_idx], open[bar_idx]) | |
itsgreen = close[bar_idx] >= open[bar_idx] | |
topwick = high[bar_idx] - body_top | |
bottomwick = body_bot - low[bar_idx] | |
body = body_top - body_bot | |
// Calculate volume distribution | |
total = 2 * topwick + 2 * bottomwick + body | |
if total > 0 // Avoid division by zero | |
bodyvol = body * volume[bar_idx] / total | |
topwickvol = 2 * topwick * volume[bar_idx] / total | |
bottomwickvol = 2 * bottomwick * volume[bar_idx] / total | |
// Distribute volume across price levels | |
for x = 0 to cnum - 1 | |
// Up volume | |
upvol = (itsgreen ? get_vol(array.get(levels, x), array.get(levels, x + 1), body_bot, body_top, body, bodyvol) : 0) + get_vol(array.get(levels, x), array.get(levels, x + 1), body_top, high[bar_idx], topwick, topwickvol) / 2 + get_vol(array.get(levels, x), array.get(levels, x + 1), body_bot, low[bar_idx], bottomwick, bottomwickvol) / 2 | |
// Down volume | |
downvol = (itsgreen ? 0 : get_vol(array.get(levels, x), array.get(levels, x + 1), body_bot, body_top, body, bodyvol)) + get_vol(array.get(levels, x), array.get(levels, x + 1), body_top, high[bar_idx], topwick, topwickvol) / 2 + get_vol(array.get(levels, x), array.get(levels, x + 1), body_bot, low[bar_idx], bottomwick, bottomwickvol) / 2 | |
// Update arrays | |
array.set(volumes, x, array.get(volumes, x) + upvol) | |
array.set(volumes, x + cnum, array.get(volumes, x + cnum) + downvol) | |
// Calculate total volumes | |
totalvols = array.new_float(cnum, 0) | |
for x = 0 to cnum - 1 | |
array.set(totalvols, x, array.get(volumes, x) + array.get(volumes, x + cnum)) | |
// Find POC | |
int poc = array.indexof(totalvols, array.max(totalvols)) | |
// Calculate value area | |
float totalmax = array.sum(totalvols) * vp_percent / 100 | |
float va_total = array.get(totalvols, poc) | |
int up = poc | |
int down = poc | |
// Find value area bounds | |
for x = 0 to cnum - 1 | |
if va_total >= totalmax | |
break | |
float uppervol = up < cnum - 1 ? array.get(totalvols, up + 1) : 0 | |
float lowervol = down > 0 ? array.get(totalvols, down - 1) : 0 | |
if uppervol == 0 and lowervol == 0 | |
break | |
if uppervol >= lowervol | |
va_total += uppervol | |
up += 1 | |
else | |
va_total += lowervol | |
down -= 1 | |
// Scale volumes for display | |
float maxvol = array.max(totalvols) | |
if maxvol > 0 // Avoid division by zero | |
for x = 0 to cnum * 2 - 1 | |
array.set(volumes, x, array.get(volumes, x) * vp_bars_count / (3 * maxvol)) | |
// Draw volume profile | |
var box[] vol_bars = array.new_box(cnum * 2, na) | |
// Process each row of the volume profile | |
for x = 0 to cnum - 1 | |
box.delete(array.get(vol_bars, x)) | |
box.delete(array.get(vol_bars, x + cnum)) | |
// Draw up volume boxes | |
box_up = box.new(bar_index - vp_bars_count + 1, array.get(levels, x + 1) - dist, bar_index - vp_bars_count + 1 + math.round(array.get(volumes, x)), array.get(levels, x) + dist, border_width=0, bgcolor=x >= down and x <= up ? vup_color : up_color) | |
array.set(vol_bars, x, box_up) | |
// Draw down volume boxes | |
box_down = box.new(bar_index - vp_bars_count + 1 + math.round(array.get(volumes, x)), array.get(levels, x + 1) - dist, bar_index - vp_bars_count + 1 + math.round(array.get(volumes, x)) + math.round(array.get(volumes, x + cnum)), array.get(levels, x) + dist, border_width=0, bgcolor=x >= down and x <= up ? vdown_color : down_color) | |
array.set(vol_bars, x + cnum, box_down) | |
// Draw POC line and label | |
if show_poc | |
poc_level = (array.get(levels, poc) + array.get(levels, poc + 1)) / 2 | |
var line poc_line = na | |
line.delete(poc_line) | |
poc_line := line.new(bar_index - vp_bars_count + 1, poc_level, bar_index + 50, poc_level, extend=extend.right, color=poc_color, width=poc_width) | |
if show_poc_label | |
var label poc_label = na | |
label.delete(poc_label) | |
poc_label := label.new(bar_index + 15, poc_level, text = "POC: " + str.tostring(math.round_to_mintick(poc_level)), style = close >= poc_level ? label.style_label_up : label.style_label_down) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment