Monte Carlo Pricing Setup for the SABR Model
Summary
The document presents a C++ Monte Carlo setup for pricing a call under the SABR model and comparing simulated prices with Hagan and first-order Paulot approximations. It describes Euler and Milstein schemes as intended approaches, and supplies code that simulates volatility and forward-price paths using correlated normal draws before averaging discounted option payoffs.
The author reports inconsistent results but gives no answer or diagnosis. The code and parameter example provide a concrete test setup, yet there are no benchmark prices, convergence checks, or findings to establish which implementation or approximation is responsible. The stated aim includes both schemes, though the shown function alone does not demonstrate a comparison between them. The document is best read as an unresolved implementation question, not validated pricing guidance.
Key ideas
- The setup uses Monte Carlo paths to estimate a SABR call option price.
- Correlated normal draws drive the forward and volatility processes in the shown simulation.
- The author intends to compare simulated prices with Hagan and first-order Paulot approximations.
- The document reports inconsistent outputs but provides no answer or validated diagnosis.
Tags
Full text
# (C++) Monte Carlo pricer for SABR model to test Hagan / Paulot formulas
# (C++) Monte Carlo pricer for SABR model to test Hagan / Paulot formulas
I'm trying to test the so-called Hagan formula (p.6 of this paper) and the Paulot formula, order 1 only (eq. (43) p.19 of this paper. For this, i'm trying to use both Euler and Milstein scheme described here (p.9, eq. (3.1) and (3.2)) to price a call option, but the results seem not very consistent, so i'm asking myself if my code's right...
That is my C++ function:
```
double MC_SABR_price(const int& num_sims, const int& num_intervals, const double& F_0, const double& K, const double& alpha, const double& beta, const double& rho, const double& nu, const double& r, const double& T)
{
double dt = T / num_intervals;
double F[num_intervals];
double V[num_intervals];
F[0] = F_0;
V[0] = alpha;
double payoff_sum = 0.0;
for (int i=1; i<num_sims; i++)
{
for (int j=1; j<num_intervals; j++)
{
double Z1 = NormalSimulation();
double Z2 = NormalSimulation();
V[j] = V[j-1] * exp((nu * sqrt(dt) * Z1) - (0.5 * nu * nu * dt));
F[j] = F[j-1] + (V[j-1] * pow(F[j-1], beta) * sqrt(dt) * ((rho * Z1) + (sqrt(1 - (rho * rho)) * Z2)));
F[j] = max(F[j], 0.0);
}
payoff_sum += max(F[num_intervals-1] - K, 0.0);
}
return (payoff_sum / num_sims) * exp(-r*T);
}
```
With those parameters:
```
double num_sims = 100000; // Number of simulated asset paths
double num_intervals = 1000; // Number of intervals for the asset path to be sampled
double F_0 = 5.0; // Initial forward price
vector<double> K(10);
for (int i=0; i<K.size(); i++) { K[i] = 1.0 + i; }
double r = 0.0; // Risk-free rate
double T = 2.5; // One year until expiry
double alpha = 0.3; // Initial volatility
double beta = 0.7; // Elasticity
double rho = -0.5; // Correlation of asset and volatility
double nu = 0.4; // "Vol of vol"
```
These are the results I get:
As you can see nothing coincide...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.