A running total of volume that adds or subtracts each bar's volume based on whether price closed up or down.
On-Balance Volume (OBV) is a cumulative volume indicator developed by Joseph Granville and popularized in the 1960s. It keeps a running total: when a bar closes higher than the previous close, that bar's volume is added to the line; when it closes lower, the volume is subtracted; when the close is unchanged, OBV stays flat. The idea is to track whether volume is broadly flowing into or out of an asset over time. OBV is plotted as a single line, usually in a separate pane below price. Its absolute value is not meaningful on its own; what matters is its direction and how it changes relative to price. Like every indicator, OBV is descriptive rather than predictive, and no indicator can forecast future prices. All trading carries risk of loss.
OBV is built one bar at a time from two simple inputs: the close and the volume. Compare the current close to the previous close. If price went up, the full bar volume is added to the previous OBV value. If price went down, the full bar volume is subtracted. If the close is exactly the same, OBV carries over unchanged. The result is a cumulative line that rises during periods dominated by up-closes on volume and falls when down-closes on volume dominate. Note that OBV uses the whole bar's volume regardless of how large the price move was, so a tiny up-tick counts the same as a large rally. Because it is a running sum, the starting value is arbitrary and only the shape of the line over time is informative.
OBV has no length or smoothing parameter by default — it is a pure cumulative calculation, so there is nothing to tune. Some traders add a moving average of OBV (for example a 20-period SMA or EMA) as a reference line to gauge OBV's own trend, but that average is an optional add-on rather than part of the original indicator.
//@version=6
indicator("On-Balance Volume", shorttitle="OBV")
// Built-in cumulative OBV
obvLine = ta.obv
// Optional reference line: a moving average of OBV
maLength = input.int(20, "OBV MA Length", minval=1)
obvMa = ta.sma(obvLine, maLength)
plot(obvLine, "OBV", color=color.blue)
plot(obvMa, "OBV MA", color=color.orange)Pro tip: Compare the shape of OBV against price rather than its raw number. Overlaying a moving average of OBV can make the line's trend easier to read. Treat any divergence as a prompt to investigate further and to manage risk, never as a standalone reason to act.
Educational only — not financial advice, not a recommendation to trade. No indicator is predictive; trading involves substantial risk of loss.