Volatility Surface Interpolation

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

Volatility Surface Interpolation

Sebastián Miranda
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
Reply | Threaded
Open this post in threaded view
|

Re: Volatility Surface Interpolation

Sebastián Miranda
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

Volatilities.xls (54K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Volatility Surface Interpolation

Bojan Nikolic

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
Reply | Threaded
Open this post in threaded view
|

Re: Volatility Surface Interpolation

Sebastián Miranda
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
Reply | Threaded
Open this post in threaded view
|

Re: Volatility Surface Interpolation

Bojan Nikolic

Hi Sebastián,

"Sebastián Miranda" <[hidden email]> writes:

> 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.

OK, I think I see now...

The only off-the-cuff suggestion I can make is to perhaps try a higher
order interpolation scheme in your BlackVarianceSurface: see the method
setInterpolation and try BicubicSpline.

But since you are using a single date in your BlackVarianceSurface would
not something like InterpolatedSmileSection better fit your needs?

Best,
Bojan


--
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
Reply | Threaded
Open this post in threaded view
|

Re: Volatility Surface Interpolation

Luigi Ballabio
In reply to this post by Sebastián Miranda
On Mon, 2008-02-04 at 19:27 +0100, Sebastián Miranda wrote:
> So that's the problem, I interpolate linearly... and no bilinearly...
> I can't be sure variance decreases !!

Hi Sebastian,
        if you think that your volatilities make sense, you might remove the
check on variances and recompile QuantLib. Be aware that you're living
dangerously though...

Question for the volatility experts: I know that a decreasing variance
makes no sense---if it's the actual variance of an underlying. Since
we're talking of smiled volatility here (i.e., something that we use to
keep working in a Black-Scholes framework, but which is at best an
approximation of the true volatility of the underlying) should we still
require monotonicity along each strike? Moreover, does the market always
enforce it?

Thanks,
        Luigi


--

There is no such thing as public opinion. There is only published
opinion.
-- Winston Churchill



-------------------------------------------------------------------------
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
Reply | Threaded
Open this post in threaded view
|

Re: Volatility Surface Interpolation

Ferdinando M. Ametrano-3
On Wed, Feb 6, 2008 at 6:16 PM, Luigi Ballabio <[hidden email]> wrote:
>  Question for the volatility experts: I know that a decreasing variance
>  makes no sense---if it's the actual variance of an underlying. Since
>  we're talking of smiled volatility here [...] should we still
>  require monotonicity along each strike?

we shouldn't in my opinion. I would remove the require condition.

mimicking the no-smile reasoning: if the ATM forward level was
constant between 2 dates then you should have increasing variance and
increasing option values in order to avoid arbitrage. But if the ATM
changes this is not true anymore.

ciao -- Nando

-------------------------------------------------------------------------
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
Reply | Threaded
Open this post in threaded view
|

Re: Volatility Surface Interpolation

Sebastián Miranda

Thanks for all the responses !!! ( Grazie mille )
I agree with you, but I'm working in finance for less than a year...
so, sometimes, I need some else confirms what I suspects...

BTW I saw, that BlackVolSurface changed in 0.9 to experimental. I'm  
using it
in a project thats goes live in some weeks... there's anything I  
should know????
I can provide feedback about this.

best regards,

   Sebastián

   Barcelona (Spain)

El  6feb, 2008, a las 18:50 , Ferdinando Ametrano escribió:

> On Wed, Feb 6, 2008 at 6:16 PM, Luigi Ballabio  
> <[hidden email]> wrote:
>>  Question for the volatility experts: I know that a decreasing  
>> variance
>>  makes no sense---if it's the actual variance of an underlying. Since
>>  we're talking of smiled volatility here [...] should we still
>>  require monotonicity along each strike?
>
> we shouldn't in my opinion. I would remove the require condition.
>
> mimicking the no-smile reasoning: if the ATM forward level was
> constant between 2 dates then you should have increasing variance and
> increasing option values in order to avoid arbitrage. But if the ATM
> changes this is not true anymore.
>
> ciao -- Nando


-------------------------------------------------------------------------
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
Reply | Threaded
Open this post in threaded view
|

Re: Volatility Surface Interpolation

Ferdinando M. Ametrano-3
On Wed, Feb 6, 2008 at 7:20 PM, Sebastián Miranda Díaz
<[hidden email]> wrote:
> I saw, that BlackVolSurface changed in 0.9 to experimental. I'm
>  using it
>  in a project thats goes live in some weeks... there's anything I
>  should know????

from your previous messages it seemed to me you were using
BlackVarianceTermStructure and derived classes. Those classes didn't
change lately.

BlackVolSurface, its base class BlackAtmVolCurve, etc. are instead
experimental. Some day they might replace BlackVarianceTermStructure
in a more coherent volatility modelling framework, but when this will
happen it will be probably just a drop-in replacement. I wouldn't hold
my breath in the meantime...

ciao -- Nando

-------------------------------------------------------------------------
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
Reply | Threaded
Open this post in threaded view
|

Re: Volatility Surface Interpolation

Luigi Ballabio
In reply to this post by Ferdinando M. Ametrano-3
On Wed, 2008-02-06 at 18:50 +0100, Ferdinando Ametrano wrote:
> On Wed, Feb 6, 2008 at 6:16 PM, Luigi Ballabio <[hidden email]> wrote:
> >  Question for the volatility experts: I know that a decreasing variance
> >  makes no sense---if it's the actual variance of an underlying. Since
> >  we're talking of smiled volatility here [...] should we still
> >  require monotonicity along each strike?
>
> we shouldn't in my opinion. I would remove the require condition.

Ok, done.

Luigi


--

Innovation is hard to schedule.
-- Dan Fylstra



-------------------------------------------------------------------------
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
Reply | Threaded
Open this post in threaded view
|

Re: Volatility Surface Interpolation

andrea-110
Ferdinando Ametrano wrote:
 > On Wed, Feb 6, 2008 at 6:16 PM, Luigi Ballabio <luigi.ballabio@gm...> wrote:
 > > Question for the volatility experts: I know that a decreasing variance
 > > makes no sense---if it's the actual variance of an underlying. Since
 > > we're talking of smiled volatility here [...] should we still
 > > require monotonicity along each strike?
 >
 > we shouldn't in my opinion. I would remove the require condition.
 >
 > mimicking the no-smile reasoning: if the ATM forward level was
 > constant between 2 dates then you should have increasing variance and
 > increasing option values in order to avoid arbitrage. But if the ATM
 > changes this is not true anymore.
 >
 > ciao -- Nando

Hi,

I think the requirement still holds but it has to be done in a world
without "interest rate and dividends".

Without interest rates and dividends this has to be true (regardless of them smile) because the
price of a call is convex and the underlying process is a martingale. (this for each constant strike
level).

With proportional dividends (as yield or as discrete amounts), the strike has to be a function of time.

If F(t) is the forward at time t, then

For each k (= moneyness) the function

vol(t, k * F(t)) ^ 2 * t

has to be increasing.

In case you have a matrix, it is a bit tricky because you normally have strikes that do not follow
these lines, so you need to interpolate.

Andrea

-------------------------------------------------------------------------
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
Reply | Threaded
Open this post in threaded view
|

Re: Volatility Surface Interpolation

Bojan Nikolic

Andrea <[hidden email]> writes:

> In case you have a matrix, it is a bit tricky because you normally
> have strikes that do not follow these lines, so you need to
> interpolate.

I think in Sebastián's case it was indeed the interpolation that was
causing problems. At least in my experience with FX options, you often
can not get away with linearly interpolating the smile.

Best,
Bojan


--
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
Reply | Threaded
Open this post in threaded view
|

Re: Volatility Surface Interpolation

Sebastián Miranda

Well, I think interpolation is OK, its not the problem, It think that my problem is whit Bloomberg option's prices (if you ask last closing price for an option, may be you get a 1 week old price... ) *and* with the option price valuation model, since I'm working with dividend paying equities is not easy... so I think I'm overpricing calls (so, mispricing vol) and mispricing puts (so overpricing vol) especially for long maturity terms (attached example log)...
...too many things to say it's just interpolation... :-(
(btw I'd changed a little the interpolation, attach code)

I'll really appreciate any suggestion...

thankx !!!

 Sebastián



On Mon, Mar 3, 2008 at 9:49 AM, Bojan Nikolic <[hidden email]> wrote:

Andrea <[hidden email]> writes:

> In case you have a matrix, it is a bit tricky because you normally
> have strikes that do not follow these lines, so you need to
> interpolate.

I think in Sebastián's case it was indeed the interpolation that was
causing problems. At least in my experience with FX options, you often
can not get away with linearly interpolating the smile.

Best,
Bojan


--
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

impVol.hpp (13K) Download Attachment
2008-2-28 BMPS IM Equity.log (25K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Volatility Surface Interpolation

Lapin
Sebastian,
 
You are also pricing American style options.
This leads to issues when trying to solve a single volatility for 1 term and strike.
 


 
2008/3/3, Sebastián Miranda <[hidden email]>:

Well, I think interpolation is OK, its not the problem, It think that my problem is whit Bloomberg option's prices (if you ask last closing price for an option, may be you get a 1 week old price... ) *and* with the option price valuation model, since I'm working with dividend paying equities is not easy... so I think I'm overpricing calls (so, mispricing vol) and mispricing puts (so overpricing vol) especially for long maturity terms (attached example log)...
...too many things to say it's just interpolation... :-(
(btw I'd changed a little the interpolation, attach code)

I'll really appreciate any suggestion...

thankx !!!

 Sebastián



On Mon, Mar 3, 2008 at 9:49 AM, Bojan Nikolic <[hidden email]> wrote:

Andrea <[hidden email]> writes:

> In case you have a matrix, it is a bit tricky because you normally
> have strikes that do not follow these lines, so you need to
> interpolate.

 
I think in Sebastián's case it was indeed the interpolation that was
causing problems. At least in my experience with FX options, you often
can not get away with linearly interpolating the smile.

Best,
Bojan


--
Bojan Nikolic


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
<a onclick="return top.js.OpenExtLink(window,event,this)" href="http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/" target="_blank">http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
QuantLib-users mailing list
[hidden email]
<a onclick="return top.js.OpenExtLink(window,event,this)" href="https://lists.sourceforge.net/lists/listinfo/quantlib-users" target="_blank">https://lists.sourceforge.net/lists/listinfo/quantlib-users




-------------------------------------------------------------------------
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
Reply | Threaded
Open this post in threaded view
|

Re: Volatility Surface Interpolation

Sebastián Miranda

Yes, most of them are American style options... but for long terms I'm trying to approximate with European options...
And, yes I have a lot of issues trying to get single volatility for calls and puts, so I'm considering just to use only calls but I'm not pretty sure that's the solution...

best regards,
 

  Sebastián



On Mon, Mar 3, 2008 at 12:11 PM, Guillaume Pealat <[hidden email]> wrote:
Sebastian,
 
You are also pricing American style options.
This leads to issues when trying to solve a single volatility for 1 term and strike.
 


 
2008/3/3, Sebastián Miranda <[hidden email]>:

Well, I think interpolation is OK, its not the problem, It think that my problem is whit Bloomberg option's prices (if you ask last closing price for an option, may be you get a 1 week old price... ) *and* with the option price valuation model, since I'm working with dividend paying equities is not easy... so I think I'm overpricing calls (so, mispricing vol) and mispricing puts (so overpricing vol) especially for long maturity terms (attached example log)...
...too many things to say it's just interpolation... :-(
(btw I'd changed a little the interpolation, attach code)

I'll really appreciate any suggestion...

thankx !!!

 Sebastián



On Mon, Mar 3, 2008 at 9:49 AM, Bojan Nikolic <[hidden email]> wrote:

Andrea <[hidden email]> writes:

> In case you have a matrix, it is a bit tricky because you normally
> have strikes that do not follow these lines, so you need to
> interpolate.

 
I think in Sebastián's case it was indeed the interpolation that was
causing problems. At least in my experience with FX options, you often
can not get away with linearly interpolating the smile.

Best,
Bojan


--
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





-------------------------------------------------------------------------
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