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