babylon.formulas.class_dynamics

Class Wealth Dynamics ODE System.

Empirically derived from FRED Distributional Financial Accounts (DFA) data (2015-2025). Models wealth flows between four Marxian classes:

  • Core Bourgeoisie (Top 1%)

  • Petty Bourgeoisie (90-99%)

  • Labor Aristocracy (50-90%)

  • Internal Proletariat (Bottom 50%)

Key Finding: Wealth distribution is remarkably stable: - Top 1% maintains ~30% homeostasis (self-reinforcing) - 90-99% slowly loses ground (-0.3%/year) - Bottom classes gain slightly through redistribution

First-Order System:

dW₁/dt = α₄₁W₄ + α₃₁W₃ + α₂₁W₂ - δ₁W₁ dW₂/dt = α₃₂W₃ + α₄₂W₄ - α₂₁W₂ - δ₂W₂ dW₃/dt = α₄₃W₄ + γ₃ - α₃₁W₃ - α₃₂W₃ - δ₃W₃ dW₄/dt = -(dW₁ + dW₂ + dW₃) [constraint: ΣWᵢ = 1]

Second-Order Terms:

d²Wᵢ/dt² = βᵢ(dWᵢ/dt) - ωᵢ²(Wᵢ - Wᵢ*)

See also

tools/analyze_wealth_distribution.py for data derivation FRED DFA: https://www.federalreserve.gov/releases/z1/dataviz/dfa/

Functions

calculate_class_dynamics_derivative(...[, ...])

Compute dW/dt for all four classes (first-order system).

calculate_equilibrium_deviation(wealth_shares)

Calculate total deviation from equilibrium wealth distribution.

calculate_full_dynamics(wealth_shares, ...)

Compute both first and second order derivatives.

calculate_wealth_acceleration(wealth_share, ...)

Compute d²W/dt² for second-order dynamics.

calculate_wealth_flow(source_share, ...[, ...])

Calculate per-tick wealth flow from source class.

invert_wealth_to_population(wealth_shares[, ...])

Find population percentile owning target wealth percentage.

Classes

ClassDynamicsParams([alpha_41, alpha_31, ...])

Parameters for class wealth dynamics ODE system.

SecondOrderParams([beta, omega, equilibrium])

Second-order dynamics parameters for momentum effects.

class babylon.formulas.class_dynamics.ClassDynamicsParams(alpha_41=0.0, alpha_31=0.0, alpha_21=0.0006, alpha_32=0.0, alpha_42=0.0, alpha_43=0.0, delta_1=0.001, delta_2=0.002, delta_3=0.001, gamma_3=0.0057)[source]

Bases: object

Parameters for class wealth dynamics ODE system.

All rates are per-tick (convert from quarterly by dividing by ticks_per_quarter).

Parameters:
alpha_41

Extraction rate from proletariat to bourgeoisie.

alpha_31

Extraction rate from labor aristocracy to bourgeoisie.

alpha_21

Extraction rate from petty bourgeoisie to bourgeoisie.

alpha_32

Rent-seeking from labor aristocracy to petty bourgeoisie.

alpha_42

Extraction from proletariat to petty bourgeoisie.

alpha_43

Extraction from proletariat to labor aristocracy.

delta_1

Redistribution rate from bourgeoisie (taxation).

delta_2

Redistribution rate from petty bourgeoisie.

delta_3

Redistribution rate from labor aristocracy.

gamma_3

Imperial rent formation rate (superwages).

Examples

>>> params = ClassDynamicsParams()
>>> params.gamma_3
0.0057
alpha_41: float = 0.0
alpha_31: float = 0.0
alpha_21: float = 0.0006
alpha_32: float = 0.0
alpha_42: float = 0.0
alpha_43: float = 0.0
delta_1: float = 0.001
delta_2: float = 0.002
delta_3: float = 0.001
gamma_3: float = 0.0057
__init__(alpha_41=0.0, alpha_31=0.0, alpha_21=0.0006, alpha_32=0.0, alpha_42=0.0, alpha_43=0.0, delta_1=0.001, delta_2=0.002, delta_3=0.001, gamma_3=0.0057)
Parameters:
Return type:

None

class babylon.formulas.class_dynamics.SecondOrderParams(beta=(-0.1, -0.15, -0.1, -0.05), omega=(0.05, 0.08, 0.05, 0.03), equilibrium=(0.305, 0.382, 0.294, 0.02))[source]

Bases: object

Second-order dynamics parameters for momentum effects.

Parameters:
beta

Damping coefficients (negative = mean-reverting).

omega

Natural frequencies of oscillation.

equilibrium

Attractor wealth shares (W*).

Examples

>>> params = SecondOrderParams()
>>> params.equilibrium
(0.305, 0.382, 0.294, 0.02)
beta: tuple[float, float, float, float] = (-0.1, -0.15, -0.1, -0.05)
omega: tuple[float, float, float, float] = (0.05, 0.08, 0.05, 0.03)
equilibrium: tuple[float, float, float, float] = (0.305, 0.382, 0.294, 0.02)
__init__(beta=(-0.1, -0.15, -0.1, -0.05), omega=(0.05, 0.08, 0.05, 0.03), equilibrium=(0.305, 0.382, 0.294, 0.02))
Parameters:
Return type:

None

babylon.formulas.class_dynamics.calculate_wealth_flow(source_share, extraction_rate, resistance=0.0)[source]

Calculate per-tick wealth flow from source class.

Parameters:
  • source_share (float) – Source class wealth share [0, 1].

  • extraction_rate (float) – Base extraction coefficient.

  • resistance (float) – Class consciousness resistance [0, 1].

Return type:

float

Returns:

Wealth delta flowing out of source class.

Examples

>>> calculate_wealth_flow(0.5, 0.01, 0.0)
0.005
>>> calculate_wealth_flow(0.5, 0.01, 0.5)  # 50% resistance
0.0025
babylon.formulas.class_dynamics.calculate_class_dynamics_derivative(wealth_shares, params=None, resistances=(0.0, 0.0, 0.0, 0.0))[source]

Compute dW/dt for all four classes (first-order system).

Implements:

dW₁/dt = α₄₁W₄ + α₃₁W₃ + α₂₁W₂ - δ₁W₁ dW₂/dt = α₃₂W₃ + α₄₂W₄ - α₂₁W₂ - δ₂W₂ dW₃/dt = α₄₃W₄ + γ₃ - α₃₁W₃ - α₃₂W₃ - δ₃W₃ dW₄/dt = -(dW₁ + dW₂ + dW₃)

Parameters:
Return type:

tuple[float, float, float, float]

Returns:

(dW₁/dt, dW₂/dt, dW₃/dt, dW₄/dt) derivatives.

Examples

>>> shares = (0.30, 0.36, 0.30, 0.04)
>>> dW = calculate_class_dynamics_derivative(shares)
>>> abs(sum(dW)) < 1e-10  # Sum constraint
True
babylon.formulas.class_dynamics.calculate_wealth_acceleration(wealth_share, velocity, equilibrium, damping=-0.1, frequency=0.05)[source]

Compute d²W/dt² for second-order dynamics.

Models momentum effects and oscillation around equilibrium:

d²W/dt² = β(dW/dt) - ω²(W - W*)

Parameters:
  • wealth_share (float) – Current wealth share W.

  • velocity (float) – First derivative dW/dt.

  • equilibrium (float) – Target equilibrium wealth share W*.

  • damping (float) – Damping coefficient (negative = mean-reverting).

  • frequency (float) – Natural frequency of oscillation.

Return type:

float

Returns:

Second derivative d²W/dt².

Examples

>>> result = calculate_wealth_acceleration(0.32, 0.001, 0.30, -0.1, 0.05)
>>> round(result, 10)
-0.00015
babylon.formulas.class_dynamics.calculate_full_dynamics(wealth_shares, velocities, params=None, second_order=None, resistances=(0.0, 0.0, 0.0, 0.0))[source]

Compute both first and second order derivatives.

Combines first-order wealth flows with second-order momentum dynamics.

Parameters:
Return type:

tuple[tuple[float, float, float, float], tuple[float, float, float, float]]

Returns:

Tuple of (first_derivatives, second_derivatives).

Examples

>>> shares = (0.305, 0.382, 0.294, 0.020)
>>> vels = (0.0, -0.001, 0.0006, 0.0004)
>>> dW, d2W = calculate_full_dynamics(shares, vels)
babylon.formulas.class_dynamics.calculate_equilibrium_deviation(wealth_shares, equilibrium=None)[source]

Calculate total deviation from equilibrium wealth distribution.

Useful for detecting when the system is far from steady state.

Parameters:
Return type:

float

Returns:

Sum of squared deviations from equilibrium.

Examples

>>> result = calculate_equilibrium_deviation((0.30, 0.38, 0.29, 0.03))
>>> 0.0001 < result < 0.0003
True
babylon.formulas.class_dynamics.invert_wealth_to_population(wealth_shares, target_wealth_pct=33.333)[source]

Find population percentile owning target wealth percentage.

Inverts the wealth distribution to find what fraction of the population owns a given fraction of total wealth. Uses linear interpolation.

Parameters:
  • wealth_shares (tuple[float, float, float, float]) – (top_1%, 90-99%, 50-90%, bottom_50%) shares.

  • target_wealth_pct (float) – Target cumulative wealth percentage.

Return type:

float

Returns:

Population percentile owning up to target_wealth_pct of wealth.

Examples

>>> shares = (30.7, 36.4, 30.3, 2.5)
>>> result = invert_wealth_to_population(shares, 33.333)
>>> 90.0 < result < 91.0
True