/src/quantlib/ql/experimental/swaptions/irregularswaption.cpp
Line | Count | Source |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2001, 2002, 2003 Sadruddin Rejeb |
5 | | Copyright (C) 2006 Cristina Duminuco |
6 | | Copyright (C) 2006 Marco Bianchetti |
7 | | Copyright (C) 2007 StatPro Italia srl |
8 | | Copyright (C) 2010 Andre Miemiec |
9 | | |
10 | | This file is part of QuantLib, a free-software/open-source library |
11 | | for financial quantitative analysts and developers - http://quantlib.org/ |
12 | | |
13 | | QuantLib is free software: you can redistribute it and/or modify it |
14 | | under the terms of the QuantLib license. You should have received a |
15 | | copy of the license along with this program; if not, please email |
16 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
17 | | <https://www.quantlib.org/license.shtml>. |
18 | | |
19 | | This program is distributed in the hope that it will be useful, but WITHOUT |
20 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
21 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
22 | | */ |
23 | | |
24 | | #include <ql/any.hpp> |
25 | | #include <ql/exercise.hpp> |
26 | | #include <ql/experimental/swaptions/irregularswaption.hpp> |
27 | | #include <ql/math/solvers1d/newtonsafe.hpp> |
28 | | #include <ql/pricingengines/swaption/blackswaptionengine.hpp> |
29 | | #include <ql/quotes/simplequote.hpp> |
30 | | #include <utility> |
31 | | |
32 | | namespace QuantLib { |
33 | | |
34 | | namespace { |
35 | | |
36 | | class IrregularImpliedVolHelper { |
37 | | public: |
38 | | IrregularImpliedVolHelper(const IrregularSwaption&, |
39 | | Handle<YieldTermStructure> discountCurve, |
40 | | Real targetValue); |
41 | | Real operator()(Volatility x) const; |
42 | | Real derivative(Volatility x) const; |
43 | | private: |
44 | | ext::shared_ptr<PricingEngine> engine_; |
45 | | Handle<YieldTermStructure> discountCurve_; |
46 | | Real targetValue_; |
47 | | ext::shared_ptr<SimpleQuote> vol_; |
48 | | const Instrument::results* results_; |
49 | | }; |
50 | | |
51 | | IrregularImpliedVolHelper::IrregularImpliedVolHelper( |
52 | | const IrregularSwaption& swaption, |
53 | | Handle<YieldTermStructure> discountCurve, |
54 | | Real targetValue) |
55 | 0 | : discountCurve_(std::move(discountCurve)), targetValue_(targetValue), |
56 | 0 | vol_(ext::make_shared<SimpleQuote>(-1.0)) { |
57 | |
|
58 | 0 | Handle<Quote> h(vol_); |
59 | 0 | engine_ = ext::shared_ptr<PricingEngine>(new |
60 | 0 | BlackSwaptionEngine(discountCurve_, h)); |
61 | 0 | swaption.setupArguments(engine_->getArguments()); |
62 | |
|
63 | 0 | results_ = |
64 | 0 | dynamic_cast<const Instrument::results*>(engine_->getResults()); |
65 | 0 | } |
66 | | |
67 | 0 | Real IrregularImpliedVolHelper::operator()(Volatility x) const { |
68 | 0 | if (x!=vol_->value()) { |
69 | 0 | vol_->setValue(x); |
70 | 0 | engine_->calculate(); |
71 | 0 | } |
72 | 0 | return results_->value-targetValue_; |
73 | 0 | } |
74 | | |
75 | 0 | Real IrregularImpliedVolHelper::derivative(Volatility x) const { |
76 | 0 | if (x!=vol_->value()) { |
77 | 0 | vol_->setValue(x); |
78 | 0 | engine_->calculate(); |
79 | 0 | } |
80 | 0 | auto vega_ = results_->additionalResults.find("vega"); |
81 | 0 | QL_REQUIRE(vega_ != results_->additionalResults.end(), |
82 | 0 | "vega not provided"); |
83 | 0 | return ext::any_cast<Real>(vega_->second); |
84 | 0 | } |
85 | | } |
86 | | |
87 | | std::ostream& operator<<(std::ostream& out, |
88 | 0 | IrregularSettlement::Type t) { |
89 | 0 | switch (t) { |
90 | 0 | case IrregularSettlement::Physical: |
91 | 0 | return out << "Delivery"; |
92 | 0 | case IrregularSettlement::Cash: |
93 | 0 | return out << "Cash"; |
94 | 0 | default: |
95 | 0 | QL_FAIL("unknown IrregularSettlement::Type(" << Integer(t) << ")"); |
96 | 0 | } |
97 | 0 | } |
98 | | |
99 | | IrregularSwaption::IrregularSwaption(ext::shared_ptr<IrregularSwap> swap, |
100 | | const ext::shared_ptr<Exercise>& exercise, |
101 | | IrregularSettlement::Type delivery) |
102 | 0 | : Option(ext::shared_ptr<Payoff>(), exercise), swap_(std::move(swap)), |
103 | 0 | settlementType_(delivery) { |
104 | 0 | registerWith(swap_); |
105 | 0 | } Unexecuted instantiation: QuantLib::IrregularSwaption::IrregularSwaption(boost::shared_ptr<QuantLib::IrregularSwap>, boost::shared_ptr<QuantLib::Exercise> const&, QuantLib::IrregularSettlement::Type) Unexecuted instantiation: QuantLib::IrregularSwaption::IrregularSwaption(boost::shared_ptr<QuantLib::IrregularSwap>, boost::shared_ptr<QuantLib::Exercise> const&, QuantLib::IrregularSettlement::Type) |
106 | | |
107 | 0 | bool IrregularSwaption::isExpired() const { |
108 | 0 | return detail::simple_event(exercise_->dates().back()).hasOccurred(); |
109 | 0 | } |
110 | | |
111 | 0 | void IrregularSwaption::setupArguments(PricingEngine::arguments* args) const { |
112 | |
|
113 | 0 | swap_->setupArguments(args); |
114 | |
|
115 | 0 | auto* arguments = dynamic_cast<IrregularSwaption::arguments*>(args); |
116 | |
|
117 | 0 | QL_REQUIRE(arguments != nullptr, "wrong argument type"); |
118 | | |
119 | 0 | arguments->swap = swap_; |
120 | 0 | arguments->settlementType = settlementType_; |
121 | 0 | arguments->exercise = exercise_; |
122 | 0 | } |
123 | | |
124 | 0 | void IrregularSwaption::arguments::validate() const { |
125 | 0 | IrregularSwap::arguments::validate(); |
126 | 0 | QL_REQUIRE(swap, "Irregular swap not set"); |
127 | 0 | QL_REQUIRE(exercise, "exercise not set"); |
128 | 0 | } |
129 | | |
130 | | Volatility IrregularSwaption::impliedVolatility( |
131 | | Real targetValue, |
132 | | const Handle<YieldTermStructure>& discountCurve, |
133 | | Volatility guess, |
134 | | Real accuracy, |
135 | | Natural maxEvaluations, |
136 | | Volatility minVol, |
137 | 0 | Volatility maxVol) const { |
138 | 0 | calculate(); |
139 | 0 | QL_REQUIRE(!isExpired(), "instrument expired"); |
140 | | |
141 | 0 | IrregularImpliedVolHelper f(*this, discountCurve, targetValue); |
142 | | //Brent solver; |
143 | 0 | NewtonSafe solver; |
144 | 0 | solver.setMaxEvaluations(maxEvaluations); |
145 | 0 | return solver.solve(f, accuracy, guess, minVol, maxVol); |
146 | 0 | } |
147 | | |
148 | | } |