Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
commodityforward.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2018 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19#include "toplevelfixture.hpp"
20#include <boost/test/unit_test.hpp>
21#include <ql/currencies/america.hpp>
22#include <ql/settings.hpp>
23#include <ql/time/calendars/nullcalendar.hpp>
24
26
27using namespace std;
28using namespace boost::unit_test_framework;
29using namespace QuantLib;
30using namespace QuantExt;
31
32namespace {
33class CommonData {
34public:
35 // Variables
36 QuantLib::ext::shared_ptr<CommodityIndex> index;
37 USDCurrency currency;
38 Position::Type position;
39 Real quantity;
40 Date maturity;
41 Real strike;
42
43 // cleanup
44 SavedSettings backup;
45
46 // Default constructor
47 CommonData() : index(QuantLib::ext::make_shared<CommoditySpotIndex>("GOLD_USD", NullCalendar())),
48 currency(USDCurrency()), position(Position::Long), quantity(100), maturity(19, Feb, 2019), strike(50.0) {}
49};
50} // namespace
51
52BOOST_FIXTURE_TEST_SUITE(QuantExtTestSuite, qle::test::TopLevelFixture)
53
54BOOST_AUTO_TEST_SUITE(CommodityForwardTests)
55
56BOOST_AUTO_TEST_CASE(testConstructor) {
57
58 BOOST_TEST_MESSAGE("Testing commodity forward constructor");
59
60 CommonData td;
61
62 CommodityForward forward(td.index, td.currency, td.position, td.quantity, td.maturity, td.strike);
63
64 BOOST_CHECK_EQUAL(forward.index()->name(), td.index->name());
65 BOOST_CHECK_EQUAL(forward.currency(), td.currency);
66 BOOST_CHECK_EQUAL(forward.position(), td.position);
67 BOOST_CHECK_EQUAL(forward.quantity(), td.quantity);
68 BOOST_CHECK_EQUAL(forward.maturityDate(), td.maturity);
69 BOOST_CHECK_EQUAL(forward.strike(), td.strike);
70}
71
72BOOST_AUTO_TEST_CASE(testIsExpired) {
73
74 BOOST_TEST_MESSAGE("Testing commodity forward expiry logic");
75
76 CommonData td;
77
78 CommodityForward forward(td.index, td.currency, td.position, td.quantity, td.maturity, td.strike);
79
80 Settings::instance().evaluationDate() = td.maturity - 1 * Days;
81 Settings::instance().includeReferenceDateEvents() = true;
82 BOOST_CHECK_EQUAL(forward.isExpired(), false);
83
84 Settings::instance().evaluationDate() = td.maturity;
85 BOOST_CHECK_EQUAL(forward.isExpired(), false);
86
87 Settings::instance().includeReferenceDateEvents() = false;
88 BOOST_CHECK_EQUAL(forward.isExpired(), true);
89}
90
91BOOST_AUTO_TEST_CASE(testIsExpiredCashSettledMaturityEqualsPayment) {
92
93 BOOST_TEST_MESSAGE("Testing commodity forward expiry logic for cash-settled forward" <<
94 " with payment equal to maturity");
95
96 CommonData td;
97
98 CommodityForward forward(td.index, td.currency, td.position, td.quantity, td.maturity, td.strike, false);
99
100 Settings::instance().evaluationDate() = td.maturity - 1 * Days;
101 Settings::instance().includeReferenceDateEvents() = true;
102 BOOST_CHECK_EQUAL(forward.isExpired(), false);
103
104 Settings::instance().evaluationDate() = td.maturity;
105 BOOST_CHECK_EQUAL(forward.isExpired(), false);
106
107 Settings::instance().includeReferenceDateEvents() = false;
108 BOOST_CHECK_EQUAL(forward.isExpired(), true);
109}
110
111BOOST_AUTO_TEST_CASE(testIsExpiredCashSettledPaymentGtMaturity) {
112
113 BOOST_TEST_MESSAGE("Testing commodity forward expiry logic for cash-settled forward" <<
114 " with payment date strictly greater than maturity date.");
115
116 CommonData td;
117
118 Date payment(21, Feb, 2019);
119 CommodityForward forward(td.index, td.currency, td.position, td.quantity, td.maturity, td.strike,
120 false, payment);
121
122 // Check not expired right up to payment date when includeReferenceDateEvents is true.
123 Settings::instance().includeReferenceDateEvents() = true;
124 Date tmpDate = td.maturity - 1 * Days;
125 while (tmpDate <= payment) {
126 Settings::instance().evaluationDate() = tmpDate;
127 BOOST_CHECK_EQUAL(forward.isExpired(), false);
128 tmpDate++;
129 }
130
131 // Is expired if we set includeReferenceDateEvents to false.
132 Settings::instance().includeReferenceDateEvents() = false;
133 BOOST_CHECK_EQUAL(forward.isExpired(), true);
134
135 // Is expired always when valuation date is greater than payment.
136 Settings::instance().evaluationDate() = payment + 1 * Days;
137 BOOST_CHECK_EQUAL(forward.isExpired(), true);
138 Settings::instance().includeReferenceDateEvents() = true;
139 BOOST_CHECK_EQUAL(forward.isExpired(), true);
140
141}
142
143BOOST_AUTO_TEST_CASE(testNegativeQuantityThrows) {
144
145 BOOST_TEST_MESSAGE("Test that using a negative quantity in the constructor causes an exception");
146
147 CommonData td;
148
149 BOOST_CHECK_THROW(CommodityForward(td.index, td.currency, td.position, -10.0, td.maturity, td.strike),
150 QuantLib::Error);
151}
152
153BOOST_AUTO_TEST_CASE(testNegativeStrikeThrows) {
154
155 BOOST_TEST_MESSAGE("Test that using a negative strike in the constructor causes an exception");
156
157 CommonData td;
158
159 BOOST_CHECK_THROW(CommodityForward(td.index, td.currency, td.position, td.quantity, td.maturity, -50.0),
160 QuantLib::Error);
161}
162
163BOOST_AUTO_TEST_CASE(testPaymentDateLtMaturityCashSettledThrows) {
164
165 BOOST_TEST_MESSAGE("Test that using a payment date less than maturity for cash settled causes an exception");
166
167 CommonData td;
168
169 BOOST_CHECK_THROW(CommodityForward(td.index, td.currency, td.position, td.quantity, td.maturity, -50.0,
170 false, td.maturity - 1 * Days), QuantLib::Error);
171}
172
173BOOST_AUTO_TEST_CASE(testNonNullPaymentDatePhysicallySettledThrows) {
174
175 BOOST_TEST_MESSAGE("Test that using a payment date for physically settled causes an exception");
176
177 CommonData td;
178
179 BOOST_CHECK_THROW(CommodityForward(td.index, td.currency, td.position, td.quantity, td.maturity, -50.0,
180 true, td.maturity + 2 * Days), QuantLib::Error);
181}
182
183BOOST_AUTO_TEST_SUITE_END()
184
185BOOST_AUTO_TEST_SUITE_END()
bool isExpired() const override
const QuantLib::ext::shared_ptr< CommodityIndex > & index() const
const QuantLib::Date & maturityDate() const
QuantLib::Position::Type position() const
const QuantLib::Currency & currency() const
QuantLib::Real quantity() const
QuantLib::Real strike() const
Instrument representing a commodity forward contract.
BOOST_AUTO_TEST_CASE(testConstructor)
Fixture that can be used at top level.