Implements the product-form test martingale $$E_t = \prod_{r=1}^{t} (1 + \lambda_r \hat\delta_r)$$ for testing the strong null \(H_0^s(p, q): \delta_t \le 0\) for all t.
Arguments
- scores1
Numeric vector. Scores S(p_t, y_t) for forecaster 1.
- scores2
Numeric vector. Scores S(q_t, y_t) for forecaster 2.
- c_t
Numeric scalar or vector (same length as scores) of predictable bounds such that |scores1 - scores2| <= c_t / 2 almost surely at every step.
- lambda_t
Optional numeric vector of predictable betting fractions in
[0, 1/c_t]. IfNULL(default), uses the fixed fractionlambda_t = 1 / (2 * c_t).- clip_max
Numeric. Maximum e-process value before clipping. Default: 1e7.
Examples
set.seed(123)
T_sim <- 100
y <- rbinom(T_sim, size = 1, prob = 0.7)
# Forecaster 1 has a genuine edge (closer to true probability 0.7)
p1 <- runif(T_sim, 0.5, 0.9)
# Forecaster 2 is just guessing uniformly
p2 <- runif(T_sim, 0.1, 0.9)
# 1. Compute positively oriented Brier scores
s1 <- brier_score(p1, y)
s2 <- brier_score(p2, y)
# 2. Establish the bound.
# Brier scores lie in [-1, 0], so the maximum absolute difference is 1.
# eprocess_betting() requires |s1 - s2| <= c_t / 2, so c_t = 2 is globally valid.
res <- eprocess_betting(scores1 = s1, scores2 = s2, c_t = 2)
# The e-process e_pq tests the null that Forecaster 1 is NOT better than Forecaster 2.
# Because Forecaster 1 is genuinely better, e_pq accumulates massive evidence.
head(res)
#> t e_pq e_qp log_e_pq log_e_qp
#> 1 1 1.1087765 0.8912235 0.103257132 -0.11516001
#> 2 2 1.2074162 0.8119379 0.188482723 -0.20833145
#> 3 3 1.2323886 0.7951450 0.208954197 -0.22923078
#> 4 4 1.0736001 0.8975963 0.071017566 -0.10803481
#> 5 5 0.9924524 0.9654409 -0.007576227 -0.03517044
#> 6 6 0.9968299 0.9611825 -0.003175163 -0.03959096
tail(res, 3)
#> t e_pq e_qp log_e_pq log_e_qp
#> 98 98 2.921947 0.1607555 1.072250 -1.827870
#> 99 99 3.273225 0.1414294 1.185776 -1.955955
#> 100 100 3.268909 0.1416159 1.184456 -1.954637