import numpy as np
from ogcore import aggregates as aggr
"""
------------------------------------------------------------------------
Firm functions for firms in the steady state and along the transition
path
------------------------------------------------------------------------
"""
"""
------------------------------------------------------------------------
Functions
------------------------------------------------------------------------
"""
[docs]
def get_Y(K, K_g, L, p, method, m=-1):
r"""
Generates aggregate output (GDP) from aggregate capital stock,
aggregate labor, and CES production function parameters.
.. math::
\hat{Y}_t &= F(\hat{K}_t, \hat{K}_{g,t}, \hat{L}_t) \\
&\equiv Z_t\biggl[(\gamma)^\frac{1}{\varepsilon}(\hat{K}_t)^\frac{\varepsilon-1}{\varepsilon} +
(\gamma_{g})^\frac{1}{\varepsilon}(\hat{K}_{g,t})^\frac{\varepsilon-1}{\varepsilon} +
(1-\gamma-\gamma_{g})^\frac{1}{\varepsilon}(\hat{L}_t)^\frac{\varepsilon-1}{\varepsilon}\biggr]^\frac{\varepsilon}{\varepsilon-1}
\quad\forall t
Args:
K (array_like): aggregate private capital
K_g (array_like): aggregate government capital
L (array_like): aggregate labor
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or
'TPI'
m (int or None): industry index
Returns:
Y (array_like): aggregate output
"""
if method == "SS":
if m is not None:
# Set gamma_g to 0 when K_g=0 and eps=1 to remove K_g from prod func
if K_g == 0 and p.epsilon[m] <= 1:
gamma_g = 0
K_g = 1
else:
gamma_g = p.gamma_g[m]
gamma = p.gamma[m]
epsilon = p.epsilon[m]
Z = p.Z[-1, m]
if epsilon == 1:
Y = (
Z
* (K**gamma)
* (K_g**gamma_g)
* (L ** (1 - gamma - gamma_g))
)
else:
Y = Z * (
(
(gamma ** (1 / epsilon))
* (K ** ((epsilon - 1) / epsilon))
)
+ (
(gamma_g ** (1 / epsilon))
* (K_g ** ((epsilon - 1) / epsilon))
)
+ (
((1 - gamma - gamma_g) ** (1 / epsilon))
* (L ** ((epsilon - 1) / epsilon))
)
) ** (epsilon / (epsilon - 1))
else:
# Set gamma_g to 0 when K_g=0 and eps=1 to remove K_g from prod func
if K_g == 0 and np.any(p.epsilon) <= 1:
gamma_g = p.gamma_g
gamma_g[p.epsilon <= 1] = 0
K_g = 1.0
else:
gamma_g = p.gamma_g
gamma = p.gamma
epsilon = p.epsilon
Z = p.Z[-1, :]
Y = Z * (
((gamma ** (1 / epsilon)) * (K ** ((epsilon - 1) / epsilon)))
+ (
(gamma_g ** (1 / epsilon))
* (K_g ** ((epsilon - 1) / epsilon))
)
+ (
((1 - gamma - gamma_g) ** (1 / epsilon))
* (L ** ((epsilon - 1) / epsilon))
)
) ** (epsilon / (epsilon - 1))
Y2 = Z * (K**gamma) * (K_g**gamma_g) * (L ** (1 - gamma - gamma_g))
Y[epsilon == 1] = Y2[epsilon == 1]
else: # TPI case
if m is not None:
# Set gamma_g to 0 when K_g=0 and eps=1 to remove K_g from prod func
if np.any(K_g == 0) and p.epsilon[m] == 1:
gamma_g = 0
K_g[K_g == 0] = 1.0
else:
gamma_g = p.gamma_g[m]
gamma = p.gamma[m]
epsilon = p.epsilon[m]
Z = p.Z[: p.T, m]
if epsilon == 1:
Y = (
Z
* (K**gamma)
* (K_g**gamma_g)
* (L ** (1 - gamma - gamma_g))
)
else:
Y = Z * (
(
(gamma ** (1 / epsilon))
* (K ** ((epsilon - 1) / epsilon))
)
+ (
(gamma_g ** (1 / epsilon))
* (K_g ** ((epsilon - 1) / epsilon))
)
+ (
((1 - gamma - gamma_g) ** (1 / epsilon))
* (L ** ((epsilon - 1) / epsilon))
)
) ** (epsilon / (epsilon - 1))
else:
# Set gamma_g to 0 when K_g=0 and eps=1 to remove K_g from prod func
if np.any(K_g == 0) and np.any(p.epsilon) == 1:
gamma_g = p.gamma_g
K_g[K_g == 0] = 1.0
else:
gamma_g = p.gamma_g
gamma = p.gamma
epsilon = p.epsilon
Z = p.Z[: p.T, :]
Y = Z * (
((gamma ** (1 / epsilon)) * (K ** ((epsilon - 1) / epsilon)))
+ (
(gamma_g ** (1 / epsilon))
* (K_g ** ((epsilon - 1) / epsilon))
)
+ (
((1 - gamma - gamma_g) ** (1 / epsilon))
* (L ** ((epsilon - 1) / epsilon))
)
) ** (epsilon / (epsilon - 1))
Y2 = Z * (K**gamma) * (K_g**gamma_g) * (L ** (1 - gamma - gamma_g))
Y[:, epsilon == 1] = Y2[:, epsilon == 1]
return Y
[docs]
def get_r(Y, K, p_m, p, method, m=-1):
r"""
This function computes the interest rate as a function of Y, K, and
parameters using the firm's first order condition for capital
demand.
.. math::
r_{t} = (1 - \tau^{corp}_t)Z_t^\frac{\varepsilon-1}{\varepsilon}
\left[\gamma\frac{Y_t}{K_t}\right]^\frac{1}{\varepsilon} -
\delta + \tau^{corp}_t\delta^\tau_t + \tau^{inv}_{m,t}
Args:
Y (array_like): aggregate output
K (array_like): aggregate capital
p_m (array_like): output prices
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or
'TPI'
m (int): index of the production industry
Returns:
r (array_like): the real interest rate
"""
if method == "SS":
delta_tau = p.delta_tau[-1, m]
tau_b = p.tau_b[-1, m]
tau_inv = p.inv_tax_credit[-1, m]
p_mm = p_m[m]
else:
delta_tau = p.delta_tau[: p.T, m].reshape(p.T, 1)
tau_b = p.tau_b[: p.T, m].reshape(p.T, 1)
tau_inv = p.inv_tax_credit[: p.T, m].reshape(p.T, 1)
p_mm = p_m[:, m].reshape(p.T, 1)
MPK = get_MPx(Y, K, p.gamma[m], p, method, m)
r = (
(1 - tau_b) * p_mm * MPK
- p.delta
+ tau_b * delta_tau
+ tau_inv * p.delta
)
return r
[docs]
def get_w(Y, L, p_m, p, method, m=-1):
r"""
This function computes the wage as a function of Y, L, and
parameters using the firm's first order condition for labor demand.
.. math::
w_t = Z_t^\frac{\varepsilon-1}{\varepsilon}\left[(1-\gamma-\gamma_g)
\frac{\hat{Y}_t}{\hat{L}_t}\right]^\frac{1}{\varepsilon}
Args:
Y (array_like): aggregate output
L (array_like): aggregate labor
p_m (array_like): output prices
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or
'TPI'
m (int): index of the production industry
Returns:
w (array_like): the real wage rate
"""
if method == "SS":
p_mm = p_m[m]
else:
p_mm = p_m[:, m].reshape(p.T, 1)
w = p_mm * get_MPx(Y, L, 1 - p.gamma[m] - p.gamma_g[m], p, method, m)
return w
def get_KLratio_KLonly(r, p, method, m=-1):
r"""
This function solves for the capital-labor ratio given the interest
rate, r, and parameters when the production function is only a
function of K and L. This is used in the get_w_from_r function.
.. math::
\frac{K}{L} = \left(\frac{(1-\gamma)^\frac{1}{\varepsilon}}
{\left[\frac{r_t + \delta - \tau_t^{corp}\delta_t^\tau}
{(1 - \tau_t^{corp})\gamma^\frac{1}
{\varepsilon}Z_t}\right]^{\varepsilon-1} -
\gamma^\frac{1}{\varepsilon}}\right)^\frac{\varepsilon}{\varepsilon-1}
Args:
r (array_like): the real interest rate
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or
'TPI'
m (int): production industry index
Returns:
KLratio (array_like): the capital-labor ratio
"""
if method == "SS":
Z = p.Z[-1, m]
else:
length = r.shape[0]
Z = p.Z[:length, m]
gamma = p.gamma[m]
epsilon = p.epsilon[m]
if epsilon == 1:
# Cobb-Douglas case
cost_of_capital = get_cost_of_capital(r, p, method, m)
KLratio = ((gamma * Z) / cost_of_capital) ** (1 / (1 - gamma))
else:
# General CES case
cost_of_capital = get_cost_of_capital(r, p, method, m)
bracket = cost_of_capital * (Z * (gamma ** (1 / epsilon))) ** -1
KLratio = (
((1 - gamma) ** (1 / epsilon))
/ ((bracket ** (epsilon - 1)) - (gamma ** (1 / epsilon)))
) ** (epsilon / (epsilon - 1))
return KLratio
[docs]
def get_KLratio(r, w, p, method, m=-1):
r"""
This function solves for the capital-labor ratio given the interest
rate r wage w and parameters.
.. math::
\frac{K}{L} = \left(\frac{\gamma}{1 - \gamma - \gamma_g}\right)
\left(\frac{w_t}{\frac{r_t + \delta -
\tau_t^{corp}\delta_t^{\tau}}{1 -
\tau_t^{corp}}}\right)^\varepsilon
Args:
r (array_like): the real interest rate
w (array_like): the wage rate
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or
'TPI'
m (int): production industry index
Returns:
KLratio (array_like): the capital-labor ratio
"""
cost_of_capital = get_cost_of_capital(r, p, method, m)
KLratio = (p.gamma[m] / (1 - p.gamma[m] - p.gamma_g[m])) * (
w / cost_of_capital
) ** p.epsilon[m]
return KLratio
[docs]
def get_MPx(Y, x, share, p, method, m=-1):
r"""
Compute the marginal product of x (where x is K, L, or K_g)
.. math::
MPx = Z_t^\frac{\varepsilon-1}{\varepsilon}\left[(share)
\frac{\hat{Y}_t}{\hat{x}_t}\right]^\frac{1}{\varepsilon}
Args:
Y (array_like): output
x (array_like): input to production function
share (scalar): share of output paid to factor x
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or
'TPI'
m (int): production industry index
Returns:
MPx (array_like): the marginal product of x
"""
if method == "SS":
Z = p.Z[-1, m]
else:
Z = p.Z[: p.T, m].reshape(p.T, 1)
Y = Y[: p.T].reshape(p.T, 1)
x = x[: p.T].reshape(p.T, 1)
if np.any(x) == 0:
MPx = np.zeros_like(Y)
else:
MPx = Z ** ((p.epsilon[m] - 1) / p.epsilon[m]) * ((share * Y) / x) ** (
1 / p.epsilon[m]
)
return MPx
[docs]
def get_w_from_r(r, p, method, m=-1):
r"""
Solve for a wage rate from a given interest rate. N.B. this is only
appropriate if the production function only uses capital and labor
as inputs. As such, this is not used for determining the domestic
wage rate due to the presense of public capital in the production
function. It is used only to determine the wage rate that affects
the open economy demand for capital.
.. math::
w = (1-\gamma)^\frac{1}{\varepsilon}Z\left[(\gamma)^\frac{1}
{\varepsilon}\left(\frac{(1-\gamma)^\frac{1}{\varepsilon}}
{\left[\frac{r + \delta - \tau^{corp}\delta^\tau}{(1 - \tau^{corp})
\gamma^\frac{1}{\varepsilon}Z}\right]^{\varepsilon-1} -
\gamma^\frac{1}{\varepsilon}}\right) +
(1-\gamma)^\frac{1}{\varepsilon}\right]^\frac{1}{\varepsilon-1}
Args:
r (array_like): the real interest rate
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or
'TPI'
m (int or None): production industry index
Returns:
w (array_like): the real wage rate
"""
KLratio = get_KLratio_KLonly(r, p, method, m)
if method == "TPI":
Z = p.Z[: p.T, m]
else:
Z = p.Z[-1, m]
gamma = p.gamma[m]
epsilon = p.epsilon[m]
if epsilon == 1:
# Cobb-Douglas case
w = (1 - gamma) * Z * (KLratio**gamma)
else:
# General CES case
w = (
((1 - gamma) ** (1 / epsilon))
* Z
* (
(
(gamma ** (1 / epsilon))
* (KLratio ** ((epsilon - 1) / epsilon))
+ ((1 - gamma) ** (1 / epsilon))
)
** (1 / (epsilon - 1))
)
)
return w
def get_K_KLonly(L, r, p, method, m=-1):
r"""
Generates vector of aggregate capital when the production function
uses only K and L as inputs. Use with the open economy options.
.. math::
K_{t} = \frac{K_{t}}{L_{t}} \times L_{t}
Args:
L (array_like): aggregate labor
r (array_like): the real interest rate
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or
'TPI'
m (int or None): production industry index
Returns:
K (array_like): aggregate capital demand
"""
KLratio = get_KLratio_KLonly(r, p, method, m)
K = KLratio * L
return K
[docs]
def get_L_from_Y(w, Y, p, method):
r"""
Find aggregate labor L from output Y and wages w
.. math::
L_{t} = \frac{(1 - \gamma - \gamma_g) Z_{t}^{\varepsilon-1}
Y_{t}}{w_{t}^{\varepsilon}}
Args:
w (array_like): the wage rate
Y (array_like): aggregate output
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or
'TPI'
Returns:
L (array_like): firm labor demand
"""
if method == "SS":
Z = p.Z[-1]
else:
Z = p.Z[: p.T]
L = ((1 - p.gamma - p.gamma_g) * Z ** (p.epsilon - 1) * Y) / (w**p.epsilon)
return L
[docs]
def get_K(r, w, L, p, method, m=-1):
r"""
Get K from r, w, L. For determining capital demand for open
economy case.
.. math::
K_{t} = \frac{K_{t}}{L_{t}} \times L_{t}
Args:
r (array_like): the real interest rate
w (array_like): the wage rate
L (array_like): aggregate labor
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or
'TPI'
m (int or None): production industry index
Returns:
K (array_like): aggregate capital demand
"""
KLratio = get_KLratio(r, w, p, method, m)
K = KLratio * L
return K
[docs]
def get_cost_of_capital(r, p, method, m=-1):
r"""
Compute the cost of capital.
.. math::
\rho_{m,t} = \frac{r_{t} + \delta_{M,t} - \tau^{b}_{m,t}
\delta^{\tau}_{m,t} - \tau^{inv}_{m,t}\delta_{M,t}}{1 - \tau^{b}_{m,t}}
Args:
r (array_like): the real interest rate
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or 'TPI'
m (int or None): production industry index
Returns:
cost_of_capital (array_like): cost of capital
"""
if m is None:
if method == "SS":
tau_b = p.tau_b[-1, :]
delta_tau = p.delta_tau[-1, :]
tau_inv = p.inv_tax_credit[-1, :]
else:
tau_b = p.tau_b[: p.T, :]
delta_tau = p.delta_tau[: p.T, :]
tau_inv = p.inv_tax_credit[: p.T, :]
r = r.reshape(p.T, 1)
else:
if method == "SS":
tau_b = p.tau_b[-1, m]
delta_tau = p.delta_tau[-1, m]
tau_inv = p.inv_tax_credit[-1, m]
else:
tau_b = p.tau_b[: p.T, m]
delta_tau = p.delta_tau[: p.T, m]
tau_inv = p.inv_tax_credit[: p.T, m]
r = r.reshape(p.T)
cost_of_capital = (r + p.delta - tau_b * delta_tau - tau_inv * p.delta) / (
1 - tau_b
)
return cost_of_capital
[docs]
def get_pm(w, Y_vec, L_vec, p, method):
r"""
Find prices for outputs from each industry.
.. math::
p_{m,t}=\frac{w_{t}}{\left((1-\gamma_m-\gamma_{g,m})
\frac{\hat{Y}_{m,t}}{\hat{L}_{m,t}}\right)^{\varepsilon_m}}
Args:
w (array_like): the wage rate
Y_vec (array_like): output for each industry
L_vec (array_like): labor demand for each industry
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or 'TPI'
Returns:
p_m (array_like): output prices for each industry
"""
if method == "SS":
Y = Y_vec.reshape(1, p.M)
L = L_vec.reshape(1, p.M)
T = 1
else:
Y = Y_vec.reshape((p.T, p.M))
L = L_vec.reshape((p.T, p.M))
T = p.T
p_m = np.zeros((T, p.M))
for m in range(p.M): # TODO: try to get rid of this loop
MPL = get_MPx(
Y[:, m], L[:, m], 1 - p.gamma[m] - p.gamma_g[m], p, method, m
).reshape(T)
p_m[:, m] = w / MPL
if method == "SS":
p_m = p_m.reshape(p.M)
return p_m
def get_KY_ratio(r, p_m, p, method, m=-1):
r"""
Get capital output ratio from FOC for interest rate.
.. math::
\frac{\hat{K}_{m,t}}{\hat{Y}_{m,t}}=\gamma_{m}
\left(\frac{p_{m,t}Z_{m,t}^{\frac{\varepsilon_m-1}
{\varepsilon_m}}}{\rho_{m,t}}\right)^{\varepsilon_m}
Args:
r (array_like): the real interest rate
p_m (array_like): output prices for each industry
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or 'TPI'
Returns:
KY_ratio (array_like): capital output ratio
"""
cost_of_capital = get_cost_of_capital(r, p, method, m)
if method == "SS":
KY_ratio = (
p.gamma[m]
* (
(p_m[m] * p.Z[-1, m] ** ((p.epsilon[m] - 1) / p.epsilon[m]))
/ cost_of_capital
)
** p.epsilon[m]
)
else:
KY_ratio = (
p.gamma[m]
* (
(
p_m[:, m]
* p.Z[: p.T, m] ** ((p.epsilon[m] - 1) / p.epsilon[m])
)
/ cost_of_capital
)
** p.epsilon[m]
)
return KY_ratio
[docs]
def solve_L(Y, K, K_g, p, method, m=-1):
r"""
Solve for labor supply from the production function
.. math::
\hat{L}_{m,t} = \left(\frac{\left(\frac{\hat{Y}_{m,t}}
{Z_{m,t}}\right)^{\frac{\varepsilon_m-1}{\varepsilon_m}} -
\gamma_{m}^{\frac{1}{\varepsilon_m}}\hat{K}_{m,t}^
{\frac{\varepsilon_m-1}{\varepsilon_m}} -
\gamma_{g,m}^{\frac{1}{\varepsilon_m}}\hat{K}_{g,m,t}^
{\frac{\varepsilon_m-1}{\varepsilon_m}}}
{(1-\gamma_m-\gamma_{g,m})^{\frac{1}{\varepsilon_m}}}
\right)^{\frac{\varepsilon_m}{\varepsilon_m-1}}
Args:
Y (array_like): output for each industry
K_vec (array_like): capital demand for each industry
K_g (array_like): public capital stock
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or 'TPI'
m (int or None): index of industry to compute L for (None will
compute L for all industries)
Returns:
L (array_like): labor demand each industry
"""
gamma = p.gamma[m]
gamma_g = p.gamma_g[m]
epsilon = p.epsilon[m]
if method == "SS":
Z = p.Z[-1, m]
else:
Z = p.Z[: p.T, m]
try:
if K_g == 0:
K_g = 1.0
gamma_g = 0
except:
if np.any(K_g == 0):
K_g[K_g == 0] = 1.0
gamma_g = 0
if epsilon == 1.0:
L = (Y / (Z * K**gamma * K_g**gamma_g)) ** (1 / (1 - gamma - gamma_g))
else:
L = (
(
(Y / Z) ** ((epsilon - 1) / epsilon)
- gamma ** (1 / epsilon) * K ** ((epsilon - 1) / epsilon)
- gamma_g ** (1 / epsilon) * K_g ** ((epsilon - 1) / epsilon)
)
/ ((1 - gamma - gamma_g) ** (1 / epsilon))
) ** (epsilon / (epsilon - 1))
return L
def adj_cost(K, Kp1, p, method):
r"""
Firm capital adjstment costs
..math::
\Psi(K_{t}, K_{t+1}) = \frac{\psi}{2}\biggr(\frac{\biggr(\frac{I_{t}}{K_{t}}-\mu\biggl)^{2}}{\frac{I_{t}}{K_{t}}}\biggl)
Args:
K (array-like): Current period capital stock
Kp1 (array-like): One-period ahead capital stock
p (OG-USA Parameters class object): Model parameters
method (str): 'SS' or 'TPI'
Returns
Psi (array-like): Capital adjustment costs per unit of investment
"""
if method == "SS":
ac_method = "total_ss"
else:
ac_method = "total_tpi"
Inv = aggr.get_I(None, Kp1, K, p, ac_method)
Psi = ((p.psi / 2) * (Inv / K - p.mu) ** 2) / (Inv / K)
return Psi