Bull Power vs Bear Power
period = 5 Overview
Bull Power vs Bear Power reduces each candle to a single signed pressure value. The raw formula compares the session range against the open, then scales that imbalance by the closing price. Positive readings suggest the bar structure favored bullish expansion from the open, while negative readings suggest bearish control.
The VectorTA implementation then smooths that raw pressure with an EMA-style running mean. That makes the final series less noisy than the per-bar calculation while still reacting quickly to changes in candle structure. The result works well as a short-horizon momentum-pressure gauge rather than a classical oscillator with fixed overbought and oversold zones.
Defaults: Bull Power vs Bear Power uses `period = 5`.
Implementation Examples
Compute the smoothed pressure line from OHLC slices or from a candle container.
use vector_ta::indicators::bull_power_vs_bear_power::{
bull_power_vs_bear_power,
BullPowerVsBearPowerInput,
BullPowerVsBearPowerParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let open = vec![100.0, 101.2, 102.0, 101.6, 103.1];
let high = vec![101.0, 102.4, 102.8, 103.0, 104.3];
let low = vec![99.4, 100.6, 101.2, 100.9, 102.5];
let close = vec![100.8, 101.9, 101.5, 102.7, 103.8];
let output = bull_power_vs_bear_power(&BullPowerVsBearPowerInput::from_slices(
&open,
&high,
&low,
&close,
BullPowerVsBearPowerParams { period: Some(5) },
))?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = bull_power_vs_bear_power(
&BullPowerVsBearPowerInput::with_default_candles(&candles)
)?;
println!("Latest pressure: {:?}", output.values.last());
println!("Candle series length: {}", candle_output.values.len()); API Reference
Input Methods ▼
// From candles
BullPowerVsBearPowerInput::from_candles(&Candles, BullPowerVsBearPowerParams)
-> BullPowerVsBearPowerInput
// From OHLC slices
BullPowerVsBearPowerInput::from_slices(
&[f64], &[f64], &[f64], &[f64], BullPowerVsBearPowerParams
) -> BullPowerVsBearPowerInput
// From candles with default parameters
BullPowerVsBearPowerInput::with_default_candles(&Candles)
-> BullPowerVsBearPowerInput Parameters Structure ▼
pub struct BullPowerVsBearPowerParams {
pub period: Option<usize>, // default 5
} Output Structure ▼
pub struct BullPowerVsBearPowerOutput {
pub values: Vec<f64>,
} Validation, Warmup & NaNs ▼
- All four OHLC slices must be present, non-empty, and the same length.
- A bar is treated as valid only when open, high, low, and close are finite and close is non-zero.
periodmust be greater than zero and no larger than the data length.- The indicator needs at least
periodvalid OHLC bars before the smoothed value becomes finite. - Warmup lasts until
first_valid_index + period - 1. - Streaming resets when it encounters an invalid bar.
- Batch mode rejects unsupported kernels and invalid integer ranges.
Builder, Streaming & Batch APIs ▼
// Builder
BullPowerVsBearPowerBuilder::new()
.period(usize)
.kernel(Kernel)
.apply_slices(&[f64], &[f64], &[f64], &[f64])
BullPowerVsBearPowerBuilder::new()
.apply(&Candles)
BullPowerVsBearPowerBuilder::new()
.into_stream()
// Stream
BullPowerVsBearPowerStream::try_new(BullPowerVsBearPowerParams)
BullPowerVsBearPowerStream::update(open, high, low, close) -> Option<f64>
BullPowerVsBearPowerStream::get_warmup_period() -> usize
// Batch
BullPowerVsBearPowerBatchBuilder::new()
.period_range(start, end, step)
.period_static(usize)
.kernel(Kernel)
.apply_slices(&[f64], &[f64], &[f64], &[f64]) Error Handling ▼
pub enum BullPowerVsBearPowerError {
EmptyInputData,
AllValuesNaN,
InvalidPeriod { period: usize, data_len: usize },
NotEnoughValidData { needed: usize, valid: usize },
InconsistentSliceLengths {
open_len: usize,
high_len: usize,
low_len: usize,
close_len: usize,
},
OutputLengthMismatch { expected: usize, got: usize },
InvalidRange { start: String, end: String, step: String },
InvalidKernelForBatch(Kernel),
} Python Bindings
Python exposes an array-returning single-run function, a streaming class, and a batch function. The single-run binding returns one NumPy array of smoothed pressure values. Batch returns a values matrix plus the tested periods and the final rows and cols shape.
import numpy as np
from vector_ta import (
bull_power_vs_bear_power,
bull_power_vs_bear_power_batch,
BullPowerVsBearPowerStream,
)
open_ = np.asarray(open_values, dtype=np.float64)
high = np.asarray(high_values, dtype=np.float64)
low = np.asarray(low_values, dtype=np.float64)
close = np.asarray(close_values, dtype=np.float64)
values = bull_power_vs_bear_power(
open_,
high,
low,
close,
period=5,
kernel="auto",
)
batch = bull_power_vs_bear_power_batch(
open_,
high,
low,
close,
period_range=(5, 9, 2),
kernel="auto",
)
stream = BullPowerVsBearPowerStream(5)
print(stream.update(open_[-1], high[-1], low[-1], close[-1])) JavaScript/WASM Bindings
The WASM layer exposes one array-returning function for a normal run, a batch wrapper that returns values plus period metadata, and lower-level allocation and in-place APIs for callers that want to manage their own buffers.
import init, {
bull_power_vs_bear_power_js,
bull_power_vs_bear_power_batch_js,
} from "/pkg/vector_ta.js";
await init();
const open = new Float64Array(openValues);
const high = new Float64Array(highValues);
const low = new Float64Array(lowValues);
const close = new Float64Array(closeValues);
const values = bull_power_vs_bear_power_js(open, high, low, close, 5);
console.log(values);
const batch = bull_power_vs_bear_power_batch_js(open, high, low, close, {
period_range: [5, 9, 2],
});
console.log(batch.values, batch.periods, batch.rows, batch.cols); CUDA Bindings (Rust)
Additional details for the CUDA bindings can be found inside the VectorTA repository.
Performance Analysis
Across sizes, Rust CPU runs about 1.14× faster than Tulip C in this benchmark.
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU)