Skip to content
All library documents

Calibrating Stochastic Volatility with Efficient Method of Moments

Article Quant Q&A · Author: AJ van Niekerk

Summary

The document describes an effort to calibrate a simple stochastic volatility model with the Efficient Method of Moments (EMM), as a step toward calibrating Heston parameters from historical equity returns. The author reproduces a SAS example in Python, estimates a GARCH(1,1) auxiliary model, forms score moments and their covariance matrix, then simulates returns under candidate stochastic volatility parameters and minimizes a weighted moment objective.

The author reports that the GARCH fit and covariance calculation appear to match, while the simulated-moment calibration does not reproduce the SAS parameters. The code shows one proposed objective and parameter bounds, but the document gives no response diagnosing it, no calibration output, and no data files for independent assessment. Thus it is a troubleshooting question rather than validated implementation guidance; it highlights the stages that need to be checked, including the simulated variance recursion, moment construction, weighting matrix, and optimizer setup.

Key ideas

  • EMM uses an auxiliary model’s score moments to compare observed and simulated data.
  • The example estimates a GARCH auxiliary model before fitting stochastic volatility parameters.
  • The calibration objective weights simulated moments using an estimated covariance matrix.
  • The author’s code and description do not establish which implementation detail causes the mismatch with SAS.

Tags

Full text
# Efficient Method of Moments(EMM) for Stochastic volatility model


# Efficient Method of Moments(EMM) for Stochastic volatility model












We are attempting to calibrate the parameters of the Heston model via EMM on historical stock price returns. However, we are first trying a simple stochastic volatility model using EMM.

We have come across an example of the EMM procedure in SAS, which corresponds to one of the models in the paper by Anderson.

Link to Andersen paper: https://www.uh.edu/~bsorense/Emmpublished.pdf

Link to SAS example: https://support.sas.com/rnd/app/ets/examples/emmweb/index.htm#:~:text=The%20Efficient%20Method%20of%20Moments,Method%20of%20Moments%20(GMM.)

We are attempting to replicate this model in Python as we are unfamiliar with SAS. We are able to fit the GARCH(1,1) parameters correctly. We compute the covariance matrix from the first moments (scores) of the GARCH model correctly. However, when attempting to do the Simulated Method of Moments (SMM) component of the SAS implementation, we are unable to align on the calibrated parameters for a, b and s. We suspect that there is an issue in the minimization algorithm in our Python implementation. Any insight into where we are going wrong would be greatly appreciated.

The TEST.csv file contains the returns[y] simulated in SAS(seen as historical returns). The EMM_u_z.csv file contains the simulated normal random variables[u and z] for the simulated method of moments from SAS(unique seed values)

```

import pandas as pd

from scipy.optimize import minimize

from arch import arch_model

directory = r'C:\Users\Heston'
filename = '\\TEST.csv'
filename2 = '\\EMM_u_z.csv'

data = pd.read_csv(directory+filename)
u_z = pd.read_csv(directory + filename2)

nobs = 1000
nsim = 20000

y = data['y'].values

print(np.mean(y))
print(np.std(y))

# Estimate GARCH(1,1) model
model = arch_model(y, vol='Garch', lags = 1, p=1, q=1, )

result = model.fit()
print(result.summary)

gsigmasq = result.conditional_volatility**2

score_1 = np.zeros(nobs)
score_2 = np.zeros(nobs)
score_3 = np.zeros(nobs)

for i in range(nobs):
   if i == 0:
       score_1[i] = (-1 + y[i]**2/gsigmasq[i])/gsigmasq[i]
       score_2[i] = 0
       score_3[i] = 0
   else:
       score_1[i] = (-1 + y[i]**2/gsigmasq[i])/gsigmasq[i]
       score_2[i] = (-1 + y[i]**2/gsigmasq[i])*gsigmasq[i-1]/gsigmasq[i]
       score_3[i] = (-1+y[i]**2/gsigmasq[i])*y[i-1]**2/gsigmasq[i]
       
score = np.vstack([score_1,score_2,score_3]).T

MSE = np.mean(result.resid**2)

#Volatility of GARCH model
params_fitted = result.params
omega = params_fitted['omega']
alpha = params_fitted['alpha[1]']
beta = params_fitted['beta[1]']
mu = params_fitted['mu']

# Parameter initialization
a_init, b_init, s_init = -0.736, 0.9, 0.363
params_init = np.array([a_init, b_init, s_init])
u_z['_ah_0'] = omega
u_z['_gh_1'] = beta
u_z['_ah_1'] = alpha
u_z['_mse_'] = MSE

# Bounds for optimization
bounds = [(-np.inf, np.inf), (-1, 1), (0, np.inf)]  # (a, b, s)

# GMM objective function
def gmm_objective(params, data, scores):
   a, b, s = params
   lsigmasq = np.exp(a)  # Replace with appropriate lag calculation
   lnsigmasq = a + b * np.log(lsigmasq) + s * data['u']
   sigmasq = np.exp(lnsigmasq)
   ysim = np.sqrt(sigmasq) * data['z']
   
   gsigmasq = data['_ah_0'] + data['_gh_1'] * data['_mse_'].shift(1) + data['_ah_1'] * (ysim ** 2)

   m1 = (-1 + (ysim ** 2) / gsigmasq) / gsigmasq
   m2 = (-1 + (ysim ** 2) / gsigmasq) * gsigmasq.shift(1) / gsigmasq
   m3 = (-1 + (ysim ** 2) / gsigmasq) * (ysim ** 2).shift(1) / gsigmasq

   moments = np.column_stack((m1, m2, m3))
   
   # GMM moment conditions
   gmm_conditions = np.nanmean(moments, axis = 0) # Use sample moments
   
   # Compute the variance-covariance matrix
   vhat = np.cov(scores, rowvar=False)

   gmm_objective_value = gmm_conditions @ np.linalg.inv(vhat) @ gmm_conditions.T
   
   return gmm_objective_value  # GMM objective function

# GMM estimation
result = minimize(gmm_objective, params_init, args=(u_z,score), method='BFGS', bounds = bounds, tol = 10e-12)

# Extract estimated parameters
params_estimated = result.x

# Display results
print("Estimated Parameters:")
print("a:", params_estimated[0])
print("b:", params_estimated[1])
print("s:", params_estimated[2])
print("\nMinimization Result:")
print(result)
```
```

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.