Cournot-Functions | R Documentation |
Calibrates consumer demand for multiple products using either a linear or log-linear demand system and then simulates the prices effect of a merger between two multi-plant firms under the assumption that all firms in the market are playing either a Cournot or Stackelberg quantity setting game.
Let k denote the number of products and n denote the number of plants below.
cournot( prices, quantities, margins = matrix(NA_real_, nrow(quantities), ncol(quantities)), demand = rep("linear", length(prices)), cost = rep("linear", nrow(quantities)), mcfunPre = list(), mcfunPost = mcfunPre, vcfunPre = list(), vcfunPost = vcfunPre, capacitiesPre = rep(Inf, nrow(quantities)), capacitiesPost = capacitiesPre, productsPre = !is.na(quantities), productsPost = productsPre, ownerPre, ownerPost, mktElast = rep(NA_real_, length(prices)), mcDelta = rep(0, nrow(quantities)), quantityStart = as.vector(quantities), control.slopes, control.equ, labels, ... ) stackelberg( prices, quantities, margins, demand = rep("linear", length(prices)), cost = rep("linear", nrow(quantities)), isLeaderPre = matrix(FALSE, ncol = ncol(quantities), nrow = nrow(quantities)), isLeaderPost = isLeaderPre, mcfunPre = list(), mcfunPost = mcfunPre, vcfunPre = list(), vcfunPost = vcfunPre, dmcfunPre = list(), dmcfunPost = dmcfunPre, capacitiesPre = rep(Inf, nrow(quantities)), capacitiesPost = capacitiesPre, productsPre = !is.na(quantities), productsPost = productsPre, ownerPre, ownerPost, mcDelta = rep(0, nrow(quantities)), quantityStart = as.vector(quantities), control.slopes, control.equ, labels, ... )
prices |
A length k vector product prices. |
quantities |
An n x k matrix of product quantities. All quantities must either be positive, or if the product is not produced by a plant, NA. |
margins |
An n x k matrix of product margins. All margins must be either be between 0 and 1, or NA. |
demand |
A length k character vector equal to "linear" if a product's demand curve is assumed to be linear or "log" if a product's demand curve is assumed to be log-linear. |
cost |
A length n character vector equal to "linear" if a plant's marginal cost curve is assumed to be linear or "constant" if a plant's marginal curve is assumed to be constant. Returns an error if a multi-plant firm with constant marginal costs does not have capacity constraints. |
mcfunPre |
a length n list of functions that calculate a plant's pre-merger marginal cost. If empty (the default), assumes quadratic costs. |
mcfunPost |
a length n list of functions that calculate a plant's post-merger marginal cost. If empty (the default), equals ‘mcfunPre’ |
vcfunPre |
a length n list of functions that calculate a plant's pre-merger variable cost. If empty (the default), assumes quadratic variable costs. |
vcfunPost |
a length n list of functions that calculate a plant's post-merger variable cost. If empty (the default), equals ‘vcfunPre’ |
capacitiesPre |
A length n numeric vector of pre-merger plant capacities. Default is Inf. |
capacitiesPost |
A length n numeric vector of post-merger plant capacities. Default ‘capacitiesPre’. |
productsPre |
An n x k matrix that equals TRUE if pre-merger, a plant produces a product. Default is TRUE if 'quantities' is not NA. |
productsPost |
An n x k matrix that equals TRUE if post-merger, a plant produces a product. Default equals ‘productsPre’. |
ownerPre |
EITHER a vector of length n whose values indicate which plants are commonly owned pre-merger OR an n x n matrix of pre-merger ownership shares. |
ownerPost |
EITHER a vector of length n whose values indicate which plants will be commonly owned after the merger OR an n x n matrix of post-merger ownership shares. |
mktElast |
A length k vector of product elasticities. Default is a length k vector of NAs |
mcDelta |
A length n vector where each element equals the proportional change in a firm's marginal costs due to the merger. Default is 0, which assumes that the merger does not affect any products' marginal cost. |
quantityStart |
A length k vector of quantities used as the initial guess in the nonlinear equation solver. Default is ‘quantities’. |
control.slopes |
A list of |
control.equ |
A list of |
labels |
A list with 2 elements. The first element is a vector of firm names, while the second element is a vector of products names. Default is ‘O1:On’, and ‘P1:Pk’. |
... |
Additional options to feed to the solver. See below. |
isLeaderPre |
An n x k logical matrix equal to TRUE if a firm is
a "leader" pre-merger for a particular product and FALSE otherwise.
Default is FALSE, which is equivalent to |
isLeaderPost |
An n x k logical matrix equal to TRUE if a firm
is a "leader" pre-merger for a particular product and FALSE otherwise.
Default is FALSE, which is equivalent to |
dmcfunPre |
a length n list of functions that calculate the derivative of a plant's pre-merger marginal cost. If empty (the default), assumes quadratic variable costs. |
dmcfunPost |
a length n list of functions that calculate the derivative of a plant's post-merger marginal cost. If empty (the default), equals ‘mcfunPre’ |
Using price, and quantity, information for all products
in each market, as well as margin information for at least
one products in each market, cournot
is able to
recover the slopes and intercepts of either a Linear or Log-linear demand
system as well as the cost parameters (see below for further details).
These parameters are then used to simulate the price
effects of a merger between
two firms under the assumption that the firms are playing a
homogeneous products simultaneous quantity setting game.
stackelberg
, is similar to cournot
, except that for a given product,
firms are either "leaders" or "followers". leaders gain a first mover advantage
over followers, which allows the leaders to anticipate how changes to their output
will effect the follower's output decisions. Firms can be the leader for
some products but the follower in others.
‘mcfunPre’ and ‘mcfunPost’ are length n lists whose elements are ‘R’ functions
that return a firm's marginal cost. The first argument of each function should be total firm quantities.
By default, each firm is assumed to have quadratic costs with a firm-specific parameter calibrated from a firm's margin.
‘vcfunPre’ and ‘vcfunPost’ are similarly defined.
‘dmcfunPre’ and ‘dmcfunPost’ are the changes in marginal cost and are only required for stackelberg
.
‘ownerPre’ and ‘ownerPost’ values will typically be equal to either 0 (element [i,j] is not commonly owned) or 1 (element [i,j] is commonly owned), though these matrices may take on any value between 0 and 1 to account for partial ownership.
Under linear demand and linear marginal costs, an analytic solution to the Cournot quantity game
exists. However, this solution can at times produce negative
equilibrium quantities. To accommodate this issue, cournot
uses BBsolve
to
find equilibrium quantities subject to a non-negativity constraint. ...
may
be used to change the default options for BBsolve
.
cournot
returns an instance of class Cournot
.
stackelberg
returns an instance of class Stackelberg
.
Charles Taragin ctaragin+antitrustr@gmail.com
## Simulate a Cournot merger between two single-plant firms ## producing a single product in a ## 5-firm market with linear demand and quadratic costs n <- 5 #number of firms in market pre-merger cap <- rnorm(n,mean = .5, sd = .1) int <- 10 slope <- -.25 B.pre.c = matrix(slope,nrow=n,ncol=n) diag(B.pre.c) = 2* diag(B.pre.c) - 1/cap quantity.pre.c = rowSums(solve(B.pre.c) * -int) price.pre.c = int + slope * sum(quantity.pre.c) mc.pre.c = quantity.pre.c/cap vc.pre.c = quantity.pre.c^2/(2*cap) margin.pre.c = 1 - mc.pre.c/price.pre.c ps.pre.c = price.pre.c*quantity.pre.c - vc.pre.c mktQuant.pre.c = sum(quantity.pre.c) ## suppose firm 1 acquires firm 2 ## This model has a closed form solution B.post.c = B.pre.c B.post.c[1,2] = 2*B.post.c[1,2] B.post.c[2,1] = 2*B.post.c[2,1] quantity.post.c = rowSums(solve(B.post.c) * -int) price.post.c = int + slope * sum(quantity.post.c) mc.post.c = quantity.post.c/cap vc.post.c = quantity.post.c^2/(2*cap) margin.post.c = 1 - mc.post.c/price.post.c ps.post.c = price.post.c*quantity.post.c - vc.post.c mktQuant.post.c = sum(quantity.post.c, na.rm=TRUE) #check if merger is profitable for merging parties isprofitable.c = ps.post.c - ps.pre.c isprofitable.c= sum(isprofitable.c[1:2]) > 0 #prep inputs for Cournot owner.pre <- diag(n) owner.post <- owner.pre owner.post[1,2] <- owner.post[2,1] <- 1 result.c <- cournot(prices = price.pre.c,quantities = as.matrix(quantity.pre.c), margins=as.matrix(margin.pre.c), ownerPre=owner.pre,ownerPost=owner.post) print(result.c) # return predicted price change summary(result.c) # summarize merger simulation ## check if 'cournot' yields the same result as closed-form solution #print(all.equal(sum(result.c@quantityPre) , mktQuant.pre.c)) #print(all.equal(sum(result.c@quantityPost) , mktQuant.post.c)) ## Simulate a Stackelberg merger between two single-plant firms ## producing a single product in a ## 5-firm market with linear demand and quadratic costs. ## Allow both merging parties to be followers pre-merger, ## but assume that they become leaders post-merger. ## Finally, assume that pre-merger, there is a single leader who ## remains a leader post-merger ## Note: This example uses setup from the above Cournot example isLeader.pre = matrix(rep(FALSE,n), ncol=1) isLeader.pre[n,] = TRUE isLeader.post = isLeader.pre isLeader.post[1:2,] = TRUE passthru.pre = matrix(-slope^2/(2*slope - 1/cap)) passthru.post = passthru.pre passthru.pre[isLeader.pre] = 0 passthru.post[isLeader.post] = 0 B.pre.s = matrix(slope,nrow=n,ncol=n) diag(B.pre.s) = 2* diag(B.pre.s) - 1/cap diag(B.pre.s)[n] = diag(B.pre.s)[n] + sum(passthru.pre) quantity.pre.s = rowSums(solve(B.pre.s) * ( -int)) price.pre.s = int + slope * sum(quantity.pre.s) mc.pre.s = quantity.pre.s/cap vc.pre.s = quantity.pre.s^2/(2*cap) margin.pre.s = 1 - mc.pre.s/price.pre.s ps.pre.s = price.pre.s*quantity.pre.s - vc.pre.s mktQuant.pre.s = sum(quantity.pre.s) ## suppose firm 1 acquires firm 2 ## This model has a closed form solution B.post.s = matrix(slope,nrow=n,ncol=n) diag(B.post.s) = 2* diag(B.post.s) - 1/cap B.post.s[1,2] = 2*B.post.s[1,2] B.post.s[1,1:2] = B.post.s[1,1:2] + sum(passthru.post) B.post.s[2,1] = 2*B.post.s[2,1] B.post.s[2,1:2] = B.post.s[2,1:2] + sum(passthru.post) diag(B.post.s)[n] = diag(B.post.s)[n] + sum(passthru.post) quantity.post.s = rowSums(solve(B.post.s) * as.vector( -int ) ) price.post.s = int + slope * sum(quantity.post.s) mc.post.s = quantity.post.s/cap vc.post.s = quantity.post.s^2/(2*cap) margin.post.s = 1 - mc.post.s/price.post.s ps.post.s = price.post.s*quantity.post.s - vc.post.s mktQuant.post.s = sum(quantity.post.s, na.rm=TRUE) #check if merger is profitable for merging parties isprofitable.s = ps.post.s - ps.pre.s isprofitable.s = sum(isprofitable.s[1:2]) > 0 #prep inputs for Stackelberg owner.pre <- diag(n) owner.post <- owner.pre owner.post[1,2] <- owner.post[2,1] <- 1 result.s <- stackelberg(prices = price.pre.s,quantities = as.matrix(quantity.pre.s), margins=as.matrix(margin.pre.s),ownerPre=owner.pre, ownerPost=owner.post, isLeaderPre = isLeader.pre, isLeaderPost = isLeader.post) print(result.s) # return predicted price change summary(result.s) # summarize merger simulation ## check if 'stackelberg' yields the same result as closed-form solution #print(all.equal(sum(result.s@quantityPre) , mktQuant.pre.s)) #print(all.equal(sum(result.s@quantityPost) , mktQuant.post.s))
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.