We specify Three models and provide the
corresponding estimating equations (math) and R
code using your dataframe df_phi_common with
columns:
market_id, firm_id_in_mkt, N_m, XD_m, R_m, XMC_im, q_im, Q_m, P_m, MC_im.
We use instrumental variables (IV) where regressors are potentially endogenous. At the market level, we instrument quantities using cost shifters; at the firm level, we instrument firm quantities using demand shifters.
XD_m).XMC_im).R_m).MC_im).We also define the market-level cost instrument \[ \bar X^{MC}_m = \frac{1}{N_m} \sum_i X^{MC}_{im}, \] used as an instrument for \(Q_m\) and its transformations.
Inverse demand (market-level): \[ \boxed{\; P_m = a_0 + a_X X^D_m + a_Q Q_m + \varepsilon_m \;} \]
Marginal cost (firm-level): \[ \boxed{\; MC_{im} = b_0 + b_X X^{MC}_{im} + b_q \, q_{im} + \nu_{im} \;} \]
Marginal Revenue (firm-level) \[ \boxed{\; MR_{im} = P_m + a_Q q_{im} \;} \]
Supply-Side Estimation Equation \[ \boxed{\; MR_{im} = b_0 + b_X X^{MC}_{im} + b_q \, q_{im} + \nu_{im} \;} \]
Endogeneity & instruments. - \(Q_m\) is endogenous in the price equation. Use instruments \(Z^{(M1)}_m = [\bar X^{MC}_m, \; R_m \bar X^{MC}_m]\) (the second is optional; it can help with strength and over-ID). - \(q_{im}\) is endogenous in the cost equation. Use instruments \(Z^{(q)}_{im} = [X^D_m]\) (demand shifter shifts output via demand but is excluded from marginal cost).
Moment conditions: \[ \mathbb E[Z^{(M1)}_m \cdot \varepsilon_m]=0, \qquad \mathbb E[Z^{(q)}_{im} \cdot \nu_{im}] = 0. \]
library(tidyverse)
library(fixest)
df_phi_common<-read_csv("C:/Users/anubh/Dropbox/UG Emp IO/My Slides/R_markdownfiles/PSET Datasets/cournot_conjectural_variation.csv")
df_m <- df_phi_common %>%
group_by(market_id) %>%
summarize(XMC_bar_m = mean(XMC_im),
Q_m = mean(Q_m), P_m = mean(P_m),
XD_m = mean(XD_m))
# Price (market-level) IV: Q_m endogenous, instrumented by XMC_bar_m
m1_price <- feols(
P_m ~ XD_m | 0 | Q_m ~ XMC_bar_m,
data = df_m
)
alpha_hat = coefficients(m1_price)["fit_Q_m"]
df <- df_phi_common %>%
group_by(market_id) %>%
mutate(MR_hat = P_m + alpha_hat*q_im) %>%
ungroup()
# Marginal cost (firm-level) IV: q_im endogenous, instrumented by XD_m
m1_mc <- feols(
MR_hat ~ XMC_im | 0 | q_im ~ XD_m,
data = df
)
etable(m1_price,m1_mc)
## m1_price m1_mc
## Dependent Var.: P_m MR_hat
##
## Constant 50.26** (18.32) 3.019** (1.076)
## Q_m -1.380. (0.7812)
## XD_m 1.364* (0.6152)
## q_im 5.298*** (0.5184)
## XMC_im 0.7057*** (0.0361)
## _______________ ________________ __________________
## S.E. type IID IID
## Observations 1,000 11,458
## R2 -9.5832 -1.3180
## Adj. R2 -9.6044 -1.3184
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Inverse demand (market-level) with conduct shifter interaction: \[ \boxed{\; P_m = a_0 + a_X X^D_m + a_Q Q_m + a_{RQ} (Q_m R_m) + \varepsilon_m \;} \]
Marginal cost (firm-level): same as Model 1, \[ MC_{im} = b_0 + b_X X^{MC}_{im} + b_q \, q_{im} + \nu_{im}. \]
Marginal Revenue (firm-level) \[ \boxed{\; MR_{im} = P_m + (a_Q + a_{RQ}) q_{im} \;} \]
Supply-Side Estimation Equation \[ \boxed{\; MR_{im} = b_0 + b_X X^{MC}_{im} + b_q \, q_{im} + \nu_{im} \;} \]
Endogeneity & instruments. - \(Q_m\) and \(Q_m R_m\) are endogenous. Use instruments \[ Z^{(M2)}_m = [\, \bar X^{MC}_m,\; (\bar X^{MC}_m \cdot R_m)\,]. \] - For the MC equation, use the same instrument \(Z^{(q)}_{im} = [X^D_m]\) for \(q_{im}\).
Moment conditions: \[ \mathbb E[Z^{(M2)}_m \cdot \varepsilon_m]=0, \qquad \mathbb E[Z^{(q)}_{im} \cdot \nu_{im}] = 0. \]
# Price (market-level) IV with interaction term
df_m <- df_phi_common %>%
group_by(market_id) %>%
summarize(XMC_bar_m = mean(XMC_im),
Q_m = mean(Q_m), P_m = mean(P_m),
XD_m = mean(XD_m), R_m = mean(R_m))
# Price (market-level) IV: Q_m endogenous, instrumented by XMC_bar_m
m2_price <- feols(
P_m ~ XD_m | 0 | Q_m + I(Q_m * R_m) ~ XMC_bar_m + I(XMC_bar_m * R_m),
data = df_m
)
alpha_hat = coefficients(m2_price)["fit_Q_m"]
gamma_hat = coefficients(m2_price)["fit_I(Q_m * R_m)"]
df <- df_phi_common %>%
group_by(market_id) %>%
mutate(MR_hat = P_m + (alpha_hat + gamma_hat*R_m)*q_im) %>%
ungroup()
# Marginal cost (firm-level) IV (same as M1)
m2_mc <- feols(
MC_im ~ XMC_im | 0 | q_im ~ XD_m,
data = df
)
etable(m2_price,m2_mc)
## m2_price m2_mc
## Dependent Var.: P_m MC_im
##
## Constant 39.80*** (0.6883) 2.165*** (0.1550)
## Q_m -0.9878*** (0.0309)
## I(Q_m*R_m) -0.2314*** (0.0068)
## XD_m 1.016*** (0.0251)
## q_im 1.422*** (0.0747)
## XMC_im 0.7956*** (0.0052)
## _______________ ___________________ __________________
## S.E. type IID IID
## Observations 1,000 11,458
## R2 0.96897 0.88083
## Adj. R2 0.96887 0.88081
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Inverse demand (market-level) with conduct shifter interaction: \[ \boxed{\; P_m = a_0 + a_X X^D_m + a_Q Q_m + a_{RQ} (Q_m R_m) + \varepsilon_m \;} \]
Marginal cost (firm-level): same as Model 1, \[ MC_{im} = b_0 + b_X X^{MC}_{im} + b_q \, q_{im} + \nu_{im}. \]
Marginal Revenue (firm-level) \[ \boxed{\; MR_{im} = P_m + (a_Q + a_{RQ}\cdot R_m)\cdot (1 + CV) q_{im} \;} \]
Supply-Side Estimation Equation \[ \boxed{\; P_m = b_0 + b_X X^{MC}_{im} + \left(b_q - a_Q \cdot (1 +CV)\right) \, q_{im} - a_{RQ} \cdot \left(1 +CV\right) \, q_{im} \cdot R_m + \nu_{im} \;} \]
\[ \boxed{\; P_m = b_0 + b_X X^{MC}_{im} +\gamma_1 \, q_{im} + \gamma_2 \, q_{im}\cdot R_m + \nu_{im} \;} \]
Endogeneity & instruments (Step B). The RHS contains \(q_{im}\) and \(Q_m - q_{im}\), both endogenous. Use demand shifters as instruments: \[ Z^{(CV)}_{im} = [\, X^D_m,\; X^D_m \cdot R_m\,]. \] Moment condition: \(\mathbb E[Z^{(CV)}_{im} e_{im}] = 0\).
# --- Step A: estimate a_Q and a_RQ (reuse Model 2 price equation) ---
# Using m2_price from above; if not in memory, re-run the model here
m3_price <- feols(
P_m ~ XD_m | 0 | Q_m + I(Q_m * R_m) ~ XMC_bar_m + I(XMC_bar_m * R_m),
data = df_m)
coefs <- coef(m2_price)
a_Q_hat <- unname(coefs["fit_Q_m"]) # coefficient on endogenous Q_m after IV
a_RQ_hat <- unname(coefs["fit_I(Q_m * R_m)"]) # coefficient on endogenous interaction
# --- Step B: More instruments for better identification ---
df_cv <- df_phi_common %>%
group_by(market_id) %>%
mutate(Z_mc = (sum(XMC_im)-XMC_im)/length(firm_id_in_mkt) ) %>%
ungroup()
# IV regression: lhs ~ q_im + Q_minus_i, instrument both with XD_m and XD_m*R_m
m3_cv <- feols(
P_m ~ XMC_im | 0 | q_im + I(q_im * R_m) ~ XD_m + I(XD_m * R_m) + Z_mc + I(Z_mc * R_m) + I(XD_m*Z_mc)+I(XD_m*R_m*Z_mc),
data = df_cv
)
etable(m1_price,m1_mc,m2_price,m2_mc,m3_price,m3_cv)
## m1_price m1_mc m2_price
## Dependent Var.: P_m MR_hat P_m
##
## Constant 50.26** (18.32) 3.019** (1.076) 39.80*** (0.6883)
## Q_m -1.380. (0.7812) -0.9878*** (0.0309)
## XD_m 1.364* (0.6152) 1.016*** (0.0251)
## q_im 5.298*** (0.5184)
## XMC_im 0.7057*** (0.0361)
## I(Q_m*R_m) -0.2314*** (0.0068)
## I(q_im*R_m)
## _______________ ________________ __________________ ___________________
## S.E. type IID IID IID
## Observations 1,000 11,458 1,000
## R2 -9.5832 -1.3180 0.96897
## Adj. R2 -9.6044 -1.3184 0.96887
##
## m2_mc m3_price m3_cv
## Dependent Var.: MC_im P_m P_m
##
## Constant 2.165*** (0.1550) 39.80*** (0.6883) 2.206*** (0.1530)
## Q_m -0.9878*** (0.0309)
## XD_m 1.016*** (0.0251)
## q_im 1.422*** (0.0747) 7.396*** (0.0776)
## XMC_im 0.7956*** (0.0052) 0.7934*** (0.0058)
## I(Q_m*R_m) -0.2314*** (0.0068)
## I(q_im*R_m) 1.474*** (0.0182)
## _______________ __________________ ___________________ __________________
## S.E. type IID IID IID
## Observations 11,458 1,000 11,458
## R2 0.88083 0.96897 0.96716
## Adj. R2 0.88081 0.96887 0.96715
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Note that \(CV = \frac{\gamma_2}{-a_{RQ}} - 1\) and \(b_q = \gamma_1 + a_Q \cdot (1 + CV)\)
CV = -coefficients(m3_cv)["fit_I(q_im * R_m)"]/coefficients(m3_price)["fit_I(Q_m * R_m)"] -1
bq = coefficients(m3_cv)["fit_q_im"] + coefficients(m3_price)["fit_Q_m"]*(1 + CV)
names(CV)<-"CV"
names(bq)<-"bq"
CV
## CV
## 5.370089
bq
## bq
## 1.103804
# market_id, product_id, RAM, Screen, income_m, input_price, mc_actual, price, share
blp_industry<-read_csv("C:/Users/anubh/Dropbox/UG Emp IO/My Slides/R_markdownfiles/PSET Datasets/est_industry_ex.csv")
# Compute outside share s0 per market if not provided
blp0 <- blp_industry %>%
group_by(market_id) %>%
mutate(s0_outside = pmax(1 - sum(share), .Machine$double.eps)) %>%
ungroup()
# Define a market size (only needed to create a quantity variable)
market_size <- 1e5
blp0 <- blp0 %>% mutate(quantity = share * market_size)
We consider differentiated products \(i = 1, \dots, J_m\) in market \(m\). Consumer utility is
\[ U_{im} = \delta_{im} + \varepsilon_{im}, \]
where \(\varepsilon_{im}\) follows i.i.d. Type I Extreme Value.
The mean utility is parameterized as
\[ \delta_{im} = X_{im}\beta - \alpha p_{im} + \xi_{im}, \]
with
- \(X_{im} = (RAM_{im},\;
Screen_{im})\),
- \(p_{im}\) the observed price,
- \(\xi_{im}\) the unobserved product
quality term.
We construct the dependent variable. We also construct the BLP-instruments for this example defined as the absolute distance between own-product characteristics and average opponent characteristic.
blp_sim_optim <- blp0 %>%
mutate(
delta_obs = log(share) - log(s0_outside)
) %>%
group_by(market_id) %>%
mutate(
n_prod = n(),
blp_ram_sum = abs((sum(RAM) - RAM) /(n_prod-1) - RAM),
blp_screen_sum = abs((sum(Screen) - Screen) /(n_prod-1) - Screen)
) %>%
ungroup()
Recall our Demand Estimation Equation is given by:
\[ \log(s_{im}) - \log(s_{0m}) = RAM_{im}\beta_1 + Screen_{im}\beta_2 - \alpha p_{im} + \xi_{im}. \]
mD <- feols(
delta_obs ~ RAM + Screen - 1 | 0 |
price ~ blp_ram_sum + blp_screen_sum,
data = blp_sim_optim
)
alpha_hat <- coef(mD)["fit_price"]
etable(mD)
## mD
## Dependent Var.: delta_obs
##
## price -1.591*** (0.0142)
## RAM 0.8141*** (0.0011)
## Screen 0.6792*** (0.0089)
## _______________ __________________
## S.E. type IID
## Observations 10,000
## R2 0.99136
## Adj. R2 0.99136
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Under single-product Bertrand logit: \(\hat{\text{MR}}_{jm} = p_{jm} -1 / (\alpha (1-s_{jm}))\) with \(\alpha\) recovered from demand estimation.
blp_sim_optim <- blp_sim_optim %>%
mutate(
markup_hat = -1 / (alpha_hat * (1 - share)),
mc_hat = price - markup_hat
)
Parametric MC: \(mc = c_0 + c_1 RAM + c_2 Screen + c_3 input\_price + \omega\). We include no fixed effects for compactness, but you could add market FE if desired. Our specification is given by:
\[ \hat{\text{MR}}_{jm} = c_0 + c_1 RAM_{jm} + c_2 Screen_{jm} + c_3 input\_price_{jm} + \omega_{jm} \]
# Use quantity as an endogenous control if desired (here it equals share*market_size)
# Instruments: rival sums (same as demand)
m_supply_A <- feols(
mc_hat ~ -1 + RAM + Screen + input_price | 0 | I(quantity/1e5) ~ blp_ram_sum + blp_screen_sum,
data = blp_sim_optim
)
etable(m_supply_A)
## m_supply_A
## Dependent Var.: mc_hat
##
## I(quantity/1e+05) 9.164*** (0.2787)
## RAM 0.1943*** (0.0019)
## Screen 0.4102*** (0.0016)
## input_price 2.146*** (0.0081)
## _________________ __________________
## S.E. type IID
## Observations 10,000
## R2 0.92034
## Adj. R2 0.92032
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
To obtain an estimate of CV parameter note we have the following regression:
\[ p_{jm} - MC_{jm} = - \frac{1}{\alpha \left(1 - s_{jm} - \sum_{j^\prime \neq j}CV_{j\rightarrow j^\prime} \cdot s_{j^\prime m}\right)} \]
Assume that we observe \(MC_{jm}\) then we can obtain the following specification (here \(\alpha\) can be negative and therefore is of the opposite sign of the one in the previous lecture notes):
\[ -\frac{1}{\alpha \left(p_{jm} - MC_{jm}\right)} - \left(1 - s_{j m}\right)= - \sum_{j^\prime \neq j} CV_{j\rightarrow j^\prime } \cdot s_{j^\prime m} \]
We assume \(CV_{j \rightarrow j^\prime}=CV\) and then the estimation equation takes the form:
\[ -\frac{1}{\alpha \left(p_{jm} - MC_{jm}\right)} - \left(1 - s_{jm}\right) = - CV \cdot \left(\sum_{j^\prime \neq j} s_{j^\prime m}\right) \]
blp_sim_optim <- blp_sim_optim %>%
group_by(market_id) %>% mutate(othr_share = pmax(sum(share) - share, 0)) %>% ungroup() %>%
mutate(lhs_est = -1/(alpha_hat*(price - mc_actual)) - (1 - share))
m_supply_cv <- feols(lhs_est ~ othr_share, data = blp_sim_optim)
cv_est <- coef(m_supply_cv) / sd(m_supply_cv$residuals)
list(
cv_regression = summary(m_supply_cv),
cv_parameter_over_resid_sd = cv_est
)
## $cv_regression
## OLS estimation, Dep. Var.: lhs_est
## Observations: 10,000
## Standard-errors: IID
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.000000787 2.15e-08 -36.681 < 2.2e-16 ***
## othr_share -0.811439618 2.19e-08 -37096448.289 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## RMSE: 1.007e-7 Adj. R2: 1
##
## $cv_parameter_over_resid_sd
## (Intercept) othr_share
## -7.815882e+00 -8.056846e+06
A second approach would be to note that the estimation equation gives us that \(CV = \frac{-\frac{1}{\alpha \left(p_{jm} - MC_{jm}\right)} - \left(1 - s_{jm}\right)}{\left(\sum_{j^\prime \neq j} s_{j^\prime m}\right)}\)
blp_sim_optim <- blp_sim_optim %>%
group_by(market_id) %>% mutate(othr_share = pmax(sum(share) - share, 0)) %>% ungroup() %>%
mutate(cv_est2 = lhs_est/othr_share)
mean(blp_sim_optim$cv_est2)
## [1] -0.8114404
etable(mD, m_supply_A, m_supply_cv, dict = c(
RAM = "RAM (GB)", Screen = "Screen (inches)", input_price = "Input price",
price = "Price", price_inc = "PriceĆIncome",
blp_ram_sum = "Rival RAM agg", blp_screen_sum = "Rival Screen agg"
))
## mD m_supply_A m_supply_cv
## Dependent Var.: delta_obs mc_hat lhs_est
##
## Price -1.591*** (0.0142)
## RAM (GB) 0.8141*** (0.0011) 0.1943*** (0.0019)
## Screen (inches) 0.6792*** (0.0089) 0.4102*** (0.0016)
## I(quantity/1e+05) 9.164*** (0.2787)
## Input price 2.146*** (0.0081)
## Constant -7.87e-7*** (2.15e-8)
## othr_share -0.8114*** (2.19e-8)
## _________________ __________________ __________________ _____________________
## S.E. type IID IID IID
## Observations 10,000 10,000 10,000
## R2 0.99136 0.92034 1.0000
## Adj. R2 0.99136 0.92032 1.0000
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1