by Fedor Iskhakov, ANU

Description: Application of the optional transport problem.

**“Black Market Performance: Illegal Trade in Beijing License Plates”**

by Øystein Daljord, Mandy Hu, Guillaume Pouliot, Junji Xiao

*From abstract:*

We estimate the incentives to trade in the black market for license plates that emerged following the recent rationing of new car sales in Beijing by lottery. Under weak assumptions on car preferences, we use optimal transport methods and comprehensive data on car sales to estimate that at least 12% of the quota is illegally traded.

- Measure the size of black market for license plates
- Case of Beijing license plates regulation
- Allocation by random lottery should have no effect on car sales
- In reality, there is sizable shift in distribution of cars
- Optimal transportation method is ideal to compute the lower bound on the volume of illegal trade of license plates

- Cars driving in Beijing are required to have Beijing license plates
- From Jan 2011 license plates are rationed to a quota of about 35% of the previous year’s sales
- License plates are allocated by a lottery with simple application
- A Beijing household needs a license plate before it can register a new car
- License plates are non-transferable

- From cheaper to more expensive car models
- Hard to explain if lottery is a truly random allocation of license plates to the car purchasers
- No similar shifts in sales in comparable cities without rationing policy, in the same time period
- No supply side responses to the rationing policy

Let $ \mathbb{P}_0 $ be the distribution of car sales prices from pre-lottery time, and $ \mathbb{P}_1 $ the analogous distribution post-lottery.

Under assumptions

- Pricing policy did not change between 2010 and 2011
- Demand structure did not change between 2010 and 2011
- Lottery is uniform

the sales distributions should not change from the pre- to the post lottery period, i.e. $ \mathbb{P}_0 = \mathbb{P}_1 $

Data on manufacturer suggested retail prices (MSRP) of the registered vehicles.

In [1]:

```
import pandas as pd
dt = pd.read_stata('_static/data/beijin_data.dta')
dt.dropna(inplace=True) # drop rows with nan
print('Data has %d observations and %d variables'%tuple(dt.shape)) # print expects tuple
print(dt.head(n=10))
```

In [2]:

```
print(dt['MSRP'].describe())
q99 = dt['MSRP'].quantile(0.99)
dt = dt[dt['MSRP']<q99]
print(dt['MSRP'].describe())
```

In [3]:

```
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = [12, 8]
def plot2hist(d1,d2,bins=10,labels=['1','2']):
'''Plots two overlapping histograms'''
plt.hist(d1,bins=bins,density=True,histtype='step',label=labels[0])
plt.hist(d2,bins=bins,density=True,histtype='step',label=labels[1])
plt.legend()
plt.show()
```

In [4]:

```
dt10 = dt[dt['year']==2010]['MSRP']
dt11 = dt[dt['year']==2011]['MSRP']
plot2hist(dt10,dt11,labels=['2010','2011'])
```

Linear programming problem solved by `scipy.optimize.linprog`

(equality constraints automatically converted)

- stack all $ x_{ij} $ into a single vector
- express equality constraints for origins and destinations as inequalities

https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.linprog.html

In [5]:

```
# Code up the model
```

In [6]:

```
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
# Answer below
```

In [7]:

```
N = 5 # number of bins to represent distribution
dt['gr'] = pd.qcut(dt.MSRP,q=N,labels=False) # N quantiles
gr10 = dt[dt.year==2010].groupby('gr')
gr11 = dt[dt.year==2011].groupby('gr')
d10 = gr10.MSRP.count()/dt[dt.year==2010].MSRP.count()
d11 = gr11.MSRP.count()/dt[dt.year==2011].MSRP.count()
print(d10,d11,sep='\n\n')
```

In [8]:

```
import numpy as np
# Set up transportation problem
costs = np.ones((N,N)) - np.eye(N) # costs matrix
origins = np.array(d10) # origins
destinations = np.array(d11) # destinations
plt.rcParams['figure.figsize'] = [5, 5]
plt.spy(costs)
```

Out[8]:

<matplotlib.image.AxesImage at 0x7fbd40c5e350>

In [9]:

```
# convert to linear programming problem
C = costs.reshape(N*N)
A1 = np.kron(np.eye(N),np.ones((1,N))) # sums of x for each origin
A2 = np.kron(np.ones((1,N)),np.eye(N)) # sums of x for each destination
A = np.vstack((A1,A2)) # concatenate vertically
plt.spy(A)
b = np.concatenate((origins,destinations))
```

In [10]:

```
# Solve the transportation problem
from scipy.optimize import linprog
res = linprog(c=C,A_eq=A[:-1],b_eq=b[:-1],bounds=(0,None),method='simplex')
print(res.message)
X = res.x.reshape((N,N)) # reshape back to X_ij
plt.spy(X)
print(X)
black_market_estim = 1 - np.diag(X).sum() # do not count the stationary diagonal
print('With N=%d the lower bound on black market share is %1.5f'%(N,black_market_estim))
```

- Main result: significant evidence for a sizable black market share!
- Computed the
**lower boundary**on the fraction of illegal trade (why?) - Grain of salt: this is one of possible mechanisms, need to eliminate other possible routes (see the paper)
- What robustness checks should be run? Technical parameter $ N $ clearly affects the numerical result