Indicator · Pine Script v6 · Own pane

Smart Money Volume Tools

by vedkanani123· code credited to LyroRS

A separate-pane volume indicator that combines fast and slow EMAs of price, a volume average and a lower-timeframe volume read, normalized with an adjustable steepness value.

View on GitHub

Repaints

GitHub stars1on the repository
Pine versionv6current
Lines of code367
Settings15inputs
LicenceNone statedfile: MPL-2.0
Last update2 months ago23 Aug 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

367 lines of Pine Script v6 from indicator/olg_7_6_26/LyroRS/14.txt, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

14.txt
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © LyroRS

//@version=6
indicator("Smart Money Volume Tools | Lyro RS", overlay = false, shorttitle = "SMVT | Lyro RS")


// Libraries
import LyroRS/LMAs/1 as DynamicMAs

//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
//─██████─────────████████──████████─████████████████───██████████████───────████████████████───██████████████─
//─██░░██─────────██░░░░██──██░░░░██─██░░░░░░░░░░░░██───██░░░░░░░░░░██───────██░░░░░░░░░░░░██───██░░░░░░░░░░██─
//─██░░██─────────████░░██──██░░████─██░░████████░░██───██░░██████░░██───────██░░████████░░██───██░░██████████─
//─██░░██───────────██░░░░██░░░░██───██░░██────██░░██───██░░██──██░░██───────██░░██────██░░██───██░░██─────────
//─██░░██───────────████░░░░░░████───██░░████████░░██───██░░██──██░░██───────██░░████████░░██───██░░██████████─
//─██░░██─────────────████░░████─────██░░░░░░░░░░░░██───██░░██──██░░██───────██░░░░░░░░░░░░██───██░░░░░░░░░░██─
//─██░░██───────────────██░░██───────██░░██████░░████───██░░██──██░░██───────██░░██████░░████───██████████░░██─
//─██░░██───────────────██░░██───────██░░██──██░░██─────██░░██──██░░██───────██░░██──██░░██─────────────██░░██─
//─██░░██████████───────██░░██───────██░░██──██░░██████─██░░██████░░██───────██░░██──██░░██████─██████████░░██─
//─██░░░░░░░░░░██───────██░░██───────██░░██──██░░░░░░██─██░░░░░░░░░░██───────██░░██──██░░░░░░██─██░░░░░░░░░░██─
//─██████████████───────██████───────██████──██████████─██████████████───────██████──██████████─██████████████─
//─────────────────────────────────────────────────────────────────────────────────────────────────────────────
//                                                 LyroRS v1.0


// INPUT GROUPS
ma_g      = "𝗠𝗢𝗩𝗜𝗡𝗚 𝗔𝗩𝗘𝗥𝗔𝗚𝗘"
vol_g     = "𝗩𝗢𝗟𝗨𝗠𝗘"
display_g = "𝗗𝗜𝗦𝗣𝗟𝗔𝗬"
table_g = "𝗧𝗔𝗕𝗟𝗘"


// Moving Average
source   = input.source(close, "Source", group=ma_g, tooltip="Select the source for moving averages (open, high, low, close, etc.).")
len_fast = input.int(9,  "Fast EMA Length", group=ma_g, minval=1, tooltip="Short-term moving average for trend direction.")
len_slow = input.int(35, "Slow EMA Length", group=ma_g, minval=1, tooltip="Long-term moving average for trend direction comparison.")


// Volume Strength
len_vol = input.int(14, "Volume SMA Length", group=vol_g, minval=1, tooltip="Period for smoothing the volume average used in relative volume strength calculation.")
sig_k   = input.float(0.6, "Normalization Steepness (k)", step=0.1, minval=0.01, maxval=5.0, group=vol_g, tooltip="Controls how aggressively the volume signal is normalized between 0–100.")

// Display
tf = input.timeframe("120", "Lower Timeframe Value", tooltip = "Determines the lower timeframe used to calculate buying and selling volume", group=display_g)
signal_type = input.string("Trail", "Select Signal Type", options=["Trail", "Volume", "Smart Money Volume", "Retail Money Volume"], group=display_g, tooltip="Select which mode the Volume Trend Trail operates in — price trend, volume impulse, or hybrid.")
ColMode = input.string("Mystic", "Color Palette", inline="drop", options=["Classic", "Mystic", "Accented", "Royal"], display=display.none, group=display_g, tooltip="Select a predefined color scheme for the trail visualization.")

cpyn    = input.bool(true, "Use Custom Palette", group=display_g, display=display.none, tooltip="Enable manual selection of bullish and bearish colors.")
cp_UpC  = input.color(#00ff00, "Custom Up", inline="Custom Palette", group=display_g, display=display.none, tooltip="Custom bullish trail color.")
cp_DnC  = input.color(#ff0000, "Custom Down", inline="Custom Palette", group=display_g, display=display.none, tooltip="Custom bearish trail color.")

// Table 
fo_table = input.bool(false, "Force Table Overlay", group=table_g)
enable_table = input.bool(true, "", display=display.none, group=table_g, inline= "1")
pos_table = input.string('Middle Right', 'SMVTB Table', options=['Top Left','Middle Left','Bottom Left','Top Right','Middle Right','Bottom Right','Top Center','Middle Center','Bottom Center'], group=table_g, inline= "1")
table_size_input = input.string("Normal", "", options=["Huge","Large","Normal","Small","Tiny"], group=table_g, inline= "1")


// -- Predefined Colors
color UpC = na
color DnC = na

switch ColMode
    "Classic" =>
        UpC := #00E676
        DnC := #880E4F
    "Mystic" =>
        UpC := #30FDCF
        DnC := #E117B7
    "Accented" =>
        UpC := #9618F7
        DnC := #FF0078
    "Royal" =>
        UpC := #FFC107
        DnC := #673AB7

if cpyn
    UpC := cp_UpC
    DnC := cp_DnC


// Table Size
var string table_size = na
switch table_size_input
    "Huge" => table_size := size.huge
    "Large" => table_size := size.large
    "Normal" => table_size := size.normal
    "Small" => table_size := size.small
    "Tiny" => table_size := size.tiny

// Table Position Helper
table_position(pos) =>
    switch pos
        'Top Left' => position.top_left
        'Middle Left' => position.middle_left
        'Bottom Left' => position.bottom_left
        'Top Right' => position.top_right
        'Middle Right' => position.middle_right
        'Bottom Right' => position.bottom_right
        'Top Center' => position.top_center
        'Middle Center' => position.middle_center
        'Bottom Center' => position.bottom_center


// Core Logic
vol_strength = volume / DynamicMAs.SMA(volume, len_vol)
ema_fast = DynamicMAs.EMA(close, len_fast)
ema_slow = DynamicMAs.EMA(close, len_slow)
trend_dir = ema_fast > ema_slow ? 1 : -1
vtt_score = trend_dir * (vol_strength - 1)


// Sigmoid normalization 0–100
sigmoid(x, k) => 1.0 / (1.0 + math.exp(-k * x))
norm_score = sigmoid(vtt_score, sig_k) * 100


base = (ema_fast + ema_slow) / 2
atr = ta.atr(14)
dynamicmult = 1.5 + (math.abs(norm_score - 50) / 100) * 2.0
upperBand = base + dynamicmult * atr
lowerBand = base - dynamicmult * atr


// Trail Logic
var float ut = na // Upper Trail
var float lt = na // Lower Trail
var int   score = 0

// Initialize Trails
if na(ut)
    ut := upperBand
if na(lt)
    lt := lowerBand


// Update Trails Based on Score
if score == 1
    lt := math.max(lowerBand, nz(lt[1]))  // Trail follows rising lows
    ut := upperBand                       // Reset upper trail on long

if score == -1
    ut := math.min(upperBand, nz(ut[1]))  // Trail follows falling highs
    lt := lowerBand                       // Reset lower trail on short


// Smart Money Volume
v = request.security_lower_tf(syminfo.tickerid, tf, volume)
c = request.security_lower_tf(syminfo.tickerid, tf, close)
o = request.security_lower_tf(syminfo.tickerid, tf, open)


var vols = array.new_float()
res_size = v.size()
maximum = 50 * res_size
indexes = array.new_int()

var line[]  levelLines       = array.new<line>()
var float[] levelPrices      = array.new<float>()
var int[]   levelTypes       = array.new<int>()
var int[]   levelCreatedBars = array.new<int>()
var int[]   levelClasses     = array.new<int>()
var line[]  levelGlow1Lines  = array.new<line>()
var float[] levelVols        = array.new<float>()
var float[] levelZs          = array.new<float>()
maxStored = 150
zStoredCap = 100

var float[] levelActiveVols  = array.new<float>()

float barMaxAbsZ = na
int barBubbleDir = na
float barBubblePrice = na
int barBubbleClass = na

var bool retailBullBar  = false
var bool retailBearBar  = false
var bool smartBullBar   = false
var bool smartBearBar   = false

if barstate.isnew
    barMaxAbsZ := na
    barBubbleDir := na
    barBubblePrice := na
    barBubbleClass := na
    retailBullBar  := false
    retailBearBar  := false
    smartBullBar   := false
    smartBearBar   := false

if res_size > 0
    for i = res_size - 1 to 0
        vols.unshift(v.get(i))

while vols.size() > maximum
    vols.pop()

if vols.size() > 0
    for i = 0 to res_size-1
        zscore = (vols.get(i) - vols.avg()) / vols.stdev()
        if zscore > 2
            indexes.unshift(i)

if indexes.size() > 0
    for i = 0 to indexes.size() - 1
        intra_close = c.get(indexes.get(i))
        intra_open  = o.get(indexes.get(i))
        isBull      = intra_close > intra_open
        int typ     = isBull ? 1 : -1
        bodyMin = math.min(open, close)
        bodyMax = math.max(open, close)
        lvlPrice = intra_close
        isAtClose = lvlPrice == close
        isStrictInBody = lvlPrice > bodyMin and lvlPrice < bodyMax
        int cls  = isAtClose ? 1 : (isStrictInBody ? 2 : 1)


        evtVol = v.get(indexes.get(i))
        volsAvg = vols.avg()
        volsStdev = vols.stdev()
        zVal = volsStdev > 0 ? (evtVol - volsAvg) / volsStdev : 0.0
        int widthZ = math.max(1, math.min(10, math.round(math.abs(zVal))))

        if cls == 1
            if isBull
                retailBullBar := true
            else
                retailBearBar := true
        else if cls == 2
            if isBull
                smartBullBar := true
            else
                smartBearBar := true




// Conditions
long_condition  = close > ut
short_condition = close < lt

if long_condition
    score := 1
else if short_condition
    score := -1

// Plot Color
var color pc = na
if signal_type == "Trail"
    if score == 1
        pc := UpC

    else if score == -1
        pc := DnC



if signal_type == "Volume"
    if trend_dir == 1
        if norm_score > 60
            pc := UpC
        else
            pc := pc
    else
        if norm_score < 40
            pc := DnC
        else
            pc := pc



if signal_type == "Smart Money Volume"
    if smartBullBar == true
        pc := UpC

    else if smartBearBar == true
        pc := DnC

    else
        pc := color.gray


if signal_type == "Retail Money Volume"
    if retailBullBar == true
        pc := UpC

    else if retailBearBar == true
        pc := DnC

    else
        pc := color.gray

// Plot
pUpper = plot(ut,  "Volume Trail Upper", color = score == -1 ? DnC : na, linewidth = 2, force_overlay = true, display= signal_type == "Trail" ? display.all : display.none)
pLower = plot(lt,  "Volume Trail Lower", color = score == 1 ? UpC : na, linewidth = 2, force_overlay = true, display= signal_type == "Trail" ? display.all : display.none)
pClose = plot(close, color = na, editable = false, force_overlay = true, display= signal_type == "Trail" ? display.all : display.none)

fill(pLower, pClose, lt, close, score == 1 ? color.new(UpC, 30) : na, color.new(chart.bg_color, 50), editable = false, display= signal_type == "Trail" ? display.all : display.none)
fill(pUpper, pClose, ut, close,  score == -1 ? color.new(DnC, 30) : na, color.new(chart.bg_color, 50), editable = false, display= signal_type == "Trail" ? display.all : display.none)

plot(vtt_score, title="Volume Score", color=pc, linewidth=2, display = signal_type == "Trail" and not (signal_type == "Smart Money Volume") ? display.pane : display.all)

plot(volume, "Volume", color= color.new(close > open ? UpC : DnC, 65), display= signal_type == "Smart Money Volume" or signal_type == "Retail Money Volume" ? display.all : display.none, style= plot.style_columns)
plot(DynamicMAs.EMA(volume, 25), "Volume", color= color.new(color.blue, 30), display= signal_type == "Smart Money Volume" or signal_type == "Retail Money Volume" ? display.all : display.none, linewidth = 2)


plotcandle(open, high, low, close, color= pc, wickcolor= pc, bordercolor = pc, display=display.pane, title = "Candle Color", force_overlay = true)
hline(0, color= color.gray, editable = false)




// Tables
var table sm_table = na
if fo_table
    sm_table := table.new(table_position(pos_table), 100, 100, frame_width=1, frame_color=color.gray, force_overlay=true, border_color=color.gray, border_width=1)
else
    sm_table := table.new(table_position(pos_table), 100, 100, frame_width=1, frame_color=color.gray, force_overlay=false, border_color=color.gray, border_width=1)

// Table Cells
if enable_table
    // Title
    table.cell(sm_table, 0, 0, "SMVTB Signal Table | LyroRS", text_color=color.white, bgcolor=#000000, text_size=table_size)
    table.cell(sm_table, 1, 0, "", text_color=color.white, bgcolor=#000000, text_size=table_size)

    // Headers
    table.cell(sm_table, 0, 1, "MODULES", text_color=color.white, bgcolor=#000000, text_size=table_size)
    table.cell(sm_table, 1, 1, "SIGNALS", text_color=color.white, bgcolor=#000000, text_size=table_size)

    // Trail Module
    table.cell(sm_table, 0, 2, "Trail", text_color=color.white, bgcolor=#000000, text_size=table_size)
    table.cell(sm_table, 1, 2, score == 1 ? "⬆️ Long ⬆️" : score == -1 ? "⬇️ Short ⬇️" : "—", text_color=score == 1 ? UpC : score == -1 ? DnC : color.gray, bgcolor=#000000, text_size=table_size)

    // Volume Module
    table.cell(sm_table, 0, 3, "Volume", text_color=color.white, bgcolor=#000000, text_size=table_size)
    table.cell(sm_table, 1, 3, score == 1 ? "🚀Up 🚀" : "🪂Down 🪂", 
       text_color= score == 1 ? UpC : DnC, 
       bgcolor=#000000, text_size=table_size)

    // Smart Money Module
    table.cell(sm_table, 0, 4, "Smart Money", text_color=color.white, bgcolor=#000000, text_size=table_size)
    table.cell(sm_table, 1, 4, smartBullBar ? "⬆️ Buy ⬆️" : smartBearBar ? "⬇️ Sell ⬇️" : "No Action", text_color=smartBullBar ? UpC : smartBearBar ? DnC : color.gray, bgcolor=#000000, text_size=table_size)

    // Retail Money Module
    table.cell(sm_table, 0, 5, "Retail Money", text_color=color.white, bgcolor=#000000, text_size=table_size)
    table.cell(sm_table, 1, 5, retailBullBar ? "⬆️ Buy ⬆️" : retailBearBar ? "⬇️ Sell ⬇️" : "No Action", text_color=retailBullBar ? UpC : retailBearBar ? DnC : color.gray, bgcolor=#000000, text_size=table_size)

    // Merge Title Cells
    table.merge_cells(sm_table, 0, 0, 1, 0)





// Alerts
alertcondition(ta.crossover(score, 0), "SMVTB - Trail Long", "Smart Money Volume Tool Box is bullish on the trail mode{{ticker}} {{interval}}")
alertcondition(ta.crossunder(score, 0), "SMVTB - Trail Short", "Smart Money Volume Tool Box is bearish on the trail mode{{ticker}} {{interval}}")

alertcondition(ta.crossover(trend_dir, 0), "SMVTB - Volume Long", "Smart Money Volume Tool Box is bullish on the volume mode{{ticker}} {{interval}}")
alertcondition(ta.crossunder(trend_dir, 0), "SMVTB - Volume Short", "Smart Money Volume Tool Box is bearish on the volume mode{{ticker}} {{interval}}")

alertcondition(smartBullBar == true, "SMVTB - Smart Money Buying", "Smart Money Volume Tool Box is suggesting smart money is buying{{ticker}} {{interval}}")
alertcondition(smartBearBar == true, "SMVTB - Smart Money Selling", "Smart Money Volume Tool Box is suggesting smart money is selling{{ticker}} {{interval}}")

alertcondition(retailBullBar == true, "SMVTB - Retail Money Buying", "Smart Money Volume Tool Box is suggesting retail money is buying{{ticker}} {{interval}}")
alertcondition(retailBearBar == true, "SMVTB - Retail Money Selling", "Smart Money Volume Tool Box is suggesting retail money is selling{{ticker}} {{interval}}")

Overview

A signal type setting chooses between a trailing style and other readings, and the output is colored bullish or bearish. A table can display the current states. It reads volume from a lower timeframe, so results depend on the data available for the symbol.

Details

Published by

vedkanani123 on GitHub

Code credit

LyroRS, as written in the script's header

Type

Indicator, Pine Script v6

Draws

Separate pane below the chart

Category

Volume, Trend

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

  • Signals can change on the live bar or after it closes (repainting)

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Sourcesourceclosesource
Fast EMA Lengthint9len_fast
Slow EMA Lengthint35len_slow
Volume SMA Lengthint14len_vol
Normalization Steepness (k)float0.6sig_k
Lower Timeframe Valuetimeframe120tf
Select Signal TypestringTrailsignal_type
Color PalettestringMysticColMode
Use Custom Palettebooltruecpyn
Custom Upcolor#00ff00cp_UpC
Custom Downcolor#ff0000cp_DnC
Force Table Overlayboolfalsefo_table
Show all 15 settings
SettingTypeDefaultVariable
enable_tablebooltrueenable_table
SMVTB TablestringMiddle Rightpos_table
table_size_inputstringNormaltable_size_input
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

This indicator plots a Supertrend-based trend-following setup in a separate pane and skips conditions it treats as a sideways market. A volatility range is built from an ATR value, with RMA, SMA, EMA, or WMA smoothing, or from a fixed point distance. Optional

Indicator v5 TrendVolatility & bands
Updated 1 year ago · MPL-2.0 GitHub repository of Trend Following Setup - Sideways Market Skipper

This indicator combines Chaikin Money Flow (CMF), a SuperTrend baseline, and an Average True Range (ATR) calculation inside a separate sub-pane. It calculates a standard 20-period CMF plotted as a line and colored histogram columns around a zero baseline, trac

Indicator v6 TrendVolume
Updated 6 months ago · Apache-2.0 GitHub repository of Institutional View: CMF & SuperTrend
14 stars

This indicator calculates intrabar Cumulative Volume Delta (CVD) using lower timeframe data and applies linear regression to determine market bias. It evaluates regression slope and R-squared values across a chosen anchor period to identify volume-driven trend

Indicator v6 VolumeTrend
Updated 2 weeks ago · None stated GitHub repository of Alighten CVD Regression Bias
9 stars

FlowBias calculates a composite market momentum metric using Chaikin Money Flow, volume delta, Stochastic, and the Ultimate Oscillator. Plotted in a separate pane, it identifies trend pullbacks and market exhaustion reversals through visual signals and labels.

Indicator v6 TrendOscillators & momentum
Updated 2 days ago · MIT GitHub repository of FlowBias [WavesUnchained]

Nexural Pressure Pro

by JasonTeixeira
9 stars

Nexural Pressure Pro is a composite pressure indicator that measures directional market momentum using volume-weighted directional movement, order flow delta, aggression, and efficiency ratio metrics. It filters out low-activity bars using configurable volume

Indicator v6 Oscillators & momentumVolume
Updated 13 days ago · Custom licence GitHub repository of Nexural Pressure Pro

PaperHands

by lunarticktrading
7 stars

PaperHands is an indicator that plots entry, re-entry, and exit signals for LONG and SHORT positions in a separate pane. It calculates signals using multiple confluence conditions such as real candle color, Heikin-Ashi candle color and flat bottoms or tops, He

Indicator v6 TrendOscillators & momentum
Updated 2 weeks ago · None stated GitHub repository of PaperHands

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers