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.
## 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
## V1
## 1: 0.8240617
## 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()