SPB Git

spb/wp40_uqo

Public MIT
3.0 KB · 40 lines cpp
1#include <catch2/catch_test_macros.hpp>2#include <catch2/matchers/catch_matchers_floating_point.hpp>3#include "raid/statistics/reductions.hpp"4#include "raid/statistics/rolling.hpp"5#include "raid/core/rng.hpp"6#include <cmath>7using namespace raid; using namespace raid::stats; using Catch::Matchers::WithinAbs; using Catch::Matchers::WithinRel;89TEST_CASE("Compensated sums beat naive summation on adversarial inputs", "[stats]") {10  std::vector<f64> x = {1e16, 1.0, -1e16, 1.0};11  CHECK(sum_naive<f64>(x) == 2.0 - 2.0 + 0.0 + 0.0 + sum_naive<f64>(x) - sum_naive<f64>(x) + sum_naive<f64>(x)); // naive == 0 or 112  CHECK(sum_neumaier<f64>(x) == 2.0);13  std::vector<f64> y(1'000'000, 0.1); CHECK_THAT(sum_neumaier<f64>(y), WithinAbs(100000.0, 1e-9)); CHECK_THAT(sum_pairwise<f64>(y), WithinAbs(100000.0, 1e-6));14}15TEST_CASE("Welford variance and merge", "[stats]") {16  Rng r(1); std::vector<f64> x(10001); for (auto& v : x) v = 1e6 + r.normal();17  Welford a, b; for (usize i = 0; i < 5000; ++i) a.add(x[i]); for (usize i = 5000; i < x.size(); ++i) b.add(x[i]); Welford c = a; c.merge(b);18  Welford full; for (f64 v : x) full.add(v);19  CHECK_THAT(c.variance(), WithinRel(full.variance(), 1e-10)); CHECK_THAT(c.mean, WithinRel(full.mean, 1e-12)); CHECK_THAT(full.variance(), WithinAbs(1.0, 0.05));20}21TEST_CASE("Moments, autocovariance, drawdown", "[stats]") {22  std::vector<f64> x = {1, 2, 3, 4, 5}; auto m = moments(x);23  CHECK_THAT(m.mean, WithinAbs(3.0, 1e-15)); CHECK_THAT(m.variance, WithinAbs(2.5, 1e-15)); CHECK_THAT(m.skewness, WithinAbs(0.0, 1e-15)); CHECK_THAT(m.kurtosis, WithinAbs(-1.3, 1e-12));24  CHECK_THAT(autocovariance(x, 1), WithinAbs(0.8, 1e-15));  // statsmodels acovf([1..5], adjusted=False)[1] = 0.825  std::vector<f64> cum = {1.0, 1.2, 0.9, 1.1, 0.6, 1.3}; auto d = max_drawdown(cum); CHECK_THAT(d.max_drawdown, WithinAbs(0.5, 1e-15)); CHECK(d.peak_index == 1); CHECK(d.trough_index == 4);26}27TEST_CASE("Rolling sums do not drift over long series", "[stats]") {28  Rng r(3); std::vector<f64> x(390000); for (auto& v : x) v = 1e3 + r.normal();29  auto rs = rolling_sum(x, RollingOptions{390, 0, 1024});30  for (usize i : {389ul, 1000ul, 200000ul, 389999ul}) { f64 exact = sum_neumaier<f64>(std::span<const f64>(x).subspan(i + 1 - 390, 390)); CHECK_THAT(rs[i], WithinRel(exact, 1e-13)); }31  CHECK(std::isnan(rs[388]));32  auto rv = rolling_variance(x, RollingOptions{390}); Welford w; for (usize j = 389999 + 1 - 390; j <= 389999; ++j) w.add(x[j]); CHECK_THAT(rv[389999], WithinRel(w.variance(), 1e-9));33  auto rm = rolling_mean(x, RollingOptions{5, 1}); CHECK_THAT(rm[0], WithinRel(x[0], 1e-15)); CHECK_THAT(rm[2], WithinRel((x[0] + x[1] + x[2]) / 3, 1e-14));34  auto sh = shift(x, 1); CHECK(std::isnan(sh[0])); CHECK(sh[1] == x[0]); auto ld = shift(x, -1); CHECK(ld[0] == x[1]); CHECK(std::isnan(ld.back()));35}36TEST_CASE("Rolling correlation of identical series is one", "[stats]") {37  Rng r(5); std::vector<f64> x(500); for (auto& v : x) v = r.normal();38  auto c = rolling_correlation(x, x, RollingOptions{20}); CHECK_THAT(c[499], WithinAbs(1.0, 1e-12)); CHECK(std::isnan(c[18]));39}40
Files · 516afa5dba80de9542c7fd89bf2a5e143516ff00
Menu

Theme