RollingBeta#
Description#
RollingBeta computes the rolling regression slope of x on y over a sliding window of fixed size. The first argument is the dependent variable (target), the second is the independent variable (regressor).
This is the CAPM-style β: RollingBeta(asset_returns, market_returns, w) returns the asset's beta with respect to the market.
Equation:
with the sums taken over the most recent window_size samples.
Parameters:
window_size(int, ≥ 2): size of the rolling window.start_policy(str, default"strict"): controls warmup behavior. SeeRollingMeanfor the full definition.
Input shape: two parallel streams, identical to RollingCorr.
Return value: the slope coefficient. Returns NaN during warmup or when y has zero variance within the window (regression is undefined).
Convention note: pandas does not ship a
rolling().beta()method directly. The pandas-equivalent expression ispd.Series(x).rolling(w).cov(pd.Series(y)) / pd.Series(y).rolling(w).var(). Some libraries call this slope "alpha" or use the inverse argument order; double-check the convention when comparing.
NaN handling#
Policy: ignore. A NaN in any input at index t causes the function to skip that step: output at t is NaN and internal state is unchanged. Subsequent finite samples are processed as if step t had not occurred.
Examples#
Usage example#
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from screamer import RollingBeta
np.random.seed(0)
N = 300
market_returns = np.random.normal(size=N)
# An asset whose beta to the market drifts from 0.5 to 1.5 over time.
true_beta = np.linspace(0.5, 1.5, N)
asset_returns = true_beta * market_returns + 0.3 * np.random.normal(size=N)
beta_60 = RollingBeta(window_size=60)(asset_returns, market_returns)
fig = make_subplots(rows=1, cols=1)
fig.add_trace(go.Scatter(y=true_beta, mode="lines", name="true beta",
line=dict(color="grey", dash="dash")))
fig.add_trace(go.Scatter(y=beta_60, mode="lines", name="RollingBeta(60)"))
fig.update_layout(
title="Rolling beta of asset returns on market returns",
xaxis_title="time",
yaxis_title="beta",
margin=dict(l=20, r=20, t=60, b=20),
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),
)
fig.show()
Implementation Details#
Four detail::RollingSum buffers maintain Σx, Σy, Σyy, Σxy over the window. Each new sample updates all four sums in O(1), then β is computed in closed form.
Time:
O(1)per new element.Space:
O(window_size)(four circular buffers).Reference: parity with
pd.Series(x).rolling(w).cov(pd.Series(y)) / pd.Series(y).rolling(w).var()verified intests/test_rolling_two_input.py.