Posted by
Sebastián Miranda on
Feb 04, 2008; 11:39am
URL: http://quantlib.414.s1.nabble.com/Volatility-Surface-Interpolation-tp5741.html
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