Balance of Power (BOP)

Haiyue
9min

I. What is BOP

The Balance of Power (BOP) is an oscillator that measures the relative strength of buyers versus sellers within each trading period. It quantifies the result of the bull-bear power struggle by calculating the ratio of the difference between the close and open prices to the total bar range.

Historical Background

BOP was invented by Igor Livshin and published in 2001 in Technical Analysis of Stocks and Commodities magazine. Livshin proposed that traditional indicators (such as RSI, MACD) primarily focus on the direction and magnitude of price changes but overlook a key question: within each trading period, are buyers or sellers in control? BOP was designed specifically to answer this question.

Indicator Classification

  • Type: Oscillator, displayed in a separate panel
  • Category: Momentum / Volume-Price
  • Default Parameters: Smoothing period =14= 14 (SMA)
  • Value Range: -1 to +1
BOP Intuition

If a bar closes well above its open (large bullish candle) and the body occupies most of the range, BOP approaches +1, indicating buyers are in full control. Conversely, a large bearish candle’s BOP approaches -1, indicating sellers are in full control.


II. Mathematical Principles and Calculation

Core Formulas

Raw BOP:

BOPt=CtOtHtLtBOP_t = \frac{C_t - O_t}{H_t - L_t}

Where:

  • CtC_t = close price
  • OtO_t = open price
  • HtH_t = high price
  • LtL_t = low price

Smoothed BOP:

BOPsmooth=SMA(BOP,n)BOP_{smooth} = SMA(BOP, n)

Default n=14n = 14.

Step-by-Step Calculation Logic

  1. Calculate numerator: Close - Open = direction and size of the candle body
  2. Calculate denominator: High - Low = total bar range
  3. Divide: Get the ratio of body to range (with sign)
  4. Smooth: Apply SMA(14) to raw BOP to reduce daily noise

Value Interpretation

BOP ValueCandle ShapeMeaning
+1Perfect bullish candle (open = low, close = high)Buyers in full control
+0.5Medium bullish candleBuyers dominant
0Doji or equal upper/lower shadowsBalanced power
-0.5Medium bearish candleSellers dominant
-1Perfect bearish candle (open = high, close = low)Sellers in full control
Handling Zero Denominator

When Ht=LtH_t = L_t (limit-up/down with no range, or zero-volatility periods), the BOP formula denominator is zero. In practice, BOP is set to 0 or forward-filled with the previous value.


III. Python Implementation

import numpy as np
import pandas as pd


def bop(open_price: pd.Series,
        high: pd.Series,
        low: pd.Series,
        close: pd.Series,
        period: int = 14) -> pd.DataFrame:
    """
    Calculate the Balance of Power (BOP)

    Parameters
    ----------
    open_price : pd.Series
        Open price series
    high : pd.Series
        High price series
    low : pd.Series
        Low price series
    close : pd.Series
        Close price series
    period : int
        SMA smoothing period, default 14

    Returns
    -------
    pd.DataFrame
        DataFrame with raw BOP and smoothed BOP
    """
    range_hl = high - low

    # Handle zero denominator
    raw_bop = np.where(
        range_hl == 0,
        0,
        (close - open_price) / range_hl
    )
    raw_bop = pd.Series(raw_bop, index=close.index)

    smooth_bop = raw_bop.rolling(window=period, min_periods=period).mean()

    return pd.DataFrame({
        "BOP_raw": raw_bop,
        "BOP": smooth_bop
    }, index=close.index)


# ========== Usage Example ==========
if __name__ == "__main__":
    np.random.seed(42)
    dates = pd.date_range("2024-01-01", periods=120, freq="D")
    base = 100 + np.cumsum(np.random.randn(120) * 1.0)

    df = pd.DataFrame({
        "date": dates,
        "open":  base + np.random.randn(120) * 0.5,
        "high":  base + np.abs(np.random.randn(120) * 1.0),
        "low":   base - np.abs(np.random.randn(120) * 1.0),
        "close": base + np.random.randn(120) * 0.4,
        "volume": np.random.randint(1000, 10000, size=120),
    })
    df.set_index("date", inplace=True)

    # Calculate BOP
    bop_df = bop(df["open"], df["high"], df["low"], df["close"])
    df = pd.concat([df, bop_df], axis=1)

    print("=== Balance of Power Results (last 15 rows) ===")
    print(df[["close", "BOP_raw", "BOP"]].tail(15).to_string())

    # Zero line crossover signals
    df["signal"] = np.where(
        (df["BOP"] > 0) & (df["BOP"].shift(1) <= 0), 1,
        np.where(
            (df["BOP"] < 0) & (df["BOP"].shift(1) >= 0), -1, 0
        )
    )

    signals = df[df["signal"] != 0]
    print("\n=== BOP Zero Line Crossover Signals ===")
    print(signals[["close", "BOP", "signal"]].to_string())

    # BOP extreme values
    print(f"\n=== BOP Descriptive Statistics ===")
    print(df["BOP"].describe().to_string())

IV. Problems the Indicator Solves

1. Bull/Bear Power Assessment

BOP directly quantifies the degree of buyer and seller control within each trading period:

  • BOP > 0: Buyers dominant, close above open
  • BOP < 0: Sellers dominant, close below open
  • BOP absolute value near 1: One side in complete control

2. Zero Line Crossover Signals

SignalConditionMeaning
BuySmoothed BOP crosses above zeroBuying power begins to dominate
SellSmoothed BOP crosses below zeroSelling power begins to dominate

3. Trend Strength Confirmation

During an uptrend:

  • BOP consistently positive and increasing — trend is healthy, strong buying power
  • BOP begins declining from positive values — buying power weakening, trend may decelerate

4. Divergence Detection

  • Bearish Divergence: Price new high + BOP peak declining — although price is rising, buyer dominance is weakening
  • Bullish Divergence: Price new low + BOP trough rising — although price is falling, seller control is weakening

5. Quantification of Candlestick Patterns

BOP is essentially a quantitative measure of the relationship between candle body and shadows, serving as a numerical alternative to candlestick pattern analysis.

Caution

BOP is highly dependent on the quality of the open price. In some markets (such as the 24-hour forex market), the open price may differ very little from the previous period’s close, causing BOP signals to become distorted. BOP performs better in markets with a clear opening auction mechanism (such as stock markets).


V. Advantages, Disadvantages, and Use Cases

Advantages

AdvantageDescription
Intuitive logicDirectly quantifies bull/bear power balance, clear meaning
Bounded range-1 to +1, easy to standardize and compare
Uses all OHLC dataCombines four price dimensions: open, high, low, close
Complementary perspectiveProvides open price information that most indicators ignore

Disadvantages

DisadvantageDescription
Dependent on open priceUnreliable when open price quality is poor
Intraday noiseRaw BOP is very volatile, must be smoothed before use
Simple signalsPrimarily relies on zero line crossovers, single signal dimension
Less researchedCompared to RSI, MACD, and other indicators, fewer academic and practical studies exist

Use Cases

  • Stock markets: Where opening auction mechanisms make the open price meaningful
  • Daily timeframe: Daily open and close prices are most representative
  • Auxiliary confirmation: As a supplementary validation tool for other technical indicator signals
ComparisonBOPRSIOBV
Data InputO/H/L/CCC + Volume
FocusBull/Bear powerRate of changeVolume-price relationship
Value Range-1 to +10-100Unbounded
SmoothingSMAWilderCumulative
Practical Tips
  1. Must smooth: Raw BOP is too noisy; use at least SMA(14) smoothing.
  2. Combine with volume: BOP only measures price-level bull/bear power; combining with OBV or volume provides a more complete picture.
  3. Watch extreme values: Smoothed BOP exceeding +/-0.5 indicates unusually strong one-sided power, with potential reversal.
  4. Multi-indicator confirmation: BOP works best as a “second opinion” — when RSI or MACD gives a signal, check whether BOP agrees in direction.