my-markdown-library 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/F24LS_md/ Lecture 4 - Public.md +347 -0
- data/F24LS_md/Lecture 1 - Introduction and Overview.md +327 -0
- data/F24LS_md/Lecture 10 - Development_.md +631 -0
- data/F24LS_md/Lecture 11 - Econometrics.md +345 -0
- data/F24LS_md/Lecture 12 - Finance.md +692 -0
- data/F24LS_md/Lecture 13 - Environmental Economics.md +299 -0
- data/F24LS_md/Lecture 15 - Conclusion.md +272 -0
- data/F24LS_md/Lecture 2 - Demand.md +349 -0
- data/F24LS_md/Lecture 3 - Supply.md +329 -0
- data/F24LS_md/Lecture 5 - Production C-D.md +291 -0
- data/F24LS_md/Lecture 6 - Utility and Latex.md +440 -0
- data/F24LS_md/Lecture 7 - Inequality.md +607 -0
- data/F24LS_md/Lecture 8 - Macroeconomics.md +704 -0
- data/F24LS_md/Lecture 8 - Macro.md +700 -0
- data/F24LS_md/Lecture 9 - Game Theory_.md +436 -0
- data/F24LS_md/summary.yaml +105 -0
- data/F24Lec_MD/LecNB_summary.yaml +206 -0
- data/F24Lec_MD/lec01/lec01.md +267 -0
- data/F24Lec_MD/lec02/Avocados_demand.md +425 -0
- data/F24Lec_MD/lec02/Demand_Steps_24.md +126 -0
- data/F24Lec_MD/lec02/PriceElasticity.md +83 -0
- data/F24Lec_MD/lec02/ScannerData_Beer.md +171 -0
- data/F24Lec_MD/lec02/demand-curve-Fa24.md +213 -0
- data/F24Lec_MD/lec03/3.0-CubicCostCurve.md +239 -0
- data/F24Lec_MD/lec03/3.1-Supply.md +274 -0
- data/F24Lec_MD/lec03/3.2-sympy.md +332 -0
- data/F24Lec_MD/lec03/3.3a-california-energy.md +120 -0
- data/F24Lec_MD/lec03/3.3b-a-really-hot-tuesday.md +121 -0
- data/F24Lec_MD/lec04/lec04-CSfromSurvey-closed.md +335 -0
- data/F24Lec_MD/lec04/lec04-CSfromSurvey.md +331 -0
- data/F24Lec_MD/lec04/lec04-Supply-Demand-closed.md +519 -0
- data/F24Lec_MD/lec04/lec04-Supply-Demand.md +514 -0
- data/F24Lec_MD/lec04/lec04-four-plot-24.md +34 -0
- data/F24Lec_MD/lec04/lec04-four-plot.md +34 -0
- data/F24Lec_MD/lec05/Lec5-Cobb-Douglas.md +131 -0
- data/F24Lec_MD/lec05/Lec5-CobbD-AER1928.md +283 -0
- data/F24Lec_MD/lec06/6.1-Sympy-Differentiation.md +253 -0
- data/F24Lec_MD/lec06/6.2-3D-utility.md +287 -0
- data/F24Lec_MD/lec06/6.3-QuantEcon-Optimization.md +399 -0
- data/F24Lec_MD/lec06/6.4-latex.md +138 -0
- data/F24Lec_MD/lec06/6.5-Edgeworth.md +269 -0
- data/F24Lec_MD/lec07/7.1-inequality.md +283 -0
- data/F24Lec_MD/lec07/7.2-historical-inequality.md +237 -0
- data/F24Lec_MD/lec08/macro-fred-api.md +313 -0
- data/F24Lec_MD/lec09/lecNB-prisoners-dilemma.md +88 -0
- data/F24Lec_MD/lec10/Lec10.2-waterguard.md +401 -0
- data/F24Lec_MD/lec10/lec10.1-mapping.md +199 -0
- data/F24Lec_MD/lec11/11.1-slr.md +305 -0
- data/F24Lec_MD/lec11/11.2-mlr.md +171 -0
- data/F24Lec_MD/lec12/Lec12-4-PersonalFinance.md +590 -0
- data/F24Lec_MD/lec12/lec12-1_Interest_Payments.md +267 -0
- data/F24Lec_MD/lec12/lec12-2-stocks-options.md +235 -0
- data/F24Lec_MD/lec13/Co2_ClimateChange.md +139 -0
- data/F24Lec_MD/lec13/ConstructingMAC.md +213 -0
- data/F24Lec_MD/lec13/EmissionsTracker.md +170 -0
- data/F24Lec_MD/lec13/KuznetsHypothesis.md +219 -0
- data/F24Lec_MD/lec13/RoslingPlots.md +217 -0
- data/F24Lec_MD/lec15/vibecession.md +485 -0
- data/F24Textbook_MD/00-intro/index.md +292 -0
- data/F24Textbook_MD/01-demand/01-demand.md +152 -0
- data/F24Textbook_MD/01-demand/02-example.md +131 -0
- data/F24Textbook_MD/01-demand/03-log-log.md +284 -0
- data/F24Textbook_MD/01-demand/04-elasticity.md +248 -0
- data/F24Textbook_MD/01-demand/index.md +15 -0
- data/F24Textbook_MD/02-supply/01-supply.md +203 -0
- data/F24Textbook_MD/02-supply/02-eep147-example.md +86 -0
- data/F24Textbook_MD/02-supply/03-sympy.md +138 -0
- data/F24Textbook_MD/02-supply/04-market-equilibria.md +204 -0
- data/F24Textbook_MD/02-supply/index.md +16 -0
- data/F24Textbook_MD/03-public/govt-intervention.md +73 -0
- data/F24Textbook_MD/03-public/index.md +10 -0
- data/F24Textbook_MD/03-public/surplus.md +351 -0
- data/F24Textbook_MD/03-public/taxes-subsidies.md +282 -0
- data/F24Textbook_MD/04-production/index.md +15 -0
- data/F24Textbook_MD/04-production/production.md +178 -0
- data/F24Textbook_MD/04-production/shifts.md +296 -0
- data/F24Textbook_MD/05-utility/budget-constraints.md +166 -0
- data/F24Textbook_MD/05-utility/index.md +15 -0
- data/F24Textbook_MD/05-utility/utility.md +136 -0
- data/F24Textbook_MD/06-inequality/historical-inequality.md +253 -0
- data/F24Textbook_MD/06-inequality/index.md +15 -0
- data/F24Textbook_MD/06-inequality/inequality.md +226 -0
- data/F24Textbook_MD/07-game-theory/bertrand.md +257 -0
- data/F24Textbook_MD/07-game-theory/cournot.md +333 -0
- data/F24Textbook_MD/07-game-theory/equilibria-oligopolies.md +96 -0
- data/F24Textbook_MD/07-game-theory/expected-utility.md +61 -0
- data/F24Textbook_MD/07-game-theory/index.md +19 -0
- data/F24Textbook_MD/07-game-theory/python-classes.md +340 -0
- data/F24Textbook_MD/08-development/index.md +35 -0
- data/F24Textbook_MD/09-macro/CentralBanks.md +101 -0
- data/F24Textbook_MD/09-macro/Indicators.md +77 -0
- data/F24Textbook_MD/09-macro/fiscal_policy.md +36 -0
- data/F24Textbook_MD/09-macro/index.md +14 -0
- data/F24Textbook_MD/09-macro/is_curve.md +76 -0
- data/F24Textbook_MD/09-macro/phillips_curve.md +70 -0
- data/F24Textbook_MD/10-finance/index.md +10 -0
- data/F24Textbook_MD/10-finance/options.md +178 -0
- data/F24Textbook_MD/10-finance/value-interest.md +60 -0
- data/F24Textbook_MD/11-econometrics/index.md +16 -0
- data/F24Textbook_MD/11-econometrics/multivariable.md +218 -0
- data/F24Textbook_MD/11-econometrics/reading-econ-papers.md +25 -0
- data/F24Textbook_MD/11-econometrics/single-variable.md +483 -0
- data/F24Textbook_MD/11-econometrics/statsmodels.md +58 -0
- data/F24Textbook_MD/12-environmental/KuznetsHypothesis-Copy1.md +187 -0
- data/F24Textbook_MD/12-environmental/KuznetsHypothesis.md +187 -0
- data/F24Textbook_MD/12-environmental/MAC.md +254 -0
- data/F24Textbook_MD/12-environmental/index.md +36 -0
- data/F24Textbook_MD/LICENSE.md +11 -0
- data/F24Textbook_MD/intro.md +26 -0
- data/F24Textbook_MD/references.md +25 -0
- data/F24Textbook_MD/summary.yaml +414 -0
- metadata +155 -0
@@ -0,0 +1,274 @@
|
|
1
|
+
---
|
2
|
+
title: "3.1-Supply"
|
3
|
+
type: lecture-notebook
|
4
|
+
week: 3
|
5
|
+
source_path: "/Users/ericvandusen/Documents/Data88E-ForTraining/F24Lec_NBs/lec03/3.1-Supply.ipynb"
|
6
|
+
---
|
7
|
+
|
8
|
+
<table style="width: 100%;" id="nb-header">
|
9
|
+
<tr style="background-color: transparent;"><td>
|
10
|
+
<img src="https://data-88e.github.io/assets/images/blue_text.png" width="250px" style="margin-left: 0;" />
|
11
|
+
</td><td>
|
12
|
+
<p style="text-align: right; font-size: 10pt;"><strong>Economic Models</strong>, Fall 24<br>
|
13
|
+
Dr. Eric Van Dusen <br>
|
14
|
+
Shashank Dalmia <br>
|
15
|
+
Ergun Acikoz <br>
|
16
|
+
Akhil Venkatesh
|
17
|
+
</p></td></tr>
|
18
|
+
</table>
|
19
|
+
|
20
|
+
# Lecture Notebook 3.1: Supply Curves
|
21
|
+
|
22
|
+
```python
|
23
|
+
try:
|
24
|
+
from csaps import csaps
|
25
|
+
except:
|
26
|
+
!pip install csaps
|
27
|
+
from csaps import csaps
|
28
|
+
```
|
29
|
+
|
30
|
+
```python
|
31
|
+
from datascience import *
|
32
|
+
import matplotlib.pyplot as plt
|
33
|
+
%matplotlib inline
|
34
|
+
import numpy as np
|
35
|
+
import pandas as pd
|
36
|
+
from utils import *
|
37
|
+
import sympy
|
38
|
+
```
|
39
|
+
|
40
|
+
```python
|
41
|
+
from __future__ import print_function
|
42
|
+
from ipywidgets import interact, interactive, fixed, interact_manual
|
43
|
+
import ipywidgets as widgets
|
44
|
+
from matplotlib import patches
|
45
|
+
import warnings
|
46
|
+
warnings.filterwarnings("ignore")
|
47
|
+
```
|
48
|
+
|
49
|
+
## The Supply Curve
|
50
|
+
|
51
|
+
The supply of a commodity refers to the quantity for which producers or sellers are willing produce and offer for sale, at a particular price in some given period of time.
|
52
|
+
|
53
|
+
To answer questions like *"at a given price, what will be the supply of a good in the market?"*, we need to know the market supply curve. A supply curve is simply a curve (or graph) which shows the quantites of a good that can be produced and the prices they will be sold at.
|
54
|
+
|
55
|
+
It is good to discern between individual and market supply. **Individual supply** refers to the supply offered by a single firm or producer, while **market supply** refers to the supply offered by all the firms or producers in a market. It is the horizontal summation of the individual supply curves in the market.
|
56
|
+
|
57
|
+
The following table and graph will give an example of a market with two firm: A and B.
|
58
|
+
|
59
|
+
```python
|
60
|
+
market_supply = Table().with_columns("Price", make_array(2, 3, 4),
|
61
|
+
"Quantity supplied by A", make_array(20, 30, 40),
|
62
|
+
"Quantity supplied by B", make_array(30, 40, 50),
|
63
|
+
"Market Supply", make_array(50, 70, 90))
|
64
|
+
market_supply
|
65
|
+
```
|
66
|
+
|
67
|
+
```python
|
68
|
+
plt.plot(market_supply.column(1), market_supply.column(0), marker='o')
|
69
|
+
plt.plot(market_supply.column(2), market_supply.column(0), marker='o')
|
70
|
+
plt.plot(market_supply.column(3), market_supply.column(0), marker='o')
|
71
|
+
plt.xlabel('Quantity')
|
72
|
+
plt.ylabel('Price')
|
73
|
+
plt.title('Market Supply')
|
74
|
+
plt.legend(make_array("Quantity supplied by A","Quantity supplied by B","Market Supply"), bbox_to_anchor=(1.04,1), loc="center left")
|
75
|
+
|
76
|
+
plt.show()
|
77
|
+
```
|
78
|
+
|
79
|
+
Market behaviour relating to supply is based on the behaviour of the individual firms that comprise it. Now, how does an individual firm make its decision about production?
|
80
|
+
|
81
|
+
It does so based on the costs associated with production. If the price of a good is enough to recover the costs, the firm produces. Generally, costs increase with the quantity of production. So, to induce producers to increase the quantity supplied, the prices need to increase to compensate for the increased costs.
|
82
|
+
|
83
|
+
## Costs and Firm Behavior
|
84
|
+
|
85
|
+
We will split costs into two categories: **Fixed costs** and **Variable costs**.
|
86
|
+
|
87
|
+
Fixed Costs are costs associated with fixed factors (or inputs) of production. For example, land for a factory, capital equipment like machinery, etc. The quantity of these inputs cannot be changed quickly in the short term. A factory owner cannot purchase land quickly enough to ramp up production in a week. A key point to note is that fixed costs are irrespective of the quantity, i.e., they do not change with the quantity produced.
|
88
|
+
|
89
|
+
Variable Costs are costs associated with variable factors (or inputs) of production. For example, labor, raw materials, etc. The quantity of these inputs can be changed quickly in the short term to adjust supply. A factory owner can hire more laborers or purchase more raw material to increase output. Variable costs change as the supply changes.
|
90
|
+
|
91
|
+
We will create a table with the following firm costs:
|
92
|
+
|
93
|
+
* **Output:** Units produced and supplied
|
94
|
+
* **Total Fixed Cost (TFC):** Cost incurred by firm on usage of all fixed factors.
|
95
|
+
* **Total Variable Cost (TVC):** Cost incurred by firm on usage of all variable factors.
|
96
|
+
* **Total Cost (TC):** Sum of the total fixed and variable costs
|
97
|
+
* **Marginal Cost (MC):** Addition to total cost as one more unit of output is produced
|
98
|
+
* **Average Fixed Cost (AFC):** Cost per unit of fixed factors
|
99
|
+
* **Average Variable Cost (AVC):** Cost per unit of variable factors
|
100
|
+
* **Average Total Cost (ATC):** Total cost per unit
|
101
|
+
|
102
|
+
```python
|
103
|
+
individual_firm_costs = Table.read_table('individual_firm_costs.csv')
|
104
|
+
individual_firm_costs.show()
|
105
|
+
```
|
106
|
+
|
107
|
+
First, let's calculate `total_cost`, which is the sum of total fixed cost and total variable cost.
|
108
|
+
|
109
|
+
```python
|
110
|
+
total_cost = individual_firm_costs.column("Total Fixed Cost") + individual_firm_costs.column("Total Variable Cost")
|
111
|
+
total_cost
|
112
|
+
```
|
113
|
+
|
114
|
+
We will now add the total costs array to the table.
|
115
|
+
|
116
|
+
```python
|
117
|
+
individual_firm_costs = individual_firm_costs.with_column("Total Cost", total_cost)
|
118
|
+
individual_firm_costs
|
119
|
+
```
|
120
|
+
|
121
|
+
Average Fixed Cost can be calculated as the Total Fixed Costs divided by the output.
|
122
|
+
|
123
|
+
At zero level of output, we would by dividing by zero, which is invalid.
|
124
|
+
So we have to manually fix that
|
125
|
+
|
126
|
+
```python
|
127
|
+
|
128
|
+
average_fixed_cost = individual_firm_costs.column("Total Fixed Cost") / individual_firm_costs.column("Output")
|
129
|
+
average_fixed_cost[0] = 0
|
130
|
+
average_fixed_cost
|
131
|
+
```
|
132
|
+
|
133
|
+
Now we will add the AFC column back into the table.
|
134
|
+
|
135
|
+
```python
|
136
|
+
individual_firm_costs = individual_firm_costs.with_column("Average Fixed Cost", average_fixed_cost)
|
137
|
+
individual_firm_costs
|
138
|
+
```
|
139
|
+
|
140
|
+
Similarly, Average Variable Cost can be calculated as the Total Variable Cost divided by the output.
|
141
|
+
|
142
|
+
```python
|
143
|
+
average_variable_cost = individual_firm_costs.column("Total Variable Cost")/individual_firm_costs.column("Output")
|
144
|
+
average_variable_cost[0] = 0
|
145
|
+
average_variable_cost
|
146
|
+
```
|
147
|
+
|
148
|
+
Now we will add the AVC column to the table.
|
149
|
+
|
150
|
+
```python
|
151
|
+
individual_firm_costs = individual_firm_costs.with_column("Average Variable Cost", average_variable_cost)
|
152
|
+
individual_firm_costs
|
153
|
+
```
|
154
|
+
|
155
|
+
Similarly, Average Total Cost can be calculated as the Total Cost divided by the output.
|
156
|
+
|
157
|
+
```python
|
158
|
+
average_total_cost = individual_firm_costs.column("Total Cost")/individual_firm_costs.column("Output")
|
159
|
+
average_total_cost[0] = 0
|
160
|
+
average_total_cost
|
161
|
+
```
|
162
|
+
|
163
|
+
```python
|
164
|
+
individual_firm_costs = individual_firm_costs.with_column("Average Total Cost", average_total_cost)
|
165
|
+
individual_firm_costs
|
166
|
+
```
|
167
|
+
|
168
|
+
Marginal Cost can be calculated as the difference between Total Cost at the current output level and Total Cost at the previous output level (or TVC, as TFC is fixed).
|
169
|
+
|
170
|
+
For this we are going to use the function `np.diff`. You can read about it on http://data8.org/fa22/reference/#array-functions-and-methods
|
171
|
+
|
172
|
+
```python
|
173
|
+
marginal_cost = np.diff(total_cost)
|
174
|
+
marginal_cost = np.append(make_array(0), marginal_cost)
|
175
|
+
marginal_cost
|
176
|
+
```
|
177
|
+
|
178
|
+
Once again, we add the MC column back to the table.
|
179
|
+
|
180
|
+
```python
|
181
|
+
individual_firm_costs = individual_firm_costs.with_column("Marginal Cost", marginal_cost)
|
182
|
+
individual_firm_costs
|
183
|
+
```
|
184
|
+
|
185
|
+
Let's look at some plots!
|
186
|
+
|
187
|
+
```python
|
188
|
+
plt.plot(individual_firm_costs.column("Output"), individual_firm_costs.column("Total Fixed Cost"), marker='o')
|
189
|
+
plt.plot(individual_firm_costs.column("Output"), individual_firm_costs.column("Total Variable Cost"), marker='o')
|
190
|
+
plt.plot(individual_firm_costs.column("Output"), individual_firm_costs.column("Total Cost"), marker='o')
|
191
|
+
plt.xlabel('Quantity')
|
192
|
+
plt.ylabel('Cost')
|
193
|
+
plt.title('TFC, TVC and TC')
|
194
|
+
plt.legend(make_array("Total Fixed Cost","Total Variable Cost","Total Cost"))
|
195
|
+
|
196
|
+
plt.show()
|
197
|
+
```
|
198
|
+
|
199
|
+
What have we observed?
|
200
|
+
|
201
|
+
1. TFC is flat
|
202
|
+
2. Vertical difference between TVC and TC is TFC, which is constant
|
203
|
+
|
204
|
+
```python
|
205
|
+
plt.plot(individual_firm_costs.column("Output")[1:], individual_firm_costs.column("Average Fixed Cost")[1:], marker='o')
|
206
|
+
plt.plot(individual_firm_costs.column("Output")[1:], individual_firm_costs.column("Average Variable Cost")[1:], marker='o')
|
207
|
+
plt.plot(individual_firm_costs.column("Output")[1:], individual_firm_costs.column("Average Total Cost")[1:], marker='o')
|
208
|
+
plt.xlabel('Quantity')
|
209
|
+
plt.ylabel('Cost')
|
210
|
+
plt.title('AFC, AVC and ATC')
|
211
|
+
plt.legend(make_array("Average Fixed Cost","Average Variable Cost","Average Total Cost"))
|
212
|
+
|
213
|
+
plt.show()
|
214
|
+
```
|
215
|
+
|
216
|
+
```python
|
217
|
+
# You do not need to understand what the code below is doing.
|
218
|
+
output = individual_firm_costs.column("Output")[1:]
|
219
|
+
mc = individual_firm_costs.column("Marginal Cost")[1:]
|
220
|
+
avc = individual_firm_costs.column("Average Variable Cost")[1:]
|
221
|
+
atc = individual_firm_costs.column("Average Total Cost")[1:]
|
222
|
+
|
223
|
+
sp_mc = csaps(output, mc, smooth=0.85)
|
224
|
+
sp_avc = csaps(output, avc, smooth=0.85)
|
225
|
+
sp_atc = csaps(output, atc, smooth=0.85)
|
226
|
+
|
227
|
+
output_s = np.linspace(output.min(), output.max(), 150)
|
228
|
+
mc_s = sp_mc(output_s)
|
229
|
+
avc_s = sp_avc(output_s)
|
230
|
+
atc_s = sp_atc(output_s)
|
231
|
+
|
232
|
+
plt.plot(output, mc, marker = 'o', color = 'tab:blue')
|
233
|
+
plt.plot(output_s, mc_s, alpha=0.7, lw = 2, label='_nolegend_', color = 'tab:blue')
|
234
|
+
plt.plot(output, avc, marker = 'o', color = 'tab:green')
|
235
|
+
plt.plot(output_s, avc_s, alpha=0.7, lw = 2, label='_nolegend_', color = 'tab:green')
|
236
|
+
plt.plot(output, atc, marker = 'o', color = 'tab:orange')
|
237
|
+
plt.plot(output_s, atc_s, alpha=0.7, lw = 2, label='_nolegend_', color = 'tab:orange')
|
238
|
+
plt.hlines(y=min(avc), xmin = 6, xmax = 8, lw=3, color='r', zorder = 10)
|
239
|
+
plt.hlines(y=min(atc), xmin = 7.5, xmax = 9.5, lw=3, color='r', zorder = 10)
|
240
|
+
plt.xlabel('Quantity')
|
241
|
+
plt.ylabel('Cost')
|
242
|
+
plt.title('MC, AVC and ATC')
|
243
|
+
plt.legend(make_array("Marginal Cost","Average Variable Cost","Average Total Cost"))
|
244
|
+
|
245
|
+
plt.show()
|
246
|
+
```
|
247
|
+
|
248
|
+
Notice something important: _A company decides to produce if it the price is greater than or equal to its Average Variable Cost._
|
249
|
+
|
250
|
+
There are 3 different scenarios:
|
251
|
+
1. A firm chooses to not produce at all
|
252
|
+
2. A firm chooses to produce at a loss (minimizing quantity)
|
253
|
+
3. A firm chooses to produce at a profit.
|
254
|
+
|
255
|
+
Play around with the slider to see them.
|
256
|
+
|
257
|
+
```python
|
258
|
+
interact(lambda price: firm_behaviour(price, individual_firm_costs), price=widgets.IntSlider(min=20,max=60,step=1,value=25));
|
259
|
+
```
|
260
|
+
|
261
|
+
In the above example if the price is 24 for any amount of production, the firm will lose money. In this case, they shut down and the loss is limited to its fixed costs.
|
262
|
+
|
263
|
+
If the price is above the minimum of the AVC (25 in the example), for some amount of production, the firm will maximise its profits (i.e. minimise its losses). Profits are Total Revenue minus Total Costs, where Total Revenue is Price times Quantity.
|
264
|
+
|
265
|
+
Therefore, based on the price, each firm looks at its costs and makes a decision on whether to produce. At low prices, only the firms with the lowest production costs produce. As the price increases, firms with higher production costs find it feasible to produce and begin to supply. Thus, the market supply rises with higher prices. Firms with lower costs make extra profits.
|
266
|
+
|
267
|
+
```python
|
268
|
+
|
269
|
+
```
|
270
|
+
|
271
|
+
```python
|
272
|
+
|
273
|
+
```
|
274
|
+
|
@@ -0,0 +1,332 @@
|
|
1
|
+
---
|
2
|
+
title: "3.2-sympy"
|
3
|
+
type: lecture-notebook
|
4
|
+
week: 3
|
5
|
+
source_path: "/Users/ericvandusen/Documents/Data88E-ForTraining/F24Lec_NBs/lec03/3.2-sympy.ipynb"
|
6
|
+
---
|
7
|
+
|
8
|
+
<table style="width: 100%;" id="nb-header">
|
9
|
+
<tr style="background-color: transparent;"><td>
|
10
|
+
<img src="https://data-88e.github.io/assets/images/blue_text.png" width="250px" style="margin-left: 0;" />
|
11
|
+
</td><td>
|
12
|
+
<p style="text-align: right; font-size: 10pt;"><strong>Economic Models</strong>, Fall 24<br>
|
13
|
+
Dr. Eric Van Dusen <br>
|
14
|
+
<br>
|
15
|
+
</table>
|
16
|
+
|
17
|
+
# Lecture Notebook 3.2: SymPy & Market Equilibrium
|
18
|
+
|
19
|
+
# SymPy - Symbolic Python
|
20
|
+
|
21
|
+
```python
|
22
|
+
from datascience import *
|
23
|
+
import numpy as np
|
24
|
+
from sympy import *
|
25
|
+
from sympy import solve
|
26
|
+
import sympy
|
27
|
+
init_printing()
|
28
|
+
import matplotlib.pyplot as plt
|
29
|
+
import matplotlib as mpl
|
30
|
+
import matplotlib.patches as patches
|
31
|
+
%matplotlib inline
|
32
|
+
solve = lambda x,y: sympy.solve(x-y)[0] if len(sympy.solve(x-y))==1 else "Not Single Solution"
|
33
|
+
mpl.rcParams['figure.dpi'] = 150
|
34
|
+
import warnings
|
35
|
+
warnings.filterwarnings('ignore')
|
36
|
+
```
|
37
|
+
|
38
|
+
Python has many tools, such as the [SymPy library](https://docs.sympy.org/latest/tutorial/index.html) that we can use for expressing and evaluating formulas and functions in economics.
|
39
|
+
|
40
|
+
Since SymPy helps with symbolic math, we start out by create a symbol using `Symbol`, which we assign to a variable name. Then, we can use the symbols to construct symbolic expressions.
|
41
|
+
|
42
|
+
```python
|
43
|
+
x = Symbol('x');
|
44
|
+
x
|
45
|
+
```
|
46
|
+
|
47
|
+
**Example 1**: Now let's try using SymPy to create a symbolic expression for 2 equations. Let's create the equation for the first curve. It will be called $y$ and will be in terms of `x`
|
48
|
+
|
49
|
+
```python
|
50
|
+
y = 2 * x - 3
|
51
|
+
y
|
52
|
+
```
|
53
|
+
|
54
|
+
Similarly, we will also use `x` to express a relationship with $y_1$
|
55
|
+
|
56
|
+
```python
|
57
|
+
y_1 = 2 - x
|
58
|
+
y_1
|
59
|
+
```
|
60
|
+
|
61
|
+
We want to see the value of `x` at which $y = y_1$. To solve this by hand, we would set up the following equation to solve for $Q$:
|
62
|
+
|
63
|
+
$$
|
64
|
+
P_D = P_S\\
|
65
|
+
2-Q = 2Q-3
|
66
|
+
$$
|
67
|
+
|
68
|
+
Before we try solving this with SymPy, let's solve this by hand.
|
69
|
+
|
70
|
+
$$ y = y_1 $$
|
71
|
+
$$ 2x - 3 = 2 - x $$
|
72
|
+
$$ 3x = 5 $$
|
73
|
+
$$ x = \frac{5}{3} $$
|
74
|
+
|
75
|
+
We can confirm our `Q` value is true by plugging it back into the original equation.
|
76
|
+
|
77
|
+
$$ y = 2x - 3 $$
|
78
|
+
$$ y = 2 \times \frac{5}{3} - 3 $$
|
79
|
+
$$ y = \frac{1}{3} $$
|
80
|
+
|
81
|
+
$$ y_1 = 2 - x $$
|
82
|
+
$$ y_1 = 2 - (-\frac{5}{3}) $$
|
83
|
+
$$ y_1 = \frac{1}{3} $$
|
84
|
+
|
85
|
+
Using SymPy, we call `solve`, which takes in 2 arguments that represent the 2 sides of an equation and solves for the underlying variable such that the equation holds. Here, we pass in $P_D$ and $P_S$, both represented in terms of $Q$, to solve for the value of $Q$ such that $P_D=P_S$. It's good to know that `solve` is a custom function built for this class, and will be provided in the notebooks for you.
|
86
|
+
|
87
|
+
```python
|
88
|
+
x_star = solve(y, y_1)
|
89
|
+
x_star
|
90
|
+
```
|
91
|
+
|
92
|
+
The value of $x$ that equates $y$ and $y_1$ is known as the optimal x value, and we denote it as $x^*$. Here, $x^* = \frac{5}{3}$.
|
93
|
+
|
94
|
+
With $x^*$ determined, we can substitute this value as $x$ to thus calculate $y$ or $y_1$. We substitute values using the `subs` function, which follows the syntax `expression.subs(symbol_we_want_to_substitute, value_to_substitute_with)`. This let's us see if our answer was correct.
|
95
|
+
|
96
|
+
```python
|
97
|
+
y.subs(x, x_star)
|
98
|
+
```
|
99
|
+
|
100
|
+
We can also substitute $x^*$ into $y_1$, and should get the same results.
|
101
|
+
|
102
|
+
```python
|
103
|
+
y_1.subs(x, x_star)
|
104
|
+
```
|
105
|
+
|
106
|
+
Thus, the equilibrium `x` and `y` values are $\frac{5}{3}$ and 0.33, respectively.
|
107
|
+
|
108
|
+
**Example 2** We will now put this in the context of suppply and demand. We can represent both as non-log functions.
|
109
|
+
|
110
|
+
To define an upward sloping supply curve with price expressed as a function of quantity, let's define `Q` first.
|
111
|
+
|
112
|
+
```python
|
113
|
+
Q = Symbol('Q')
|
114
|
+
Q
|
115
|
+
```
|
116
|
+
|
117
|
+
Suppose our demand function is $\text{P}_{D}=-2 \cdot \text{Q} + 10$. $P_D$ is the price of the good purchased (how much the consumer pays). Using SymPy, this would be
|
118
|
+
|
119
|
+
```python
|
120
|
+
P_D = -2 * Q + 10
|
121
|
+
P_D
|
122
|
+
```
|
123
|
+
|
124
|
+
The supply function is $\text{P}_{S}=3 \cdot \text{Q} + 1$. which denotes the price of the supplied good (how much the producer earns), in terms of $Q$.Using SymPy, this would be
|
125
|
+
|
126
|
+
```python
|
127
|
+
P_S = 3 * Q + 1
|
128
|
+
P_S
|
129
|
+
```
|
130
|
+
|
131
|
+
We will now try to find the market equilibrium. The market price equilibrium $P^*$ is the price at which the quantity supplied and quantity demanded of a good or service are equal to each other. Similarly, the market quantity equilibrium $Q^*$ is the quantity at which the price paid by consumers is equal to the price received by producers.
|
132
|
+
|
133
|
+
To solve for the equilibrium given the supply and demand curve, we know that the price paid by consumers must equal to the price earned by suppliers. Thus, $P_D = P_S$, allowing us to set the two equations equal to each other and solve for the equilibrium quantity and thus equilibrium price.
|
134
|
+
|
135
|
+
Combined, the price equilibrium and quantity equilibrium form a point on the graph with quantity and price as its axes, called the equilibrium point. This point is the point at which the demand and supply curves intersect.
|
136
|
+
|
137
|
+
Let's take a step back and solve this by hand first.
|
138
|
+
|
139
|
+
$$ P_D = P_S $$
|
140
|
+
$$ -2Q + 10 = 3Q + 1 $$
|
141
|
+
$$ 5Q = 9 $$
|
142
|
+
$$ Q = \frac{9}{5} $$
|
143
|
+
|
144
|
+
Now that we have our optimal Q value, let's plug it in each equation and see if our condition holds true.
|
145
|
+
|
146
|
+
$$ P_D = -2Q + 10 $$
|
147
|
+
$$ P_D = -2 \times \frac{9}{5} + 10 $$
|
148
|
+
$$ P_D = \frac{32}{5} = 6.4 $$
|
149
|
+
|
150
|
+
$$ P_S = 3Q + 1 $$
|
151
|
+
$$ P_S = 3 \times \frac{9}{5} + 1 $$
|
152
|
+
$$ P_S = \frac{32}{5} = 6.4 $$
|
153
|
+
|
154
|
+
Now, let's use SymPy
|
155
|
+
|
156
|
+
First, we solve for the quantity equilibrium.
|
157
|
+
|
158
|
+
```python
|
159
|
+
Q_star = solve(P_D, P_S)
|
160
|
+
Q_star
|
161
|
+
```
|
162
|
+
|
163
|
+
Next, we plug the quantity equilibrium into our demand or supply expression to get the price equilibrium
|
164
|
+
|
165
|
+
```python
|
166
|
+
P_S.subs(Q, Q_star)
|
167
|
+
```
|
168
|
+
|
169
|
+
Graphically, we can plot the supply and demand curves with quantity on the $x$ axis and price on the $y$ axis. The point at which they intersect is the equilibrium point.
|
170
|
+
|
171
|
+
```python
|
172
|
+
def plot_equation(equation, price_start, price_end, label=None):
|
173
|
+
plot_prices = [price_start, price_end]
|
174
|
+
plot_quantities = [equation.subs(list(equation.free_symbols)[0], c) for c in plot_prices]
|
175
|
+
plt.plot(plot_prices, plot_quantities, label=label)
|
176
|
+
|
177
|
+
def plot_intercept(eq1, eq2):
|
178
|
+
ex = sympy.solve(eq1-eq2)[0]
|
179
|
+
why = eq1.subs(list(eq1.free_symbols)[0], ex)
|
180
|
+
plt.scatter([ex], [why])
|
181
|
+
return (ex, why)
|
182
|
+
|
183
|
+
plot_equation(P_D, 0, 5)
|
184
|
+
plot_equation(P_S, 0, 5)
|
185
|
+
plt.ylim(0,20)
|
186
|
+
plt.xlabel("Quantity")
|
187
|
+
plt.ylabel("Price")
|
188
|
+
plt.title("Supply & Demand with SymPy")
|
189
|
+
plot_intercept(P_D, P_S);
|
190
|
+
```
|
191
|
+
|
192
|
+
# Market Equilibrium with Real Data
|
193
|
+
|
194
|
+
We will now explore the relationship between price and quantity of oranges produced between 1924 and 1938. Since the [data](https://data-88e.github.io/textbook/content/references.html#demand-fruits) is from the 1920s and 1930s, it is important to remember that the prices are much lower than what they would be today because of inflation, competition, innovations, and other factors. For example, in 1924, a ton of oranges would have costed $\$6.63$; that same amount in 2019 is \$100.78, holding all factors except for inflation constant.
|
195
|
+
|
196
|
+
Remember, the **market equilibrium** is the price and quantity at which the demand and supply curves intersect. The price and resulting transaction quantity at the equilibrium is what we would predict to observe in the market. This is the point at which the demand and supply curves meet and represents the "optimal" level of production and price in that market.
|
197
|
+
|
198
|
+
```python
|
199
|
+
fruitprice = Table.read_table('fruitprice.csv')
|
200
|
+
fruitprice
|
201
|
+
```
|
202
|
+
|
203
|
+
Let's walk through how to the market equilibrium using the market for oranges as an example.
|
204
|
+
|
205
|
+
### Data Preprocessing
|
206
|
+
|
207
|
+
Because we are only examining the relationship between prices and quantity for oranges, we can create a new table with the relevant columns: `Year`, `Orange Price`, and `Orange Unloads`. Here, `Orange Price` is measured in dollars, while `Orange Unloads` is measured in tons.
|
208
|
+
|
209
|
+
```python
|
210
|
+
oranges_raw = fruitprice.select("Year", "Orange Price", "Orange Unloads")
|
211
|
+
oranges_raw
|
212
|
+
```
|
213
|
+
|
214
|
+
Next, we will rename our columns. In this case, let's rename `Orange Unloads` to `Quantity` and `Orange Price` to `Price` for brevity and understandability.
|
215
|
+
|
216
|
+
```python
|
217
|
+
oranges = oranges_raw.relabel("Orange Unloads", "Quantity").relabel("Orange Price", "Price")
|
218
|
+
oranges
|
219
|
+
```
|
220
|
+
|
221
|
+
### Visualize the Relationship
|
222
|
+
|
223
|
+
Let's first take a look to see what the relationship between price and quantity is. We would expect to see a downward-sloping relationship between price and quantity; if a product's price increases, consumers will purchase less, and if a product's price decreases, then consumers will purchase more.
|
224
|
+
|
225
|
+
We will create a scatterplot between the points.
|
226
|
+
|
227
|
+
```python
|
228
|
+
oranges.scatter("Quantity", "Price", width=3, height=3)
|
229
|
+
plt.title("Demand Curve for Oranges", fontsize = 16);
|
230
|
+
```
|
231
|
+
|
232
|
+
### Fit a Polynomial
|
233
|
+
|
234
|
+
We will now quantify our demand curve using NumPy's [`np.polyfit` function](https://numpy.org/doc/stable/reference/generated/numpy.polyfit.html). Recall that `np.polyfit` returns an array of size 2, where the first element is the slope and the second is the $y$-intercept.
|
235
|
+
|
236
|
+
For this exercise, we will be expressing demand and supply as quantities in terms of price.
|
237
|
+
|
238
|
+
```python
|
239
|
+
orange_parameters = np.polyfit(oranges.column("Price"), oranges.column("Quantity"), 1)
|
240
|
+
print ("The coefficient is", orange_parameters[0])
|
241
|
+
print ("The y-intercept is", orange_parameters[1])
|
242
|
+
```
|
243
|
+
|
244
|
+
This shows that the demand curve is $D(P) = -3433 P+ 53626$. The slope is -3433 and $y$-intercept is 53626. That means that as price increases by 1 unit (in this case, \$1), quantity decreases by 3433 units (in this case, 3433 tons).
|
245
|
+
|
246
|
+
### Create the Demand Curve
|
247
|
+
|
248
|
+
We will now use SymPy to write out this demand curve. To do so, we start by creating a symbol `P` that we can use to create the equation.
|
249
|
+
|
250
|
+
```python
|
251
|
+
P = sympy.Symbol("P")
|
252
|
+
demand = orange_parameters[0] * P + orange_parameters[1]
|
253
|
+
demand
|
254
|
+
```
|
255
|
+
|
256
|
+
### Create the Supply Curve
|
257
|
+
|
258
|
+
As the price of the oranges increases, the quantity of oranges that orange manufacturers are willing to supply increases. They capture the producer's side of market decisions and are upward-sloping.
|
259
|
+
|
260
|
+
Let's now assume that the supply curve is given by $S(P) = 4348P$. (Note that this supply curve is not based on data.)
|
261
|
+
|
262
|
+
```python
|
263
|
+
supply_coefficient = 4348
|
264
|
+
supply = supply_coefficient * P
|
265
|
+
supply
|
266
|
+
```
|
267
|
+
|
268
|
+
This means that as the price of oranges increases by 1, the quantity supplied increases by 4348. At a price of 0, no oranges are supplied.
|
269
|
+
|
270
|
+
### Find the Price Equilibrium
|
271
|
+
The equilbrium consists of 2 components: the quantity equilbrium and price equilbrium.
|
272
|
+
The price equilibrium is the price at which the supply curve and demand curve intersect: the price of the good that consumers desire to purchase at is equivalent to the price of the good that producers want to sell at. There is no shortage of surplus of the product at this price.
|
273
|
+
|
274
|
+
|
275
|
+
Let's find the price equilibrium. To do this, we will use the provided `solve` function. This is a custom function that leverages some SymPy magic and will be provided to you in assignments.
|
276
|
+
|
277
|
+
```python
|
278
|
+
P_star = solve(demand, supply)
|
279
|
+
P_star
|
280
|
+
```
|
281
|
+
|
282
|
+
This means that the price of oranges that consumers want to purchase at and producers want to provide is about \$6.89.
|
283
|
+
|
284
|
+
### Find the Quantity Equilibrium
|
285
|
+
|
286
|
+
Similarly, the quantity equilibrium is the quantity of the good that consumers desire to purchase is equivalent to the quantity of the good that producers supply; there is no shortage or surplus of the good at this quantity.
|
287
|
+
|
288
|
+
```python
|
289
|
+
demand.subs(P, P_star)
|
290
|
+
```
|
291
|
+
|
292
|
+
```python
|
293
|
+
supply.subs(P, P_star)
|
294
|
+
```
|
295
|
+
|
296
|
+
This means that the number of tons of oranges that consumers want to purchase and producers want to provide in this market is about 29,967 tons of oranges.
|
297
|
+
|
298
|
+
### Visualize the Market Equilibrium
|
299
|
+
|
300
|
+
Now that we have our demand and supply curves and price and quantity equilibria, we can visualize them on a graph to see what they look like.
|
301
|
+
|
302
|
+
```python
|
303
|
+
def plot_equation(equation, price_start, price_end, label=None):
|
304
|
+
plot_prices = [price_start, price_end]
|
305
|
+
plot_quantities = [equation.subs(list(equation.free_symbols)[0], c) for c in plot_prices]
|
306
|
+
plt.plot(plot_quantities, plot_prices, label=label)
|
307
|
+
|
308
|
+
def plot_intercept(eq1, eq2):
|
309
|
+
ex = sympy.solve(eq1-eq2)[0]
|
310
|
+
why = eq1.subs(list(eq1.free_symbols)[0], ex)
|
311
|
+
plt.scatter([why], [ex], zorder=10, color="tab:orange")
|
312
|
+
return (ex, why)
|
313
|
+
```
|
314
|
+
|
315
|
+
We can leverage these functions and the equations we made earlier to create a graph that shows the market equilibrium.
|
316
|
+
|
317
|
+
```python
|
318
|
+
plot_equation(demand, 2, 12, label = "Demand")
|
319
|
+
plot_equation(supply, 2, 12, label = "Supply")
|
320
|
+
plt.ylim(0,13)
|
321
|
+
plt.title("Orange Supply and Demand in 1920's and 1930's", fontsize = 15)
|
322
|
+
plt.xlabel("Quantity (Tons)", fontsize = 14)
|
323
|
+
plt.ylabel("Price ($)", fontsize = 14)
|
324
|
+
plot_intercept(supply, demand)
|
325
|
+
plt.legend(loc = "upper right", fontsize = 12)
|
326
|
+
plt.show()
|
327
|
+
```
|
328
|
+
|
329
|
+
You can also practice on your own and download additional data sets [here](http://users.stat.ufl.edu/~winner/datasets.html), courtesy of the University of Flordia's Statistics Department.
|
330
|
+
|
331
|
+
|
332
|
+
|