1+ {
2+ "cells" : [
3+ {
4+ "cell_type" : " markdown" ,
5+ "id" : " intro" ,
6+ "metadata" : {},
7+ "source" : [
8+ " # Price Controls\n " ,
9+ " \n " ,
10+ " This tutorial demonstrates how to model and analyze price controls (ceilings and floors) using FreeRide.\n " ,
11+ " \n " ,
12+ " ## Setup\n " ,
13+ " \n " ,
14+ " First, install FreeRide (if running in Colab):"
15+ ]
16+ },
17+ {
18+ "cell_type" : " code" ,
19+ "execution_count" : null ,
20+ "id" : " install" ,
21+ "metadata" : {},
22+ "outputs" : [],
23+ "source" : [
24+ " !pip install freeride"
25+ ]
26+ },
27+ {
28+ "cell_type" : " markdown" ,
29+ "id" : " concept" ,
30+ "metadata" : {},
31+ "source" : [
32+ " ## The Concept\n " ,
33+ " \n " ,
34+ " Price controls are government-imposed constraints on market prices:\n " ,
35+ " \n " ,
36+ " - **Price Ceiling**: A legal maximum price (e.g., rent control)\n " ,
37+ " - **Price Floor**: A legal minimum price (e.g., minimum wage)\n " ,
38+ " \n " ,
39+ " When binding, price controls create market distortions:\n " ,
40+ " - Binding ceilings (below equilibrium) create **shortages**\n " ,
41+ " - Binding floors (above equilibrium) create **surpluses**\n " ,
42+ " - Both generate **deadweight loss** by preventing mutually beneficial trades"
43+ ]
44+ },
45+ {
46+ "cell_type" : " markdown" ,
47+ "id" : " modeling" ,
48+ "metadata" : {},
49+ "source" : [
50+ " ## Modeling with FreeRide\n " ,
51+ " \n " ,
52+ " Let's explore how price controls affect market outcomes:"
53+ ]
54+ },
55+ {
56+ "cell_type" : " code" ,
57+ "execution_count" : null ,
58+ "id" : " free-market" ,
59+ "metadata" : {},
60+ "outputs" : [],
61+ "source" : [
62+ " from freeride.curves import Demand, Supply\n " ,
63+ " from freeride.equilibrium import Market\n " ,
64+ " \n " ,
65+ " # Create a market\n " ,
66+ " demand = Demand.from_formula(\" P = 20 - Q\" )\n " ,
67+ " supply = Supply.from_formula(\" P = 5 + 0.5*Q\" )\n " ,
68+ " \n " ,
69+ " # Find free market equilibrium\n " ,
70+ " free_market = Market(demand, supply)\n " ,
71+ " print(f\" Free Market Equilibrium: P = ${free_market.p:.2f}, Q = {free_market.q:.0f}\" )\n " ,
72+ " print(f\" Total Surplus: ${free_market.total_surplus:.2f}\" )"
73+ ]
74+ },
75+ {
76+ "cell_type" : " markdown" ,
77+ "id" : " ceilings" ,
78+ "metadata" : {},
79+ "source" : [
80+ " ## Price Ceilings\n " ,
81+ " \n " ,
82+ " A binding price ceiling creates a shortage because quantity demanded exceeds quantity supplied:"
83+ ]
84+ },
85+ {
86+ "cell_type" : " code" ,
87+ "execution_count" : null ,
88+ "id" : " ceiling-analysis" ,
89+ "metadata" : {},
90+ "outputs" : [],
91+ "source" : [
92+ " # Apply a binding price ceiling at $8\n " ,
93+ " ceiling_market = Market(demand, supply, ceiling=8)\n " ,
94+ " \n " ,
95+ " # Calculate shortage\n " ,
96+ " q_demanded = demand.q(8)\n " ,
97+ " q_supplied = supply.q(8)\n " ,
98+ " shortage = q_demanded - q_supplied\n " ,
99+ " \n " ,
100+ " print(f\" With Price Ceiling at $8:\" )\n " ,
101+ " print(f\" Quantity Supplied: {q_supplied:.0f}\" )\n " ,
102+ " print(f\" Quantity Demanded: {q_demanded:.0f}\" )\n " ,
103+ " print(f\" Shortage: {shortage:.0f} units\" )\n " ,
104+ " print(f\" Deadweight Loss: ${ceiling_market.dwl:.2f}\" )"
105+ ]
106+ },
107+ {
108+ "cell_type" : " code" ,
109+ "execution_count" : null ,
110+ "id" : " ceiling-plot" ,
111+ "metadata" : {},
112+ "outputs" : [],
113+ "source" : [
114+ " # Visualize the market with ceiling\n " ,
115+ " ceiling_market.plot(surplus=True)"
116+ ]
117+ },
118+ {
119+ "cell_type" : " markdown" ,
120+ "id" : " floors" ,
121+ "metadata" : {},
122+ "source" : [
123+ " ## Price Floors\n " ,
124+ " \n " ,
125+ " A binding price floor creates a surplus because quantity supplied exceeds quantity demanded:"
126+ ]
127+ },
128+ {
129+ "cell_type" : " code" ,
130+ "execution_count" : null ,
131+ "id" : " floor-analysis" ,
132+ "metadata" : {},
133+ "outputs" : [],
134+ "source" : [
135+ " # Apply a binding price floor at $12\n " ,
136+ " floor_market = Market(demand, supply, floor=12)\n " ,
137+ " \n " ,
138+ " # Calculate surplus\n " ,
139+ " q_demanded = demand.q(12)\n " ,
140+ " q_supplied = supply.q(12)\n " ,
141+ " surplus = q_supplied - q_demanded\n " ,
142+ " \n " ,
143+ " print(f\" With Price Floor at $12:\" )\n " ,
144+ " print(f\" Quantity Demanded: {q_demanded:.0f}\" )\n " ,
145+ " print(f\" Quantity Supplied: {q_supplied:.0f}\" )\n " ,
146+ " print(f\" Surplus: {surplus:.0f} units\" )\n " ,
147+ " print(f\" Deadweight Loss: ${floor_market.dwl:.2f}\" )"
148+ ]
149+ },
150+ {
151+ "cell_type" : " code" ,
152+ "execution_count" : null ,
153+ "id" : " floor-plot" ,
154+ "metadata" : {},
155+ "outputs" : [],
156+ "source" : [
157+ " # Visualize the market with floor\n " ,
158+ " floor_market.plot(surplus=True)"
159+ ]
160+ },
161+ {
162+ "cell_type" : " markdown" ,
163+ "id" : " non-binding" ,
164+ "metadata" : {},
165+ "source" : [
166+ " ## Non-Binding Controls\n " ,
167+ " \n " ,
168+ " Price controls only affect the market when they're binding:"
169+ ]
170+ },
171+ {
172+ "cell_type" : " code" ,
173+ "execution_count" : null ,
174+ "id" : " non-binding-analysis" ,
175+ "metadata" : {},
176+ "outputs" : [],
177+ "source" : [
178+ " # Non-binding ceiling (above equilibrium)\n " ,
179+ " high_ceiling = Market(demand, supply, ceiling=15)\n " ,
180+ " print(f\" Non-binding ceiling at $15: P = ${high_ceiling.p:.2f}, Q = {high_ceiling.q:.0f}\" )\n " ,
181+ " \n " ,
182+ " # Non-binding floor (below equilibrium)\n " ,
183+ " low_floor = Market(demand, supply, floor=7)\n " ,
184+ " print(f\" Non-binding floor at $7: P = ${low_floor.p:.2f}, Q = {low_floor.q:.0f}\" )\n " ,
185+ " \n " ,
186+ " # Both should equal free market equilibrium\n " ,
187+ " print(f\" Free market: P = ${free_market.p:.2f}, Q = {free_market.q:.0f}\" )"
188+ ]
189+ }
190+ ],
191+ "metadata" : {
192+ "kernelspec" : {
193+ "display_name" : " Python 3" ,
194+ "language" : " python" ,
195+ "name" : " python3"
196+ },
197+ "language_info" : {
198+ "codemirror_mode" : {
199+ "name" : " ipython" ,
200+ "version" : 3
201+ },
202+ "file_extension" : " .py" ,
203+ "mimetype" : " text/x-python" ,
204+ "name" : " python" ,
205+ "nbconvert_exporter" : " python" ,
206+ "pygments_lexer" : " ipython3" ,
207+ "version" : " 3.8.0"
208+ }
209+ },
210+ "nbformat" : 4 ,
211+ "nbformat_minor" : 5
212+ }
0 commit comments