Basic Usage
This guide covers the fundamental usage patterns for GRU Dynamic Beta.
The DynamicBeta Class
The DynamicBeta class is the main interface for beta estimation.
Creating a Model
from grubeta import DynamicBeta
# Default configuration
model = DynamicBeta()
# Custom parameters
model = DynamicBeta(
lookback=60,
lambda_beta=0.05,
lambda_alpha=0.3
)
Using a Configuration Object
For more control, use DynamicBetaConfig:
from grubeta import DynamicBeta, DynamicBetaConfig
config = DynamicBetaConfig(
lookback=90,
initial_train_size=500,
wf_step_size=126,
learning_rate=1e-4,
gru_units=128,
dropout_rate=0.2,
lambda_beta=0.05,
lambda_alpha=0.5,
lambda_alpha_smooth=0.1,
epochs_init=40,
epochs_retrain=4,
verbose=1
)
model = DynamicBeta(config=config)
Input Data Formats
GRU Dynamic Beta accepts various input formats:
NumPy Arrays
import numpy as np
stock_returns = np.array([0.01, -0.02, 0.015, ...])
market_returns = np.array([0.008, -0.015, 0.012, ...])
results = model.fit_predict(stock_returns, market_returns)
Pandas Series
import pandas as pd
stock_returns = df['stock_close'].pct_change()
market_returns = df['market_close'].pct_change()
results = model.fit_predict(stock_returns, market_returns)
With Date Index
results = model.fit_predict(
stock_returns,
market_returns,
dates=df['date'].values
)
# Results will include 'date' column
print(results[['date', 'beta']].tail())
The fit_predict Method
The recommended method for most use cases:
results = model.fit_predict(
stock_returns, # Required: stock return series
market_returns, # Required: market return series
market_features=None, # Optional: additional market features
stock_features=None, # Optional: additional stock features
dates=None # Optional: date index
)
This method performs walk-forward validation to prevent lookahead bias.
Separate Fit and Predict
For more control, use separate fit and predict steps:
# Fit on training data
model.fit(
stock_returns[:800],
market_returns[:800]
)
# Predict on new data
predictions = model.predict(
stock_returns[800:],
market_returns[800:]
)
Understanding Results
The results DataFrame contains:
results.columns
# ['date', 'beta', 'alpha', 'stock_return', 'market_return']
NaN Values
The first lookback + initial_train_size rows have NaN beta values:
# These are NaN (burn-in period)
results.head(200)
# Valid estimates start here
results.dropna().head()
Working with Results
# Get valid beta series
valid_betas = results['beta'].dropna()
# Calculate summary statistics
print(f"Mean beta: {valid_betas.mean():.4f}")
print(f"Beta volatility: {valid_betas.std():.4f}")
print(f"Beta range: [{valid_betas.min():.4f}, {valid_betas.max():.4f}]")
# Check for regime changes
rolling_mean = valid_betas.rolling(60).mean()
rolling_std = valid_betas.rolling(60).std()
Visualization
Built-in Plotting
model.plot_beta(
results,
figsize=(12, 6),
title='AAPL Dynamic Beta',
save_path='beta_plot.png'
)
Custom Visualization
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 1, figsize=(12, 8), sharex=True)
# Beta trajectory
axes[0].plot(results['date'], results['beta'], 'b-', label='GRU Beta')
axes[0].axhline(1.0, color='red', linestyle='--', alpha=0.5)
axes[0].fill_between(
results['date'],
results['beta'] - 0.1,
results['beta'] + 0.1,
alpha=0.2
)
axes[0].set_ylabel('Beta')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# Alpha trajectory
axes[1].plot(results['date'], results['alpha'], 'purple', label='Alpha')
axes[1].axhline(0, color='red', linestyle='--', alpha=0.5)
axes[1].set_ylabel('Alpha')
axes[1].set_xlabel('Date')
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Model Persistence
Saving Models
# After fitting
model.fit_predict(stock_returns, market_returns)
# Save to directory
model.save('./saved_models/aapl_beta')
This saves:
model.h5- Keras model weightsartifacts.pkl- Scalers and configuration
Loading Models
# Load saved model
model = DynamicBeta.load('./saved_models/aapl_beta')
# Use for predictions
new_results = model.predict(new_stock_returns, new_market_returns)
Error Handling
Common errors and solutions:
# Insufficient data
try:
model = DynamicBeta(lookback=90, initial_train_size=500)
model.fit_predict(short_data, short_market) # < 590 samples
except ValueError as e:
print(f"Error: {e}")
# Solution: Use shorter lookback or more data
# Model not fitted
try:
model = DynamicBeta()
model.predict(data, market) # Before fitting
except ValueError as e:
print(f"Error: {e}")
# Solution: Call fit_predict() or fit() first