Coverage Report

Created: 2025-08-05 06:45

/src/quantlib/ql/termstructures/volatility/optionlet/optionletstripper.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2007 Ferdinando Ametrano
5
 Copyright (C) 2007 Giorgio Facchinetti
6
 Copyright (C) 2015 Peter Caspers
7
8
 This file is part of QuantLib, a free-software/open-source library
9
 for financial quantitative analysts and developers - http://quantlib.org/
10
11
 QuantLib is free software: you can redistribute it and/or modify it
12
 under the terms of the QuantLib license.  You should have received a
13
 copy of the license along with this program; if not, please email
14
 <quantlib-dev@lists.sf.net>. The license is also available online at
15
 <http://quantlib.org/license.shtml>.
16
17
 This program is distributed in the hope that it will be useful, but WITHOUT
18
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 FOR A PARTICULAR PURPOSE.  See the license for more details.
20
*/
21
22
#include <ql/indexes/iborindex.hpp>
23
#include <ql/termstructures/volatility/optionlet/optionletstripper.hpp>
24
#include <utility>
25
26
using std::vector;
27
28
namespace QuantLib {
29
30
    OptionletStripper::OptionletStripper(
31
        const ext::shared_ptr<CapFloorTermVolSurface>& termVolSurface,
32
        ext::shared_ptr<IborIndex> iborIndex,
33
        Handle<YieldTermStructure> discount,
34
        const VolatilityType type,
35
        const Real displacement,
36
        ext::optional<Period> optionletFrequency
37
    )
38
0
    : termVolSurface_(termVolSurface), iborIndex_(std::move(iborIndex)),
39
0
      discount_(std::move(discount)), nStrikes_(termVolSurface->strikes().size()),
40
0
      volatilityType_(type), displacement_(displacement), 
41
0
      optionletFrequency_(optionletFrequency) {
42
43
0
        if (volatilityType_ == Normal) {
44
0
            QL_REQUIRE(displacement_ == 0.0,
45
0
                       "non-null displacement is not allowed with Normal model");
46
0
        }
47
48
0
        if (ext::dynamic_pointer_cast<OvernightIndex>(iborIndex_)) {
49
0
            QL_REQUIRE(optionletFrequency_, 
50
0
                       "an optionlet frequency is required when using an overnight index");
51
0
        }
52
53
0
        registerWith(termVolSurface);
54
0
        registerWith(iborIndex_);
55
0
        registerWith(discount_);
56
0
        registerWith(Settings::instance().evaluationDate());
57
58
0
        Period indexTenor = optionletFrequency_ ? *optionletFrequency_ : iborIndex_->tenor();
59
0
        Period maxCapFloorTenor = termVolSurface->optionTenors().back();
60
61
        // optionlet tenors and capFloor lengths
62
0
        optionletTenors_.push_back(indexTenor);
63
0
        capFloorLengths_.push_back(optionletTenors_.back()+indexTenor);
64
0
        QL_REQUIRE(maxCapFloorTenor>=capFloorLengths_.back(),
65
0
                   "too short (" << maxCapFloorTenor <<
66
0
                   ") capfloor term vol termVolSurface");
67
0
        Period nextCapFloorLength = capFloorLengths_.back()+indexTenor;
68
0
        while (nextCapFloorLength<=maxCapFloorTenor) {
69
0
            optionletTenors_.push_back(capFloorLengths_.back());
70
0
            capFloorLengths_.push_back(nextCapFloorLength);
71
0
            nextCapFloorLength += indexTenor;
72
0
        }
73
0
        nOptionletTenors_ = optionletTenors_.size();
74
        
75
0
        optionletVolatilities_ =
76
0
            vector<vector<Volatility> >(nOptionletTenors_, 
77
0
                                        vector<Volatility>(nStrikes_));
78
0
        optionletStrikes_ = vector<vector<Rate> >(nOptionletTenors_,
79
0
                                                  termVolSurface->strikes());
80
0
        optionletDates_ = vector<Date>(nOptionletTenors_);
81
0
        optionletTimes_ = vector<Time>(nOptionletTenors_);
82
0
        atmOptionletRate_ = vector<Rate>(nOptionletTenors_);
83
0
        optionletPaymentDates_ = vector<Date>(nOptionletTenors_);
84
0
        optionletAccrualPeriods_ = vector<Time>(nOptionletTenors_);
85
0
    }
86
87
0
    const vector<Rate>& OptionletStripper::optionletStrikes(Size i) const {
88
0
        calculate();
89
0
        QL_REQUIRE(i<optionletStrikes_.size(),
90
0
                   "index (" << i <<
91
0
                   ") must be less than optionletStrikes size (" <<
92
0
                   optionletStrikes_.size() << ")");
93
0
        return optionletStrikes_[i];
94
0
    }   
95
96
    const vector<Volatility>&
97
0
    OptionletStripper::optionletVolatilities(Size i) const {
98
0
        calculate();
99
0
        QL_REQUIRE(i<optionletVolatilities_.size(),
100
0
                   "index (" << i <<
101
0
                   ") must be less than optionletVolatilities size (" <<
102
0
                   optionletVolatilities_.size() << ")");
103
0
        return optionletVolatilities_[i];
104
0
    }   
105
106
0
    const vector<Period>& OptionletStripper::optionletFixingTenors() const {
107
0
        return optionletTenors_;
108
0
    }
109
110
0
    const vector<Date>& OptionletStripper::optionletFixingDates() const {
111
0
        calculate();
112
0
        return optionletDates_;
113
0
    }
114
      
115
0
    const vector<Time>& OptionletStripper::optionletFixingTimes() const {
116
0
        calculate();
117
0
        return optionletTimes_;
118
0
    }
119
     
120
0
    Size OptionletStripper::optionletMaturities() const {
121
0
        return optionletTenors_.size();
122
0
    }
123
124
0
    const vector<Date>& OptionletStripper::optionletPaymentDates() const {
125
0
        calculate();
126
0
        return optionletPaymentDates_;
127
0
    }  
128
129
0
    const vector<Time>& OptionletStripper::optionletAccrualPeriods() const {
130
0
        calculate();
131
0
        return optionletAccrualPeriods_;
132
0
    }
133
134
0
    const vector<Rate>& OptionletStripper::atmOptionletRates() const {
135
0
        calculate();
136
0
        return atmOptionletRate_;
137
0
    }
138
    
139
140
0
    DayCounter OptionletStripper::dayCounter() const {
141
0
        return termVolSurface_->dayCounter();
142
0
    }
143
144
0
    Calendar OptionletStripper::calendar() const {
145
0
        return termVolSurface_->calendar();
146
0
    }
147
148
0
    Natural OptionletStripper::settlementDays() const {
149
0
        return termVolSurface_->settlementDays();
150
0
    }
151
152
0
    BusinessDayConvention OptionletStripper::businessDayConvention() const {
153
0
        return termVolSurface_->businessDayConvention();
154
0
    }
155
156
    ext::shared_ptr<CapFloorTermVolSurface>
157
0
    OptionletStripper::termVolSurface() const {
158
0
        return termVolSurface_;
159
0
    }
160
161
0
    ext::shared_ptr<IborIndex> OptionletStripper::iborIndex() const {
162
0
        return iborIndex_;
163
0
    }
164
165
0
    Real OptionletStripper::displacement() const {
166
0
        return displacement_;
167
0
    }
168
169
0
    VolatilityType OptionletStripper::volatilityType() const {
170
0
        return volatilityType_;
171
0
    }
172
173
0
    ext::optional<Period> OptionletStripper::optionletFrequency() const {
174
0
        return optionletFrequency_;
175
0
    }
176
177
}