Login  Register

Re: Volatility Surface Interpolation

Posted by Sebastián Miranda on Feb 04, 2008; 6:27pm
URL: http://quantlib.414.s1.nabble.com/Volatility-Surface-Interpolation-tp5741p5744.html

Hi Bojan,

The problem is that, I have the smiles and I need to get a volatility
matrix, so I interpolate all the smiles such that every smiles has the
same strikes (you can see it after the line... "if ( Smiles[i].size()
< numStrikes )" ). Then with that matrix, I interpolate to get the
volatilities at the predefined terms.

So that's the problem, I interpolate linearly... and no bilinearly...
I can't be sure variance decreases !!

best regards,

 Sebastián


On Feb 4, 2008 2:10 PM, Bojan Nikolic <[hidden email]> wrote:

>
> Hi Sebastián,
>
> If I'm reading your volatility matrix right then for the 130 strike
> the variance indeed decreases as time progresses;
> that  is the vol^2 * time :
>
>  0.4989**2 * 0.127777777777777 =0.031804043499999803
>
>  0.3775**2 * 0.205555555555555 = 0.029292951388888808
>
> You should check with your source of volatility quotes.
>
> Best,
> Bojan
>
>
>
> "Sebastián Miranda" <[hidden email]> writes:
>
> > thanks Bojan!!
> >
> > For the example matrix use this:
> >
> > Settlement date: 39482
> >
> > strikes:      dates:
> > ------------------------------
> > 130           39493
> > 140           39528
> > 150           39556
> > 160           39619
> > 165           39710
> > 170           39801
> > 175           39983
> > 180           40165
> > 185
> > 190
> > 195
> > 200
> > 210
> > 220
> >
> > dates in years:
> > --------------------------------
> > 0,0305555555555555
> > 0,0305555555555555
> > 0,127777777777777
> > 0,205555555555555
> > 0,380555555555555
> > 0,633333333333333
> > 0,886111111111111
> > 1,39166666666666
> > 1,89722222222222
> >
> >
> > On Feb 4, 2008 12:39 PM, Sebastián Miranda
> > <[hidden email]> wrote:
> >> Hello,
> >>
> >> I'm trying to interpolate time/strike dependent volatilities using the
> >> BlackVarianceTermStructure.
> >>
> >> I interpolate every term smile to get the volatility matrix and then
> >> interpolate that matrix to get volatilities at given standard times.
> >>
> >> But, when I call the constructor, I get the error:
> >>
> >>                 QL_REQUIRE(variances_[i][j]>=variances_[i][j-1],
> >>                            "variance must be non-decreasing");
> >>
> >> Any ideas about where's the error????
> >>
> >> Tankx !!!!
> >>
> >>     Sebastián
> >>
> >> ============================================================================
> >> ==
> >> Example Volatility Matrix:
> >>
> >> 0,7335    0,4989    0,3775    0,3467    0,3305    0,3342    0,5698    0,5814
> >> 0,6635    0,4404    0,3730    0,3324    0,3271    0,3275    0,5407    0,5463
> >> 0,5853    0,3983    0,3685    0,3217    0,3237    0,3239    0,5098    0,5138
> >> 0,4948    0,3855    0,3613    0,3225    0,3203    0,3196    0,4770    0,4899
> >> 0,4187    0,3604    0,3448    0,3188    0,3172    0,3175    0,4466    0,4382
> >> 0,4298    0,3545    0,3428    0,3150    0,3140    0,3154    0,4140    0,3796
> >> 0,3915    0,3456    0,3225    0,3135    0,3109    0,3115    0,3785    0,3712
> >> 0,3571    0,3365    0,3143    0,3119    0,3077    0,3076    0,3394    0,3626
> >> 0,4132    0,3206    0,2915    0,3083    0,3059    0,3030    0,3148    0,3401
> >> 0,3823    0,3169    0,2873    0,3046    0,3040    0,2983    0,2882    0,3160
> >> 0,3749    0,3170    0,2870    0,3008    0,2994    0,2921    0,2588    0,2900
> >> 0,3245    0,3183    0,2866    0,2970    0,2948    0,2857    0,2256    0,2613
> >> 0,4503    0,3375    0,2860    0,2939    0,2862    0,2815    0,2063    0,2472
> >> 0,5691    0,3396    0,2853    0,2906    0,2774    0,2772    0,1849    0,2323
> >>
> >>
> >> ============================================================================
> >> ==
> >> The code:
> >>
> >> void cargarBBDD( vector< MaturitySmileData > ACUMULADOR ){
> >>     // ==============================================================
> >>     // FECHA INICIAL DEL CALCULO -> Atentos a los históricos
> >>     Date fechaINICIAL    = ACUMULADOR[0].subyacente.settlementDate;
> >>     // Date fechaINICIAL    =    Date::todaysDate();
> >>     // ==============================================================
> >>     typedef map<double, double> Smile;
> >>     typedef map<double,double>::iterator Iterador;
> >>     const unsigned  int numVenc    =    ACUMULADOR.size();
> >>     std::vector<Date> maturities(numVenc);
> >>     // Monto set ordenado con todos los strikes.
> >>     std::set< double >        strikesSet;
> >>     std::vector< Smile >    Smiles;
> >>     for ( unsigned int i = 0; i < numVenc ; i++){
> >>         Smile tmpSmile__;
> >>         Iterador iterSmile;
> >>         Iterador iter_;
> >>         iter_    =    ACUMULADOR[i].callSmile.begin();
> >>         while (iter_ != ACUMULADOR[i].callSmile.end() ){
> >>             strikesSet.insert( iter_->first );
> >>             tmpSmile__.insert( *iter_ );
> >>             iter_++;
> >>         }
> >>         iter_    =    ACUMULADOR[i].putSmile.begin();
> >>         while (iter_ != ACUMULADOR[i].putSmile.end() ){
> >>             strikesSet.insert( iter_->first );
> >>             iterSmile    = tmpSmile__.find( iter_->first );
> >>             if (iterSmile == tmpSmile__.end() ){
> >>                 tmpSmile__.insert( *iter_ ) ;
> >>             } else{ //! Si ya tenemos este strike para las Calls,
> >> promediamos ambos.
> >>                 if( fabs(iter_->second - iterSmile->second)
> >> > 0.02) {
> >>                     string MegError = "Error promediando curva -> ";
> >>                     MegError += "RIC: " +
> >> ACUMULADOR[i].subyacente.RIC + "\t Vencimiento. "+ ACUMULADOR[i].vencimiento ;
> >>                     MegError += "\n Vol. Call:\t"  +
> >> boost::lexical_cast<std::string>( (*iterSmile).second );
> >>                     MegError += "\n Vol. Put:\t"   +
> >> boost::lexical_cast<std::string>( (*iter_).second );
> >>                     MegError += "\n
> >> --------------------------------";
> >>                     MegError += "\n DIFERENCIA:\t" +
> >> boost::lexical_cast<std::string>(fabs((*iter_).second - (*iterSmile).second) );
> >>                     VOLCAR_LOG( MegError  );
> >>                 }
> >>                 iterSmile->second = ((*iter_).second +
> >> (*iterSmile).second) / 2;
> >>             }
> >>             iter_++;
> >>         }// end while
> >>         Smiles.push_back(tmpSmile__);
> >>     };   // end for numVenc
> >>     const unsigned int numStrikes    =    strikesSet.size();
> >>     vector< double> strikes( strikesSet.begin(), strikesSet.end());
> >>     Matrix volatilidades( numStrikes, numVenc );
> >>     for ( unsigned  int i = 0; i < numVenc ; i++){
> >>         maturities[i]    = ACUMULADOR[i].maturity;
> >>         Iterador iter_;
> >>         // Si no tiene todos los strikes, interpolamos.
> >>         if ( Smiles[i].size() < numStrikes ){
> >>
> >>             const unsigned int s_    =    Smiles[i].size();
> >>             Matrix vols_( s_ , 1);
> >>             std::vector<Date> dates_(1);
> >>             dates_[0]        = ACUMULADOR[i].maturity;
> >>             // Cargo las volas
> >>             iter_ = Smiles[i].begin();
> >>             vector< double> strikesTMP;
> >>             int j = 0;
> >>             while ( iter_ != Smiles[i].end() ){
> >>                 strikesTMP.push_back( (*iter_).first ) ;
> >>                 vols_[j][0] = (*iter_).second ; j++;
> >>                 iter_++;
> >>             };
> >>             // Montamos el Smile con lo que tenemos y lo interpolamos.
> >>             boost::shared_ptr<BlackVolTermStructure>
> >> curvaVolas(new
> >>                 BlackVarianceSurface( fechaINICIAL, dates_,
> >> strikesTMP, vols_, dayCounter ));
> >>             for (unsigned int j = 0 ; j < numStrikes ; j++){
> >>                 volatilidades[j][i] =
> >> curvaVolas->blackVol(fechaINICIAL, strikes[j] , true );
> >>                 std::cout << "Vol " << j << " " << i << "\t"
> >> << volatilidades[j][i] << "\n";
> >>             };
> >>             /*
> >>             set< double >::iterator itrK_ ;
> >>             itrK_        =    strikesSet.begin();
> >>             int indx_    =    0;
> >>             while ( itrK_ != strikesSet.end() ){
> >>             volatilidades[indx_][i] =
> >> curvaVolas->blackVol(fechaINICIAL, *itrK_ , true );
> >>             indx_++;
> >>             itrK_++;
> >>             };*/
> >>
> >>         } else{ // Si tiene todos los strikes, no necesitamos interpolar nada.
> >>             iter_ = Smiles[i].begin();
> >>             int j = 0;
> >>             while ( iter_ != Smiles[i].end() ){
> >> volatilidades[j][i] = (*iter_).second ;
> >>             std::cout << "Vol " << j << " " << i << "\t" <<
> >> volatilidades[j][i] << "\n";
> >>             j++; iter_++; };
> >>         };
> >>
> >>     };
> >>
> >>     // Volatility Surface
> >>     // HERE IS THE PROBLEM
> >> *********************************************************
> >>     boost::shared_ptr<BlackVolTermStructure> SupVolatilidad(new
> >>         BlackVarianceSurface( fechaINICIAL, maturities, strikes,
> >> volatilidades, dayCounter ));
> >>     // HERE IS THE PROBLEM
> >> *********************************************************
> >>
> >>     // Interpolamos
> >>     const int    numStrikesSTD    =    13;
> >>     const int    numTermsSTD        =     8;
> >>     double    strikesSTD[]        =    { 0.8,
> >>
> >> 0.85,
> >>
> >> 0.9,
> >>
> >> 0.95,
> >>
> >> 0.975,
> >>
> >> 0.9875,
> >>
> >> 1.0,
> >>
> >> 1.0125,
> >>
> >> 1.025,
> >>
> >> 1.05,
> >>
> >> 1.1,
> >>
> >> 1.15,
> >>
> >> 1.2 };
> >>     Date    termsSTD[]            =    {fechaINICIAL +
> >> 1*Months,
> >>
> >> fechaINICIAL + 3*Months,
> >>
> >> fechaINICIAL + 6*Months,
> >>
> >> fechaINICIAL + 1*Years,
> >>
> >> fechaINICIAL + 2*Years,
> >>
> >> fechaINICIAL + 3*Years,
> >>
> >> fechaINICIAL + 4*Years,
> >>
> >> fechaINICIAL + 5*Years };
> >>     // Superficie de Volatilidades interpolada.
> >>     double    volasBBDD[numStrikesSTD][numTermsSTD];
> >>     for (unsigned int i = 0 ; i < numStrikesSTD ; i++){
> >>         double    strike__    =    strikesSTD[i] *
> >> ACUMULADOR[0].subyacente.spot;
> >>         for (unsigned int j = 0 ; j < numTermsSTD ; j++){
> >>             volasBBDD[i][j] =
> >> SupVolatilidad->blackVol(termsSTD[j], strike__ , true );
> >>         };
> >>     };
> >>     string dia =
> >> boost::lexical_cast<std::string>(fechaINICIAL.dayOfMonth());
> >>     dia    = ( dia.length() == 1 )? "0" + dia : dia ;
> >>     int mes__  = fechaINICIAL.month();
> >>     string mes = boost::lexical_cast<std::string>(mes__);
> >>     mes    = ( mes.length() == 1 )? "0" + mes : mes ;
> >>     std::string query = "";
> >>     query    += "INSERT INTO `advisory`.`tsupvolas` VALUES ";
> >>     for (unsigned int i = 0 ; i < numStrikesSTD ; i++){
> >>         query    +=    "( " + ACUMULADOR[0].subyacente.ID + ",'" +
> >> boost::lexical_cast<std::string>(fechaINICIAL.year());
> >>         query    +=    mes + dia + "'," +
> >> boost::lexical_cast<std::string>(strikesSTD[i]) + "," ;
> >>         query    +=
> >> boost::lexical_cast<std::string>(ACUMULADOR[0].subyacente.spot);
> >>         for (unsigned int j = 0 ; j < numTermsSTD ; j++){
> >>             query    +=    "," +
> >> boost::lexical_cast<std::string>(volasBBDD[i][j]);
> >>         };
> >>         query    +=    ") ";
> >>         query    +=    (i + 1 == numStrikesSTD)? "" : ",";
> >>     };
> >>     query    +=    "; ";
> >>     // INSERTAMOS EN LA BBDD
> >>     res            =    consultaSQL(query);
> >>     //int filas    =    mysql_affected_rows();
> >>     //string staus=    ( filas == numStrikesSTD)?
> >> ACUMULADOR[0].subyacente.RIC + " insertado OK." :
> >> ACUMULADOR[0].subyacente.RIC + " Error Inserción.";
> >>     mysql_free_result(res);
> >> // boost::lexical_cast<std::string>
> >> };
> >>
> >
> > -------------------------------------------------------------------------
> > This SF.net email is sponsored by: Microsoft
> > Defy all challenges. Microsoft(R) Visual Studio 2008.
> > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/_______________________________________________
> > QuantLib-users mailing list
> > [hidden email]
> > https://lists.sourceforge.net/lists/listinfo/quantlib-users
>
>
> --
> Bojan Nikolic
>

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users