Suppose the function double bsCall(double S0, const double &K, double T, double r, double sigma)
computes analytically the Black-Scholes price of a call option and double impVolCall(double S0, const double &K, double T, double r, double C)
calculates the implied volatility.
Using the put-call parity, one can define the function that returns the put implied volatility in this way:
double ImpliedVolPut(double S0, const double &K, double T, double r, double C)
{
double x = impVolCall(S0, K, T, r, C + S0 - K*exp(-r*T));
return x;
}
Moreover, I have a function that computes European Call/Put option price for the Heston model semi-analytically:
hestonClosedPrice(double lambda, double vbar, double eta, double rho, double v0, double r, double tau, double S0, double K, char optionType)
My question is why the volatility surface obtained for different values of K
and T
for the call and put options look the same:
std::vector<double> hestonPrice(std::vector<double> k, std::vector<double> t)
{
if(optionType == 'Call'){
HestonPrice(k[i],t[j]) = hestonClosedPrice(lambda, vbar, eta, rho, v0, r, t[j], S0, k[i], 'Call');
}
else{
HestonPrice(k[i],t[j]) = hestonClosedPrice(lambda, vbar, eta, rho, v0, r, t[j], S0, k[i], 'Put');
}
if (optionType == "Call") {
hestonIVS = impVolCall(S0, k, t, r, HestonPrice(k[i],t[j]));
} else if (optionType == "Put") {
hestonIVS = impVolPut(S0, k, t, r, HestonPrice(k[i],t[j]));
}
...
}
Intuitively, one should have that the lower the strike, the higher the call implied vol and the lower the put implied vol. The option pricer for both call and put is correct.