Skip to content

Commit

Permalink
Merge pull request #1057.
Browse files Browse the repository at this point in the history
Reduce run time for longest-running test cases.
  • Loading branch information
lballabio committed Feb 28, 2021
2 parents 9aa5cfb + dc82ea9 commit f69b36c
Show file tree
Hide file tree
Showing 26 changed files with 316 additions and 259 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/test-times.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Check test times
on: [push, pull_request]
jobs:
check-test-times:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Cache
uses: actions/cache@v2
with:
path: ~/.ccache
key: linux-build-times-${{ github.ref }}-${{ github.head_ref }}-${{ hashFiles('**/*.hpp', '**/*.cpp') }}
restore-keys: |
linux-build-times-${{ github.ref }}-${{ github.head_ref }}-
linux-build-times-${{ github.ref }}-
linux-build-times-refs/heads/master-
linux-build-times-
- name: Setup
run: |
sudo apt install -y libboost-all-dev autoconf automake libtool ccache
- name: Build
run: |
./autogen.sh
./configure --disable-static CC="ccache gcc" CXX="ccache g++" CXXFLAGS="-O2 -g0"
make -j 2
- name: Run tests
run: |
./test-suite/quantlib-test-suite --logger=JUNIT,warning,faster.xml:HRF,message -- --faster
./test-suite/quantlib-test-suite --logger=JUNIT,warning,fast.xml:HRF,message -- --fast
./test-suite/quantlib-test-suite --logger=JUNIT,warning,all.xml:HRF,message
- name: Save test times
uses: actions/upload-artifact@v2
with:
name: test-reports
path: ./all.xml
- name: Check test times
run: |
python ./tools/check_test_times.py
19 changes: 9 additions & 10 deletions test-suite/americanoption.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -604,21 +604,20 @@ void AmericanOptionTest::testFDShoutNPV() {
}
}

test_suite* AmericanOptionTest::suite() {
test_suite* AmericanOptionTest::suite(SpeedLevel speed) {
auto* suite = BOOST_TEST_SUITE("American option tests");
suite->add(
QUANTLIB_TEST_CASE(&AmericanOptionTest::testBaroneAdesiWhaleyValues));
suite->add(
QUANTLIB_TEST_CASE(&AmericanOptionTest::testBjerksundStenslandValues));
// FLOATING_POINT_EXCEPTION

suite->add(QUANTLIB_TEST_CASE(&AmericanOptionTest::testBaroneAdesiWhaleyValues));
suite->add(QUANTLIB_TEST_CASE(&AmericanOptionTest::testBjerksundStenslandValues));
suite->add(QUANTLIB_TEST_CASE(&AmericanOptionTest::testJuValues));
// FLOATING_POINT_EXCEPTION
suite->add(QUANTLIB_TEST_CASE(&AmericanOptionTest::testFdValues));
// FLOATING_POINT_EXCEPTION
suite->add(QUANTLIB_TEST_CASE(&AmericanOptionTest::testFdAmericanGreeks));
// FLOATING_POINT_EXCEPTION
suite->add(QUANTLIB_TEST_CASE(&AmericanOptionTest::testFdShoutGreeks));
suite->add(QUANTLIB_TEST_CASE(&AmericanOptionTest::testFDShoutNPV));

if (speed <= Fast) {
suite->add(QUANTLIB_TEST_CASE(&AmericanOptionTest::testFdShoutGreeks));
}

return suite;
}

3 changes: 2 additions & 1 deletion test-suite/americanoption.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#define quantlib_test_american_option_hpp

#include <boost/test/unit_test.hpp>
#include "speedlevel.hpp"

/* remember to document new and/or updated tests in the Doxygen
comment block of the corresponding class */
Expand All @@ -36,7 +37,7 @@ class AmericanOptionTest {
static void testFdAmericanGreeks();
static void testFdShoutGreeks();
static void testFDShoutNPV();
static boost::unit_test_framework::test_suite* suite();
static boost::unit_test_framework::test_suite* suite(SpeedLevel);
};


Expand Down
107 changes: 56 additions & 51 deletions test-suite/asianoptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,15 +514,23 @@ void testDiscreteGeometricAveragePriceHeston(const ext::shared_ptr<PricingEngine

// data from "A Recursive Method for Discretely Monitored Geometric Asian Option
// Prices", Kim, Kim, Kim & Wee, Bull. Korean Math. Soc. 53, 733-749, 2016
int days[] = {30, 91, 182, 365, 730, 1095, 30, 91, 182, 365, 730, 1095, 30,
91, 182, 365, 730, 1095};
Real strikes[] = {90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 110,
110, 110, 110, 110, 110};
int days[] = {
30, 91, 182, 365, 730, 1095,
30, 91, 182, 365, 730, 1095,
30, 91, 182, 365, 730, 1095
};
Real strikes[] = {
90, 90, 90, 90, 90, 90,
100, 100, 100, 100, 100, 100,
110, 110, 110, 110, 110, 110
};

// Prices from Tables 1, 2 and 3
Real prices[] = {10.2732, 10.9554, 11.9916, 13.6950, 16.1773, 18.0146, 2.4389,
3.7881, 5.2132, 7.2243, 9.9948, 12.0639, 0.1012, 0.5949, 1.4444,
2.9479, 5.3531, 7.3315};
Real prices[] = {
10.2732, 10.9554, 11.9916, 13.6950, 16.1773, 18.0146,
2.4389, 3.7881, 5.2132, 7.2243, 9.9948, 12.0639,
0.1012, 0.5949, 1.4444, 2.9479, 5.3531, 7.3315
};

DayCounter dc = Actual365Fixed();
Date today = Settings::instance().evaluationDate();
Expand Down Expand Up @@ -616,9 +624,11 @@ void AsianOptionTest::testMCDiscreteGeometricAveragePriceHeston() {

// 30-day options need wider tolerance due to uncertainty around what "weekly
// fixing" dates mean over a 30-day month!
Real tol[] = {4.0e-2, 2.0e-2, 2.0e-2, 3.0e-2, 3.0e-2, 2.0e-2, 1.0e-1, 1.0e-2,
2.0e-2, 2.0e-2, 2.0e-2, 1.0e-2, 2.0e-2, 1.0e-2, 1.0e-2, 1.0e-2,
1.0e-2, 1.0e-2};
Real tol[] = {
4.0e-2, 2.0e-2, 2.0e-2, 3.0e-2, 3.0e-2, 6.0e-2,
1.0e-1, 1.0e-2, 2.0e-2, 2.0e-2, 4.0e-2, 6.0e-2,
2.0e-2, 1.0e-2, 1.0e-2, 1.0e-2, 4.0e-2, 6.0e-2
};

DayCounter dc = Actual365Fixed();
Date today = Settings::instance().evaluationDate();
Expand All @@ -641,7 +651,7 @@ void AsianOptionTest::testMCDiscreteGeometricAveragePriceHeston() {

ext::shared_ptr<PricingEngine> engine =
MakeMCDiscreteGeometricAPHestonEngine<LowDiscrepancy>(hestonProcess)
.withSamples(65535)
.withSamples(32767)
.withSeed(43);

testDiscreteGeometricAveragePriceHeston(engine, tol);
Expand Down Expand Up @@ -965,7 +975,7 @@ void AsianOptionTest::testMCDiscreteArithmeticAveragePriceHeston() {
ext::shared_ptr<PricingEngine> engine =
MakeMCDiscreteArithmeticAPHestonEngine<LowDiscrepancy>(hestonProcess)
.withSeed(42)
.withSamples(32768);
.withSamples(8191);

DiscreteAveragingAsianOption option(averageType, runningSum,
pastFixings, fixingDates,
Expand All @@ -989,7 +999,7 @@ void AsianOptionTest::testMCDiscreteArithmeticAveragePriceHeston() {
MakeMCDiscreteArithmeticAPHestonEngine<LowDiscrepancy>(hestonProcess)
.withSeed(42)
.withSteps(48)
.withSamples(8192)
.withSamples(8191)
.withControlVariate(true);

option.setPricingEngine(engine2);
Expand Down Expand Up @@ -1039,14 +1049,14 @@ void AsianOptionTest::testMCDiscreteArithmeticAveragePriceHeston() {
ext::shared_ptr<PricingEngine> engine3 =
MakeMCDiscreteArithmeticAPHestonEngine<LowDiscrepancy>(hestonProcess2)
.withSeed(42)
.withSteps(360)
.withSamples(32768);
.withSteps(180)
.withSamples(32767);

ext::shared_ptr<PricingEngine> engine4 =
MakeMCDiscreteArithmeticAPHestonEngine<LowDiscrepancy>(hestonProcess2)
.withSeed(42)
.withSteps(360)
.withSamples(16384)
.withSteps(180)
.withSamples(16383)
.withControlVariate(true);

std::vector<Date> fixingDates(120);
Expand All @@ -1057,7 +1067,7 @@ void AsianOptionTest::testMCDiscreteArithmeticAveragePriceHeston() {
ext::shared_ptr<Exercise> exercise(new
EuropeanExercise(fixingDates[119]));

for (Size i=0; i<5; i++) {
for (Size i=0; i<LENGTH(prices); i++) {
Real strike = strikes[i];
Real expected = prices[i];

Expand All @@ -1070,7 +1080,7 @@ void AsianOptionTest::testMCDiscreteArithmeticAveragePriceHeston() {

option.setPricingEngine(engine3);
Real calculated = option.NPV();
Real tolerance = 5.0e-2;
Real tolerance = 6.0e-2;

if (std::fabs(calculated-expected) > tolerance) {
REPORT_FAILURE("value", averageType, runningSum, pastFixings,
Expand Down Expand Up @@ -1984,46 +1994,41 @@ void AsianOptionTest::testAnalyticContinuousGeometricAveragePriceHeston() {

}

test_suite* AsianOptionTest::suite() {
test_suite* AsianOptionTest::suite(SpeedLevel speed) {
auto* suite = BOOST_TEST_SUITE("Asian option tests");

suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testAnalyticContinuousGeometricAveragePrice));
suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testAnalyticContinuousGeometricAveragePriceGreeks));
suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testAnalyticDiscreteGeometricAveragePrice));
suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testAnalyticDiscreteGeometricAverageStrike));
suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testMCDiscreteGeometricAveragePrice));
suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testMCDiscreteGeometricAveragePriceHeston));
suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testMCDiscreteArithmeticAveragePrice));
suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testMCDiscreteArithmeticAveragePriceHeston));
suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testMCDiscreteArithmeticAverageStrike));
suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testAnalyticDiscreteGeometricAveragePriceGreeks));
suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testPastFixings));
suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testAllFixingsInThePast));
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testAnalyticContinuousGeometricAveragePrice));
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testAnalyticContinuousGeometricAveragePriceGreeks));
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testAnalyticDiscreteGeometricAveragePrice));
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testAnalyticDiscreteGeometricAverageStrike));
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testMCDiscreteGeometricAveragePrice));
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testMCDiscreteArithmeticAverageStrike));
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testAnalyticDiscreteGeometricAveragePriceGreeks));
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testPastFixings));
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testAllFixingsInThePast));

if (speed <= Fast) {
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testMCDiscreteArithmeticAveragePrice));
}

if (speed == Slow) {
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testMCDiscreteGeometricAveragePriceHeston));
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testMCDiscreteArithmeticAveragePriceHeston));
}

return suite;
}

test_suite* AsianOptionTest::experimental() {
test_suite* AsianOptionTest::experimental(SpeedLevel speed) {
auto* suite = BOOST_TEST_SUITE("Asian option experimental tests");
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testLevyEngine));
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testVecerEngine));
suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testAnalyticContinuousGeometricAveragePriceHeston));
suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testAnalyticDiscreteGeometricAveragePriceHeston));
suite->add(QUANTLIB_TEST_CASE(
&AsianOptionTest::testDiscreteGeometricAveragePriceHestonPastFixings));
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testAnalyticContinuousGeometricAveragePriceHeston));
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testAnalyticDiscreteGeometricAveragePriceHeston));

if (speed <= Fast) {
suite->add(QUANTLIB_TEST_CASE(&AsianOptionTest::testDiscreteGeometricAveragePriceHestonPastFixings));
}

return suite;
}
5 changes: 3 additions & 2 deletions test-suite/asianoptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#define quantlib_test_asian_options_hpp

#include <boost/test/unit_test.hpp>
#include "speedlevel.hpp"

/* remember to document new and/or updated tests in the Doxygen
comment block of the corresponding class */
Expand All @@ -46,8 +47,8 @@ class AsianOptionTest {
static void testAllFixingsInThePast();
static void testLevyEngine();
static void testVecerEngine();
static boost::unit_test_framework::test_suite* suite();
static boost::unit_test_framework::test_suite* experimental();
static boost::unit_test_framework::test_suite* suite(SpeedLevel);
static boost::unit_test_framework::test_suite* experimental(SpeedLevel);
};


Expand Down
4 changes: 2 additions & 2 deletions test-suite/brownianbridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ void BrownianBridgeTest::testPathGeneration() {

Size N = times.size();

Size samples = 262143;
Size samples = 131071;
unsigned long seed = 42;
SobolRsg sobol(N, seed);
InverseCumulativeRsg<SobolRsg,InverseCumulativeNormal> gsg(sobol);
Expand Down Expand Up @@ -218,7 +218,7 @@ void BrownianBridgeTest::testPathGeneration() {
std::vector<Real> mean = stats2.mean();
Matrix covariance = stats2.covariance();

Real meanTolerance = 1.5e-5;
Real meanTolerance = 3.0e-5;
Real covTolerance = 3.0e-3;

Real maxMeanError = maxRelDiff(mean.begin(), mean.end(),
Expand Down
20 changes: 7 additions & 13 deletions test-suite/distributions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -760,19 +760,13 @@ test_suite* DistributionTest::suite(SpeedLevel speed) {
suite->add(QUANTLIB_TEST_CASE(&DistributionTest::testBivariate));
suite->add(QUANTLIB_TEST_CASE(&DistributionTest::testPoisson));
suite->add(QUANTLIB_TEST_CASE(&DistributionTest::testCumulativePoisson));
suite->add(QUANTLIB_TEST_CASE(
&DistributionTest::testInverseCumulativePoisson));
suite->add(QUANTLIB_TEST_CASE(
&DistributionTest::testBivariateCumulativeStudent));
suite->add(QUANTLIB_TEST_CASE(
&DistributionTest::testInvCDFviaStochasticCollocation));

suite->add(QUANTLIB_TEST_CASE(
&DistributionTest::testSankaranApproximation));

if (speed <= Fast) {
suite->add(QUANTLIB_TEST_CASE(
&DistributionTest::testBivariateCumulativeStudentVsBivariate));
suite->add(QUANTLIB_TEST_CASE(&DistributionTest::testInverseCumulativePoisson));
suite->add(QUANTLIB_TEST_CASE(&DistributionTest::testBivariateCumulativeStudent));
suite->add(QUANTLIB_TEST_CASE(&DistributionTest::testInvCDFviaStochasticCollocation));
suite->add(QUANTLIB_TEST_CASE(&DistributionTest::testSankaranApproximation));

if (speed == Slow) {
suite->add(QUANTLIB_TEST_CASE(&DistributionTest::testBivariateCumulativeStudentVsBivariate));
}

return suite;
Expand Down
29 changes: 16 additions & 13 deletions test-suite/doublebarrieroption.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ void DoubleBarrierOptionTest::testMonteCarloDoubleBarrierWithAnalytical() {

ext::shared_ptr<PricingEngine> mcdoublebarrierengine;
mcdoublebarrierengine = MakeMCDoubleBarrierEngine<PseudoRandom>(bsmProcess)
.withSteps(10000)
.withSteps(5000)
.withAntitheticVariate()
.withAbsoluteTolerance(0.5)
.withSeed(1);
Expand All @@ -618,18 +618,20 @@ void DoubleBarrierOptionTest::testMonteCarloDoubleBarrierWithAnalytical() {
knockOutDoubleBarrierOption.setPricingEngine(analyticdoublebarrierengine);
analytical = knockOutDoubleBarrierOption.NPV();

tolerance = 0.01;

mcdoublebarrierengine = MakeMCDoubleBarrierEngine<PseudoRandom>(bsmProcess)
.withSteps(10000)
.withAntitheticVariate()
.withAbsoluteTolerance(0.005)
.withSeed(3);
.withAbsoluteTolerance(tolerance)
.withSeed(10);
knockOutDoubleBarrierOption.setPricingEngine(mcdoublebarrierengine);
monteCarlo = knockOutDoubleBarrierOption.NPV();

percentageDiff = std::abs(analytical - monteCarlo) / analytical;
Real diff = std::abs(analytical - monteCarlo);

if (percentageDiff > tolerance){
REPORT_FAILURE_DOUBLE_BARRIER_MC(analytical, monteCarlo, percentageDiff);
if (diff > tolerance){
REPORT_FAILURE_DOUBLE_BARRIER_MC(analytical, monteCarlo, diff);
}

}
Expand All @@ -638,18 +640,19 @@ test_suite* DoubleBarrierOptionTest::suite(SpeedLevel speed) {
auto* suite = BOOST_TEST_SUITE("DoubleBarrier");

if (speed <= Fast) {
suite->add(QUANTLIB_TEST_CASE(
&DoubleBarrierOptionTest::testEuropeanHaugValues));
suite->add(QUANTLIB_TEST_CASE(&DoubleBarrierOptionTest::testEuropeanHaugValues));
}

return suite;
}

test_suite* DoubleBarrierOptionTest::experimental() {
test_suite* DoubleBarrierOptionTest::experimental(SpeedLevel speed) {
auto* suite = BOOST_TEST_SUITE("DoubleBarrier_experimental");
suite->add(QUANTLIB_TEST_CASE(
&DoubleBarrierOptionTest::testVannaVolgaDoubleBarrierValues));
suite->add(QUANTLIB_TEST_CASE(
&DoubleBarrierOptionTest::testMonteCarloDoubleBarrierWithAnalytical));
suite->add(QUANTLIB_TEST_CASE(&DoubleBarrierOptionTest::testVannaVolgaDoubleBarrierValues));

if (speed == Slow) {
suite->add(QUANTLIB_TEST_CASE(&DoubleBarrierOptionTest::testMonteCarloDoubleBarrierWithAnalytical));
}

return suite;
}
Loading

0 comments on commit f69b36c

Please sign in to comment.