Replication.cpp
This example uses the CompositeInstrument class to perform static replication of a down-and-out barrier option.
00001
00002
00020
00021
00022
00023
00024
00025
00026
00027
00028 #define BOOST_LIB_DIAGNOSTIC
00029 # include <ql/quantlib.hpp>
00030 #undef BOOST_LIB_DIAGNOSTIC
00031
00032 #ifdef BOOST_MSVC
00033
00034
00035
00036
00037
00038
00039
00040
00041 #endif
00042
00043 #include <boost/timer.hpp>
00044 #include <iostream>
00045 #include <iomanip>
00046
00047 using namespace QuantLib;
00048
00049 #if defined(QL_ENABLE_SESSIONS)
00050 namespace QuantLib {
00051
00052 Integer sessionId() { return 0; }
00053
00054 }
00055 #endif
00056
00057 int main(int, char* [])
00058 {
00059 try {
00060 QL_IO_INIT
00061
00062 boost::timer timer;
00063 std::cout << std::endl;
00064
00065 Date today(29, May, 2006);
00066 Settings::instance().evaluationDate() = today;
00067
00068
00069 Barrier::Type barrierType = Barrier::DownOut;
00070 Real barrier = 70.0;
00071 Real rebate = 0.0;
00072 Option::Type type = Option::Put;
00073 Real underlyingValue = 100.0;
00074 boost::shared_ptr<SimpleQuote> underlying(
00075 new SimpleQuote(underlyingValue));
00076 Real strike = 100.0;
00077 boost::shared_ptr<SimpleQuote> riskFreeRate(new SimpleQuote(0.04));
00078 boost::shared_ptr<SimpleQuote> volatility(new SimpleQuote(0.20));
00079 Date maturity = today + 1*Years;
00080
00081 std::cout << std::endl ;
00082
00083
00084 Size widths[] = { 45, 15, 15 };
00085 Size totalWidth = widths[0]+widths[1]+widths[2];
00086 std::string rule(totalWidth, '-'), dblrule(totalWidth, '=');
00087
00088 std::cout << dblrule << std::endl;
00089 std::cout << "Initial market conditions" << std::endl;
00090 std::cout << dblrule << std::endl;
00091 std::cout << std::setw(widths[0]) << std::left << "Option"
00092 << std::setw(widths[1]) << std::left << "NPV"
00093 << std::setw(widths[2]) << std::left << "Error"
00094 << std::endl;
00095 std::cout << rule << std::endl;
00096
00097
00098 DayCounter dayCounter = Actual365Fixed();
00099 Handle<Quote> h1(riskFreeRate);
00100 Handle<Quote> h2(volatility);
00101 Handle<YieldTermStructure> flatRate(
00102 boost::shared_ptr<YieldTermStructure>(
00103 new FlatForward(0, NullCalendar(),
00104 h1, dayCounter)));
00105 Handle<BlackVolTermStructure> flatVol(
00106 boost::shared_ptr<BlackVolTermStructure>(
00107 new BlackConstantVol(0, NullCalendar(),
00108 h2, dayCounter)));
00109
00110
00111 boost::shared_ptr<Exercise> exercise(
00112 new EuropeanExercise(maturity));
00113 boost::shared_ptr<StrikedTypePayoff> payoff(
00114 new PlainVanillaPayoff(type, strike));
00115
00116 boost::shared_ptr<StochasticProcess> stochasticProcess(
00117 new BlackScholesProcess(Handle<Quote>(underlying),
00118 flatRate, flatVol));
00119
00120 BarrierOption referenceOption(barrierType, barrier, rebate,
00121 stochasticProcess, payoff, exercise);
00122
00123 Real referenceValue = referenceOption.NPV();
00124
00125 std::cout << std::setw(widths[0]) << std::left
00126 << "Original barrier option"
00127 << std::fixed
00128 << std::setw(widths[1]) << std::left << referenceValue
00129 << std::setw(widths[2]) << std::left << "N/A"
00130 << std::endl;
00131
00132
00133 CompositeInstrument portfolio1, portfolio2, portfolio3;
00134
00135
00136
00137 boost::shared_ptr<Instrument> put1(
00138 new EuropeanOption(stochasticProcess, payoff, exercise));
00139 portfolio1.add(put1);
00140 portfolio2.add(put1);
00141 portfolio3.add(put1);
00142
00143 boost::shared_ptr<StrikedTypePayoff> digitalPayoff(
00144 new CashOrNothingPayoff(Option::Put, barrier, 1.0));
00145 boost::shared_ptr<Instrument> digitalPut(
00146 new EuropeanOption(stochasticProcess, digitalPayoff, exercise));
00147 portfolio1.subtract(digitalPut, strike-barrier);
00148 portfolio2.subtract(digitalPut, strike-barrier);
00149 portfolio3.subtract(digitalPut, strike-barrier);
00150
00151 boost::shared_ptr<StrikedTypePayoff> lowerPayoff(
00152 new PlainVanillaPayoff(Option::Put, barrier));
00153 boost::shared_ptr<Instrument> put2(
00154 new EuropeanOption(stochasticProcess, lowerPayoff, exercise));
00155 portfolio1.subtract(put2);
00156 portfolio2.subtract(put2);
00157 portfolio3.subtract(put2);
00158
00159
00160
00161
00162 Integer i;
00163 for (i=12; i>=1; i--) {
00164
00165 Date innerMaturity = today + i*Months;
00166 boost::shared_ptr<Exercise> innerExercise(
00167 new EuropeanExercise(innerMaturity));
00168 boost::shared_ptr<StrikedTypePayoff> innerPayoff(
00169 new PlainVanillaPayoff(Option::Put, barrier));
00170 boost::shared_ptr<Instrument> putn(
00171 new EuropeanOption(stochasticProcess,
00172 innerPayoff, innerExercise));
00173
00174
00175 Date killDate = today + (i-1)*Months;
00176 Settings::instance().evaluationDate() = killDate;
00177 underlying->setValue(barrier);
00178 Real portfolioValue = portfolio1.NPV();
00179 Real putValue = putn->NPV();
00180
00181
00182 Real notional = portfolioValue/putValue;
00183
00184
00185 portfolio1.subtract(putn, notional);
00186 }
00187
00188 Settings::instance().evaluationDate() = today;
00189 underlying->setValue(underlyingValue);
00190
00191 Real portfolioValue = portfolio1.NPV();
00192 Real error = portfolioValue - referenceValue;
00193 std::cout << std::setw(widths[0]) << std::left
00194 << "Replicating portfolio (12 dates)"
00195 << std::fixed
00196 << std::setw(widths[1]) << std::left << portfolioValue
00197 << std::setw(widths[2]) << std::left << error
00198 << std::endl;
00199
00200
00201
00202 for (i=52; i>=2; i-=2) {
00203
00204 Date innerMaturity = today + i*Weeks;
00205 boost::shared_ptr<Exercise> innerExercise(
00206 new EuropeanExercise(innerMaturity));
00207 boost::shared_ptr<StrikedTypePayoff> innerPayoff(
00208 new PlainVanillaPayoff(Option::Put, barrier));
00209 boost::shared_ptr<Instrument> putn(
00210 new EuropeanOption(stochasticProcess,
00211 innerPayoff, innerExercise));
00212 Date killDate = today + (i-2)*Weeks;
00213 Settings::instance().evaluationDate() = killDate;
00214 underlying->setValue(barrier);
00215 Real portfolioValue = portfolio2.NPV();
00216 Real putValue = putn->NPV();
00217 Real notional = portfolioValue/putValue;
00218 portfolio2.subtract(putn, notional);
00219 }
00220 Settings::instance().evaluationDate() = today;
00221 underlying->setValue(underlyingValue);
00222 portfolioValue = portfolio2.NPV();
00223 error = portfolioValue - referenceValue;
00224 std::cout << std::setw(widths[0]) << std::left
00225 << "Replicating portfolio (26 dates)"
00226 << std::fixed
00227 << std::setw(widths[1]) << std::left << portfolioValue
00228 << std::setw(widths[2]) << std::left << error
00229 << std::endl;
00230
00231
00232
00233 for (i=52; i>=1; i--) {
00234
00235 Date innerMaturity = today + i*Weeks;
00236 boost::shared_ptr<Exercise> innerExercise(
00237 new EuropeanExercise(innerMaturity));
00238 boost::shared_ptr<StrikedTypePayoff> innerPayoff(
00239 new PlainVanillaPayoff(Option::Put, barrier));
00240 boost::shared_ptr<Instrument> putn(
00241 new EuropeanOption(stochasticProcess,
00242 innerPayoff, innerExercise));
00243 Date killDate = today + (i-1)*Weeks;
00244 Settings::instance().evaluationDate() = killDate;
00245 underlying->setValue(barrier);
00246 Real portfolioValue = portfolio3.NPV();
00247 Real putValue = putn->NPV();
00248 Real notional = portfolioValue/putValue;
00249 portfolio3.subtract(putn, notional);
00250 }
00251 Settings::instance().evaluationDate() = today;
00252 underlying->setValue(underlyingValue);
00253 portfolioValue = portfolio3.NPV();
00254 error = portfolioValue - referenceValue;
00255 std::cout << std::setw(widths[0]) << std::left
00256 << "Replicating portfolio (52 dates)"
00257 << std::fixed
00258 << std::setw(widths[1]) << std::left << portfolioValue
00259 << std::setw(widths[2]) << std::left << error
00260 << std::endl;
00261
00262
00263
00264
00265 std::cout << dblrule << std::endl;
00266 std::cout << "Modified market conditions: out of the money"
00267 << std::endl;
00268 std::cout << dblrule << std::endl;
00269 std::cout << std::setw(widths[0]) << std::left << "Option"
00270 << std::setw(widths[1]) << std::left << "NPV"
00271 << std::setw(widths[2]) << std::left << "Error"
00272 << std::endl;
00273 std::cout << rule << std::endl;
00274
00275 underlying->setValue(110.0);
00276
00277 referenceValue = referenceOption.NPV();
00278 std::cout << std::setw(widths[0]) << std::left
00279 << "Original barrier option"
00280 << std::fixed
00281 << std::setw(widths[1]) << std::left << referenceValue
00282 << std::setw(widths[2]) << std::left << "N/A"
00283 << std::endl;
00284 portfolioValue = portfolio1.NPV();
00285 error = portfolioValue - referenceValue;
00286 std::cout << std::setw(widths[0]) << std::left
00287 << "Replicating portfolio (12 dates)"
00288 << std::fixed
00289 << std::setw(widths[1]) << std::left << portfolioValue
00290 << std::setw(widths[2]) << std::left << error
00291 << std::endl;
00292 portfolioValue = portfolio2.NPV();
00293 error = portfolioValue - referenceValue;
00294 std::cout << std::setw(widths[0]) << std::left
00295 << "Replicating portfolio (26 dates)"
00296 << std::fixed
00297 << std::setw(widths[1]) << std::left << portfolioValue
00298 << std::setw(widths[2]) << std::left << error
00299 << std::endl;
00300 portfolioValue = portfolio3.NPV();
00301 error = portfolioValue - referenceValue;
00302 std::cout << std::setw(widths[0]) << std::left
00303 << "Replicating portfolio (52 dates)"
00304 << std::fixed
00305 << std::setw(widths[1]) << std::left << portfolioValue
00306 << std::setw(widths[2]) << std::left << error
00307 << std::endl;
00308
00309
00310
00311 std::cout << dblrule << std::endl;
00312 std::cout << "Modified market conditions: in the money" << std::endl;
00313 std::cout << dblrule << std::endl;
00314 std::cout << std::setw(widths[0]) << std::left << "Option"
00315 << std::setw(widths[1]) << std::left << "NPV"
00316 << std::setw(widths[2]) << std::left << "Error"
00317 << std::endl;
00318 std::cout << rule << std::endl;
00319
00320 underlying->setValue(90.0);
00321
00322 referenceValue = referenceOption.NPV();
00323 std::cout << std::setw(widths[0]) << std::left
00324 << "Original barrier option"
00325 << std::fixed
00326 << std::setw(widths[1]) << std::left << referenceValue
00327 << std::setw(widths[2]) << std::left << "N/A"
00328 << std::endl;
00329 portfolioValue = portfolio1.NPV();
00330 error = portfolioValue - referenceValue;
00331 std::cout << std::setw(widths[0]) << std::left
00332 << "Replicating portfolio (12 dates)"
00333 << std::fixed
00334 << std::setw(widths[1]) << std::left << portfolioValue
00335 << std::setw(widths[2]) << std::left << error
00336 << std::endl;
00337 portfolioValue = portfolio2.NPV();
00338 error = portfolioValue - referenceValue;
00339 std::cout << std::setw(widths[0]) << std::left
00340 << "Replicating portfolio (26 dates)"
00341 << std::fixed
00342 << std::setw(widths[1]) << std::left << portfolioValue
00343 << std::setw(widths[2]) << std::left << error
00344 << std::endl;
00345 portfolioValue = portfolio3.NPV();
00346 error = portfolioValue - referenceValue;
00347 std::cout << std::setw(widths[0]) << std::left
00348 << "Replicating portfolio (52 dates)"
00349 << std::fixed
00350 << std::setw(widths[1]) << std::left << portfolioValue
00351 << std::setw(widths[2]) << std::left << error
00352 << std::endl;
00353
00354
00355
00356 std::cout << dblrule << std::endl;
00357 std::cout
00358 << std::endl
00359 << "The replication seems to be less robust when volatility and \n"
00360 << "risk-free rate are changed. Feel free to experiment with \n"
00361 << "the example and contribute a patch if you spot any errors."
00362 << std::endl;
00363
00364 Real seconds = timer.elapsed();
00365 Integer hours = int(seconds/3600);
00366 seconds -= hours * 3600;
00367 Integer minutes = int(seconds/60);
00368 seconds -= minutes * 60;
00369 std::cout << " \nRun completed in ";
00370 if (hours > 0)
00371 std::cout << hours << " h ";
00372 if (hours > 0 || minutes > 0)
00373 std::cout << minutes << " m ";
00374 std::cout << std::fixed << std::setprecision(0)
00375 << seconds << " s\n" << std::endl;
00376
00377 return 0;
00378 } catch (std::exception& e) {
00379 std::cout << e.what() << std::endl;
00380 return 1;
00381 } catch (...) {
00382 std::cout << "unknown error" << std::endl;
00383 return 1;
00384 }
00385 }