Global games and coordination under private information

bayesian-methods
global-games
coordination
incomplete-information
Implement the Carlsson-van Damme and Morris-Shin global games framework in R, showing how private noisy signals about fundamentals resolve equilibrium multiplicity in coordination games through threshold strategies.
Author

Raban Heller

Published

May 8, 2026

Modified

May 8, 2026

Keywords

global games, coordination game, private information, threshold strategy, Morris-Shin, currency attack, equilibrium uniqueness

Introduction & motivation

Coordination games with multiple equilibria pose a fundamental challenge for economic theory: if a game has two or more Nash equilibria, which one will players select? The standard model of a bank run, a currency crisis, or a debt rollover problem features two equilibria – a good one (no attack, no run) and a bad one (attack, run) – and the theory is silent on when each occurs. This multiplicity problem plagued macroeconomic models of financial crises throughout the 1980s and 1990s, limiting their predictive and policy-relevant content. If a currency crisis can happen in any equilibrium, the model cannot tell us which fundamentals make crises more likely.

The global games framework, pioneered by Carlsson and van Damme (1993) and applied to macroeconomic settings by Morris and Shin (1998, 2003), provides an elegant resolution. The key innovation is to introduce a small amount of private information: instead of fundamentals being common knowledge, each player observes a noisy private signal about the true state of the economy. This seemingly minor perturbation has dramatic consequences – the game that had multiple equilibria under common knowledge now has a unique equilibrium in threshold strategies. Each player attacks (withdraws, speculates against the currency) if and only if their private signal falls below a critical threshold, and this threshold is uniquely determined by the model parameters.

The intuition for uniqueness is subtle and powerful. Under common knowledge, players can coordinate on either equilibrium because they all share the same information. With private signals, each player is uncertain about what others observe, which destroys the ability to coordinate on the “good” equilibrium in states where fundamentals are weak. The resulting threshold equilibrium has a natural interpretation: the attack succeeds (the bank fails, the currency devalues) when the fundamental is below a critical value that depends on the noise precision. As signals become more precise, the threshold converges to the point where fundamentals alone determine the outcome, independent of expectations. As signals become noisier, the threshold shifts toward the risk-dominant equilibrium of the underlying complete-information game. This tutorial implements the Morris-Shin currency attack model, derives the equilibrium threshold analytically, and visualises how signal precision shapes the boundary between crisis and stability. The global games approach has become one of the most widely used tools in modern financial economics, applied to bank runs, sovereign debt crises, corporate finance, and political regime change.

Mathematical formulation

Consider a continuum of agents indexed on \([0, 1]\). The true fundamental is \(\theta \sim \text{Uniform}[\underline{\theta}, \overline{\theta}]\). Each agent \(i\) observes a private signal:

\[ x_i = \theta + \varepsilon_i, \quad \varepsilon_i \sim N(0, \sigma^2) \]

where \(\varepsilon_i\) are i.i.d. and independent of \(\theta\). Each agent chooses to attack (\(a_i = 1\)) or not attack (\(a_i = 0\)). Let \(\ell = \int_0^1 a_i \, di\) be the fraction of agents who attack.

The attack succeeds (regime change, currency devaluation, bank failure) if and only if \(\ell \geq \theta\) – the proportion of attackers exceeds the fundamental strength. Payoffs:

\[ u_i(a_i, \ell, \theta) = \begin{cases} 1 - c & \text{if } a_i = 1 \text{ and attack succeeds } (\ell \geq \theta) \\ -c & \text{if } a_i = 1 \text{ and attack fails } (\ell < \theta) \\ 0 & \text{if } a_i = 0 \end{cases} \]

where \(c \in (0, 1)\) is the cost of attacking.

Threshold equilibrium: In the unique equilibrium, agent \(i\) attacks if and only if \(x_i < x^*\), where \(x^*\) is the equilibrium signal threshold. The equilibrium threshold and the critical fundamental \(\theta^*\) (below which the regime falls) satisfy:

\[ \theta^* = 1 - \Phi\!\left(\frac{\theta^* - x^*}{\sigma}\right), \quad \Phi\!\left(\frac{x^* - \theta^*}{\sigma}\right) = 1 - c \]

where \(\Phi\) is the standard normal CDF. Combining these conditions:

\[ x^* = \theta^* + \sigma \, \Phi^{-1}(1 - c) \]

and \(\theta^*\) solves:

\[ \theta^* = 1 - \Phi\!\left(-\Phi^{-1}(1 - c)\right) = c \]

In the limit of precise signals (\(\sigma \to 0\)), the fundamental threshold is \(\theta^* = c\): the regime falls if and only if the fundamental is below the attack cost. This is the unique equilibrium of the global game.

R implementation

# Morris-Shin global game: currency attack model
global_game_threshold <- function(c_cost, sigma) {
  # Equilibrium fundamental threshold
  theta_star <- c_cost

  # Equilibrium signal threshold
  x_star <- theta_star + sigma * qnorm(1 - c_cost)

  # Probability of successful attack given theta
  prob_attack_succeeds <- function(theta) {
    # Fraction attacking = Prob(x_i < x_star | theta) = Phi((x_star - theta)/sigma)
    ell <- pnorm((x_star - theta) / sigma)
    # Attack succeeds if ell >= theta
    as.numeric(ell >= theta)
  }

  list(theta_star = theta_star, x_star = x_star, c_cost = c_cost, sigma = sigma)
}

cat("=== Global Game: Currency Attack Model ===\n")
=== Global Game: Currency Attack Model ===
for (sigma in c(0.1, 0.5, 1.0, 2.0)) {
  result <- global_game_threshold(c_cost = 0.3, sigma = sigma)
  cat(sprintf("sigma = %.1f: theta* = %.3f, x* = %.3f\n",
              sigma, result$theta_star, result$x_star))
}
sigma = 0.1: theta* = 0.300, x* = 0.352
sigma = 0.5: theta* = 0.300, x* = 0.562
sigma = 1.0: theta* = 0.300, x* = 0.824
sigma = 2.0: theta* = 0.300, x* = 1.349
cat("\n=== How attack cost affects equilibrium ===\n")

=== How attack cost affects equilibrium ===
for (c_cost in c(0.1, 0.3, 0.5, 0.7, 0.9)) {
  result <- global_game_threshold(c_cost = c_cost, sigma = 0.5)
  cat(sprintf("c = %.1f: theta* = %.3f, x* = %.3f\n",
              c_cost, result$theta_star, result$x_star))
}
c = 0.1: theta* = 0.100, x* = 0.741
c = 0.3: theta* = 0.300, x* = 0.562
c = 0.5: theta* = 0.500, x* = 0.500
c = 0.7: theta* = 0.700, x* = 0.438
c = 0.9: theta* = 0.900, x* = 0.259
# Simulate the global game
cat("\n=== Simulation: N = 1000 agents, sigma = 0.3 ===\n")

=== Simulation: N = 1000 agents, sigma = 0.3 ===
set.seed(42)
N_agents <- 1000
sigma <- 0.3
c_cost <- 0.3

result <- global_game_threshold(c_cost, sigma)

# Simulate for different true fundamentals
for (theta_true in c(0.1, 0.3, 0.5, 0.7)) {
  signals <- theta_true + rnorm(N_agents, 0, sigma)
  attacks <- signals < result$x_star
  frac_attacking <- mean(attacks)
  regime_falls <- frac_attacking >= theta_true

  cat(sprintf("theta = %.1f: %.1f%% attack, regime %s (threshold: %.1f%%)\n",
              theta_true, 100 * frac_attacking,
              ifelse(regime_falls, "FALLS", "survives"),
              100 * theta_true))
}
theta = 0.1: 88.2% attack, regime FALLS (threshold: 10.0%)
theta = 0.3: 70.6% attack, regime FALLS (threshold: 30.0%)
theta = 0.5: 43.6% attack, regime survives (threshold: 50.0%)
theta = 0.7: 21.7% attack, regime survives (threshold: 70.0%)
# Expected payoff from attacking given signal x
cat("\n=== Expected payoff from attacking given signal ===\n")

=== Expected payoff from attacking given signal ===
expected_payoff_attack <- function(x, c_cost, sigma) {
  # E[u | attack, x] = Prob(regime falls | x) * (1-c) + Prob(survives | x) * (-c)
  # Prob(regime falls | x) = Prob(theta < theta* | x) by the equilibrium characterization
  # In the limit, this simplifies. For the exact calculation:
  # Agent believes theta | x ~ N(x, sigma^2) (with uniform prior approximation)
  # Regime falls when theta < theta_star = c
  prob_falls <- pnorm((c_cost - x) / sigma)
  prob_falls * (1 - c_cost) + (1 - prob_falls) * (-c_cost)
}

x_vals <- c(0.0, 0.15, 0.30, 0.45, 0.60)
for (x in x_vals) {
  ep <- expected_payoff_attack(x, c_cost, sigma)
  cat(sprintf("  x = %.2f: E[payoff|attack] = %+.4f -> %s\n",
              x, ep, ifelse(ep > 0, "ATTACK", "don't attack")))
}
  x = 0.00: E[payoff|attack] = +0.5413 -> ATTACK
  x = 0.15: E[payoff|attack] = +0.3915 -> ATTACK
  x = 0.30: E[payoff|attack] = +0.2000 -> ATTACK
  x = 0.45: E[payoff|attack] = +0.0085 -> ATTACK
  x = 0.60: E[payoff|attack] = -0.1413 -> don't attack

Static publication-ready figure

c_cost <- 0.3
theta_grid <- seq(-0.5, 1.5, by = 0.005)
sigma_vals <- c(0.05, 0.2, 0.5, 1.0)

attack_data <- bind_rows(lapply(sigma_vals, function(s) {
  res <- global_game_threshold(c_cost, s)
  # Fraction attacking = Phi((x* - theta) / sigma)
  frac_attack <- pnorm((res$x_star - theta_grid) / s)
  tibble(
    theta = theta_grid,
    frac_attack = frac_attack,
    regime_falls = as.numeric(frac_attack >= theta_grid),
    sigma_label = sprintf("sigma = %.2f", s),
    sigma = s
  )
}))

attack_data$sigma_label <- factor(attack_data$sigma_label,
                                    levels = sprintf("sigma = %.2f", sigma_vals))

# Left panel: fraction attacking
p_left <- ggplot(attack_data |> filter(theta >= 0, theta <= 1),
                  aes(x = theta, y = frac_attack, color = sigma_label)) +
  geom_line(linewidth = 1) +
  geom_abline(slope = 1, intercept = 0, linetype = "dashed", color = "grey50") +
  geom_vline(xintercept = c_cost, linetype = "dotted", color = "grey30") +
  annotate("text", x = c_cost + 0.02, y = 0.95, label = "theta* = c",
           size = 3, hjust = 0) +
  scale_color_manual(values = okabe_ito[c(3, 2, 1, 6)], name = "Signal precision") +
  labs(
    title = "Fraction of agents attacking",
    x = expression(paste("True fundamental  ", theta)),
    y = "Fraction attacking (l)"
  ) +
  theme_publication() +
  theme(legend.position = "right")

# Right panel: regime outcome boundary
boundary_data <- attack_data |>
  filter(theta >= 0, theta <= 1) |>
  mutate(net_attack = frac_attack - theta)  # positive = regime falls

p_right <- ggplot(boundary_data, aes(x = theta, y = net_attack, color = sigma_label)) +
  geom_line(linewidth = 1) +
  geom_hline(yintercept = 0, linetype = "solid", color = "grey30", linewidth = 0.5) +
  geom_vline(xintercept = c_cost, linetype = "dotted", color = "grey30") +
  annotate("text", x = 0.05, y = 0.4, label = "Regime falls\n(l > theta)",
           size = 3, fontface = "italic") +
  annotate("text", x = 0.8, y = -0.4, label = "Regime survives\n(l < theta)",
           size = 3, fontface = "italic") +
  scale_color_manual(values = okabe_ito[c(3, 2, 1, 6)], name = "Signal precision") +
  labs(
    title = "Regime survival margin",
    x = expression(paste("True fundamental  ", theta)),
    y = expression(paste("Net attack pressure (l - ", theta, ")"))
  ) +
  theme_publication() +
  theme(legend.position = "right")

# Combine using patchwork-free approach: side by side via grid
gridExtra::grid.arrange(p_left, p_right, ncol = 2)
Figure 1: Figure 1. Global game equilibrium: attack probability and regime survival as a function of the true fundamental theta, for varying signal precision. Left panel: fraction of agents who attack in equilibrium (agents with signals below x* attack). Right panel: regime outcome (falls if attack fraction exceeds theta). As precision increases (sigma decreases), the transition sharpens around theta* = c = 0.3, approaching a knife-edge where fundamentals alone determine the outcome. Okabe-Ito palette.

Interactive figure

# Interactive: signal threshold x* as function of sigma and c
param_data <- expand.grid(
  sigma = seq(0.01, 2, by = 0.05),
  c_cost = seq(0.1, 0.9, by = 0.1)
) |>
  mutate(
    theta_star = c_cost,
    x_star = theta_star + sigma * qnorm(1 - c_cost),
    text = paste0("sigma = ", round(sigma, 2),
                  "\nc = ", c_cost,
                  "\ntheta* = ", round(theta_star, 3),
                  "\nx* = ", round(x_star, 3))
  )

p_interactive <- ggplot(param_data, aes(x = sigma, y = x_star,
                                         color = factor(c_cost), text = text)) +
  geom_line(linewidth = 1) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "grey50") +
  scale_color_manual(
    values = rep(okabe_ito, length.out = length(unique(param_data$c_cost))),
    name = "Attack cost (c)"
  ) +
  labs(
    title = "Signal threshold x* across parameter space",
    subtitle = "Higher noise (sigma) shifts threshold; higher cost reduces attacks",
    x = expression(paste("Signal noise (", sigma, ")")),
    y = "Signal threshold (x*)"
  ) +
  theme_publication()

ggplotly(p_interactive, tooltip = "text") |>
  config(displaylogo = FALSE,
         modeBarButtonsToRemove = c("select2d", "lasso2d"))
Figure 2

Interpretation

The global games framework achieves something remarkable: it provides a principled, parameter-dependent answer to the question “when do coordination failures occur?” that the standard multiple-equilibria models cannot. The equilibrium threshold \(\theta^* = c\) has a clean economic interpretation: the regime falls when the fundamental is below the attack cost. This means that in equilibrium, agents attack when – and only when – their private information suggests the fundamental is weak enough that the attack is likely to succeed. The self-fulfilling nature of crises is not eliminated but is disciplined: crises occur in a deterministic region of the fundamental space (for precise enough signals), and the width of the “crisis zone” depends on model parameters.

The visualisation of how signal precision affects the transition is particularly instructive. With very precise signals (\(\sigma \to 0\)), the fraction-attacking curve approaches a step function at \(\theta^* = c\): below this threshold, essentially all agents attack; above it, essentially none do. Fundamentals alone determine the outcome. With imprecise signals (\(\sigma\) large), the transition is gradual: even with moderately strong fundamentals, a non-trivial fraction of agents attack because their signals are noisy enough to suggest weakness. This gradualism means that the regime can fail at fundamentals above \(\theta^*\) due to noise-induced coordination on the bad outcome.

The policy implications are profound. First, transparency matters: improving the quality of public information (reducing \(\sigma\)) sharpens the crisis boundary, making crises less likely for sound fundamentals but no less certain for unsound ones. Second, the cost of attacking matters: policies that raise the cost of speculation (capital controls, transaction taxes) shift \(\theta^*\) downward, reducing the fundamental range over which crises occur. Third, unlike multiple-equilibria models where “animal spirits” or “sunspots” drive crises, the global games model makes crises predictable – they are more likely when fundamentals are weak, noise is high, and attack costs are low. This predictability is what makes the framework valuable for empirical work and stress testing.

The connection to the underlying coordination game is also illuminating. Without private information, the game has two equilibria for intermediate fundamentals. The global game selects between them using a refinement that is robust to the details of the information structure – the unique equilibrium converges to the risk-dominant equilibrium of the complete-information game as signals become noisy. This provides a game-theoretic foundation for risk dominance as a selection criterion.

References

Back to top

Reuse

Citation

BibTeX citation:
@online{heller2026,
  author = {Heller, Raban},
  title = {Global Games and Coordination Under Private Information},
  date = {2026-05-08},
  url = {https://r-heller.github.io/equilibria/tutorials/bayesian-methods/global-games-coordination/},
  langid = {en}
}
For attribution, please cite this work as:
Heller, Raban. 2026. “Global Games and Coordination Under Private Information.” May 8. https://r-heller.github.io/equilibria/tutorials/bayesian-methods/global-games-coordination/.