Balance of Power (BOP)
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 (SMA)
- Value Range: -1 to +1
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:
Where:
- = close price
- = open price
- = high price
- = low price
Smoothed BOP:
Default .
Step-by-Step Calculation Logic
- Calculate numerator: Close - Open = direction and size of the candle body
- Calculate denominator: High - Low = total bar range
- Divide: Get the ratio of body to range (with sign)
- Smooth: Apply SMA(14) to raw BOP to reduce daily noise
Value Interpretation
| BOP Value | Candle Shape | Meaning |
|---|---|---|
| +1 | Perfect bullish candle (open = low, close = high) | Buyers in full control |
| +0.5 | Medium bullish candle | Buyers dominant |
| 0 | Doji or equal upper/lower shadows | Balanced power |
| -0.5 | Medium bearish candle | Sellers dominant |
| -1 | Perfect bearish candle (open = high, close = low) | Sellers in full control |
When (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
| Signal | Condition | Meaning |
|---|---|---|
| Buy | Smoothed BOP crosses above zero | Buying power begins to dominate |
| Sell | Smoothed BOP crosses below zero | Selling 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.
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
| Advantage | Description |
|---|---|
| Intuitive logic | Directly quantifies bull/bear power balance, clear meaning |
| Bounded range | -1 to +1, easy to standardize and compare |
| Uses all OHLC data | Combines four price dimensions: open, high, low, close |
| Complementary perspective | Provides open price information that most indicators ignore |
Disadvantages
| Disadvantage | Description |
|---|---|
| Dependent on open price | Unreliable when open price quality is poor |
| Intraday noise | Raw BOP is very volatile, must be smoothed before use |
| Simple signals | Primarily relies on zero line crossovers, single signal dimension |
| Less researched | Compared 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
Comparison with Related Indicators
| Comparison | BOP | RSI | OBV |
|---|---|---|---|
| Data Input | O/H/L/C | C | C + Volume |
| Focus | Bull/Bear power | Rate of change | Volume-price relationship |
| Value Range | -1 to +1 | 0-100 | Unbounded |
| Smoothing | SMA | Wilder | Cumulative |
- Must smooth: Raw BOP is too noisy; use at least SMA(14) smoothing.
- Combine with volume: BOP only measures price-level bull/bear power; combining with OBV or volume provides a more complete picture.
- Watch extreme values: Smoothed BOP exceeding +/-0.5 indicates unusually strong one-sided power, with potential reversal.
- Multi-indicator confirmation: BOP works best as a “second opinion” — when RSI or MACD gives a signal, check whether BOP agrees in direction.