Analysis - FX Carry Trade vs UIP#

Notation Reminder#

  • Spot FX rate:
    \(S_t^i\) = USD price of one unit of foreign currency \(i\).

  • Log spot FX:
    \(s_t^i = \ln\bigl(S_t^i\bigr)\).

  • Risk‑free rate:
    \(r_{t,t+1}^{f,i}\) = annualized risk‑free rate for currency \(i\) over \([t,t+1]\).

  • Log risk‑free rate:
    \(\tilde r_{t,t+1}^{f,i} = \ln\bigl(1 + r_{t,t+1}^{f,i}\bigr)\).

  • Log return of FX position:
    $\( r_{t+1}^i = s_{t+1}^i - s_t^i + \tilde r_{t,t+1}^{f,i}. \)$

  • Excess log return (vs. USD):
    $\( \tilde r_{t+1}^i = \bigl(s_{t+1}^i - s_t^i\bigr) + \tilde r_{t,t+1}^{f,i} - \tilde r_{t,t+1}^{f,\mathrm{USD}}. \)$

  • \(E_t[\cdot]\) = expectation conditional on information at time \(t\).

  • \(\alpha^i,\,\beta^i\) = intercept and slope from the FX forecasting regression for currency \(i\).

  • \(R^2\) = coefficient of determination of that regression.

Data#

Use the daily data in fx_data.xlsx on risk-free rates and exchange rates.

  • Risk‑free rates: annualized, across currencies, denoted \(r^{f,i}_{t,t+1}\).

  • Exchange rates: spot FX rates \(S^i_t\), quoted directly against the USD.

Note

  • The risk-free rate data is annualized by the money-market convention of 360.

Data is in levels,

  • Risk‑free rates: daily quotes of \(r_{t,t+1}^{f,i}\).

  • Exchange rates: daily quotes of \(S_t^i\) (USD per unit).

You need to **convert to logs for the analysis that follows.

  • \(s_t^i = \ln(S_t^i)\).

  • \(\tilde r_{t,t+1}^{f,i} = \ln\bigl(1 + r_{t,t+1}^{f,i}\bigr)\).

Timing#

Timing of the risk-free rate

  • The data is defined such that the March value of the risk-free rate corresponds to the rate beginning in March and ending in April.

  • In terms of the class notation, \(r^{f,i}_{t,t+1}\) is reported at time \(t\). (It is risk-free, so it is a rate from \(t\) to \(t+1\) but it is know at \(t\).

import pandas as pd

DATAPATH_FX = '../data/fx_data.xlsx'
SHEET = 'exchange rates'

fx = pd.read_excel(DATAPATH_FX, sheet_name=SHEET).set_index('date')

SHEET = 'risk-free rates'
DAYS = 360

rf = pd.read_excel(DATAPATH_FX,sheet_name=SHEET).set_index('date')
rf /= DAYS
display(fx.tail().style.format('{:.4f}').set_caption('Exchange Rates').format_index(lambda x: x.strftime('%Y-%m-%d')))
display(rf.tail().style.format('{:.4%}').set_caption('Risk-Free Rates').format_index(lambda x: x.strftime('%Y-%m-%d')))
Exchange Rates
  JPY EUR GBP MXN CHF
date          
2025-07-14 0.0068 1.1664 1.3427 0.0534 1.2533
2025-07-15 0.0067 1.1601 1.3384 0.0531 1.2474
2025-07-16 0.0068 1.1641 1.3422 0.0534 1.2487
2025-07-17 0.0067 1.1596 1.3416 0.0533 1.2430
2025-07-18 0.0067 1.1626 1.3416 0.0533 1.2479
Risk-Free Rates
  USD JPY EUR GBP MXN CHF
date            
2025-07-14 0.0120% 0.0013% 0.0053% 0.0117% 0.0222% 0.0000%
2025-07-15 0.0121% 0.0013% 0.0053% 0.0117% 0.0222% 0.0000%
2025-07-16 0.0121% 0.0013% 0.0053% 0.0117% 0.0222% 0.0000%
2025-07-17 0.0121% 0.0013% 0.0053% 0.0117% 0.0222% 0.0000%
2025-07-18 0.0119% 0.0013% 0.0053% 0.0117% 0.0222% 0.0000%

1. The Static Carry Trade in Logs#

Log return of a long position in currency \(i\):
$\( r_{t+1}^i = s_{t+1}^i - s_t^i + \tilde r_{t,t+1}^{f,i}. \)$

Excess log return (with respect to USD):
$\( \tilde r_{t+1}^i = (s_{t+1}^i - s_t^i) + \tilde r_{t,t+1}^{f,i} - \tilde r_{t,t+1}^{f,\mathrm{USD}}. \)$

  1. Build the spread in risk-free rates:

  • Lag this variable, so that the March-to-April value is stamped as April.

\[r^{f,\$}_{t,t+1} - r^{f,i}_{t,t+1}\]
  1. Build the FX growth rates:

  • These are already stamped as April for the March-to-April FX growth.

\[ s^i_{t+1} - s^i_t\]

Then the excess log return is simply the difference of the two objects.

1.1. Static Carry Stats#

Compute (annualized) for each \(i\):

  • Mean of \(\tilde r^i\).

  • Volatility (std. dev.) of \(\tilde r^i\).

  • Sharpe ratio = mean / volatility.

Compare these statistics across currencies.

1.2. Implications for UIP#

Uncovered Interest Parity (log form) predicts $\( E_t\bigl[s_{t+1}^i - s_t^i\bigr] = \tilde r_{t,t+1}^{f,\mathrm{USD}} - \tilde r_{t,t+1}^{f,i}. \)$

  • Do any of the observed means or Sharpe ratios contradict this relation?

  • Which currency, if held long, yielded the highest Sharpe ratio?

  • Did any currency earn a negative average excess return?

2. The Evidence on UIP#

2.1. Predicting FX#

For each currency \(i\), estimate $\( s_{t+1}^i - s_t^i = \alpha^i + \beta^i\Bigl(\tilde r_{t,t+1}^{f,\mathrm{USD}} - \tilde r_{t,t+1}^{f,i}\Bigr) + \epsilon_{t+1}^i. \)$

where \(r^{f,i}\) denotes the risk‑free rate of currency \(i\), and \(s^i\) denotes the FX rate for currency \(i\).

Both \(r^{f,usd}_{t,t+1}\) and \(s^i_t\) are determined at time \(t\). Thus, this is a forecasting regression for \(s_{t+1}^i\)

Collect your regression estimates in a table of \(\alpha^i\), \(\beta^i\), and \(R^2\) for each currency.

2.2.#

If \(r_{t,t+1}^{f,i}\) rises relative to the US rate:

  • Which currencies predict a strengthening of USD (i.e.\ \(s_{t+1}^i - s_t^i < 0\))?

  • Which predict a weakening of USD?

  • For which currency is the predictive relationship strongest (largest \(|\beta^i|\) or highest \(R^2\))?

Note: \(s_{t+1}^i - s_t^i\) is the log growth of USD per unit of foreign currency, so negative values mean USD appreciation.

2.3. UIP Conclusions#

What do you conclude about the UIP?

3. The Dynamic Carry Trade#

Try implementing the forecasts with a simple proportional weighting of each forecast. Similar to the implementation in HW#7.

Timing#

We do not need to lag the forecasts with .shift() if we already use the lagged calculation of the interest rate spread.

Then, the regressor is lagged, and thus is generating forecasts stamped with the date of their targeted value, as desired.

3.1. Examining the Carry Forecasts#

Using the regression, $\( E_t\bigl[\tilde r_{t+1}^i\bigr] = \alpha^i + (\beta^i - 1)\Bigl(\tilde r_{t,t+1}^{f,\mathrm{USD}} - \tilde r_{t,t+1}^{f,i}\Bigr). \)$

  1. Compute for each \(i\) the fraction of periods with $\(E_t[\tilde r_{t+1}^i]>0.\)$

  2. Which currencies most often have a positive expected risk premium?

  3. Which most often have a negative expected premium?

  4. Discuss how to use these conditional expected premia to improve the static carry trade returns from above.

3.2.#

Consider a simple system to dynamically overweight the carry trade during periods where the forecast (derived from the regression above) is particularly encouraging.

For simplicity, set a weighting strategy where you invest…

\[w_t = 1,000 E_t\]

where \(E_t\) is shorthand for the time-\(t\) expectation of the time \(t+1\) excess return.

That is, we weight proportionally to the forecast at any given time \(t\). Thus, the position size for any given currency trade is dynamic.

Calculate the excess returns of the dynamic strategies.

3.3.#

Report the (annualized) mean, vol, and mean/vol ratio (Sharpe) for each dynamic strategy.

4. Technical Points#

4.1. Combining Multiple Trades#

Compare to the equally-weighted combination of the currency trades

Note that currencies have low cross-correlations, so we expect substantial gains to diversification.

4.2. Is the dynamic carry much different from the static carry?#

How correlated are the active (forecasted) excess returns to the passive excess returns?