% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/causalsim_eval.R
\name{causalsim_eval}
\alias{causalsim_eval}
\title{Evaluate a causal estimator against a known DGP}
\usage{
causalsim_eval(
  dgp,
  estimator,
  reps = 200L,
  metrics = c("bias", "rmse", "coverage", "power"),
  seed = NULL
)
}
\arguments{
\item{dgp}{A \code{causalsim_dgp} object.}

\item{estimator}{A function that accepts a data frame produced by
\code{\link[=causalsim_draw]{causalsim_draw()}} and returns a named numeric vector or single-row
data frame. Must include an \code{estimate} field. For \code{"coverage"} and
\code{"power"} metrics, must also include \code{ci_lower} and \code{ci_upper}. See
Details.}

\item{reps}{Positive integer. Number of simulation replications.
Default \code{200L}.}

\item{metrics}{Character vector. Subset of \code{"bias"}, \code{"rmse"},
\code{"coverage"}, \code{"power"}. Default: all four.}

\item{seed}{Integer or \code{NULL}. Passed to \code{\link[=set.seed]{set.seed()}} before the first
replication. Default \code{NULL}.}
}
\value{
An S3 object of class \code{causalsim_eval} with components:
\describe{
\item{\code{metrics}}{Tidy data frame: \code{metric}, \code{value}, \code{se}.}
\item{\code{draws}}{Data frame of per-replication estimates, one row per rep.}
\item{\code{true_ate}}{The DGP's true ATE.}
\item{\code{reps}}{Number of replications run.}
}
}
\description{
Repeatedly draws datasets from a \code{\link[=causalsim_dgp]{causalsim_dgp()}} object, applies a
user-supplied estimator to each draw, and returns a tidy summary of
estimator performance against the known ground truth.
}
\details{
\subsection{Estimator convention}{

The estimator receives the full data frame returned by \code{\link[=causalsim_draw]{causalsim_draw()}},
including ground-truth columns \code{.tau} and \code{.p}. It should return a named
numeric vector or one-row data frame with at minimum:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{my_estimator <- function(data) \{
  fit <- lm(Y ~ A + W, data = data)
  est <- coef(fit)["A"]
  se <- sqrt(vcov(fit)["A", "A"])
  c(estimate = est, ci_lower = est - 1.96 * se, ci_upper = est + 1.96 * se)
\}
}\if{html}{\out{</div>}}
}

\subsection{Metrics}{

\describe{
\item{\code{"bias"}}{Monte Carlo estimate of bias: \code{mean(estimate) - true_ate}.}
\item{\code{"rmse"}}{Root mean squared error: \code{sqrt(mean((estimate - true_ate)^2))}.}
\item{\code{"coverage"}}{Proportion of replications where the CI brackets
\code{true_ate}. Requires \code{ci_lower} and \code{ci_upper}.}
\item{\code{"power"}}{Proportion of replications where the CI excludes zero,
i.e., the rejection rate of H0: ATE = 0. When \code{true_ate != 0},
this is power; when \code{true_ate == 0}, it is the Type I error rate.
Requires \code{ci_lower} and \code{ci_upper}.}
}

Monte Carlo standard errors (MCSE) are reported alongside each metric.
For bias: \code{sd(estimates) / sqrt(reps)}. For RMSE: delta-method
approximation. For coverage and power: Bernoulli SE.
}

\subsection{Raw draws}{

Per-replication estimates are stored in \code{result$draws} and can be used
for custom analysis or plotting.
}
}
\examples{
dgp <- causalsim_dgp(n = 300, n_confounders = 1, effect = 2,
                     propensity = 0.5)

# OLS estimator (unbiased under RCT)
ols_estimator <- function(data) {
  fit <- lm(Y ~ A + W, data = data)
  est <- coef(fit)[["A"]]
  se <- sqrt(vcov(fit)["A", "A"])
  c(estimate = est, ci_lower = est - 1.96 * se, ci_upper = est + 1.96 * se)
}

\donttest{
result <- causalsim_eval(dgp, ols_estimator, reps = 100L, seed = 1L)
result
}

}
