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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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:
------------------------------------------------------------------------- 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 |
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]>:
------------------------------------------------------------------------- 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 |
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:
------------------------------------------------------------------------- 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 |
Free forum by Nabble | Edit this page |