QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
energybasisswap.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 ext::shared_ptr<CommodityIndex> spreadIndex,
28 ext::shared_ptr<CommodityIndex> payIndex,
29 ext::shared_ptr<CommodityIndex> receiveIndex,
30 bool spreadToPayLeg,
31 const Currency& payCurrency,
32 const Currency& receiveCurrency,
33 const PricingPeriods& pricingPeriods,
35 const CommodityType& commodityType,
36 const ext::shared_ptr<SecondaryCosts>& secondaryCosts,
37 Handle<YieldTermStructure> payLegTermStructure,
38 Handle<YieldTermStructure> receiveLegTermStructure,
39 Handle<YieldTermStructure> discountTermStructure)
40 : EnergySwap(
41 calendar, payCurrency, receiveCurrency, pricingPeriods, commodityType, secondaryCosts),
42 spreadIndex_(std::move(spreadIndex)), payIndex_(std::move(payIndex)),
43 receiveIndex_(std::move(receiveIndex)), spreadToPayLeg_(spreadToPayLeg),
44 basis_(std::move(basis)), payLegTermStructure_(std::move(payLegTermStructure)),
45 receiveLegTermStructure_(std::move(receiveLegTermStructure)),
46 discountTermStructure_(std::move(discountTermStructure)) {
47 QL_REQUIRE(!pricingPeriods_.empty(), "no payment dates");
51 }
52
54
55 try {
56
57 if (payIndex_->empty()) {
58 if (payIndex_->forwardCurveEmpty()) {
59 QL_FAIL("index [" + payIndex_->name() +
60 "] does not have any quotes or forward prices");
61 } else {
63 "index [" + payIndex_->name() +
64 "] does not have any quotes; "
65 "using forward prices from [" +
66 payIndex_->forwardCurve()->name() + "]");
67 }
68 }
69 if (receiveIndex_->empty()) {
70 if (receiveIndex_->forwardCurveEmpty()) {
71 QL_FAIL("index [" + receiveIndex_->name() +
72 "] does not have any quotes or forward prices");
73 } else {
75 "index [" + receiveIndex_->name() +
76 "] does not have any quotes; "
77 "using forward prices from [" +
78 receiveIndex_->forwardCurve()->name() +
79 "]");
80 }
81 }
82
83 NPV_ = 0.0;
84 additionalResults_.clear();
85 dailyPositions_.clear();
86 paymentCashFlows_.clear();
87
88 Date evaluationDate = Settings::instance().evaluationDate();
89
90 const Currency& baseCurrency =
92 const UnitOfMeasure baseUnitOfMeasure =
94
95 Real quantityUomConversionFactor =
98 baseUnitOfMeasure,
99 pricingPeriods_[0]->quantity().unitOfMeasure());
100 Real payIndexUomConversionFactor =
102 payIndex_->unitOfMeasure(),
103 baseUnitOfMeasure);
104 Real receiveIndexUomConversionFactor =
106 receiveIndex_->unitOfMeasure(),
107 baseUnitOfMeasure);
108
109 Real payIndexFxConversionFactor =
111 baseCurrency, evaluationDate);
112 Real receiveIndexFxConversionFactor =
114 baseCurrency, evaluationDate);
115 Real payLegFxConversionFactor =
117 evaluationDate);
118 Real receiveLegFxConversionFactor =
120 evaluationDate);
121
122 Real basisUomConversionFactor =
125 basis_.unitOfMeasure(), baseUnitOfMeasure);
126 Real basisFxConversionFactor =
127 calculateFxConversionFactor(baseCurrency,
129 evaluationDate);
130
131 Real basisValue = basis_.amount().value() *
132 basisUomConversionFactor * basisFxConversionFactor;
133
134 Date lastPayIndexQuoteDate = payIndex_->lastQuoteDate();
135 Date lastReceiveIndexQuoteDate = receiveIndex_->lastQuoteDate();
136
137 if (lastPayIndexQuoteDate < evaluationDate - 1) {
138 std::ostringstream message;
139 message << "index [" << payIndex_->name()
140 << "] has last quote date of "
141 << io::iso_date(lastPayIndexQuoteDate);
143 }
144 if (lastReceiveIndexQuoteDate < evaluationDate - 1) {
145 std::ostringstream message;
146 message << "index [" << receiveIndex_->name()
147 << "] has last quote date of "
148 << io::iso_date(lastReceiveIndexQuoteDate);
150 }
151
152 Date lastQuoteDate = std::min(lastPayIndexQuoteDate,
153 lastReceiveIndexQuoteDate);
154
155 Real totalQuantityAmount = 0;
156
157 // price each period
158 for (const auto& pricingPeriod : pricingPeriods_) {
159 Integer periodDayCount = 0;
160
161 // get the index quotes
162 Date periodStartDate =
163 calendar_.adjust(pricingPeriod->startDate());
164 for (Date stepDate = periodStartDate;
165 stepDate <= pricingPeriod->endDate();
166 stepDate = calendar_.advance(stepDate, 1*Days)) {
167
168 bool unrealized = stepDate > evaluationDate;
169 Real payQuoteValue = 0;
170 Real receiveQuoteValue = 0;
171
172 if (stepDate <= lastQuoteDate) {
173 payQuoteValue = payIndex_->price(stepDate);
174 receiveQuoteValue = receiveIndex_->price(stepDate);
175 } else {
176 payQuoteValue = payIndex_->forwardPrice(stepDate);
177 receiveQuoteValue =
178 receiveIndex_->forwardPrice(stepDate);
179 }
180
181 if (payQuoteValue == 0) {
182 std::ostringstream message;
183 message << "pay quote value for curve ["
184 << payIndex_->name() << "] is 0 for date "
185 << io::iso_date(stepDate);
187 }
188 if (receiveQuoteValue == 0) {
189 std::ostringstream message;
190 message << "receive quote value for curve ["
191 << receiveIndex_->name() << "] is 0 for date "
192 << io::iso_date(stepDate);
194 }
195
196 QL_REQUIRE(payQuoteValue != Null<Real>(),
197 "curve [" << payIndex_->name() <<
198 "] missing value for pricing date: "
199 << stepDate);
200 QL_REQUIRE(receiveQuoteValue != Null<Real>(),
201 "curve [" << receiveIndex_->name() <<
202 "] missing value for pricing date: "
203 << stepDate);
204
205 Real payLegPriceValue =
206 payQuoteValue * payIndexUomConversionFactor *
207 payIndexFxConversionFactor;
208 Real receiveLegPriceValue =
209 receiveQuoteValue * receiveIndexUomConversionFactor *
210 receiveIndexFxConversionFactor;
211
212 if (spreadToPayLeg_)
213 payLegPriceValue += basisValue;
214 else
215 receiveLegPriceValue += basisValue;
216
217 dailyPositions_[stepDate] =
218 EnergyDailyPosition(stepDate, payLegPriceValue,
219 receiveLegPriceValue, unrealized);
220 periodDayCount++;
221 }
222
223 Real periodQuantityAmount =
224 pricingPeriod->quantity().amount() *
225 quantityUomConversionFactor;
226 totalQuantityAmount += periodQuantityAmount;
227
228 Real avgDailyQuantityAmount =
229 periodDayCount == 0 ? Real(0) :
230 periodQuantityAmount / periodDayCount;
231
232 Real payLegValue = 0;
233 Real receiveLegValue = 0;
234 for (auto dpi = dailyPositions_.find(periodStartDate);
235 dpi != dailyPositions_.end() && dpi->first <= pricingPeriod->endDate();
236 ++dpi) {
237 EnergyDailyPosition& dailyPosition = dpi->second;
238 dailyPosition.quantityAmount = avgDailyQuantityAmount;
239 dailyPosition.riskDelta =
240 (-dailyPosition.payLegPrice + dailyPosition.receiveLegPrice) * avgDailyQuantityAmount;
241 payLegValue += -dailyPosition.payLegPrice * avgDailyQuantityAmount;
242 receiveLegValue += dailyPosition.receiveLegPrice * avgDailyQuantityAmount;
243 }
244
245 Real discountFactor = 1;
246 Real payLegDiscountFactor = 1;
247 Real receiveLegDiscountFactor = 1;
248 if (pricingPeriod->paymentDate() >= evaluationDate + 2 /* settlement days*/) {
249 discountFactor =
250 discountTermStructure_->discount(
251 pricingPeriod->paymentDate());
252 payLegDiscountFactor =
253 payLegTermStructure_->discount(
254 pricingPeriod->paymentDate());
255 receiveLegDiscountFactor =
256 receiveLegTermStructure_->discount(
257 pricingPeriod->paymentDate());
258 }
259
260 Real uDelta = receiveLegValue + payLegValue;
261 Real dDelta = (receiveLegValue * receiveLegDiscountFactor) +
262 (payLegValue * payLegDiscountFactor);
263 Real pmtFxConversionFactor =
264 (dDelta > 0) ? payLegFxConversionFactor : receiveLegFxConversionFactor;
265 Currency pmtCurrency =
266 (dDelta > 0) ? receiveCurrency_ : payCurrency_;
267 Real pmtDiscountFactor =
268 (dDelta > 0) ? receiveLegDiscountFactor : payLegDiscountFactor;
269
270 paymentCashFlows_[pricingPeriod->paymentDate()] =
271 ext::make_shared<CommodityCashFlow> (
272 pricingPeriod->paymentDate(),
273 Money(baseCurrency,
274 uDelta * discountFactor),
275 Money(baseCurrency, uDelta),
276 Money(pmtCurrency,
277 dDelta * pmtFxConversionFactor),
278 Money(pmtCurrency,
279 uDelta * pmtFxConversionFactor),
280 discountFactor,
281 pmtDiscountFactor,
282 pricingPeriod->paymentDate() <= evaluationDate);
283
286 totalQuantityAmount, evaluationDate);
287
288 NPV_ += dDelta;
289 }
290
291 QL_REQUIRE(!paymentCashFlows_.empty(), "no cashflows");
292
293 for (SecondaryCostAmounts::const_iterator i =
294 secondaryCostAmounts_.begin();
295 i != secondaryCostAmounts_.end(); ++i) {
296 Real amount = i->second.value();
297 NPV_ -= amount;
298 }
299
300 additionalResults_["dailyPositions"] = dailyPositions_;
301
302 } catch (const QuantLib::Error& e) {
304 throw;
305 } catch (const std::exception& e) {
307 throw;
308 }
309 }
310
311}
312
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
const Money & amount() const
const UnitOfMeasure & unitOfMeasure() const
Currency specification
Definition: currency.hpp:36
Concrete date class.
Definition: date.hpp:125
void performCalculations() const override
ext::shared_ptr< CommodityIndex > payIndex_
ext::shared_ptr< CommodityIndex > spreadIndex_
Handle< YieldTermStructure > payLegTermStructure_
EnergyBasisSwap(const Calendar &calendar, ext::shared_ptr< CommodityIndex > spreadIndex, ext::shared_ptr< CommodityIndex > payIndex, ext::shared_ptr< CommodityIndex > receiveIndex, bool spreadToPayLeg, const Currency &payCurrency, const Currency &receiveCurrency, const PricingPeriods &pricingPeriods, CommodityUnitCost basis, const CommodityType &commodityType, const ext::shared_ptr< SecondaryCosts > &secondaryCosts, Handle< YieldTermStructure > payLegTermStructure, Handle< YieldTermStructure > receiveLegTermStructure, Handle< YieldTermStructure > discountTermStructure)
ext::shared_ptr< CommodityIndex > receiveIndex_
Handle< YieldTermStructure > receiveLegTermStructure_
Handle< YieldTermStructure > discountTermStructure_
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
Base error class.
Definition: errors.hpp:39
const char * what() const noexcept override
returns the error message.
Definition: errors.cpp:100
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
Energy basis 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.