20#include <boost/test/unit_test.hpp>
21#include <boost/test/data/test_case.hpp>
23#include <boost/timer/timer.hpp>
29#include <oret/toplevelfixture.hpp>
38 std::string label,
script, expectedAST;
41std::ostream&
operator<<(std::ostream& os,
const TestDatum& testDatum) {
return os <<
"[" << testDatum.label <<
"]"; }
43TestDatum scriptData[] = {
44 {
"assignment number",
"x=1;",
49 " ConstantNumber(1.000000)\n"},
51 {
"assignment number",
"x=1.2;",
56 " ConstantNumber(1.200000)\n"},
59 "Option = Quantity * PAY(max( PutCall * (Underlying(Expiry) - Strike), 0 ),\n"
60 " Expiry, Settlement, PayCcy);",
66 " Variable(Quantity)\n"
71 " Variable(PutCall)\n"
75 " Variable(Underlying)\n"
82 " ConstantNumber(0.000000)\n"
85 " Variable(Settlement)\n"
90 {
"american window option",
91 "NUMBER Exercise, Continuation;\n"
92 "NUMBER ExerciseIndex;\n"
93 "FOR i IN (SIZE(Expiry), 1, -1) DO\n"
94 " Exercise = PAY( max(PutCall * (Underlying(Expiry[i]) - Strike), 0 ),\n"
95 " Expiry[i], Settlement[i], PayCcy );\n"
96 " IF exercise > NPV( continuation, Expiry[i] ) THEN\n"
97 " Continuation = Exercise;\n"
98 " ExerciseIndex = i;\n"
101 "Option = Quantity * PAY(Continuation,\n"
102 " Expiry[exerciseIndex], Settlement[exericseIndex], PayCcy);\n",
104 " DeclarationNumber\n"
105 " Variable(Exercise)\n"
107 " Variable(Continuation)\n"
109 " DeclarationNumber\n"
110 " Variable(ExerciseIndex)\n"
114 " ConstantNumber(1.000000)\n"
115 " ConstantNumber(-1.000000)\n"
118 " Variable(Exercise)\n"
122 " OperatorMultiply\n"
123 " Variable(PutCall)\n"
127 " Variable(Underlying)\n"
129 " Variable(Expiry)\n"
133 " Variable(Strike)\n"
135 " ConstantNumber(0.000000)\n"
136 " Variable(Expiry)\n"
139 " Variable(Settlement)\n"
142 " Variable(PayCcy)\n"
146 " Variable(exercise)\n"
149 " Variable(continuation)\n"
151 " Variable(Expiry)\n"
159 " Variable(Continuation)\n"
161 " Variable(Exercise)\n"
164 " Variable(ExerciseIndex)\n"
170 " Variable(Option)\n"
172 " OperatorMultiply\n"
173 " Variable(Quantity)\n"
176 " Variable(Continuation)\n"
178 " Variable(Expiry)\n"
179 " Variable(exerciseIndex)\n"
181 " Variable(Settlement)\n"
182 " Variable(exericseIndex)\n"
184 " Variable(PayCcy)\n"
189 "FOR i IN (2, SIZE(Observation), 1) DO\n"
190 "variance = variance + pow(\n"
191 " ln( Underlying(Observation[i]) / Underlying(Observation[i-1]) ), 2);\n"
193 "Option = Notional * PAY( pow(variance / SIZE(Observation), 0.5) - Strike,\n"
194 " Observation[SIZE(Observation)], Payment, PayCcy);\n",
196 " DeclarationNumber\n"
197 " Variable(variance)\n"
200 " ConstantNumber(2.000000)\n"
201 " Size(Observation)\n"
202 " ConstantNumber(1.000000)\n"
205 " Variable(variance)\n"
208 " Variable(variance)\n"
214 " Variable(Underlying)\n"
216 " Variable(Observation)\n"
221 " Variable(Underlying)\n"
223 " Variable(Observation)\n"
227 " ConstantNumber(1.000000)\n"
229 " ConstantNumber(2.000000)\n"
231 " Variable(Option)\n"
233 " OperatorMultiply\n"
234 " Variable(Notional)\n"
240 " Variable(variance)\n"
242 " Size(Observation)\n"
243 " ConstantNumber(0.500000)\n"
244 " Variable(Strike)\n"
246 " Variable(Observation)\n"
247 " Size(Observation)\n"
248 " Variable(Payment)\n"
250 " Variable(PayCcy)\n"
255 "FOR i IN (2, SIZE(Valuation), 1) DO\n"
256 "P = P + max( min( Underlying(Valuation[i]) / Underlying(Valuation[i-1]) - 1,\n"
260 "Option = PAY(Notional * max( min(P, globalCap) , globalFloor),\n"
261 " Valuation[SIZE(Valuation)], Settlement, PayCcy);\n",
263 " DeclarationNumber\n"
267 " ConstantNumber(2.000000)\n"
269 " ConstantNumber(1.000000)\n"
282 " Variable(Underlying)\n"
284 " Variable(Valuation)\n"
289 " Variable(Underlying)\n"
291 " Variable(Valuation)\n"
295 " ConstantNumber(1.000000)\n"
297 " ConstantNumber(1.000000)\n"
298 " Variable(localCap)\n"
300 " Variable(localFloor)\n"
303 " Variable(Option)\n"
306 " OperatorMultiply\n"
307 " Variable(Notional)\n"
313 " Variable(globalCap)\n"
315 " Variable(globalFloor)\n"
317 " Variable(Valuation)\n"
319 " Variable(Settlement)\n"
321 " Variable(PayCcy)\n"
325 "NUMBER StrikePrice, KnockInPrice, Value;\n"
326 "NUMBER terminated, knockedIn, u, v;\n"
327 "FOR u IN (1, SIZE(Underlying), 1) DO\n"
328 " StrikePrice = StrikePrice + Underlying[u](StrikeDate);\n"
330 "StrikePrice = StrikePrice / SIZE(Underlying);\n"
331 "KnockInPrice = KnockInRatio * StrikePrice;\n"
332 "FOR v IN (1, SIZE(Valuation), 1) DO\n"
333 " IF v == SIZE(Valuation) AND knockedIn == 1 AND terminated == 0 THEN\n"
334 " Option = PAY(Notional * ( 1 - Value / StrikePrice), Valuation[v], Settlement[v], PayCcy);\n"
336 " IF v > 2 AND terminated == 0 THEN\n"
338 " FOR u IN (1, SIZE(Underlying), 1) DO\n"
339 " Value = Value + Underlying[u](Valuation[v]);\n"
341 " Value = Value / SIZE(Underlying);\n"
342 " IF Value > StrikePrice THEN\n"
343 " Option = PAY (Notional * v * 0.06, Valuation[v], Settlement[v], PayCcy);\n"
346 " IF Value < KnockInPrice THEN\n"
354 " DeclarationNumber\n"
355 " Variable(StrikePrice)\n"
357 " Variable(KnockInPrice)\n"
361 " DeclarationNumber\n"
362 " Variable(terminated)\n"
364 " Variable(knockedIn)\n"
371 " ConstantNumber(1.000000)\n"
372 " Size(Underlying)\n"
373 " ConstantNumber(1.000000)\n"
376 " Variable(StrikePrice)\n"
379 " Variable(StrikePrice)\n"
382 " Variable(Underlying)\n"
385 " Variable(StrikeDate)\n"
389 " Variable(StrikePrice)\n"
392 " Variable(StrikePrice)\n"
394 " Size(Underlying)\n"
396 " Variable(KnockInPrice)\n"
398 " OperatorMultiply\n"
399 " Variable(KnockInRatio)\n"
401 " Variable(StrikePrice)\n"
404 " ConstantNumber(1.000000)\n"
406 " ConstantNumber(1.000000)\n"
416 " Variable(knockedIn)\n"
418 " ConstantNumber(1.000000)\n"
420 " Variable(terminated)\n"
422 " ConstantNumber(0.000000)\n"
425 " Variable(Option)\n"
428 " OperatorMultiply\n"
429 " Variable(Notional)\n"
432 " ConstantNumber(1.000000)\n"
436 " Variable(StrikePrice)\n"
438 " Variable(Valuation)\n"
441 " Variable(Settlement)\n"
444 " Variable(PayCcy)\n"
452 " ConstantNumber(2.000000)\n"
454 " Variable(terminated)\n"
456 " ConstantNumber(0.000000)\n"
461 " ConstantNumber(0.000000)\n"
463 " ConstantNumber(1.000000)\n"
464 " Size(Underlying)\n"
465 " ConstantNumber(1.000000)\n"
474 " Variable(Underlying)\n"
477 " Variable(Valuation)\n"
487 " Size(Underlying)\n"
492 " Variable(StrikePrice)\n"
496 " Variable(Option)\n"
499 " OperatorMultiply\n"
500 " OperatorMultiply\n"
501 " Variable(Notional)\n"
505 " ConstantNumber(0.060000)\n"
506 " Variable(Valuation)\n"
509 " Variable(Settlement)\n"
512 " Variable(PayCcy)\n"
515 " Variable(terminated)\n"
517 " ConstantNumber(1.000000)\n"
523 " Variable(KnockInPrice)\n"
527 " Variable(knockedIn)\n"
529 " ConstantNumber(1.000000)\n"
534BOOST_FIXTURE_TEST_SUITE(OREDataTestSuite, ore::test::TopLevelFixture)
536BOOST_AUTO_TEST_SUITE(ScriptParserTest)
540 BOOST_TEST_MESSAGE(
"Testing Script Parser...");
544 BOOST_TEST_MESSAGE(
"Parsing succeeded\n" <<
to_string(parser.
ast()));
546 BOOST_TEST_MESSAGE(
"Parsing failed\n" << parser.
error());
548 BOOST_REQUIRE(parser.
success());
549 BOOST_CHECK_EQUAL(
to_string(parser.
ast(),
false), testScript.expectedAST);
554 BOOST_TEST_MESSAGE(
"Testing Script Parser AST->Script->AST Roundtrip...");
557 BOOST_REQUIRE(parser.
success());
559 BOOST_TEST_MESSAGE(
"Generated script:\n<<<<<<<<<<\n" +
script +
"\n>>>>>>>>>>");
561 BOOST_REQUIRE(parser2.
success());
567 BOOST_TEST_MESSAGE(
"Testing Script Parser Random AST->Script->AST Roundtrip...");
569 std::vector<std::tuple<Size, Size, Size>> testSizes;
570 testSizes.push_back(std::make_tuple(1, 5, 1000));
571 testSizes.push_back(std::make_tuple(5, 5, 1000));
572 testSizes.push_back(std::make_tuple(10, 5, 1000));
573 testSizes.push_back(std::make_tuple(1, 10, 1000));
574 testSizes.push_back(std::make_tuple(5, 10, 1000));
575 testSizes.push_back(std::make_tuple(10, 10, 100));
577 for (
auto const& t : testSizes) {
578 BOOST_TEST_MESSAGE(
"Testing Script Parser Random AST->Script->AST RoundTrip (len="
579 << std::get<0>(t) <<
", "
580 <<
"dep=" << std::get<1>(t) <<
", n=" << std::get<2>(t) <<
")");
582 double avgLen = 0.0, avgTiming = 0.0, maxTiming = 0.0;
583 for (Size i = 0; i < std::get<2>(t); ++i) {
586 maxLen = std::max(
script.length(), maxLen);
587 avgLen +=
static_cast<double>(
script.length()) /
static_cast<double>(std::get<2>(t));
588 boost::timer::cpu_timer timer;
591 BOOST_TEST_MESSAGE(
"Error while parsing script: " << parser.
error());
593 BOOST_REQUIRE(parser.
success());
594 double timing = timer.elapsed().wall * 1e-9;
595 maxTiming = std::max(timing, maxTiming);
596 avgTiming += timing /
static_cast<double>(std::get<2>(t));
599 BOOST_TEST_MESSAGE(
"Finished, script size avg = " << avgLen <<
", max = " << maxLen
600 <<
", timing avg = " << avgTiming * 1E3
601 <<
" ms, max = " << maxTiming * 1E3 <<
" ms");
609 BOOST_TEST_MESSAGE(
"Creating randomg script based on LEN, DEP and SEED env variables");
611 if (getenv(
"LEN") && getenv(
"DEP") && getenv(
"SEED")) {
612 auto ast =
generateRandomAST(atoi(getenv(
"LEN")), atoi(getenv(
"DEP")), atoi(getenv(
"SEED")));
614 BOOST_TEST_MESSAGE(
"Generated script:\n<<<<<<<<<<\n" +
script +
"\n>>>>>>>>>>");
622 BOOST_TEST_MESSAGE(
"Running Script Parser on INPUT env variable...");
624 std::string
script =
"IF x==2 THEN y=1; ELSE z=2; END;";
625 if (
auto c = getenv(
"INPUT"))
630 std::cout <<
"Parsing succeeded\n" <<
to_string(parser.
ast()) << std::endl;
632 std::cout <<
"Parsing failed\n" << parser.
error();
636BOOST_AUTO_TEST_SUITE_END()
638BOOST_AUTO_TEST_SUITE_END()
const ParserError & error() const
std::ostream & operator<<(std::ostream &out, EquityReturnType t)
ASTNodePtr generateRandomAST(const Size maxSequenceLength, const Size maxDepth, const Size seed)
std::string to_string(const LocationInfo &l)
std::string to_script(const ASTNodePtr root)
random ast generator for testing purposes
BOOST_DATA_TEST_CASE(testScriptParsing, boost::unit_test::data::make(scriptData), testScript)
BOOST_AUTO_TEST_CASE(testRandomRoundTrip)