Very interesting to mark points of interest of the market profileiardavan wrote: Wed Jun 11, 2025 10:34 am Hello and regards to everyone,
This LuxAlgo indicator is very useful — especially the way it automatically identifies peak points and draws support and resistance levels based on volume peaks and valleys.
I would really appreciate it if this indicator could be converted to MQL4 so that it can be used in MetaTrader 4.
Also, it would be great if the indicator could be anchored manually, similar to Anchored Volume Profile — allowing the user to move and resize the range between lines, rather than relying on a fixed number of bars.
If you need any additional information to help with the conversion, I am more than happy to provide it.
Thank you very much in advance for making this available for MT4!
https://www.luxalgo.com/library/indicat ... detection/
Main code:
Code: Select all
// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/ // © LuxAlgo //@version=5 indicator("Volume Profile with Node Detection [LuxAlgo]", "LuxAlgo - Volume Profile with Node Detection", overlay = true, max_boxes_count = 500, max_bars_back = 5000) //--------------------------------------------------------------------------------------------------------------------- // Settings //---------------------------------------------------------------------------------------------------------------------{ display = display.all - display.status_line vn_volumeNodesGroup = 'Volume Nodes' vn_peakTTip = 'A volume peak node is recognized when the volume profile nodes for the N preceding and N succeeding nodes are lower than that of the evaluated one, where N is determined by the \'Node Detection Percent %\' option' vn_peaksShow = input.string('Peaks', 'Volume Peaks', options = ['Peaks', 'Clusters', 'None'], inline = 'vnP', tooltip = vn_peakTTip, group = vn_volumeNodesGroup, display = display) vn_peakVolumeColor = input.color(color.new(color.blue, 50), '', inline = 'vnP', group = vn_volumeNodesGroup) vn_peaksNumberOfNodes = input.int(9, '  Node Detection Percent %', minval = 0, maxval = 100, group = vn_volumeNodesGroup, display = display) / 100 vn_peaksShow := vn_peaksNumberOfNodes == 0 ? 'None' : vn_peaksShow vn_troughsTTip = 'A volume trough node is recognized when the volume profile nodes for the N preceding and N succeeding nodes exceed that of the evaluated one, where N is determined by the \'Node Detection Percent %\' option' vn_troughsShow = input.string('None', 'Volume Troughs', options = ['Troughs', 'Clusters', 'None'], inline = 'vnT', tooltip = vn_troughsTTip, group = vn_volumeNodesGroup, display = display) vn_troughVolumeColor = input.color(color.new(color.gray, 50), '', inline = 'vnT', group = vn_volumeNodesGroup) vn_troughsNumberOfNodes = input.int(7, '  Node Detection Percent %', minval = 0, maxval = 100, group = vn_volumeNodesGroup, display = display) / 100 vn_troughsShow := vn_troughsNumberOfNodes == 0 ? 'None' : vn_troughsShow vn_thresholdTTip = 'A threshold value specified as a percentage is utilized to detect peak/trough volume nodes. If a value is set, the detection will disregard volume node values lower than the specified threshold.' vn_VolumeNodeThreshold = input.int(1, 'Volume Node Threshold %', minval = 0, maxval = 100, tooltip = vn_thresholdTTip, group = vn_volumeNodesGroup, display = display) / 100 vn_highestNVolumeNodes = input.int(0, 'Highest Volume Nodes', minval = 0, maxval = 31, inline = 'vnL', group = vn_volumeNodesGroup, display = display) vn_highestVolumeColor = input.color(color.new(color.orange, 25), '', inline = 'vnL', group = vn_volumeNodesGroup) vn_lowestNVolumeNodes = input.int(0, 'Lowest Volume Nodes', minval = 0, maxval = 31, inline = 'vnH', group = vn_volumeNodesGroup, display = display) vn_lowestVolumeColor = input.color(color.new(color.navy, 25), '', inline = 'vnH', group = vn_volumeNodesGroup) vp_componentsGroup = 'Volume Profile - Components' vp_profileShow = input.bool(true, 'Volume Profile', inline = 'vp', group = vp_componentsGroup) vp_profileGradientColors = input.string('Gradient Colors', '', options = ['Gradient Colors', 'Classic Colors' ], inline = 'vp', group = vp_componentsGroup) vp_valueAreaUpColor = input.color(color.new(#2962ff, 30), '  Value Area Up / Down', inline = 'VA', group = vp_componentsGroup) vp_valueAreaDwonColor = input.color(color.new(#fbc02d, 30), '/', inline = 'VA', group = vp_componentsGroup) vp_profileUpVolumeColor = input.color(color.new(#5d606b, 50), '  Profile Up / Down Volume', inline = 'VP', group = vp_componentsGroup) vp_profileDownVolumeColor = input.color(color.new(#d1d4dc, 50), '/', inline = 'VP', group = vp_componentsGroup) vp_pocShow = input.string('None', 'Point of Control', options = ['Developing', 'Regular', 'None'], inline = 'poc', group = vp_componentsGroup, display = display) vp_pocColor = input.color(#fbc02d, '', inline = 'poc', group = vp_componentsGroup) vp_pocWidth = input.int(2, 'Width', inline = 'poc', group = vp_componentsGroup, display = display) vp_vahShow = input.bool(false, 'Value Area High (VAH)', inline = 'vah', group = vp_componentsGroup) vp_vahColor = input.color(#2962ff, '', inline = 'vah', group = vp_componentsGroup) vp_valShow = input.bool(false, 'Value Area Low (VAL)', inline = 'val', group = vp_componentsGroup) vp_valColor = input.color(#2962ff, '', inline = 'val', group = vp_componentsGroup) vp_profileLevels = input.string('Small', "Profile Price Labels", options=['Tiny', 'Small', 'Normal', 'None'], group = vp_componentsGroup, display = display) vp_displayGroup = 'Volume Profile - Display Settings' vp_profileLength = input.int(360, 'Profile Lookback Length', minval = 10, maxval = 5000, step = 10, group = vp_displayGroup, display = display) vp_profileLength:= last_bar_index < vp_profileLength ? last_bar_index : vp_profileLength - 1 vp_valueAreaThreshold = input.float(70, 'Value Area (%)', minval = 0, maxval = 100, group = vp_displayGroup, display = display) / 100 vp_profilePlracment = input.string('Right', 'Profile Placement', options = ['Right', 'Left'], group = vp_displayGroup, display = display), profilePlacementRight = vp_profilePlracment == 'Right' vp_profileNumberOfRows = input.int(100, 'Profile Number of Rows' , minval = 30, maxval = 130 , step = 10, group = vp_displayGroup, display = display) vp_profileWidth = input.float(31, 'Profile Width', minval = 0, maxval = 250, group = vp_displayGroup, display = display) / 100 vp_profileHorizontalOffset = input.int(13, 'Profile Horizontal Offset', maxval = 50, group = vp_displayGroup, display = display) vp_valueAreaBackground = input.bool(false, 'Value Area Background  ', inline = 'vBG', group = vp_displayGroup) vp_valueAreaBackgroundColor = input.color(color.new(#2962ff, 89), '', inline = 'vBG', group = vp_displayGroup) vp_profileBackground = input.bool(false, 'Profile Range Background ', inline = 'pBG', group = vp_displayGroup) vp_profileBackgroundColor = input.color(color.new(#2962ff, 95), '', inline = 'pBG', group = vp_displayGroup) //---------------------------------------------------------------------------------------------------------------------} // User Defined Types //---------------------------------------------------------------------------------------------------------------------{ type BAR float open = open float high = high float low = low float close = close float volume = volume int index = bar_index type barData float [] barHigh float [] barLow float [] barVolume bool [] barPolarity int [] barCount type volumeData float [] totalVolume float [] bullishVolume float [] bearishVolume int [] endProfileIndex bool [] peakVolume bool [] troughVolume type volumeProfile box [] boxes chart.point [] pocPoints polyline pocPolyline int pocLevel int vahLevel int valLevel int startIndex //---------------------------------------------------------------------------------------------------------------------} // Variables //---------------------------------------------------------------------------------------------------------------------{ BAR bar = BAR.new() BAR [] ltfBarData = array.new<BAR> (1, BAR.new()) var barData barDataArray = barData.new( array.new <float> (na), array.new <float> (na), array.new <float> (na), array.new <bool> (na), array.new <int> (na) ) volumeData volumeDataArray = volumeData.new( array.new <float> (vp_profileNumberOfRows, 0.), array.new <float> (vp_profileNumberOfRows, 0.), array.new <float> (vp_profileNumberOfRows, 0.), array.new <int> (vp_profileNumberOfRows, 0 ), array.new <bool> (vp_profileNumberOfRows, 0.), array.new <bool> (vp_profileNumberOfRows, 0.) ) var volumeProfile VP = volumeProfile.new( array.new<box> (na), array.new<chart.point> (na), polyline.new (na), na, na, na, na ) var float highestPrice = na var float lowestPrice = na //---------------------------------------------------------------------------------------------------------------------} // Functions / Methods //---------------------------------------------------------------------------------------------------------------------{ renderLine(_x1, _y1, _x2, _y2, _xloc, _extend, _color, _style, _width) => var id = line.new(_x1, _y1, _x2, _y2, _xloc, _extend, _color, _style, _width) line.set_xy1(id, _x1, _y1) line.set_xy2(id, _x2, _y2) line.set_color(id, _color) renderLabel(_x, _y, _text, _color, _style, _textcolor, _size, _tooltip) => var lb = label.new(_x, _y, _text, xloc.bar_index, yloc.price, _color, _style, _textcolor, _size, text.align_left, _tooltip) lb.set_xy(_x, _y) lb.set_text(_text) lb.set_tooltip(_tooltip) lb.set_textcolor(_textcolor) requestBarData(_lowerTimeframe) => request.security_lower_tf(syminfo.tickerid, _lowerTimeframe, BAR.new(), ignore_invalid_timeframe = true) calculateTimeframe(_depth) => int tfInMs = timeframe.in_seconds(timeframe.period) int mInMS = 60 if _depth == 2 switch tfInMs < 30 => '1S' tfInMs < 1 * mInMS => '5S' tfInMs <= 15 * mInMS => '1' tfInMs <= 60 * mInMS => '5' tfInMs <= 240 * mInMS => '15' tfInMs <= 1440 * mInMS => '60' => 'D' else if _depth == 1 switch tfInMs < 15 => '1S' tfInMs < 30 => '5S' tfInMs < 1 * mInMS => '15S' tfInMs <= 5 * mInMS => '1' tfInMs <= 15 * mInMS => '5' tfInMs <= 60 * mInMS => '15' tfInMs <= 240 * mInMS => '60' tfInMs <= 1440 * mInMS => '240' => 'D' getTextSize(_text) => if _text != 'None' switch _text 'Tiny' => size.tiny 'Small' => size.small 'Normal' => size.normal => size.auto //---------------------------------------------------------------------------------------------------------------------} // Calculations - Volume Profile //---------------------------------------------------------------------------------------------------------------------{ profileLevesSize = getTextSize(vp_profileLevels) if bar.index == last_bar_index - vp_profileLength VP.startIndex := bar.index lowestPrice := bar.low highestPrice := bar.high else if bar.index > last_bar_index - vp_profileLength lowestPrice := math.min(bar.low, lowestPrice) highestPrice := math.max(bar.high, highestPrice) //if vp_profileLength <= 200 // ltfBarData := requestBarData(calculateTimeframe(2)) //else if vp_profileLength <= 700 ltfBarData := requestBarData(calculateTimeframe(2)) else ltfBarData := array.new<BAR> (1, BAR.new(bar.open, bar.high, bar.low, bar.close, bar.volume)) if barstate.ishistory and (bar.index >= last_bar_index - vp_profileLength) and bar.index < last_bar_index and ltfBarData.size() > 0 log.info("yaz_kizim {0} {1}", ltfBarData.get(0).volume, na(nz(ltfBarData.get(0).volume)) ) if ltfBarData.size() > 0 and not na(nz(ltfBarData.get(0).volume)) for currentLtfBar = 0 to ltfBarData.size() - 1 barDataArray.barHigh.push(ltfBarData.get(currentLtfBar).high) barDataArray.barLow.push(ltfBarData.get(currentLtfBar).low) barDataArray.barVolume.push(ltfBarData.get(currentLtfBar).volume) barDataArray.barPolarity.push(ltfBarData.get(currentLtfBar).close > ltfBarData.get(currentLtfBar).open) barDataArray.barCount.push(ltfBarData.size()) priceStep = (highestPrice - lowestPrice) / vp_profileNumberOfRows if barstate.islast and ltfBarData.size() > 0 // barDataArray.barVolume.size() > 0 // if VP.boxes.size() > 0 for boxIndex = 0 to VP.boxes.size() - 1 box.delete(VP.boxes.shift()) if barDataArray.barCount.size() > vp_profileLength barCount = barDataArray.barCount.shift() for barCountIndex = 0 to barCount - 1 barDataArray.barHigh.shift() barDataArray.barLow.shift() barDataArray.barVolume.shift() barDataArray.barPolarity.shift() VP.pocPoints.clear() VP.pocPolyline.delete() if ltfBarData.size() > 0 and not na(nz(ltfBarData.get(0).volume)) for currentLtfBar = 0 to ltfBarData.size() - 1 barDataArray.barHigh.push(ltfBarData.get(currentLtfBar).high) barDataArray.barLow.push(ltfBarData.get(currentLtfBar).low) barDataArray.barVolume.push(ltfBarData.get(currentLtfBar).volume) barDataArray.barPolarity.push(ltfBarData.get(currentLtfBar).close > ltfBarData.get(currentLtfBar).open) barDataArray.barCount.push(ltfBarData.size()) barIndex = vp_profileLength numberOfBars = 0 arraySize = barDataArray.barVolume.size() for arrayIndex = 0 to arraySize - 1 levelHigh = barDataArray.barHigh.get(arrayIndex) levelLow = barDataArray.barLow.get(arrayIndex) levelVolume = barDataArray.barVolume.get(arrayIndex) // Shoutout to @tkarolak for contributing to the code's optimization! Much appreciated. int startSlotIndex = math.max(math.floor((levelLow - lowestPrice) / priceStep), 0) int endSlotIndex = math.min(math.floor((levelHigh - lowestPrice) / priceStep), vp_profileNumberOfRows - 1) for priceLevelIndex = startSlotIndex to endSlotIndex float priceLevel = lowestPrice + priceLevelIndex * priceStep volumeProportion = switch levelLow >= priceLevel and levelHigh > priceLevel + priceStep => (priceLevel + priceStep - levelLow) / (levelHigh - levelLow) levelHigh <= priceLevel + priceStep and levelLow < priceLevel => (levelHigh - priceLevel) / (levelHigh - levelLow) levelLow >= priceLevel and levelHigh <= priceLevel + priceStep => 1 => priceStep / (levelHigh - levelLow) volumeDataArray.totalVolume.set(priceLevelIndex, volumeDataArray.totalVolume.get(priceLevelIndex) + levelVolume * volumeProportion) if barDataArray.barPolarity.get(arrayIndex) volumeDataArray.bullishVolume.set(priceLevelIndex, volumeDataArray.bullishVolume.get(priceLevelIndex) + levelVolume * volumeProportion) // priceLevelIndex = 0 // for priceLevel = lowestPrice to highestPrice - priceStep by priceStep // // if levelHigh >= priceLevel and levelLow < priceLevel + priceStep // // volumeProportion = if levelLow >= priceLevel and levelHigh > priceLevel + priceStep // (priceLevel + priceStep - levelLow) / (levelHigh - levelLow) // else if levelHigh <= priceLevel + priceStep and levelLow < priceLevel // (levelHigh - priceLevel) / (levelHigh - levelLow) // else if levelLow >= priceLevel and levelHigh <= priceLevel + priceStep // 1 // else // priceStep / (levelHigh - levelLow) // // volumeDataArray.totalVolume.set(priceLevelIndex, volumeDataArray.totalVolume.get(priceLevelIndex) + levelVolume * volumeProportion) // // if barDataArray.barPolarity.get(arrayIndex) // volumeDataArray.bullishVolume.set(priceLevelIndex, volumeDataArray.bullishVolume.get(priceLevelIndex) + levelVolume * volumeProportion) // priceLevelIndex += 1 if vp_pocShow == 'Developing' if arrayIndex == barDataArray.barCount.get(vp_profileLength - barIndex) VP.pocPoints.push(chart.point.from_index(bar.index[barIndex], math.avg(bar.high[barIndex], bar.low[barIndex]))) VP.pocPoints.push(chart.point.from_index(bar.index[barIndex] + 1, lowestPrice + (volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.max()) + .5) * priceStep)) numberOfBars += barDataArray.barCount.get(vp_profileLength - barIndex) barIndex -= 1 else if arrayIndex == (numberOfBars + barDataArray.barCount.get(vp_profileLength - barIndex)) and numberOfBars != 0 VP.pocPoints.push(chart.point.from_index(bar.index[barIndex] + 1, lowestPrice + (volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.max()) + .5) * priceStep)) numberOfBars += barDataArray.barCount.get(vp_profileLength - barIndex) barIndex -= 1 else if barIndex == 0 VP.pocPoints.push(chart.point.from_index(bar.index[barIndex] + 1, lowestPrice + (volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.max()) + .5) * priceStep)) numberOfBars += barDataArray.barCount.get(vp_profileLength - barIndex) VP.pocPolyline := polyline.new(VP.pocPoints, false, false, xloc.bar_index, vp_pocColor, color(na), line.style_solid, vp_pocWidth) for volumeIndex = 0 to vp_profileNumberOfRows - 1 bearishVolume = 2 * volumeDataArray.bullishVolume.get(volumeIndex) - volumeDataArray.totalVolume.get(volumeIndex) volumeDataArray.bearishVolume.set(volumeIndex, volumeDataArray.bearishVolume.get(volumeIndex) + bearishVolume * (bearishVolume > 0 ? 1 : -1) ) VP.pocLevel := volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.max()) totalTradedVolume = volumeDataArray.totalVolume.sum() * vp_valueAreaThreshold valueAreaVolume = VP.pocLevel != -1 ? volumeDataArray.totalVolume.get(VP.pocLevel) : 0 VP.vahLevel := VP.pocLevel VP.valLevel := VP.pocLevel while valueAreaVolume < totalTradedVolume if VP.valLevel == 0 and VP.vahLevel == vp_profileNumberOfRows - 1 break volumeAbovePOC = 0. if VP.vahLevel < vp_profileNumberOfRows - 1 volumeAbovePOC := volumeDataArray.totalVolume.get(VP.vahLevel + 1) volumeBelowPOC = 0. if VP.valLevel > 0 volumeBelowPOC := volumeDataArray.totalVolume.get(VP.valLevel - 1) if volumeBelowPOC == 0 and volumeAbovePOC == 0 break if volumeAbovePOC >= volumeBelowPOC valueAreaVolume += volumeAbovePOC VP.vahLevel += 1 else valueAreaVolume += volumeBelowPOC VP.valLevel -= 1 vahPrice = lowestPrice + (VP.vahLevel + 1.) * priceStep pocPrice = lowestPrice + (VP.pocLevel + .5) * priceStep valPrice = lowestPrice + (VP.valLevel + .0) * priceStep profilePlottingLength = vp_profileLength > 360 ? 360 : vp_profileLength profileWidth = profilePlottingLength * vp_profileWidth profileHorizontalOffset = int(profileWidth + vp_profileHorizontalOffset) if vp_profileShow and profilePlacementRight and vp_pocShow == 'Developing' renderLine(last_bar_index, pocPrice, profileHorizontalOffset + int(last_bar_index - profileWidth + 1), pocPrice, xloc.bar_index, extend.none, vp_pocColor, line.style_solid, vp_pocWidth) if vp_vahShow renderLine(VP.startIndex, vahPrice, profilePlacementRight ? (vp_profileShow ? profileHorizontalOffset : 0) + last_bar_index : last_bar_index, vahPrice, xloc.bar_index, extend.none, vp_vahColor, line.style_solid, 1) if vp_pocShow == 'Regular' renderLine(VP.startIndex, pocPrice, profilePlacementRight ? vp_profileShow ? profileHorizontalOffset + int(last_bar_index - profileWidth + 1) : last_bar_index : last_bar_index, pocPrice, xloc.bar_index, extend.none, vp_pocColor, line.style_solid, vp_pocWidth) if vp_valShow renderLine(VP.startIndex, valPrice, profilePlacementRight ? (vp_profileShow ? profileHorizontalOffset : 0) + last_bar_index : last_bar_index, valPrice, xloc.bar_index, extend.none, vp_valColor, line.style_solid, 1) if vp_valueAreaBackground VP.boxes.push(box.new(VP.startIndex, valPrice, last_bar_index, vahPrice, vp_valueAreaBackgroundColor, 1, line.style_dotted, bgcolor = vp_valueAreaBackgroundColor)) if vp_profileBackground VP.boxes.push(box.new(VP.startIndex, lowestPrice, last_bar_index, highestPrice, vp_profileBackgroundColor, 1, line.style_dotted, bgcolor = vp_profileBackgroundColor)) if vp_profileLevels != 'None' and VP.pocLevel != -1 renderLabel(profilePlacementRight ? (vp_profileShow ? profileHorizontalOffset : 0) + last_bar_index : vp_profileShow ? VP.startIndex : last_bar_index, highestPrice, str.tostring(highestPrice, format.mintick), color.new(chart.fg_color, 89), label.style_label_down, chart.fg_color, profileLevesSize, 'Profile High') renderLabel(profilePlacementRight ? (vp_profileShow ? profileHorizontalOffset : 0) + last_bar_index : last_bar_index, vahPrice, str.tostring(vahPrice, format.mintick), color.new(vp_vahColor, 89), label.style_label_left, vp_vahColor, profileLevesSize, 'Value Area High') renderLabel(profilePlacementRight ? (vp_profileShow ? profileHorizontalOffset : 0) + last_bar_index : last_bar_index, pocPrice, str.tostring(pocPrice, format.mintick), color.new(vp_pocColor, 89), label.style_label_left, vp_pocColor, profileLevesSize, 'Point of Control') renderLabel(profilePlacementRight ? (vp_profileShow ? profileHorizontalOffset : 0) + last_bar_index : last_bar_index, valPrice, str.tostring(valPrice, format.mintick), color.new(vp_valColor, 89), label.style_label_left, vp_valColor, profileLevesSize, 'Value Area Low') renderLabel(profilePlacementRight ? (vp_profileShow ? profileHorizontalOffset : 0) + last_bar_index : vp_profileShow ? VP.startIndex : last_bar_index, lowestPrice, str.tostring(lowestPrice, format.mintick), color.new(chart.fg_color, 89), label.style_label_up, chart.fg_color, profileLevesSize, 'Profile Low') for volumeNodeLevel = 0 to vp_profileNumberOfRows - 1 if vp_profileShow if vp_profileGradientColors == 'Gradient Colors' vp_valueAreaUpColor := color.from_gradient(volumeDataArray.totalVolume.get(volumeNodeLevel) / volumeDataArray.totalVolume.max(), 0, 1, color.new(vp_valueAreaUpColor , 95), color.new(vp_valueAreaUpColor , 0)) vp_valueAreaDwonColor := color.from_gradient(volumeDataArray.totalVolume.get(volumeNodeLevel) / volumeDataArray.totalVolume.max(), 0, 1, color.new(vp_valueAreaDwonColor , 95), color.new(vp_valueAreaDwonColor , 0)) vp_profileUpVolumeColor := color.from_gradient(volumeDataArray.totalVolume.get(volumeNodeLevel) / volumeDataArray.totalVolume.max(), 0, 1, color.new(vp_profileUpVolumeColor , 95), color.new(vp_profileUpVolumeColor , 0)) vp_profileDownVolumeColor := color.from_gradient(volumeDataArray.totalVolume.get(volumeNodeLevel) / volumeDataArray.totalVolume.max(), 0, 1, color.new(vp_profileDownVolumeColor, 95), color.new(vp_profileDownVolumeColor, 0)) startProfileIndex = profilePlacementRight ? profileHorizontalOffset + int(last_bar_index - volumeDataArray.bullishVolume.get(volumeNodeLevel) / volumeDataArray.totalVolume.max() * profileWidth) : VP.startIndex endProfileIndex = profilePlacementRight ? profileHorizontalOffset + last_bar_index : int(startProfileIndex + volumeDataArray.bullishVolume.get(volumeNodeLevel) / volumeDataArray.totalVolume.max() * profileWidth) VP.boxes.push(box.new(startProfileIndex, lowestPrice + (volumeNodeLevel + .1) * priceStep, endProfileIndex, lowestPrice + (volumeNodeLevel + .9) * priceStep, color(na), bgcolor = volumeNodeLevel >= VP.valLevel and volumeNodeLevel <= VP.vahLevel ? vp_valueAreaUpColor : vp_profileUpVolumeColor)) startProfileIndex := profilePlacementRight ? startProfileIndex : endProfileIndex endProfileIndex := profilePlacementRight ? startProfileIndex - int( (volumeDataArray.totalVolume.get(volumeNodeLevel) - volumeDataArray.bullishVolume.get(volumeNodeLevel)) / volumeDataArray.totalVolume.max() * profileWidth) : startProfileIndex + int( (volumeDataArray.totalVolume.get(volumeNodeLevel) - volumeDataArray.bullishVolume.get(volumeNodeLevel)) / volumeDataArray.totalVolume.max() * profileWidth) VP.boxes.push(box.new(startProfileIndex, lowestPrice + (volumeNodeLevel + .1) * priceStep, endProfileIndex, lowestPrice + (volumeNodeLevel + .9) * priceStep, color(na), bgcolor = volumeNodeLevel >= VP.valLevel and volumeNodeLevel <= VP.vahLevel ? vp_valueAreaDwonColor : vp_profileDownVolumeColor)) volumeDataArray.endProfileIndex.set(volumeNodeLevel, endProfileIndex) if vn_peaksShow != 'None' or vn_troughsShow != 'None' var int startVolumeNodeIndex = na, var int endVolumeNodeIndex = na var bool peakUpperNth = na, var bool peakLowerNth = na peaksNumberOfNodes = int(vp_profileNumberOfRows * vn_peaksNumberOfNodes) tempPeakTotalVolume = volumeDataArray.totalVolume.copy() for index = 1 to peaksNumberOfNodes tempPeakTotalVolume.unshift(0.) tempPeakTotalVolume.push(0.) for volumeNodeLevel = 0 to vp_profileNumberOfRows - 1 + 2 * peaksNumberOfNodes if vn_peaksShow != 'None' and volumeNodeLevel >= 2 * peaksNumberOfNodes for currentVolumeNode = volumeNodeLevel - 2 * peaksNumberOfNodes to volumeNodeLevel - peaksNumberOfNodes - 1 if tempPeakTotalVolume.get(volumeNodeLevel - peaksNumberOfNodes) <= tempPeakTotalVolume.get(currentVolumeNode) peakUpperNth := false break else peakUpperNth := true for currentVolumeNode = volumeNodeLevel - peaksNumberOfNodes + 1 to volumeNodeLevel if tempPeakTotalVolume.get(volumeNodeLevel - peaksNumberOfNodes) <= tempPeakTotalVolume.get(currentVolumeNode) peakLowerNth := false break else peakLowerNth := true if peakUpperNth and peakLowerNth and tempPeakTotalVolume.get(volumeNodeLevel - peaksNumberOfNodes) / tempPeakTotalVolume.max() > vn_VolumeNodeThreshold startVolumeNodeIndex := vp_profileShow ? profilePlacementRight ? VP.startIndex : volumeDataArray.endProfileIndex.get(volumeNodeLevel - 2 * peaksNumberOfNodes) : //VP.startIndex + int(volumeDataArray.totalVolume.get(volumeNodeLevel - vn_peaksNumberOfNodes) / volumeDataArray.totalVolume.max() * profileWidth) : VP.startIndex endVolumeNodeIndex := vp_profileShow ? profilePlacementRight ? volumeDataArray.endProfileIndex.get(volumeNodeLevel - 2 * peaksNumberOfNodes) : //profileHorizontalOffset + int(last_bar_index - volumeDataArray.totalVolume.get(volumeNodeLevel - vn_peaksNumberOfNodes) / volumeDataArray.totalVolume.max() * profileWidth) : last_bar_index : last_bar_index vn_peakVolumeColor := vn_peaksShow == 'Peaks' ? vn_peakVolumeColor : color.from_gradient(tempPeakTotalVolume.get(volumeNodeLevel - peaksNumberOfNodes) / tempPeakTotalVolume.max(), 0, 1, color.new(vn_peakVolumeColor, 95), color.new(vn_peakVolumeColor, 65)) VP.boxes.push(box.new(startVolumeNodeIndex, lowestPrice + (volumeNodeLevel - 2 * peaksNumberOfNodes + .1) * priceStep, endVolumeNodeIndex, lowestPrice + (volumeNodeLevel - 2 * peaksNumberOfNodes + .9) * priceStep, color(na), bgcolor = vn_peakVolumeColor)) if vn_peaksShow == 'Clusters' for currentVolumeNode = volumeNodeLevel - 2 * peaksNumberOfNodes to volumeNodeLevel if currentVolumeNode >= peaksNumberOfNodes and currentVolumeNode <= vp_profileNumberOfRows - 1 + peaksNumberOfNodes if not volumeDataArray.peakVolume.get(currentVolumeNode - peaksNumberOfNodes) startVolumeNodeIndex := vp_profileShow ? profilePlacementRight ? VP.startIndex : volumeDataArray.endProfileIndex.get(currentVolumeNode - peaksNumberOfNodes) : //VP.startIndex + int(volumeDataArray.totalVolume.get(currentVolumeNode) / volumeDataArray.totalVolume.max() * profileWidth) : VP.startIndex endVolumeNodeIndex := vp_profileShow ? profilePlacementRight ? volumeDataArray.endProfileIndex.get(currentVolumeNode - peaksNumberOfNodes) : //profileHorizontalOffset + int(last_bar_index - volumeDataArray.totalVolume.get(currentVolumeNode) / volumeDataArray.totalVolume.max() * profileWidth) : last_bar_index : last_bar_index VP.boxes.push(box.new(startVolumeNodeIndex, lowestPrice + (currentVolumeNode - peaksNumberOfNodes + .0) * priceStep, endVolumeNodeIndex, lowestPrice + (currentVolumeNode - peaksNumberOfNodes + 1.) * priceStep, color(na), bgcolor = vn_peakVolumeColor)) volumeDataArray.peakVolume.set(currentVolumeNode - peaksNumberOfNodes, true) tempPeakTotalVolume.clear() var bool troughUpperNth = na, var bool troughLowerNth = na troughsNumberOfNodes = int(vp_profileNumberOfRows * vn_troughsNumberOfNodes) tempTroughTotalVolume = volumeDataArray.totalVolume.copy() for index = 1 to troughsNumberOfNodes tempTroughTotalVolume.unshift(volumeDataArray.totalVolume.max()) tempTroughTotalVolume.push(volumeDataArray.totalVolume.max()) for volumeNodeLevel = 0 to vp_profileNumberOfRows - 1 + 2 * troughsNumberOfNodes if vn_troughsShow != 'None' and volumeNodeLevel >= 2 * troughsNumberOfNodes for currentVolumeNode = volumeNodeLevel - 2 * troughsNumberOfNodes to volumeNodeLevel - troughsNumberOfNodes - 1 if tempTroughTotalVolume.get(volumeNodeLevel - troughsNumberOfNodes) >= tempTroughTotalVolume.get(currentVolumeNode) troughUpperNth := false break else troughUpperNth := true for currentVolumeNode = volumeNodeLevel - troughsNumberOfNodes + 1 to volumeNodeLevel if tempTroughTotalVolume.get(volumeNodeLevel - troughsNumberOfNodes) >= tempTroughTotalVolume.get(currentVolumeNode) troughLowerNth := false break else troughLowerNth := true if troughUpperNth and troughLowerNth and tempTroughTotalVolume.get(volumeNodeLevel - troughsNumberOfNodes) / tempTroughTotalVolume.max() > vn_VolumeNodeThreshold startVolumeNodeIndex := vp_profileShow ? profilePlacementRight ? VP.startIndex : volumeDataArray.endProfileIndex.get(volumeNodeLevel - 2 * troughsNumberOfNodes) : //VP.startIndex + int(volumeDataArray.totalVolume.get(volumeNodeLevel - vn_troughsNumberOfNodes) / volumeDataArray.totalVolume.max() * profileWidth) : VP.startIndex endVolumeNodeIndex := vp_profileShow ? profilePlacementRight ? volumeDataArray.endProfileIndex.get(volumeNodeLevel - 2 * troughsNumberOfNodes) : //profileHorizontalOffset + int(last_bar_index - volumeDataArray.totalVolume.get(volumeNodeLevel - vn_troughsNumberOfNodes) / volumeDataArray.totalVolume.max() * profileWidth) : last_bar_index : last_bar_index vn_troughVolumeColor := vn_troughsShow == 'Troughs' ? vn_troughVolumeColor : color.from_gradient(tempTroughTotalVolume.get(volumeNodeLevel - troughsNumberOfNodes) / tempTroughTotalVolume.max(), 0, 1, color.new(vn_troughVolumeColor, 95), color.new(vn_troughVolumeColor, 31)) VP.boxes.push(box.new(startVolumeNodeIndex, lowestPrice + (volumeNodeLevel - 2 * troughsNumberOfNodes + .1) * priceStep, endVolumeNodeIndex, lowestPrice + (volumeNodeLevel - 2 * troughsNumberOfNodes + .9) * priceStep, color(na), bgcolor = vn_troughVolumeColor)) if vn_troughsShow == 'Clusters' for currentVolumeNode = volumeNodeLevel - 2 * troughsNumberOfNodes to volumeNodeLevel if currentVolumeNode >= troughsNumberOfNodes and currentVolumeNode <= vp_profileNumberOfRows - 1 + troughsNumberOfNodes if not volumeDataArray.troughVolume.get(currentVolumeNode - troughsNumberOfNodes) startVolumeNodeIndex := vp_profileShow ? profilePlacementRight ? VP.startIndex : volumeDataArray.endProfileIndex.get(currentVolumeNode - troughsNumberOfNodes) : //VP.startIndex + int(volumeDataArray.totalVolume.get(currentVolumeNode) / volumeDataArray.totalVolume.max() * profileWidth) : VP.startIndex endVolumeNodeIndex := vp_profileShow ? profilePlacementRight ? volumeDataArray.endProfileIndex.get(currentVolumeNode - troughsNumberOfNodes) : //profileHorizontalOffset + int(last_bar_index - volumeDataArray.totalVolume.get(currentVolumeNode) / volumeDataArray.totalVolume.max() * profileWidth) : last_bar_index : last_bar_index VP.boxes.push(box.new(startVolumeNodeIndex, lowestPrice + (currentVolumeNode - troughsNumberOfNodes + .0) * priceStep, endVolumeNodeIndex, lowestPrice + (currentVolumeNode - troughsNumberOfNodes + 1.) * priceStep, color(na), bgcolor = vn_troughVolumeColor)) volumeDataArray.troughVolume.set(currentVolumeNode - troughsNumberOfNodes, true) tempTroughTotalVolume.clear() if vn_highestNVolumeNodes > 0 for highestNode = 0 to vn_highestNVolumeNodes - 1 startVolumeNodeIndex = vp_profileShow ? profilePlacementRight ? VP.startIndex : volumeDataArray.endProfileIndex.get(volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.max(highestNode))) : //VP.startIndex + int(volumeDataArray.totalVolume.get(volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.max(highestNode))) / volumeDataArray.totalVolume.max() * profileWidth) : VP.startIndex endVolumeNodeIndex = vp_profileShow ? profilePlacementRight ? volumeDataArray.endProfileIndex.get(volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.max(highestNode))) : //profileHorizontalOffset + int(last_bar_index - volumeDataArray.totalVolume.get(volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.max(highestNode))) / volumeDataArray.totalVolume.max() * profileWidth) : last_bar_index : last_bar_index VP.boxes.push(box.new(startVolumeNodeIndex, lowestPrice + (volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.max(highestNode)) + .1) * priceStep, endVolumeNodeIndex, lowestPrice + (volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.max(highestNode)) + .9) * priceStep, color(na), bgcolor = vn_highestVolumeColor)) if vn_lowestNVolumeNodes > 0 lowestNVolumeNodeCount = 0 lowestNVolumeNodeIndex = 0//volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.min()) lowestNVolumeNodeValue = 0. while lowestNVolumeNodeCount < vn_lowestNVolumeNodes if lowestNVolumeNodeIndex == vp_profileNumberOfRows break if volumeDataArray.totalVolume.min(lowestNVolumeNodeIndex) != lowestNVolumeNodeValue lowestNVolumeNodeValue := volumeDataArray.totalVolume.min(lowestNVolumeNodeIndex) startVolumeNodeIndex = vp_profileShow ? profilePlacementRight ? VP.startIndex : volumeDataArray.endProfileIndex.get(volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.min(lowestNVolumeNodeIndex))) : //VP.startIndex + int(volumeDataArray.totalVolume.get(volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.min(lowestNVolumeNodeIndex))) / volumeDataArray.totalVolume.max() * profileWidth) : VP.startIndex endVolumeNodeIndex = vp_profileShow ? profilePlacementRight ? volumeDataArray.endProfileIndex.get(volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.min(lowestNVolumeNodeIndex))) : //profileHorizontalOffset + int(last_bar_index - volumeDataArray.totalVolume.get(volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.min(lowestNVolumeNodeIndex))) / volumeDataArray.totalVolume.max() * profileWidth) : last_bar_index : last_bar_index VP.boxes.push(box.new(startVolumeNodeIndex, lowestPrice + (volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.min(lowestNVolumeNodeIndex)) + .1) * priceStep, endVolumeNodeIndex, lowestPrice + (volumeDataArray.totalVolume.indexof(volumeDataArray.totalVolume.min(lowestNVolumeNodeIndex)) + .9) * priceStep, color(na), bgcolor = vn_lowestVolumeColor)) lowestNVolumeNodeCount += 1 lowestNVolumeNodeIndex += 1 log.info("yaz_kizim {0} {1}", VP.boxes.size(), volumeDataArray.totalVolume.size() ) //---------------------------------------------------------------------------------------------------------------------}
Attachments forums
Re: Already Converted TradingView Indicators to MT4 Indicators
RodrigoRT7, Thu Jun 19, 2025 4:52 am