Skip to content

Instantly share code, notes, and snippets.

@williampolley
Last active August 18, 2020 03:14
Show Gist options
  • Save williampolley/77fbe4f5c066e475eb8dd5b3ee16794d to your computer and use it in GitHub Desktop.
Save williampolley/77fbe4f5c066e475eb8dd5b3ee16794d to your computer and use it in GitHub Desktop.
efficiency
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 106,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "a268718cf2244898946cae086006cc0a",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"interactive(children=(IntSlider(value=100, description='D Intercept', max=150, min=50, step=10), IntSlider(val…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# nbi:hide_in\n",
"#This script can be used to show simple supply and demand diagrams for teaching.\n",
"#\n",
"#William Polley\n",
"#\n",
"#\n",
"\n",
"\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import ipywidgets as widgets\n",
"import scipy\n",
"from scipy.optimize import fsolve\n",
"%matplotlib inline\n",
"\n",
"class Line:\n",
"\n",
" def __init__(self,slope,intercept):\n",
" self.slope=slope\n",
" self.intercept=intercept\n",
"\n",
"\n",
"def excess_demand(x):\n",
" return d.intercept+d.slope*x-(s.intercept+s.slope*x)\n",
"\n",
"def excess_demand_tax(x):\n",
" return d.intercept+d.slope*x-(s.intercept+10+s.slope*x)\n",
"\n",
"\n",
"d=Line(-1,0)\n",
"s=Line(.5,0)\n",
"pc=Line(0,30)\n",
"pf=Line(0,70)\n",
"\n",
"q=np.linspace(0,100,101)\n",
" \n",
"# Create the plot \n",
"def g(di,si,ds,ss,Case):\n",
" fig = plt.figure(figsize = (6,6))\n",
" ax = fig.add_axes([0,0,1,1])\n",
" ax.axis([0,100,0,100])\n",
" d.intercept=di\n",
" s.intercept=si\n",
" d.slope=ds\n",
" s.slope=ss\n",
" demand=d.intercept+d.slope*q\n",
" supply=s.intercept+s.slope*q\n",
" eq_q=fsolve(excess_demand,25)[0]\n",
" if eq_q<0:\n",
" eq_q=0\n",
" eq_p=d.intercept+d.slope*eq_q\n",
" tax=s.intercept+10+s.slope*q\n",
" eq_q_tax=fsolve(excess_demand_tax,25)[0]\n",
" if eq_q_tax<0:\n",
" eq_q_tax=0\n",
" eq_p_tax=d.intercept+d.slope*eq_q_tax\n",
" ceiling=pc.intercept+pc.slope*q\n",
" if (30-s.intercept)/s.slope>0:\n",
" eq_q_ceiling=(30-s.intercept)/s.slope\n",
" else:\n",
" eq_q_ceiling=0\n",
" ed=((30-d.intercept)/d.slope)-eq_q_ceiling\n",
" floor=pf.intercept+pf.slope*q\n",
" if (70-d.intercept)/d.slope>0:\n",
" eq_q_floor=(70-d.intercept)/d.slope\n",
" else:\n",
" eq_q_floor=0\n",
" es=((70-s.intercept)/s.slope)-eq_q_floor\n",
" if Case=='none of the above':\n",
" print('equilibrium quantity = ',eq_q)\n",
" print('equilibrium price = ',eq_p)\n",
" print('blue = consumer surplus')\n",
" print('orange = producer surplus')\n",
" plt.plot(demand,label='demand')\n",
" plt.plot(supply,label='supply')\n",
" ax.fill_between(q, demand, eq_p, where=q <=eq_q, facecolor='blue')\n",
" ax.fill_between(q, supply, eq_p, where=q <=eq_q, facecolor='orange')\n",
" elif Case=='tax of 10':\n",
" if s.intercept+10<d.intercept:\n",
" print('equilibrium quantity without tax = ',eq_q)\n",
" print('equilibrium price without tax = ',eq_p)\n",
" print('equilibrium quantity with tax = ',eq_q_tax)\n",
" print('buyer pays ',eq_p_tax)\n",
" print('seller receives ',eq_p_tax-10)\n",
" print('blue = consumer surplus')\n",
" print('orange = producer surplus')\n",
" print('black = deadweight loss')\n",
" print('green = tax burden on buyer')\n",
" print('yellow = tax burden on seller')\n",
" plt.plot(demand,label='demand')\n",
" plt.plot(supply,label='supply')\n",
" plt.plot(tax,label='supply curve with tax')\n",
" ax.fill_between(q,demand,supply,where=q<=eq_q, facecolor='black')\n",
" ax.fill_between(q, demand, eq_p_tax, where=q <=eq_q_tax, facecolor='blue')\n",
" ax.fill_between(q, supply, eq_p_tax-10, where=q <=eq_q_tax, facecolor='orange')\n",
" ax.fill_between(q,eq_p_tax,eq_p,where=q<=eq_q_tax,facecolor='green')\n",
" ax.fill_between(q,eq_p_tax-10,eq_p,where=q<=eq_q_tax,facecolor='yellow')\n",
" else:\n",
" print('supply and demand curve intercepts are too close together to illustrate the tax')\n",
" print('equilibrium quantity = ',eq_q)\n",
" print('equilibrium price = ',eq_p)\n",
" plt.plot(demand,label='demand')\n",
" plt.plot(supply,label='supply')\n",
" ax.fill_between(q, demand, eq_p, where=q <=eq_q, facecolor='blue')\n",
" ax.fill_between(q, supply, eq_p, where=q <=eq_q, facecolor='orange')\n",
" elif Case=='price ceiling at 30':\n",
" if eq_p>30:\n",
" print('equilibrium quantity without price ceiling = ',eq_q)\n",
" print('equilibrium price without price ceiling = ',eq_p)\n",
" print('quantity traded with price ceiling = ',eq_q_ceiling)\n",
" print('excess demand = ',ed)\n",
" print('blue = upper bound on consumer surplus')\n",
" print('orange = producer surplus')\n",
" print('black = lower bound on deadweight loss')\n",
" print('Note that deadweight loss is likely larger than the triangular area')\n",
" print('due to non-price rationing. The triangular area is the exact deadweight')\n",
" print('loss if, and only if, demanders with the highest reservation price')\n",
" print('receive the good.')\n",
" plt.plot(demand,label='demand')\n",
" plt.plot(supply,label='supply')\n",
" plt.plot(ceiling,label='price ceiling')\n",
" ax.fill_between(q,demand,supply,where=q<=eq_q, facecolor='black')\n",
" ax.fill_between(q, demand, 30, where=q <=eq_q_ceiling, facecolor='blue')\n",
" ax.fill_between(q, supply, 30, where=q <=eq_q_ceiling, facecolor='orange')\n",
" else:\n",
" print('equilibrium price is below 30, so a price ceiling of 30 has no effect')\n",
" print('equilibrium quantity = ',eq_q)\n",
" print('equilibrium price = ',eq_p)\n",
" plt.plot(demand,label='demand')\n",
" plt.plot(supply,label='supply')\n",
" ax.fill_between(q, demand, eq_p, where=q <=eq_q, facecolor='blue')\n",
" ax.fill_between(q, supply, eq_p, where=q <=eq_q, facecolor='orange')\n",
" else:\n",
" if eq_p<70:\n",
" print('equilibrium quantity without price floor = ',eq_q)\n",
" print('equilibrium price without price floor = ',eq_p)\n",
" print('quantity traded with price floor = ',eq_q_floor)\n",
" print('excess supply = ',es)\n",
" print('blue = consumer surplus')\n",
" print('orange = upper bound on producer surplus')\n",
" print('black = lower bound on deadweight loss')\n",
" print('Note that deadweight loss is likely larger than the triangular area')\n",
" print('due to non-price rationing. The triangular area is the exact deadweight')\n",
" print('loss if, and only if, suppliers with the lowest cost sell the good.')\n",
" plt.plot(demand,label='demand')\n",
" plt.plot(supply,label='supply')\n",
" plt.plot(floor,label='price floor')\n",
" ax.fill_between(q,demand,supply,where=q<=eq_q, facecolor='black')\n",
" ax.fill_between(q, demand, 70, where=q <=eq_q_floor, facecolor='blue')\n",
" ax.fill_between(q, supply, 70, where=q <=eq_q_floor, facecolor='orange')\n",
" else:\n",
" print('equilibrium price is above 70, so a price floor of 70 has no effect')\n",
" print('equilibrium quantity = ',eq_q)\n",
" print('equilibrium price = ',eq_p)\n",
" plt.plot(demand,label='demand')\n",
" plt.plot(supply,label='supply')\n",
" ax.fill_between(q, demand, eq_p, where=q <=eq_q, facecolor='blue')\n",
" ax.fill_between(q, supply, eq_p, where=q <=eq_q, facecolor='orange')\n",
" \n",
" \n",
" \n",
" plt.xlabel('quantity', fontsize=24)\n",
" plt.ylabel('price',fontsize=24)\n",
" \n",
" plt.tick_params(axis='both', labelsize=24)\n",
"\n",
" plt.title('supply and demand', fontsize=24, fontweight='bold')\n",
" plt.show()\n",
" \n",
" \n",
"\n",
"interactive_plot = widgets.interactive(g,\n",
" di=widgets.IntSlider(value=100,min=50,max=150,step=10,description='D Intercept'),\n",
" si=widgets.IntSlider(value=20,min=0,max=100,step=10,description='S Intercept'),\n",
" ds=widgets.FloatSlider(value=-1,min=-4,max=-1,step=.2,description='D Slope'),\n",
" ss=widgets.FloatSlider(value=.4,min=.2,max=4,step=.2,description='S Slope'),\n",
" Case=widgets.RadioButtons(options=['price ceiling at 30','price floor at 70','tax of 10','none of the above'],value='none of the above',description='Choose one:')\n",
" )\n",
"interactive_plot"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
channels:
- defaults
dependencies:
- ipython
- ipywidgets
- matplotlib
- numpy
- scipy
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment