Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Functions
commodityasianoption.cpp File Reference
#include <boost/test/unit_test.hpp>
#include <oret/toplevelfixture.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/make_shared.hpp>
#include <ql/currencies/america.hpp>
#include <ql/instruments/asianoption.hpp>
#include <ql/math/interpolations/linearinterpolation.hpp>
#include <ql/pricingengines/blackformula.hpp>
#include <ql/termstructures/volatility/equityfx/blackvariancecurve.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/time/daycounters/actual360.hpp>
#include <qle/termstructures/pricecurve.hpp>
#include <qle/math/flatextrapolation.hpp>
#include <ored/marketdata/marketimpl.hpp>
#include <ored/portfolio/builders/commodityasianoption.hpp>
#include <ored/portfolio/asianoption.hpp>
#include <ored/portfolio/optiondata.hpp>
#include <ored/portfolio/portfolio.hpp>
#include <ored/utilities/to_string.hpp>

Go to the source code of this file.

Functions

 BOOST_AUTO_TEST_CASE (testCommodityAsianOptionTradeBuilding)
 
 BOOST_AUTO_TEST_CASE (testCommodityAsianOptionFromXml)
 

Function Documentation

◆ BOOST_AUTO_TEST_CASE() [1/2]

BOOST_AUTO_TEST_CASE ( testCommodityAsianOptionTradeBuilding  )

Definition at line 99 of file commodityasianoption.cpp.

99 {
100
101 BOOST_TEST_MESSAGE("Testing commodity Asian option trade building with constant vol term structure");
102
103 // Data from "The Complete Guide to Option Pricing Formulas", E. G. Haug, 2007, p. 194
104 // std::vector<DiscreteAsianTestData> asians{
105 // {95, 100, 0.08, 0.03, 0 * Days, 7 * Days, 180 * Days, 0.10, 27, 0.2719},
106 // {105, 100, 0.08, 0.03, 0 * Days, 1 * Days, 180 * Days, 0.50, 27, 11.1094},
107 // {95, 100, 0.08, 0.03, 70 * Days, 1 * Days, 180 * Days, 0.10, 27, 0.8805},
108 // {105, 100, 0.08, 0.03, 70 * Days, 1 * Days, 180 * Days, 0.50, 27, 14.8936},
109 // {95, 100, 0.08, 0.03, 140 * Days, 1 * Days, 180 * Days, 0.10, 27, 1.4839},
110 // {105, 100, 0.08, 0.03, 140 * Days, 1 * Days, 180 * Days, 0.50, 27, 17.6981}};
111
112 // Data from "Asian Option", Levy, 1997 in "Exotic Options: The State of the Art",
113 // edited by Clewlow, Strickland
114 // Tests with > 100 fixings are skipped here for speed, QL already tests these
115 std::vector<DiscreteAsianTestData> asians = {
116 {Option::Put, 90.0, 87.0, 0.06, 0.025, 0.0, 11.0 / 12.0, 2, 0.13, 1.3942835683},
117 {Option::Put, 90.0, 87.0, 0.06, 0.025, 0.0, 11.0 / 12.0, 4, 0.13, 1.5852442983},
118 {Option::Put, 90.0, 87.0, 0.06, 0.025, 0.0, 11.0 / 12.0, 8, 0.13, 1.66970673},
119 {Option::Put, 90.0, 87.0, 0.06, 0.025, 0.0, 11.0 / 12.0, 12, 0.13, 1.6980019214},
120 {Option::Put, 90.0, 87.0, 0.06, 0.025, 0.0, 11.0 / 12.0, 26, 0.13, 1.7255070456},
121 {Option::Put, 90.0, 87.0, 0.06, 0.025, 0.0, 11.0 / 12.0, 52, 0.13, 1.7401553533},
122 {Option::Put, 90.0, 87.0, 0.06, 0.025, 0.0, 11.0 / 12.0, 100, 0.13, 1.7478303712},
123 {Option::Put, 90.0, 87.0, 0.06, 0.025, 1.0 / 12.0, 11.0 / 12.0, 2, 0.13, 1.8496053697},
124 {Option::Put, 90.0, 87.0, 0.06, 0.025, 1.0 / 12.0, 11.0 / 12.0, 4, 0.13, 2.0111495205},
125 {Option::Put, 90.0, 87.0, 0.06, 0.025, 1.0 / 12.0, 11.0 / 12.0, 8, 0.13, 2.0852138818},
126 {Option::Put, 90.0, 87.0, 0.06, 0.025, 1.0 / 12.0, 11.0 / 12.0, 12, 0.13, 2.1105094397},
127 {Option::Put, 90.0, 87.0, 0.06, 0.025, 1.0 / 12.0, 11.0 / 12.0, 26, 0.13, 2.1346526695},
128 {Option::Put, 90.0, 87.0, 0.06, 0.025, 1.0 / 12.0, 11.0 / 12.0, 52, 0.13, 2.147489651},
129 {Option::Put, 90.0, 87.0, 0.06, 0.025, 1.0 / 12.0, 11.0 / 12.0, 100, 0.13, 2.154728109},
130 {Option::Put, 90.0, 87.0, 0.06, 0.025, 3.0 / 12.0, 11.0 / 12.0, 2, 0.13, 2.63315092584},
131 {Option::Put, 90.0, 87.0, 0.06, 0.025, 3.0 / 12.0, 11.0 / 12.0, 4, 0.13, 2.76723962361},
132 {Option::Put, 90.0, 87.0, 0.06, 0.025, 3.0 / 12.0, 11.0 / 12.0, 8, 0.13, 2.83124836881},
133 {Option::Put, 90.0, 87.0, 0.06, 0.025, 3.0 / 12.0, 11.0 / 12.0, 12, 0.13, 2.84290301412},
134 {Option::Put, 90.0, 87.0, 0.06, 0.025, 3.0 / 12.0, 11.0 / 12.0, 26, 0.13, 2.88179560417},
135 {Option::Put, 90.0, 87.0, 0.06, 0.025, 3.0 / 12.0, 11.0 / 12.0, 52, 0.13, 2.88447044543},
136 {Option::Put, 90.0, 87.0, 0.06, 0.025, 3.0 / 12.0, 11.0 / 12.0, 100, 0.13, 2.89985329603}};
137
138 Date asof = Date(01, Feb, 2021);
139 Envelope env("CP1");
140 QuantLib::ext::shared_ptr<EngineFactory> engineFactory;
141 QuantLib::ext::shared_ptr<Market> market;
142
143 for (const auto& a : asians) {
144 Time deltaT = a.length / (a.fixings - 1);
145 Date expiry;
146 vector<Date> fixingDates(a.fixings);
147 vector<std::string> strFixingDates(a.fixings);
148 for (Size i = 0; i < a.fixings; ++i) {
149 fixingDates[i] = (asof + static_cast<Integer>((a.firstFixing + i * deltaT) * 360 + 0.5));
150 strFixingDates[i] = to_string(fixingDates[i]);
151 }
152 expiry = fixingDates[a.fixings - 1];
153
154 ScheduleDates scheduleDates("NullCalendar", "", "", strFixingDates);
155 ScheduleData scheduleData(scheduleDates);
156
157 market = QuantLib::ext::make_shared<TestMarket>(a.spot, expiry, a.riskFreeRate, a.convenienceYield, a.volatility);
158 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
159 std::string productName = "CommodityAsianOptionArithmeticPrice";
160 engineData->model(productName) = "BlackScholesMerton";
161 engineData->engine(productName) = "MCDiscreteArithmeticAPEngine";
162 engineData->engineParameters(productName) = {{"ProcessType", "Discrete"}, {"BrownianBridge", "True"},
163 {"AntitheticVariate", "False"}, {"ControlVariate", "True"},
164 {"RequiredSamples", "2047"}, {"Seed", "0"}};
165 engineFactory = QuantLib::ext::make_shared<EngineFactory>(engineData, market);
166
167 // Set evaluation date
168 Settings::instance().evaluationDate() = market->asofDate();
169
170 // Test the building of a commodity Asian option doesn't throw
171 PremiumData premiumData;
172 OptionData optionData("Long", to_string(a.type), "European", true, {to_string(expiry)}, "Cash", "",
173 premiumData, vector<Real>(), vector<Real>(), "", "", "", vector<string>(),
174 vector<string>(), "", "", "", "Asian", "Arithmetic", boost::none, boost::none,
175 boost::none);
176
177 QuantLib::ext::shared_ptr<CommodityAsianOption> asianOption = QuantLib::ext::make_shared<CommodityAsianOption>(
178 env, "CommodityAsianOption", 1.0, TradeStrike(a.strike, "USD"), optionData, scheduleData,
179 QuantLib::ext::make_shared<CommodityUnderlying>("ALU_USD", 1.0, "Spot", 0, 0, ""), Date(), "USD");
180 BOOST_CHECK_NO_THROW(asianOption->build(engineFactory));
181
182 // Check the underlying instrument was built as expected
183 QuantLib::ext::shared_ptr<Instrument> qlInstrument = asianOption->instrument()->qlInstrument();
184
185 QuantLib::ext::shared_ptr<DiscreteAveragingAsianOption> discreteAsian =
186 QuantLib::ext::dynamic_pointer_cast<DiscreteAveragingAsianOption>(qlInstrument);
187
188 BOOST_CHECK(discreteAsian);
189 BOOST_CHECK_EQUAL(discreteAsian->exercise()->type(), Exercise::Type::European);
190 BOOST_CHECK_EQUAL(discreteAsian->exercise()->dates().size(), 1);
191 BOOST_CHECK_EQUAL(discreteAsian->exercise()->dates()[0], expiry);
192
193 QuantLib::ext::shared_ptr<TypePayoff> payoff = QuantLib::ext::dynamic_pointer_cast<TypePayoff>(discreteAsian->payoff());
194 BOOST_CHECK(payoff);
195 BOOST_CHECK_EQUAL(payoff->optionType(), a.type);
196
197 Real expectedPrice = a.expectedNPV;
198
199 // Check the price
200 BOOST_CHECK_SMALL(asianOption->instrument()->NPV() - expectedPrice, 2e-2);
201 }
202 }
Serializable object holding generic trade data, reporting dimensions.
Definition: envelope.hpp:51
Serializable object holding option data.
Definition: optiondata.hpp:42
Serializable object holding premium data.
Definition: premiumdata.hpp:37
Serializable schedule data.
Definition: schedule.hpp:202
Serializable object holding schedule Dates data.
Definition: schedule.hpp:110
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [2/2]

BOOST_AUTO_TEST_CASE ( testCommodityAsianOptionFromXml  )

Definition at line 205 of file commodityasianoption.cpp.

205 {
206
207 BOOST_TEST_MESSAGE("Testing parsing of commodity Asian option trade from XML");
208
209 // Create an XML string representation of the trade
210 string tradeXml;
211 tradeXml.append("<Portfolio>");
212 tradeXml.append(" <Trade id=\"CommodityAsianOption_Alu\">");
213 tradeXml.append(" <TradeType>CommodityAsianOption</TradeType>");
214 tradeXml.append(" <Envelope>");
215 tradeXml.append(" <CounterParty>CPTY_A</CounterParty>");
216 tradeXml.append(" <NettingSetId>CPTY_A</NettingSetId>");
217 tradeXml.append(" <AdditionalFields/>");
218 tradeXml.append(" </Envelope>");
219 tradeXml.append(" <CommodityAsianOptionData>");
220 tradeXml.append(" <OptionData>");
221 tradeXml.append(" <LongShort>Long</LongShort>");
222 tradeXml.append(" <OptionType>Call</OptionType>");
223 tradeXml.append(" <Style>European</Style>");
224 tradeXml.append(" <Settlement>Cash</Settlement>");
225 tradeXml.append(" <PayOffAtExpiry>false</PayOffAtExpiry>");
226 tradeXml.append(" <PayoffType>Asian</PayoffType>");
227 tradeXml.append(" <PayoffType2>Arithmetic</PayoffType2>");
228 tradeXml.append(" <ExerciseDates>");
229 tradeXml.append(" <ExerciseDate>2021-02-26</ExerciseDate>");
230 tradeXml.append(" </ExerciseDates>");
231 tradeXml.append(" </OptionData>");
232 tradeXml.append(" <ObservationDates>");
233 tradeXml.append(" <Dates>");
234 tradeXml.append(" <Dates>");
235 tradeXml.append(" <Date>2021-02-01</Date>");
236 tradeXml.append(" <Date>2021-02-02</Date>");
237 tradeXml.append(" <Date>2021-02-03</Date>");
238 tradeXml.append(" <Date>2021-02-04</Date>");
239 tradeXml.append(" <Date>2021-02-05</Date>");
240 tradeXml.append(" <Date>2021-02-08</Date>");
241 tradeXml.append(" <Date>2021-02-09</Date>");
242 tradeXml.append(" <Date>2021-02-10</Date>");
243 tradeXml.append(" <Date>2021-02-11</Date>");
244 tradeXml.append(" <Date>2021-02-12</Date>");
245 tradeXml.append(" <Date>2021-02-15</Date>");
246 tradeXml.append(" <Date>2021-02-16</Date>");
247 tradeXml.append(" <Date>2021-02-17</Date>");
248 tradeXml.append(" <Date>2021-02-18</Date>");
249 tradeXml.append(" <Date>2021-02-19</Date>");
250 tradeXml.append(" <Date>2021-02-22</Date>");
251 tradeXml.append(" <Date>2021-02-23</Date>");
252 tradeXml.append(" <Date>2021-02-24</Date>");
253 tradeXml.append(" <Date>2021-02-25</Date>");
254 tradeXml.append(" <Date>2021-02-26</Date>");
255 tradeXml.append(" </Dates>");
256 tradeXml.append(" </Dates>");
257 tradeXml.append(" </ObservationDates>");
258 tradeXml.append(" <Underlying>");
259 tradeXml.append(" <Type>Commodity</Type>");
260 tradeXml.append(" <Name>ALU_USD</Name>");
261 tradeXml.append(" </Underlying>");
262 tradeXml.append(" <IsFuturePrice>false</IsFuturePrice>");
263 tradeXml.append(" <Currency>USD</Currency>");
264 tradeXml.append(" <Strike>2270</Strike>");
265 tradeXml.append(" <Quantity>1</Quantity>");
266 tradeXml.append(" </CommodityAsianOptionData>");
267 tradeXml.append(" </Trade>");
268 tradeXml.append("</Portfolio>");
269
270 // Load portfolio from XML string
271 Portfolio portfolio;
272 portfolio.fromXMLString(tradeXml);
273
274 // Extract CommodityAsianOption trade from portfolio
275 QuantLib::ext::shared_ptr<Trade> trade = portfolio.trades().begin()->second;
276 QuantLib::ext::shared_ptr<CommodityAsianOption> option =
277 QuantLib::ext::dynamic_pointer_cast<ore::data::CommodityAsianOption>(trade);
278 BOOST_CHECK(option != nullptr);
279
280 // Check fields after checking that the cast was successful
281 BOOST_CHECK(option);
282 BOOST_CHECK_EQUAL(option->tradeType(), "CommodityAsianOption");
283 BOOST_CHECK_EQUAL(option->id(), "CommodityAsianOption_Alu");
284 // BOOST_CHECK_EQUAL(option->asset(), "ALU_USD"); // only available after build()
285 BOOST_CHECK_EQUAL(option->payCurrency(), "USD");
286 BOOST_CHECK_EQUAL(option->strike().value(), 2270);
287 BOOST_CHECK_EQUAL(option->quantity(), 1);
288 BOOST_CHECK_EQUAL(option->option().longShort(), "Long");
289 BOOST_CHECK_EQUAL(option->option().callPut(), "Call");
290 BOOST_CHECK_EQUAL(option->option().style(), "European");
291 BOOST_CHECK_EQUAL(option->option().exerciseDates().size(), 1);
292 BOOST_CHECK_EQUAL(option->option().exerciseDates()[0], "2021-02-26");
293 BOOST_CHECK(option->observationDates().hasData());
294
295 BOOST_CHECK_EQUAL(option->option().payoffType(), "Asian");
296 BOOST_CHECK_EQUAL(option->option().payoffType2(), "Arithmetic");
297 }
Serializable portfolio.
Definition: portfolio.hpp:43
const std::map< std::string, QuantLib::ext::shared_ptr< Trade > > & trades() const
Return the map tradeId -> trade.
Definition: portfolio.cpp:162
void fromXMLString(const std::string &xml)
Parse from XML string.
Definition: xmlutils.cpp:162
+ Here is the call graph for this function: