Coverage Report

Created: 2026-03-31 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/instruments/forward.hpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2006 Allen Kuo
5
6
 This file is part of QuantLib, a free-software/open-source library
7
 for financial quantitative analysts and developers - http://quantlib.org/
8
9
 QuantLib is free software: you can redistribute it and/or modify it
10
 under the terms of the QuantLib license.  You should have received a
11
 copy of the license along with this program; if not, please email
12
 <quantlib-dev@lists.sf.net>. The license is also available online at
13
 <https://www.quantlib.org/license.shtml>.
14
15
 This program is distributed in the hope that it will be useful, but WITHOUT
16
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
 FOR A PARTICULAR PURPOSE.  See the license for more details.
18
*/
19
20
/*! \file forward.hpp
21
    \brief Base forward class
22
*/
23
24
#ifndef quantlib_forward_hpp
25
#define quantlib_forward_hpp
26
27
#include <ql/instrument.hpp>
28
#include <ql/position.hpp>
29
#include <ql/time/calendar.hpp>
30
#include <ql/time/daycounter.hpp>
31
#include <ql/interestrate.hpp>
32
#include <ql/types.hpp>
33
#include <ql/handle.hpp>
34
#include <ql/payoff.hpp>
35
#include <ql/termstructures/yieldtermstructure.hpp>
36
37
namespace QuantLib {
38
39
    //! Abstract base forward class
40
    /*! Derived classes must implement the virtual functions
41
        spotValue() (NPV or spot price) and spotIncome() associated
42
        with the specific relevant underlying (e.g. bond, stock,
43
        commodity, loan/deposit). These functions must be used to set the
44
        protected member variables underlyingSpotValue_ and
45
        underlyingIncome_ within performCalculations() in the derived
46
        class before the base-class implementation is called.
47
48
        spotIncome() refers generically to the present value of
49
        coupons, dividends or storage costs.
50
51
        discountCurve_ is the curve used to discount forward contract
52
        cash flows back to the evaluation day, as well as to obtain
53
        forward values for spot values/prices.
54
55
        incomeDiscountCurve_, which for generality is not
56
        automatically set to the discountCurve_, is the curve used to
57
        discount future income/dividends/storage-costs etc back to the
58
        evaluation date.
59
60
        \todo Add preconditions and tests
61
62
        \warning This class still needs to be rigorously tested
63
64
        \ingroup instruments
65
    */
66
    class Forward : public Instrument {
67
      public:
68
        //! \name Inspectors
69
        //@{
70
        virtual Date settlementDate() const;
71
        const Calendar& calendar() const;
72
        BusinessDayConvention businessDayConvention() const;
73
        const DayCounter& dayCounter() const;
74
        //! term structure relevant to the contract (e.g. repo curve)
75
        Handle<YieldTermStructure> discountCurve() const;
76
        //! term structure that discounts the underlying's income cash flows
77
        Handle<YieldTermStructure> incomeDiscountCurve() const;
78
        //! returns whether the instrument is still tradable.
79
        bool isExpired() const override;
80
        //@}
81
82
        //! returns spot value/price of an underlying financial instrument
83
        virtual Real spotValue() const = 0;
84
        //! NPV of income/dividends/storage-costs etc. of underlying instrument
85
        virtual Real spotIncome(const Handle<YieldTermStructure>&
86
                                               incomeDiscountCurve) const = 0;
87
88
        //! \name Calculations
89
        //@{
90
        //! forward value/price of underlying, discounting income/dividends
91
        /*! \note if this is a bond forward price, is must be a dirty
92
                  forward price.
93
        */
94
        virtual Real forwardValue() const;
95
96
        /*! Simple yield calculation based on underlying spot and
97
            forward values, taking into account underlying income.
98
            When \f$ t>0 \f$, call with:
99
            underlyingSpotValue=spotValue(t),
100
            forwardValue=strikePrice, to get current yield. For a
101
            repo, if \f$ t=0 \f$, impliedYield should reproduce the
102
            spot repo rate. For FRA's, this should reproduce the
103
            relevant zero rate at the FRA's maturityDate_;
104
        */
105
        InterestRate impliedYield(Real underlyingSpotValue,
106
                                  Real forwardValue,
107
                                  Date settlementDate,
108
                                  Compounding compoundingConvention,
109
                                  const DayCounter& dayCounter);
110
        //@}
111
      protected:
112
        Forward(DayCounter dayCounter,
113
                Calendar calendar,
114
                BusinessDayConvention businessDayConvention,
115
                Natural settlementDays,
116
                ext::shared_ptr<Payoff> payoff,
117
                const Date& valueDate,
118
                const Date& maturityDate,
119
                Handle<YieldTermStructure> discountCurve = Handle<YieldTermStructure>());
120
121
        void performCalculations() const override;
122
        /*! derived classes must set this, typically via spotIncome() */
123
        mutable Real underlyingIncome_;
124
        /*! derived classes must set this, typically via spotValue() */
125
        mutable Real underlyingSpotValue_;
126
127
        DayCounter dayCounter_;
128
        Calendar calendar_;
129
        BusinessDayConvention businessDayConvention_;
130
        Natural settlementDays_;
131
        ext::shared_ptr<Payoff> payoff_;
132
        /*! valueDate = settlement date (date the fwd contract starts
133
            accruing)
134
        */
135
        Date valueDate_;
136
        //! maturityDate of the forward contract or delivery date of underlying
137
        Date maturityDate_;
138
        Handle<YieldTermStructure> discountCurve_;
139
        /*! must set this in derived classes, based on particular underlying */
140
        Handle<YieldTermStructure> incomeDiscountCurve_;
141
    };
142
143
144
    //! Class for forward type payoffs
145
    class ForwardTypePayoff : public Payoff {
146
      public:
147
        ForwardTypePayoff(Position::Type type, Real strike)
148
0
        : type_(type),strike_(strike) {
149
0
            QL_REQUIRE(strike >= 0.0,"negative strike given");
150
0
        }
151
0
        Position::Type forwardType() const { return type_; };
152
0
        Real strike() const { return strike_; };
153
        //! \name Payoff interface
154
        //@{
155
0
        std::string name() const override { return "Forward"; }
156
        std::string description() const override;
157
        Real operator()(Real price) const override;
158
        //@}
159
      protected:
160
        Position::Type type_;
161
        Real strike_;
162
    };
163
164
165
166
    // inline definitions
167
168
0
    inline const Calendar& Forward::calendar() const {
169
0
        return calendar_;
170
0
    }
171
172
0
    inline BusinessDayConvention Forward::businessDayConvention() const {
173
0
        return businessDayConvention_;
174
0
    }
175
176
0
    inline const DayCounter& Forward::dayCounter() const {
177
0
        return dayCounter_;
178
0
    }
179
180
0
    inline Handle<YieldTermStructure> Forward::discountCurve() const {
181
0
        return discountCurve_;
182
0
    }
183
184
0
    inline Handle<YieldTermStructure> Forward::incomeDiscountCurve() const {
185
0
        return incomeDiscountCurve_;
186
0
    }
187
188
189
0
    inline std::string ForwardTypePayoff::description() const {
190
0
        std::ostringstream result;
191
0
        result << name() << ", " << strike() << " strike";
192
0
        return result.str();
193
0
    }
194
195
0
    inline Real ForwardTypePayoff::operator()(Real price) const {
196
0
        switch (type_) {
197
0
          case Position::Long:
198
0
            return (price-strike_);
199
0
          case Position::Short:
200
0
            return (strike_-price);
201
0
          default:
202
            QL_FAIL("unknown/illegal position type");
203
0
        }
204
0
    }
205
206
}
207
208
209
#endif
210