{
"cells": [
{
"cell_type": "markdown",
"id": "2b8e1351",
"metadata": {},
"source": [
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "22cd645d",
"metadata": {},
"source": [
"# Market Equilibrium with Heterogeneity"
]
},
{
"cell_type": "markdown",
"id": "97265977",
"metadata": {},
"source": [
"## Contents\n",
"\n",
"- [Market Equilibrium with Heterogeneity](#Market-Equilibrium-with-Heterogeneity) \n",
" - [Overview](#Overview) \n",
" - [An simple example](#An-simple-example) \n",
" - [Pure exchange economy](#Pure-exchange-economy) \n",
" - [Implementation](#Implementation) \n",
" - [Deducing a representative consumer](#Deducing-a-representative-consumer) "
]
},
{
"cell_type": "markdown",
"id": "2184b668",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"In the [previous lecture](https://intro.quantecon.org/supply_demand_multiple_goods.html), we studied competitive equilibria in an economy with many goods.\n",
"\n",
"While the results of the study were informative, we used a strong simplifying assumption: all of the agents in the economy are identical.\n",
"\n",
"In the real world, households, firms and other economic agents differ from one another along many dimensions.\n",
"\n",
"In this lecture, we introduce heterogeneity across consumers by allowing their preferences and endowments to differ.\n",
"\n",
"We will examine competitive equilibrium in this setting.\n",
"\n",
"We will also show how a “representative consumer” can be constructed.\n",
"\n",
"Here are some imports:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bf254a08",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"from scipy.linalg import inv"
]
},
{
"cell_type": "markdown",
"id": "42635194",
"metadata": {},
"source": [
"## An simple example\n",
"\n",
"Let’s study a simple example of **pure exchange** economy without production.\n",
"\n",
"There are two consumers who differ in their endowment vectors $ e_i $ and their bliss-point vectors $ b_i $ for $ i=1,2 $.\n",
"\n",
"The total endowment is $ e_1 + e_2 $.\n",
"\n",
"A competitive equilibrium requires that\n",
"\n",
"$$\n",
"c_1 + c_2 = e_1 + e_2\n",
"$$\n",
"\n",
"Assume the demand curves\n",
"\n",
"$$\n",
"c_i = (\\Pi^\\top \\Pi )^{-1}(\\Pi^\\top b_i - \\mu_i p )\n",
"$$\n",
"\n",
"Competitive equilibrium then requires that\n",
"\n",
"$$\n",
"e_1 + e_2 =\n",
" (\\Pi^\\top \\Pi)^{-1}(\\Pi^\\top (b_1 + b_2) - (\\mu_1 + \\mu_2) p )\n",
"$$\n",
"\n",
"which, after a line or two of linear algebra, implies that\n",
"\n",
"\n",
"\n",
"$$\n",
"(\\mu_1 + \\mu_2) p = \\Pi^\\top(b_1+ b_2) - \\Pi^\\top \\Pi (e_1 + e_2) \\tag{35.1}\n",
"$$\n",
"\n",
"We can normalize prices by setting $ \\mu_1 + \\mu_2 =1 $ and then solving\n",
"\n",
"\n",
"\n",
"$$\n",
"\\mu_i(p,e) = \\frac{p^\\top (\\Pi^{-1} b_i - e_i)}{p^\\top (\\Pi^\\top \\Pi )^{-1} p} \\tag{35.2}\n",
"$$\n",
"\n",
"for $ \\mu_i, i = 1,2 $."
]
},
{
"cell_type": "markdown",
"id": "8eddb12d",
"metadata": {},
"source": [
"## Exercise 35.1\n",
"\n",
"Show that, up to normalization by a positive scalar, the same competitive equilibrium price vector that you computed in the preceding two-consumer economy would prevail in a single-consumer economy in which a single **representative consumer** has utility function\n",
"\n",
"$$\n",
"-.5 (\\Pi c -b) ^\\top (\\Pi c -b )\n",
"$$\n",
"\n",
"and endowment vector $ e $, where\n",
"\n",
"$$\n",
"b = b_1 + b_2\n",
"$$\n",
"\n",
"and\n",
"\n",
"$$\n",
"e = e_1 + e_2 .\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "219d828c",
"metadata": {},
"source": [
"## Pure exchange economy\n",
"\n",
"Let’s further explore a pure exchange economy with $ n $ goods and $ m $ people."
]
},
{
"cell_type": "markdown",
"id": "102e1485",
"metadata": {},
"source": [
"### Competitive equilibrium\n",
"\n",
"We’ll compute a competitive equilibrium.\n",
"\n",
"To compute a competitive equilibrium of a pure exchange economy, we use the fact that\n",
"\n",
"- Relative prices in a competitive equilibrium are the same as those in a special single person or representative consumer economy with preference $ \\Pi $ and $ b=\\sum_i b_i $, and endowment $ e = \\sum_i e_{i} $. \n",
"\n",
"\n",
"We can use the following steps to compute a competitive equilibrium:\n",
"\n",
"- First we solve the single representative consumer economy by normalizing $ \\mu = 1 $. Then, we renormalize the price vector by using the first consumption good as a numeraire. \n",
"- Next we use the competitive equilibrium prices to compute each consumer’s marginal utility of wealth: \n",
"\n",
"\n",
"$$\n",
"\\mu_{i}=\\frac{-W_{i}+p^{\\top}\\left(\\Pi^{-1}b_{i}-e_{i}\\right)}{p^{\\top}(\\Pi^{\\top}\\Pi)^{-1}p}\n",
"$$\n",
"\n",
"- Finally we compute a competitive equilibrium allocation by using the demand curves: \n",
"\n",
"\n",
"$$\n",
"c_{i}=\\Pi^{-1}b_{i}-(\\Pi^{\\top}\\Pi)^{-1}\\mu_{i}p\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "4a624639",
"metadata": {},
"source": [
"### Designing some Python code\n",
"\n",
"Below we shall construct a Python class with the following attributes:\n",
"\n",
"- **Preferences** in the form of \n",
" - an $ n \\times n $ positive definite matrix $ \\Pi $ \n",
" - an $ n \\times 1 $ vector of bliss points $ b $ \n",
"- **Endowments** in the form of \n",
" - an $ n \\times 1 $ vector $ e $ \n",
" - a scalar “wealth” $ W $ with default value $ 0 $ \n",
"\n",
"\n",
"The class will include a test to make sure that $ b \\gg \\Pi e $ and raise an exception if it is violated\n",
"(at some threshold level we’d have to specify).\n",
"\n",
"- **A Person** in the form of a pair that consists of \n",
" - **Preferences** and **Endowments** \n",
"- **A Pure Exchange Economy** will consist of \n",
" - a collection of $ m $ **persons** \n",
" - $ m=1 $ for our single-agent economy \n",
" - $ m=2 $ for our illustrations of a pure exchange economy \n",
" - an equilibrium price vector $ p $ (normalized somehow) \n",
" - an equilibrium allocation $ c_1, c_2, \\ldots, c_m $ – a collection of $ m $ vectors of dimension $ n \\times 1 $ \n",
"\n",
"\n",
"Now let’s proceed to code."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "343d28cf",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"class ExchangeEconomy:\n",
" def __init__(self, \n",
" Π, \n",
" bs, \n",
" es, \n",
" Ws=None, \n",
" thres=1.5):\n",
" \"\"\"\n",
" Set up the environment for an exchange economy\n",
"\n",
" Args:\n",
" Π (np.array): shared matrix of substitution\n",
" bs (list): all consumers' bliss points\n",
" es (list): all consumers' endowments\n",
" Ws (list): all consumers' wealth\n",
" thres (float): a threshold set to test b >> Pi e violated\n",
" \"\"\"\n",
" n, m = Π.shape[0], len(bs)\n",
"\n",
" # check non-satiation\n",
" for b, e in zip(bs, es):\n",
" if np.min(b / np.max(Π @ e)) <= thres:\n",
" raise Exception('set bliss points further away')\n",
"\n",
" if Ws == None:\n",
" Ws = np.zeros(m)\n",
" else:\n",
" if sum(Ws) != 0:\n",
" raise Exception('invalid wealth distribution')\n",
"\n",
" self.Π, self.bs, self.es, self.Ws, self.n, self.m = Π, bs, es, Ws, n, m\n",
"\n",
" def competitive_equilibrium(self):\n",
" \"\"\"\n",
" Compute the competitive equilibrium prices and allocation\n",
" \"\"\"\n",
" Π, bs, es, Ws = self.Π, self.bs, self.es, self.Ws\n",
" n, m = self.n, self.m\n",
" slope_dc = inv(Π.T @ Π)\n",
" Π_inv = inv(Π)\n",
"\n",
" # aggregate\n",
" b = sum(bs)\n",
" e = sum(es)\n",
"\n",
" # compute price vector with mu=1 and renormalize\n",
" p = Π.T @ b - Π.T @ Π @ e\n",
" p = p / p[0]\n",
"\n",
" # compute marginal utility of wealth\n",
" μ_s = []\n",
" c_s = []\n",
" A = p.T @ slope_dc @ p\n",
"\n",
" for i in range(m):\n",
" μ_i = (-Ws[i] + p.T @ (Π_inv @ bs[i] - es[i])) / A\n",
" c_i = Π_inv @ bs[i] - μ_i * slope_dc @ p\n",
" μ_s.append(μ_i)\n",
" c_s.append(c_i)\n",
"\n",
" for c_i in c_s:\n",
" if any(c_i < 0):\n",
" print('allocation: ', c_s)\n",
" raise Exception('negative allocation: equilibrium does not exist')\n",
"\n",
" return p, c_s, μ_s"
]
},
{
"cell_type": "markdown",
"id": "0da76dfe",
"metadata": {},
"source": [
"## Implementation\n",
"\n",
"Next we use the class `ExchangeEconomy` defined above to study\n",
"\n",
"- a two-person economy without production, \n",
"- a dynamic economy, and \n",
"- an economy with risk and arrow securities. "
]
},
{
"cell_type": "markdown",
"id": "b54f9561",
"metadata": {},
"source": [
"### Two-person economy without production\n",
"\n",
"Here we study how competitive equilibrium $ p, c_1, c_2 $ respond to different $ b_i $ and $ e_i $, $ i \\in \\{1, 2\\} $."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c525da51",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"Π = np.array([[1, 0],\n",
" [0, 1]])\n",
"\n",
"bs = [np.array([5, 5]), # first consumer's bliss points\n",
" np.array([5, 5])] # second consumer's bliss points\n",
"\n",
"es = [np.array([0, 2]), # first consumer's endowment\n",
" np.array([2, 0])] # second consumer's endowment\n",
"\n",
"EE = ExchangeEconomy(Π, bs, es)\n",
"p, c_s, μ_s = EE.competitive_equilibrium()\n",
"\n",
"print('Competitive equilibrium price vector:', p)\n",
"print('Competitive equilibrium allocation:', c_s)"
]
},
{
"cell_type": "markdown",
"id": "a50c583d",
"metadata": {},
"source": [
"What happens if the first consumer likes the first good more and the second consumer likes the second good more?"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c9fd97a2",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"EE.bs = [np.array([6, 5]), # first consumer's bliss points\n",
" np.array([5, 6])] # second consumer's bliss points\n",
"\n",
"p, c_s, μ_s = EE.competitive_equilibrium()\n",
"\n",
"print('Competitive equilibrium price vector:', p)\n",
"print('Competitive equilibrium allocation:', c_s)"
]
},
{
"cell_type": "markdown",
"id": "b7f90e3b",
"metadata": {},
"source": [
"Let the first consumer be poorer."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e1bda43f",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"EE.es = [np.array([0.5, 0.5]), # first consumer's endowment\n",
" np.array([1, 1])] # second consumer's endowment\n",
"\n",
"p, c_s, μ_s = EE.competitive_equilibrium()\n",
"\n",
"print('Competitive equilibrium price vector:', p)\n",
"print('Competitive equilibrium allocation:', c_s)"
]
},
{
"cell_type": "markdown",
"id": "59ff224d",
"metadata": {},
"source": [
"Now let’s construct an autarky (i.e., no-trade) equilibrium."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f64ac114",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"EE.bs = [np.array([4, 6]), # first consumer's bliss points\n",
" np.array([6, 4])] # second consumer's bliss points\n",
"\n",
"EE.es = [np.array([0, 2]), # first consumer's endowment\n",
" np.array([2, 0])] # second consumer's endowment\n",
"\n",
"p, c_s, μ_s = EE.competitive_equilibrium()\n",
"\n",
"print('Competitive equilibrium price vector:', p)\n",
"print('Competitive equilibrium allocation:', c_s)"
]
},
{
"cell_type": "markdown",
"id": "cd236360",
"metadata": {},
"source": [
"Now let’s redistribute endowments before trade."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5529f5ef",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"bs = [np.array([5, 5]), # first consumer's bliss points\n",
" np.array([5, 5])] # second consumer's bliss points\n",
"\n",
"es = [np.array([1, 1]), # first consumer's endowment\n",
" np.array([1, 1])] # second consumer's endowment\n",
"\n",
"Ws = [0.5, -0.5]\n",
"EE_new = ExchangeEconomy(Π, bs, es, Ws)\n",
"p, c_s, μ_s = EE_new.competitive_equilibrium()\n",
"\n",
"print('Competitive equilibrium price vector:', p)\n",
"print('Competitive equilibrium allocation:', c_s)"
]
},
{
"cell_type": "markdown",
"id": "5bbf862e",
"metadata": {},
"source": [
"### A dynamic economy\n",
"\n",
"Now let’s use the tricks described above to study a dynamic economy, one with two periods."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7dcaddb7",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"beta = 0.95\n",
"\n",
"Π = np.array([[1, 0],\n",
" [0, np.sqrt(beta)]])\n",
"\n",
"bs = [np.array([5, np.sqrt(beta) * 5])]\n",
"\n",
"es = [np.array([1, 1])]\n",
"\n",
"EE_DE = ExchangeEconomy(Π, bs, es)\n",
"p, c_s, μ_s = EE_DE.competitive_equilibrium()\n",
"\n",
"print('Competitive equilibrium price vector:', p)\n",
"print('Competitive equilibrium allocation:', c_s)"
]
},
{
"cell_type": "markdown",
"id": "204f396e",
"metadata": {},
"source": [
"### Risk economy with arrow securities\n",
"\n",
"We use the tricks described above to interpret $ c_1, c_2 $ as “Arrow securities” that are state-contingent claims to consumption goods."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5bfcc90a",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"prob = 0.7\n",
"\n",
"Π = np.array([[np.sqrt(prob), 0],\n",
" [0, np.sqrt(1 - prob)]])\n",
"\n",
"bs = [np.array([np.sqrt(prob) * 5, np.sqrt(1 - prob) * 5]),\n",
" np.array([np.sqrt(prob) * 5, np.sqrt(1 - prob) * 5])]\n",
"\n",
"es = [np.array([1, 0]),\n",
" np.array([0, 1])]\n",
"\n",
"EE_AS = ExchangeEconomy(Π, bs, es)\n",
"p, c_s, μ_s = EE_AS.competitive_equilibrium()\n",
"\n",
"print('Competitive equilibrium price vector:', p)\n",
"print('Competitive equilibrium allocation:', c_s)"
]
},
{
"cell_type": "markdown",
"id": "b79ffc36",
"metadata": {},
"source": [
"## Deducing a representative consumer\n",
"\n",
"In the class of multiple consumer economies that we are studying here, it turns out that there\n",
"exists a single **representative consumer** whose preferences and endowments can be deduced from lists of preferences and endowments for separate individual consumers.\n",
"\n",
"Consider a multiple consumer economy with initial distribution of wealth $ W_i $ satisfying $ \\sum_i W_{i}=0 $\n",
"\n",
"We allow an initial redistribution of wealth.\n",
"\n",
"We have the following objects\n",
"\n",
"- The demand curve: \n",
"\n",
"\n",
"$$\n",
"c_{i}=\\Pi^{-1}b_{i}-(\\Pi^{\\top}\\Pi)^{-1}\\mu_{i}p\n",
"$$\n",
"\n",
"- The marginal utility of wealth: \n",
"\n",
"\n",
"$$\n",
"\\mu_{i}=\\frac{-W_{i}+p^{\\top}\\left(\\Pi^{-1}b_{i}-e_{i}\\right)}{p^{\\top}(\\Pi^{\\top}\\Pi)^{-1}p}\n",
"$$\n",
"\n",
"- Market clearing: \n",
"\n",
"\n",
"$$\n",
"\\sum c_{i}=\\sum e_{i}\n",
"$$\n",
"\n",
"Denote aggregate consumption $ \\sum_i c_{i}=c $ and $ \\sum_i \\mu_i = \\mu $.\n",
"\n",
"Market clearing requires\n",
"\n",
"$$\n",
"\\Pi^{-1}\\left(\\sum_{i}b_{i}\\right)-(\\Pi^{\\top}\\Pi)^{-1}p\\left(\\sum_{i}\\mu_{i}\\right)=\\sum_{i}e_{i}\n",
"$$\n",
"\n",
"which, after a few steps, leads to\n",
"\n",
"$$\n",
"p=\\mu^{-1}\\left(\\Pi^{\\top}b-\\Pi^{\\top}\\Pi e\\right)\n",
"$$\n",
"\n",
"where\n",
"\n",
"$$\n",
"\\mu = \\sum_i\\mu_{i}=\\frac{0 + p^{\\top}\\left(\\Pi^{-1}b-e\\right)}{p^{\\top}(\\Pi^{\\top}\\Pi)^{-1}p}.\n",
"$$\n",
"\n",
"Now consider the representative consumer economy specified above.\n",
"\n",
"Denote the marginal utility of wealth of the representative consumer by $ \\tilde{\\mu} $.\n",
"\n",
"The demand function is\n",
"\n",
"$$\n",
"c=\\Pi^{-1}b-(\\Pi^{\\top}\\Pi)^{-1}\\tilde{\\mu} p\n",
"$$\n",
"\n",
"Substituting this into the budget constraint gives\n",
"\n",
"$$\n",
"\\tilde{\\mu}=\\frac{p^{\\top}\\left(\\Pi^{-1}b-e\\right)}{p^{\\top}(\\Pi^{\\top}\\Pi)^{-1}p}\n",
"$$\n",
"\n",
"In an equilibrium $ c=e $, so\n",
"\n",
"$$\n",
"p=\\tilde{\\mu}^{-1}(\\Pi^{\\top}b-\\Pi^{\\top}\\Pi e)\n",
"$$\n",
"\n",
"Thus, we have verified that, up to the choice of a numeraire in which to express absolute prices, the price\n",
"vector in our representative consumer economy is the same as that in an underlying economy with multiple consumers."
]
}
],
"metadata": {
"date": 1696997366.8710868,
"filename": "supply_demand_heterogeneity.md",
"kernelspec": {
"display_name": "Python",
"language": "python3",
"name": "python3"
},
"title": "Market Equilibrium with Heterogeneity"
},
"nbformat": 4,
"nbformat_minor": 5
}