Login  Register

Re: Error with old-style implied vol

Posted by Dirk Eddelbuettel on Nov 27, 2003; 2:36pm
URL: http://quantlib.414.s1.nabble.com/Error-with-old-style-implied-vol-tp10464p10465.html

On Wed, Nov 26, 2003 at 10:29:04PM -0600, Dirk Eddelbuettel wrote:

>
> In the process of updating RQuantLib to 0.3.4, I found that my wrappers
> around European and American implied vol no longer work. [ That I found that
> is a good thing; R stronly encourages a manual page for every function.
> These manual pages usually have examples, and during the 'make check' phase
> all of the available examples are run. Quite nice. ]
>
> I do know that I'll have to convert to the new prices one day anyway, but is
> there a shortcut to keep the current alive while I prepare one based on the
> new pricing engines?  
>
> I include a simple stand-alone below.  It builds fine, compute the NPV of an
> option (just to show that it links right etc pp) but abort on implied vol.
>
> CHROOT edd@chibud:~/src/progs/C++$ g++ -Wall -o test_ql_impliedvol
> test_ql_impliedvol.cc -lQuantLib
> CHROOT edd@chibud:~/src/progs/C++$ ./test_ql_impliedvol
> Value:  5.81756
> Aborted
>
> Here is the short program:
>
>
> // implied vol in RQuantLib-0.1.7 blows up with QL 0.3.4
>
> #include <ql/quantlib.hpp>
> #include <iostream>
>
> using namespace QuantLib;
> using QuantLib::Pricers::EuropeanOption;
>
> int main(void) {
>   double underlying = 100;
>   double strike = 100;
>   double dividendYield = 0.02;
>   double riskFreeRate = 0.03;
>   double maturity = 0.5;
>   double volatility = 0.2;
>   Option::Type optionType = Option::Call;
>
>   EuropeanOption EO = EuropeanOption(optionType, underlying, strike,
>     dividendYield, riskFreeRate, maturity,
>     volatility);
>   std::cout << "Value:  " << EO.value() << std::endl;
>   double impliedVol = EO.impliedVolatility(EO.value()+0.1);
>   std::cout << "Implied:" << impliedVol << std::endl;
>   exit(0);
> }
>
> Thanks in advance for any insights.

Given the deafening silence :) as well as some curiousity on my part as to
whether I'd manage to understand the fancy-pants new-style C++, I turned the
above example into a small-ish standalone -- see below.

Now that I crossed that bridge, is there an FAQ / site I could consult to
upgrade my early-1990s understanding of C++ to learn about the handles etc?

Cheers, Dirk


// implied vol in RQuantLib-0.1.7 blows up with QL 0.3.4

#define NEW 1

#ifdef OLD
#include <ql/quantlib.hpp>
#include <iostream>

using namespace QuantLib;
using QuantLib::Pricers::EuropeanOption;

int main(void) {
  double underlying = 100;
  double strike = 100;
  double dividendYield = 0.02;
  double riskFreeRate = 0.03;
  double maturity = 0.5;
  double volatility = 0.2;
  Option::Type optionType = Option::Call;

  EuropeanOption EO = EuropeanOption(optionType, underlying, strike,
                                     dividendYield, riskFreeRate, maturity,
                                     volatility);
  double value = EO.value();
  std::cout << "Value:  " << value << std::endl;
  double impliedVol = EO.impliedVolatility(value-0.1);
  std::cout << "Implied:" << impliedVol << std::endl;
  exit(0);
}
#endif

#include <ql/quantlib.hpp>
#include <iostream>

#include <ql/Instruments/vanillaoption.hpp>
#include <ql/PricingEngines/mceuropeanengine.hpp>
#include <ql/TermStructures/flatforward.hpp>
#include <ql/Volatilities/blackconstantvol.hpp>
#include <ql/Calendars/target.hpp>
#include <cppunit/TestSuite.h>
#include <cppunit/TestCaller.h>
#include <map>


using namespace QuantLib;
using namespace QuantLib::PricingEngines;
using namespace QuantLib::Instruments;
using namespace QuantLib::TermStructures;
using namespace QuantLib::VolTermStructures;
using namespace QuantLib::DayCounters;
using namespace QuantLib::Calendars;
using namespace QuantLib::MonteCarlo;

int main(void) {
  Option::Type type = Option::Call;
  double strike = 100;
  int length = 180;
  double underlyingprice = 100.0;
  Rate qRateval = 0.01;
  Rate rRateval = 0.05;
  double volval = 0.20;

  Date today = Date::todaysDate();
  Date reference = TARGET().advance(today,2,Days);

  Handle<SimpleMarketElement> underlying(new SimpleMarketElement(0.0));
  Handle<SimpleMarketElement> volatility(new SimpleMarketElement(0.0));
  Handle<BlackVolTermStructure>
    volCurve(new BlackConstantVol(reference,
                                  RelinkableHandle<MarketElement>(volatility),
                                  Actual365()));
  Handle<SimpleMarketElement> qRate(new SimpleMarketElement(0.0));
  Handle<TermStructure>
    divCurve(new FlatForward(today, reference,
                             RelinkableHandle<MarketElement>(qRate),
                             Actual365()));
  Handle<SimpleMarketElement> rRate(new SimpleMarketElement(0.0));
  Handle<TermStructure>
    rfCurve(new FlatForward(today, reference,
                             RelinkableHandle<MarketElement>(rRate),
                             Actual365()));
  Handle<PricingEngine> engine(new AnalyticEuropeanEngine);

  Date exDate = today.plusDays(length);
  Handle<VanillaOption>
    option(new VanillaOption(type,
                             RelinkableHandle<MarketElement>(underlying),
                             strike,
                             RelinkableHandle<TermStructure>(divCurve),
                             RelinkableHandle<TermStructure>(rfCurve),
                             EuropeanExercise(exDate),
                             RelinkableHandle<BlackVolTermStructure>(volCurve),
                             engine));

  underlying->setValue(underlyingprice);
  qRate->setValue(qRateval);
  rRate->setValue(rRateval);
  volatility->setValue(volval);
 
  double value = option->NPV();
  volatility->setValue(volval*1.5); // initialize as too high
  double implVol = option->impliedVolatility(value+0.1);
             
  std::cout << "Value:  " << value << std::endl;
  std::cout << "Implied:" << implVol << std::endl;

}


--
Those are my principles, and if you don't like them... well, I have others.
                                                -- Groucho Marx