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 <http://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
25namespace QuantLib {
26
27 namespace {
28
29 Date getValidSofrStart(Month month, Year year, Frequency freq) {
30 return freq == Monthly ?
31 UnitedStates(UnitedStates::GovernmentBond).adjust(Date(1, month, year)) :
32 Date::nthWeekday(n: 3, w: Wednesday, m: month, y: year);
33 }
34
35 Date getValidSofrEnd(Month month, Year year, Frequency freq) {
36 if (freq == Monthly) {
37 Calendar dc = UnitedStates(UnitedStates::GovernmentBond);
38 Date d = dc.endOfMonth(d: Date(1, month, year));
39 return dc.advance(date: d, period: 1*Days);
40 } else {
41 Date d = getValidSofrStart(month, year, freq) + Period(freq);
42 return Date::nthWeekday(n: 3, w: Wednesday, m: d.month(), y: d.year());
43 }
44
45 }
46
47 }
48
49 OvernightIndexFutureRateHelper::OvernightIndexFutureRateHelper(
50 const Handle<Quote>& price,
51 // first day of reference period
52 const Date& valueDate,
53 // delivery date
54 const Date& maturityDate,
55 const ext::shared_ptr<OvernightIndex>& overnightIndex,
56 const Handle<Quote>& convexityAdjustment,
57 RateAveraging::Type averagingMethod)
58 : RateHelper(price) {
59 ext::shared_ptr<Payoff> payoff;
60 ext::shared_ptr<OvernightIndex> index =
61 ext::dynamic_pointer_cast<OvernightIndex>(r: overnightIndex->clone(h: termStructureHandle_));
62 future_ = ext::make_shared<OvernightIndexFuture>(
63 args&: index, args: valueDate, args: maturityDate, args: convexityAdjustment, args&: averagingMethod);
64 earliestDate_ = valueDate;
65 latestDate_ = maturityDate;
66 }
67
68 Real OvernightIndexFutureRateHelper::impliedQuote() const {
69 future_->recalculate();
70 return future_->NPV();
71 }
72
73 void OvernightIndexFutureRateHelper::setTermStructure(YieldTermStructure* t) {
74 // do not set the relinkable handle as an observer -
75 // force recalculation when needed
76 bool observer = false;
77
78 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
79 termStructureHandle_.linkTo(h: temp, registerAsObserver: observer);
80
81 RateHelper::setTermStructure(t);
82 }
83
84 void OvernightIndexFutureRateHelper::accept(AcyclicVisitor& v) {
85 auto* v1 = dynamic_cast<Visitor<OvernightIndexFutureRateHelper>*>(&v);
86 if (v1 != nullptr)
87 v1->visit(*this);
88 else
89 RateHelper::accept(v);
90 }
91
92 Real OvernightIndexFutureRateHelper::convexityAdjustment() const {
93 return future_->convexityAdjustment();
94 }
95
96
97 SofrFutureRateHelper::SofrFutureRateHelper(
98 const Handle<Quote>& price,
99 Month referenceMonth,
100 Year referenceYear,
101 Frequency referenceFreq,
102 const Handle<Quote>& convexityAdjustment)
103 : OvernightIndexFutureRateHelper(price,
104 getValidSofrStart(month: referenceMonth, year: referenceYear, freq: referenceFreq),
105 getValidSofrEnd(month: referenceMonth, year: referenceYear, freq: referenceFreq),
106 ext::make_shared<Sofr>(),
107 convexityAdjustment,
108 referenceFreq == Quarterly ? RateAveraging::Compound : RateAveraging::Simple) {
109 QL_REQUIRE(referenceFreq == Quarterly || referenceFreq == Monthly,
110 "only monthly and quarterly SOFR futures accepted");
111 }
112
113 SofrFutureRateHelper::SofrFutureRateHelper(
114 Real price,
115 Month referenceMonth,
116 Year referenceYear,
117 Frequency referenceFreq,
118 Real convexityAdjustment)
119 : OvernightIndexFutureRateHelper(
120 Handle<Quote>(ext::make_shared<SimpleQuote>(args&: price)),
121 getValidSofrStart(month: referenceMonth, year: referenceYear, freq: referenceFreq),
122 getValidSofrEnd(month: referenceMonth, year: referenceYear, freq: referenceFreq),
123 ext::make_shared<Sofr>(),
124 Handle<Quote>(ext::make_shared<SimpleQuote>(args&: convexityAdjustment)),
125 referenceFreq == Quarterly ? RateAveraging::Compound : RateAveraging::Simple) {
126 QL_REQUIRE(referenceFreq == Quarterly || referenceFreq == Monthly,
127 "only monthly and quarterly SOFR futures accepted");
128 }
129}
130

source code of quantlib/ql/termstructures/yield/overnightindexfutureratehelper.cpp