Re: Vanilla Swap valuation

Posted by Luigi Ballabio on
URL: http://quantlib.414.s1.nabble.com/Vanilla-Swap-valuation-tp405p406.html

On Thu, 2011-05-19 at 09:30 -0700, Pointman wrote:
> I am trying to value a plain old vanilla swap (pay fixed - receive usd libor)
> and have based my code on swapvaluation.cpp example. My swap settled on
> 3-may-2011, today is 19-may-2011 and it is a 7 year swap and fixed rate is
> 2.83. I am getting an error at line NPV = spot5YearSwap.NPV() which I can
> not figure out why. The code follows. Any help is greatly appreciated. Thank
> you.

The settlementDate is not meant to be the past date at which the swap
settled, it's the date at which you'd settle if you were to unwind the
swap today.  Basically it is the date at which you discount the cash
flows, which probably makes settlementDate a bit of a misnomer.

Anyway, you can just set settlementDate = todaysDate, or todaysDate plus
two settlement days if you want to discount to spot.

After that, it should work.

Luigi



> -------------------
> Error message : 1st iteration: failed at 3rd alive instrument, maturity
> August 23rd, 2011, refer
> ence date May 3rd, 2011: root not bracketed: f[2.22045e-016,0.999738] ->
> [-1.762
> 113e+016,-2.035924e-004]
> ---------------------
> // the only header you need to use QuantLib
> #include <ql/quantlib.hpp>
>
> #ifdef BOOST_MSVC
> /* Uncomment the following lines to unmask floating-point
>    exceptions. Warning: unpredictable results can arise...
>
>    See http://www.wilmott.com/messageview.cfm?catid=10&threadid=9481
>    Is there anyone with a definitive word about this?
> */
> // #include <float.h>
> // namespace { unsigned int u = _controlfp(_EM_INEXACT, _MCW_EM); }
> #endif
>
> #include <boost/timer.hpp>
> #include <iostream>
> #include <iomanip>
>
> using namespace QuantLib;
>
> #if defined(QL_ENABLE_SESSIONS)
> namespace QuantLib {
>
>     Integer sessionId() { return 0; }
>
> }
> #endif
>
>
> int main(int, char* []) {
>
>     try {
>
>         boost::timer timer;
>         std::cout << std::endl;
>
>         /*********************
>          ***  MARKET DATA  ***
>          *********************/
>
>         Calendar calendar = TARGET();
>         Date settlementDate(3, May, 2011);
>         // must be a business day
>         settlementDate = calendar.adjust(settlementDate);
>
>         Integer fixingDays = 2;
>         Date todaysDate(19,May,2011);
>         // nothing to do with Date::todaysDate
>         Settings::instance().evaluationDate() = todaysDate;
>
>
>         todaysDate = Settings::instance().evaluationDate();
>         std::cout << "Today: " << todaysDate.weekday()
>                   << ", " << todaysDate << std::endl;
>
>         std::cout << "Settlement date: " << settlementDate.weekday()
>                   << ", " << settlementDate << std::endl;
>
>         // deposits
>         Rate d1wQuote=0.0016835;
>         Rate d1mQuote=0.0019575;
>         Rate d3mQuote=0.000456;
>         Rate d6mQuote=0.000862;
>         Rate d9mQuote=0.00571;
>         Rate d1yQuote=0.0073475;
>        
>         // swaps
>         Rate s2yQuote=0.0075;
>         Rate s3yQuote=0.0122;
>         Rate s5yQuote=0.02071;
>         Rate s10yQuote=0.03254;
>         Rate s15yQuote=0.03722;
>
>
>         /********************
>          ***    QUOTES    ***
>          ********************/
>
>         // SimpleQuote stores a value which can be manually changed;
>         // other Quote subclasses could read the value from a database
>         // or some kind of data feed.
>
>         // deposits
>         boost::shared_ptr d1wRate(new SimpleQuote(d1wQuote));
>         boost::shared_ptr d1mRate(new SimpleQuote(d1mQuote));
>         boost::shared_ptr d3mRate(new SimpleQuote(d3mQuote));
>         boost::shared_ptr d6mRate(new SimpleQuote(d6mQuote));
>         boost::shared_ptr d9mRate(new SimpleQuote(d9mQuote));
>         boost::shared_ptr d1yRate(new SimpleQuote(d1yQuote));
>        
>         // swaps
>         boost::shared_ptr s2yRate(new SimpleQuote(s2yQuote));
>         boost::shared_ptr s3yRate(new SimpleQuote(s3yQuote));
>         boost::shared_ptr s5yRate(new SimpleQuote(s5yQuote));
>         boost::shared_ptr s10yRate(new SimpleQuote(s10yQuote));
>         boost::shared_ptr s15yRate(new SimpleQuote(s15yQuote));
>
>
>         /*********************
>          ***  RATE HELPERS ***
>          *********************/
>
>         // RateHelpers are built from the above quotes together with
>         // other instrument dependant infos.  Quotes are passed in
>         // relinkable handles which could be relinked to some other
>         // data source later.
>
>         // deposits
>         DayCounter depositDayCounter = Actual360();
>
>         boost::shared_ptr<RateHelper> d1w(new DepositRateHelper(
>             Handle(d1wRate),
>             1*Weeks, fixingDays,
>             calendar, ModifiedFollowing,
>             true, depositDayCounter));
>         boost::shared_ptr<RateHelper> d1m(new DepositRateHelper(
>             Handle(d1mRate),
>             1*Months, fixingDays,
>             calendar, ModifiedFollowing,
>             true, depositDayCounter));
>         boost::shared_ptr<RateHelper> d3m(new DepositRateHelper(
>             Handle(d3mRate),
>             3*Months, fixingDays,
>             calendar, ModifiedFollowing,
>             true, depositDayCounter));
>         boost::shared_ptr<RateHelper> d6m(new DepositRateHelper(
>             Handle(d6mRate),
>             6*Months, fixingDays,
>             calendar, ModifiedFollowing,
>             true, depositDayCounter));
>         boost::shared_ptr<RateHelper> d9m(new DepositRateHelper(
>             Handle(d9mRate),
>             9*Months, fixingDays,
>             calendar, ModifiedFollowing,
>             true, depositDayCounter));
>         boost::shared_ptr<RateHelper> d1y(new DepositRateHelper(
>             Handle(d1yRate),
>             1*Years, fixingDays,
>             calendar, ModifiedFollowing,
>             true, depositDayCounter));
>
>
>        
>
>        
>
>         // setup swaps
>         Frequency swFixedLegFrequency = Semiannual;
>         BusinessDayConvention swFixedLegConvention = ModifiedFollowing;
>         DayCounter swFixedLegDayCounter = Thirty360(Thirty360::USA);
>         boost::shared_ptr<IborIndex> swFloatingLegIndex(new
> USDLibor(Period(3,Months)));
>
>         boost::shared_ptr<RateHelper> s2y(new SwapRateHelper(
>             Handle(s2yRate), 2*Years,
>             calendar, swFixedLegFrequency,
>             swFixedLegConvention, swFixedLegDayCounter,
>             swFloatingLegIndex));
>         boost::shared_ptr<RateHelper> s3y(new SwapRateHelper(
>             Handle(s3yRate), 3*Years,
>             calendar, swFixedLegFrequency,
>             swFixedLegConvention, swFixedLegDayCounter,
>             swFloatingLegIndex));
>         boost::shared_ptr<RateHelper> s5y(new SwapRateHelper(
>             Handle(s5yRate), 5*Years,
>             calendar, swFixedLegFrequency,
>             swFixedLegConvention, swFixedLegDayCounter,
>             swFloatingLegIndex));
>         boost::shared_ptr<RateHelper> s10y(new SwapRateHelper(
>             Handle(s10yRate), 10*Years,
>             calendar, swFixedLegFrequency,
>             swFixedLegConvention, swFixedLegDayCounter,
>             swFloatingLegIndex));
>         boost::shared_ptr<RateHelper> s15y(new SwapRateHelper(
>             Handle(s15yRate), 15*Years,
>             calendar, swFixedLegFrequency,
>             swFixedLegConvention, swFixedLegDayCounter,
>             swFloatingLegIndex));
>
>
>         /*********************
>          **  CURVE BUILDING **
>          *********************/
>
>         // Any DayCounter would be fine.
>         // ActualActual::ISDA ensures that 30 years is 30.0
>         DayCounter termStructureDayCounter =
>             ActualActual(ActualActual::ISDA);
>
>
>         double tolerance = 1.0e-15;
>
>         // A depo-swap curve
>         std::vector<boost::shared_ptr<RateHelper> > depoSwapInstruments;
>         depoSwapInstruments.push_back(d1w);
>         depoSwapInstruments.push_back(d1m);
>         depoSwapInstruments.push_back(d3m);
>         depoSwapInstruments.push_back(d6m);
>         depoSwapInstruments.push_back(d9m);
>         depoSwapInstruments.push_back(d1y);
>         depoSwapInstruments.push_back(s2y);
>         depoSwapInstruments.push_back(s3y);
>         depoSwapInstruments.push_back(s5y);
>         depoSwapInstruments.push_back(s10y);
>         depoSwapInstruments.push_back(s15y);
>         boost::shared_ptr<YieldTermStructure> depoSwapTermStructure(
>             new PiecewiseYieldCurve<Discount,LogLinear>(
>                                           settlementDate,
> depoSwapInstruments,
>                                           termStructureDayCounter,
>                                           tolerance));
>
>
>        
>         // Term structures that will be used for pricing:
>         // the one used for discounting cash flows
>         RelinkableHandle<YieldTermStructure> discountingTermStructure;
>         // the one used for forward rate forecasting
>         RelinkableHandle<YieldTermStructure> forecastingTermStructure;
>
>
>         /*********************
>         * SWAPS TO BE PRICED *
>         **********************/
>
>         // constant nominal 1,000,000 Euro
>         Real nominal = 1350000.0;
>         // fixed leg
>         Frequency fixedLegFrequency = Semiannual;
>         BusinessDayConvention fixedLegConvention = ModifiedFollowing;
>         BusinessDayConvention floatingLegConvention = ModifiedFollowing;
>         DayCounter fixedLegDayCounter = Thirty360(Thirty360::USA);
>         Rate fixedRate = .02883;
>         DayCounter floatingLegDayCounter = Actual360();
>
>         // floating leg
>         Frequency floatingLegFrequency = Quarterly;
>         boost::shared_ptr<IborIndex> euriborIndex(
>                                      new
> USDLibor(Period(6,Months),discountingTermStructure));
>         Spread spread = 0.0;
>
>         Integer lenghtInYears = 7;
>         VanillaSwap::Type swapType = VanillaSwap::Payer;
>
>         Date maturity = settlementDate + lenghtInYears*Years;
>         Schedule fixedSchedule(settlementDate, maturity,
>                                Period(fixedLegFrequency),
>                                calendar, fixedLegConvention,
>                                fixedLegConvention,
>                                DateGeneration::Forward, false);
>         Schedule floatSchedule(settlementDate, maturity,
>                                Period(floatingLegFrequency),
>                                calendar, floatingLegConvention,
>                                floatingLegConvention,
>                                DateGeneration::Forward, false);
>         VanillaSwap spot5YearSwap(swapType, nominal,
>             fixedSchedule, fixedRate, fixedLegDayCounter,
>             floatSchedule, euriborIndex, spread,
>             floatingLegDayCounter);
>
>         Date fwdStart = calendar.advance(settlementDate, 1, Years);
>         Date fwdMaturity = fwdStart + lenghtInYears*Years;
>         Schedule fwdFixedSchedule(fwdStart, fwdMaturity,
>                                   Period(fixedLegFrequency),
>                                   calendar, fixedLegConvention,
>                                   fixedLegConvention,
>                                   DateGeneration::Forward, false);
>         Schedule fwdFloatSchedule(fwdStart, fwdMaturity,
>                                   Period(floatingLegFrequency),
>                                   calendar, floatingLegConvention,
>                                   floatingLegConvention,
>                                   DateGeneration::Forward, false);
>         VanillaSwap oneYearForward5YearSwap(swapType, nominal,
>             fwdFixedSchedule, fixedRate, fixedLegDayCounter,
>             fwdFloatSchedule, euriborIndex, spread,
>             floatingLegDayCounter);
>
>
>         /***************
>         * SWAP PRICING *
>         ****************/
>
>         // utilities for reporting
>         std::vector<std::string> headers(4);
>         headers[0] = "term structure";
>         headers[1] = "net present value";
>         headers[2] = "fair spread";
>         headers[3] = "fair fixed rate";
>         std::string separator = " | ";
>         Size width = headers[0].size() + separator.size()
>                    + headers[1].size() + separator.size()
>                    + headers[2].size() + separator.size()
>                    + headers[3].size() + separator.size() - 1;
>         std::string rule(width, '-'), dblrule(width, '=');
>         std::string tab(8, ' ');
>
>         // calculations
>         std::cout << dblrule << std::endl;
>         std::cout <<  "5-year market swap-rate = "
>                   << std::setprecision(2) << io::rate(s5yRate->value())
>                   << std::endl;
>         std::cout << dblrule << std::endl;
>
>         std::cout << tab << "5-years swap paying "
>                   << io::rate(fixedRate) << std::endl;
>         std::cout << headers[0] << separator
>                   << headers[1] << separator
>                   << headers[2] << separator
>                   << headers[3] << separator << std::endl;
>         std::cout << rule << std::endl;
>
>         Real NPV;
>         Rate fairRate;
>         Spread fairSpread;
>
>         boost::shared_ptr<PricingEngine> swapEngine(
>                          new
> DiscountingSwapEngine(discountingTermStructure));
>
>         spot5YearSwap.setPricingEngine(swapEngine);
>         oneYearForward5YearSwap.setPricingEngine(swapEngine);
>
>         // Of course, you're not forced to really use different curves
>         forecastingTermStructure.linkTo(depoSwapTermStructure);
>         discountingTermStructure.linkTo(depoSwapTermStructure);
>
>         NPV = spot5YearSwap.NPV();
>         fairSpread = spot5YearSwap.fairSpread();
>         fairRate = spot5YearSwap.fairRate();
>
>         std::cout << std::setw(headers[0].size())
>                   << "depo-swap" << separator;
>         std::cout << std::setw(headers[1].size())
>                   << std::fixed << std::setprecision(2) << NPV << separator;
>         std::cout << std::setw(headers[2].size())
>                   << io::rate(fairSpread) << separator;
>         std::cout << std::setw(headers[3].size())
>                   << io::rate(fairRate) << separator;
>         std::cout << std::endl;
>
>
>        
>         std::cout << rule << std::endl;
>
>         // now let's price the 1Y forward 5Y swap
>
>         std::cout << tab << "5-years, 1-year forward swap paying "
>                   << io::rate(fixedRate) << std::endl;
>         std::cout << headers[0] << separator
>                   << headers[1] << separator
>                   << headers[2] << separator
>                   << headers[3] << separator << std::endl;
>         std::cout << rule << std::endl;
>
>
>         forecastingTermStructure.linkTo(depoSwapTermStructure);
>         discountingTermStructure.linkTo(depoSwapTermStructure);
>
>         NPV = oneYearForward5YearSwap.NPV();
>         fairSpread = oneYearForward5YearSwap.fairSpread();
>         fairRate = oneYearForward5YearSwap.fairRate();
>
>         std::cout << std::setw(headers[0].size())
>                   << "depo-swap" << separator;
>         std::cout << std::setw(headers[1].size())
>                   << std::fixed << std::setprecision(2) << NPV << separator;
>         std::cout << std::setw(headers[2].size())
>                   << io::rate(fairSpread) << separator;
>         std::cout << std::setw(headers[3].size())
>                   << io::rate(fairRate) << separator;
>         std::cout << std::endl;
>
>
>                // now let's say that the 5-years swap rate goes up to 4.60%.
>         // A smarter market element--say, connected to a data source-- would
>         // notice the change itself. Since we're using SimpleQuotes,
>         // we'll have to change the value manually--which forces us to
>         // downcast the handle and use the SimpleQuote
>         // interface. In any case, the point here is that a change in the
>         // value contained in the Quote triggers a new bootstrapping
>         // of the curve and a repricing of the swap.
>
>         boost::shared_ptr<SimpleQuote> fiveYearsRate =
>             boost::dynamic_pointer_cast<SimpleQuote>(s5yRate);
>         fiveYearsRate->setValue(0.0460);
>
>         std::cout << dblrule << std::endl;
>         std::cout <<  "5-year market swap-rate = "
>                   << io::rate(s5yRate->value()) << std::endl;
>         std::cout << dblrule << std::endl;
>
>         std::cout << tab << "5-years swap paying "
>                   << io::rate(fixedRate) << std::endl;
>         std::cout << headers[0] << separator
>                   << headers[1] << separator
>                   << headers[2] << separator
>                   << headers[3] << separator << std::endl;
>         std::cout << rule << std::endl;
>
>         // now get the updated results
>         forecastingTermStructure.linkTo(depoSwapTermStructure);
>         discountingTermStructure.linkTo(depoSwapTermStructure);
>
>         NPV = spot5YearSwap.NPV();
>         fairSpread = spot5YearSwap.fairSpread();
>         fairRate = spot5YearSwap.fairRate();
>
>         std::cout << std::setw(headers[0].size())
>                   << "depo-swap" << separator;
>         std::cout << std::setw(headers[1].size())
>                   << std::fixed << std::setprecision(2) << NPV << separator;
>         std::cout << std::setw(headers[2].size())
>                   << io::rate(fairSpread) << separator;
>         std::cout << std::setw(headers[3].size())
>                   << io::rate(fairRate) << separator;
>         std::cout << std::endl;
>
>         QL_REQUIRE(std::fabs(fairRate-s5yRate->value())<1e-8,
>                    "5-years swap mispriced!");
>
>
>        
>         std::cout << rule << std::endl;
>
>         // the 1Y forward 5Y swap changes as well
>
>         std::cout << tab << "5-years, 1-year forward swap paying "
>                   << io::rate(fixedRate) << std::endl;
>         std::cout << headers[0] << separator
>                   << headers[1] << separator
>                   << headers[2] << separator
>                   << headers[3] << separator << std::endl;
>         std::cout << rule << std::endl;
>
>
>         forecastingTermStructure.linkTo(depoSwapTermStructure);
>         discountingTermStructure.linkTo(depoSwapTermStructure);
>
>         NPV = oneYearForward5YearSwap.NPV();
>         fairSpread = oneYearForward5YearSwap.fairSpread();
>         fairRate = oneYearForward5YearSwap.fairRate();
>
>         std::cout << std::setw(headers[0].size())
>                   << "depo-swap" << separator;
>         std::cout << std::setw(headers[1].size())
>                   << std::fixed << std::setprecision(2) << NPV << separator;
>         std::cout << std::setw(headers[2].size())
>                   << io::rate(fairSpread) << separator;
>         std::cout << std::setw(headers[3].size())
>                   << io::rate(fairRate) << separator;
>         std::cout << std::endl;
>
>
>        
>         Real seconds = timer.elapsed();
>         Integer hours = int(seconds/3600);
>         seconds -= hours * 3600;
>         Integer minutes = int(seconds/60);
>         seconds -= minutes * 60;
>         std::cout << " \nRun completed in ";
>         if (hours > 0)
>             std::cout << hours << " h ";
>         if (hours > 0 || minutes > 0)
>             std::cout << minutes << " m ";
>         std::cout << std::fixed << std::setprecision(0)
>                   << seconds << " s\n" << std::endl;
>
>         return 0;
>
>     } catch (std::exception& e) {
>         std::cerr << e.what() << std::endl;
>         return 1;
>     } catch (...) {
>         std::cerr << "unknown error" << std::endl;
>         return 1;
>     }
> }
>
>

--

This gubblick contains many nonsklarkish English flutzpahs, but the
overall pluggandisp can be glorked from context.
-- David Moser



------------------------------------------------------------------------------
What Every C/C++ and Fortran developer Should Know!
Read this article and learn how Intel has extended the reach of its
next-generation tools to help Windows* and Linux* C/C++ and Fortran
developers boost performance applications - including clusters.
http://p.sf.net/sfu/intel-dev2devmay
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users