/src/quantlib/ql/indexes/equityindex.cpp
Line | Count | Source |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2023 Marcin Rybacki |
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 | | #include <ql/indexes/equityindex.hpp> |
21 | | #include <ql/settings.hpp> |
22 | | #include <utility> |
23 | | |
24 | | namespace QuantLib { |
25 | | |
26 | | namespace { |
27 | 0 | Real resolveSpot(const Handle<Quote>& spot, Real lastFixing) { |
28 | 0 | QL_REQUIRE(!spot.empty() || lastFixing != Null<Real>(), |
29 | 0 | "Cannot forecast equity index, missing both spot and historical index"); |
30 | 0 | return spot.empty() ? lastFixing : spot->value(); |
31 | 0 | } |
32 | | } |
33 | | |
34 | | EquityIndex::EquityIndex(std::string name, |
35 | | Calendar fixingCalendar, |
36 | | Currency currency, |
37 | | Handle<YieldTermStructure> interest, |
38 | | Handle<YieldTermStructure> dividend, |
39 | | Handle<Quote> spot) |
40 | 0 | : name_(std::move(name)), fixingCalendar_(std::move(fixingCalendar)), |
41 | 0 | currency_(std::move(currency)), interest_(std::move(interest)), |
42 | 0 | dividend_(std::move(dividend)), spot_(std::move(spot)) { |
43 | |
|
44 | 0 | registerWith(interest_); |
45 | 0 | registerWith(dividend_); |
46 | 0 | registerWith(spot_); |
47 | 0 | registerWith(Settings::instance().evaluationDate()); |
48 | 0 | registerWith(notifier()); |
49 | 0 | } |
50 | | |
51 | 0 | Real EquityIndex::fixing(const Date& fixingDate, bool forecastTodaysFixing) const { |
52 | |
|
53 | 0 | QL_REQUIRE(isValidFixingDate(fixingDate), "Fixing date " << fixingDate << " is not valid"); |
54 | | |
55 | 0 | Date today = Settings::instance().evaluationDate(); |
56 | |
|
57 | 0 | if (fixingDate > today || (fixingDate == today && forecastTodaysFixing)) |
58 | 0 | return forecastFixing(fixingDate); |
59 | | |
60 | 0 | Real result = pastFixing(fixingDate); |
61 | |
|
62 | 0 | if (result != Null<Real>()) |
63 | | // if historical fixing is present use it |
64 | 0 | return result; |
65 | | |
66 | 0 | if (fixingDate == today && !spot_.empty()) |
67 | | // Today's fixing is missing, but spot is |
68 | | // provided, so use it as proxy |
69 | 0 | return spot_->value(); |
70 | | |
71 | 0 | QL_FAIL("Missing " << name() << " fixing for " << fixingDate); |
72 | 0 | } |
73 | | |
74 | 0 | Real EquityIndex::forecastFixing(const Date& fixingDate) const { |
75 | 0 | QL_REQUIRE(!interest_.empty(), |
76 | 0 | "null interest rate term structure set to this instance of " << name()); |
77 | | |
78 | 0 | Date today = Settings::instance().evaluationDate(); |
79 | 0 | Date lastFixingDate = fixingCalendar_.adjust(today, BusinessDayConvention::Preceding); |
80 | |
|
81 | 0 | Real spot = resolveSpot(spot_, pastFixing(lastFixingDate)); |
82 | |
|
83 | 0 | Real forward; |
84 | 0 | if (!dividend_.empty()) { |
85 | 0 | forward = spot * dividend_->discount(fixingDate) / interest_->discount(fixingDate); |
86 | 0 | } else { |
87 | 0 | forward = spot / interest_->discount(fixingDate); |
88 | 0 | } |
89 | 0 | return forward; |
90 | 0 | } |
91 | | |
92 | | ext::shared_ptr<EquityIndex> EquityIndex::clone(const Handle<YieldTermStructure>& interest, |
93 | | const Handle<YieldTermStructure>& dividend, |
94 | 0 | const Handle<Quote>& spot) const { |
95 | 0 | return ext::make_shared<EquityIndex>(name(), fixingCalendar(), currency(), interest, |
96 | 0 | dividend, spot); |
97 | 0 | } |
98 | | } |