Coverage Report

Created: 2026-01-25 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/termstructures/yield/overnightindexfutureratehelper.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2018 Roy Zywina
5
 Copyright (C) 2019, 2020 Eisuke Tani
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/termstructures/yield/overnightindexfutureratehelper.hpp>
22
#include <ql/indexes/ibor/sofr.hpp>
23
#include <ql/utilities/null_deleter.hpp>
24
25
namespace QuantLib {
26
27
    namespace {
28
29
0
        Date getSofrStart(Month month, Year year, Frequency freq) {
30
0
            return freq == Monthly ? Date(1, month, year) :
31
0
                   Date::nthWeekday(3, Wednesday, month, year);
32
0
        }
33
34
0
        Date getSofrEnd(Month month, Year year, Frequency freq) {
35
0
            if (freq == Monthly) {
36
0
                return Date::endOfMonth(Date(1, month, year)) + 1;
37
0
            } else {
38
0
                Date d = getSofrStart(month, year, freq) + Period(freq);
39
0
                return Date::nthWeekday(3, Wednesday, d.month(), d.year());
40
0
            }
41
42
0
        }
43
44
    }
45
46
    OvernightIndexFutureRateHelper::OvernightIndexFutureRateHelper(
47
        const Handle<Quote>& price,
48
        // first day of reference period
49
        const Date& valueDate,
50
        // delivery date
51
        const Date& maturityDate,
52
        const ext::shared_ptr<OvernightIndex>& overnightIndex,
53
        const Handle<Quote>& convexityAdjustment,
54
        RateAveraging::Type averagingMethod)
55
0
    : RateHelper(price) {
56
0
        ext::shared_ptr<OvernightIndex> index =
57
0
            ext::dynamic_pointer_cast<OvernightIndex>(overnightIndex->clone(termStructureHandle_));
58
0
        future_ = ext::make_shared<OvernightIndexFuture>(
59
0
            index, valueDate, maturityDate, convexityAdjustment, averagingMethod);
60
0
        registerWithObservables(future_);
61
0
        earliestDate_ = valueDate;
62
0
        latestDate_ = maturityDate;
63
0
    }
64
65
0
    Real OvernightIndexFutureRateHelper::impliedQuote() const {
66
0
        future_->recalculate();
67
0
        return future_->NPV();
68
0
    }
69
70
0
    void OvernightIndexFutureRateHelper::setTermStructure(YieldTermStructure* t) {
71
        // do not set the relinkable handle as an observer -
72
        // force recalculation when needed
73
0
        bool observer = false;
74
75
0
        ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
76
0
        termStructureHandle_.linkTo(temp, observer);
77
78
0
        RateHelper::setTermStructure(t);
79
0
    }
80
81
0
    void OvernightIndexFutureRateHelper::accept(AcyclicVisitor& v) {
82
0
        auto* v1 = dynamic_cast<Visitor<OvernightIndexFutureRateHelper>*>(&v);
83
0
        if (v1 != nullptr)
84
0
            v1->visit(*this);
85
0
        else
86
0
            RateHelper::accept(v);
87
0
    }
88
89
0
    Real OvernightIndexFutureRateHelper::convexityAdjustment() const {
90
0
        return future_->convexityAdjustment();
91
0
    }
92
93
94
    SofrFutureRateHelper::SofrFutureRateHelper(
95
        const Handle<Quote>& price,
96
        Month referenceMonth,
97
        Year referenceYear,
98
        Frequency referenceFreq,
99
        const Handle<Quote>& convexityAdjustment)
100
0
    : OvernightIndexFutureRateHelper(price,
101
0
            getSofrStart(referenceMonth, referenceYear, referenceFreq),
102
0
            getSofrEnd(referenceMonth, referenceYear, referenceFreq),
103
0
            ext::make_shared<Sofr>(),
104
0
            convexityAdjustment,
105
0
            referenceFreq == Quarterly ? RateAveraging::Compound : RateAveraging::Simple) {
106
0
        QL_REQUIRE(referenceFreq == Quarterly || referenceFreq == Monthly,
107
0
            "only monthly and quarterly SOFR futures accepted");
108
0
    }
109
110
    SofrFutureRateHelper::SofrFutureRateHelper(
111
        Real price,
112
        Month referenceMonth,
113
        Year referenceYear,
114
        Frequency referenceFreq,
115
        Real convexityAdjustment)
116
0
    : OvernightIndexFutureRateHelper(
117
0
            Handle<Quote>(ext::make_shared<SimpleQuote>(price)),
118
0
            getSofrStart(referenceMonth, referenceYear, referenceFreq),
119
0
            getSofrEnd(referenceMonth, referenceYear, referenceFreq),
120
0
            ext::make_shared<Sofr>(),
121
0
            Handle<Quote>(ext::make_shared<SimpleQuote>(convexityAdjustment)),
122
0
            referenceFreq == Quarterly ? RateAveraging::Compound : RateAveraging::Simple) {
123
        QL_REQUIRE(referenceFreq == Quarterly || referenceFreq == Monthly,
124
0
            "only monthly and quarterly SOFR futures accepted");
125
0
    }
126
}