Last active
August 18, 2020 03:14
-
-
Save williampolley/77fbe4f5c066e475eb8dd5b3ee16794d to your computer and use it in GitHub Desktop.
efficiency
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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