3.4 KiB
BOP: Balance of Power
"The market is a tug of war between buyers and sellers. BOP tells you who's pulling harder."
The Balance of Power (BOP) indicator measures the strength of buying and selling pressure by comparing the closing price to the opening price, relative to the high-low range. It oscillates between -1 and 1, providing a clear picture of market dominance.
Historical Context
Developed by Igor Livshin and published in the August 2001 issue of Stocks & Commodities magazine, BOP was designed to expose the underlying action of price movement. Unlike trend-following indicators that lag, BOP is a momentum oscillator that can identify hidden accumulation or distribution patterns.
Architecture & Physics
BOP is a stateless, zero-lag indicator in its raw form. It evaluates each bar independently, calculating the ratio of the body (Close - Open) to the range (High - Low).
- Inertia: None (raw).
- Momentum: Instantaneous.
- Range: Bounded [-1, 1].
The Zero-Range Challenge
A key architectural challenge is handling bars where High == Low. In these cases, the range is zero, leading to a potential division by zero. QuanTAlib handles this by returning 0, indicating a neutral balance of power (no movement).
Mathematical Foundation
The formula is deceptively simple:
BOP = \frac{Close - Open}{High - Low}
Where:
- Close > Open: Positive BOP (Buyers dominate)
- Close < Open: Negative BOP (Sellers dominate)
- Close = Open: Zero BOP (Balance)
- High = Low: Zero BOP (No movement)
Performance Profile
BOP is extremely lightweight, requiring minimal computation.
Zero-Allocation Design
The implementation uses stackalloc and Span<T> where applicable, ensuring no heap allocations during the Update cycle. The Calculate method is fully vectorized using SIMD instructions (AVX2) when available, processing multiple bars in parallel.
| Metric | Score | Notes |
|---|---|---|
| Throughput | 1ns | O(1) per bar, SIMD-optimized. |
| Allocations | 0 | Zero allocations in the hot path. |
| Complexity | O(1) | Constant time per update. |
| Accuracy | 10/10 | Exact mathematical calculation. |
| Timeliness | 10/10 | Zero lag. |
| Overshoot | 0/10 | Bounded -1 to 1. |
| Smoothness | 0/10 | Raw signal, very noisy. |
Validation
BOP is validated against major technical analysis libraries to ensure correctness.
| Library | Status | Notes |
|---|---|---|
| TA-Lib | ✅ | Matches TA_BOP exactly. |
| Skender | ✅ | Matches GetBop. |
| Tulip | ✅ | Matches ti.bop. |
| Ooples | ✅ | Matches CalculateBalanceOfPower. |
Common Pitfalls
- Noise: The raw BOP is very volatile. It is often smoothed with a Moving Average (e.g., SMA-14) to identify trends. QuanTAlib provides the raw signal, allowing you to chain any smoothing algorithm you prefer.
- Doji Candles: When Open equals Close, BOP is 0. This is mathematically correct but can be interpreted as a lack of momentum.
Usage
using QuanTAlib;
// 1. Streaming (Real-time)
var bop = new Bop();
TValue result = bop.Update(new TBar(time, open, high, low, close, volume));
Console.WriteLine($"BOP: {result.Value}");
// 2. Batch (Historical)
var bars = new TBarSeries(...);
var bopSeries = Bop.Batch(bars);
// 3. Chaining (Smoothing)
var smoothedBop = new Sma(14);
var bop = new Bop();
// ... inside loop ...
var raw = bop.Update(bar);
var smooth = smoothedBop.Update(raw);