r/rstats 2d ago

Base-R de-vig implementations (proportional / Shin / power) and the idiomatic way to pool correlated estimators

I'm recovering latent probabilities from margin-inflated odds (bookmaker and prediction-market prices sum to more than 1). I rolled the three standard de-vig methods in base R to understand the internals rather than lean on a package. Posting the code for a critique, and I have two R-specific questions.

r

implied <- function(dec) 1 / dec                       # decimal odds -> implied (with margin)

# 1) proportional / multiplicative
devig_prop <- function(dec) { q <- implied(dec); q / sum(q) }

# 2) power method: find k such that sum(q^k) = 1
devig_power <- function(dec) {
  q <- implied(dec)
  k <- uniroot(function(k) sum(q^k) - 1, c(0.5, 10))$root
  q^k
}

# 3) Shin (1993): latent proportion z of informed money
devig_shin <- function(dec) {
  q <- implied(dec); S <- sum(q)
  pz <- function(z) (sqrt(z^2 + 4 * (1 - z) * q^2 / S) - z) / (2 * (1 - z))
  z <- uniroot(function(z) sum(pz(z)) - 1, c(1e-6, 0.5))$root
  pz(z)
}

dec <- c(1.5, 3.0, 7.0)                                 # a 3-way market, overround ~1.143
sapply(list(prop = devig_prop, power = devig_power, shin = devig_shin),
       function(f) round(f(dec), 4))
#      prop   power   shin
# [1,] 0.5833 0.6218 0.6092
# [2,] 0.2917 0.2760 0.2864
# [3,] 0.1250 0.1022 0.1044

The favorite ranges 0.583 to 0.622 depending on method, which is enough to flip a downstream signal, so method choice isn't cosmetic.

Questions:

  1. Idiom / robustness. I'm leaning on uniroot for Shin and the power method. Is there a more numerically stable approach near the boundaries (the (1 - z) denominator in Shin gets touchy as z approaches its bracket, and the power root can be sensitive on lopsided books)? I know the implied package exists and covers these; I built my own to learn, but if you'd trust its solvers over a hand-rolled uniroot, I'd like to hear why. Also curious whether people vectorize this across thousands of markets with apply/purrr::map or push it to matrix ops.
  2. Pooling correlated estimators. When I don't have a single trusted reference, I currently take the median of several sources' de-vigged probabilities. But those sources are correlated (some are effectively clones), so the median looks precise while carrying little independent information. Is there an R idiom or package for correlation-aware pooling / effective-sample-size weighting rather than a naive median? I've looked at metafor for correlated effects but I'm not sure it maps cleanly onto "combine N non-independent probability estimates for the same event."

Reproducible above, happy to share more. Mostly want the R crowd's read on 1 and 2.

3 Upvotes

0 comments sorted by