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