Introduction

The test of uncovered interest parity is the test that exchange rates are driven by capital flows (proxies by money market flows to places with the highest interest rate). If one currency has a higher interest rate than the other, flows into that currency will drive it higher until the expected deprecation is sufficient to offset the interest rate advantage.

Using the South African to US exchange rate and three month interest rates from the St. Louis Fed database for the period December 1980 to October 2025.

# Download data
da <- read.csv('./Data/SAUIP.csv')
# Change the column names
colnames(da) <- c("Date", "SA3m", "US3m", "SAUSD")
# Make the date a date object
da$Date <- as.Date(da$Date, format = "%Y-%m-%d")
# Remove the rows with no data
da <- da[complete.cases(da), ]
# Check
head(da)
##           Date     SA3m  US3m  SAUSD
## 564 1980-12-01 6.040000 15.49 0.7529
## 565 1981-01-01 6.486154 15.02 0.7481
## 566 1981-02-01 7.364167 14.79 0.7737
## 567 1981-03-01 7.543077 13.36 0.7906
## 568 1981-04-01 7.743478 13.69 0.8109
## 569 1981-05-01 8.540000 16.30 0.8380

The interest rate data are in raw percentages and are one-year equivalent. Therefore we need to adjust to the funds that you will actually receive or pay over three months.

# Create the 3 month equivalent interest rate 
da$SA3meq <- (1 + da$SA3m/100)^(1/4)
da$US3meq <- (1 + da$US3m/100)^(1/4)
# Check
head(da)
##           Date     SA3m  US3m  SAUSD   SA3meq   US3meq
## 564 1980-12-01 6.040000 15.49 0.7529 1.014770 1.036659
## 565 1981-01-01 6.486154 15.02 0.7481 1.015835 1.035603
## 566 1981-02-01 7.364167 14.79 0.7737 1.017923 1.035085
## 567 1981-03-01 7.543077 13.36 0.7906 1.018347 1.031846
## 568 1981-04-01 7.743478 13.69 0.8109 1.018821 1.032596
## 569 1981-05-01 8.540000 16.30 0.8380 1.020698 1.038472

The forward rate will be equal to

\[F_{3m, SA-USD} = \frac{3m SA}{3m US} \times \frac{ZAR}{USD}\]

# Combine three NAs because we do not have data for the first three months, 
# with the forward rate to create a vector of forward rates
da$SAUSDf <- c(rep(NA, 3), da$SA3meq[1:(length(da$SAUSD)-3)]
                                     /da$US3meq[1:(length(da$SAUSD)-3)]
               *da$SAUSD[1:(length(da$SAUSD)-3)])

Covered interest parity

Covered interest parity must hold if there are no frictions otherwise there is an immediate arbitrage. However, uncovered interest parity may make or lose money. If there is a consistent deviation, it suggests that there is an inefficiency that can be exploited.

Rational expectations would assume that foreign exchange players know the UIP model and will expect the exchange rate to equal the forward rate. Therefore if we test

\[\Delta[S_{+3m}] = \alpha + \beta E[\Delta_{3m} S_t] + \varepsilon_t\]

We could substitute the forward rate for the expected change and estimate the value of \(\beta\). UIP says that \(\beta\) should be equal to one.

\[\Delta[S_{+3m}] = \alpha + \beta [F_{3m} /S_t] + \varepsilon_t\] Calculate the 3 month percentage change in the exchange rate (\(\delta[S_{+3m}]\)) and the difference between the current exchange rate and the forward rate (or the forward premium, \(F_{3m}/S_t\).

# The actual change in the exchange rate over three months
da$FX3mret <- c(rep(NA, 3), da$SAUSD[4:length(da$SAUSD)] /
                  da$SAUSD[1:(length(da$SAUSD) - 3)] - 1)
# The expected change in the exchange rate over three months.
da$EXP3mret <- c(rep(NA, 3), da$SAUSDf[4:length(da$SAUSD)] /
                   da$SAUSD[1:(length(da$SAUSD) -3)] - 1)

Now run the regression to see if \(\beta\) is equal to one.

summary(lm(da$FX3mret ~ da$EXP3mret))
## 
## Call:
## lm(formula = da$FX3mret ~ da$EXP3mret)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.26591 -0.04339 -0.00446  0.03229  0.32590 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  0.030619   0.007345   4.168 3.58e-05 ***
## da$EXP3mret -0.679190   0.441437  -1.539    0.124    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.07692 on 534 degrees of freedom
##   (3 observations deleted due to missingness)
## Multiple R-squared:  0.004413,   Adjusted R-squared:  0.002549 
## F-statistic: 2.367 on 1 and 534 DF,  p-value: 0.1245

The null hypothesis for the summary is the usual test of whether the coefficient is equal to zero. We want to test if it is equal to one:

  • \(H0: \beta = 1\)

  • \(H1: \beta \ne 1\)

Therefore the test statistic is

\[ T = \frac{\hat{\beta} - 1}{SE} = \frac{-0.6792 - 1}{0.4414} = -3.8\]

Therefore the null hypothesis is rejected.

However, the joint hypothesis problem means that we are not sure if we are rejecting UIP or the idea that expectations are formed rationally and are represented by the forward rate.

The carry trade

One indication that UIP does not generally hold is the popularity of the carry trade whereby investors borrow in a low interet rate currency to deposit in a high interest rate currency. The theory suggest that on average, the interest rate advantage will be offset by a fall in the value of the exchange rate.

We can calculate the profit from CIP and UIP each 3 months.

# Calculate the CIP
# (SA3m * exchange rate) / (US3m * forward rate)
da$CIP <- c(rep(NA, 3), (da$SA3meq[1:(length(da$Date) -3)] *  
             da$SAUSD[1:(length(da$Date) - 3)]) 
           / (da$US3meq[1:(length(da$Date) -3)] * 
                da$SAUSDf[4:length(da$Date)]))
# Calculate UIP
# (SA3m * exchange rate) / (USD3m * actual exchange rate in 3 months)
da$UIP <- c(rep(NA, 3), (da$SA3meq[1:(length(da$Date) -3)] *  
             da$SAUSD[1:(length(da$Date) - 3)]) 
           / (da$US3meq[1:(length(da$Date) -3)] * 
                da$SAUSD[4:length(da$Date)]))
head(da)
##           Date     SA3m  US3m  SAUSD   SA3meq   US3meq    SAUSDf    FX3mret
## 564 1980-12-01 6.040000 15.49 0.7529 1.014770 1.036659        NA         NA
## 565 1981-01-01 6.486154 15.02 0.7481 1.015835 1.035603        NA         NA
## 566 1981-02-01 7.364167 14.79 0.7737 1.017923 1.035085        NA         NA
## 567 1981-03-01 7.543077 13.36 0.7906 1.018347 1.031846 0.7370019 0.05007305
## 568 1981-04-01 7.743478 13.69 0.8109 1.018821 1.032596 0.7338201 0.08394600
## 569 1981-05-01 8.540000 16.30 0.8380 1.020698 1.038472 0.7608717 0.08310715
##        EXP3mret CIP       UIP
## 564          NA  NA        NA
## 565          NA  NA        NA
## 566          NA  NA        NA
## 567 -0.02111576   1 0.9322058
## 568 -0.01908823   1 0.9049452
## 569 -0.01658048   1 0.9079614

Note that the CIP is equal to one (as expected). The costs are equal to the gains. However, UIP has an mean value of 0.9999.

hist(da$UIP, main = "Histogram of SA-USD carry returns", 
     col = 'lightblue', xlab = "Returns")

A histogram of the UIP returns also suggests that the return to the carry trade is very limited.