In [1]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit, minimize
%matplotlib inline
In [2]:
data = pd.read_csv('lab1v1.csv')
P, D, S = data['Price'].values, data['Demand'].values, data['Supply'].values
data
Out[2]:
In [3]:
def plot(*args, x='Quantity', y='Price', **kw):
plt.figure(figsize=(15, 10))
plt.plot(*args)
plt.xlabel(x)
plt.ylabel(y)
plt.legend(kw['legend'])
plt.title(kw['title'])
plt.show()
In [4]:
plot(D, P, 'ro', S, P, 'bo', legend=['Demand', 'Supply'], title='Demand vs Supply')
In [5]:
def compare(x, y, fs, label, title):
plt.figure(figsize=(15, 10))
scores, cs = [], []
for i, f in enumerate(fs):
c, _ = curve_fit(f, x, y)
fy = f(x, *c)
plt.plot(fy, x, '-', label=f.__name__)
scores.append(np.sum(y - fy)**2)
cs.append(c)
plt.plot(y, x, 'o', label=label)
plt.xlabel('Quantity'); plt.ylabel('Price')
plt.legend(); plt.title(title); plt.show()
return fs[np.argmin(scores)], cs[np.argmin(scores)]
We'll try to approximate our demand function with $$Q_d(P) = \frac{a}{bP + c}$$
$$Q_d(P) = \frac{a}{e^{bP} + c}$$
In [6]:
def inverted_linear(x, a, b, c): return a / (b*x + c)
def inverted_exponent(x, a, b, c): return a / (np.exp(b*x) + c)
d_f, d_c = compare(P, D, [inverted_linear, inverted_exponent], label='Demand', title='Demand approximation')
'Demand is better to approximate with {} function'.format(d_f.__name__)
Out[6]:
Now let's approximate our supply function with $$Q_s(P) = e^{aP} + b$$
$$Q_s(P) = a\log{P} + b$$
In [7]:
def exponent(x, a, b): return np.exp(a*x) + b
def logarithmic(x, a, b): return a*np.log(x) + b
s_f, s_c = compare(P, S, [exponent, logarithmic], label='Supply', title='Supply approximation')
'Supply is better to approximate with {} function'.format(s_f.__name__)
Out[7]:
In [8]:
def diff(x): return abs(d_f(x, *d_c) - s_f(x, *s_c))
bounds = (P.min(), P.max())
e_p = minimize(diff, 1, bounds=[bounds]).x[0]
e_q = d_f(e_p, *d_c)
plot(d_f(P, *d_c), P, 'r-', s_f(P, *s_c), P, 'b-', D, P, 'ro', S, P, 'bo', e_q, e_p, 'go',
legend=['Demand(approx)', 'Supply(approx)', 'Demand', 'Supply', 'Equilibrium'], title='Equilibrium')
'Equilibrium is ({0:.2f}, {1:.2f})'.format(e_q, e_p)
Out[8]:
By definition $$E = \frac{dQ}{dP} \cdot \frac{P}{Q}$$
For demand we have $$Q_d = \frac{a}{e^{bP}+c}$$
$$E_d = \frac{dQ_d}{dP} \cdot \frac{P}{Q_d} = -\frac{abe^{bP}}{(e^{bP}+c)^2} \cdot \frac{P(e^{bP}+c)}{a} = -\frac{bPe^{bP}}{e^{bP}+c}$$And for supply $$Q_s = l\log{P}+m$$
$$E_s = \frac{dQ_s}{dP} \cdot \frac{P}{Q_s} = \frac{l}{P} \cdot \frac{P}{l\log{P}+m} = \frac{l}{l\log{P}+m}$$
In [9]:
d_c, s_c
Out[9]:
Provided that $a = 55.4, b = 0.97, c = -0.55, l = 39.02, m = 81.92$ we have
$$E_d = -\frac{0.97 \cdot Pe^{0.97 P}}{e^{0.97 P}-0.55}$$$$E_s = \frac{39.02}{39.02\log{P}+81.92}$$Let's calculate elasticity at the equilibrium
In [10]:
def elasticity_d(p): return -d_c[1]*p*np.exp(d_c[1]*p) / (np.exp(d_c[1]*p) - d_c[2])
def elasticity_s(p): return s_c[0] / (s_c[0]*np.log(p) + s_c[1])
print('Demand elasticity: {0:.2f}'.format(elasticity_d(e_p)))
print('Supply elasticity: {0:.2f}'.format(elasticity_s(e_p)))
Because $|E_d(e_p)| < |E_s(e_p)|$ we can say that equilibrium is not stable.
In [11]:
def arc_elasticity(P, Q): return (Q[-1] - Q[0]) / (P[-1] - P[0]) * np.sum(P) / np.sum(Q)
print('Demand arc elasticity: {0:.2f}'.format(arc_elasticity(D, P)))
print('Supply arc elasticity: {0:.2f}'.format(arc_elasticity(S, P)))
In [12]:
def taxed_d_f(x): return d_f(x + 0.5, *d_c)
def diff(x): return abs(taxed_d_f(x) - s_f(x, *s_c))
e_p = minimize(diff, 1, bounds=[bounds]).x[0]
e_q = s_f(e_p, *s_c)
plot(d_f(P, *d_c), P, 'r-', taxed_d_f(P), P, 'r--', s_f(P, *s_c), P, 'b-', e_q, e_p, 'go',
legend=['Demand', 'Demand(taxed)', 'Supply', 'Equilibrium'], title='Tax in demand')
'Equilibrium is ({0:.2f}, {1:.2f})'.format(e_q, e_p)
Out[12]: