Logit-Functions: (Nested) Logit Demand Calibration and Merger Simulation)

Logit-FunctionsR Documentation

(Nested) Logit Demand Calibration and Merger Simulation)

Description

Calibrates consumer demand using (Nested) Logit and then simulates the price effect of a merger between two firms under the assumption that all firms in the market are playing a differentiated products Bertrand pricing game.

Let k denote the number of products produced by all firms playing the Bertrand pricing game below.

Usage

logit(
  prices,
  shares,
  margins,
  diversions,
  ownerPre,
  ownerPost,
  normIndex = ifelse(isTRUE(all.equal(sum(shares), 1, check.names = FALSE)), 1, NA),
  mcDelta = rep(0, length(prices)),
  subset = rep(TRUE, length(prices)),
  insideSize = NA_real_,
  priceOutside = 0,
  priceStart = prices,
  isMax = FALSE,
  control.slopes,
  control.equ,
  labels = paste("Prod", 1:length(prices), sep = ""),
  ...
)

logit.nests(
  prices,
  shares,
  margins,
  diversions,
  ownerPre,
  ownerPost,
  nests = rep(1, length(shares)),
  normIndex = ifelse(sum(shares) < 1, NA, 1),
  mcDelta = rep(0, length(prices)),
  subset = rep(TRUE, length(prices)),
  priceOutside = 0,
  priceStart = prices,
  isMax = FALSE,
  constraint = TRUE,
  parmsStart,
  control.slopes,
  control.equ,
  labels = paste("Prod", 1:length(prices), sep = ""),
  ...
)

logit.nests.alm(
  prices,
  shares,
  margins,
  ownerPre,
  ownerPost,
  nests = rep(1, length(shares)),
  mcDelta = rep(0, length(prices)),
  subset = rep(TRUE, length(prices)),
  priceOutside = 0,
  priceStart = prices,
  isMax = FALSE,
  constraint = TRUE,
  parmsStart,
  control.slopes,
  control.equ,
  labels = paste("Prod", 1:length(prices), sep = ""),
  ...
)

logit.cap(
  prices,
  shares,
  margins,
  ownerPre,
  ownerPost,
  capacitiesPre = rep(Inf, length(prices)),
  capacitiesPost = capacitiesPre,
  insideSize,
  normIndex = ifelse(sum(shares) < 1, NA, 1),
  mcDelta = rep(0, length(prices)),
  subset = rep(TRUE, length(prices)),
  priceOutside = 0,
  priceStart = prices,
  isMax = FALSE,
  control.slopes,
  control.equ,
  labels = paste("Prod", 1:length(prices), sep = ""),
  ...
)

logit.alm(
  prices,
  shares,
  margins,
  ownerPre,
  ownerPost,
  mktElast = NA_real_,
  insideSize = NA_real_,
  mcDelta = rep(0, length(prices)),
  subset = rep(TRUE, length(prices)),
  priceOutside = 0,
  priceStart = prices,
  isMax = FALSE,
  parmsStart,
  control.slopes,
  control.equ,
  labels = paste("Prod", 1:length(prices), sep = ""),
  ...
)

logit.cap.alm(
  prices,
  shares,
  margins,
  ownerPre,
  ownerPost,
  capacitiesPre = rep(Inf, length(prices)),
  capacitiesPost = capacitiesPre,
  mktElast = NA_real_,
  insideSize,
  mcDelta = rep(0, length(prices)),
  subset = rep(TRUE, length(prices)),
  priceOutside = 0,
  priceStart = prices,
  isMax = FALSE,
  parmsStart,
  control.slopes,
  control.equ,
  labels = paste("Prod", 1:length(prices), sep = ""),
  ...
)

Arguments

prices

A length k vector of product prices.

shares

A length k vector of product (quantity) shares. Values must be between 0 and 1.

margins

A length k vector of product margins, some of which may equal NA.

diversions

A k x k matrix of diversion ratios with diagonal elements equal to -1. Default is missing.

ownerPre

EITHER a vector of length k whose values indicate which firm produced a product pre-merger OR a k x k matrix of pre-merger ownership shares.

ownerPost

EITHER a vector of length k whose values indicate which firm produced a product after the merger OR a k x k matrix of post-merger ownership shares.

normIndex

An integer equalling the index (position) of the inside product whose mean valuation will be normalized to 1. Default is 1, unless ‘shares’ sum to less than 1, in which case the default is NA and an outside good is assumed to exist.

mcDelta

A vector of length k where each element equals the proportional change in a product's marginal costs due to the merger. Default is 0, which assumes that the merger does not affect any products' marginal cost.

subset

A vector of length k where each element equals TRUE if the product indexed by that element should be included in the post-merger simulation and FALSE if it should be excluded.Default is a length k vector of TRUE.

insideSize

An integer equal to total pre-merger units sold. If shares sum to one, this also equals the size of the market.

priceOutside

A length 1 vector indicating the price of the outside good. Default is 0.

priceStart

A length k vector of starting values used to solve for equilibrium price. Default is the ‘prices’ vector.

isMax

If TRUE, checks to see whether computed price equilibrium locally maximizes firm profits and returns a warning if not. Default is FALSE.

control.slopes

A list of optim control parameters passed to the calibration routine optimizer (typically the calcSlopes method).

control.equ

A list of BBsolve control parameters passed to the non-linear equation solver (typically the calcPrices method).

labels

A k-length vector of labels. Default is "Prod#", where ‘#’ is a number between 1 and the length of ‘prices’.

...

Additional options to feed to the BBsolve optimizer used to solve for equilibrium prices.

nests

A length k vector identifying the nest that each product belongs to.

constraint

if TRUE, then the nesting parameters for all non-singleton nests are assumed equal. If FALSE, then each non-singleton nest is permitted to have its own value. Default is TRUE.

parmsStart

For logit.cap.alm, a length-2 vector of starting values used to solve for the price coefficient and outside share (in that order). For logit.nets, rhe first element should always be the price coefficient and the remaining elements should be the nesting parameters. Theory requires the nesting parameters to be greater than the price coefficient. If missing then the random draws with the appropriate restrictions are employed.

capacitiesPre

A length k vector of pre-merger product capacities. Capacities must be at least as great as shares * insideSize.

capacitiesPost

A length k vector of post-merger product capacities.

mktElast

a negative value indicating market elasticity. Default is NA.

Details

Using product prices, quantity shares and all of the product margins from at least one firm, logit is able to recover the price coefficient and product mean valuations in a Logit demand model. logit then uses these calibrated parameters to simulate a merger between two firms.

logit.alm is identical to logit except that it assumes that an outside product exists and uses additional margin information to estimate the share of the outside good. If market elasticity is known, it may be supplied using the ‘mktElast’ argument.

logit.nests is identical to logit except that it includes the ‘nests’ argument which may be used to assign products to different nests. Nests are useful because they allow for richer substitution patterns between products. Products within the same nest are assumed to be closer substitutes than products in different nests. The degree of substitutability between products located in different nests is controlled by the value of the nesting parameter sigma. The nesting parameters for singleton nests (nests containing only one product) are not identified and normalized to 1. The vector of sigmas is calibrated from the prices, revenue shares, and margins supplied by the user.

By default, all non-singleton nests are assumed to have a common value for sigma. This constraint may be relaxed by setting ‘constraint’ to FALSE. In this case, at least one product margin must be supplied from a product within each nest.

logit.nests.alm is identical to logit.nests except that it assumes that an outside product exists and uses additional margin information to estimate the share of the outside good.

logit.cap is identical to logit except that firms are playing the Bertrand pricing game under exogenously supplied capacity constraints. Unlike logit, logit.cap requires users to specify capacity constraints via ‘capacities’ and the number of potential customers in a market via ‘mktSize’. ‘mktSize’ is needed to transform ‘shares’ into quantities that must be directly compared to ‘capacities’.

In logit, logit.nests and logit.cap, if quantity shares sum to 1, then one product's mean value is not identified and must be normalized to 0. ‘normIndex’ may be used to specify the index (position) of the product whose mean value is to be normalized. If the sum of revenue shares is less than 1, both of these functions assume that the exists a k+1st product in the market whose price and mean value are both normalized to 0.

Value

logit returns an instance of class Logit. logit.alm returns an instance of LogitALM, a child class of Logit.. logit.nests returns an instance of LogitNests, a child class of Logit. logit.cap returns an instance of LogitCap, a child class of Logit.

Author(s)

Charles Taragin ctaragin+antitrustr@gmail.com

References

Anderson, Simon, Palma, Andre, and Francois Thisse (1992). Discrete Choice Theory of Product Differentiation. The MIT Press, Cambridge, Mass.

Epstein, Roy and Rubinfeld, Daniel (2004). “Effects of Mergers Involving Differentiated Products.”

Werden, Gregory and Froeb, Luke (1994). “The Effects of Mergers in Differentiated Products Industries: Structural Merger Policy and the Logit Model”, Journal of Law, Economics, and Organization, 10, pp. 407-426.

Froeb, Luke, Tschantz, Steven and Phillip Crooke (2003). “Bertrand Competition and Capacity Constraints: Mergers Among Parking Lots”, Journal of Econometrics, 113, pp. 49-67.

Froeb, Luke and Werden, Greg (1996). “Computational Economics and Finance: Modeling and Analysis with Mathematica, Volume 2.” In Varian H (ed.), chapter Simulating Mergers among Noncooperative Oligopolists, pp. 177-95. Springer-Verlag, New York.

See Also

ces

Examples

## Calibration and simulation results from a merger between Budweiser and
## Old Style.
## Source: Epstein/Rubenfeld 2004, pg 80


prodNames <- c("BUD","OLD STYLE","MILLER","MILLER-LITE","OTHER-LITE","OTHER-REG")
ownerPre <-c("BUD","OLD STYLE","MILLER","MILLER","OTHER-LITE","OTHER-REG")
ownerPost <-c("BUD","BUD","MILLER","MILLER","OTHER-LITE","OTHER-REG")
nests <- c("Reg","Reg","Reg","Light","Light","Reg")

price    <- c(.0441,.0328,.0409,.0396,.0387,.0497)
shares   <- c(.066,.172,.253,.187,.099,.223)
margins <- c(.3830,.5515,.5421,.5557,.4453,.3769)

insideSize <- 1000

names(price) <-
  names(shares) <-
  names(margins) <-
  prodNames

result.logit <- logit(price,shares,margins,
                      ownerPre=ownerPre,ownerPost=ownerPost,
                      insideSize = insideSize,
                      labels=prodNames)



print(result.logit)           # return predicted price change
summary(result.logit)         # summarize merger simulation

elast(result.logit,TRUE)      # returns premerger elasticities
elast(result.logit,FALSE)     # returns postmerger elasticities

diversion(result.logit,TRUE)  # return premerger diversion ratios
diversion(result.logit,FALSE) # return postmerger diversion ratios


cmcr(result.logit)            #calculate compensating marginal cost reduction
upp(result.logit)            #calculate Upwards Pricing Pressure Index

CV(result.logit)              #calculate representative agent compensating variation


## Implement the Hypothetical Monopolist Test
## for BUD and OLD STYLE using a 5\% SSNIP

HypoMonTest(result.logit,prodIndex=1:2)



## Get a detailed description of the 'Logit' class slots
showClass("Logit")

## Show all methods attached to the 'Logit' Class
showMethods(classes="Logit")

## Show which classes have their own 'elast' method
showMethods("elast")

## Show the method definition for 'elast' and Class 'Logit'
getMethod("elast","Logit")



#
# Logit With capacity Constraints
#


cap     <- c(66,200,300,200,99,300) # BUD and OTHER-LITE are capacity constrained
result.cap <- logit.cap(price,shares,margins,capacitiesPre=cap,
                        insideSize=insideSize,ownerPre=ownerPre,
                        ownerPost=ownerPost,labels=prodNames)
print(result.cap)


antitrust documentation built on Aug. 24, 2022, 9:05 a.m.