1 Estimation Under Homogeneous Products

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.


1.1 Notation

  • Markets: \(m = 1,\ldots, M\); firms within market: \(i = 1,\ldots, N_m\).
  • Market price and quantity: \(P_m, Q_m\). Firm output: \(q_{im}\), with \(Q_m = \sum_i q_{im}\).
  • Demand shifter (market-level): \(X^D_m\) (column XD_m).
  • Cost shifter (firm-level): \(X^{MC}_{im}\) (column XMC_im).
  • Demand Rotator (market-level): \(R_m\) (column R_m).
  • Marginal cost (observed): \(MC_{im}\) (column 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.


1.2 Model 1

1.2.1 Mathematical specification

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. \]

1.2.2 R code

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

1.3 Model 2

1.3.1 Mathematical specification

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. \]

1.3.2 R code

# 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

1.4 Model 3: Conjectural Variation

1.4.1 Economic structure

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\).

1.4.2 R code

# --- 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

1.4.3 Recover \(CV\) and \(b_q\)

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

2 Estimation Under Differentiated Products

2.1 Data

# 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)

2.2 Demand Specification

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.

2.2.1 Logit Market Shares and Inversion

The logit market share of product \(i\) in market \(m\) is

\[ s_{im} = \frac{\exp(\delta_{im})} {1 + \sum_j \exp(\delta_{jm})}. \]

The BLP inversion gives

\[ \delta_{im} = \log(s_{im}) - \log(s_{0m}), \]

where \(s_{0m}\) is the outside share.
Thus \(\delta_{im}\) becomes data-based.

2.3 Instruments & Transformations

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() 

2.4 Demand

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

2.5 Markups & Implied Marginal Costs

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
  )

2.6 Supply Equation (Linear MC)

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

2.7 Conjectural Variations Extension

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

2.8 Clean Output Tables

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