What (One-liner)
N agents start with log-normal wealth; each tick, two random agents exchange 5% of the smaller wealth with a −0.025 mean drift; track Gini evolution. Purely pedagogical / demo — NOT a real market simulation.
How to use
Drop b0_abm_v1 onto the Canvas and fill in n_agents (default 50), ticks (default 100), and seed (default 42). Fully deterministic: the same seed yields byte-identical output.
canvas node b0_abm_v1 (n_agents=50, ticks=100, seed=42)
→ final_gini ≈ 0.21, gini_sample_path[last 10]Core formulas
wealth = rng.lognormal(0, 0.5, n_agents)
for tick in range(ticks):
i, j = rng.integers(0, n_agents, 2)
if i == j: continue
min_w = min(wealth[i], wealth[j])
transfer = 0.05 * min_w * (rng.random() - 0.45) # mean drift -0.025
wealth[i] = max(1e-9, wealth[i] + transfer)
wealth[j] = max(1e-9, total - wealth[i])
if tick % max(1, ticks // 20) == 0:
gini_sampled = gini(wealth)
final_gini = gini(wealth)Assumptions & applicability
Assumptions: fully-connected pair selection + log-normal initial + wealth floor 1e-9 + no external shocks + deterministic seed.
Applies to: Canvas teaching, complexity-skill demos, ABM primers.
Does not apply to: real markets, policy analysis, bankruptcy modeling, network-structure research.
Known limitations
- Pedagogical only — the
_modelfield explicitly declares "toy ABM" - Not calibrated — transfer=0.05 / drift=0.45 are stylized constants
- Fully-connected — no network topology
- No bankruptcy — the 1e-9 floor keeps agents alive indefinitely
- No external shocks / income / policy
- gini_sample_path only returns the last 10
- Log-normal ≠ Pareto — different from Dragulescu-Yakovenko's uniform or Bouchaud-Mézard's Pareto
References
- Dragulescu-Yakovenko (2000) EPJB — pairwise-exchange statistical mechanics
- Bouchaud-Mézard (2000) Physica A — wealth condensation
- Gini (1912) — original Gini-coefficient definition
Golden Test
tests/golden/fixtures/tier4/b0_abm/ — numpy_manual (self-referential: the golden IS the source — bit-deterministic pinned-numpy RNG). 1e-12 tolerance. 12 tests:
6 Scenarios
- default_50agents_100ticks (Canvas defaults, seed=42)
- small_10agents_20ticks
- large_200agents_500ticks
- different_seed_123 — verifies the seed IS honored
- short_ticks_5 — sample path with interval=1
- one_tick — gini_sample_path empty (boundary)
6 Contract tests
- determinism: 5 reruns byte-identical
- result_structure: 7 fixed top-level keys
- gini_in_range: ∈ [0, 1]
- gini_rounded_to_4_decimals
- sample_path_last_10: ≤ 10 elements
- model_field_locked: "toy ABM" substring present
Changelog
- 1.0.0 (2026-04-21) — First Active (Tier 4 batch 1.1)

