Calibration - continued

library(data.table)
library(fst)

wiot <- read_fst("output/wiot.fst", as.data.table = TRUE)
trade_flows <- read_fst("output/trade_flows.fst", as.data.table = TRUE)
theta <- 6.543

Let’s create some auxiliary variables to easily compute trade costs afterwards. \(\delta_{ij}^k \equiv \pi_{ij}^k / \pi_{jj}^k\). Also, let \(\text{z_ratio} = z_i^k / z_j^k\) and \(\text{w_ratio} = w_i / w_j\).

trade_flows[, `:=`(
  delta_ijk = pi_ijk / pi_jjk,
  z_ratio_ijk = z_ik / z_jk,
  w_ratio_ij = wage_i / wage_j
)]

Computing the trade costs \(d_{ij}^k\)

From equation (1) below, valid under assumptions 1 to 4 in Costinot, Donaldson, and Komunjer (2012) it’s possible to compute all values of \(d_{ij}^k\).

\[ \begin{equation} x_{ij}^k=\frac{(w_id_{ij}^k/z_i^k)^{-\theta}}{\sum_{i'}(w_{i'}d_{i'j}^k/z_{i'}^k)^{-\theta}}\cdot\alpha_j^k w_j L_j \end{equation} \]

and given the definition, \(\pi_{ij}^k\equiv x_{ij}^k / \sum_i x_{ij}^k\), we arrive at (You should prove it in your notes!):

\[ \begin{equation} \pi_{ij}^k = \frac{(w_id_{ij}^k/z_i^k)^{-\theta}}{\sum_{i'}(w_{i'}d_{i'j}^k/z_{i'}^k)^{-\theta}}. \end{equation} \]

This is a non-linear system of \(I\times I\times K\) equations to solve for each \(d_{ij}^k\). If we further impose \(d_{jj}^k=1\), then it can be easily solved for \(d_{ij}^k\) when \(i\neq j\) in terms of \(\delta_{ij}^k \equiv \pi_{ij}^k / \pi_{jj}^k\), at the cost of not matching exactly trade flows \(x_{ij}^k\), thus:

\[ \begin{equation} \delta_{ij}^k = \left(\frac{d_{ij}^k\cdot w_i/w_j}{z_i^k / z_j^k}\right)^{-\theta} \end{equation} \]

and inverting this relation for \(d_{ij}^k\) we have:

\[ \begin{equation} d_{ij}^k=\frac{\left(\delta_{ij}^k\right)^{-1/\theta}}{w_i/w_j}\cdot z_i^k/z_j^k \end{equation} \]

trade_flows[, d_ijk := ((delta_ijk)^(-1/theta))*z_ratio_ijk/w_ratio_ij]
#' Insert predicted trade flows and shares into trade_flows
trade_flows[, by = c("in_country", "out_ind"),
            Phi_jk := sum((wage_i*d_ijk / z_ik)^(-theta))]
trade_flows[, `:=`(
  pred_value = (((wage_i*d_ijk / z_ik)^(-theta))/Phi_jk)*alpha_jk*wage_j*employed_j,
  pred_pi = ((wage_i*d_ijk / z_ik)^(-theta))/Phi_jk
)]

Once we have computed trade costs, we finally have calibrated the model by inputing \(\theta\)’s value taken from the orignal article to be 6.543, revealed productivities found by means of a regression like equation (6) in session 2, shares \(\alpha_j^k\) and \(\pi_{ij}^k\) and labor force \(L_i\) are calculated (or gathered) from WIOD data, shares of world income and consequently, wages are matched such that assumption A5 holds and the last term computed is trade costs, which is a residual term and is found through equation (1) with the additional assumption, \(d_{jj}^k=1\).

Now we can check the calibration quality. We should perform some checks to see if our calculations make sense. For example, \(\hat\pi_{ij}^k\) must sum to one over \(i\), helding fixed \(j\) and \(k\). Actually, \(\hat\pi_{ij}^k\) must match exactly the ones computed from the data. Moreover, although the predicted trade flows, \(\hat x_{ij}^k\), are not guaranteed to match the observed ones, they should at least be highly correlated.

set.seed(657286)
# pi sum to one
trade_flows[, by = c("in_country", "out_ind"), sum(pred_pi)]
##       in_country out_ind V1
##    1:        AUS       1  1
##    2:        AUS       2  1
##    3:        AUS       3  1
##    4:        AUS       4  1
##    5:        AUS       5  1
##   ---                      
## 2416:        USA      51  1
## 2417:        USA      52  1
## 2418:        USA      53  1
## 2419:        USA      54  1
## 2420:        USA      55  1
# predicted pi equals actual pi
trade_flows[sample(.N, 20), .(out_country, in_country, out_ind, pred_pi, pi_ijk)]
##     out_country in_country out_ind      pred_pi       pi_ijk
##  1:         DNK        RUS      22 1.774586e-03 1.774586e-03
##  2:         IDN        LVA      26 0.000000e+00 0.000000e+00
##  3:         NOR        ITA      42 9.293128e-05 9.293128e-05
##  4:         TUR        DEU      34 1.409783e-03 1.409783e-03
##  5:         LVA        NOR      54 1.231603e-04 1.231603e-04
##  6:         IND        AUS      49          NaN 0.000000e+00
##  7:         GRC        ROU      40 4.347204e-04 4.347204e-04
##  8:         SVN        MLT       9 6.966083e-04 6.966083e-04
##  9:         RUS        NOR      37 0.000000e+00 0.000000e+00
## 10:         CYP        IND      18 1.810569e-07 1.810569e-07
## 11:         HUN        IND      25 3.539286e-06 3.539286e-06
## 12:         CHN        TWN      47          NaN 0.000000e+00
## 13:         FRA        BRA       8 1.942664e-03 1.942664e-03
## 14:         ESP        MEX      21 4.721910e-03 4.721910e-03
## 15:         NOR        NLD      11 1.292312e-02 1.292312e-02
## 16:         RUS        TUR       2 0.000000e+00 0.000000e+00
## 17:         CAN        ROU      22 5.298390e-04 5.298390e-04
## 18:         NOR        SVK      35 2.428118e-05 2.428118e-05
## 19:         BEL        SVN      52 4.646474e-04 4.646474e-04
## 20:         USA        TUR      26 1.060064e-04 1.060064e-04
# Correlations
trade_flows[, .(cor(pred_value, value, use = "complete"))]
##           V1
## 1: 0.8240617
trade_flows[, .(cor(pred_pi, pi_ijk, use = "complete"))]
##    V1
## 1:  1

As you can see above, there are some invalid values for \(\hat\pi_{ij}^k\) (i.e. NaN or Inf). This is due to the fact that some countries do not trade to each other, hence, a few \(x_{ij}^{kl}\) trade flows are zero and this may lead to either \(\pi_{ij}^k=0\) or \(\pi_{jj}^k=0\). I will leave it to you to figure out how this can be a problem and a way get around it!

Python code

# Computing trading costs
trade_flows = (trade_flows
               .assign(delta_ijk=lambda x: x['pi_ijk'] / x['pi_jjk'],
                       z_ratio_ijk=lambda x: x['z_ik'] / x['z_jk'],
                       w_ratio_ij=lambda x: x['wage_i'] / x['wage_j'])
               )
trade_flows = (trade_flows
               .assign(d_ijk=lambda x: x['delta_ijk']**(-1/theta)*x['z_ratio_ijk']/x['w_ratio_ij']))
# Insert predicted trade flows and shares into trade_flows
df = trade_flows[['in_country', 'out_ind', 'wage_i', 'd_ijk', 'z_ik']]
df['Phi_jk'] = (df['wage_i']*df['d_ijk'] / df['z_ik'])**(-theta)
df = df.groupby(['in_country', 'out_ind'], as_index=False)['Phi_jk'].agg(sum)
trade_flows = trade_flows.merge(df, on=['in_country', 'out_ind'], how='left')

# Auxilary functions


def pred_value(df):
    return (((df['wage_i']*df['d_ijk'] / df['z_ik'])**(-theta))/df['Phi_jk'])*df['alpha_jk']*df['wage_j']*df['employed_j']


def pred_pi(df):
    return ((df['wage_i']*df['d_ijk'] / df['z_ik'])**(-theta))/df['Phi_jk']


trade_flows['pred_value'] = pred_value(trade_flows)
trade_flows['pred_pi'] = pred_pi(trade_flows)

# Check pred_pi sums to one
trade_flows.groupby(['in_country', 'out_ind'])['pred_pi'].sum()
# predicted pi equals actual pi
trade_flows[ijk_cols + ['pred_pi', 'pi_ijk']].sample(20)
# Correlations
trade_flows[['pred_pi', 'pi_ijk']].corr()
trade_flows[['pred_value', 'value']].corr()

References

Costinot, Arnaud, Dave Donaldson, and Ivana Komunjer. 2012. “What Goods Do Countries Trade? A Quantitative Exploration of Ricardo’s Ideas.” The Review of Economic Studies 79 (2): 581–608.