QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
energyvanillaswap.cpp
Go to the documentation of this file.
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2008 J. Erik Radmall
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 <http://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
22#include <utility>
23
24namespace QuantLib {
25
27 const Calendar& calendar,
28 Money fixedPrice,
29 UnitOfMeasure fixedPriceUnitOfMeasure,
30 ext::shared_ptr<CommodityIndex> index,
31 const Currency& payCurrency,
32 const Currency& receiveCurrency,
33 const PricingPeriods& pricingPeriods,
34 const CommodityType& commodityType,
35 const ext::shared_ptr<SecondaryCosts>& secondaryCosts,
36 Handle<YieldTermStructure> payLegTermStructure,
37 Handle<YieldTermStructure> receiveLegTermStructure,
38 Handle<YieldTermStructure> discountTermStructure)
39 : EnergySwap(
40 calendar, payCurrency, receiveCurrency, pricingPeriods, commodityType, secondaryCosts),
41 payReceive_(payer ? 1 : 0), fixedPrice_(std::move(fixedPrice)),
42 fixedPriceUnitOfMeasure_(std::move(fixedPriceUnitOfMeasure)), index_(std::move(index)),
43 payLegTermStructure_(std::move(payLegTermStructure)),
44 receiveLegTermStructure_(std::move(receiveLegTermStructure)),
45 discountTermStructure_(std::move(discountTermStructure)) {
46
47 QL_REQUIRE(!pricingPeriods_.empty(), "no pricing periods");
49 }
50
52 return detail::simple_event(pricingPeriods_.back()->endDate())
53 .hasOccurred();
54 }
55
57
58 try {
59 if (index_->empty()) {
60 if (index_->forwardCurveEmpty()) {
61 QL_FAIL("index [" << index_->name()
62 << "] does not have any quotes");
63 } else {
65 "index [" + index_->name() +
66 "] does not have any quotes; "
67 "using forward prices from ["
68 + index_->forwardCurve()->name() + "]");
69 }
70 }
71
72 NPV_ = 0.0;
73 additionalResults_.clear();
74 dailyPositions_.clear();
75 paymentCashFlows_.clear();
76
77 Date evaluationDate = Settings::instance().evaluationDate();
78
79 const Currency& baseCurrency =
81 const UnitOfMeasure baseUnitOfMeasure =
83
84 Real quantityUomConversionFactor =
87 baseUnitOfMeasure,
88 pricingPeriods_[0]->quantity().unitOfMeasure());
89 Real fixedPriceUomConversionFactor =
92 fixedPriceUnitOfMeasure_, baseUnitOfMeasure);
93 Real indexUomConversionFactor =
94 calculateUomConversionFactor(index_->commodityType(),
95 index_->unitOfMeasure(),
96 baseUnitOfMeasure);
97
98 Real fixedPriceFxConversionFactor =
100 baseCurrency, evaluationDate);
101 Real indexPriceFxConversionFactor =
103 baseCurrency, evaluationDate);
104 Real payLegFxConversionFactor =
106 baseCurrency,
108 evaluationDate);
109 Real receiveLegFxConversionFactor =
111 baseCurrency,
113 evaluationDate);
114
115 Date lastQuoteDate = index_->lastQuoteDate();
116 if (lastQuoteDate < evaluationDate - 1) {
117 std::ostringstream message;
118 message << "index [" << index_->name()
119 << "] has last quote date of "
120 << io::iso_date(lastQuoteDate);
122 }
123
124 Real totalQuantityAmount = 0;
125
126 // price each period
127 for (const auto& pricingPeriod : pricingPeriods_) {
128 QL_REQUIRE(pricingPeriod->quantity().amount() != 0, "quantity is zero");
129
130 Integer periodDayCount = 0;
131
132 // get the futures quotes or everything after
133 Date periodStartDate =
134 calendar_.adjust(pricingPeriod->startDate());
135 for (Date stepDate = periodStartDate;
136 stepDate <= pricingPeriod->endDate();
137 stepDate = calendar_.advance(stepDate, 1*Days)) {
138
139 bool unrealized = stepDate > evaluationDate;
140 Real quoteValue = 0;
141
142 if (stepDate <= lastQuoteDate) {
143 quoteValue = index_->price(stepDate);
144 } else {
145 quoteValue = index_->forwardPrice(stepDate);
146 }
147
148 if (quoteValue == 0) {
149 std::ostringstream message;
150 message << "pay quote value for curve ["
151 << index_->name() << "] is 0 for date "
152 << io::iso_date(stepDate);
154 }
155
156 QL_REQUIRE(quoteValue != Null<Real>(),
157 "curve [" << index_->name() <<
158 "] missing value for pricing date: "
159 << stepDate);
160
161 Real fixedLegPriceValue =
162 fixedPrice_.value() * fixedPriceUomConversionFactor *
163 fixedPriceFxConversionFactor;
164 Real floatingLegPriceValue =
165 quoteValue * indexUomConversionFactor *
166 indexPriceFxConversionFactor;
167 Real payLegPriceValue =
168 payReceive_ > 0 ? fixedLegPriceValue :
169 floatingLegPriceValue;
170 Real receiveLegPriceValue =
171 payReceive_ > 0 ? floatingLegPriceValue :
172 fixedLegPriceValue;
173
174 dailyPositions_[stepDate] =
175 EnergyDailyPosition(stepDate, payLegPriceValue,
176 receiveLegPriceValue, unrealized);
177 periodDayCount++;
178 }
179
180 Real periodQuantityAmount =
181 pricingPeriod->quantity().amount() *
182 quantityUomConversionFactor;
183 totalQuantityAmount += periodQuantityAmount;
184
185 Real avgDailyQuantityAmount =
186 periodDayCount == 0 ? Real(0) :
187 periodQuantityAmount / periodDayCount;
188
189 Real payLegValue = 0;
190 Real receiveLegValue = 0;
191 for (auto dpi = dailyPositions_.find(periodStartDate);
192 dpi != dailyPositions_.end() && dpi->first <= pricingPeriod->endDate();
193 ++dpi) {
194 EnergyDailyPosition& dailyPosition = dpi->second;
195 dailyPosition.quantityAmount = avgDailyQuantityAmount;
196 dailyPosition.riskDelta =
197 (-dailyPosition.payLegPrice + dailyPosition.receiveLegPrice) * avgDailyQuantityAmount;
198 payLegValue += -dailyPosition.payLegPrice * avgDailyQuantityAmount;
199 receiveLegValue += dailyPosition.receiveLegPrice * avgDailyQuantityAmount;
200 }
201
202 Real discountFactor = 1;
203 Real payLegDiscountFactor = 1;
204 Real receiveLegDiscountFactor = 1;
205 if (pricingPeriod->paymentDate() >= evaluationDate + 2) {
206 discountFactor =
207 discountTermStructure_->discount(
208 pricingPeriod->paymentDate());
209 payLegDiscountFactor =
210 payLegTermStructure_->discount(
211 pricingPeriod->paymentDate());
212 receiveLegDiscountFactor =
213 receiveLegTermStructure_->discount(
214 pricingPeriod->paymentDate());
215 }
216
217 Real uDelta = receiveLegValue + payLegValue;
218 Real dDelta = (receiveLegValue * receiveLegDiscountFactor) +
219 (payLegValue * payLegDiscountFactor);
220 Real pmtFxConversionFactor =
221 ((dDelta * payReceive_) > 0) ? payLegFxConversionFactor :
222 receiveLegFxConversionFactor;
223 Currency pmtCurrency =
224 ((dDelta * payReceive_) > 0) ? receiveCurrency_ :
226 Real pmtDiscountFactor =
227 (dDelta > 0) ? receiveLegDiscountFactor :
228 payLegDiscountFactor;
229
230 paymentCashFlows_[pricingPeriod->paymentDate()] =
231 ext::make_shared<CommodityCashFlow>(
232 pricingPeriod->paymentDate(),
233 Money(baseCurrency,
234 uDelta * discountFactor),
235 Money(baseCurrency, uDelta),
236 Money(pmtCurrency,
237 dDelta * pmtFxConversionFactor),
238 Money(pmtCurrency,
239 uDelta * pmtFxConversionFactor),
240 discountFactor,
241 pmtDiscountFactor,
242 pricingPeriod->paymentDate() <= evaluationDate);
243
246 totalQuantityAmount, evaluationDate);
247
248 NPV_ += dDelta;
249 }
250
251 QL_REQUIRE(!paymentCashFlows_.empty(), "no cashflows");
252
253 for (SecondaryCostAmounts::const_iterator i =
254 secondaryCostAmounts_.begin();
255 i != secondaryCostAmounts_.end(); ++i) {
256 Real amount = i->second.value();
257 NPV_ -= amount;
258 }
259
260 additionalResults_["dailyPositions"] = dailyPositions_;
261
262 } catch (const QuantLib::Error& e) {
264 throw;
265 } catch (const std::exception& e) {
267 throw;
268 }
269 }
270
271}
272
calendar class
Definition: calendar.hpp:61
Date adjust(const Date &, BusinessDayConvention convention=Following) const
Definition: calendar.cpp:84
Date advance(const Date &, Integer n, TimeUnit unit, BusinessDayConvention convention=Following, bool endOfMonth=false) const
Definition: calendar.cpp:130
void addPricingError(PricingError::Level errorLevel, const std::string &error, const std::string &detail="") const
Definition: commodity.cpp:37
SecondaryCostAmounts secondaryCostAmounts_
Definition: commodity.hpp:75
Currency specification
Definition: currency.hpp:36
Concrete date class.
Definition: date.hpp:125
static Real calculateUomConversionFactor(const CommodityType &commodityType, const UnitOfMeasure &fromUnitOfMeasure, const UnitOfMeasure &toUnitOfMeasure)
void calculateSecondaryCostAmounts(const CommodityType &commodityType, Real totalQuantityValue, const Date &evaluationDate) const
static Real calculateFxConversionFactor(const Currency &fromCurrency, const Currency &toCurrency, const Date &evaluationDate)
EnergyDailyPositions dailyPositions_
Definition: energyswap.hpp:63
PricingPeriods pricingPeriods_
Definition: energyswap.hpp:62
Quantity quantity() const override
Definition: energyswap.cpp:41
Currency receiveCurrency_
Definition: energyswap.hpp:61
const CommodityType & commodityType() const
Definition: energyswap.cpp:36
CommodityCashFlows paymentCashFlows_
Definition: energyswap.hpp:64
void performCalculations() const override
bool isExpired() const override
returns whether the instrument might have value greater than zero.
EnergyVanillaSwap(bool payer, const Calendar &calendar, Money fixedPrice, UnitOfMeasure fixedPriceUnitOfMeasure, ext::shared_ptr< CommodityIndex > index, const Currency &payCurrency, const Currency &receiveCurrency, const PricingPeriods &pricingPeriods, const CommodityType &commodityType, const ext::shared_ptr< SecondaryCosts > &secondaryCosts, Handle< YieldTermStructure > payLegTermStructure, Handle< YieldTermStructure > receiveLegTermStructure, Handle< YieldTermStructure > discountTermStructure)
Handle< YieldTermStructure > payLegTermStructure_
ext::shared_ptr< CommodityIndex > index_
Handle< YieldTermStructure > receiveLegTermStructure_
Handle< YieldTermStructure > discountTermStructure_
Base error class.
Definition: errors.hpp:39
const char * what() const noexcept override
returns the error message.
Definition: errors.cpp:100
virtual bool hasOccurred(const Date &refDate=Date(), ext::optional< bool > includeRefDate=ext::nullopt) const
returns true if an event has already occurred before a date
Definition: event.cpp:28
Shared handle to an observable.
Definition: handle.hpp:41
std::map< std::string, ext::any > additionalResults_
Definition: instrument.hpp:108
amount of cash
Definition: money.hpp:38
const Currency & currency() const
Definition: money.hpp:173
Decimal value() const
Definition: money.hpp:177
template class providing a null value for a given type.
Definition: null.hpp:76
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:228
DateProxy & evaluationDate()
the date at which pricing is to be performed.
Definition: settings.hpp:147
static Settings & instance()
access to the unique instance
Definition: singleton.hpp:104
Unit of measure specification
commodity settings
Vanilla energy swap.
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
#define QL_FAIL(message)
throw an error (possibly with file and line information)
Definition: errors.hpp:92
detail::iso_date_holder iso_date(const Date &d)
output dates in ISO format (yyyy-mm-dd)
Definition: date.cpp:991
QL_REAL Real
real number
Definition: types.hpp:50
QL_INTEGER Integer
integer number
Definition: types.hpp:35
Definition: any.hpp:35
std::vector< ext::shared_ptr< PricingPeriod > > PricingPeriods
STL namespace.