---
title: "Sensitivity Analysis with tvbounds"
author: "Filippo Palomba"
output:
  rmarkdown::html_vignette:
    toc: true
vignette: >
  %\VignetteIndexEntry{Sensitivity Analysis with tvbounds}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup-knitr, include = FALSE}
knitr::opts_chunk$set(
  collapse  = TRUE,
  comment   = "#>",
  fig.width = 6.5,
  fig.height = 4,
  fig.align = "center",
  out.width = "92%"
)
```

```{r setup, message = FALSE}
library(tvbounds)
library(ggplot2)
```

## 1. The framework in a nutshell

Empirical conclusions often rest on untestable distributional assumptions:
that attrition in a randomized experiment is as good as random, that the
exogenous shocks in a formula instrument were assigned by the mechanism
the design postulates, or that the preference shocks in a discrete choice model
follow an extreme-value distribution. Each of them amounts to a choice of
distribution for an object the data does not identify, and a stakeholder may
reasonably ask by how much the reported conclusion would change were that
choice wrong. **tvbounds** implements the sensitivity analysis of Palomba
(2026), which answers this question and computes sensitivity bounds, for
randomized experiments with attrition, counterfactuals in structural models,
and recentered (formula) instrumental variables.

The exercise rests on three ingredients:

* an **estimand** $\mathbb{E}_P[g(Z;\theta)]$, the expectation of a known
  function $g$ of a random vector $Z$ under a distribution $P$, indexed by
  a structural parameter $\theta \in \Theta$ in the applications that carry
  one;
* a **baseline distribution** $P_{*}$, the distribution the econometrician
  would use absent any concern for misspecification;
* a **budget** $\delta \in [0, 1]$, the sensitivity parameter, which caps
  the discrepancy from the baseline we are willing to entertain.

The candidate distributions the package optimizes over form the
**robustness set**
$$
\mathcal{P}_\phi(\theta; \rho, P_{*}, \delta)
  = \{P : \mathbb{E}_P[m(Z;\theta)] \in \mathcal{M}(\rho), \;\;
          D_\phi(P \,\|\, P_{*}) \le \delta\},
$$
which collects the distributions that remain compatible with the model,
where $m$ is the moment function and $\mathcal{M}(\rho)$ the moment
constraint set at the target $\rho$, and that lie within $\delta$ of the
baseline in the divergence $D_\phi$ selected by an entropy function $\phi$.
We abbreviate it $\mathcal{P}_\phi(\theta;\delta)$ whenever the target and
the baseline are clear from the context. At $\delta = 0$ the baseline is the
only admissible distribution.

Our preferred divergence is the one generated by the total variation entropy
$\phi_{\mathsf{TV}}(s) = |s - 1| / 2$, for which
$D_{\phi_{\mathsf{TV}}}(P \,\|\, P_{*}) = \mathsf{TV}(P, P_{*})$. A
distribution within total variation distance $\delta$ of the baseline agrees
with it except on at most a $\delta$-fraction of the baseline probability
mass, so that $\delta$ reads as the fraction of the mass in $P_{*}$ that may
be misspecified. The second neighborhood available in the package is the
*contamination* neighborhood in the tradition of Huber (1964), which
collects the distributions of the mixture form
$P = (1-\delta) P_{*} + \delta R$ for an arbitrary distribution $R$,
equivalently $P \ge (1-\delta) P_{*}$ as measures. It follows that $(1-\delta)$-share of
the population is distributed exactly as the baseline and only the remaining
$\delta$-share is left arbitrary. Since every such mixture lies within total variation
distance $\delta$ of the baseline, the contamination bounds are weakly
tighter at every budget than the total variation one.

Given the estimand, the baseline, and the budget, the package reports
**sensitivity bounds**
$$
\Big[\;\inf_{\theta \in \Theta} \; \inf_{P \in \mathcal{P}_\phi(\theta;\delta)} \mathbb{E}_P[g(Z;\theta)],\;\;
\sup_{\theta \in \Theta} \; \sup_{P \in \mathcal{P}_\phi(\theta;\delta)} \mathbb{E}_P[g(Z;\theta)]\;\Big],
$$
the extreme values the estimand can take over the robustness set. They are
nested extrema of the same sign rather than a minimax, and they trace the
exact range of the estimand: every value inside the bounds is attained by
some distribution in the robustness set, and no value outside is. The
exercise reports the whole path of the bounds as the budget varies over the
range of the chosen divergence. At $\delta = 0$ the interval collapses to
the baseline value of the estimand and, as $\delta$ grows, it widens
monotonically; the budget at which the bounds first reach a
reference value $\tau_{\star}$ (zero, say, at which the sign of the effect
is no longer identified) is the **breakdown budget**
$\delta_b(\tau_{\star})$, the direct answer to the question of how much
misspecification would overturn the conclusion.

The package provides three interfaces, one per empirical application of the
paper.

* **Randomized experiments with attrition** —
  `tvbounds_attrition()` bounds the average treatment effect when outcomes
  are recorded only for respondents and attrition may be selective. At
  $\delta = 0$ the bounds collapse to the baseline difference in means among
  respondents and at $\delta = 1$ they coincide with the trimming bounds of
  Lee (2009). Bootstrap standard errors and confidence intervals, optionally
  with cluster resampling, and covariate-pooled bounds are also available.

* **Recentered instrumental variables** — `tvbounds_riv()` bounds a
  recentered (formula) instrumental-variables estimate in the design of
  Borusyak and Hull (2023), where identification rests on a distribution for
  the shocks that the researcher postulates. The bounds trace how far the
  estimate can move when up to a $\delta$-fraction of the postulated
  distribution is misspecified, and a first-stage breakdown budget records
  the budget at which the design itself collapses. The exercise is
  conducted conditionally on the realized sample and carries no inference by
  design.

* **Counterfactual predictions in structural models** —
  `tvbounds_counterfactual()` bounds a counterfactual of a structural model
  when the distribution of the latent variables ranges over a divergence
  neighborhood of the simulated baseline $P_{*}$, as in
  Christensen and Connault (2023). It is the only function that supports
  divergences beyond total variation and contamination, and it relies on
  Julia and on the commercial Artelys KNITRO solver (Section 4).

All three return a common `tvbounds` object with `print()`, `plot()`, and
`summary()` methods. `tvbounds_summary()` computes the summary measures of
the paper, namely the breakdown budgets, the shadow price of robustness, the
robustness standard error, and the certification frontier, and
`tvbounds_plot()` draws the bounds against the budget.

## 2. Randomized experiments with attrition

Consider a randomized experiment that grants a treatment to half of the
applicants and then runs a follow-up survey to record their outcomes.
Outcomes are observed only for the applicants who respond, and respondents
may be selected on dimensions that also drive the outcome, confounding the
effects of the program. Practitioners typically assume that attrition is
ignorable or, equivalently, that nonresponse is as good as random, an
assumption known as missingness completely at random. That assumption is
untestable, and the corroborating evidence usually offered, that attrition
is not differential across arms, is hardly conclusive. A stakeholder might
accordingly be interested in quantifying by how much the treatment effect
can change when it fails, which is what `tvbounds_attrition()` does.

### 2.1 A small simulated experiment

We simulate a randomized experiment with 500 individuals in 50 villages and
treatment assigned at the village level. Follow-up response is markedly
higher under treatment and depends on an unobserved `ability` that also
drives the outcome, so that attrition is selective and the comparison of
respondents across arms confounds the effect of the program with composition
effects.

```{r rct-simulate}
set.seed(20260820)
n <- 500
village <- rep(1:50, each = 10)
d <- as.integer(rbinom(50, 1, 0.5)[village])       # village-level assignment
x <- rbinom(n, 1, 0.4)                             # baseline covariate
ability <- rnorm(n)
s <- as.integer(runif(n) < plogis(0.2 + 1.2 * d + 0.5 * ability))
y <- ifelse(s == 1, 1 + 0.35 * d + 0.5 * x + ability + 0.5 * rnorm(n), NA)
rct <- data.frame(y = y, d = d, s = s, x = x, village = village)
tapply(rct$s, rct$d, mean)                         # response rates by arm
```

By construction the treatment effect equals 0.35, whereas only roughly
`r round(100 * mean(rct$s[rct$d == 0]))`%
of control units respond against `r round(100 * mean(rct$s[rct$d == 1]))`% of
treated units, and high-ability units respond more often in both arms.

### 2.2 Total variation bounds

`tvbounds_attrition()` requires the column names of the outcome $Y$, of the
binary treatment $D$, and of the response indicator $S$, which equals 1 when
the outcome is observed and may be paired with an `NA` outcome otherwise. We
compute the bounds on a grid of budgets, with a small number of bootstrap
replications for the purposes of this vignette; the `seed` argument makes
the bootstrap reproducible without altering the caller's random-number
stream.

```{r rct-tv}
fit_tv <- tvbounds_attrition(rct,
  outcome = "y", treatment = "d", response = "s",
  delta = seq(0, 1, by = 0.05), B = 200, seed = 1)
fit_tv
```

The estimand is the average treatment effect for the *always-observed*
subpopulation, the units that would respond under either arm:
$$
\tau_0
  := \mathbb{E}_{P_0}[Y(1) - Y(0) \mid S(0) = 1, S(1) = 1],
$$
where $Y(d)$ and $S(d)$ are the potential outcome and the potential response
indicator under treatment $d$, and $P_0$ is the distribution of the
data. Under random assignment and the monotonicity assumption of Lee
(2009) there are no defiers, so that the outcome distribution of the treated
respondents, $P_{\mathsf{T}}$, is a mixture of the outcome distribution of
the compliers, $P_{\mathsf{C}}$, the units that respond only because they
were treated, and that of the always-observed units, $P_{\mathsf{AO}}$:
$$
P_{\mathsf{T}} = \pi P_{\mathsf{C}} + (1 - \pi) P_{\mathsf{AO}},
\qquad
\pi = 1 - \frac{r_0}{r_1}.
$$
The mixing weight $\pi$, the complier share among treated respondents, is
identified by comparing the response rates of the two arms, $r_1$ and
$r_0$; the package reports the complier share $\pi$ as `p_star`:

```{r rct-pstar}
fit_tv$details$p_star
```

Neither $P_{\mathsf{C}}$ nor $P_{\mathsf{AO}}$ is identified, and
missingness completely at random requires that the two coincide. A natural
way to relax it is thus to let them lie at most $\delta$ apart in total
variation, $\mathsf{TV}(P_{\mathsf{C}} \,\|\, P_{\mathsf{AO}}) \le \delta$, so
that the two outcome distributions may disagree on at most a
$\delta$-fraction of their mass. Rescaling that restriction onto the
identified law $P_{\mathsf{T}}$ pins down one of the two distributions and
lets the candidate complier distribution $Q$, of which $P_{\mathsf{C}}$ is
one, range over the robustness set
$$
\mathcal{Q}_{\mathsf{C}}(\delta)
  := \{Q \in \Delta(\mathcal{Y}) :
       \mathsf{TV}(Q \,\|\, P_{\mathsf{T}}) \le (1 - \pi)\delta, \;\;
       \pi Q \le P_{\mathsf{T}}\},
$$
where $\Delta(\mathcal{Y})$ collects the distributions on the outcome space
and the second restriction encodes the mixture structure of the treated arm.
The resulting sensitivity bounds $\underline{\tau}(\delta)$ and
$\overline{\tau}(\delta)$ on $\tau_0$
admit a closed form, as trimmed means of $P_{\mathsf{T}}$ net of the
control mean
$\mu^{\mathsf{AO}}(0) = \mathbb{E}_{P_0}[Y \mid D = 0, S = 1]$,
which is identified because, absent defiers, the control respondents are
always-observed units. The `bounds` data frame carries one row per budget,
with bootstrap standard errors and the outer percentile confidence interval:

```{r rct-bounds-head}
head(fit_tv$bounds, 4)
```

`plot()`, an alias of `tvbounds_plot()`, shades the identified region, draws
the outer confidence interval as dashed lines, marks the baseline point estimate
at $\delta = 0$, and flags the plug-in breakdown budget at which the lower
bound crosses zero:

```{r rct-plot, fig.cap = "Total variation bounds for the simulated experiment."}
plot(fit_tv)
```

### 2.3 The endpoints: baseline at $\delta = 0$, Lee bounds at $\delta = 1$

The two endpoints of the budget grid anchor the interpretation. At
$\delta = 0$ the baseline is the only admissible distribution, the two
unobserved outcome distributions coincide,
$P_{\mathsf{C}} = P_{\mathsf{AO}}$, and the bounds collapse to the
difference in means among respondents $\tau_{\mathsf{MCAR}}(P_0)$, the
point estimate one would report under missingness completely at random:

```{r rct-endpoint-0}
naive <- mean(rct$y[rct$d == 1 & rct$s == 1]) -
         mean(rct$y[rct$d == 0 & rct$s == 1])
c(point = fit_tv$point, naive = naive)
```

At $\delta = 1$ the total variation restriction is vacuous, the robustness
set imposes nothing beyond the mixture structure of the treated arm, and the
bounds coincide with the trimming bounds of Lee (2009),
$\underline{\tau}_{\mathsf{Lee}}$ and $\overline{\tau}_{\mathsf{Lee}}$,
stored in `details$lee`:

```{r rct-endpoint-1}
subset(fit_tv$bounds, delta == 1, select = c(delta, lower, upper))
unlist(fit_tv$details$lee)
```

The exercise therefore interpolates between the two poles of the attrition
literature, the point estimate that assumes attrition away and the bounds of
Lee (2009) that restrict the two unobserved outcome distributions only
through the mixture structure, and indexes the continuum between them by a
budget that reads as a share of misspecified mass. Both endpoints are
computed internally even when the `delta` grid omits them.

### 2.4 The contamination neighborhood

`neighborhood = "contamination"` replaces the total variation restriction
with the one-sided mixture restriction
$P_{\mathsf{C}} = (1 - \delta) P_{\mathsf{AO}} + \delta R$ for some
distribution $R$, equivalently
$P_{\mathsf{C}} \ge (1 - \delta) P_{\mathsf{AO}}$ as measures. Since
every such mixture lies within total variation distance $\delta$ of
$P_{\mathsf{AO}}$, the contamination bounds are weakly tighter at every
budget, while the two sets of bounds share both endpoints, the baseline at
$\delta = 0$ and the Lee bounds at $\delta = 1$:

```{r rct-contamination}
fit_ct <- tvbounds_attrition(rct,
  outcome = "y", treatment = "d", response = "s",
  delta = seq(0, 1, by = 0.05), neighborhood = "contamination",
  bootstrap = FALSE)

all(fit_ct$bounds$lower >= fit_tv$bounds$lower - 1e-12)   # nesting
all(fit_ct$bounds$upper <= fit_tv$bounds$upper + 1e-12)
```

Because `bounds` is a plain data frame, the two neighborhoods are readily
compared with `ggplot2`:

```{r rct-compare-plot, fig.cap = "Total variation versus contamination bounds."}
comp <- rbind(
  cbind(fit_tv$bounds[c("delta", "lower", "upper")],
        neighborhood = "total variation"),
  cbind(fit_ct$bounds[c("delta", "lower", "upper")],
        neighborhood = "contamination"))
ggplot(comp, aes(x = delta)) +
  geom_line(aes(y = lower, linetype = neighborhood), color = "#1F4E79",
            linewidth = 0.9) +
  geom_line(aes(y = upper, linetype = neighborhood), color = "#1F4E79",
            linewidth = 0.9) +
  geom_hline(yintercept = 0, linetype = "dotted", color = "gray50") +
  labs(x = expression(delta), y = "treatment effect") +
  theme_bw(base_size = 12) +
  theme(panel.grid = element_blank(), legend.position = "bottom")
```

Which neighborhood to report is a modeling choice. The total variation
bounds guard against arbitrary misspecification of a $\delta$-fraction of
the baseline mass, whereas the contamination bounds impose in addition that
the remaining $(1-\delta)$-share of the compliers is distributed exactly as
the always-observed units.

### 2.5 Cluster bootstrap

Treatment is assigned at the village level, so resampling villages is the
appropriate bootstrap. Passing `cluster` makes each replicate draw whole
clusters with replacement. Every replicate also redraws the arm-specific
response rates, so that the standard errors reflect the estimation
uncertainty in the complier share $\pi$, which a plug-in formula would omit.

```{r rct-cluster}
fit_cl <- tvbounds_attrition(rct,
  outcome = "y", treatment = "d", response = "s",
  delta = seq(0, 1, by = 0.05), B = 200, cluster = "village", seed = 1)
fit_cl$details$n_clusters

data.frame(delta      = fit_tv$bounds$delta,
           se_iid     = fit_tv$bounds$lower_se,
           se_cluster = fit_cl$bounds$lower_se)[1:4, ]
```

As one would expect with village-level assignment, the clustered standard
errors are markedly larger than those obtained by resampling units
independently.

### 2.6 Covariates and pooled bounds

When `covariates` is supplied, units are stratified on the interaction of
the covariate columns, which plays the role of a discrete covariate $X$ with
support $\mathcal{X}$, and cells with fewer than `min_obs` observed outcomes
in either arm are dropped with a warning. Within a cell the complier share
$\pi(x)$ and the outcome distribution of the treated respondents
$P_{\mathsf{T}}(x)$ are identified, and the cell-level construction is the
one of Section 2.2.

The budget can then be allocated across cells in two ways. The
within-stratum ("pointwise") restriction imposes
$\mathsf{TV}(P_{\mathsf{C}}(x) \,\|\, P_{\mathsf{AO}}(x)) \le \delta$ in every
cell separately, giving one robustness set
$\mathcal{Q}^{\mathsf{pw}}_{\mathsf{C}}(\delta; x)$ per
cell, whereas the pooled restriction caps only the average departure,
$$
\int_{\mathcal{X}} \mathsf{TV}(P_{\mathsf{C}}(x) \,\|\, P_{\mathsf{AO}}(x))
  \, \mathrm{d}P_{X \mid \mathsf{AO}}(x) \le \delta ,
$$
and so allows heterogeneity across cells inside the single robustness set
$\mathcal{Q}_{\mathsf{C},X}(\delta)$. Under the total
variation neighborhood the reported bounds are the *pooled* (joint) bounds
of the paper, $\underline{\tau}_{X}(\delta)$ and
$\overline{\tau}_{X}(\delta)$, for which a **single** budget
$\delta$ is allocated optimally across the covariate cells rather than
imposed cell by cell: the least favorable distributions concentrate the
misspecified mass in the cells in which it moves the aggregate effect the
most.

```{r rct-covariates}
fit_x <- tvbounds_attrition(rct,
  outcome = "y", treatment = "d", response = "s", covariates = "x",
  delta = seq(0, 1, by = 0.05), B = 200, seed = 1)
fit_x$details$pooled$strata
```

The per-stratum table records the weight of each retained cell, that is its
share of control respondents, which under monotonicity is the covariate
distribution of the always-observed population,
$P_{X \mid D = 0, S = 1} = P_{X \mid \mathsf{AO}}$, together with the
complier share and the sample sizes. The within-stratum reference curve
$\underline{\tau}^{\mathsf{pw}}_{X}(\delta)$,
$\overline{\tau}^{\mathsf{pw}}_{X}(\delta)$ is kept in
`details$pooled$pw`. The pooled bounds contain it by construction, since a
common budget in every cell is one of the ways of spending the average one,
and the two coincide at both endpoints:

```{r rct-pooled-vs-pw}
pw <- fit_x$details$pooled$pw
all(fit_x$bounds$upper >= pw$upper - 1e-12)
all(fit_x$bounds$lower <= pw$lower + 1e-12)
```

Conditioning on covariates tightens the worst case. At $\delta = 1$ both
covariate constructions collapse to the covariate Lee bounds
$\underline{\tau}_{\mathsf{Lee},X}$ and $\overline{\tau}_{\mathsf{Lee},X}$,
which aggregate cell-level trimming bounds and are tighter than the Lee
bounds that ignore the covariate, stored in `details$lee_nocov` for
reference:

```{r rct-lee-cov}
rbind(with_covariate    = unlist(fit_x$details$lee),
      without_covariate = unlist(fit_x$details$lee_nocov))
```

With `neighborhood = "contamination"` the covariate version imposes the
common budget $\delta$ within every retained cell and then aggregates, and
those bounds remain weakly inside the total variation ones at every budget.

### 2.7 Summary measures

`summary()`, an alias of `tvbounds_summary()`, condenses the bounds into the
summary measures of the paper. These are stated for generic bound paths
$\underline{\tau}(\delta)$ and $\overline{\tau}(\delta)$, here the attrition
bounds of Section 2.2, and are evaluated on
the path adjacent to the reference value $\tau_{\star}$, which is set
through the argument `tau_star` and defaults to 0; here that is the lower
path, since the baseline estimate is positive:

```{r rct-summary}
summary(fit_tv)
```

We read the output line by line.

* **Plug-in breakdown budget** (`delta_b`) — the breakdown budget
  $\delta_b(\tau_{\star})$, the smallest budget at which the estimated
  bounds reach $\tau_{\star}$, linearly interpolated between grid points.
  Here the positive-effect conclusion survives until roughly
  `r round(summary(fit_tv)$measures$delta_b, 2)`: the outcome distributions
  of the compliers and of the always-observed units would have to disagree
  on more than
  `r round(100 * summary(fit_tv)$measures$delta_b)`% of their mass to
  overturn the sign. When the path never reaches $\tau_{\star}$, the
  breakdown is *censored*: in view of the convention of the paper that the
  infimum over an empty set equals one, it is reported at the right endpoint
  of the budget grid, which is 1 for the total variation and contamination
  neighborhoods, with `censored = TRUE` rather than as "greater than one".

* **Certified breakdown budget** (`delta_b_ci`) — the certified breakdown
  budget $\widehat{\delta}_{b}^{\,\mathsf{C}}(\alpha)$, read off as the
  first crossing of the outer confidence limit, that is of the same band the
  figures draw, so that tables and figures agree on one number. It is the
  largest budget at which the conclusion is still certified at the `level`
  of the band and, since the band is wider than the estimated bounds, it is
  never larger than the plug-in breakdown: sampling uncertainty erodes the
  robustness one can certify.

* **Normal floor** (`delta_b_ci_norm`) — a diagnostic that recomputes the
  certified breakdown from the normal approximation
  $\widehat{\underline{\tau}}_{n}(\delta) - z_{1-\alpha/2}
  \widehat{\sigma}_{n}(\delta) / \sqrt{n}$. It estimates the same
  population quantity as `delta_b_ci` and differs from it only when the
  bootstrap distribution of the bound is asymmetric.

* **Shadow price** (`eta`) — the shadow price of robustness
  $\underline{\eta}(\delta) = -\underline{\tau}'(\delta)$, minus the slope
  of the bound path at the evaluation budget, which measures how fast the
  bound deteriorates per unit of misspecification. A large `eta` indicates
  that conclusions erode quickly.

* **Robustness standard error** (`varsigma`) — the quantity
  $\varsigma_{b} = \sigma(\delta_b) / \underline{\eta}(\delta_b)$, computed
  as `se * sqrt(n) / eta`, which converts the sampling uncertainty of the
  bound from units of the estimand into budget units and thereby makes
  robustness comparable across studies; `varsigma_sc` is its finite-sample
  analogue `se / eta`, that is $\varsigma_b / \sqrt{n}$.

* **Certification frontier** (`n_star`, `delta_n`, `cost_per_pp`) — the
  frontier $n^{\star}(\delta;\alpha)$, the sample size at which the normal
  confidence limit would just certify the conclusion at the certified
  budget raised by `jump` (default 0.05). `delta_n` is the additional
  sample relative to the realized `n`, and `cost_per_pp` prices one
  percentage point of certified budget at `cost_per_unit` (default 50 USD
  per sampled unit, the paper's benchmark) — a discrete version of the
  certification elasticity
  $\mathrm{d}\log n^{\star}(\delta;\alpha) / \mathrm{d}\delta$, the paper's
  exchange rate between observations and misspecified probability mass.

By default the shadow price and the robustness standard error are evaluated
at the plug-in breakdown budget. Passing `delta` evaluates them at a budget
of substantive interest instead, and the one-row data frame `measures` gives
access to all of them programmatically:

```{r rct-summary-delta}
s01 <- tvbounds_summary(fit_tv, delta = 0.1)
s01$measures[c("delta_eval", "eta", "varsigma", "n_star")]
```

## 3. Recentered instrumental variables

### 3.1 A small formula-instrument design

Many causal questions in economics involve treatments or instruments that
combine several sources of variation according to a known formula,
shift-share designs being the leading example.
Write $y_i = \beta x_i + \varepsilon_i$ for the structural equation of unit
$i$, with $\beta$ the parameter of interest, $x_i$ the endogenous regressor
and $\varepsilon_i$ the unobserved residual; let $v \in \mathcal{V}$ be the
vector of exogenous shocks, $w$ the predetermined covariates, and
$f_i(\cdot\,;w) : \mathcal{V} \to \mathbb{R}$ the known formula, so that
$z_i = f_i(v;w)$ is the candidate instrument at the realized shocks.
Borusyak and Hull (2023) point out that exogeneity of the shocks does not,
by itself, deliver a consistent instrumental variables estimator, because
units are nonrandomly exposed to the shocks, and show that validity is
restored once the instrument is *recentered* at the expected instrument
$\mu_i(P_{*}) = \mathbb{E}_{P_{*}}[f_i(v;w) \mid w]$, its average across the
shocks that might as well have been realized under the assignment process
$P_{*}$ the researcher postulates, which gives the recentered instrument
$\widetilde{z}_i(P_{*}) = z_i - \mu_i(P_{*})$. In a randomized experiment
the assignment process is given by the randomization protocol, but in
natural experiments it is rarely known or justified by economic theory, and
the sensitivity exercise of Palomba (2026) accordingly asks how much the
estimate would move when up to a $\delta$-fraction of $P_{*}$ is
misspecified.

We simulate 150 regions exposed to $K = 10$ sectors through the employment
shares collected in `W`, so the formula is the shift-share
$f_i(v;w) = \sum_{k=1}^{K} w_{ik} v_k$ and the realized instrument is
$z_i = \sum_{k} w_{ik} v_k$ at the realized sector shocks `g0`. The
researcher
postulates that the shocks are i.i.d. standard normal and recenters using
`S = 80` counterfactual shock configurations $v^{(1)}, \dots, v^{(S)}$ drawn
from that postulated process, the columns of `G`. The matrix `Fmat` collects
the formula evaluated at each configuration, so that `Fmat[i, s]` is
$f_i(v^{(s)};w)$, the instrument of region `i` under the `s`-th draw. The
realized shocks are drawn with a small positive mean, so that the postulated
mean-zero assignment process is itself mildly misspecified, and the outcome
loads on a sectoral confounder, so that nonrandom exposure matters.

```{r riv-simulate}
set.seed(1901)
n <- 150; K <- 10; S <- 80
W <- matrix(rexp(n * K)^2, n, K)
W <- W / rowSums(W)                        # exposure shares
g0   <- rnorm(K, mean = 0.3)               # realized sector shocks
G    <- matrix(rnorm(K * S), K, S)         # S draws from the postulated process
e_x  <- rnorm(n); e_s <- rnorm(K); e_y <- rnorm(n)

z    <- as.vector(W %*% g0)                # realized formula instrument
Fmat <- W %*% G                            # n x S counterfactual draws
x    <- z + e_x                            # endogenous regressor (first stage)
y    <- 0.5 * x + 0.4 * as.vector(W %*% e_s) + 0.5 * e_y
```

### 3.2 Bounds under both neighborhoods

`tvbounds_riv()` takes the outcome $y_i$, the endogenous regressor $x_i$,
the realized instrument $z_i$, and the matrix of counterfactual draws.
Optionally, `p` supplies the probabilities that $P_{*}$ attaches to the
configurations, uniform by default, and `controls` collects the covariates
to be partialled out of `y`, `x`, `z`, and every column of `Fmat`, in view of
the Frisch–Waugh–Lovell theorem. As in the paper, all analyses are conducted
conditionally on the realized sample, so that the bounds are deterministic
and no standard errors or confidence intervals are reported.

```{r riv-fit}
riv_tv <- tvbounds_riv(y, x, z, Fmat, delta = seq(0, 1, by = 0.01))
riv_tv

riv_ct <- tvbounds_riv(y, x, z, Fmat, delta = seq(0, 1, by = 0.01),
                       neighborhood = "contamination")
```

The baseline point is the recentered instrumental-variables estimate
$\widehat{\beta}_{*} = \widehat{\beta}(P_{*})$, so that the exercise is
centered at the reported estimate. The formula enters only through the two
criteria
$g_y(\cdot) = \sum_{i=1}^{n} y_i f_i(\cdot\,;w)$ and
$g_x(\cdot) = \sum_{i=1}^{n} x_i f_i(\cdot\,;w)$, whose recentered values
are the reduced form $G_y(P) = g_y(v) - \mathbb{E}_P[g_y]$ and the first
stage $G_x(P) = g_x(v) - \mathbb{E}_P[g_x]$, so that
$\widehat{\beta}(P) = G_y(P) / G_x(P)$. The bounds trace the range of
$\widehat{\beta}(P)$ as the distribution over the `S` configurations varies
either in the total variation ball
$$
\mathcal{P}^{\mathsf{FI}}_{\mathsf{TV}}(\delta)
  := \{P \in \Delta(\mathcal{V}) : \mathsf{TV}(P, P_{*}) \le \delta\},
$$
which delivers $\underline{\beta}_{\mathsf{TV}}(\delta)$ and
$\overline{\beta}_{\mathsf{TV}}(\delta)$, or in the contamination
neighborhood
$$
\mathcal{P}^{\mathsf{FI}}_{\mathsf{cont}}(\delta)
  := \{P \in \Delta(\mathcal{V}) : P = \delta R + (1 - \delta) P_{*}, \;
       R \in \Delta(\mathcal{V})\},
$$
which delivers $\underline{\beta}_{\mathsf{cont}}(\delta)$ and
$\overline{\beta}_{\mathsf{cont}}(\delta)$. As in the attrition
application, the contamination bounds are nested within the total variation
bounds at every budget:

```{r riv-nesting}
all(riv_ct$bounds$lower >= riv_tv$bounds$lower - 1e-10, na.rm = TRUE)
```

```{r riv-plot, fig.cap = "Total variation bounds for the recentered IV estimate."}
plot(riv_tv)
```

The breakdown budget for the sign of $\beta$, obtained at the reference
value $\tau_{\star} = 0$ set through the argument `tau_star`, is interior
here, and summarizes in a single number how robust the design is. Since the
exercise carries no inference, `summary()` reports the plug-in measures and
returns `NA` for the certified ones, together with a note to that effect.

```{r riv-summary}
riv_tv$details$delta_breakdown
summary(riv_tv)
```

### 3.3 The first-stage breakdown budget and its censoring convention

A formula-instrument design can fail in a more fundamental way than by a
change of sign. Once the budget is large enough that some distribution in
the neighborhood makes the *recentered first stage*
$G_x(P) = \sum_{i=1}^{n} \widetilde{z}_i(P)\, x_i$ vanish, the estimate
$\widehat{\beta}(P)$ is no longer well defined over the whole neighborhood
and the identified set is the entire real line. The smallest such budget is
the **first-stage breakdown budget**, $\delta^{\mathsf{TV}}_{\mathsf{FS}}$
under the total variation ball and
$\delta^{\mathsf{cont}}_{\mathsf{FS}}$ under the contamination
neighborhood, reported, for the neighborhood in use, in `details$delta_fs`
together with a censoring flag:

```{r riv-fs}
c(delta_fs = riv_tv$details$delta_fs,
  censored = riv_tv$details$delta_fs_censored)
```

Following the convention of the paper, the infimum over an empty set equals
one, so that when the first stage never breaks down on $[0, 1]$, as is the
case here, `delta_fs` is reported as 1 with `delta_fs_censored = TRUE`,
which records that the first stage never breaks down over the budget range
rather than that breakdown occurs at 1; the summary measures adopt the same
convention for censored breakdown budgets. The first-stage budgets of both
neighborhoods, $\delta^{\mathsf{TV}}_{\mathsf{FS}}$ and
$\delta^{\mathsf{cont}}_{\mathsf{FS}}$, are always stored, each carrying its
own censoring attribute, in `details$delta_fs_tv` and
`details$delta_fs_cont`.

With a weaker first stage the breakdown becomes interior, and the rows of
`bounds` beyond it carry `NA`, the bounds being vacuous there:

```{r riv-weak}
x_weak <- 0.2 * z + e_x                      # same noise, weaker first stage
y_weak <- 0.5 * x_weak + 0.4 * as.vector(W %*% e_s) + 0.5 * e_y
riv_weak <- tvbounds_riv(y_weak, x_weak, z, Fmat,
                         delta = seq(0, 1, by = 0.01))
c(delta_fs = riv_weak$details$delta_fs,
  censored = riv_weak$details$delta_fs_censored)
tail(riv_weak$bounds, 3)                     # vacuous budgets are NA
```

```{r riv-weak-plot, fig.cap = "A weak first stage: the bounds diverge and become vacuous at the first-stage breakdown budget."}
plot(riv_weak, breakdown = FALSE)
```

The figure makes the mechanics apparent: the bounds fan out as the budget
approaches `details$delta_fs` and are not drawn beyond it. Reporting the
first-stage breakdown budget alongside the bounds keeps two rather different
fragilities distinct, a conclusion whose sign is overturned and a design
whose identifying variation can be undone altogether.

## 4. Counterfactual predictions in structural models

Counterfactual predictions from structural models depend on the distribution
of the latent variables, which is typically not nonparametrically
identifiable and is often chosen for tractability alone; taste shocks,
unobserved heterogeneity, and productivity shocks are common instances. A
stakeholder may thus be interested in knowing how sensitive such predictions
are to that untestable assumption. The third application bounds a
counterfactual
$\mathbb{E}_P[g(U;\theta)]$ of a structural model when the distribution $P$
of the latent variables $U$ ranges over a divergence neighborhood of the
simulated baseline $P_{*}$ and the structural parameter $\theta \in \Theta$
ranges over the values compatible with the moment conditions
$\mathbb{E}_P[m(U;\theta)] \in \mathcal{M}(\rho)$, following Christensen and
Connault (2023) and Palomba (2026). The reported bounds are the nested
extrema
$$
\underline{\mathsf{k}}(\delta)
  = \inf_{\theta \in \Theta} \; \inf_{P \in \mathcal{P}_\phi(\theta;\delta)}
    \mathbb{E}_P[g(U;\theta)],
\qquad
\overline{\mathsf{k}}(\delta)
  = \sup_{\theta \in \Theta} \; \sup_{P \in \mathcal{P}_\phi(\theta;\delta)}
    \mathbb{E}_P[g(U;\theta)] .
$$
`tvbounds_counterfactual()` is the only function in the package that
supports divergences beyond total variation and contamination.

**None of the code chunks in this section is executed when the vignette is
built**, since the function relies on Julia (>= 1.9) *and on a licensed copy
of the commercial Artelys KNITRO solver*, neither of which can be assumed on
the machine building the vignette. The code is nevertheless complete and
runs as it stands on a machine with a working installation.

### 4.1 Requirements and the first-use check

The solver is written in Julia and reached through the 'JuliaCall' package.
One-time setup:

1. install the R bridge: `install.packages("JuliaCall")`;
2. install Julia (>= 1.9) from <https://julialang.org/downloads/> and make
   sure the `julia` binary is on the `PATH` (or set the `JULIA_HOME`
   environment variable to its `bin/` directory);
3. install KNITRO and obtain a valid license — KNITRO is a commercial
   solver by Artelys, and free academic trials are available at
   <https://www.artelys.com/solvers/knitro/>; make sure KNITRO.jl can
   locate the installation (e.g. set the `KNITRO_DIR` environment variable
   before starting R).

On the first call in each R session the package initializes the embedded
Julia, activates and instantiates its own Julia environment, downloading
KNITRO.jl, ForwardDiff.jl, Optim.jl, and their dependencies into the
standard Julia depot on first use, which requires network access. It then
sources the solver module and **verifies that KNITRO.jl loads and that a
KNITRO solver context can be created, which exercises the license**. On
success a message reports that KNITRO is available; on failure the call
stops and reports installation and license guidance. The check is performed
once per R session.

Two session-level caveats are worth recording:

* **The package activates its own Julia project inside the embedded
  session.** If JuliaCall is used for other work in the same R session,
  that Julia code will run with the project environment of tvbounds active
  from the first `tvbounds_counterfactual()` call onward.
* **Julia's global random-number generator is re-seeded by the solver**,
  since the multi-start restarts are deterministic by design. The
  random-number state of R is saved and restored around each call, so R
  streams are unaffected, but the continuity of the global stream of Julia
  should not be relied upon across a call.

### 4.2 The moments function: the Julia route

The model is communicated through a single *moments function* with the
in-place signature `moments!(K, G, theta, U, obj)`: given the current
parameter `theta` and the `M x u_dim` matrix of latent draws `U`, it fills
the `M`-vector `K` with the counterfactual values $g(U^{(j)};\theta)$ and
the `M x d` matrix `G` with the moment functions $m(U^{(j)};\theta)$, one
row per draw $U^{(j)}$, $j = 1, \dots, M$. The paper writes the
counterfactual integrand $g$ and the moment function $m$ while the code
arrays are named `K` and `G`, so read `K` as $g$ and `G` as $m$ throughout.
The package ships a toy example in `inst/julia/examples/toy.jl` — the latent
draw is a scalar $U \sim \mathrm{Uniform}(0,1)$, the single moment pins its
mean to $\theta$, and the counterfactual is $U$ itself:

```julia
function tvb_toy_moments!(K, G, theta, U, obj)
    M = size(U, 1)
    @inbounds for m in 1:M
        K[m]    = U[m, 1]
        G[m, 1] = U[m, 1] - theta[1]
    end
    return nothing
end
```

For your own model, put a function with the same signature in a `.jl` file.
The `obj.gamma` field carries an arbitrary payload passed from R through
the `gamma` argument (an R list arrives in Julia as an ordered dictionary
keyed by symbols, so read entries as `obj.gamma[:name]`), and the
scrambled-Halton draws are uniform on the unit cube
$(0,1)^{\mathsf{d}_z}$, whose dimension $\mathsf{d}_z$ is set by `u_dim`, so
the moments function is responsible for mapping them into baseline draws,
typically through quantile transforms:

```julia
# mymodel.jl -- a template
using Distributions   # available in the package's Julia environment

function my_moments!(K, G, theta, U, obj)
    M = size(U, 1)
    a = obj.gamma[:a]                       # payload passed from R
    @inbounds for m in 1:M
        u1 = quantile(Normal(), U[m, 1])    # map uniforms into N(0,1) draws
        K[m]    = exp(theta[1] + theta[2] * u1)       # counterfactual
        G[m, 1] = u1 * (theta[1] + theta[2] * u1 - a) # moment condition 1
        G[m, 2] = theta[1] + theta[2] * u1 - a        # moment condition 2
    end
    return nothing
end
```

Write the function generically in the element type of `theta` (as above:
no `Float64` annotations on the values it computes): the outer optimization
differentiates the moments in $\theta$ by automatic differentiation
(ForwardDiff), which feeds dual numbers through your code. For a
non-generic function, pass `gradient = "fd"` to fall back on finite
differences.

### 4.3 Running the solver

The complete call for the toy model (not run — Julia and a licensed KNITRO
are required):

```{r cf-toy, eval = FALSE}
toy <- system.file("julia", "examples", "toy.jl", package = "tvbounds")

fit_cf <- tvbounds_counterfactual(
  moments    = c(toy, "tvb_toy_moments!"),  # Julia file + function name
  d          = 1,                           # number of moment conditions
  theta_lb   = 0.4, theta_ub = 0.6,         # box for the structural parameter
  delta      = c(0.05, 0.1, 0.25, 0.5, 1),  # budgets (strictly positive)
  divergence = "TVmix",
  side       = "both",                      # lower and upper bound problems
  M          = 5000, u_dim = 1,             # scrambled-Halton draws
  theta_init = 0.5,                         # baseline parameter estimate
  seed       = 1234,
  control    = tvbounds_control(maxsolves = 5))

fit_cf$bounds       # one row per budget
fit_cf$point        # plug-in counterfactual at theta_init
fit_cf$details$solver   # per-budget KNITRO status codes and timings
plot(fit_cf)
```

For this toy model the bounds under `"TVmix"` equal the endpoints of the
$\theta$ box (up to the smoothing described below) whenever the moment
condition is satisfiable, which is what the package's integration tests
check.

Beyond the moments specification, the main arguments are the following.

* `d` is the number of moment conditions $\mathsf{d}_m$; the common length
  of `theta_lb`/`theta_ub` fixes the dimension $\mathsf{d}_\theta$ of
  $\theta$, and the outer problems optimize over that box. A *degenerate*
  box (`theta_lb == theta_ub`) skips the outer optimization and reports
  fixed-$\theta$ bounds at `theta_init` — useful for pure
  distribution-sensitivity exercises.
* `side` selects which problems to solve per budget: `"both"` (default),
  `"lower"`, or `"upper"`.
* `U` supplies the `M x u_dim` matrix of latent draws
  $U^{(1)}, \dots, U^{(M)}$ directly; when `U = NULL` the package generates
  `M` scrambled-Halton uniforms (Owen, 2017) of dimension `u_dim` (at most
  15), seeded by `seed`. The paper's default is `M = 50000`.
* `theta_init` should be set to the baseline estimate of the model: the
  reported baseline `point` is the plug-in counterfactual
  $\mathsf{k}(\theta;P_{*}) = \mathbb{E}_{P_{*}}[g(U;\theta)]$ at
  `theta_init` and is only returned when `theta_init` is supplied. The
  budget-zero baseline is *not* part of the `delta` grid (all budgets must
  be strictly positive); it is exactly this `point`.
* Failed budgets are reported as `NA` in `bounds` (for `"TVmix"` an `NA`
  typically signals an empty robustness set at that budget).

**Divergences.** The `divergence` keyword selects the entropy function
$\phi$ whose divergence $D_\phi(P \,\|\, P_{*})$ defines the neighborhood;
the budget must lie in $(0, 1]$ for the total-variation family and may be
any positive number for the others:

| keyword    | neighborhood                                                                 |
|------------|-------------------------------------------------------------------------------|
| `"KL_chi2"`| hybrid Kullback–Leibler/chi-square divergence of Christensen and Connault (2023); the default |
| `"KL"`     | pure Kullback–Leibler divergence, with entropy $\phi_{\mathsf{KL}}(s) = s \log s - s + 1$ |
| `"chi2"`   | Pearson chi-square divergence                                                 |
| `"TV"`     | total variation, with entropy $\phi_{\mathsf{TV}}(s) = \lvert s - 1 \rvert / 2$, so the budget constraint is $\mathsf{TV}(P, P_{*}) \le \delta$ |
| `"TVmix"`  | total variation intersected with the mixture (contamination) constraint $P \ge \kappa P_{*}$ at mixing weight $\kappa = 1 - \delta$, solved in its exact reduced form |
| `"TVmixC"` | the literal dual of the same program — slower, kept as a cross-check, and the only mode supporting a mixing weight $\kappa < 1 - \delta$ (set `tvmix_kappa` in the control list) |
| `"TVac"`   | total variation restricted to distributions absolutely continuous with respect to the baseline, $P \ll P_{*}$ |

The kinked total-variation conjugates $\phi^{*}_{\mathsf{TV}}$ are
Huber-smoothed and the per-draw maxima log-sum-exp-smoothed; both smoothings
lie above the exact functions, so computed bounds are
*outward-conservative* (wider, never narrower) at order $10^{-3}$.

### 4.4 The moments function: the R route

The model may alternatively be supplied as an R function of the form
`function(theta, U, gamma)` returning
`list(K = <numeric length M>, G = <numeric M x d matrix>)`:

```{r cf-rmoments, eval = FALSE}
r_moments <- function(theta, U, gamma) {
  u <- qnorm(U[, 1])                 # map uniforms into baseline draws
  list(K = u + theta[1],             # counterfactual values
       G = cbind(u - theta[1]))      # moment conditions (M x d)
}

fit_r <- tvbounds_counterfactual(
  moments  = r_moments, d = 1,
  theta_lb = -0.5, theta_ub = 0.5,
  delta    = c(0.1, 0.5),
  divergence = "TV",
  M = 2000, u_dim = 1, theta_init = 0,
  seed = 1234)
```

Two caveats are worth recording. First, **the R route is much
slower**: every objective evaluation crosses the R/Julia boundary. Second,
ForwardDiff cannot differentiate through R code, so the outer optimization
uses finite differences by default; alternatively, supply `gradient` as an
R function `function(theta, U, gamma)` returning either the stacked
`(M*(d+1)) x l` Jacobian of `c(K, G)` (the `K` rows first, then `G` in
column-major order) or a list with components `K` (`M x l`) and `G`
(`M x d x l`), where `l` is the dimension $\mathsf{d}_\theta$ of $\theta$.
For sustained use we recommend porting the moments to a small Julia file;
the template above is complete.

### 4.5 Tuning with `tvbounds_control()`

`tvbounds_control()` collects the solver tuning options, and its defaults
reproduce the settings of the paper. The options most commonly adjusted are
the following.

```{r cf-control, eval = FALSE}
ctrl <- tvbounds_control(
  maxsolves = 3,                       # multi-start restarts per budget/side
  startptrange = 0.05,                 # spread of the restart perturbations
  outer_opt = system.file("julia", "opt", "outer_fast.opt",
                          package = "tvbounds"),
  knitro_options = list(maxit = 300, outlev = 0))

fit_fast <- tvbounds_counterfactual(
  moments  = c(toy, "tvb_toy_moments!"), d = 1,
  theta_lb = 0.4, theta_ub = 0.6,
  delta    = seq(0.1, 1, by = 0.1), divergence = "TVmix",
  M = 5000, u_dim = 1, theta_init = 0.5, seed = 1234,
  control  = ctrl)
```

* `maxsolves` restarts the outer optimization over $\theta$ from perturbed
  starting points (`startptrange` controls the perturbation size); each
  budget is warm-started at the previous budget's optimum, and the reported
  bound is the inner dual value re-solved at the best candidate, which
  makes the bound curves monotone in the budget by construction.
* `inner_opt` / `outer_opt` point at KNITRO option files for the inner
  (dual) and outer problems. The package ships four under
  `system.file("julia", "opt", package = "tvbounds")`: the defaults
  `inner.opt` and `outer.opt`, plus `outer_fast.opt` (analytic envelope
  gradient with looser tolerances, suited to plotting grids) and
  `outer_boot_tv.opt`.
* `knitro_options` overrides individual KNITRO options by name (e.g.
  `list(maxit = 500, outlev = 2)`); the overrides are merged into *both*
  option files by writing merged copies to `tempdir()` — the shipped files
  are never modified.
* `use_optim = TRUE` replaces the outer KNITRO solve with Optim.jl
  (projected L-BFGS with the analytic envelope-theorem gradient), which
  avoids nested KNITRO contexts — these segfault with some KNITRO.jl
  versions; `time_limit`, `iterations`, and `outer_iterations` govern that
  fallback.
* The remaining options (`eta_min`, `lower_limit`, `psi_tv_eps`,
  `tvac_tau`, `tvmix_tau`, `purekl_acap`, `tvmix_kappa`) expose the
  smoothing and guard constants of the divergence machinery; see
  `?tvbounds_control` for the full list.

Diagnostics are collected in `details$solver` (per-budget outer flags, inner KNITRO
status codes, and timings for each side), `details$theta_lower` /
`details$theta_upper` (the optimal structural parameters at each budget),
and `details$control` (the resolved control list, including the option
files actually used).

## 5. From the paper to the package

The table below maps each empirical application of Palomba (2026) to its
package interface.

| Application in the paper | Exemplar | Package call |
|---|---|---|
| Randomized experiments with attrition: bounds on the treatment effect for the always-observed, bootstrap inference, covariate-pooled bounds | Lee (2009) | `tvbounds_attrition()` |
| Recentered instrumental variables / formula instruments: bounds on the IV coefficient, first-stage breakdown budget | Borusyak and Hull (2023) | `tvbounds_riv()` |
| Counterfactual predictions in structural models: divergence bounds through Julia/KNITRO | Christensen and Connault (2023) | `tvbounds_counterfactual()` |
| Summary measures: breakdown budgets, shadow price of robustness, robustness standard error, certification frontier | — | `tvbounds_summary()` / `summary()` |
| Sensitivity figures: bounds against the budget | — | `tvbounds_plot()` / `plot()` |

### Citation

If you use **tvbounds** in your work, please cite the paper:

> Palomba, F. (2026). "Sensitivity Analysis in Population Shares." Working
> paper.

`citation("tvbounds")` produces a citation entry for the package itself.

## References

Borusyak, K. and Hull, P. (2023). "Nonrandom Exposure to Exogenous
Shocks." *Econometrica*, 91(6), 2155–2185.

Christensen, T. and Connault, B. (2023). "Counterfactual Sensitivity and
Robustness." *Econometrica*, 91(1), 263–298.

Huber, P. J. (1964). "Robust Estimation of a Location Parameter." *Annals
of Mathematical Statistics*, 35(1), 73–101.

Lee, D. S. (2009). "Training, Wages, and Sample Selection: Estimating
Sharp Bounds on Treatment Effects." *Review of Economic Studies*, 76(3),
1071–1102.

Owen, A. B. (2017). "A randomized Halton algorithm in R."
arXiv:1706.02808.

Palomba, F. (2026). "Sensitivity Analysis in Population Shares." Working
paper.
