Skip to main content
Pro Feature. Requires a Pro or Ultra subscription. Get started at api.mathematicalcompany.com
What is this? Monte Carlo simulation assumes you know the data-generating distribution. Bootstrap methods don’t - they resample your actual data to estimate confidence intervals, standard errors, and p-values. Use bootstrap when you want to know if your edge is statistically real without making distributional assumptions.

Bootstrap Methods

Horizon provides 11 bootstrap variants and jackknife bias estimation, all implemented in Rust for performance. These are non-parametric alternatives to Monte Carlo that work directly from observed data. The bootstrap is especially valuable in prediction markets where returns are non-normal and sample sizes are small.

IID Bootstrap

bootstrap_mean(), bootstrap_sharpe(), bootstrap_var(), bootstrap_edge() - classic resampling with replacement.

Time-Series Bootstrap

block_bootstrap(), circular_block_bootstrap(), stationary_bootstrap() - preserve autocorrelation structure.

Hypothesis Testing

bootstrap_hypothesis_test() - permutation test to compare two strategies without distributional assumptions.

Jackknife

jackknife_bias() - leave-one-out bias and variance estimation with pseudovalues.

IID Bootstrap Functions

hz.bootstrap_mean

Confidence interval for the mean via IID resampling.
import horizon as hz

returns = [0.02, -0.01, 0.03, 0.01, -0.005, 0.015, 0.025, -0.008]
r = hz.bootstrap_mean(returns, n_resamples=10000, confidence=0.95, seed=42)
print(f"Mean: {r.point_estimate:.4f}")
print(f"95% CI: [{r.ci_lower:.4f}, {r.ci_upper:.4f}]")
print(f"Std error: {r.std_error:.4f}")

hz.bootstrap_sharpe

Confidence interval for the Sharpe ratio. Particularly useful because the Sharpe ratio’s sampling distribution is highly non-normal for small samples.
r = hz.bootstrap_sharpe(returns, n_resamples=10000, confidence=0.95, seed=42)
print(f"Sharpe: {r.point_estimate:.4f}")
print(f"95% CI: [{r.ci_lower:.4f}, {r.ci_upper:.4f}]")
# If CI includes zero, your Sharpe isn't significantly different from zero

hz.bootstrap_var

Confidence interval for Value-at-Risk.
r = hz.bootstrap_var(returns, var_level=0.05, n_resamples=10000, seed=42)
print(f"5% VaR: {r.point_estimate:.4f}")
print(f"95% CI: [{r.ci_lower:.4f}, {r.ci_upper:.4f}]")

hz.bootstrap_correlation

Confidence interval for Pearson correlation (paired resampling).
x = [0.5, 0.6, 0.7, 0.55, 0.65]
y = [0.48, 0.62, 0.71, 0.52, 0.68]
r = hz.bootstrap_correlation(x, y, n_resamples=10000, seed=42)
print(f"Correlation: {r.point_estimate:.4f}")
print(f"95% CI: [{r.ci_lower:.4f}, {r.ci_upper:.4f}]")

hz.bootstrap_edge

Confidence interval for prediction edge mean(outcome - prediction). This is the core bootstrap for prediction market edge estimation.
predictions = [0.55, 0.60, 0.45, 0.70, 0.50]
outcomes =    [1.0,  1.0,  0.0,  1.0,  0.0]
r = hz.bootstrap_edge(predictions, outcomes, n_resamples=10000, seed=42)
print(f"Edge: {r.point_estimate:.4f}")
print(f"95% CI: [{r.ci_lower:.4f}, {r.ci_upper:.4f}]")
if r.ci_lower > 0:
    print("Statistically significant positive edge!")

Time-Series Bootstrap

For autocorrelated data (e.g., cumulative returns, price series), IID resampling destroys the dependence structure. These variants preserve it.

hz.block_bootstrap

Moving block bootstrap (Kunsch 1989). Resamples contiguous blocks of data.
prices = [0.50, 0.51, 0.52, 0.51, 0.53, 0.54, 0.52, 0.55]
r = hz.block_bootstrap(prices, block_size=3, n_resamples=5000, seed=42)
print(f"Mean: {r.point_estimate:.4f}, CI: [{r.ci_lower:.4f}, {r.ci_upper:.4f}]")
ParameterTypeDescription
datalist[float]Time series data
block_sizeintSize of each contiguous block
n_resamplesintNumber of bootstrap resamples (default 10000)
confidencefloatConfidence level (default 0.95)
seedintRNG seed (default 42)

hz.circular_block_bootstrap

Politis-Romano circular variant. Wraps the data circularly so blocks can span the boundary. Reduces bias from edge effects.
r = hz.circular_block_bootstrap(prices, block_size=3, n_resamples=5000, seed=42)

hz.stationary_bootstrap

Politis-Romano stationary bootstrap. Block lengths are geometric random variables, making the resampled series stationary.
r = hz.stationary_bootstrap(prices, expected_block_size=5.0, n_resamples=5000, seed=42)
ParameterTypeDescription
expected_block_sizefloatExpected block length (geometric distribution)

Hypothesis Testing

hz.bootstrap_hypothesis_test

Two-sample permutation test. Tests whether two samples come from distributions with the same mean.
strategy_a = [0.02, 0.01, 0.03, -0.01, 0.015]
strategy_b = [0.005, -0.01, 0.01, -0.005, 0.002]

r = hz.bootstrap_hypothesis_test(strategy_a, strategy_b, n_resamples=10000, seed=42)
print(f"Test statistic: {r.test_statistic:.4f}")
print(f"P-value: {r.p_value:.4f}")
print(f"Reject H0: {r.reject}")  # True if p < 0.05

Prediction Intervals

hz.bootstrap_prediction_interval

Build prediction intervals from residual resampling. Useful for forecasting.
residuals = [-0.05, -0.02, 0.01, 0.03, -0.01, 0.04, -0.03]
forecast = 0.65
r = hz.bootstrap_prediction_interval(residuals, forecast, n_resamples=10000, seed=42)
print(f"Forecast: {r.point_estimate:.4f}")
print(f"95% PI: [{r.ci_lower:.4f}, {r.ci_upper:.4f}]")

Jackknife

hz.jackknife_bias

Leave-one-out jackknife for bias and variance estimation.
data = [0.02, 0.01, 0.03, -0.01, 0.015, 0.025]
r = hz.jackknife_bias(data, statistic="mean")
print(f"Estimate: {r.estimate:.4f}")
print(f"Bias: {r.bias:.6f}")
print(f"Std error: {r.std_error:.4f}")
print(f"Pseudovalues: {len(r.pseudovalues)}")
ParameterTypeDescription
datalist[float]Input data
statisticstrOne of "mean", "sharpe", "var" (default "mean")

Result Types

BootstrapResult

FieldTypeDescription
point_estimatefloatOriginal sample statistic
ci_lowerfloatLower confidence bound
ci_upperfloatUpper confidence bound
std_errorfloatBootstrap standard error
n_resamplesintNumber of resamples used
biasfloatBootstrap bias estimate

BootstrapHypothesisResult

FieldTypeDescription
test_statisticfloatObserved difference in means
p_valuefloatTwo-sided p-value
ci_lowerfloatLower CI of permutation distribution
ci_upperfloatUpper CI of permutation distribution
rejectboolTrue if p-value < 0.05

JackknifeResult

FieldTypeDescription
estimatefloatFull-sample statistic
biasfloatJackknife bias estimate
std_errorfloatJackknife standard error
pseudovalueslist[float]Leave-one-out pseudovalues

Pipeline Integration

hz.bootstrap_edge_tracker

Tracks bootstrap CI for prediction edge in a live pipeline. Accumulates (prediction, outcome) pairs per market and computes CIs when the window fills.
hz.run(
    pipeline=[
        my_model,
        my_quoter,
        hz.bootstrap_edge_tracker(window=100, n_resamples=5000, confidence=0.95),
    ],
    ...
)
# Injects into ctx.params: "bootstrap_edge" = {edge, ci_lower, ci_upper, is_significant}

hz.bootstrap_strategy_test

Compares two strategies’ returns using a permutation test.
hz.run(
    pipeline=[
        hz.bootstrap_strategy_test("returns_a", "returns_b"),
    ],
    ...
)
# Reads "returns_a" and "returns_b" from ctx.params
# Injects: "strategy_test" = {test_statistic, p_value, reject}