Discussion:
[Quantlib-users] SABR Calibration
mmmarra
8 years ago
Permalink
Hi all!

I am trying to do a SABR calibration for Equity Futures the same was as it
is explained here:
https://letianquant.files.wordpress.com/2016/01/12-sabr-model.pdf

I would like to keep Beta = 1 fixed and find Alpha, Rho and Nu such that
equation (6) from the paper would return me the correct ATM Vol (so I can
use the ATM Vols later on to shift Alpha without needing to recalibrate
Beta, Rho and Nu).

I see that there are a lot of post on SABR and I apologize if the solution
is already out there but I am relatively new to C++ (~2 months) and I come
from a very good knowledge of VBA but I still struggle to properly
understand everything happening in the background of QuantLib.

Attached you can see what I have done so far, I hope it helps.

Thank you,

Mario

SABR_so_Far.txt
<http://quantlib.10058.n7.nabble.com/file/n18226/SABR_so_Far.txt>



--
View this message in context: http://quantlib.10058.n7.nabble.com/SABR-Calibration-tp18226.html
Sent from the quantlib-users mailing list archive at Nabble.com.
Mario Marra
8 years ago
Permalink
Ok guys, there are some progress and I want to share them with you. Thanks to
Luigi's help, I managed to solve the following issues:

- As it is available elsewhere, in order to get the calibration, you need a
call to update. In my code I did:
SABRLinInterpolation.update();

- To calibrate 3 parameters it is needed at least 4 (should be)
observations, however, I found a way around it by incrementing the the
strikes and the vol by an amount close to zero and the calibration seems to
work well (I compared to the one in RStudio and the results seem to be
correct);

What we are still trying to solve is the issue related to the constraint.
From the equation (6) of the file I attached you can see that the constraint
of alpha is a specific figure which is a function of ATM_Vol, Forward,
Time_to_Maturity, Beta, Rho and Nu.
I suggested to use a Composite constraint but it seems that it might not be
that easy as suggested by Luigi through emails.

So from now the real question is, do you know how can I force the
calibration to have AlphaIsFixed = False while at the same time returning a
parameter which returns the correct value if the equation (6) from the paper
is used?

Thank you in advance,

Mario


Following there is what I have down so far

######

int main(int argc, const char * argv[])
{
//~~~~~~~~~~~~~~~~~~~~~~~~~SABR Interpolation Curve
std::cout << "SABR Interpolation" << std::endl;
std::vector <Real> xVec(4), yVec(xVec.size());

xVec[0] = 100; yVec[0] = 0.120232487; //Create vectors
xVec[1] = 120; yVec[1] = 0.088666203;
xVec[2] = 120.00000000001; yVec[2] = 0.0886662030001; //Trick to have the
calibration working as you need n+1 observations to calibrate n parameters
xVec[3] = 120.00000000002; yVec[3] = 0.0886662030002;//Trick to have the
calibration working as you need n+1 observations to calibrate n parameters

//SABR::SABR(4.649315068, 110.5, 0.5, 1, 0.5, 0.5, false,
false, false, false); //It just assigns value within the private components
of the class
SABRInterpolation SABRLinInterpolation(xVec.begin(), xVec.end(),
yVec.begin(), 3.649315068, 114.3, 0.087443, 1, 0.657465, -0.41797, false,
true, false, false);
SABRLinInterpolation.enableExtrapolation(); //This step is necessary to get
the possibility of interpolate the curve outside the strikes provided
{//Without Calibration
for (double x = 90; x <= 150; x++)
std::cout << "Sabr Vol at Strike " << x << ":" << SABRLinInterpolation(x)
<< std::endl;
}
std::cout << "The error is :" << SABRLinInterpolation.rmsError() <<
std::endl << std::endl << std::endl;

//~~~~~~~~~~~~~~~~~~~~~~~~~SABR Calibration
{
SABRLinInterpolation.update(); //Return Parameters
Real Return_Parms[4] = { SABRLinInterpolation.alpha(),
SABRLinInterpolation.beta(),SABRLinInterpolation.rho(),SABRLinInterpolation.nu()
};
std::cout << "The parameters calibrated are are (alpha, beta, rho and nu):
" << std::endl;
{
for (int y = 0; y <= 3; y++)
std::cout << Return_Parms[y] << std::endl;
}
std::cout << "\n\n";
{
for (double x = 90; x <= 150; x++)
std::cout << "Sabr Vol at Strike (Calibrated) " << x << ":" <<
SABRLinInterpolation(x) << std::endl;
}
std::cout << "\nThe error is :" << SABRLinInterpolation.rmsError() <<
std::endl;

system("pause");
}



--
View this message in context: http://quantlib.10058.n7.nabble.com/SABR-Calibration-tp18226p18265.html
Sent from the quantlib-users mailing list archive at Nabble.com.
Peter Caspers
8 years ago
Permalink
Hi Mario,

the SABR interpolation set up is quite generic, so I think it’s easy to add your new calibration strategy: Add a

struct SABRSmartAlphaSpecs

similar to SABRSpecs in sabrinterpolation.hpp and modify the inverse() and direct() methods that are the transformations between the (unconstrained) optimisation space and the SABR parameter space. You can probably inherit from SABRSpecs and just overwrite the two methods.

You can check if alpha is fixed in these methods (they have the isFixed bool-vector as an input) and if yes set it to the value from the paper. Then add the spec struct as a template parameter to SABRInterpolation (it’s hardcoded to SABRSpecs at the moment) and typedef SABRInterpolation_t<SABRSpec> to SABRInterpolation to maintain backwards compatibility. You can add a second typedef SABRInterpolation_t<SABRSmartAlphaSpecs> to SABRSmartAlphaInterpolation, which is then your new interpolation class.

There is a small problem though, since neither the option maturity nor the atm vol is provided to the inverse / direct methods. This would require an extension of the signature of these methods in SABRSpecs, ZabrSpecs, SviSpecs, and their common backbone XABRInterpolationImpl. Which is straightforward though.

If the new interpolation is actually working more stable and / or is faster to compute, then the whole thing might be worth a pull request.

About the number of parameters: When you use Levenberg Marquardt I’d expect that you need 3 points (not 4) to calibrate 3 parameters? Do you get an exception if you provide 3 points?
If on the other hand you use e.g. the Simplex Optimiser there is no such restriction, the optimisation should run with any number of points.

Best Regards
Peter
...
Mario Marra
8 years ago
Permalink
Hi Peter,

Thank you very much for taking the time to give me such a comprehensive
response!

Regarding the last point, I can confirm you that I just tested it and I just
needed 3 parameters to get the calibration and not 4 as I previously said.
Thank you for that.

Regarding the SABRSmartAlphaSpecs, it seems that your response gets straight
to the issue and you identified the changes to be made. I will try to solve
this asap and post the code here as soon as I have a solution so you can
decide whether a pull request would be beneficial.

I hope to be able to post it by tomorrow but if not, I will probably post at
some point in June as I have an exam coming up and won't be working for the
next 3 weeks.

Thank you again for your help.

Best regards,
Mario



--
View this message in context: http://quantlib.10058.n7.nabble.com/SABR-Calibration-tp18226p18269.html
Sent from the quantlib-users mailing list archive at Nabble.com.

Loading...