22#include <boost/test/unit_test.hpp>
23#include <boost/make_shared.hpp>
24#include <boost/test/data/test_case.hpp>
26#include <ql/currencies/america.hpp>
27#include <ql/math/interpolations/linearinterpolation.hpp>
28#include <ql/math/optimization/levenbergmarquardt.hpp>
29#include <ql/math/randomnumbers/rngtraits.hpp>
30#include <ql/math/statistics/incrementalstatistics.hpp>
31#include <ql/methods/montecarlo/multipathgenerator.hpp>
32#include <ql/methods/montecarlo/pathgenerator.hpp>
33#include <ql/quotes/simplequote.hpp>
34#include <ql/termstructures/yield/flatforward.hpp>
35#include <ql/time/calendars/target.hpp>
36#include <ql/time/daycounters/actual360.hpp>
37#include <ql/time/daycounters/actualactual.hpp>
38#include <ql/time/daycounters/thirty360.hpp>
50#if BOOST_VERSION >= 106400
51#include <boost/serialization/array_wrapper.hpp>
53#include <boost/accumulators/accumulators.hpp>
54#include <boost/accumulators/statistics/covariance.hpp>
55#include <boost/accumulators/statistics/density.hpp>
56#include <boost/accumulators/statistics/error_of_mean.hpp>
57#include <boost/accumulators/statistics/mean.hpp>
58#include <boost/accumulators/statistics/stats.hpp>
59#include <boost/accumulators/statistics/variates/covariate.hpp>
60#include <boost/make_shared.hpp>
65using namespace boost::accumulators;
70std::vector<Period> periods = { 1*Days, 1*Years, 2*Years, 3*Years, 5*Years, 10*Years, 15*Years, 20*Years, 30*Years };
71std::vector<Real> prices { 100, 101, 102, 103, 105, 110, 115, 120, 130 };
77 referenceDate = Date(10, November, 2022);
78 Settings::instance().evaluationDate() = referenceDate;
80 Handle<Quote> fx(QuantLib::ext::make_shared<SimpleQuote>(1.0));
84 parametrization = QuantLib::ext::make_shared<CommoditySchwartzParametrization>(USDCurrency(),
"WTI", ts, fx, sigma, kappa,
driftFreeState);
85 QL_REQUIRE(parametrization != NULL,
"CommoditySchwartzParametrization has null pointer");
89 QuantLib::ext::make_shared<CommoditySchwartzModel>(parametrization, CommoditySchwartzModel::Discretization::Exact);
95 Handle<QuantExt::PriceTermStructure> ts;
97 QuantLib::ext::shared_ptr<CommoditySchwartzParametrization> parametrization;
98 QuantLib::ext::shared_ptr<CommoditySchwartzModel> model;
106BOOST_AUTO_TEST_SUITE(CommoditySchwartzModelTest)
117 BOOST_TEST_MESSAGE(
"Testing martingale property in the COM Schwartz model ...");
120 QuantLib::ext::shared_ptr<StochasticProcess> process = data.model->stateProcess();
121 QL_REQUIRE(process != NULL,
"process has null pointer!");
129 TimeGrid grid(t,
steps);
130 LowDiscrepancy::rsg_type sg = LowDiscrepancy::make_sequence_generator(
steps, seed);
131 MultiPathGenerator<LowDiscrepancy::rsg_type> pg(process, grid, sg,
false);
134 accumulator_set<double, stats<tag::mean, tag::variance, tag::error_of<tag::mean>>> acc_price, acc_state;
137 for (Size j = 0; j < n; ++j) {
138 Sample<MultiPath> path = pg.next();
139 Size l = path.value[0].length() - 1;
140 state[0] = path.value[0][l];
141 Real price = data.model->forwardPrice(t, T, state);
146 BOOST_TEST_MESSAGE(
"sigma = " << data.model->parametrization()->sigmaParameter());
147 BOOST_TEST_MESSAGE(
"kappa = " << data.model->parametrization()->kappaParameter());
148 BOOST_TEST_MESSAGE(
"samples = " << n);
149 BOOST_TEST_MESSAGE(
"steps = " <<
steps);
150 BOOST_TEST_MESSAGE(
"t = " << t);
151 BOOST_TEST_MESSAGE(
"T = " << T);
155 Real found = mean(acc_price);
156 Real expected = data.parametrization->priceCurve()->price(T);
157 Real error = error_of<tag::mean>(acc_price);
159 BOOST_TEST_MESSAGE(
"Check that E[F(t,T)] = F(0,T)");
160 BOOST_TEST_MESSAGE(
"Avg = " << found
162 <<
" vs expected " << expected);
163 BOOST_TEST(fabs(found - expected) < error,
"Martingale test failed for F(t,T) evolution, found " << found <<
", expected " << expected);
168 Real found = mean(acc_state);
170 Real error = error_of<tag::mean>(acc_state);
172 BOOST_TEST_MESSAGE(
"Check that the mean of the state variable is zero");
173 BOOST_TEST_MESSAGE(
"Avg = " << found
174 <<
" +- " << error_of<tag::mean>(acc_state)
175 <<
" vs expected " << expected);
176 BOOST_TEST(fabs(found - expected) < error,
"Martingale test failed for the state variable, found " << found <<
", expected " << expected);
182 Real expected = data.parametrization->variance(t);
184 Real error = error_of<tag::mean>(acc_state);
186 QuantLib::ext::shared_ptr<CommoditySchwartzStateProcess> stateProcess = QuantLib::ext::dynamic_pointer_cast<CommoditySchwartzStateProcess>(process);
187 QL_REQUIRE(stateProcess,
"state process is null");
188 Real expected2 = stateProcess->variance(0.0, 0.0, t);
191 BOOST_TEST(fabs(expected - expected2) < 1e-10,
"Inconsistent state variable variance " << expected <<
" vs " << expected2);
193 BOOST_TEST_MESSAGE(
"Check that the variance of the state variable matches expectation");
194 BOOST_TEST_MESSAGE(
"Var = " << found
196 <<
" vs expected " << expected);
197 BOOST_TEST(fabs(found - expected2) < error,
198 "Simulated variance of the state variable does match expectation, found " << found <<
", expected " << expected);
205BOOST_AUTO_TEST_SUITE_END()
207BOOST_AUTO_TEST_SUITE_END()
Interpolated price curve.
Schwartz (1997) one-factor model of the commodity price termstructure.
Schwartz commodity model parametrization.
COM state process for the one-factor Schwartz model.
base class for multi path generators
RandomVariable variance(const RandomVariable &r)
Interpolated price curve.
BOOST_DATA_TEST_CASE(testMartingaleProperty, bdata::make(driftFreeState) *bdata::make(steps), driftFreeState, steps)
std::vector< bool > driftFreeState
std::vector< Size > steps
Fixture that can be used at top level.
helper macros and methods for tests