TradingView indicator guides

Ease of Movement indicator: formula and limits

Ease of Movement (EOM) multiplies the change in a bar's high-low midpoint by its range, then divides by scaled volume. It describes price movement relative to reported volume. It does not measure cash flowing into an asset or identify the cause of a price move.

Raw EOM = S × (midpoint − previous midpoint) × (high − low) / volume

S > 0 controls scale. The worked example and script use S = 10,000. An optional SMA averages the raw values.

Inspect the Pine Script example

The Ease of Movement formula and its scale

TradingView credits Richard Arms with EOM. Its official calculation example uses midpoint change divided by a box ratio: (volume / 100,000,000) / (high − low), followed by a 14-period SMA. With positive range and volume, expanding that expression gives the formula above.

The divisor divides volume inside the box ratio, so it multiplies the final EOM value. This page keeps the existing script's 10,000 scale. The official article's 100,000,000 example produces values 10,000 times larger for identical inputs. Check the actual divisor in the indicator you are comparing; a difference in magnitude alone does not prove a calculation error.

EOM has no fixed upper or lower bound. Treating S as a numeric scale, the result has price-squared per volume-unit dimensions. Changing price denomination by a factor of 100, with volume unchanged, multiplies EOM by 10,000. A threshold such as +50 therefore has no universal meaning across instruments.

For valid positive range and volume, the raw value's sign follows midpoint movement. A smoothed value can remain above zero after the latest midpoint falls, because earlier positive contributions are still in its window. Read raw and averaged values separately.

Worked example: the same move with less volume

Hypothetical consecutive bars, with prices in dollars, volume in shares, and S = 10,000. These are demonstration inputs, not market observations or backtest results. Bar A supplies the first midpoint.

Hypothetical Ease of Movement calculation
BarHigh / lowMidpoint / changeRangeVolumeRaw EOM
A102 / 98100 / unavailable420,000na
B105 / 101103 / +3420,000+6
C108 / 104106 / +342,000+60
D106 / 102104 / −2420,000−4
E105 / 105105 / +1010,0000 (convention)
F108 / 104106 / +140na

Bar B: 10,000 × 3 × 4 / 20,000 = 6. Bar C repeats the midpoint change and range, but one tenth of the volume produces ten times the EOM. The larger value is explained by its denominator; it is not evidence of ten times the buying pressure.

A three-bar SMA at D is (6 + 60 − 4) / 3 = 20.67, despite D's negative raw value. At E it becomes (60 − 4 + 0) / 3 = 18.67. At F the script suppresses the average because the window contains an invalid volume input. Set length to 3 to reproduce these averages; the script starts at 14.

Volume units and boundary conditions

Keep the data source fixed

Compare the same exchange symbol, session, timeframe, and price-adjustment settings. Pine uses the chart's reported OHLCV, including developing values on an open bar. Record whether volume is shares, contracts, base currency, quote currency, or a tick-based measure before comparing EOM values. See TradingView's chart information documentation.

The syminfo.volumetype reference lists base, quote, tick, and n/a, but only some providers supply this metadata. An n/a type can mean unspecified volume units; it does not by itself mean the volume series is absent. Inspect the actual volume values too.

Choose invalid-input behavior explicitly

  • Missing or nonpositive volume produces na in this example. Replacing it with 1 would manufacture an extreme reading; replacing it with 0 as an output would disguise missing data as a neutral contribution.
  • A zero range with positive volume contributes 0 by convention in the expanded formula. The original box ratio divides by range, so it is undefined at that point. The convention must be documented when matching another implementation.
  • The first bar has no previous midpoint and cannot yield raw EOM. The SMA requires length consecutive valid contributions; a missing-volume bar restarts that requirement.
  • Very small positive volume remains valid and can amplify the result. The script does not invent a minimum-volume threshold or clip large values. Inspect volume alongside every spike.

Pine Script v6: raw EOM, optional smoothing, and alerts

The gray plot shows raw contributions; the blue plot shows the optional SMA. Missing values remain gaps. The selected series drives zero-crossing alerts, which require barstate.isconfirmed. Current-bar plots still update before the close.

Pine Script v6

Copy the complete example into the Pine Editor.

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// (c) Pineify
//@version=6
indicator("Ease of Movement: checked inputs", overlay=false)

scale = input.float(10000.0, "Volume divisor (scale)", minval=0.000001)
useSmoothing = input.bool(true, "Use SMA")
length = input.int(14, "SMA length", minval=1)

midpointChange = ta.change(hl2)
barRange = high - low
hasInputs = not na(midpointChange) and not na(barRange) and not na(volume) and volume > 0 and barRange >= 0
// With positive volume, a zero range contributes 0 by explicit convention.
rawEom = hasInputs ? scale * midpointChange * barRange / volume : na

// Require a full window of consecutive valid bars, without bridging gaps.
validFraction = ta.sma(hasInputs ? 1.0 : 0.0, length)
windowAverage = ta.sma(nz(rawEom, 0.0), length)
smoothedEom = validFraction == 1.0 ? windowAverage : na
selectedEom = useSmoothing ? smoothedEom : rawEom

plot(rawEom, "Raw EOM", color=color.gray, style=plot.style_linebr)
plot(useSmoothing ? smoothedEom : na, "EOM SMA", color=color.blue, linewidth=2, style=plot.style_linebr)
hline(0, "Zero", color=color.gray)

crossUp = ta.crossover(selectedEom, 0)
crossDown = ta.crossunder(selectedEom, 0)
alertcondition(barstate.isconfirmed and crossUp, "EOM crosses above zero", "Selected EOM crossed above zero on a closed bar.")
alertcondition(barstate.isconfirmed and crossDown, "EOM crosses below zero", "Selected EOM crossed below zero on a closed bar.")
Example script settings
InputExample defaultEffect
Volume divisor10,000Positive numeric scale; changing it does not change zero-crossing times.
Use SMAOnShows the average and uses it for alerts. Off selects raw EOM.
SMA length14At least 1. A full valid window is required; zeros from zero-range bars count.

The temporary zero fill inside windowAverage is only an arithmetic aid. validFraction prevents that average from appearing when even one input in the window is invalid. This gap policy may differ from an implementation that averages the latest non-missing values across gaps.

How to check EOM on a chart

  1. Copy the example into the Pine Editor, save it, and select Add to chart. Start with a standard candle chart and record the symbol, interval, session, and divisor.
  2. Turn off Use SMA and inspect a closed bar in the Data Window. Calculate the current and previous midpoint, then check the range and volume against the raw plot.
  3. Change only the divisor by a factor of ten. The plot values should change by that factor while their signs and zero crossings stay fixed.
  4. Enable the SMA and compare an entire valid window. A positive average can include a negative latest bar. Check missing-volume gaps before attributing any disagreement to rounding.
  5. Create an alert from a named EOM crossing condition. A crossing describes the chosen series at the close; it supplies no order size, stop, exit, commission, or slippage rule.

Unlike the cumulative Price Volume Trend series, EOM divides by volume and measures midpoint movement. Balance of Power compares the candle body with its range and does not require volume. These formulas answer different questions; their numeric values are not interchangeable.

This material explains indicator calculations. It is not investment advice or evidence that a zero-crossing strategy will be profitable.

Specify your EOM rules in Pineify

Use the Pine Script AI Coding Agent to adapt the example. Describe the scale, smoothing window, missing-volume policy, and alert confirmation time. Ask for a syntax check, then compare the generated values bar by bar before adding strategy entries, exits, sizing, and costs.

"Use an EOM scale of 10,000 and optional 14-bar SMA. Return na for missing or nonpositive volume; use zero for a zero-range bar with positive volume. Require a full valid SMA window and confirm zero-crossing alerts at bar close. Plot raw and smoothed values separately so I can check them."
Open Pine Script AI Coding Agent

Ease of Movement questions

Raw EOM = S × change in the high-low midpoint × (high − low) / volume. S is a positive volume scaling factor. A moving average can then smooth the raw series. The box-ratio version divides the midpoint change by (volume / S) / (high − low); the two forms agree when range and volume are positive.

With positive volume, scale, and range, positive raw EOM means the current high-low midpoint exceeds the previous midpoint. Positive smoothed EOM means the average of the selected contributions is positive; the latest raw value can still be negative. Neither reading identifies the buyers or proves that money entered the market.

Multiplying a fixed positive divisor by ten multiplies every valid raw and SMA value by ten. Zero-crossing times stay the same, while numeric thresholds must change by the same factor. Changing the smoothing length is different: it changes the sequence being averaged and can change zero-crossing times.

This script returns na for missing or nonpositive volume, and for a missing previous midpoint. With positive volume and a zero range, it assigns raw EOM a value of zero. That is an explicit extension of the expanded formula: the box-ratio formula itself divides by the range and is undefined there. A missing input also suppresses the SMA until its full window is valid.

Only after checking price units, volume units, provider, session, timeframe, and scale. Volume can represent different quantities, and some feeds have no usable volume. The syminfo.volumetype field can help when the provider supplies it, but n/a can mean an unspecified type. EOM is not a normalized percentage, so a shared absolute threshold is not automatically comparable.

There is no best setting established by this page. The example preserves a scale of 10,000 and starts with a 14-bar SMA. Disable smoothing to inspect each contribution. Choose any change in length as a separate hypothesis to test with matching data and costs; changing the scale only changes the displayed units.

Copy the complete script into the Pine Editor, save it, and select Add to chart. Inspect Raw EOM and EOM SMA in the Data Window on closed bars. Select one of the named EOM conditions when creating an alert. The conditions require bar confirmation, while the plotted current-bar values can still update before the close.

A large value can come from a wide range, a large midpoint change, or a small volume denominator. Hold prices fixed and divide volume by ten: the EOM magnitude becomes ten times larger. Inspect the component values before interpreting a spike. An indicator crossing is not a complete trading strategy with entries, exits, sizing, and costs.

Sources and further checks

Official references checked October 17, 2026. The worked data and gap-handling policy are this page's demonstration choices.

Browse TradingView indicator guides