| 1 | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| 2 | |
| 3 | /*! |
| 4 | Copyright (C) 2006 Allen Kuo |
| 5 | |
| 6 | This file is part of QuantLib, a free-software/open-source library |
| 7 | for financial quantitative analysts and developers - http://quantlib.org/ |
| 8 | |
| 9 | QuantLib is free software: you can redistribute it and/or modify it |
| 10 | under the terms of the QuantLib license. You should have received a |
| 11 | copy of the license along with this program; if not, please email |
| 12 | <quantlib-dev@lists.sf.net>. The license is also available online at |
| 13 | <http://quantlib.org/license.shtml>. |
| 14 | |
| 15 | This program is distributed in the hope that it will be useful, but WITHOUT |
| 16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 17 | FOR A PARTICULAR PURPOSE. See the license for more details. |
| 18 | */ |
| 19 | |
| 20 | /* This example shows how to set up a term structure and price a simple |
| 21 | forward-rate agreement. |
| 22 | */ |
| 23 | |
| 24 | #include <ql/qldefines.hpp> |
| 25 | #if !defined(BOOST_ALL_NO_LIB) && defined(BOOST_MSVC) |
| 26 | # include <ql/auto_link.hpp> |
| 27 | #endif |
| 28 | #include <ql/instruments/forwardrateagreement.hpp> |
| 29 | #include <ql/termstructures/yield/piecewiseyieldcurve.hpp> |
| 30 | #include <ql/termstructures/yield/ratehelpers.hpp> |
| 31 | #include <ql/indexes/ibor/euribor.hpp> |
| 32 | #include <ql/time/daycounters/actualactual.hpp> |
| 33 | |
| 34 | #include <iostream> |
| 35 | |
| 36 | #define LENGTH(a) (sizeof(a)/sizeof(a[0])) |
| 37 | |
| 38 | using namespace std; |
| 39 | using namespace QuantLib; |
| 40 | |
| 41 | int main(int, char* []) { |
| 42 | |
| 43 | try { |
| 44 | |
| 45 | std::cout << std::endl; |
| 46 | |
| 47 | /********************* |
| 48 | *** MARKET DATA *** |
| 49 | *********************/ |
| 50 | |
| 51 | RelinkableHandle<YieldTermStructure> euriborTermStructure; |
| 52 | auto euribor3m = ext::make_shared<Euribor3M>(args&: euriborTermStructure); |
| 53 | |
| 54 | Date todaysDate = Date(23, May, 2006); |
| 55 | Settings::instance().evaluationDate() = todaysDate; |
| 56 | |
| 57 | Calendar calendar = euribor3m->fixingCalendar(); |
| 58 | Integer fixingDays = euribor3m->fixingDays(); |
| 59 | Date settlementDate = calendar.advance(todaysDate, n: fixingDays, unit: Days); |
| 60 | |
| 61 | std::cout << "Today: " << todaysDate.weekday() |
| 62 | << ", " << todaysDate << std::endl; |
| 63 | |
| 64 | std::cout << "Settlement date: " << settlementDate.weekday() |
| 65 | << ", " << settlementDate << std::endl; |
| 66 | |
| 67 | |
| 68 | // 3 month term FRA quotes (index refers to monthsToStart) |
| 69 | Rate threeMonthFraQuote[10]; |
| 70 | |
| 71 | threeMonthFraQuote[1]=0.030; |
| 72 | threeMonthFraQuote[2]=0.031; |
| 73 | threeMonthFraQuote[3]=0.032; |
| 74 | threeMonthFraQuote[6]=0.033; |
| 75 | threeMonthFraQuote[9]=0.034; |
| 76 | |
| 77 | /******************** |
| 78 | *** QUOTES *** |
| 79 | ********************/ |
| 80 | |
| 81 | // SimpleQuote stores a value which can be manually changed; |
| 82 | // other Quote subclasses could read the value from a database |
| 83 | // or some kind of data feed. |
| 84 | |
| 85 | |
| 86 | // FRAs |
| 87 | auto fra1x4Rate = ext::make_shared<SimpleQuote>(args&: threeMonthFraQuote[1]); |
| 88 | auto fra2x5Rate = ext::make_shared<SimpleQuote>(args&: threeMonthFraQuote[2]); |
| 89 | auto fra3x6Rate = ext::make_shared<SimpleQuote>(args&: threeMonthFraQuote[3]); |
| 90 | auto fra6x9Rate = ext::make_shared<SimpleQuote>(args&: threeMonthFraQuote[6]); |
| 91 | auto fra9x12Rate = ext::make_shared<SimpleQuote>(args&: threeMonthFraQuote[9]); |
| 92 | |
| 93 | RelinkableHandle<Quote> h1x4; h1x4.linkTo(h: fra1x4Rate); |
| 94 | RelinkableHandle<Quote> h2x5; h2x5.linkTo(h: fra2x5Rate); |
| 95 | RelinkableHandle<Quote> h3x6; h3x6.linkTo(h: fra3x6Rate); |
| 96 | RelinkableHandle<Quote> h6x9; h6x9.linkTo(h: fra6x9Rate); |
| 97 | RelinkableHandle<Quote> h9x12; h9x12.linkTo(h: fra9x12Rate); |
| 98 | |
| 99 | /********************* |
| 100 | *** RATE HELPERS *** |
| 101 | *********************/ |
| 102 | |
| 103 | // RateHelpers are built from the above quotes together with |
| 104 | // other instrument dependant infos. Quotes are passed in |
| 105 | // relinkable handles which could be relinked to some other |
| 106 | // data source later. |
| 107 | |
| 108 | DayCounter fraDayCounter = euribor3m->dayCounter(); |
| 109 | BusinessDayConvention convention = euribor3m->businessDayConvention(); |
| 110 | bool endOfMonth = euribor3m->endOfMonth(); |
| 111 | |
| 112 | auto fra1x4 = ext::make_shared<FraRateHelper>(args&: h1x4, args: 1, args: 4, |
| 113 | args&: fixingDays, args&: calendar, args&: convention, |
| 114 | args&: endOfMonth, args&: fraDayCounter); |
| 115 | |
| 116 | auto fra2x5 = ext::make_shared<FraRateHelper>(args&: h2x5, args: 2, args: 5, |
| 117 | args&: fixingDays, args&: calendar, args&: convention, |
| 118 | args&: endOfMonth, args&: fraDayCounter); |
| 119 | |
| 120 | auto fra3x6 = ext::make_shared<FraRateHelper>(args&: h3x6, args: 3, args: 6, |
| 121 | args&: fixingDays, args&: calendar, args&: convention, |
| 122 | args&: endOfMonth, args&: fraDayCounter); |
| 123 | |
| 124 | auto fra6x9 = ext::make_shared<FraRateHelper>(args&: h6x9, args: 6, args: 9, |
| 125 | args&: fixingDays, args&: calendar, args&: convention, |
| 126 | args&: endOfMonth, args&: fraDayCounter); |
| 127 | |
| 128 | auto fra9x12 = ext::make_shared<FraRateHelper>(args&: h9x12, args: 9, args: 12, |
| 129 | args&: fixingDays, args&: calendar, args&: convention, |
| 130 | args&: endOfMonth, args&: fraDayCounter); |
| 131 | |
| 132 | |
| 133 | /********************* |
| 134 | ** CURVE BUILDING ** |
| 135 | *********************/ |
| 136 | |
| 137 | // Any DayCounter would be fine. |
| 138 | // ActualActual::ISDA ensures that 30 years is 30.0 |
| 139 | DayCounter termStructureDayCounter = |
| 140 | ActualActual(ActualActual::ISDA); |
| 141 | |
| 142 | // A FRA curve |
| 143 | std::vector<ext::shared_ptr<RateHelper>> fraInstruments; |
| 144 | |
| 145 | fraInstruments.push_back(x: fra1x4); |
| 146 | fraInstruments.push_back(x: fra2x5); |
| 147 | fraInstruments.push_back(x: fra3x6); |
| 148 | fraInstruments.push_back(x: fra6x9); |
| 149 | fraInstruments.push_back(x: fra9x12); |
| 150 | |
| 151 | auto fraTermStructure = ext::make_shared<PiecewiseYieldCurve<Discount, LogLinear>>( |
| 152 | args&: settlementDate, args&: fraInstruments, |
| 153 | args&: termStructureDayCounter); |
| 154 | |
| 155 | /*********************** |
| 156 | *** construct FRA's *** |
| 157 | ***********************/ |
| 158 | |
| 159 | Calendar fraCalendar = euribor3m->fixingCalendar(); |
| 160 | BusinessDayConvention fraBusinessDayConvention = |
| 161 | euribor3m->businessDayConvention(); |
| 162 | Position::Type fraFwdType = Position::Long; |
| 163 | Real fraNotional = 100.0; |
| 164 | Integer monthsToStart[] = { 1, 2, 3, 6, 9 }; |
| 165 | |
| 166 | euriborTermStructure.linkTo(h: fraTermStructure); |
| 167 | |
| 168 | cout << endl; |
| 169 | cout << "Test FRA construction, NPV calculation, and FRA purchase" |
| 170 | << endl |
| 171 | << endl; |
| 172 | |
| 173 | Size i; |
| 174 | for (i=0; i<LENGTH(monthsToStart); i++) { |
| 175 | |
| 176 | Date fraValueDate = fraCalendar.advance( |
| 177 | settlementDate,n: monthsToStart[i],unit: Months, |
| 178 | convention: fraBusinessDayConvention); |
| 179 | |
| 180 | Rate fraStrikeRate = threeMonthFraQuote[monthsToStart[i]]; |
| 181 | |
| 182 | ForwardRateAgreement myFRA(euribor3m, fraValueDate, |
| 183 | fraFwdType,fraStrikeRate, |
| 184 | fraNotional); |
| 185 | |
| 186 | cout << "3m Term FRA, Months to Start: " |
| 187 | << monthsToStart[i] |
| 188 | << endl; |
| 189 | cout << "strike FRA rate: " |
| 190 | << io::rate(r: fraStrikeRate) |
| 191 | << endl; |
| 192 | cout << "FRA 3m forward rate: " |
| 193 | << myFRA.forwardRate() |
| 194 | << endl; |
| 195 | cout << "FRA market quote: " |
| 196 | << io::rate(r: threeMonthFraQuote[monthsToStart[i]]) |
| 197 | << endl; |
| 198 | cout << "FRA amount [should be zero]: " |
| 199 | << myFRA.amount() |
| 200 | << endl; |
| 201 | cout << "FRA NPV [should be zero]: " |
| 202 | << myFRA.NPV() |
| 203 | << endl |
| 204 | << endl; |
| 205 | |
| 206 | } |
| 207 | |
| 208 | |
| 209 | |
| 210 | |
| 211 | cout << endl << endl; |
| 212 | cout << "Now take a 100 basis-point upward shift in FRA quotes " |
| 213 | << "and examine NPV" |
| 214 | << endl |
| 215 | << endl; |
| 216 | |
| 217 | const Real BpsShift = 0.01; |
| 218 | |
| 219 | threeMonthFraQuote[1]=0.030+BpsShift; |
| 220 | threeMonthFraQuote[2]=0.031+BpsShift; |
| 221 | threeMonthFraQuote[3]=0.032+BpsShift; |
| 222 | threeMonthFraQuote[6]=0.033+BpsShift; |
| 223 | threeMonthFraQuote[9]=0.034+BpsShift; |
| 224 | |
| 225 | fra1x4Rate->setValue(threeMonthFraQuote[1]); |
| 226 | fra2x5Rate->setValue(threeMonthFraQuote[2]); |
| 227 | fra3x6Rate->setValue(threeMonthFraQuote[3]); |
| 228 | fra6x9Rate->setValue(threeMonthFraQuote[6]); |
| 229 | fra9x12Rate->setValue(threeMonthFraQuote[9]); |
| 230 | |
| 231 | |
| 232 | for (i=0; i<LENGTH(monthsToStart); i++) { |
| 233 | |
| 234 | Date fraValueDate = fraCalendar.advance( |
| 235 | settlementDate,n: monthsToStart[i],unit: Months, |
| 236 | convention: fraBusinessDayConvention); |
| 237 | |
| 238 | Rate fraStrikeRate = |
| 239 | threeMonthFraQuote[monthsToStart[i]] - BpsShift; |
| 240 | |
| 241 | ForwardRateAgreement myFRA(euribor3m, fraValueDate, |
| 242 | fraFwdType, fraStrikeRate, |
| 243 | fraNotional); |
| 244 | |
| 245 | cout << "3m Term FRA, 100 notional, Months to Start = " |
| 246 | << monthsToStart[i] |
| 247 | << endl; |
| 248 | cout << "strike FRA rate: " |
| 249 | << io::rate(r: fraStrikeRate) |
| 250 | << endl; |
| 251 | cout << "FRA 3m forward rate: " |
| 252 | << myFRA.forwardRate() |
| 253 | << endl; |
| 254 | cout << "FRA market quote: " |
| 255 | << io::rate(r: threeMonthFraQuote[monthsToStart[i]]) |
| 256 | << endl; |
| 257 | cout << "FRA amount [should be positive]: " |
| 258 | << myFRA.amount() |
| 259 | << endl; |
| 260 | cout << "FRA NPV [should be positive]: " |
| 261 | << myFRA.NPV() |
| 262 | << endl |
| 263 | << endl; |
| 264 | } |
| 265 | |
| 266 | return 0; |
| 267 | |
| 268 | } catch (exception& e) { |
| 269 | cerr << e.what() << endl; |
| 270 | return 1; |
| 271 | } catch (...) { |
| 272 | cerr << "unknown error" << endl; |
| 273 | return 1; |
| 274 | } |
| 275 | } |
| 276 | |
| 277 | |