Saw this approach and tried replication it with code in Python, following the steps outlined by @knrumsey. The results are similar.
# the libraries
import pandas as pd
import numpy as np
from scipy import stats
# for bootstrapping
rng = np.random.default_rng()
# random seed
import random
random.seed(42)
Data simulation and bootstrapping
# simulate data
n = 30 # sample size
x = np.round(np.random.uniform(low=0.0, high=100, size=n), 0)
print(x)
array([ 96., 76., 52., 89., 31., 40., 73., 30., 13., 75., 75.,
77., 75., 66., 25., 98., 41., 77., 47., 92., 29., 14.,
100., 49., 9., 20., 38., 39., 8., 29.])
# small function to calc index
def fn(s):
return np.var(s)/np.mean(s)**2 - 1/np.mean(s)
# call fn
theta_hat = fn(x)
print(theta_hat)
0.2744459152021498
# bootstrap samples
def bootstrap(sample, func, n_reps=1000, replace=True, shuffle=True, random_state=None):
boot_resamples = np.empty([n_reps])
def resample(sample, size=len(sample), replace=replace, shuffle=shuffle, axis=0):
return rng.choice(a=sample, size=size, axis=axis)
for i in range(n_reps):
boot_resamples[i] = func(resample(sample))
return boot_resamples
# call bootstrap function
theta_boot = bootstrap(sample=x, func=fn, n_reps=10000)
print(theta_boot)
array([0.22055184, 0.28982115, 0.35431769, ..., 0.25468442, 0.23192187,
0.25084865])
Plot the distribution
# Plot the distribution
import matplotlib.pyplot as plt
# plot bootstrap distribution
n, bins, patches = plt.hist(theta_boot, 30, density=True, facecolor='b', alpha=0.5)
plt.xlabel('theta')
plt.title('Bootstrap distribution')
plt.axvline(x=theta_hat, color='orange')
plt.show()

estimating z0 and the bca intervals
# Confidence intervals using the (percentile) Bootstrap
alpha = 0.05
p = np.quantile(theta_boot, [alpha/2, 1-alpha/2])
print(p)
# desired quantiles
u = [alpha/2, 1-alpha/2]
print('u:', u)
# compute constants
from scipy import stats
z0 = stats.norm.ppf(np.mean(theta_boot <= theta_hat))
print('z0:', z0)
zu = stats.norm.ppf(u)
print('zu:', zu)
a = 0.046
# adjusted quantiles
u_adjusted = stats.norm.cdf(z0 + (z0+zu)/(1-a*(z0+zu)))
print('u_adjusted:', u_adjusted)
# accelerated bootstrap CI
bca = np.quantile(theta_boot, u_adjusted)
print('bca:', bca)
u: [0.025, 0.975]
z0: 0.12540870112199437
zu: [-1.95996398 1.95996398]
u_adjusted: [0.05863013 0.9924932 ]
bca: [0.17385148 0.46037554]
Plot of the percentile and bca intervals
- red vertical bars = bca intervals
- blue vertical bars = percentile intervals
# plot percentile and bca intervals
n, bins, patches = plt.hist(theta_boot, 30, density=True, facecolor='b', alpha=0.5)
plt.xlabel('theta')
plt.title('Bootstrap distribution')
plt.axvline(x=theta_hat, color='orange')
for i in range(len(p)):
plt.axvline(x=p[i], color='blue')
for j in range(len(bca)):
plt.axvline(x=bca[j], color='red')
plt.show()

Estimate acceleration constant a
# estimate a
def jackknife(sample, func, theta_hat):
theta_jack = np.empty([sample.shape[0]])
for i in range(len(sample)):
# delete row 'i' from df and run function with row 'i' removed
jackknife_resample = np.delete(arr=sample, obj=i, axis=0)
theta_jack[i] = func(jackknife_resample)
I = (n-1)*(theta_hat - theta_jack)
return (np.sum(I**3)/np.sum(I**2)**1.5)/6
# call jackknife function
a = jackknife(sample=x, func=fn, theta_hat=theta_hat)
print(a)
0.04435518601382892