38 {
39
40 BOOST_TEST_MESSAGE("Testing discounting commodity forward engine pricing");
41
42 SavedSettings backup;
43
44
45 Real tolerance = 1e-10;
46
47
48 Date asof(19, Feb, 2018);
49 string name("GOLD_USD");
50 USDCurrency currency;
51 Date maturity(19, Feb, 2019);
52
53
54 Actual365Fixed dayCounter;
55
56
57 vector<Date> dates(2);
58 vector<DiscountFactor> dfs(2);
59 dates[0] = asof;
60 dfs[0] = 1.0;
61 dates[1] = maturity;
62 dfs[1] = 0.85;
65
66
67 vector<Real> prices(2);
68 prices[0] = 1346.0;
69 prices[1] = 1384.0;
70 Handle<PriceTermStructure> priceCurve(
72
73
74 QuantLib::ext::shared_ptr<DiscountingCommodityForwardEngine> engine =
75 QuantLib::ext::make_shared<DiscountingCommodityForwardEngine>(discountCurve);
76
77
78 Settings::instance().evaluationDate() = asof;
79
80
81 QuantLib::ext::shared_ptr<CommodityIndex> index = QuantLib::ext::make_shared<CommoditySpotIndex>(
82 name, NullCalendar(), priceCurve);
83 Position::Type position = Position::Long;
84 Real quantity = 100;
85 Real strike = 1380.0;
86 QuantLib::ext::shared_ptr<CommodityForward> forward =
87 QuantLib::ext::make_shared<CommodityForward>(index, currency, position, quantity, maturity, strike);
88 forward->setPricingEngine(engine);
89 BOOST_CHECK_CLOSE(forward->NPV(), quantity * (prices[1] - strike) * dfs[1], tolerance);
90
91
92 position = Position::Short;
93 forward = QuantLib::ext::make_shared<CommodityForward>(index, currency, position, quantity, maturity, strike);
94 forward->setPricingEngine(engine);
95 BOOST_CHECK_CLOSE(forward->NPV(), -quantity * (prices[1] - strike) * dfs[1], tolerance);
96
97
98 quantity = 50.0;
99 forward = QuantLib::ext::make_shared<CommodityForward>(index, currency, position, quantity, maturity, strike);
100 forward->setPricingEngine(engine);
101 BOOST_CHECK_CLOSE(forward->NPV(), -quantity * (prices[1] - strike) * dfs[1], tolerance);
102
103
104 strike = 1375.0;
105 forward = QuantLib::ext::make_shared<CommodityForward>(index, currency, position, quantity, maturity, strike);
106 forward->setPricingEngine(engine);
107 BOOST_CHECK_CLOSE(forward->NPV(), -quantity * (prices[1] - strike) * dfs[1], tolerance);
108
109
110 maturity = Date(19, Aug, 2018);
111 forward = QuantLib::ext::make_shared<CommodityForward>(index, currency, position, quantity, maturity, strike);
112 forward->setPricingEngine(engine);
113 BOOST_CHECK_CLOSE(forward->NPV(),
114 -quantity * (priceCurve->price(maturity) - strike) * discountCurve->discount(maturity),
115 tolerance);
116
117
118 forward = QuantLib::ext::make_shared<CommodityForward>(index, currency, position, quantity, asof, strike);
119
120 forward->setPricingEngine(engine);
121 BOOST_CHECK_CLOSE(forward->NPV(), 0.0, tolerance);
122
123 Settings::instance().includeReferenceDateEvents() = true;
124 forward->recalculate();
125 BOOST_CHECK_CLOSE(forward->NPV(), -quantity * (prices[0] - strike), tolerance);
126
127
128 engine = QuantLib::ext::make_shared<DiscountingCommodityForwardEngine>(discountCurve, false);
129 forward->setPricingEngine(engine);
130 BOOST_CHECK_CLOSE(forward->NPV(), 0.0, tolerance);
131
132 Settings::instance().includeReferenceDateEvents() = false;
133 engine = QuantLib::ext::make_shared<DiscountingCommodityForwardEngine>(discountCurve, true);
134 forward->setPricingEngine(engine);
135 BOOST_CHECK_CLOSE(forward->NPV(), 0.0, tolerance);
136
137
138 maturity = Date(19, Feb, 2019);
139 forward = QuantLib::ext::make_shared<CommodityForward>(index, currency, position, quantity, maturity, strike);
140 Date npvDate = asof + 2 * Days;
141 engine = QuantLib::ext::make_shared<DiscountingCommodityForwardEngine>(discountCurve, boost::none, npvDate);
142 forward->setPricingEngine(engine);
143 DiscountFactor npvDateDiscount = discountCurve->discount(npvDate);
144 BOOST_CHECK_CLOSE(forward->NPV(), -quantity * (prices[1] - strike) * dfs[1] / npvDateDiscount, tolerance);
145}
InterpolatedDiscountCurve based on loglinear interpolation of DiscountFactors.
Interpolated price curve.