On-Balance Volume (OBV): Formula, Signals, and What Tests Reveal

Volume-weighted signed flow and equal votes of the same closing directions sometimes fall on opposite sides of zero.

Key takeaways

  • OBV adds or subtracts an entire candle's volume according to the direction of its close; it discards the size of that price change.
  • OBV's cumulative starting level is arbitrary. Changes and relative comparisons survive a constant shift, while raw zero crossings do not.
  • At a 20-bar lookback, volume-weighted flow and equal closing-direction votes had strictly opposite signs on about 5–11% of checked candles in the historical samples.

On-Balance Volume, usually shortened to OBV, adds volume after an up close and subtracts it after a down close. The resulting line summarizes volume signed by closing direction.

Our 129,887 configuration evaluations compare that volume weighting with an equal vote for each candle’s direction. At a 20-bar lookback, the two measures had strictly opposite signs on about 5–11% of checked candles across the historical samples. Volume confirmation can materially disagree with a simple tally of up and down closes.

How is OBV calculated?

The update has three cases:

Close above the previous close: add this bar's volume
Close below the previous close: subtract this bar's volume
Close unchanged:                leave OBV unchanged

TradingView’s OBV documentation describes that cumulative construction and its conventional uses for trend confirmation and divergence.

Suppose three candles have volumes of 100, 300, and 200. Their closes move up, down, and up. OBV’s net change is 100 − 300 + 200 = 0, although two of the three closes rose.

A move from 100 to 100.01 and a move from 100 to 110 both add the entire candle’s volume when they are up closes. OBV preserves the sign of the price change and discards its magnitude. It also does not identify the aggressor of each transaction: assigning all an up candle’s volume a positive sign is a calculation convention.

What does a rising OBV mean?

A rise means more volume has accumulated on up closes than on down closes over that portion of the line. Traders compare that direction with price, look for range breaks, or add a smoothing average.

It is a description of the signed-volume history. Price can still decline afterward. One large-volume candle can dominate the line, and a different venue or volume feed can produce a different path.

Calling OBV a leading indicator expresses the hope that a change in volume behavior comes before a price turn. The calculation itself supplies no guarantee that it will lead the next move.

Divergence means price and OBV fail to confirm one another’s highs, lows, or direction. A precise divergence strategy needs defined pivots, confirmation delays, and an entry rule. Our tested rules use rolling signed flow; they do not test discretionary chart divergence.

Why OBV’s zero level is arbitrary

If a chart starts OBV at zero and another starts it at one million, their curves differ by a constant. The signed-volume changes are identical.

That shift changes whether the raw OBV line lies above or below zero. It does not change these comparisons:

OBV now − OBV N bars ago

OBV now − its moving average

The constant cancels. A raw zero crossing therefore needs a deliberately fixed starting convention before it has a stable interpretation. An OBV-to-average comparison or rolling change asks a question that survives that shift.

This is an identity in the calculation, not a discovery established by counting more backtests.

How much difference does volume weighting make?

To compare volume with an equal vote, we put both measures on a shared scale:

Volume-weighted flow = rolling OBV change ÷ total volume
Equal-vote flow       = (up closes − down closes) ÷ number of bars

Both lie between −1 and +1 when volume is positive. The first gives a larger vote to a candle with more volume. The second gives each closing direction the same weight.

Historical indicator values Volume and closing-direction votes can disagree

A selected episode where total signed volume and an equal vote of closing directions point to opposite sides of zero.

The value table below is available without JavaScript.

Chart data
Data and calculation details
Source: Exact TrainBard-returned historical candles. Selected later-window two-hour sample; indicator values calculated locally from the exact returned OHLCV. Values are aligned to candle-open UTC timestamps and known at candle close. No execution markers or inferred fills.
Accessible value table (51 observations)
ObservationClosing price · Close20-bar normalized signed flow · Volume weighting20-bar normalized signed flow · Equal votes
2025-09-05T02:00:00Z111,311.7700.1470.100
2025-09-05T04:00:00Z111,574.5000.1410.100
2025-09-05T06:00:00Z112,954.3200.1440.100
2025-09-05T08:00:00Z112,303.8700.0220.000
2025-09-05T10:00:00Z112,354.0000.0940.100
2025-09-05T12:00:00Z113,084.1600.2940.200
2025-09-05T14:00:00Z110,716.8200.1040.200
2025-09-05T16:00:00Z110,608.1800.0490.100
2025-09-05T18:00:00Z111,614.5400.1170.200
2025-09-05T20:00:00Z110,605.0100.0960.200
2025-09-05T22:00:00Z110,659.9900.1390.300
2025-09-06T00:00:00Z110,867.7000.1350.300
2025-09-06T02:00:00Z111,082.2200.1730.400
2025-09-06T04:00:00Z110,714.0000.1950.400
2025-09-06T06:00:00Z110,825.6000.2890.500
2025-09-06T08:00:00Z110,695.0600.2440.400
2025-09-06T10:00:00Z110,781.0200.2250.400
2025-09-06T12:00:00Z110,936.8200.2170.400
2025-09-06T14:00:00Z110,384.1500.1440.300
2025-09-06T16:00:00Z110,157.4100.0670.200
2025-09-06T18:00:00Z110,038.4100.0200.100
2025-09-06T20:00:00Z110,201.000-0.0160.100
2025-09-06T22:00:00Z110,187.970-0.1400.000
2025-09-07T00:00:00Z110,546.660-0.0580.100
2025-09-07T02:00:00Z110,629.150-0.0700.100
2025-09-07T04:00:00Z110,649.440-0.3890.100
2025-09-07T06:00:00Z110,753.420-0.0650.200
2025-09-07T08:00:00Z111,115.9800.0960.300
2025-09-07T10:00:00Z111,292.1300.0300.300
2025-09-07T12:00:00Z111,214.6200.2320.300
2025-09-07T14:00:00Z111,329.9900.2360.300
2025-09-07T16:00:00Z110,962.8300.1250.200
2025-09-07T18:00:00Z111,259.9900.1260.200
2025-09-07T20:00:00Z111,050.1400.1570.200
2025-09-07T22:00:00Z111,137.3400.1960.200
2025-09-08T00:00:00Z110,890.5700.1200.200
2025-09-08T02:00:00Z111,052.1100.1590.200
2025-09-08T04:00:00Z111,027.1600.0780.100
2025-09-08T06:00:00Z111,280.3900.2060.200
2025-09-08T08:00:00Z112,094.9900.4330.300
2025-09-08T10:00:00Z112,052.4300.3320.300
2025-09-08T12:00:00Z111,906.5500.1730.200
2025-09-08T14:00:00Z112,631.7500.2900.300
2025-09-08T16:00:00Z112,214.4000.1820.200
2025-09-08T18:00:00Z112,097.3100.1030.100
2025-09-08T20:00:00Z112,326.4500.1180.100
2025-09-08T22:00:00Z112,065.2300.0440.000
2025-09-09T00:00:00Z111,364.730-0.087-0.100
2025-09-09T02:00:00Z111,708.000-0.056-0.100
2025-09-09T04:00:00Z112,200.0000.0150.000
2025-09-09T06:00:00Z112,991.1100.0990.000

Select Volume and votes disagree. The same twenty closing directions produce opposing signs because their volumes differ.

Across all eight historical samples, strict opposite signs covered about 5–11% of post-startup candles at that lookback. Ties in the equal-vote measure are counted separately; the percentage does not include them. This distinction matters because equal votes can sum to zero while signed volume points either way.

The observations share overlapping windows. They describe how often the calculations disagreed in these samples, not independent predictions.

Why some threshold changes make no difference

An equal vote produces a discrete score. With two candles and no unchanged closes, the possible averages are −1, 0, and +1.

A positive entry threshold of 0.10 or 0.80 then selects the same +1 state. Searching more numbers between them does not create a different signal. Volume weighting can distinguish mixed-direction pairs because unequal volumes need not cancel. With unchanged closes, zero votes introduce extra possible scores: at two bars, one up close and one unchanged close average +0.5.

The backtests compare strength entries above a positive flow threshold with fade entries below the negative threshold. Both exit when the flow returns across zero.

Recorded backtest metrics The lookback changes how volume and votes affect execution counts

One fixed rule and historical sample, changing only the displayed setting and line comparison. Each buy/sell is one execution.

The value table below is available without JavaScript.

Chart data
Data and calculation details
Source: Completed TrainBard fixed small-notional controls. Recorded historical execution counts; omitted-zero counts appear only after full UI reconciliation. Each entry requests100 quote units at signal close via qty=100/close; next-open notional can differ. Main99%-equity sweeps are separate. Exact source/frame/row mapping is in the evidence.
Accessible value table (99 observations)
ObservationExecutions by lookback (bars) · Volume weightingExecutions by lookback (bars) · Equal votes
23,756.0002,162.000
42,466.0001,492.000
61,847.0001,209.000
81,355.000979.000
101,051.000541.000
12853.000513.000
14709.000476.000
16620.000452.000
18516.000414.000
20442.000242.000
22392.000248.000
24328.000232.000
26316.000224.000
28290.000224.000
30248.000150.000
32240.000160.000
34210.000154.000
36184.000164.000
38176.000156.000
40166.00098.000
42150.000100.000
44144.00096.000
46140.00096.000
48130.00094.000
50122.00068.000
52120.00062.000
54116.00068.000
56104.00062.000
5894.00062.000
6088.00046.000
6290.00046.000
6484.00052.000
6676.00052.000
6876.00052.000
7070.00038.000
7264.00038.000
7470.00044.000
7668.00042.000
7860.00048.000
8058.00034.000
8250.00032.000
8446.00034.000
8648.00034.000
8840.00034.000
9040.00028.000
9240.00028.000
9438.00026.000
9638.00026.000
9840.00026.000
10036.00020.000
10238.00020.000
10436.00022.000
10632.00022.000
10826.00022.000
11026.00016.000
11226.00014.000
11424.00016.000
11624.00014.000
11824.00016.000
12024.00012.000
12224.0008.000
12422.00010.000
12620.00012.000
12818.00014.000
13018.0008.000
13218.0008.000
13418.0008.000
13618.00010.000
13816.0008.000
14016.0006.000
14218.0006.000
14416.0006.000
14616.0008.000
14816.0008.000
15014.0004.000
15214.0004.000
15416.0006.000
15614.0006.000
15816.0006.000
16014.0002.000
16214.0002.000
16412.0004.000
16612.0004.000
16814.0004.000
17012.0000.000
17212.0002.000
17412.0000.000
17612.0000.000
17810.0002.000
18012.0000.000
18212.0000.000
18412.0000.000
1868.0000.000
18810.0000.000
19012.0000.000
19212.0000.000
1948.0000.000
1968.0000.000
1988.0000.000

At twenty bars and a 0.20 imbalance threshold, one matched sample recorded 442 executions with volume weighting and 242 with equal votes. The price history, threshold, and strength rule were the same. Changing the weights changed more than the appearance of the line. At that same lookback and threshold, the volume-weighted rule also recorded more executions in all eight historical replications.

This separate comparison uses small positions and fixes the threshold and strength rule while varying lookback. Recorded execution counts include position state and the platform’s fill model. They are not counts of every qualifying candle.

A larger imbalance requirement can reduce activity, but that alone does not improve a strategy. Lower activity changes exposure and fee costs as well as which moves the strategy catches. The evidence gives returned performance summaries alongside their observed-row counts.

OBV settings and comparisons

Raw OBV has no rolling period: it accumulates. A period enters when a trader adds smoothing, measures a rolling change, or defines a breakout window. Specify which of those is being changed.

OBV and VWAP also answer different questions. OBV signs volume by the direction of the close. VWAP averages prices using volume weights. Neither is an interchangeable measure of actual order flow.

For a reproducible test, keep the volume feed fixed and define the lookback, normalization, threshold, and position rule. Comparing the two weightings under the same rules makes the effect of volume easier to assess.

Reproduce the comparison

The script defaults to twenty-bar volume-weighted flow and a zero-threshold strength rule. Equal-vote mode is a matched control for closing direction.

Pine Script v6
Open editor

//@version=6
strategy("OBV Lab: signed volume and equal votes", overlay=false, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=99, process_orders_on_close=false)

flow_length = input.int(20, "Flow lookback", minval=2, maxval=198)
threshold = input.float(0.0, "Imbalance threshold", minval=0.0, maxval=0.8)
weight_mode = input.int(0, "Weight: 0 volume, 1 equal votes", minval=0, maxval=1)
rule_mode = input.int(0, "Rule: 0 strength, 1 fade", minval=0, maxval=1)

vote = close > close[1] ? 1.0 : close < close[1] ? -1.0 : 0.0
obv_value = ta.obv
volume_total = flow_length * ta.sma(volume, flow_length)
volume_flow = volume_total > 0 ? (obv_value - obv_value[flow_length]) / volume_total : na
equal_flow = ta.sma(vote, flow_length)
flow = weight_mode == 0 ? volume_flow : equal_flow
ready = bar_index >= 500 and volume_total > 0
enter_long = ready and (rule_mode == 0 ? flow > threshold : flow < -threshold)
exit_long = ready and (rule_mode == 0 ? flow < 0 : flow >= 0)

plot(flow, "Normalized signed flow", color=color.blue)
plot(threshold, "Upper threshold", color=color.orange)
plot(-threshold, "Lower threshold", color=color.green)
plot(0, "Balance", color=color.gray)
if exit_long and strategy.position_size > 0
    strategy.close("Long")
if enter_long and not exit_long and strategy.position_size == 0
    strategy.entry("Long", strategy.long)

Markets, settings, accounting, and reproducibility

The study used Binance Spot BTCUSDT and ETHUSDT on two-hour and four-hour candles in 2021-01-01–2023-12-31 and 2024-01-01–2025-12-31. The eight historical frames use the same frozen grid; the later window is retrospective replication.

The two BTCUSDT two-hour main frames and the earlier frame’s activity controls were run through TrainBard’s MCP endpoint. Remaining frames were run through its web interface with the same frozen scripts. Completed UI totals, exact parameter membership, settings snapshots, and original exports are reconciled before inclusion. Omitted zero-trade tuples remain valid tested configurations; execution counts of zero are retained without inventing absent performance cells. Interface bridge checks are outside the main count.

Each frame has 16,236 configurations: 99 even lookbacks from 2 through 198, 41 imbalance thresholds from 0 through 0.8 in steps of 0.02, two weightings, and two rules. The requested grid contains 129,888 configurations. The main count is 129,887 accepted evaluations: one ETHUSDT two-hour earlier-window volume/fade tuple, lookback 2 and threshold 0.28, returned a runtime error in both its original run and an identical single-setting diagnostic. It is excluded, and its exact server cause remains unknown. The original joint UI batch was initially rejected; a documented independent review then accepted only its clean metric rows and uniquely reconciled zero tuples, preserving both the rejection and reviewed acceptance history. No result was substituted for the failed tuple. The accepted data contain 80,080 observed metric rows and 49,807 valid UI-omitted zero tuples. Return and drawdown summaries use the observed rows only; their coverage of cash configurations differs by interface. Fine thresholds can share an identical equal-vote decision path; all are related tested settings, not independent evidence. Diagnostic runs are excluded. 1,584 additional fixed small-notional evaluations repeat the complete activity curves across the same eight frames. In those controls, each entry requests qty = 100 / signal close; actual next-open fill notional can differ. Their smaller requested size separates the displayed activity comparison from the broad sweeps’ equity-funding behavior. The exact activity-control script is retained separately; these confirmations are excluded from the main count. The control total includes 119 reconciled UI-omitted zero tuples, with no invented portfolio metrics.

Volume flow is (OBV − OBV[length]) divided by length × SMA(volume, length). Equal flow is the SMA of +1, −1, or 0 closing-direction votes. Strength entries require flow greater than the threshold and exit below zero. Fade entries require flow less than minus the threshold and exit at or above zero. Entry requires flat position state; exit takes priority.

Every frame starts with 10,000 USDT and 500 startup bars in cash. Signals use completed candles and request next-open execution, 99% equity sizing, no leverage, and 0.1% combined fee/slippage per execution. That sizing request does not guarantee a persistent 1% cash reserve in returned fills. Idle cash earns no yield. Remaining positions are valued at the endpoint. The same 500-bar startup spans different elapsed time on the two candle sizes.

The end-date boundary includes the candle opening at 00:00 UTC on the named final date. Each buy and sell counts as an execution; totalTrades is not a count of completed round trips. Return and drawdown use the platform’s returned metrics. The execution and source audit preserves passive controls, sizing and fee checks.

All direct indicator measurements use exact TrainBard-returned candles. An official-archive crosscheck found small earlier-window differences, including volume fields, preserved in the audit. The teaching chart uses later-window values that matched the archive comparison.

The 20-bar sign comparison has 61,664 post-startup candle observations across eight frames. Strictly opposing nonzero signs and equal-vote ties are reported separately for each frame in the study evidence. Two-hour and four-hour observations are related representations of the same markets and are not independent trials.

The historical chart selects the largest volume/equal-flow difference among strict opposite-sign observations in the BTCUSDT two-hour later frame. It is a conditional teaching example with locally calculated values and no execution markers. The activity chart uses the fixed small-notional controls on the BTCUSDT two-hour early frame, a 0.20 threshold, and the strength rule, varying only lookback and weighting.

The evidence file contains run identifiers, exact grids, per-frame counts, results summaries, candle provenance, checksums, and the calculation selection rule. The tested script accompanies it; full requests and exports remain in the research archive. The tests concern normalized flow rules, not all OBV strategies or divergence detection.

Original TrainBard completion for an accepted on-balance-volume study batch.

This later ETHUSDT two- and four-hour batch completed 32,472 configurations without error flags. The separate earlier-window failed setting is accounted for above. The best displayed row is completion evidence, not a recommended setting.

See VWAP for another use of volume weights, and RSI for a different way to summarize the direction and size of recent price changes.