Indicator · Pine Script v6 · Own pane

On Balance Volume

by TamTH-Dev· code credited to tamth_

Calculates On Balance Volume (OBV) and displays it in a separate pane alongside optional exponential moving averages.

View on GitHub

GitHub stars2on the repository
Pine versionv6current
Lines of code112
Settings13inputs
LicenceNone statedfile: MPL-2.0
Last update5 weeks ago18 Sep 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

112 lines of Pine Script v6 from strategies/strategies3/On Balance Volume.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

On Balance Volume.pine
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © tamth_
 
//@version=6
indicator("On Balance Volume", "OBV", overlay = false, precision = 2, max_labels_count = 500, max_lines_count = 500, max_boxes_count = 1000, max_bars_back = 1000)

//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
// Colors
color TRANSPARENT_COLOR = color.new(#000000, 100)
color WHITE_COLOR      = #dee2e6
color BLACK_COLOR      = #000000
color RED_COLOR        = #F72585
color ORANGE_COLOR     = #fb5607
color YELLOW_COLOR     = #ffbe0b
color GREEN_COLOR      = #2a9d8f
color AQUA_COLOR       = #4CC9F0
color BLUE_COLOR       = #4361ee
color PURPLE_COLOR     = #3F37C9
color PINK_COLOR       = #B5179E
color LIGHT_GRAY_COLOR = #364156
color DARK_GRAY_COLOR  = #212d40
color TEXT_COLOR       = #ced4da

//-----------------------------------------------------------------------------
// Common Variables
//-----------------------------------------------------------------------------
// Bar index and input
series int barIdx = bar_index

//-----------------------------------------------------------------------------
// Common Methods
//-----------------------------------------------------------------------------
// Debug label function
debug(simple string txt) =>
    var label lbl = label.new(barIdx, na, txt, xloc.bar_index, yloc.price, color(na), label.style_none, WHITE_COLOR, size.large, text.align_left)
    label.set_xy(lbl, barIdx, ta.highest(10)[1])
    label.set_text(lbl, txt)

//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// On Balance Volume
//-----------------------------------------------------------------------------
// Settings
//-----------------------------------------------------------------------------
obvGrp = "On Balance Volume"
obvEma1Showed = input.bool(defval = true, title = "EMA 1", inline = "ema1", group = obvGrp)
obvEma1Len = input.int(defval = 21, title = "", minval = 1, inline = "ema1", group = obvGrp)
obvEma1Color = input.color(defval = AQUA_COLOR, title = "", inline = "ema1", group = obvGrp)
obvEma2Showed = input.bool(defval = true, title = "EMA 2", inline = "ema2", group = obvGrp)
obvEma2Len = input.int(defval = 55, title = "", minval = 1, inline = "ema2", group = obvGrp)
obvEma2Color = input.color(defval = PURPLE_COLOR, title = "", inline = "ema2", group = obvGrp)
obvEma3Showed = input.bool(defval = true, title = "EMA 3", inline = "ema3", group = obvGrp)
obvEma3Len = input.int(defval = 144, title = "", minval = 1, inline = "ema3", group = obvGrp)
obvEma3Color = input.color(defval = PINK_COLOR, title = "", inline = "ema3", group = obvGrp)
obvBodyUpColor = input.color(defval = TRANSPARENT_COLOR, title = "Body", inline = "bcol", group = obvGrp)
obvBodyDnColor = input.color(defval = TRANSPARENT_COLOR, title = "", inline = "bcol", group = obvGrp)
obvBorderUpColor = input.color(defval = WHITE_COLOR, title = "Border", inline = "bocol", group = obvGrp)
obvBorderDnColor = input.color(defval = BLUE_COLOR, title = "", inline = "bocol", group = obvGrp)

//-----------------------------------------------------------------------------
// Methods
//-----------------------------------------------------------------------------
// obvHaClose = (open + high + low + close) / 4
// obvHaOpen  = (open[1] + close[1]) / 2     
// obvHaHigh  = math.max(high, math.max(open, close))
// obvHaLow   = math.min(low,  math.min(open, close))
obvHaClose = close
obvHaOpen  = open    
obvHaHigh  = high
obvHaLow   = low

obvTw = obvHaHigh - math.max(obvHaOpen, obvHaClose) 
obvBw = math.min(obvHaOpen, obvHaClose) - obvHaLow 
obvBody = math.abs(obvHaClose - obvHaOpen) 

obvGetRate(cond) =>
    ret = 0.5 * (obvTw + obvBw + (cond ? 2 * obvBody : 0)) / (obvTw + obvBw + obvBody) 
    ret := nz(ret) == 0 ? 0.5 : ret
    ret
    
//-----------------------------------------------------------------------------
// Calculate
//-----------------------------------------------------------------------------
obvDeltaUp =  volume * obvGetRate(obvHaOpen <= obvHaClose) 
obvDeltaDn = volume * obvGetRate(obvHaOpen > obvHaClose)
obvDelta = obvHaClose >= obvHaOpen ? obvDeltaUp : -obvDeltaDn
obvCumDelta = ta.cum(obvDelta)
float obvCumDeltaOpen = obvCumDelta[1]
float obvCumDeltaHigh = math.max(obvCumDelta, obvCumDelta[1])
float obvCumDeltaLow = math.min(obvCumDelta, obvCumDelta[1])
float obvCumDeltaClose = obvCumDelta
float obvClose = na
float obvOpen = na
float obvHigh = na
float obvLow = na
obvClose := (obvCumDeltaOpen + obvCumDeltaHigh + obvCumDeltaLow + obvCumDeltaClose) / 4
obvOpen  := na(obvOpen[1]) ? (obvCumDeltaOpen + obvCumDeltaClose) / 2 : (obvOpen[1] + obvClose[1]) / 2
obvHigh  := math.max(obvCumDeltaHigh, math.max(obvOpen, obvClose))
obvLow   := math.min(obvCumDeltaLow, math.min(obvOpen, obvClose))

//-----------------------------------------------------------------------------
// Render
//-----------------------------------------------------------------------------
plotcandle(obvOpen, obvHigh, obvLow, obvClose, title = 'OBV Candles', color = obvOpen <= obvClose ? obvBodyUpColor : obvBodyDnColor, bordercolor = obvOpen <= obvClose ? obvBorderUpColor : obvBorderDnColor, wickcolor = obvOpen <= obvClose ? obvBorderUpColor : obvBorderDnColor, display = display.pane)
plot(obvEma1Showed ? ta.ema(obvClose, obvEma1Len) : na, title = "EMA 1", color = obvEma1Color, display = display.pane)
plot(obvEma2Showed ? ta.ema(obvClose, obvEma2Len) : na, title = "EMA 2", color = obvEma2Color, display = display.pane)
plot(obvEma3Showed ? ta.ema(obvClose, obvEma3Len) : na, title = "EMA 3", color = obvEma3Color, display = display.pane)

//-----------------------------------------------------------------------------

Overview

Traders can toggle and configure three distinct EMAs with default lengths of 21, 55, and 144. The indicator provides extensive visual settings, allowing customization of EMA colors, candle body fills, and border outlines for volume-based candlestick rendering.

Details

Published by

TamTH-Dev on GitHub

Code credit

tamth_, as written in the script's header

Type

Indicator, Pine Script v6

Draws

Separate pane below the chart

Category

Volume, Moving averages

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

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

SettingTypeDefaultVariable
EMA 1booltrueobvEma1Showed
obvEma1Lenint21obvEma1Len
obvEma1ColorcolorAQUA_COLORobvEma1Color
EMA 2booltrueobvEma2Showed
obvEma2Lenint55obvEma2Len
obvEma2ColorcolorPURPLE_COLORobvEma2Color
EMA 3booltrueobvEma3Showed
obvEma3Lenint144obvEma3Len
obvEma3ColorcolorPINK_COLORobvEma3Color
BodycolorTRANSPARENT_COLORobvBodyUpColor
obvBodyDnColorcolorTRANSPARENT_COLORobvBodyDnColor
BordercolorWHITE_COLORobvBorderUpColor
Show all 13 settings
SettingTypeDefaultVariable
obvBorderDnColorcolorBLUE_COLORobvBorderDnColor
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

Aggregate Signal (v.2)

by capissimo
114 stars

Aggregate Signal (v.2) is an oscillator indicator that combines multiple technical factors into a single composite score. It scales OHLCV data using minimax normalization and evaluates indicators such as MACD, RSI, Stochastic, CCI, Momentum, On-Balance Volume,

Indicator v4 Oscillators & momentumMoving averages Repaints
Updated 1 year ago · None stated GitHub repository of Aggregate Signal (v.2)

Volume-Weighted MACD

by mihakralj
99 stars

This indicator plots a volume-weighted MACD in a separate pane. It subtracts a slow volume-weighted moving average of close from a faster one, then smooths that line with an exponential moving average to form the signal. A column histogram shows the gap betwee

Indicator v5 Oscillators & momentumMoving averages
Updated 4 weeks ago · Apache-2.0 GitHub repository of Volume-Weighted MACD

PPO ATR Bands

by cryptorife
75 stars

PPO ATR Bands plots a percentage price oscillator in a separate pane. It compares a Hull average of typical price with a volume-weighted exponential average of Parabolic SAR, then scales three true-range bands around the slow average into matching oscillator l

Indicator v4 Oscillators & momentumMoving averages
Updated 3 years ago · GPL-3.0 GitHub repository of PPO ATR Bands

RSI-VWMA

by Zettt
43 stars

This indicator calculates the Relative Strength Index using a volume-weighted moving average of the closing price as its source. It plots the resulting oscillator in a separate pane alongside configurable overbought and oversold threshold lines. The plot line

Indicator v4 Oscillators & momentumMoving averages
Updated 1 year ago · None stated GitHub repository of RSI-VWMA

Trap Shorts - Hamza Naveed

by ProfHamzaNaveed
43 stars

This indicator tracks and visualizes cryptocurrency net positioning across multiple derivative exchanges, including Binance, BitMEX, and Kraken. It calculates aggregated net longs, net shorts, net delta, and ratio metrics, or an optional Position RSI, renderin

Indicator v5 VolumeOscillators & momentum
Updated 9 months ago · None stated GitHub repository of Trap Shorts - Hamza Naveed

On Balance Volume

by TWODS-CAPITAL
37 stars

This indicator plots the standard On Balance Volume (OBV) in a separate pane by accumulating volume based on the direction of price changes. It includes an optional smoothing line that can apply a Simple, Exponential, Smoothed, Weighted, or Volume-Weighted Mov

Indicator v5 VolumeMoving averages
Updated 3 years ago · MIT GitHub repository of On Balance Volume

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