Coverage Report

Created: 2026-03-11 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/models/shortrate/calibrationhelpers/caphelper.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) 2007 StatPro Italia srl
6
7
 This file is part of QuantLib, a free-software/open-source library
8
 for financial quantitative analysts and developers - http://quantlib.org/
9
10
 QuantLib is free software: you can redistribute it and/or modify it
11
 under the terms of the QuantLib license.  You should have received a
12
 copy of the license along with this program; if not, please email
13
 <quantlib-dev@lists.sf.net>. The license is also available online at
14
 <https://www.quantlib.org/license.shtml>.
15
16
 This program is distributed in the hope that it will be useful, but WITHOUT
17
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 FOR A PARTICULAR PURPOSE.  See the license for more details.
19
*/
20
21
#include <ql/cashflows/cashflowvectors.hpp>
22
#include <ql/models/shortrate/calibrationhelpers/caphelper.hpp>
23
#include <ql/pricingengines/capfloor/bacheliercapfloorengine.hpp>
24
#include <ql/pricingengines/capfloor/blackcapfloorengine.hpp>
25
#include <ql/pricingengines/capfloor/discretizedcapfloor.hpp>
26
#include <ql/pricingengines/swap/discountingswapengine.hpp>
27
#include <ql/quotes/simplequote.hpp>
28
#include <ql/time/schedule.hpp>
29
#include <utility>
30
31
namespace QuantLib {
32
33
    CapHelper::CapHelper(const Period& length,
34
                         const Handle<Quote>& volatility,
35
                         ext::shared_ptr<IborIndex> index,
36
                         Frequency fixedLegFrequency,
37
                         DayCounter fixedLegDayCounter,
38
                         bool includeFirstSwaplet,
39
                         Handle<YieldTermStructure> termStructure,
40
                         BlackCalibrationHelper::CalibrationErrorType errorType,
41
                         const VolatilityType type,
42
                         const Real shift)
43
0
    : BlackCalibrationHelper(volatility, errorType, type, shift), length_(length),
44
0
      index_(std::move(index)), termStructure_(std::move(termStructure)),
45
0
      fixedLegFrequency_(fixedLegFrequency), fixedLegDayCounter_(std::move(fixedLegDayCounter)),
46
0
      includeFirstSwaplet_(includeFirstSwaplet) {
47
0
        registerWith(index_);
48
0
        registerWith(termStructure_);
49
0
    }
Unexecuted instantiation: QuantLib::CapHelper::CapHelper(QuantLib::Period const&, QuantLib::Handle<QuantLib::Quote> const&, boost::shared_ptr<QuantLib::IborIndex>, QuantLib::Frequency, QuantLib::DayCounter, bool, QuantLib::Handle<QuantLib::YieldTermStructure>, QuantLib::BlackCalibrationHelper::CalibrationErrorType, QuantLib::VolatilityType, double)
Unexecuted instantiation: QuantLib::CapHelper::CapHelper(QuantLib::Period const&, QuantLib::Handle<QuantLib::Quote> const&, boost::shared_ptr<QuantLib::IborIndex>, QuantLib::Frequency, QuantLib::DayCounter, bool, QuantLib::Handle<QuantLib::YieldTermStructure>, QuantLib::BlackCalibrationHelper::CalibrationErrorType, QuantLib::VolatilityType, double)
50
51
0
    void CapHelper::addTimesTo(std::list<Time>& times) const {
52
0
        calculate();
53
0
        CapFloor::arguments args;
54
0
        cap_->setupArguments(&args);
55
0
        std::vector<Time> capTimes =
56
0
            DiscretizedCapFloor(args,
57
0
                                termStructure_->referenceDate(),
58
0
                                termStructure_->dayCounter()).mandatoryTimes();
59
0
        times.insert(times.end(),
60
0
                     capTimes.begin(), capTimes.end());
61
0
    }
62
63
0
    Real CapHelper::modelValue() const {
64
0
        calculate();
65
0
        cap_->setPricingEngine(engine_);
66
0
        return cap_->NPV();
67
0
    }
68
69
0
    Real CapHelper::blackPrice(Volatility sigma) const {
70
0
        calculate();
71
0
        Handle<Quote> vol(ext::shared_ptr<Quote>(new SimpleQuote(sigma)));
72
0
        ext::shared_ptr<PricingEngine> engine;
73
0
        switch(volatilityType_) {
74
0
          case ShiftedLognormal:
75
0
            engine = ext::make_shared<BlackCapFloorEngine>(
76
0
                termStructure_, vol, Actual365Fixed(), shift_);
77
0
            break;
78
0
          case Normal:
79
0
            engine = ext::make_shared<BachelierCapFloorEngine>(
80
0
                termStructure_, vol, Actual365Fixed());
81
0
            break;
82
0
          default:
83
0
            QL_FAIL("unknown volatility type: " << volatilityType_);
84
0
        }
85
0
        cap_->setPricingEngine(engine);
86
0
        Real value = cap_->NPV();
87
0
        cap_->setPricingEngine(engine_);
88
0
        return value;
89
0
    }
90
91
0
    void CapHelper::performCalculations() const {
92
93
0
        Period indexTenor = index_->tenor();
94
0
        Rate fixedRate = 0.04; // dummy value
95
0
        Date startDate, maturity;
96
0
        if (includeFirstSwaplet_) {
97
0
            startDate = termStructure_->referenceDate();
98
0
            maturity = termStructure_->referenceDate() + length_;
99
0
        } else {
100
0
            startDate = termStructure_->referenceDate() + indexTenor;
101
0
            maturity = termStructure_->referenceDate() + length_;
102
0
        }
103
0
        ext::shared_ptr<IborIndex> dummyIndex(new
104
0
            IborIndex("dummy",
105
0
                      indexTenor,
106
0
                      index_->fixingDays(),
107
0
                      index_->currency(),
108
0
                      index_->fixingCalendar(),
109
0
                      index_->businessDayConvention(),
110
0
                      index_->endOfMonth(),
111
0
                      termStructure_->dayCounter(),
112
0
                      termStructure_));
113
114
0
        std::vector<Real> nominals(1,1.0);
115
116
0
        Schedule floatSchedule(startDate, maturity,
117
0
                               index_->tenor(), index_->fixingCalendar(),
118
0
                               index_->businessDayConvention(),
119
0
                               index_->businessDayConvention(),
120
0
                               DateGeneration::Forward, false);
121
0
        Leg floatingLeg = IborLeg(floatSchedule, index_)
122
0
            .withNotionals(nominals)
123
0
            .withPaymentAdjustment(index_->businessDayConvention())
124
0
            .withFixingDays(0);
125
126
0
        Schedule fixedSchedule(startDate, maturity, Period(fixedLegFrequency_),
127
0
                               index_->fixingCalendar(),
128
0
                               Unadjusted, Unadjusted,
129
0
                               DateGeneration::Forward, false);
130
0
        Leg fixedLeg = FixedRateLeg(fixedSchedule)
131
0
            .withNotionals(nominals)
132
0
            .withCouponRates(fixedRate, fixedLegDayCounter_)
133
0
            .withPaymentAdjustment(index_->businessDayConvention());
134
135
0
        Swap swap(floatingLeg, fixedLeg);
136
0
        swap.setPricingEngine(ext::shared_ptr<PricingEngine>(
137
0
                            new DiscountingSwapEngine(termStructure_, false)));
138
0
        Rate fairRate = fixedRate - swap.NPV()/(swap.legBPS(1)/1.0e-4);
139
0
        cap_ = ext::make_shared<Cap>(floatingLeg,
140
0
                                              std::vector<Rate>(1, fairRate));
141
142
0
        BlackCalibrationHelper::performCalculations();
143
144
0
    }
145
146
147
}