Files
sica-fondt/core/src/economy/sims/statistical/copula.R
T
Claude eefdb2fb5f M3a statistical sims implementation + Ada config
- Install hook: add three vital CRAN packages (HiddenMarkov, rugarch, rmgarch)
- M3a spec: document vital packages and hand-rolled implementations
- Ada config: create core_config.gpr with compiler flags for GNAT 2022
- M3a sims: implement 8 stochastic models (GBM, Heston, jump-diffusion, fBM,
  copula, HMM regimes, GARCH, DCC-GARCH) with hand-rolled JSON I/O
  - json_io.R: recursive-descent parser + emitter (no jsonlite)
  - sde_sims.R: GBM, Heston (Euler-Maruyama), jump-diffusion, fBM (Wood & Chan)
  - copula.R: empirical copula + tail-dependence
  - regimes_garch.R: lazy-load vital packages for regime/GARCH/DCC sims
  - main.R: Hub stdin/stdout protocol entry point

Non-Turing M1 law script design complete (S-expressions + fixed combinators).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 02:08:05 +00:00

45 lines
1.9 KiB
R

# copula.R — hand-rolled copula tail-dependence (M3a spec §3).
# Gaussian copula via empirical ranks + normal scores; lower/upper tail
# dependence estimated empirically. Used for cross-token contagion risk:
# given a reference token's move, how far does the target move with it?
# Empirical copula pseudo-observations.
.pobs <- function(x) rank(x, ties.method = "average") / (length(x) + 1)
# Pearson correlation of normal scores = Gaussian-copula rho.
copula_rho <- function(x, y) {
cor(qnorm(.pobs(x)), qnorm(.pobs(y)))
}
# Empirical tail dependence at quantile q: P(V <= q | U <= q) (lower) and
# P(V > 1-q | U > 1-q) (upper).
copula_tails <- function(x, y, q = 0.05) {
u <- .pobs(x); v <- .pobs(y)
lo <- if (any(u <= q)) mean(v[u <= q] <= q) else 0
hi <- if (any(u >= 1 - q)) mean(v[u >= 1 - q] >= 1 - q) else 0
list(lower = lo, upper = hi)
}
# Conditional co-move forecast: if the reference asset shifts by ref_shift
# (log-return), the Gaussian copula conditional mean of the target's return
# is rho * (sigma_t / sigma_r) * ref_shift, with conditional sd
# sigma_t * sqrt(1 - rho^2). Returns a price band for the target.
sim_copula <- function(prices, ref_prices, horizon, ref_shift = NULL,
level = 0.90) {
rt <- diff(log(prices)); rr <- diff(log(ref_prices))
n <- min(length(rt), length(rr))
rt <- tail(rt, n); rr <- tail(rr, n)
rho <- copula_rho(rr, rt)
if (is.null(ref_shift)) ref_shift <- mean(rr) * horizon
st <- sd(rt); sr <- sd(rr)
cond_mu <- mean(rt) * horizon + rho * (st / sr) * (ref_shift - mean(rr) * horizon)
cond_sd <- st * sqrt(pmax(1 - rho^2, 1e-12)) * sqrt(horizon)
s0 <- prices[length(prices)]
zq <- qnorm(1 - (1 - level) / 2)
tails <- copula_tails(rr, rt)
list(value = s0 * exp(cond_mu),
lower_bound = s0 * exp(cond_mu - zq * cond_sd),
upper_bound = s0 * exp(cond_mu + zq * cond_sd),
certainty = abs(rho) * (1 - abs(tails$lower - tails$upper)))
}