Skip to article frontmatterSkip to article content
Contents
Wisselkoersen: risk sharing, carry, momentum, value
Maarten Nies

Wisselkoersen: risk sharing, carry, momentum, value

1Overzicht

Wat vertellen wisselkoersen over de SDF’s van twee landen? Een wisselkoers is de verhouding van die twee SDF’s, zodat gladde wisselkoersen betekenen dat marginaal nut in landen bijna gelijk op beweegt, en een renteverschil zonder bijbehorende depreciatie een risicopremie is. In dit college:

  • leiden we af dat de wisselkoersverandering het verschil is van twee log-SDF’s, en wat dat zegt over internationale risk sharing;

  • leiden we uit dezelfde identiteit de UIP-regressie van Fama af, en een carry-premie voor de munt van het land met de rustigste SDF;

  • simuleren we hoe onzeker de ondergrens voor risk sharing is als de Sharpe-ratio geschat moet worden;

  • repliceren we voor negen G10-valuta’s de Fama-regressie, de carry-portefeuilles met hun crash van 2008, de index van Brandt, Cochrane en Santa-Clara, en kort momentum en value.

Dat de wisselkoers de verhouding van twee SDF’s is, lieten Bekaert en Backus, Foresi en Telmer zien Bekaert (1996)Backus et al. (2001). Brandt, Cochrane en Santa-Clara maakten er in 2006 een meetinstrument van Brandt et al. (2006), zodat twee standaarddeviaties, die van de wisselkoers en die van de SDF, volstaan om de oude macrovraag te beantwoorden of landen hun risico delen. De uncovered interest parity (UIP, ongedekte rentepariteit: de verwachte depreciatie van een valuta is gelijk aan het renteverschil) was toen al lang verworpen, meestal met het verkeerde teken Hansen & Hodrick (1980)Fama (1984). Daardoor is de carry trade (lenen in een valuta met lage rente, beleggen in een valuta met hoge rente) winstgevend. Zo werd een verworpen theorie een vast feit waarvoor pas achteraf verklaringen werden gezocht, en bij carry ging het feit dus zuiver aan de theorie vooraf. Die verklaringen zijn consumptierisico Lustig & Verdelhan (2007), een gemeenschappelijke factor Lustig et al. (2011), volatiliteitsrisico Menkhoff et al. (2012), crashrisico Brunnermeier et al. (2008) en peso problems Burnside et al. (2011). Barroso en Santa-Clara voegden momentum en value toe en vroegen welke combinatie een belegger zou moeten aanhouden Barroso & Santa-Clara (2015).

2Intuïtie: waarom zou dit waar zijn?

Denk aan een Amerikaanse en een Zwitserse belegger. Een SDF is een lijst van waarderingen, namelijk hoeveel een extra eenheid van de eigen munt in elke toekomstige toestand waard is. Stel dat het de Amerikaanse economie in een bepaalde toestand slecht gaat, terwijl het in Zwitserland meevalt. Een dollar is dan voor de Amerikaan veel waard en een frank voor de Zwitser niet bijzonder, zodat de dollar in die toestand duurder wordt ten opzichte van de frank. De wisselkoers beweegt dus met het verschil tussen hoe hard de twee beleggers hun eigen munt nodig hebben.

Hoe sterk die samenhang moet zijn, volgt uit een telling. Om een Sharpe-ratio van een half te verklaren, moet marginaal nut in elk land met minstens de helft per jaar schommelen. De koers van de dollar tegenover de frank beweegt echter maar met ongeveer tien procent per jaar. Twee grootheden die elk met vijftig procent schommelen en waarvan het verschil met tien procent schommelt, moeten vrijwel altijd samen bewegen. Als landen hun risico’s slecht deelden, zouden wisselkoersen zeven keer zo volatiel zijn. Consumptiegroei is tussen landen toch maar matig gecorreleerd, dus ofwel meet consumptie marginaal nut slecht, ofwel zijn wisselkoersen te glad.

Bij de rente gaat het leerboek ook mis. Als de Australische rente vier procent hoger is dan de Japanse, zou de Australische dollar volgens UIP vier procent per jaar moeten dalen. In de data daalt hij gemiddeld veel minder, of stijgt hij zelfs. Een belegger die in yen leent en in Australische dollars belegt, verdient daardoor het renteverschil en houdt het meestal.

Toch is dat geen gratis geld. Hoge-rentevaluta’s horen bij landen waar weinig uit voorzorg wordt gespaard, terwijl yen en frank als toevluchtsoord dienen. In een wereldwijde paniek, zoals in oktober 2008, stijgen yen en frank en vallen de Australische en de Nieuw-Zeelandse dollar. Handelaren zeggen dat valuta’s met de trap omhoog gaan en met de lift omlaag. Een strategie die juist in de slechtste tijden verliest, draagt risico waarvoor een SDF een hoge premie vraagt. Maar als dertig jaar data geen crash bevatten, lijkt dezelfde strategie gratis geld. Dat heet een peso problem (risico dat wel in de prijzen zit maar niet in de steekproef).

Zo komen we bij risico of vergissing, een vraag die Santa-Clara zo stelt: draagt de belegger risico waarvoor een premie wordt betaald, of denkt hij iets te weten wat de prijs niet weet Santa-Clara (2026)? Als het risico is, verwachten we twee dingen. De munt van het land met het rustigste marginale nut heeft de hoogste rente en levert een premie op, en die premie gaat juist in crises verloren, zodat het carry-rendement links scheef verdeeld is.

3Toy-voorbeeld: twee landen, twee toestanden

Eerst laden we de bibliotheken die het hele college gebruikt.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm

import hap
from hap import data as hap_data
hap.plotting.setup()

rng = np.random.default_rng(20240101)

Opzet. Er zijn twee toestanden op t+1t+1, elk met kans 12\tfrac12. De Amerikaanse SDF mm waardeert payoffs in dollars en de Zwitserse SDF m∗m^* payoffs in franken:

toestandkansmm (dollar)m∗m^* (frank)
goed0{,}50{,}800{,}88
slecht0{,}51{,}201{,}08

Het recept. Laat StS_t de dollarprijs van één frank zijn. De wisselkoers is de verhouding van de twee SDF’s, zodat St+1/St=m∗/mS_{t+1}/S_t = m^*/m in elke toestand. Dat is de enige formule die de theorie pas later afleidt, want de premieformule in stap 5 kennen we al en de index in stap 6 is een definitie.

  1. Rentes. Rf=1/E[m]=1/1,00=1,00R^f = 1/\E[m] = 1/1{,}00 = 1{,}00 en Rf∗=1/E[m∗]=1/0,98=1,0204R^{f*} = 1/\E[m^*] = 1/0{,}98 = 1{,}0204 (RfR^f staat in dit college kortheidshalve voor het bruto risicovrije rendement, 1+Rf1 + R^f in de notatie van de setup). De Zwitserse E[m∗]\E[m^*] is hier lager gekozen, zodat het land met de rustigere SDF ook de hogere rente heeft. Of dat in het algemeen zo is, bepaalt in de theorie de parameter bb.

  2. Wisselkoers. St+1/StS_{t+1}/S_t is 0,88/0,80=1,100{,}88/0{,}80 = 1{,}10 in de goede en 1,08/1,20=0,901{,}08/1{,}20 = 0{,}90 in de slechte toestand, dus de frank stijgt als het goed gaat en daalt als het slecht gaat.

  3. Controle. Een dollar in de frankobligatie levert Rf∗St+1/StR^{f*}S_{t+1}/S_t op, dat is 1,12241{,}1224 of 0,91840{,}9184 dollar. De Amerikaanse SDF waardeert dat op 12(0,80⋅1,1224+1,20⋅0,9184)=1,0000\tfrac12(0{,}80 \cdot 1{,}1224 + 1{,}20 \cdot 0{,}9184) = 1{,}0000 dollar.

  4. UIP en carry. De frank stijgt gemiddeld niet, want 12(1,10+0,90)=1,00\tfrac12(1{,}10 + 0{,}90) = 1{,}00, terwijl UIP een daling tot Rf/Rf∗=0,98R^f/R^{f*} = 0{,}98 voorspelt. Een dollar lenen en in de frankobligatie beleggen levert daardoor +12,24%+12{,}24\% of −8,16%-8{,}16\% op, gemiddeld +2,04%+2{,}04\%.

  5. Premie. Een premie is min de covariantie met mm, gedeeld door E[m]\E[m]. De afwijkingen zijn ∓0,20\mp 0{,}20 voor mm en ±0,102\pm 0{,}102 voor het carry-rendement, zodat Cov⁡=−0,0204\Cov = -0{,}0204 en de premie 0,02040{,}0204 is, het hele renteverschil.

  6. Risk sharing. Omdat Δs=log⁡m∗−log⁡m\Delta s = \log m^* - \log m, is Var⁡(Δs)\Var(\Delta s) de som van de twee log-SDF-varianties min twee keer hun covariantie. Brandt, Cochrane en Santa-Clara definiëren de risk-sharing-index als het deel van die som dat de covariantie wegwerkt. Met standaarddeviaties 0,20270{,}2027, 0,10240{,}1024 en 0,10030{,}1003 is dat 1−0,01007/(0,04110+0,01049)=0,80481 - 0{,}01007/(0{,}04110 + 0{,}01049) = 0{,}8048.

De twee log-SDF’s zijn hier perfect gecorreleerd, maar de index blijft onder één omdat hij ook een verschil in grootte bestraft. De cel hieronder rekent dezelfde getallen na.

prob = np.array([0.5, 0.5])
m_home = np.array([0.80, 1.20])        # US SDF, values dollar payoffs
m_foreign = np.array([0.88, 1.08])     # Swiss SDF, values franc payoffs


def pvar(x):
    """Population variance under the state probabilities."""
    return prob @ (x - prob @ x) ** 2


Rf, Rf_star = 1 / (prob @ m_home), 1 / (prob @ m_foreign)
fx_growth = m_foreign / m_home                          # S_{t+1} / S_t
carry_payoff = Rf_star * fx_growth                      # dollars per dollar in the franc bill
carry_excess = carry_payoff - Rf
log_m, log_m_star, ds_toy = np.log(m_home), np.log(m_foreign), np.log(fx_growth)

code = pd.Series({
    "R^f": Rf, "R^f*": Rf_star,
    "S'/S goed": fx_growth[0], "S'/S slecht": fx_growth[1],
    "prijs frankbelegging": prob @ (m_home * carry_payoff),
    "E[S'/S]": prob @ fx_growth, "UIP-voorspelling R^f/R^f*": Rf / Rf_star,
    "carry goed": carry_excess[0], "carry slecht": carry_excess[1], "E[carry]": prob @ carry_excess,
    "SD log m": np.sqrt(pvar(log_m)), "SD log m*": np.sqrt(pvar(log_m_star)),
    "SD ds": np.sqrt(pvar(ds_toy)),
    "risk-sharing-index": 1 - pvar(ds_toy) / (pvar(log_m) + pvar(log_m_star)),
})
hand = pd.Series([1.00, 1.0204, 1.10, 0.90, 1.00, 1.00, 0.98, 0.1224, -0.0816, 0.0204,
                  0.2027, 0.1024, 0.1003, 0.8048], index=code.index)
pd.DataFrame({"met de hand": hand, "code": code}).round(4)
Loading...

De twee kolommen zijn gelijk. Een frank die in slechte tijden daalt, is voor een Amerikaan dus riskant en levert het hele renteverschil als premie op. Een wisselkoers die met tien procent schommelt, geeft naast SDF’s van tien en twintig procent al een index van 0,8048.

4Theorie

De theorie volgt uit één identiteit, namelijk dat de wisselkoers de verhouding van twee SDF’s is. Daaruit volgen twee voorspellingen. Bij gladde wisselkoersen moeten de SDF’s van landen sterk samenbewegen, en de munt van een land met rustig marginaal nut levert een premie op. Daarna zien we hoe de UIP-regressie die premie meet, en wat de literatuur over carry, crashes, momentum en value vond.

4.1Opzet en notatie

Het binnenland is de VS, en StS_t is de dollarprijs van één eenheid buitenlandse munt. Met st=log⁡Sts_t = \log S_t betekent een positieve Δst+1\Delta s_{t+1} dat de buitenlandse munt stijgt, en bij de G10-valuta’s schommelt Δs\Delta s met zeven tot twaalf procent per jaar. De SDF mt+1m_{t+1} waardeert dollarpayoffs en mt+1∗m^*_{t+1} payoffs in buitenlandse munt, waarbij de ster “buitenland” betekent en niet “optimaal”. De log risicovrije rentes iti_t en it∗i^*_t voldoen aan eit=1/Et[mt+1]e^{i_t} = 1/\E_t[m_{t+1}] en eit∗=1/Et[mt+1∗]e^{i^*_t} = 1/\E_t[m^*_{t+1}]. Wie dollars leent en één periode in de buitenlandse obligatie belegt, verdient het log overrendement

rxt+1=it∗−it+Δst+1.rx_{t+1} = i^*_t - i_t + \Delta s_{t+1} .

Dat rendement is het renteverschil plus de koerswinst op de buitenlandse munt. Het is nul als de munt precies zoveel daalt als het renteverschil, en in het toy-voorbeeld was het renteverschil ongeveer twee procent en de koerswinst plus of min tien procent.

4.2De wisselkoers als verhouding van twee SDF’s

Zodra de twee SDF’s vastliggen, ligt ook de wisselkoersverandering vast, want die is hun verhouding. Een Amerikaan kan een buitenlandse payoff kopen door dollars om te wisselen en de opbrengst later terug te wisselen. Voor hem is dat een dollarpayoff maal de wisselkoersverandering, en zijn eigen SDF moet die goed waarderen. Daardoor is mm maal de wisselkoersverandering een geldige buitenlandse SDF. Als er maar één buitenlandse SDF is, moet het deze zijn.

De buitenlandse munt stijgt dus in precies die toestanden waarin marginaal nut in het buitenland hoog is ten opzichte van thuis. Bij onvolledige markten is mt+1St+1/Stm_{t+1}S_{t+1}/S_t nog steeds een geldige buitenlandse SDF, zodat de rest van de theorie ook dan bruikbaar is. Met de twee SDF’s liggen ook de rentes vast, want it−it∗=log⁡Et[mt+1∗]−log⁡Et[mt+1]i_t - i^*_t = \log\E_t[m^*_{t+1}] - \log\E_t[m_{t+1}].

4.3Hoe glad mogen wisselkoersen zijn?

Hoe sterk moeten de SDF’s van twee landen samenbewegen als de wisselkoers maar met tien procent per jaar schommelt? De variantie van een verschil is de som van de varianties min twee keer de covariantie. Links in (2) staat iets kleins en rechts het verschil van twee zeer volatiele grootheden, zodat alleen een grote covariantie dat verschil kan wegwerken.

Proof 2

De eerste vergelijking is de variantie van log⁡m∗−log⁡m\log m^* - \log m. De tweede volgt door beide kanten te delen door Var⁡(log⁡m)+Var⁡(log⁡m∗)\Var(\log m) + \Var(\log m^*). □\square

De index is één als de twee log-SDF’s gelijk zijn en nul als ze ongecorreleerd zijn. Omdat we de SDF’s niet waarnemen, hebben we een ondergrens nodig. Als beide log-SDF’s een standaarddeviatie van minstens aa hebben, geldt

Corr⁡(log⁡m,log⁡m∗)  ≥  1−Var⁡(Δs)2a2.\Corr(\log m, \log m^*) \;\geq\; 1 - \frac{\Var(\Delta s)}{2a^2}.

Dezelfde uitdrukking begrenst ook de index, omdat de noemer Var⁡(log⁡m)+Var⁡(log⁡m∗)\Var(\log m) + \Var(\log m^*) minstens 2a22a^2 is. Bij SD⁡(log⁡m)=SD⁡(log⁡m∗)=a\SD(\log m) = \SD(\log m^*) = a vallen index, correlatie en grens samen. Het toy-voorbeeld laat zien dat ze daarbuiten verschillen, want daar is de correlatie één en de index 0,8048. Vanaf hier heet 1−Var⁡(Δs)/(2a2)1 - \Var(\Delta s)/(2a^2) kortweg de grens. Die stijgt met aa en daalt met de wisselkoersvariantie, zoals de tweede oefening laat zien.

De waarde van aa komt uit de Hansen-Jagannathan-grens (5), die zegt dat SD⁡(m)/E[m]\SD(m)/\E[m] minstens gelijk is aan de hoogste Sharpe-ratio. Die grens gaat over het niveau van mm, en als mm lognormaal is met log-standaarddeviatie σ\sigma, is SD⁡(m)/E[m]=eσ2−1\SD(m)/\E[m] = \sqrt{e^{\sigma^2} - 1}. Daaruit volgt

SD⁡(log⁡m)  ≥  a=log⁡(1+SR2),\SD(\log m) \;\geq\; a = \sqrt{\log\left(1 + \mathrm{SR}^2\right)} ,

zodat een hogere Sharpe-ratio een volatielere SDF vraagt, met a=0,47a = 0{,}47 bij een Sharpe-ratio van een half.

Brandt, Cochrane en Santa-Clara rekenden met ronde getallen. Een wisselkoersvolatiliteit van 10% en een SDF-volatiliteit van 50% geven een grens van 1−0,12/(2⋅0,52)=0,981 - 0{,}1^2/(2 \cdot 0{,}5^2) = 0{,}98, en zonder risk sharing zou de wisselkoers met 2⋅0,5=71%\sqrt{2} \cdot 0{,}5 = 71\% moeten schommelen. Hun eigen schattingen voor de VS tegenover Engeland, Duitsland en Japan bevestigen die orde van grootte, met wisselkoersvolatiliteiten van 11,5 tot 12,9% (tabel

  1. en ondergrenzen voor de index van 0,98 of hoger (tabel 2). De telling uit de intuïtie komt dus uit, want de SDF’s van landen bewegen bijna perfect samen.

Tegenover die 0,98 staan consumptiedata. Consumptiegroei is tussen landen maar matig gecorreleerd, en reële wisselkoersen bewegen nauwelijks met relatieve consumptie Backus & Smith (1993). Welke kant het mis heeft, zegt de grens niet.

4.4Gedekte en ongedekte rentepariteit

Een gedekte valutabelegging moet de dollarrente opleveren, maar over de verwachte wisselkoers zegt arbitrage niets. Wie dollars in franken wisselt, frankrente ontvangt en de franken op termijn terugverkoopt, heeft een risicovrije dollarbelegging gebouwd. Laat FtF_t de termijnkoers zijn en ft=log⁡Ftf_t = \log F_t. Eén dollar levert dan eite^{i_t} op, of eit∗Ft/Ste^{i^*_t}F_t/S_t via de gedekte frankbelegging. Omdat arbitrage niet mag bestaan, geldt dan covered interest parity (CIP, gedekte rentepariteit):

ft−st=it−it∗,rxt+1=st+1−ft.f_t - s_t = i_t - i^*_t , \qquad rx_{t+1} = s_{t+1} - f_t .

De termijnpremie is dus gelijk aan het renteverschil, en het carry-rendement is de koers op t+1t+1 min de termijnkoers. UIP voegt daar de hypothese aan toe dat Et[Δst+1]=it−it∗\E_t[\Delta s_{t+1}] = i_t - i^*_t, oftewel Et[rxt+1]=0\E_t[rx_{t+1}] = 0, zodat valutarisico geen premie krijgt. De standaardtoets is de regressie

Δst+1=α+β (ft−st)+εt+1=α+β (it−it∗)+εt+1.\Delta s_{t+1} = \alpha + \beta\,(f_t - s_t) + \varepsilon_{t+1} = \alpha + \beta\,(i_t - i^*_t) + \varepsilon_{t+1}.

Onder UIP zijn α=0\alpha = 0 en β=1\beta = 1, zodat een renteverschil van één procentpunt een verwachte depreciatie van één procentpunt geeft. Hansen en Hodrick Hansen & Hodrick (1980) toetsten of de termijnkoers een zuivere voorspeller is, met de standaardfouten voor overlappende waarnemingen uit Voorspelbaarheid van rendementen. Fama Fama (1984) vond hellingen onder nul. In het overzicht van Engel Engel (1996) is de zuiverheid van de termijnkoers in de periode van zwevende koersen verworpen, en Froot en Thaler namen het resultaat op in hun reeks over anomalieën Froot & Thaler (1990).

4.5De Fama-decompositie

Een negatieve helling in (7) zegt iets over de risicopremie, zonder dat we een model van die premie nodig hebben. Het renteverschil is de som van een verwachte depreciatie en een premie, en de helling meet hoe sterk de verwachte depreciatie met die som meebeweegt. Is de helling negatief, dan moet de premie harder bewegen dan de verwachte depreciatie en er tegenin gaan. Definieer daarom qt=Et[Δst+1]q_t = \E_t[\Delta s_{t+1}] en pt=ft−Et[st+1]=−Et[rxt+1]p_t = f_t - \E_t[s_{t+1}] = -\E_t[rx_{t+1}], zodat ft−st=pt+qtf_t - s_t = p_t + q_t. Net als bij Fama staat ptp_t dus voor de premie.

Proof 3

Schrijf Δst+1=qt+ut+1\Delta s_{t+1} = q_t + u_{t+1} met Et[ut+1]=0\E_t[u_{t+1}] = 0, zodat uu ongecorreleerd is met pt+qtp_t + q_t. Dan is β=Cov⁡(q,p+q)/Var⁡(p+q)\beta = \Cov(q, p+q)/\Var(p+q), en dat is (8). Gevolg 1. De noemer is positief, dus β<0\beta < 0 precies als Var⁡(q)+Cov⁡(p,q)<0\Var(q) + \Cov(p,q) < 0. Gevolg 2. β<12\beta < \tfrac12 geldt precies als 2Var⁡(q)+2Cov⁡(p,q)<Var⁡(p)+Var⁡(q)+2Cov⁡(p,q)2\Var(q) + 2\Cov(p,q) < \Var(p) + \Var(q) + 2\Cov(p,q), dus als Var⁡(q)<Var⁡(p)\Var(q) < \Var(p). Gevolg 3. Omdat rx=(i∗−i)+Δsrx = (i^* - i) + \Delta s en de helling van Δs\Delta s op i∗−ii^* - i gelijk is aan −β-\beta, is de helling van rxrx op i∗−ii^* - i gelijk aan 1−β1 - \beta. □\square

Om de eerste twee gevolgen staat het artikel van Fama bekend, en het derde vertaalt de helling naar beleggen. Bij β=1\beta = 1 verdient carry niets voorspelbaars en bij β=0\beta = 0 het renteverschil. Bij β=−1\beta = -1 verdient carry het dubbele, omdat de hoge-rentevaluta er dan ook nog bij stijgt. De gepoolde schatting in de replicatie ligt met −0,62-0{,}62 tussen β=0\beta = 0 en β=−1\beta = -1.

4.6Carry als risicopremie in een lognormaal model

In een lognormaal model levert de munt van het land met de rustigste SDF een premie op. Een land waar marginaal nut sterk schommelt, spaart uit voorzorg en heeft daardoor een lage rente. Zijn munt wordt bovendien duur precies wanneer marginaal nut daar hoog is. Een belegger die zo’n munt aanhoudt, heeft dus een verzekering en betaalt ervoor, terwijl de munt van een land met rustig marginaal nut een premie oplevert. Laat (log⁡mt+1,log⁡mt+1∗)(\log m_{t+1}, \log m^*_{t+1}) conditioneel normaal zijn met varianties vtv_t en vt∗v^*_t en covariantie ctc_t. In het toy-voorbeeld zijn de varianties 0,04110{,}0411 en 0,01050{,}0105.

Proof 4

Onder normaliteit is Et[m]=exp⁡(Et[log⁡m]+12vt)\E_t[m] = \exp(\E_t[\log m] + \tfrac12 v_t), zodat it=−Et[log⁡mt+1]−12vti_t = -\E_t[\log m_{t+1}] - \tfrac12 v_t, en hetzelfde geldt in het buitenland. Met (2) is dan Et[rx]=i∗−i+Et[log⁡m∗]−Et[log⁡m]=12(v−v∗)\E_t[rx] = i^* - i + \E_t[\log m^*] - \E_t[\log m] = \tfrac12(v - v^*). Omdat rxrx conditioneel normaal is met variantie v+v∗−2cv + v^* - 2c, is log⁡Et[erx]=12(v−v∗)+12(v+v∗−2c)=v−c\log\E_t[e^{rx}] = \tfrac12(v - v^*) + \tfrac12(v + v^* - 2c) = v - c, en Cov⁡t(log⁡m,log⁡m∗−log⁡m)=c−v\Cov_t(\log m, \log m^* - \log m) = c - v. □\square

Een Amerikaan verdient dus een premie op de munt van een land met een minder volatiele SDF. In het toy-voorbeeld is 12(v−v∗)=12(0,04110−0,01049)=0,0153\tfrac12(v - v^*) = \tfrac12(0{,}04110 - 0{,}01049) = 0{,}0153, dicht bij de exacte log-premie log⁡1,0204+E[Δs]=0,0202−0,0050=0,0152\log 1{,}0204 + \E[\Delta s] = 0{,}0202 - 0{,}0050 = 0{,}0152. Het teken uit de intuïtie klopt dus. Of die munt ook de hogere rente heeft, hangt af van hoe de rente met de variantie beweegt, en de parameter bb hieronder meet precies dat.

Proof 5

Nu is it−it∗=b(vt−vt∗)i_t - i^*_t = b(v_t - v^*_t) en Et[Δs]=(b+12)(vt−vt∗)\E_t[\Delta s] = (b + \tfrac12)(v_t - v^*_t). De verwachte depreciatie is dus een vast veelvoud (b+12)/b(b + \tfrac12)/b van het renteverschil. □\square

Een negatieve helling vraagt dus een rente die daalt met de SDF-variantie, maar niet te hard. Daar hangt een prijs aan. Volgens Backus, Foresi en Telmer Backus et al. (2001) vraagt de anomalie in affiene modellen asymmetrische landen of rentes die met positieve kans negatief worden, en in het model hierboven wordt iti_t met b<0b < 0 en een onbegrensde vtv_t inderdaad vroeg of laat negatief. Bekaert Bekaert (1996) vond het spiegelbeeld: zelfs zijn meest complexe model leverde geen voldoende variabele premies zonder te volatiele wisselkoersen.

4.7Carry-portefeuilles en een gemeenschappelijke factor

Als valuta’s verschillen in hun gevoeligheid voor een gemeenschappelijke SDF, ligt het voor de hand om ze op renteverschil te sorteren, zoals aandelen in Fama-French 1992/1993. Lustig en Verdelhan Lustig & Verdelhan (2007) deden dat vanaf 1953 met acht portefeuilles op jaardata. Ze vonden een verschil van tot vijf procentpunt per jaar tussen lage en hoge rente, dat ze met consumptiegroeirisico verklaarden, maar wel bij een risicoaversie rond 100.

Lustig, Roussanov en Verdelhan Lustig et al. (2011) zochten de factor in de rendementen zelf. Met zes portefeuilles uit 37 valuta’s over 1983–2008 haalde het verschil tussen hoge- en lage-rentevaluta na kosten een Sharpe-ratio van 0,54 per jaar. Hun factor HMLFX_{FX}, de portefeuille met de hoogste rente min die met de laagste, verklaart ongeveer 70% van de verschillen in gemiddeld rendement.

Menkhoff, Sarno, Schmeling en Schrimpf Menkhoff et al. (2012) vonden dat hoge-rentevaluta’s verliezen als de wereldwijde valutavolatiliteit onverwacht stijgt. Die volatiliteit verklaart meer dan 90% van de verschillen tussen vijf carry-portefeuilles, zodat de carry trade volatiliteitsverzekering verkoopt, net als de strategieën uit Opties en crashrisico.

4.8Crashrisico en peso problems

Als slechte toestanden zeldzaam en extreem zijn, zit het risico niet in de standaarddeviatie maar in de staart. Neem een overrendement per maand r=μ+σε+JBr = \mu + \sigma\varepsilon + JB, met ε∼N(0,1)\varepsilon \sim N(0,1), een sprong J<0J < 0 en een BB die met kans π\pi gelijk is aan één, alle onafhankelijk. Dan is

E[r]=μ+πJ,E[(r−Er)3]=π(1−π)(1−2π) J3<0  (π<12),Pr⁡(geen sprong in T)=(1−π)T.\E[r] = \mu + \pi J, \qquad \E\big[(r - \E r)^3\big] = \pi(1-\pi)(1-2\pi)\,J^3 < 0 \ \ (\pi < \tfrac12), \qquad \Pr(\text{geen sprong in } T) = (1-\pi)^T .

Het gemiddelde daalt met de verwachte sprong, en de scheefheid is negatief zolang crashes zeldzaam zijn, omdat alleen de sprongterm een derde moment heeft. De kans op een steekproef zonder crash daalt exponentieel met de lengte TT. In zo’n steekproef is de verdeling normaal, zodat het gemiddelde dan niet E[r]\E[r] schat maar μ=E[r]+π∣J∣\mu = \E[r] + \pi|J|.

Brunnermeier, Nagel en Pedersen Brunnermeier et al. (2008) vonden met dagdata voor acht valuta’s over 1986–2006 een R2R^2 van 81% tussen gemiddelde scheefheid en gemiddeld renteverschil (hun figuur 2). Zij verklaren crashes uit het plotseling afbouwen van carry-posities als financieringsliquiditeit opdroogt, het mechanisme van VaR, RiskMetrics en LTCM.

Burnside en coauteurs Burnside et al. (2011) vroegen of een peso problem de winst verklaart. Over 1976 tot 2009 had hun gelijkgewogen carry-portefeuille van twintig valuta’s een Sharpe-ratio van 0,911 (tabel 2). Volgens hen is er een peso problem, maar heeft de zeldzame toestand vooral een zeer hoge SDF en geen zeer groot verlies. De peso-simulatie aan het eind van de Simulatie laat zien waarom sprongen in het rendement alleen niet genoeg zijn.

4.9Momentum en value in valuta

Carry is niet het enige kenmerk dat valutarendementen voorspelt. In een tweede artikel vonden Menkhoff en coauteurs Menkhoff et al. (2012) een verschil van tot 10% per jaar tussen valuta’s die in het verleden wonnen en valuta’s die verloren. Asness, Moskowitz en Pedersen Asness et al. (2013) namen valuta’s op in hun acht markten (Jegadeesh-Titman, Carhart en momentum crashes), met als value-signaal minus de verandering van de reële wisselkoers (de afwijking van koopkrachtpariteit) over vijf jaar. Over 1979–2011 hadden hun valutafactoren voor value en momentum Sharpe-ratio’s van 0,44 en 0,32 (tabel I).

Barroso en Santa-Clara Barroso & Santa-Clara (2015) schatten portefeuillegewichten als functie van gestandaardiseerde kenmerken, met de techniek van Brandt, Santa-Clara en Valkanov Brandt et al. (2009). Volgens hen dragen carry, momentum, value en reversal bij, terwijl de reële wisselkoers en de lopende rekening dat niet doen. Valuta verhoogde de Sharpe-ratio van hun portefeuilles gemiddeld met een half, terwijl het crashrisico daalde.

5Simulatie: de grens met een geschatte Sharpe-ratio

Hoe onzeker is de grens als de Sharpe-ratio uit de data geschat moet worden? De grens gebruikt een goed gemeten tweede moment, de wisselkoersvolatiliteit, en een slecht gemeten Sharpe-ratio.

We nemen een ware Sharpe-ratio van een half, een aandelenvolatiliteit van 16% en een wisselkoersvolatiliteit van 10%, zoals die van Δs\Delta s in het toy-voorbeeld. De aandelenvolatiliteit bepaalt hoe ver het geschatte gemiddelde, en daarmee de geschatte Sharpe-ratio, van de ware waarde afligt. De ware grens is dan 1−0,01/(2log⁡1,25)=0,9781 - 0{,}01/(2\log 1{,}25) = 0{,}978. Per steekproef van TT jaar maanddata trekken we een normaal steekproefgemiddelde en een geschaalde χ2\chi^2-variantie, omdat de maandrendementen onafhankelijk en normaal verdeeld zijn.

SR_TRUE, VOL_EQ, VOL_FX, N_SIM = 0.5, 0.16, 0.10, 100_000


def implied_corr(sharpe, vol_fx):
    """Lower bound on Corr(log m, log m*) with both SDF log-vols at the lognormal HJ bound."""
    a2 = np.log1p(np.asarray(sharpe) ** 2)
    return 1 - vol_fx**2 / (2 * a2)


rho_true = implied_corr(SR_TRUE, VOL_FX)
bcs_draws, bcs_rows = {}, {}
for years in (30, 50, 100):
    T = 12 * years
    mean_eq = rng.normal(SR_TRUE * VOL_EQ / 12, VOL_EQ / np.sqrt(12 * T), N_SIM)
    var_eq = VOL_EQ**2 / 12 * rng.chisquare(T - 1, N_SIM) / (T - 1)
    var_fx = VOL_FX**2 / 12 * rng.chisquare(T - 1, N_SIM) / (T - 1)
    sr_hat = np.sqrt(12) * mean_eq / np.sqrt(var_eq)
    vol_fx_hat = np.sqrt(12 * var_fx)
    rho_hat = implied_corr(sr_hat, vol_fx_hat)
    bcs_draws[years] = rho_hat
    bcs_rows[f"{years} jaar"] = {
        "Sharpe-ratio 5%": np.percentile(sr_hat, 5), "Sharpe-ratio 95%": np.percentile(sr_hat, 95),
        "vol. wisselkoers 5%": np.percentile(vol_fx_hat, 5),
        "vol. wisselkoers 95%": np.percentile(vol_fx_hat, 95),
        "grens 5%": np.percentile(rho_hat, 5), "grens mediaan": np.median(rho_hat),
        "P(grens < 0,9)": np.mean(rho_hat < 0.9), "P(grens < 0)": np.mean(rho_hat < 0),
    }
print(f"ware ondergrens voor de correlatie: {rho_true:.3f}")
pd.DataFrame(bcs_rows).T.round(3)
ware ondergrens voor de correlatie: 0.978
Loading...

De mediaan van de geschatte grens ligt op de ware waarde, en de wisselkoersvolatiliteit is nauwelijks onzeker, want bij dertig jaar ligt ze met 90% kans tussen 9,4 en 10,6%. In de figuur gaat het om de linkerstaart, die langer wordt naarmate de steekproef korter is.

Source
fig, ax = plt.subplots()
bins = np.linspace(0.5, 1.0, 101)
for k, (years, draws) in enumerate(bcs_draws.items()):
    ax.hist(np.clip(draws, 0.5, 1.0), bins=bins, histtype="step", lw=1.6, density=True,
            color=hap.plotting.COLORS[k], label=f"{years} jaar maanddata")
ax.axvline(rho_true, color="black", ls="--", lw=1, label="ware ondergrens")
ax.set_xlabel("Geschatte ondergrens voor Corr(log m, log m*) (afgekapt op 0,5)")
ax.set_ylabel("Dichtheid")
ax.set_title("De grens voor risk sharing als de Sharpe-ratio geschat moet worden")
ax.legend(loc="upper left")
plt.show()
<Figure size 990x550 with 1 Axes>
<Figure size 990x550 with 1 Axes>

Figure 1:De verdeling van de geschatte ondergrens voor de SDF-correlatie. De massa ligt dicht bij de ware waarde, omdat de grens ongevoelig is voor de SDF-volatiliteit zolang die groot is ten opzichte van de wisselkoers. De linkerstaart komt van steekproeven waarin de Sharpe-ratio toevallig laag uitvalt.

Ook met dertig jaar data valt de grens in 93% van de steekproeven boven de 0,9. De onzekerheid zit in de Sharpe-ratio, en de grens is daar sterk niet-lineair in. Een Sharpe-ratio van 0,2, bij dertig jaar ongeveer het 5%-kwantiel, geeft nog een grens van 0,87. Bij een Sharpe-ratio van 0,1 zakt de grens naar 0,50, en onder 0,07 wordt hij negatief. De puzzel verdwijnt dus pas als de ware Sharpe-ratio veel lager is dan we denken, net als bij de aandelenpremie.

6Replicatie op echte data

6.1De data

We laden de spotkoersen op maandeinde en de korte rentes, en berekenen per valuta het renteverschil en het carry-rendement van de maand erna.

FX_CODES = {  # FRED id, True if quoted as USD per foreign unit
    "GBP": ("DEXUSUK", True), "JPY": ("DEXJPUS", False), "CHF": ("DEXSZUS", False),
    "CAD": ("DEXCAUS", False), "AUD": ("DEXUSAL", True), "NZD": ("DEXUSNZ", True),
    "NOK": ("DEXNOUS", False), "SEK": ("DEXSDUS", False), "EUR": ("DEXUSEU", True),
}
CURRENCIES = list(FX_CODES)
MONTHS = pd.date_range("1976-01-31", "2025-12-31", freq="ME")


def fred_month_end(code):
    """Last available observation of each month."""
    return hap_data.fred(code)[code].dropna().resample("ME").last()


def fred_rate(code):
    """Monthly OECD short rate as a decimal per year, stamped at month end."""
    return hap_data.fred(code)[code].dropna().resample("ME").mean() / 100


log_spot = pd.DataFrame(
    {c: (1 if usd_per_unit else -1) * np.log(fred_month_end(code)) for c, (code, usd_per_unit) in FX_CODES.items()}
).reindex(MONTHS)

rates = pd.DataFrame({
    "USD": fred_rate("IR3TIB01USM156N"),
    "GBP": fred_rate("IR3TIB01GBM156N"),
    "JPY": fred_rate("IR3TCD01JPM156N").loc[:"2002-03"].combine_first(fred_rate("IR3TIB01JPM156N")),
    "CHF": fred_rate("IRSTCI01CHM156N").loc[:"1999-06"].combine_first(fred_rate("IR3TIB01CHM156N")),
    "CAD": fred_rate("IR3TIB01CAM156N"),
    "AUD": fred_rate("IR3TIB01AUM156N"),
    "NZD": fred_rate("IR3TIB01NZM156N"),
    "NOK": fred_rate("IR3TIB01NOM156N"),
    "SEK": fred_rate("IR3TIB01SEM156N"),
    "EUR": fred_rate("IR3TIB01DEM156N").loc["1999":],
}).reindex(MONTHS)

rate_diff = rates[CURRENCIES].sub(rates["USD"], axis=0) / 12    # i*_t - i_t per month, known at t
ds_next = log_spot.diff().shift(-1)                               # Delta s_{t+1}, stored at t
rx_next = (rate_diff + ds_next).where(ds_next.notna())            # carry excess return t -> t+1, stored at t

pd.DataFrame({
    "eerste maand": rx_next.apply(lambda x: x.first_valid_index()).dt.strftime("%Y-%m"),
    "maanden": rx_next.notna().sum(),
    "gem. renteverschil (%/jr)": 1200 * rate_diff.mean(),
    "vol. wisselkoers (%/jr)": 100 * np.sqrt(12) * log_spot.diff().std(),
}).round(2)
Loading...

De wisselkoersvolatiliteiten liggen tussen ongeveer 7% (Canada) en 12% (Nieuw-Zeeland), dezelfde orde van grootte als bij Brandt, Cochrane en Santa-Clara en in het toy-voorbeeld.

6.2De Fama-regressie

We schatten (7) op maanddata met Newey-West-standaardfouten. De gepoolde schatting haalt per valuta het gemiddelde eraf en clustert de standaardfouten per maand, omdat alle valuta’s tegen dezelfde dollar bewegen.

fama_rows = {}
for c in CURRENCIES:
    fit = hap.stats.newey_west(ds_next[c], -rate_diff[c], lags=3)
    b, se = fit.params.iloc[1], fit.bse.iloc[1]
    fama_rows[c] = {"helling": b, "SE": se, "t (helling = 0)": b / se, "t (helling = 1)": (b - 1) / se,
                    "R2 (%)": 100 * fit.rsquared, "maanden": int(fit.nobs)}

panel = pd.DataFrame({"ds": ds_next.stack(), "fwd": (-rate_diff).stack()}).dropna()
panel_dm = panel - panel.groupby(level=1).transform("mean")
pooled = sm.OLS(panel_dm["ds"], panel_dm[["fwd"]]).fit(
    cov_type="cluster", cov_kwds={"groups": panel_dm.index.get_level_values(0).factorize()[0]}
)
b, se = pooled.params.iloc[0], pooled.bse.iloc[0]
fama_rows["gepoold"] = {"helling": b, "SE": se, "t (helling = 0)": b / se, "t (helling = 1)": (b - 1) / se,
                        "R2 (%)": 100 * pooled.rsquared, "maanden": int(pooled.nobs)}
fama_table = pd.DataFrame(fama_rows).T
fama_table.round(2)
Loading...

Acht van de negen hellingen zijn negatief, en alleen de Zweedse kroon heeft een kleine positieve helling (0,16) met een grote standaardfout (1,11). Voor zeven valuta’s verwerpt de toets β=1\beta = 1 op het 5%-niveau. De gepoolde helling is −0,62-0{,}62, met een tt-waarde van −4,2-4{,}2 tegen β=1\beta = 1. In het lognormale model van Corollary 2 hoort daarbij een bb van ongeveer min een derde, binnen het vereiste bereik tussen −12-\tfrac12 en nul.

Tegen β=0\beta = 0 haalt echter geen enkele valuta ∣t∣>2|t| > 2, en de yen komt met −1,96-1{,}96 het dichtst bij. Het renteverschil verklaart minder dan één procent van de maandelijkse variantie van wisselkoersen. Vijftig jaar data zijn dus genoeg om UIP te verwerpen, maar nauwelijks om het teken vast te leggen. Dat is de standaardfout van 2% in valutavorm, want een klein gemiddeld effect naast veel ruis is slecht te meten. Toch zegt de puntschatting via Proposition 3 iets scherps, namelijk dat de premie volatieler dan de verwachte depreciatie en er negatief mee gecorreleerd is, en dat carry 1,621{,}62 keer het renteverschil verdient.

6.3Carry-portefeuilles

Elke maand sorteren we de beschikbare valuta’s, minstens zes, op it∗−iti^*_t - i_t in drie gelijkgewogen portefeuilles. HMLFX_{FX} is P3 min P1, en het rendement is (1).

def sort_portfolios(signal, returns_next, n_groups=3, min_assets=6):
    """Equal-weighted portfolios sorted on a signal at t; returns earned t -> t+1, indexed at t+1."""
    ranks = signal.where(returns_next.notna()).rank(axis=1, method="first")
    count = ranks.notna().sum(axis=1)
    group = np.ceil(ranks.mul(n_groups).div(count, axis=0))  # group g: rank share in ((g-1)/n, g/n]
    out = pd.DataFrame({f"P{g}": returns_next.where(group == g).mean(axis=1) for g in range(1, n_groups + 1)})
    out = out[count >= min_assets].copy()
    out["HML"] = out[f"P{n_groups}"] - out["P1"]
    out.index = out.index + pd.offsets.MonthEnd(1)
    return out


def portfolio_table(frame):
    """Annualised statistics with the standard error of the mean and of the Sharpe ratio."""
    stats = hap.stats.summary_stats(frame).astype({"nobs": int})
    years = stats["nobs"] / 12
    sharpe = stats["sharpe_ann"].astype(float)
    return pd.DataFrame({
        "gem. (%/jr)": 100 * stats["mean_ann"], "SE gem.": 100 * stats["se_mean_ann"],
        "vol. (%/jr)": 100 * stats["std_ann"], "Sharpe": sharpe,
        "SE Sharpe": np.sqrt((1 + sharpe**2 / 2) / years),
        "scheefheid": stats["skew"], "slechtste maand (%)": 100 * stats["min"],
        "maanden": stats["nobs"],
    }).astype(float)


carry = sort_portfolios(rate_diff, rx_next)
print(f"carry-portefeuilles {carry.index[0]:%Y-%m} t/m {carry.index[-1]:%Y-%m}")
portfolio_table(carry).round(2)
carry-portefeuilles 1979-02 t/m 2025-12
Loading...

De portefeuilles beginnen in februari 1979, de eerste maand met zes valuta’s, en de rangorde is monotoon, want het gemiddelde rendement stijgt van P1 naar P3. HMLFX_{FX} haalt een Sharpe-ratio van 0,44 met een standaardfout van 0,15, en de overige waarden staan in de tabel. De negatieve scheefheid van HMLFX_{FX} komt van de hoge-rentekant, want P3 is links scheef en P1 rechts. De volgende cel kijkt naar de crisis van 2008 en naar de slechtste maanden.

carry_crisis = carry.loc["2008-08":"2008-12"]
hml_dd = hap.stats.drawdowns(np.expm1(carry.loc["2007-06":"2009-12", "HML"]))
worst = carry["HML"].nsmallest(5)
print(f"HML_FX aug-dec 2008: {100 * carry_crisis['HML'].sum():.1f}% (log, cumulatief)")
print(f"grootste drawdown 2007-06 t/m 2009-12: {100 * hml_dd.attrs['max_drawdown']:.1f}%, "
      f"dal in {hml_dd.attrs['trough']:%Y-%m}")
print(f"grootste drawdown volledige steekproef: {100 * hap.stats.drawdowns(np.expm1(carry['HML'])).attrs['max_drawdown']:.1f}%")
(100 * worst).round(1).rename("vijf slechtste maanden HML_FX (%)").to_frame().T
HML_FX aug-dec 2008: -26.6% (log, cumulatief)
grootste drawdown 2007-06 t/m 2009-12: -28.0%, dal in 2009-01
grootste drawdown volledige steekproef: -29.7%
Loading...

Van augustus tot en met december 2008 verloor HMLFX_{FX} 26,6% in logs, en tot januari 2009 liep de drawdown op tot 28%. Oktober 2008 was met −11,2%-11{,}2\% de slechtste maand, gelijk met juli 1986, en ook oktober 1987 staat in de lijst. Een handvol maanden bepaalt zo het risicoprofiel van 47 jaar. In de figuur gaat het om de dikke lijn van HMLFX_{FX} in het grijze najaar van 2008.

Source
fig, ax = plt.subplots()
labels = {"P1": "P1 (lage rente)", "P2": "P2", "P3": "P3 (hoge rente)", "HML": "HML$_{FX}$"}
for k, col in enumerate(["P1", "P2", "P3", "HML"]):
    ax.plot(carry.index, 100 * carry[col].cumsum(), color=hap.plotting.COLORS[k], label=labels[col],
            lw=2.2 if col == "HML" else 1.4)
ax.axvspan(pd.Timestamp("2008-08-01"), pd.Timestamp("2008-12-31"), color="grey", alpha=0.25, lw=0)
ax.axhline(0, color="black", lw=0.8)
hap.plotting.timeline_axis(ax)
ax.set_xlabel("Jaar")
ax.set_ylabel("Cumulatief log overrendement (%)")
ax.set_title("Carry-portefeuilles van G10-valuta's tegenover de dollar")
ax.legend()
plt.show()
<Figure size 990x550 with 1 Axes>
<Figure size 990x550 with 1 Axes>

Figure 2:Cumulatieve log overrendementen van drie portefeuilles gesorteerd op renteverschil. Lage-rentevaluta’s verliezen gestaag en hoge-rentevaluta’s winnen gestaag, maar in het grijze najaar van 2008 gaat een groot deel van het verschil in een paar maanden verloren. Zo zijn de trap en de lift uit de intuïtie in de data terug te zien.

6.4Brandt, Cochrane en Santa-Clara op G10-data

We nemen de Sharpe-ratio van de Amerikaanse markt als grens voor beide SDF’s, zetten die met (5) om en berekenen (4) per valuta. Ter controle doen we dat ook met de Sharpe-ratio min twee standaardfouten, en met de maximale Sharpe-ratio van de 25 portefeuilles en de markt, die in de steekproef overschat is.

ff3 = hap_data.french("F-F_Research_Data_Factors").loc["1976":"2025"]
ff25 = hap_data.french("25_Portfolios_5x5").loc["1976":"2025"]
excess_25 = ff25.sub(ff3["RF"], axis=0).join(ff3["Mkt-RF"])
mu_vec = excess_25.mean().to_numpy()
max_sharpe = np.sqrt(12 * mu_vec @ np.linalg.solve(excess_25.cov().to_numpy(), mu_vec))

years_eq = len(ff3) / 12
sr_market = float(hap.stats.sharpe(ff3["Mkt-RF"]))
se_sr = np.sqrt((1 + sr_market**2 / 2) / years_eq)
bounds = {"markt": sr_market, "markt - 2 SE": sr_market - 2 * se_sr, "max. 25 + markt": max_sharpe}
print(f"Sharpe-ratio markt 1976-2025: {sr_market:.2f} (SE {se_sr:.2f}); "
      f"maximale Sharpe-ratio 25 portefeuilles + markt: {max_sharpe:.2f}")

fx_vol = np.sqrt(12) * log_spot.diff().loc["1976":"2025"].std()
bcs_table = pd.DataFrame({"vol. wisselkoers": fx_vol})
for name, sr in bounds.items():
    bcs_table[f"grens ({name})"] = implied_corr(sr, fx_vol)
bcs_table.loc["gem. G10"] = bcs_table.mean()
bcs_table.round(3)
Sharpe-ratio markt 1976-2025: 0.56 (SE 0.15); maximale Sharpe-ratio 25 portefeuilles + markt: 1.56
Loading...

Met de Sharpe-ratio van de markt over 1976–2025 ligt de grens per valuta tussen 0,975 voor de Nieuw-Zeelandse en 0,991 voor de Canadese dollar. Een Sharpe-ratio die twee standaardfouten lager ligt, trekt de grens omlaag, en de maximale Sharpe-ratio duwt hem dichter naar één. In alle drie de kolommen blijft het G10-gemiddelde boven de 0,9.

Eén grens voor beide landen is verdedigbaar. Brandt, Cochrane en Santa-Clara vonden lokale Sharpe-ratio’s van 0,26 (Japan) tot 0,63 (VS), maar minimum-variantie-SDF’s van vergelijkbare volatiliteit, doordat alle beleggers in wezen dezelfde activa kunnen kopen. Het resultaat is robuust omdat de wisselkoersvariantie klein is ten opzichte van de SDF-variantie, zoals de simulatie al liet zien.

6.5Momentum en value in valuta

Momentum is het cumulatieve carry-rendement over maand t−11t-11 tot en met t−1t-1, zoals de 12-1-regel van Jegadeesh-Titman, Carhart en momentum crashes. Value is minus de verandering van de reële wisselkoers over vijf jaar, omdat een munt die reëel goedkoper is geworden als ondergewaardeerd geldt, net als bij Asness, Moskowitz en Pedersen. We laten de hele reële wisselkoers drie maanden achterlopen, zodat de prijsindices op dat moment gepubliceerd zijn.

CPI_CODES = {"USD": "USACPIALLMINMEI", "GBP": "GBRCPIALLMINMEI", "JPY": "JPNCPIALLMINMEI",
             "CHF": "CHECPIALLMINMEI", "CAD": "CANCPIALLMINMEI", "AUD": "AUSCPIALLQINMEI",
             "NZD": "NZLCPIALLQINMEI", "NOK": "NORCPIALLMINMEI", "SEK": "SWECPIALLMINMEI",
             "EUR": "DEUCPIALLMINMEI"}


def log_cpi(code):
    """Log CPI at month end; quarterly series are carried forward within the quarter."""
    series = hap_data.fred(code)[code]
    series = series[series > 0].resample("ME").last()
    return np.log(series).ffill(limit=2)


cpi = pd.DataFrame({c: log_cpi(code) for c, code in CPI_CODES.items()}).reindex(MONTHS)
real_fx = log_spot + cpi[CURRENCIES].sub(cpi["USD"], axis=0)

momentum_signal = rx_next.shift(2).rolling(11, min_periods=11).sum()
value_signal = -(real_fx.shift(3) - real_fx.shift(63))

momentum = sort_portfolios(momentum_signal, rx_next)
value = sort_portfolios(value_signal, rx_next)
factors = pd.DataFrame({"carry": carry["HML"], "momentum": momentum["HML"], "value": value["HML"]}).dropna()
factors["50/50 momentum-value"] = 0.5 * (factors["momentum"] + factors["value"])
factors["gelijk gewogen, drie"] = factors[["carry", "momentum", "value"]].mean(axis=1)
print(f"gemeenschappelijke steekproef {factors.index[0]:%Y-%m} t/m {factors.index[-1]:%Y-%m}")
print("correlaties:")
print(factors[["carry", "momentum", "value"]].corr().round(2).to_string())
portfolio_table(factors).round(2)
gemeenschappelijke steekproef 1981-05 t/m 2025-07
correlaties:
          carry  momentum  value
carry      1.00      0.17   0.10
momentum   0.17      1.00  -0.29
value      0.10     -0.29   1.00
Loading...

Over 1981–2025 haalt value de hoogste Sharpe-ratio van de drie kenmerken, terwijl momentum vrijwel niets doet. Momentum en value zijn negatief gecorreleerd, en carry hangt met beide nauwelijks samen. Een gelijkgewogen mix van de drie haalt daardoor met 0,52 een hogere Sharpe-ratio dan elk kenmerk alleen. De crash van carry verdwijnt niet, want de scheefheid blijft −0,71-0{,}71, maar hij wordt verdund. Barroso en Santa-Clara bouwen precies zo’n portefeuille uit kenmerken die elk een ander risico dragen.

6.6Vergelijking met de originelen

De tabel zet de belangrijkste getallen naast de gepubliceerde waarden. Voor de Fama-helling geeft de eerste rij alleen het teken uit het origineel, omdat Fama per valuta rapporteerde.

carry_stats, factor_stats = portfolio_table(carry), portfolio_table(factors)
comparison = pd.DataFrame(
    {"origineel": [np.nan, 0.54, 0.98, 0.44, 0.32],
     "hier": [fama_table.loc["gepoold", "helling"], carry_stats.loc["HML", "Sharpe"],
              bcs_table.loc["gem. G10", "grens (markt)"],
              factor_stats.loc["value", "Sharpe"], factor_stats.loc["momentum", "Sharpe"]],
     "SE hier": [fama_table.loc["gepoold", "SE"], carry_stats.loc["HML", "SE Sharpe"], np.nan,
                 factor_stats.loc["value", "SE Sharpe"], factor_stats.loc["momentum", "SE Sharpe"]]},
    index=["Fama-helling, gepoold (Fama 1984: onder nul)", "Sharpe-ratio HML_FX (Lustig e.a., tabel 1)",
           "grens voor de index (Brandt e.a., tabel 2)",
           "Sharpe-ratio value (Asness e.a., tabel I)", "Sharpe-ratio momentum (Asness e.a., tabel I)"],
)
comparison.round(2)
Loading...

Geslaagd. De data gedragen zich zoals we vooraf verwachtten. De hellingen liggen onder één en zijn op één na negatief, de carry-portefeuilles zijn monotoon, en HMLFX_{FX} verloor van augustus tot en met december 2008 26,6%. Voor elke valuta ligt de grens boven de 0,9. Momentum blijft als enige achter bij het origineel, maar het verschil is kleiner dan twee keer de standaardfout van 0,15.

7Wat er brak, en wat daarna kwam

Wat het model verklaart. De identiteit (2) koppelt het SDF-raamwerk rechtstreeks aan data. Ze verklaart waarom rentes, wisselkoersen en risicopremies samenhangen, en waarom de munt van een land met volatiel marginaal nut een lage rente heeft en in crises stijgt. Ook een UIP-helling onder nul wordt zo een mogelijke risicopremie in plaats van irrationaliteit. De uitspraak van Brandt, Cochrane en Santa-Clara over risk sharing komt op onze G10-data terug met hetzelfde getal, 0,98.

Waar het breekt. Het model breekt op dezelfde data. De gepoolde Fama-helling is −0,62-0{,}62 in plaats van één, en HMLFX_{FX} verloor in het najaar van 2008 ruim een kwart, waarna de Sharpe-ratio zakte naar 0,13 (derde oefening). Het lognormale model geeft dat teken alleen als de rente daalt met de SDF-variantie, en dat kost volgens Backus, Foresi en Telmer negatieve rentes of asymmetrische landen. Een SDF-correlatie van 0,98 staat bovendien haaks op consumptiedata. De theorie voorspelde het feit dus niet, maar maakte er achteraf ruimte voor.

Risico of vergissing? In de Chicago-lezing is carry een beloning voor wereldwijd risico. Hoge-rentevaluta’s verliezen als de wereldwijde volatiliteit onverwacht stijgt Menkhoff et al. (2012), laden op één gemeenschappelijke factor Lustig et al. (2011), en hun peso problem is een toestand waarin een dollar extreem veel waard is Burnside et al. (2011). In de Yale-lezing is de winst een vergissing die blijft bestaan door limits of arbitrage (arbitrageurs met beperkt kapitaal kunnen niet alles corrigeren). Valutamomentum komt dan uit onder- en overreactie Menkhoff et al. (2012), crashes uit gedwongen afbouw Brunnermeier et al. (2008) en de winst deels uit schaars speculatief kapitaal Barroso & Santa-Clara (2015). Om de kampen te scheiden is de SDF in zeldzame crisistoestanden nodig, en die is met een handvol crises niet te meten.

Wat er daarna kwam. Barroso en Santa-Clara pasten op valuta’s de methode toe die het sorteren op één kenmerk vervangt door gewichten die rechtstreeks als functie van kenmerken worden geschat. Die parametrische portefeuilles zijn het onderwerp van Parametrische portefeuilles en idiosyncratisch risico.

8Oefeningen

Solution to Exercise 1

(1) Nu is E[m∗]=1,00\E[m^*] = 1{,}00, dus Rf∗=Rf=1,00R^{f*} = R^f = 1{,}00. De frank stijgt met factor 0,90/0,80=1,1250{,}90/0{,}80 = 1{,}125 in de goede toestand en daalt tot 1,10/1,20=0,91671{,}10/1{,}20 = 0{,}9167 in de slechte. Het carry-rendement is daardoor +12,5%+12{,}5\% of −8,33%-8{,}33\%, gemiddeld +2,08%+2{,}08\%.

m_calm = np.array([0.90, 1.10])
Rf_calm = 1 / (prob @ m_calm)
fx_calm = m_calm / m_home
excess_calm = Rf_calm * fx_calm - Rf
pd.Series({
    "R^f*": Rf_calm, "S'/S goed": fx_calm[0], "S'/S slecht": fx_calm[1],
    "E[carry]": prob @ excess_calm,
    "log-premie (exact)": np.log(Rf_calm / Rf) + prob @ np.log(fx_calm),
    "log-premie (lognormaal)": 0.5 * (pvar(np.log(m_home)) - pvar(np.log(m_calm))),
}).round(4)
R^f* 1.0000 S'/S goed 1.1250 S'/S slecht 0.9167 E[carry] 0.0208 log-premie (exact) 0.0154 log-premie (lognormaal) 0.0155 dtype: float64

(2) De premie komt uit de covariantie met de Amerikaanse SDF en niet uit het renteverschil. De frank daalt nog steeds in de slechte toestand, omdat marginaal nut in Zwitserland daar minder stijgt dan in de VS. De lognormale benadering geeft 0,0155 tegen een exacte log-premie van 0,0154. Een renteverschil is dus een symptoom en geen oorzaak, want de premie hoort bij het verschil in SDF-volatiliteit.

Solution to Exercise 2

(1) Uit (3) volgt Corr⁡=(σ2+σ∗2−V)/(2σσ∗)\Corr = (\sigma^2 + \sigma^{*2} - V)/(2\sigma\sigma^*), en σ2+σ∗2=(σ−σ∗)2+2σσ∗\sigma^2 + \sigma^{*2} = (\sigma - \sigma^*)^2 + 2\sigma\sigma^*. De eerste term is niet-negatief, dus Corr⁡≥1−V/(2σσ∗)≥1−V/(2a2)\Corr \geq 1 - V/(2\sigma\sigma^*) \geq 1 - V/(2a^2), omdat σσ∗≥a2\sigma\sigma^* \geq a^2. Gelijkheid geldt precies bij σ=σ∗=a\sigma = \sigma^* = a.

(2) en (3) De cel rekent het voorbeeld van Brandt, Cochrane en Santa-Clara na en zoekt de Sharpe-ratio die bij de gemiddelde G10-volatiliteit een grens van een half geeft.

V_bcs, a_bcs = 0.10**2, 0.5
print(f"grens BCS-voorbeeld: {1 - V_bcs / (2 * a_bcs**2):.2f}")
print(f"wisselkoersvolatiliteit bij correlatie nul: {np.sqrt(2) * a_bcs:.3f}")
vol_g10 = float(bcs_table.loc["gem. G10", "vol. wisselkoers"])
a2_needed = vol_g10**2 / (2 * (1 - 0.5))
print(f"G10-vol {vol_g10:.3f}: grens 0.5 vraagt log-SDF-vol {np.sqrt(a2_needed):.3f}, "
      f"dus een Sharpe-ratio van {np.sqrt(np.expm1(a2_needed)):.3f}")
grens BCS-voorbeeld: 0.98
wisselkoersvolatiliteit bij correlatie nul: 0.707
G10-vol 0.103: grens 0.5 vraagt log-SDF-vol 0.103, dus een Sharpe-ratio van 0.103

Ongecorreleerde SDF’s vragen wisselkoersen die met 71% per jaar schommelen. Een grens van een half vraagt een Sharpe-ratio van ongeveer 0,1 per jaar. De conclusie van Brandt, Cochrane en Santa-Clara volgt dus uit de orde van grootte van twee getallen en niet uit randgevallen van hun aannames.

Solution to Exercise 3

De cel schat de gepoolde helling en de statistieken van HMLFX_{FX} voor beide periodes.

def pooled_fama(frame):
    """Pooled UIP slope with currency fixed effects and month-clustered standard errors."""
    dm = frame - frame.groupby(level=1).transform("mean")
    fit = sm.OLS(dm["ds"], dm[["fwd"]]).fit(
        cov_type="cluster", cov_kwds={"groups": dm.index.get_level_values(0).factorize()[0]}
    )
    return fit.params.iloc[0], fit.bse.iloc[0]


dates = panel.index.get_level_values(0)
split_rows = {}
for label, (start, end) in {"1979-2007": ("1979-01-01", "2007-12-31"),
                            "2008-2025": ("2008-01-01", "2025-12-31")}.items():
    b_sub, se_sub = pooled_fama(panel[(dates >= start) & (dates <= end)])
    hml_stats = portfolio_table(carry.loc[start:end, ["HML"]]).iloc[0]
    split_rows[label] = {"Fama-helling": b_sub, "SE": se_sub, "t (helling = 1)": (b_sub - 1) / se_sub,
                         **hml_stats[["gem. (%/jr)", "SE gem.", "Sharpe", "SE Sharpe", "scheefheid",
                                      "slechtste maand (%)"]].to_dict()}
pd.DataFrame(split_rows).T.round(2)
Loading...

Eind 2007 zag carry eruit als een gevestigde regelmaat. De gepoolde helling was −1,01-1{,}01, bijna het dubbele renteverschil uit Proposition 3, en de Sharpe-ratio 0,60 (standaardfout 0,20). Na 2008 is de helling positief (1,39, standaardfout 1,38), in een periode waarin de renteverschillen binnen de G10 jarenlang bijna nul waren, en de Sharpe-ratio is 0,13 (standaardfout 0,24). Een premie die met dertig jaar data zeker leek, is na één crash dus niet meer aantoonbaar. Dat past bij een uitbetaalde risicopremie en bij een weggearbitreerde anomalie, want met deze standaardfouten zijn de twee niet uit elkaar te houden.

Solution to Exercise 4

(1) Er geldt rp,t+1=∑iwi,t rxi,t+1=θ′Ft+1r_{p,t+1} = \sum_i w_{i,t}\, rx_{i,t+1} = \boldsymbol{\theta}'\mathbf{F}_{t+1}, dus E[rp]−γ2Var⁡(rp)=θ′μF−γ2θ′ΣFθ\E[r_p] - \tfrac{\gamma}{2}\Var(r_p) = \boldsymbol{\theta}'\boldsymbol{\mu}_F - \tfrac{\gamma}{2}\boldsymbol{\theta}'\boldsymbol{\Sigma}_F\boldsymbol{\theta}. De eerste-ordevoorwaarde geeft θ=γ−1ΣF−1μF\boldsymbol{\theta} = \gamma^{-1}\boldsymbol{\Sigma}_F^{-1}\boldsymbol{\mu}_F, zodat het een mean-variance-probleem met drie kenmerkportefeuilles is.

(2) De cel schat de gewichten in de eerste helft en evalueert ze in de tweede.

signals = {"carry": rate_diff, "momentum": momentum_signal, "value": value_signal}
available = rx_next.notna()
for sig in signals.values():
    available &= sig.notna()
n_avail = available.sum(axis=1)


def cross_section_z(signal):
    """Cross-sectional z-score over currencies with all signals and a next-month return."""
    x = signal.where(available)
    return x.sub(x.mean(axis=1), axis=0).div(x.std(axis=1), axis=0)


char_returns = pd.DataFrame(
    {k: (cross_section_z(sig) * rx_next).sum(axis=1, min_count=1) / n_avail for k, sig in signals.items()}
)[n_avail >= 6].dropna()
char_returns.index = char_returns.index + pd.offsets.MonthEnd(1)

train, test = char_returns.loc["1981":"2002"], char_returns.loc["2003":"2025"]
theta = np.linalg.solve(train.cov().to_numpy(), train.mean().to_numpy())
policies = {"optimaal (geschat in de steekproef)": theta, "alleen carry": np.array([1.0, 0.0, 0.0]),
            "gelijke gewichten": np.ones(3)}
rows_pp = {}
for name, th in policies.items():
    scale = 0.10 / (np.sqrt(12) * (train @ th).std())                 # 10% volatility in the training sample
    for label, sample in {"1981-2002": train, "2003-2025": test}.items():
        r_p = scale * (sample @ th)
        rows_pp[(name, label)] = {"Sharpe": float(hap.stats.sharpe(r_p)), "vol. (%/jr)": 100 * np.sqrt(12) * r_p.std(),
                                  "scheefheid": r_p.skew()}
print("theta (genormeerd):", dict(zip(char_returns.columns, (theta / np.abs(theta).sum()).round(2))))
pd.DataFrame(rows_pp).T.round(2)
theta (genormeerd): {'carry': np.float64(0.15), 'momentum': np.float64(0.21), 'value': np.float64(0.64)}
Loading...

In de schattingsperiode legt de optimale portefeuille het meeste gewicht op value, met een Sharpe-ratio van 1,02. Buiten de steekproef is dat 0,24, iets onder gelijke gewichten (0,26) en boven carry alleen (0,18). Dat is het bekende effect uit Markowitz, Roy en Tobin, waarbij ΣF−1μF\boldsymbol{\Sigma}_F^{-1}\boldsymbol{\mu}_F de schattingsfout in μF\boldsymbol{\mu}_F versterkt. De winst zit dus in het combineren van kenmerken met verschillend risico, en geschatte gewichten helpen pas als de schattingsfout wordt ingetoomd, zoals in Parametrische portefeuilles en idiosyncratisch risico.

References
  1. Bekaert, G. (1996). The Time Variation of Risk and Return in Foreign Exchange Markets: A General Equilibrium Perspective. The Review of Financial Studies, 9(2), 427–470. 10.1093/rfs/9.2.427
  2. Backus, D. K., Foresi, S., & Telmer, C. I. (2001). Affine Term Structure Models and the Forward Premium Anomaly. The Journal of Finance, 56(1), 279–304. 10.1111/0022-1082.00325
  3. Brandt, M. W., Cochrane, J. H., & Santa-Clara, P. (2006). International Risk Sharing Is Better Than You Think, or Exchange Rates Are Too Smooth. Journal of Monetary Economics, 53(4), 671–698. 10.1016/j.jmoneco.2005.02.004
  4. Hansen, L. P., & Hodrick, R. J. (1980). Forward Exchange Rates as Optimal Predictors of Future Spot Rates: An Econometric Analysis. Journal of Political Economy, 88(5), 829–853. 10.1086/260910
  5. Fama, E. F. (1984). Forward and Spot Exchange Rates. Journal of Monetary Economics, 14(3), 319–338. 10.1016/0304-3932(84)90046-1
  6. Lustig, H., & Verdelhan, A. (2007). The Cross Section of Foreign Currency Risk Premia and Consumption Growth Risk. American Economic Review, 97(1), 89–117. 10.1257/aer.97.1.89
  7. Lustig, H., Roussanov, N., & Verdelhan, A. (2011). Common Risk Factors in Currency Markets. The Review of Financial Studies, 24(11), 3731–3777. 10.1093/rfs/hhr068
  8. Menkhoff, L., Sarno, L., Schmeling, M., & Schrimpf, A. (2012). Carry Trades and Global Foreign Exchange Volatility. The Journal of Finance, 67(2), 681–718. 10.1111/j.1540-6261.2012.01728.x
  9. Brunnermeier, M. K., Nagel, S., & Pedersen, L. H. (2008). Carry Trades and Currency Crashes. NBER Macroeconomics Annual, 23(1), 313–348. 10.1086/593088
  10. Burnside, C., Eichenbaum, M., Kleshchelski, I., & Rebelo, S. (2011). Do Peso Problems Explain the Returns to the Carry Trade? The Review of Financial Studies, 24(3), 853–891. 10.1093/rfs/hhq138
  11. Barroso, P., & Santa-Clara, P. (2015). Beyond the Carry Trade: Optimal Currency Portfolios. Journal of Financial and Quantitative Analysis, 50(5), 1037–1056. 10.1017/S0022109015000460
  12. Santa-Clara, P. (2026). What I Learned About Asset Pricing. LinkedIn post. https://www.linkedin.com/pulse/what-i-learned-asset-pricing-pedro-santa-clara-apjce/
  13. Backus, D. K., & Smith, G. W. (1993). Consumption and Real Exchange Rates in Dynamic Economies with Non-Traded Goods. Journal of International Economics, 35(3–4), 297–316. 10.1016/0022-1996(93)90021-O
  14. Engel, C. (1996). The Forward Discount Anomaly and the Risk Premium: A Survey of Recent Evidence. Journal of Empirical Finance, 3(2), 123–192. 10.1016/0927-5398(95)00016-X
  15. Froot, K. A., & Thaler, R. H. (1990). Anomalies: Foreign Exchange. Journal of Economic Perspectives, 4(3), 179–192. 10.1257/jep.4.3.179

Deze onafhankelijke site is niet verbonden aan of onderschreven door QuantEcon. De vormgeving is gebaseerd op het MIT-gelicentieerde QuantEcon MyST-thema. Zie THIRD_PARTY_NOTICES.md voor de licentie-informatie.