1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
Copyright (C) 2015 Peter Caspers
This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
<quantlib-dev@lists.sf.net>. The license is also available online at
<http://quantlib.org/license.shtml>.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
#include <ql/instruments/makecapfloor.hpp>
#include <ql/instruments/makeswaption.hpp>
#include <ql/pricingengines/blackformula.hpp>
#include <ql/termstructures/volatility/gaussian1dsmilesection.hpp>
#include <utility>
using std::sqrt;
namespace QuantLib {
Gaussian1dSmileSection::Gaussian1dSmileSection(
const Date& fixingDate,
ext::shared_ptr<SwapIndex> swapIndex,
const ext::shared_ptr<Gaussian1dModel>& model,
const DayCounter& dc,
const ext::shared_ptr<Gaussian1dSwaptionEngine>& swaptionEngine)
: SmileSection(fixingDate, dc, model->termStructure()->referenceDate()),
fixingDate_(fixingDate), swapIndex_(std::move(swapIndex)), model_(model),
engine_(swaptionEngine) {
atm_ = model_->swapRate(fixingDate_, swapIndex_->tenor(), Null<Date>(), 0.0, swapIndex_);
annuity_ =
model_->swapAnnuity(fixingDate_, swapIndex_->tenor(), Null<Date>(), 0.0, swapIndex_);
if (engine_ == nullptr) {
engine_ = ext::make_shared<Gaussian1dSwaptionEngine>(
model_, 64, 7.0, true, false, swapIndex_->discountingTermStructure());
}
}
Gaussian1dSmileSection::Gaussian1dSmileSection(
const Date& fixingDate,
ext::shared_ptr<IborIndex> iborIndex,
const ext::shared_ptr<Gaussian1dModel>& model,
const DayCounter& dc,
const ext::shared_ptr<Gaussian1dCapFloorEngine>& capEngine)
: SmileSection(fixingDate, dc, model->termStructure()->referenceDate()),
fixingDate_(fixingDate), iborIndex_(std::move(iborIndex)), model_(model), engine_(capEngine) {
atm_ = model_->forwardRate(fixingDate_, Null<Date>(), 0.0, iborIndex_);
CapFloor c =
MakeCapFloor(CapFloor::Cap, iborIndex_->tenor(), iborIndex_, Null<Real>(), 0 * Days)
.withEffectiveDate(fixingDate_, false);
annuity_ = iborIndex_->dayCounter().yearFraction(c.startDate(), c.maturityDate()) *
model_->zerobond(c.maturityDate());
if (engine_ == nullptr) {
engine_ = ext::make_shared<Gaussian1dCapFloorEngine>(
model_, 64, 7.0, true,
false); // use model curve as discounting curve
}
}
Real Gaussian1dSmileSection::atmLevel() const { return atm_; }
Real Gaussian1dSmileSection::optionPrice(Rate strike, Option::Type type,
Real discount) const {
if (swapIndex_ != nullptr) {
Swaption s = MakeSwaption(swapIndex_, fixingDate_, strike)
.withUnderlyingType(type == Option::Call
? Swap::Payer
: Swap::Receiver)
.withPricingEngine(engine_);
Real tmp = s.NPV();
return tmp / annuity_ * discount;
} else {
CapFloor c =
MakeCapFloor(type == Option::Call ? CapFloor::Cap : CapFloor::Floor,
iborIndex_->tenor(), iborIndex_, strike, 0 * Days)
.withEffectiveDate(fixingDate_, false)
.withPricingEngine(engine_);
Real tmp = c.NPV();
return tmp / annuity_ * discount;
}
}
Real Gaussian1dSmileSection::volatilityImpl(Rate strike) const {
Real vol = 0.0;
try {
Option::Type type = strike >= atm_ ? Option::Call : Option::Put;
Real o = optionPrice(strike, type);
vol = blackFormulaImpliedStdDev(type, strike, atm_, o) /
sqrt(exerciseTime());
} catch (...) {
}
return vol;
}
}
|