关于 general-equilibrium-model-builder
general-equilibrium-model-builder 是帮助经济学家构建和求解瓦尔拉斯纯交换一般均衡模型的技能,结合理论结果、Julia 数值求解和埃奇沃思盒可视化。
主要功能
- 01构建纯交换经济模型
- 02讲解均衡与福利定理
- 03生成 Julia 均衡求解代码
- 04规范化价格并求解超额需求
- 05用埃奇沃思盒可视化配置
适用场景
- 01推导经济模型的均衡条件
- 02计算均衡价格与配置
- 03分析福利与帕累托效率
- 04通过比较静态研究参数变化
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ meleantonio/ awesome-econ-ai-stuff --skill general-equilibrium-model-builder安装后在 Claude Code 中输入/general-equilibrium-model-builder确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
index.mdexamples/comparative_statics.jlpure_exchange_2x2.jl详细介绍
一般均衡模型构建器
目的
此技能可帮助经济学家构建、分析并数值求解**瓦尔拉斯一般均衡(GE)**模型,涵盖理论基础(存在性、唯一性、福利定理)以及使用 Julia 计算均衡价格和配置。
当前范围:纯交换经济(无生产)。未来版本将扩展到生产经济、含不确定性的 Arrow-Debreu 模型和动态模型。
适用场景
- 理论研究:为论文构建正式的纯交换 GE 模型
- 教学:为微观经济学理论课程创建示例
- 计算:数值求解均衡价格和配置
- 福利分析:评估帕累托效率和社会福利
- 比较静态分析:分析均衡如何随参数变化
说明
步骤 1:了解经济环境
生成任何模型之前,先询问用户:
- 商品数量($L$):经济中有多少种商品?
- 消费者数量($I$):有多少个主体?
- 偏好:效用函数是什么?(Cobb-Douglas、CES、Leontief、拟线性)
- 禀赋:每个主体的初始禀赋向量是什么?
- 输出格式:理论推导、Julia 代码,还是两者兼有?
步骤 2:建立理论框架
纯交换经济 $\mathcal{E}$ 的特征如下:
$$\mathcal{E} = \left{ (u^i, \omega^i)_{i=1}^{I} \right}$$
其中:
- $u^i: \mathbb{R}^L_+ \to \mathbb{R}$ 是消费者 $i$ 的效用函数
- $\omega^i \in \mathbb{R}^L_+$ 是消费者 $i$ 的禀赋向量
- $L$ 是商品数量
- $I$ 是消费者数量
消费者问题:给定价格 $p \in \mathbb{R}^L_{++}$,消费者 $i$ 求解:
$$\max_{x^i \in \mathbb{R}^L_+} u^i(x^i) \quad \text{s.t.} \quad p \cdot x^i \leq p \cdot \omega^i$$
该问题的解给出马歇尔需求 $x^i(p, p \cdot \omega^i)$。
步骤 3:定义瓦尔拉斯均衡
定义(瓦尔拉斯均衡):若配置 $(x^{*1}, \ldots, x^{I})$ 和价格向量 $p^ \in \mathbb{R}^L_{++}$ 满足以下条件,则构成瓦尔拉斯均衡:
- 效用最大化:对每个 $i$,$x^{i}$ 都是在价格 $p^$ 下消费者 $i$ 问题的解
- 市场出清:$\sum_{i=1}^{I} x^{*i} = \sum_{i=1}^{I} \omega^i$
等价地,超额需求函数 $z(p) = \sum_{i=1}^{I} [x^i(p) - \omega^i]$ 满足 $z(p^*) = 0$。
步骤 4:陈述关键理论结果
酌情纳入以下定理:
定理(瓦尔拉斯定律):对于任意价格向量 $p$: $$p \cdot z(p) = 0$$
解释:超额需求的价值始终为零(预算约束取等号)。
定理(第一福利定理):每个瓦尔拉斯均衡配置都是帕累托有效的。
定理(第二福利定理):在凸性假设下,任何帕累托有效配置都可以通过适当的一次性转移支持为瓦尔拉斯均衡。
定理(存在性——Debreu,1959):在标准假设下(偏好连续、严格凸、严格单调,禀赋严格为正),瓦尔拉斯均衡存在。
步骤 5:生成用于计算的 Julia 代码
使用 Julia,并采用以下结构:
# ============================================
# General Equilibrium Solver in Julia
# Pure Exchange Economy
# ============================================
using LinearAlgebra
using NLsolve
using Plots
# Define the economy structure
struct PureExchangeEconomy
n_goods::Int # Number of goods (L)
n_consumers::Int # Number of consumers (I)
endowments::Matrix{Float64} # I × L matrix of endowments
utility_params::Vector{Any} # Parameters for utility functions
utility_type::Symbol # :cobb_douglas, :ces, :leontief
end
# Cobb-Douglas utility: u(x) = ∏ x_l^α_l
function utility_cobb_douglas(x, α)
return prod(x .^ α)
end
# Marshallian demand for Cobb-Douglas preferences
function demand_cobb_douglas(p, wealth, α)
# x_l = (α_l / sum(α)) * (wealth / p_l)
α_normalized = α / sum(α)
return α_normalized .* wealth ./ p
end
# Excess demand function
function excess_demand(p, economy::PureExchangeEconomy)
z = zeros(economy.n_goods)
for i in 1:economy.n_consumers
ω_i = economy.endowments[i, :]
wealth_i = dot(p, ω_i)
if economy.utility_type == :cobb_douglas
α_i = economy.utility_params[i]
x_i = demand_cobb_douglas(p, wealth_i, α_i)
else
error("Unsupported utility_type: $(economy.utility_type). Only :cobb_douglas is currently implemented.")
end
z += x_i - ω_i
end
return z
end
# Solve for equilibrium prices (normalize p_1 = 1)
# Uses log-price parameterization to ensure prices remain strictly positive
function solve_equilibrium(economy::PureExchangeEconomy)
# Initial guess in log-space (log of ones = zeros)
p0 = zeros(economy.n_goods - 1)
# Excess demand for goods 2 to L (Walras' Law implies good 1 clears)
# Reparameterize using log-prices: x = log(p_rest), so p_rest = exp(x)
function excess_demand_reduced!(F, x)
p_rest = exp.(x) # Exponentiate to get positive prices
p = vcat(1.0, p_rest) # Numeraire p_1 = 1
z = excess_demand(p, economy)
F .= z[2:end]
end
# Solve z(p) = 0 in log-space
result = nlsolve(excess_demand_reduced!, p0, autodiff=:forward)
if converged(result)
p_rest_star = exp.(result.zero) # Convert back from log-space
p_star = vcat(1.0, p_rest_star)
return p_star
else
error("Equilibrium solver did not converge")
end
end
# Compute equilibrium allocations
function equilibrium_allocations(p_star, economy::PureExchangeEconomy)
allocations = zeros(economy.n_consumers, economy.n_goods)
for i in 1:economy.n_consumers
ω_i = economy.endowments[i, :]
wealth_i = dot(p_star, ω_i)
if economy.utility_type == :cobb_douglas
α_i = economy.utility_params[i]
allocations[i, :] = demand_cobb_douglas(p_star, wealth_i, α_i)
else
throw(ArgumentError("Unsupported utility_type: $(economy.utility_type) in equilibrium_allocations. Only :cobb_douglas is currently implemented."))
end
end
return allocations
end
# Check Pareto efficiency via MRS equality
function check_pareto_efficiency(allocations, economy::PureExchangeEconomy)
# Currently only supports 2-good economies
if economy.n_goods != 2
throw(ArgumentError("check_pareto_efficiency currently only supports 2-good economies. Got economy.n_goods = $(economy.n_goods)."))
end
if economy.utility_type == :cobb_douglas
# MRS_{12} = (α_1/α_2) * (x_2/x_1) should be equal for all consumers
epsilon = 1e-12 # Small threshold for near-zero detection
mrs_values = []
for i in 1:economy.n_consumers
α_i = economy.utility_params[i]
x_i = allocations[i, :]
# Guard against division by zero: check both x_i[1] and α_i[2]
if abs(x_i[1]) < epsilon || abs(α_i[2]) < epsilon
# Handle corner case: set sentinel value for zero/near-zero consumption
push!(mrs_values, Inf)
else
mrs_i = (α_i[1] / α_i[2]) * (x_i[2] / x_i[1])
push!(mrs_values, mrs_i)
end
end
return mrs_values
else
throw(ArgumentError("Unsupported utility type: $(economy.utility_type) in check_pareto_efficiency. Only :cobb_douglas is currently implemented."))
end
end
步骤 6:提供完整示例
# ============================================
# Example: 2×2 Pure Exchange Economy
# ============================================
# Two consumers, two goods
# Consumer 1: u(x,y) = x^0.6 * y^0.4, endowment (4, 1)
# Consumer 2: u(x,y) = x^0.3 * y^0.7, endowment (1, 4)
economy = PureExchangeEconomy(
2, # 2 goods
2, # 2 consumers
[4.0 1.0; 1.0 4.0], # Endowment matrix
[[0.6, 0.4], [0.3, 0.7]], # Cobb-Douglas parameters
:cobb_douglas
)
# Solve for equilibrium
p_star = solve_equilibrium(economy)
println("Equilibrium prices: p = ", p_star)
# Compute allocations
x_star = equilibrium_allocations(p_star, economy)
println("Consumer 1 allocation: ", x_star[1, :])
println("Consumer 2 allocation: ", x_star[2, :])
# Verify market clearing
total_endowment = sum(economy.endowments, dims=1)
total_allocation = sum(x_star, dims=1)
println("Market clearing check: ", isapprox(total_endowment, total_allocation))
# Check Pareto efficiency (MRS equality)
mrs = check_pareto_efficiency(x_star, economy)
println("MRS values (should be equal): ", mrs)
步骤 7:使用埃奇沃思盒图示
# ============================================
# Edgeworth Box Visualization
# ============================================
function plot_edgeworth_box(economy::PureExchangeEconomy, p_star, x_star)
# Total endowment defines box dimensions
ω_total = vec(sum(economy.endowments, dims=1))
# Create plot
plt = plot(
xlim=(0, ω_total[1]),
ylim=(0, ω_total[2]),
xlabel="Good 1",
ylabel="Good 2",
title="Edgeworth Box",
legend=:topright,
aspect_ratio=:equal
)
# Plot endowment point
ω1 = economy.endowments[1, :]
scatter!([ω1[1]], [ω1[2]], label="Endowment", markersize=8, color=:red)
# Plot equilibrium allocation
scatter!([x_star[1, 1]], [x_star[1, 2]], label="Equilibrium", markersize=8, color=:green)
# Plot budget line through endowment
# p_1 * x_1 + p_2 * x_2 = p_1 * ω_1 + p_2 * ω_2
wealth1 = dot(p_star, ω1)
x1_range = range(0, ω_total[1], length=100)
x2_budget = (wealth1 .- p_star[1] .* x1_range) ./ p_star[2]
plot!(x1_range, x2_budget, label="Budget line", color=:blue, linewidth=2)
# Plot contract curve (locus of Pareto efficient allocations)
# For Cobb-Douglas, contract curve: x_2^1 / x_1^1 = (α_2^1/α_1^1) / (α_2^2/α_1^2) * (ω_2 - x_2^1) / (ω_1 - x_1^1)
return plt
end
# Generate the plot
plt = plot_edgeworth_box(economy, p_star, x_star)
savefig(plt, "edgeworth_box.png")
示例提示词
用户可能会使用以下提示词调用此技能:
- “构建一个有 2 种商品、3 个消费者且偏好为 CES 的纯交换经济”
- “推导 Cobb-Douglas 经济的瓦尔拉斯均衡条件”
- “编写 Julia 代码,求解我的交换经济中的均衡价格”
- “证明纯交换经济的第一福利定理”
- “绘制一个显示契约曲线和均衡的埃奇沃思盒图”
- “计算比较静态:禀赋变化时均衡如何变化?”
要求
软件
- Julia 1.9+
Packages
using Pkg
Pkg.add(["NLsolve", "LinearAlgebra", "Plots", "ForwardDiff"])
| Package | Purpose |
|---|---|
NLsolve | 求解超额需求等于 0 的非线性方程 |
LinearAlgebra | 向量/矩阵运算 |
Plots | 可视化(埃奇沃思盒等) |
ForwardDiff | 用于计算雅可比矩阵的自动微分 |
数学背景
存在性假设
确保均衡存在的标准假设:
- 连续性:每个 $u^i$ 都是连续的
- 严格单调性:$x \gg y \Rightarrow u^i(x) > u^i(y)$
- 严格凸性:$u^i$ 严格拟凹
- 禀赋为正:对所有 $i$,$\omega^i \gg 0$
超额需求的性质
在标准假设下,$z(p)$ 满足:
- 连续性:$z$ 连续
- 0 次齐次性:对所有 $\lambda > 0$,$z(\lambda p) = z(p)$
- 瓦尔拉斯定律:$p \cdot z(p) = 0$
- 边界行为:若 $p_l \to 0$,则 $z_l(p) \to +\infty$
数值求解策略
- 价格归一化:设 $p_1 = 1$(计价物)
- 降低维度:求解 $z_2(p) = \cdots = z_L(p) = 0$(根据瓦尔拉斯定律,$z_1 = 0$)
- 使用牛顿法:使用带自动微分雅可比矩阵的
NLsolve.jl - 处理边界:确保迭代过程中 $p_l > 0$
最佳实践
- 求解后始终验证市场出清
- 检查瓦尔拉斯定律在数值上是否成立($p \cdot z \approx 0$)
- 检查消费者之间的边际替代率是否相等,以验证帕累托效率
- 若求解器不收敛,使用多个初始猜测值
- 对价格进行归一化,以避免不确定性(0 次齐次性)
常见问题
- ❌ 忘记价格只在相差一个比例因子的意义下确定(必须归一化)
- ❌ 未检查角点解(某种商品的消费量为零)
- ❌ 忽视边界附近的数值精度问题
- ❌ 未经验证就假定解唯一(可能存在多个均衡)
- ❌ 混淆马歇尔需求(未补偿需求)和希克斯需求(已补偿需求)
扩展(未来版本)
- 生产经济:追求利润最大化的企业
- 阿罗-德布鲁证券:或有索取权与不确定性
- 世代交叠模型(OLG):具有代际交叠的动态一般均衡
- 可计算一般均衡(CGE):用于政策分析的校准模型
- 不完全市场:并非所有或有事件都可以交易的情形
参考资料
教科书
- Mas-Colell、Whinston 和 Green(1995)。Microeconomic Theory。Oxford University Press。第 15–17 章。
- Debreu,G.(1959)。Theory of Value。Yale University Press。
- Varian,H.(1992)。Microeconomic Analysis。第 3 版。第 17–18 章。
计算资源
- QuantEcon Julia 讲义:https://julia.quantecon.org/
- Judd,K.(1998)。Numerical Methods in Economics。MIT Press。
重要论文
- Arrow,K. J. 和 Debreu,G.(1954)。竞争经济中均衡的存在性。Econometrica,22(3),265-290。
- Scarf,H.(1967)。连续映射不动点的近似。SIAM Journal on Applied Mathematics,15(5),1328-1343。
更新日志
v1.0.0
- 首次发布:采用 Cobb-Douglas 偏好的纯交换经济
- 使用 NLsolve 的 Julia 实现
- 埃奇沃思盒可视化
- 理论框架与福利定理