Estimates jump parameters and diffusion volatility from historical returns.
This function separates historical log returns into a "diffusion" component
(normal daily movements) and a "jump" component (extreme movements) based
on a standard deviation threshold. It then calculates the annualized
parameters for a jump-diffusion model like Merton's.
Parameters:
Name |
Type |
Description |
Default |
log_returns
|
Series
|
A pandas Series of daily log returns.
|
required
|
threshold_stds
|
float
|
The number of standard deviations to use as a threshold for identifying
jumps, by default 3.0.
|
3.0
|
Returns:
Type |
Description |
dict
|
A dictionary containing the estimated parameters: 'sigma', 'lambda',
'mu_j', and 'sigma_j'.
|
Source code in src/quantfin/calibration/fit_jump_parameters.py
| def fit_jump_params_from_history(
log_returns: pd.Series,
threshold_stds: float = 3.0,
) -> dict:
"""
Estimates jump parameters and diffusion volatility from historical returns.
This function separates historical log returns into a "diffusion" component
(normal daily movements) and a "jump" component (extreme movements) based
on a standard deviation threshold. It then calculates the annualized
parameters for a jump-diffusion model like Merton's.
Parameters
----------
log_returns : pd.Series
A pandas Series of daily log returns.
threshold_stds : float, optional
The number of standard deviations to use as a threshold for identifying
jumps, by default 3.0.
Returns
-------
dict
A dictionary containing the estimated parameters: 'sigma', 'lambda',
'mu_j', and 'sigma_j'.
"""
print("Fitting jump parameters from historical returns...")
std_dev = log_returns.std()
jump_threshold = threshold_stds * std_dev
diffusion_returns = log_returns[abs(log_returns) < jump_threshold]
jump_returns = log_returns[abs(log_returns) >= jump_threshold]
# Annualize daily std dev by multiplying by sqrt(252 trading days)
sigma_est = diffusion_returns.std() * np.sqrt(252)
if len(jump_returns) > 2:
lambda_est = len(jump_returns) / len(log_returns) * 252
mu_j_est = jump_returns.mean()
sigma_j_est = jump_returns.std()
else:
lambda_est, mu_j_est, sigma_j_est = 0.1, 0.0, 0.0
print(" -> Warning: Not enough jumps detected. Using default jump parameters.")
# Use the key 'sigma' to match the parameter name in the Merton/Kou models.
fitted_params = {
"sigma": sigma_est,
"lambda": lambda_est,
"mu_j": mu_j_est,
"sigma_j": sigma_j_est,
}
formatted = ", ".join(f"{k}: {v:.4f}" for k, v in fitted_params.items())
print(f" -> Estimated Historical Params: {{{formatted}}}")
return fitted_params
|