---
title: "3.3.2 Carry, momentum y value en divisas; cestas"
description: "Carry desde los forwards, su riesgo de crash tramo a tramo, momentum y value con el tipo de cambio real, y una cesta de los tres con costes."
url: "https://pythonparatrading.com/curso-python-trading/nivel-3/carry-momentum-y-value-en-divisas/"
lang: "es"
image: "https://pythonparatrading.com/og/curso-python-trading/nivel-3/carry-momentum-y-value-en-divisas.png"
---

# 3.3.2 · Carry y riesgo de crash, momentum y value en divisas; cestas

> La lección 2.3.4 midió el carry de divisas y sus crashes. Esta va más lejos: saca el carry de los forwards y separa la base de la paridad cubierta, descompone la prima por carteras, mide cada crash contra el que está plantado, construye momentum y value con el tipo de cambio real y los combina en una cesta neta de costes. Los datos son doce divisas ficticias con los tres efectos plantados y un control sin ninguno.

- Curso: [Nivel 3: Derivados: futuros, spreads, forex y opciones](https://pythonparatrading.com/curso-python-trading/nivel-3/)
- Módulo: 3.3 · Forex avanzado
- Duración: 75 min
- Requisitos: [1.2.4 · Forex: pares, pips, lotes, rollover y CFD](https://pythonparatrading.com/curso-python-trading/nivel-1/forex-pares-pips-lotes-y-rollover/), [2.3.1 · Seguimiento de tendencia y momentum](https://pythonparatrading.com/curso-python-trading/nivel-2/seguimiento-de-tendencia-y-momentum/), [2.3.4 · Carry en divisas, futuros y bonos; estacionalidad y efectos calendario](https://pythonparatrading.com/curso-python-trading/nivel-2/carry-estacionalidad-y-efectos-calendario/), [2.5.6 · Sensibilidad de parámetros: mesetas frente a picos, robustez entre activos y periodos](https://pythonparatrading.com/curso-python-trading/nivel-2/sensibilidad-de-parametros-y-robustez/), [2.6.1 · CAGR, Sharpe, Sortino, Calmar, Omega, drawdown y Ulcer Index](https://pythonparatrading.com/curso-python-trading/nivel-2/metricas-de-rentabilidad-y-riesgo/)

## Al terminar esta lección

- Calcular el diferencial de tipos implícito en el forward a 1 mes y separar la base de la paridad cubierta, y comprobar que la base no predice rentabilidades.
- Descomponer la prima del carry en interés y tipo de cambio con carteras ordenadas por diferencial, y relacionarla con los factores dólar y HML de la literatura.
- Medir el riesgo de crash del carry tramo a tramo frente al plantado, su relación con la volatilidad global de las divisas y lo que hace (y no hace) escalar por volatilidad.
- Construir momentum (transversal y serial) y value con el tipo de cambio real sin anticipación, y medir su fragilidad ante la ventana elegida.
- Combinar carry, momentum y value en una cesta con pesos por volatilidad pasada y costes por divisa, y juzgarla por subperiodos y por caídas, no solo por el Sharpe.

## Doce divisas y lo que tienen plantado

La lección 2.3.4 definió el carry, construyó la cartera clásica de tres contra tres con ejecución al día siguiente,
estimó la regresión de Fama y miró los crashes. Aquí se da por sabido todo eso y se trabaja con un conjunto de datos
más rico: **doce divisas ficticias** frente al USD, en días laborables de 2006 a 2025, cada una con su tipo de cambio,
su forward a un mes, sus tipos de depósito y su IPC mensual. Cada divisa imita el perfil de una real: el evro (`QEV`)
al euro, el yen de Nara (`QYN`) al yen, el real de Brava (`QBR`) al real brasileño. Los datos son sintéticos y tres
efectos están plantados con parámetros conocidos:

| Efecto | Qué hace en los datos | Parámetro plantado |
|---|---|---|
| Carry | Largo en la divisa rinde el 80 % del diferencial de tipos (paridad descubierta incompleta) | θ = 0,20 |
| Crash | En ocho tramos de estrés, cada divisa cae k · (su diferencial − la media) | k de 0,6 a 3,0 |
| Momentum | Deriva anual en la dirección del rendimiento en exceso de 63 sesiones | λ = 0,15 volatilidades |
| Value | El componente propio de cada divisa revierte a cero | Vida media de 3 años |
| Control | `sorpresas_macro`: una serie que no entra en ninguna ecuación | Sin efecto |

Además hay un factor dólar común, un factor de riesgo que sube las divisas de tipo alto y baja las refugio (`QYN`,
`QFR`) en las crisis, y una base de la paridad cubierta en cinco divisas. Todo está en
`public/curso/datos/nivel-3/README.md` y en `fx3_verdad.csv`. La lección mide cada efecto como si no lo conociera y
compara.

```mermaid
flowchart TB
  D[fx3_diario] --> C[Carry]
  D --> M[Momentum]
  I[fx3_ipc_mensual] --> V[Value]
  D --> V
  C --> R[Rangos fin de mes]
  M --> R
  V --> R
  R --> P[3 largas, 3 cortas]
  P --> E[Escala por vol]
  E --> K[Cesta neta]
```

## El carry en los forwards y la base de la paridad cubierta

Un gestor de divisas no suele pedir prestado en una divisa para depositar en otra: compra a plazo. El forward a un mes
ya lleva dentro el diferencial de tipos, por la **paridad cubierta de intereses** (lección 1.2.4):

$$
F = S \cdot \frac{1 + i_{\text{USD}}\,\tau}{1 + i\,\tau}
\qquad\Longrightarrow\qquad
i_{\text{USD}}^{\text{impl}} = \frac{(1 + i\,\tau)\,F/S - 1}{\tau}
$$

con $S$ y $F$ en USD por unidad de la divisa, $i$ el tipo de la divisa y $\tau = 30/360$. Si la paridad se cumpliera,
el tipo en USD implícito en el forward sería el del depósito. Desde 2008 no se cumple en las divisas reales: Du,
Tepper y Verdelhan (2018) documentan desviaciones persistentes (la **base**) en las divisas del G10, que atribuyen a
que arbitrarlas consume balance de los bancos. En los datos hay una base plantada en cinco divisas. Se recupera con la
fórmula exacta; la aproximación logarítmica habitual, $\ln(S/F)/\tau$, deja varios puntos básicos de error en las de
tipo alto, donde $\ln(1 + i\,\tau)$ ya no se parece a $i\,\tau$.

```python
import numpy as np
import pandas as pd
import statsmodels.api as sm

fx = pd.read_parquet("fx3_diario.parquet")

def tabla(col):
    return fx.pivot(index="fecha", columns="divisa", values=col)

X = tabla("usd_por_unidad")
i_div = tabla("tipo_deposito_1m")
i_usd = fx.groupby("fecha")["tipo_deposito_1m_usd"].first()
dif = i_div.sub(i_usd, axis=0)                  # % anual
cotiza_usd = fx.groupby("divisa")["par"].first().str.startswith("USD")
F = tabla("forward_1m")
F.loc[:, cotiza_usd] = 1 / F.loc[:, cotiza_usd]  # USD por unidad
TAU = 30 / 360
i_usd_impl = ((1 + i_div / 100 * TAU) * F / X - 1) / TAU * 100
base_pb = 100 * i_usd_impl.sub(i_usd, axis=0)
base_pb.median().round(1).sort_values().to_frame("base_pb").T
```
```output
divisa    QYN   QEV  QFR  QLB  QSK  QBR  QCD  QAD  QNK  QMP  QZD  QZR
base_pb -30.3 -15.4 -9.9 -5.4 -5.4 -0.0  0.0 -0.0 -0.0 -0.0 -0.0 -0.0
```

Las cinco bases plantadas salen casi exactas: −30 pb en `QYN`, −15 en `QEV`, −10 en `QFR` y −5 en `QLB` y `QSK`
(las cifras plantadas en calma; en los tramos de estrés se amplían, y la mediana los ignora). El resto, cero. Una base
negativa significa que conseguir dólares a plazo con esa divisa sale más caro que pedirlos prestados: el tipo en USD
implícito en el forward está por debajo del depósito, y quien vende la divisa a plazo para cubrirse paga esa
diferencia (lección 3.3.3).

¿Importa la base para el carry? Para ordenar las divisas, casi nada: 30 pb frente a diferenciales de varios puntos.
¿Predice algo? En el modelo no entra en ninguna ecuación de rentabilidad: es un control. La regresión del rendimiento
en exceso del mes siguiente sobre la base, con errores agrupados por mes (lección 2.1.1), lo confirma:

```python
dias = X.index.to_series().diff().dt.days
interes = dif.shift(1).div(100).mul(dias / 360, axis=0)
d_spot = np.log(X).diff()
r = d_spot + interes                       # rendimiento en exceso
fin = X.index.to_series().groupby(X.index.to_period("M")).max()

sig_mes = r.groupby(r.index.to_period("M")).sum().shift(-1)
sig_mes.index = fin.values                 # el mes siguiente a cada fin
panel = pd.DataFrame({"y": 1200 * sig_mes.stack(),   # % anual
                      "base": base_pb.loc[fin].stack(),
                      "dif": dif.loc[fin].stack()}).dropna()
grupos = panel.index.get_level_values(0).astype(str)
for xs in (["base"], ["dif", "base"]):
    m = sm.OLS(panel["y"], sm.add_constant(panel[xs])).fit(
        cov_type="cluster", cov_kwds={"groups": grupos})
    print(xs, "t =", m.tvalues[xs].round(2).to_dict())
```
```output
['base'] t = {'base': 0.3}
['dif', 'base'] t = {'dif': 1.75, 'base': -0.39}
```

Sola, la base tiene un t de 0,30; con el diferencial en la regresión, −0,39. El diferencial tiene un t de 1,75: ni
siquiera el carry, que sí está plantado, es significativo divisa a divisa y mes a mes. Es el mismo problema de potencia
que la regresión de Fama de la lección 2.3.4. La medida útil es la cartera.

## La prima, cartera a cartera

Lustig, Roussanov y Verdelhan (2011) ordenan las divisas por su diferencial de tipos (o su descuento a plazo) en
carteras y documentan dos factores: el **dólar** (la media de todas las divisas frente al USD) y el **HML de
divisas** (la cartera de tipo alto menos la de tipo bajo). Con doce divisas salen cuatro carteras de tres. Cada fin de
mes se ordenan por diferencial y se mantienen desde la sesión siguiente:

```python
puesto = dif.loc[fin].rank(axis=1)
grupo = ((puesto - 1) // 3 + 1).reindex(X.index, method="ffill")
grupo = grupo.shift(1)                      # desde la sesión siguiente
filas = {}
for g in range(1, 5):
    en_g = grupo == g
    filas[f"C{g}"] = {
        "dif_medio": dif.where(en_g).mean(axis=1).mean(),
        "interes": 260 * 100 * interes.where(en_g).mean(axis=1).mean(),
        "spot": 260 * 100 * d_spot.where(en_g).mean(axis=1).mean(),
        "total": 260 * 100 * r.where(en_g).mean(axis=1).mean(),
    }
pd.DataFrame(filas).T.round(2)
```
```output
    dif_medio  interes  spot  total
C1      -1.40    -1.41  1.39  -0.02
C2      -0.29    -0.29  0.35   0.06
C3       1.24     1.26 -0.69   0.57
C4       6.18     6.25 -0.31   5.95
```

Es la figura de la cabecera. La cartera de tipo más alto (`C4`, 6,18 puntos sobre el USD de media) cobra un 6,25 %
anual de interés y pierde solo un 0,31 % en el tipo de cambio: se queda con un 5,95 % de rendimiento en exceso. La de
tipo más bajo (`C1`) paga un 1,41 % de interés y lo recupera casi entero en el tipo de cambio (+1,39 %): su total es
cero. La paridad descubierta predice que el tipo de cambio compensa el diferencial en todas; lo hace en las de tipo
bajo y no en las de tipo alto, donde el modelo cobra el 80 % del diferencial y pierde, además, los crashes. Que la
`C4` solo pierda un 0,31 % anual en el spot incluye los crashes: se pierden de golpe, pero entre uno y otro la divisa
de tipo alto ni siquiera se deprecia lo que dice la paridad.

La diferencia `C4 − C1` es el HML de divisas, y con doce divisas en cuatro grupos de tres es exactamente la cartera de
carry de tres contra tres. La media de todas frente al USD es el factor dólar:

```python
dolar = r.mean(axis=1)
hml = (r.where(grupo == 4).mean(axis=1)
       - r.where(grupo == 1).mean(axis=1)).dropna()

def sharpe(x, n=260):
    return x.mean() / x.std() * np.sqrt(n)

pd.DataFrame({"media_pct": [260 * 100 * dolar.mean(),
                            260 * 100 * hml.mean()],
              "sharpe": [sharpe(dolar), sharpe(hml)]},
             index=["dolar", "hml"]).round(2)
```
```output
       media_pct  sharpe
dolar       1.50    0.20
hml         5.97    0.52
```

El factor dólar rinde un 1,50 % anual con un Sharpe de 0,20: la media de las doce divisas incluye las de tipo alto y
cobra algo de carry. El HML, un 5,97 % con un Sharpe de 0,52. En la literatura, el dólar explica la mayor parte de la
variación común de las divisas y el HML la diferencia de rentabilidad media entre carteras; en los datos, por
construcción, el factor dólar es un AR(1) acotado sin deriva y casi toda la prima está en el HML.

## El riesgo de crash, tramo a tramo

La cartera de carry de tres contra tres, con la convención del mercado monetario (360 días) y 260 días laborables
para anualizar:

```python
def cartera(senal, n=3):
    """Largo en las n de señal más alta y corto en las n más bajas,
    señal a fin de mes, posición desde la sesión siguiente."""
    s = senal.loc[fin]
    k = s.notna().sum(axis=1)
    pos = s.rank(axis=1)
    w = (pos.gt(k - n, axis=0).astype(float)
         - (pos <= n).astype(float)) / n
    w = w.where(k >= 2 * n, 0.0, axis=0)
    w = w.reindex(X.index, method="ffill").shift(1)
    vivo = w.abs().sum(axis=1) > 0
    return (w * r).sum(axis=1)[vivo], w[vivo]

def resumen(x, n=260):
    m = x.resample("ME").sum()
    curva = x.cumsum()
    return pd.Series({
        "sharpe": x.mean() / x.std() * np.sqrt(n),
        "media_pct": 100 * x.mean() * n,
        "vol_pct": 100 * x.std() * np.sqrt(n),
        "asim_mensual": m.skew(),
        "max_dd_pct": 100 * (curva - curva.cummax()).min(),
        "peor_mes_pct": 100 * m.min(),
    })

carry, w_carry = cartera(dif)
print(resumen(carry).round(2).to_string())
mensual = carry.resample("ME").sum()
print((100 * mensual.nsmallest(4)).round(1).to_string())
```
```output
sharpe           0.52
media_pct        5.97
vol_pct         11.50
asim_mensual    -1.49
max_dd_pct     -51.80
peor_mes_pct   -27.61
fecha
2008-10-31   -27.6
2010-05-31    -8.7
2020-03-31    -8.3
2014-05-31    -8.1
```

Sharpe de 0,52, un 5,97 % anual con un 11,50 % de volatilidad, asimetría mensual de −1,49, una caída máxima del 51,8 %
(en log) y un peor mes de −27,6 %, octubre de 2008. El README de los datos da 0,55 y 6,2 % porque anualiza con 252 días
y cobra el interés con 365: las convenciones mueven la segunda cifra decimal del Sharpe, no la conclusión. Los otros
tres peores meses (mayo de 2010, marzo de 2020, mayo de 2014) son mucho menores: el riesgo del carry está concentrado
en un episodio.

### Cada tramo, contra el plantado

En cada tramo de estrés el generador hace caer cada divisa $k \cdot (\Delta i_j - \overline{\Delta i})$ en log,
repartido en el tramo. Una regresión transversal de la caída de cada divisa en el tramo sobre su diferencial respecto
a la media, al empezar el tramo, debería dar una pendiente de $-k$:

```python
tramos = pd.DataFrame({
    "desde": ["2008-09-29", "2010-05-03", "2011-08-01", "2013-05-22",
              "2015-08-11", "2018-04-16", "2020-02-24", "2024-07-31"],
    "hasta": ["2008-10-27", "2010-05-25", "2011-09-23", "2013-06-24",
              "2015-08-25", "2018-09-07", "2020-03-23", "2024-08-05"],
    "k": [3.0, 0.8, 1.2, 1.0, 0.8, 0.6, 2.5, 0.6]})
filas = []
for t in tramos.itertuples():
    antes = X.index[X.index < t.desde][-1]
    caida = np.log(X.loc[t.hasta] / X.loc[antes])
    x = (dif.loc[antes] - dif.loc[antes].mean()) / 100
    fit = sm.OLS(caida, sm.add_constant(x)).fit()
    filas.append({"desde": t.desde[:7],
                  "sesiones": len(X.loc[t.desde:t.hasta]),
                  "k": t.k, "pendiente": fit.params.iloc[1],
                  "error": fit.bse.iloc[1],
                  "carry_pct": 100 * carry[t.desde:t.hasta].sum()})
pd.DataFrame(filas).round(2)
```
```output
     desde  sesiones    k  pendiente  error  carry_pct
0  2008-09        21  3.0      -3.14   0.17     -28.41
1  2010-05        17  0.8      -1.12   0.09      -7.98
2  2011-08        40  1.2      -1.22   0.32      -8.28
3  2013-05        24  1.0      -0.17   0.16       0.64
4  2015-08        11  0.8      -0.81   0.12      -7.33
5  2018-04       105  0.6       2.62   0.96      28.18
6  2020-02        21  2.5      -2.38   0.22     -11.38
7  2024-07         4  0.6      -0.60   0.07      -4.46
```

*Fig. — Resultado de la cartera de carry en cada tramo de estrés plantado, con su k y la pendiente transversal medida b (debería ser −k).* Barras verticales por tramo de estrés. 2008 (k 3,0, b −3,14): −28,4 %, destacado. 2010 (k 0,8, b −1,12): −8,0 %. 2011 (k 1,2, b −1,22): −8,3 %. 2013 (k 1,0, b −0,17): +0,6 %. 2015 (k 0,8, b −0,81): −7,3 %. 2018 (k 0,6, b +2,62): +28,2 %. 2020 (k 2,5, b −2,38): −11,4 %. 2024 (k 0,6, b −0,60): −4,5 %. Los tramos grandes y cortos se recuperan; el de 2018, largo y pequeño, no.

Los dos tramos grandes y cortos se recuperan bien: octubre de 2008 (k = 3,0) da −3,14 con un error de 0,17, y la
pandemia (k = 2,5), −2,38 con 0,22. En ellos la cartera pierde un 28,4 % y un 11,4 %. Los tramos pequeños se recuperan
peor o nada: 2013 (k = 1,0) da −0,17, y 2018 (k = 0,6) da **+2,62**: la cartera **gana** un 28,2 % en un tramo
plantado de estrés. Ese tramo dura 105 sesiones y la caída plantada, 0,6 veces un diferencial de unos 5 puntos,
es de un 3 %; en esos cinco meses las divisas de tipo alto se apreciaron un 20–30 % por los otros componentes del
modelo (el factor de riesgo, el momentum, el ruido). La lección general: un efecto pequeño repartido en un periodo
largo no se ve en ese periodo; un efecto grande y concentrado, sí. Y una lectura de los datos reales que diga «en el
episodio X el carry no cayó, luego el riesgo de crash es un mito» comete el mismo error.

### La volatilidad global de las divisas

Menkhoff, Sarno, Schmeling y Schrimpf (2012) relacionan las rentabilidades del carry con las **innovaciones de la
volatilidad global de las divisas**: las divisas de tipo alto pierden cuando la volatilidad sube por sorpresa, y las
de tipo bajo hacen de cobertura. Su medida es la media de los cambios absolutos diarios de todas las divisas. En los
datos, la volatilidad del factor de riesgo se duplica en los tramos de estrés, así que la relación debería aparecer:

```python
vol_global = (d_spot.abs().mean(axis=1).resample("ME").mean()
              * np.sqrt(260))
ar1 = sm.OLS(vol_global, sm.add_constant(vol_global.shift(1)),
             missing="drop").fit()
sorpresa = ar1.resid                    # lo que el AR(1) no esperaba
j = pd.concat({"carry": 100 * mensual, "sorpresa": 100 * sorpresa},
              axis=1).dropna()
m = sm.OLS(j["carry"], sm.add_constant(j["sorpresa"])).fit(
    cov_type="HAC", cov_kwds={"maxlags": 3})
print("correlación:", round(j.corr().iloc[0, 1], 2))
print("pendiente:", round(m.params["sorpresa"], 2),
      " t:", round(m.tvalues["sorpresa"], 2))
```
```output
correlación: -0.21
pendiente: -0.6  t: -1.37
```

La correlación es de −0,21, con el signo de la literatura: el carry pierde en los meses en que la volatilidad global
sube más de lo esperado. Pero la pendiente, con errores robustos a la autocorrelación (HAC), tiene un t de −1,37:
con 240 meses, no es significativa. El riesgo está ahí, en los datos y en el modelo, pero concentrado en pocos meses;
una regresión sobre todos los meses lo diluye.

### Escalar por volatilidad: lo que hace y lo que no

La respuesta habitual al riesgo de crash es escalar la posición por la inversa de su volatilidad reciente
(lección 2.2.2 y el research de volatility targeting del sitio). Con un objetivo del 10 % anual y la volatilidad de las
63 sesiones anteriores, con un máximo de 2 veces:

```python
vol_63 = carry.rolling(63).std().shift(1) * np.sqrt(260)
escala = (0.10 / vol_63).clip(upper=2.0)
carry_esc = (carry * escala).dropna()
pd.DataFrame({"carry": resumen(carry[carry_esc.index]),
              "escalado": resumen(carry_esc)}).round(2)
```
```output
              carry  escalado
sharpe         0.51      0.42
media_pct      5.82      4.41
vol_pct       11.52     10.43
asim_mensual  -1.49     -1.53
max_dd_pct   -51.80    -45.34
peor_mes_pct -27.61    -23.72
```

El escalado reduce la caída máxima del 51,8 % al 45,3 % y el peor mes del 27,6 % al 23,7 %, pero baja el Sharpe de
0,51 a 0,42 y deja la asimetría igual (−1,53). No protege del primer golpe porque los crashes del carry llegan después
de periodos tranquilos: en septiembre de 2008 la volatilidad de los tres meses anteriores era baja y la posición
estaba en su tamaño máximo. Ayuda en lo que viene después, cuando la volatilidad ya ha subido. El seguro contra el
primer golpe es otro: un tamaño que lo sobreviva, o opciones fuera de dinero sobre las divisas de tipo alto, que cuestan
prima (módulos 3.4 y 3.5).

```mermaid
flowchart TB
  A[Calma: vol baja] --> B[Posición máxima]
  B --> C[Crash: primer mes]
  C --> D[La vol sube]
  D --> E[Escalado reduce]
  E --> F[Menos pérdida]
```

## Momentum: transversal y serial

El momentum de divisas compra las que más han subido (en exceso del depósito) en los últimos meses y vende las que
menos. Menkhoff, Sarno, Schmeling y Schrimpf (2012, en el *Journal of Financial Economics*) lo documentan en divisas
con un rasgo propio: es más fuerte en divisas con costes altos y difíciles de arbitrar. En los datos está plantado
como una deriva de λ = 0,15 volatilidades al año en la dirección del rendimiento en exceso de las 63 sesiones
anteriores. Dos versiones: **transversal** (tres contra tres por rango, como el carry) y **serial** (cada divisa larga
o corta según su propio signo, lección 2.3.1).

```python
exceso_63 = r.rolling(63).sum()
mom, w_mom = cartera(exceso_63)
ts_w = (np.sign(exceso_63.loc[fin]) / 12).reindex(
    X.index, method="ffill").shift(1)
tsmom = (ts_w * r).sum(axis=1)[ts_w.abs().sum(axis=1) > 0]
print(pd.DataFrame({"transversal": resumen(mom),
                    "serial": resumen(tsmom)}).round(2).to_string())

# rendimiento del mes siguiente en volatilidades anuales
vol = d_spot.rolling(63).std() * np.sqrt(260)
y = r.rolling(21).sum().shift(-21) * 12 / vol
pan = pd.DataFrame({"y": y.loc[fin].stack(),
                    "senal": np.sign(exceso_63).loc[fin].stack()}
                   ).dropna()
m = sm.OLS(pan["y"], sm.add_constant(pan["senal"])).fit(
    cov_type="cluster",
    cov_kwds={"groups": pan.index.get_level_values(0).astype(str)})
print(f"lambda = {m.params['senal']:.3f} "
      f"(error típico {m.bse['senal']:.3f}; plantada 0,15)")
```
```output
              transversal  serial
sharpe               0.20    0.16
media_pct            1.69    0.79
vol_pct              8.60    5.05
asim_mensual        -0.24   -0.03
max_dd_pct         -44.83  -28.49
peor_mes_pct       -11.64   -5.77
lambda = 0.060 (error típico 0.109; plantada 0,15)
```

La cartera transversal tiene un Sharpe de 0,20 y la serial de 0,16. Las dos, con una asimetría cercana a cero, sin
el perfil de crash del carry; pero el peor mes del momentum transversal es también octubre de 2008 (−11,6 %): en un
crash las divisas que venían subiendo eran las de tipo alto. La estimación directa del parámetro plantado da
λ = 0,060 con un error típico de 0,109: el intervalo incluye el 0,15 plantado y el cero. Con doce divisas y 240 meses,
un efecto de 0,15 volatilidades al año está por debajo de lo que se puede medir con precisión, aunque esté.

## Value: el tipo de cambio real

La señal de value en divisas compara el tipo de cambio con un valor de equilibrio. El más simple es la **paridad del
poder adquisitivo** (PPP): a largo plazo, el tipo de cambio real, $q = \ln X + \ln(\text{IPC}_{\text{divisa}} /
\text{IPC}_{\text{USD}})$, debería volver a su media. Una divisa cuyo tipo real ha subido mucho en cinco años está cara;
una que ha caído, barata. Asness, Moskowitz y Pedersen (2013) usan esa señal (menos el cambio del tipo real en cinco
años) en divisas, junto con value en otras clases de activos. Menkhoff, Sarno, Schmeling y Schrimpf (2017) refinan la
medida ajustando por productividad y otros fundamentales[^1].

Dos detalles de anticipación. El IPC de un mes se publica con retraso: a fin del mes $t$ solo se conoce el del mes
$t-1$, y eso es lo que se usa. Y la señal necesita cinco años de historia, así que el value empieza en 2011.

```python
ipc = pd.read_csv("fx3_ipc_mensual.csv", parse_dates=["mes"])
ipc = ipc.set_index("mes")
rel = ipc[X.columns].div(ipc["USD"], axis=0).shift(1)  # mes anterior
rel.index = rel.index.to_period("M")
q_real = np.log(X.loc[fin]) + np.log(rel.loc[fin.index].to_numpy())

ventanas = {}
for meses in (36, 48, 60, 72):
    senal = -(q_real - q_real.shift(meses)).reindex(X.index)
    v, _ = cartera(senal)
    ventanas[meses] = resumen(v)[["sharpe", "media_pct",
                                  "max_dd_pct"]]
val, w_val = cartera(-(q_real - q_real.shift(60)).reindex(X.index))
pd.DataFrame(ventanas).T.round(2)
```
```output
    sharpe  media_pct  max_dd_pct
36    0.05       0.40      -35.41
48    0.34       2.99      -28.72
60    0.18       1.66      -30.46
72    0.60       5.19      -27.12
```

*Fig. — Sharpe de la cartera de value en divisas según la ventana del cambio del tipo de cambio real.* Barras horizontales: 36 meses 0,05; 48 meses 0,34; 60 meses 0,18 (destacado, la ventana usada); 72 meses 0,60; 1.260 sesiones, la del README de los datos, 0,31. Una banda sombreada marca ±1 error típico (0,26) alrededor de 0,18, desde 0 hasta 0,44: todas menos la de 72 meses caen dentro.

Con 60 meses, la ventana de Asness, Moskowitz y Pedersen, el value tiene un Sharpe de 0,18. Con 48, de 0,34; con 36,
de 0,05; con 72, de 0,60. El README de los datos, con 1.260 sesiones (unos 58 meses) y anualizando con 252 días, da
0,30. Cada ventana empieza en una fecha distinta y deja fuera años distintos, y con unos quince años de señal el error
típico de un Sharpe es de alrededor de $1/\sqrt{15} \approx 0{,}26$. Las cuatro cifras son compatibles con una prima
real pero débil; elegir la de 72 meses porque sale mejor sería sobreajuste (lecciones 2.5.4 y 2.5.6).

¿Recupera el tipo real la vida media plantada de tres años? El value plantado es el componente propio de cada divisa,
sin el factor dólar; el tipo real lo mezcla con el factor dólar (vida media de cinco años), la deriva del carry y las
diferencias de inflación:

```python
vida = {}
for c in q_real:
    z = q_real[c].dropna()
    z = z - z.mean()
    ar = sm.OLS(z.diff().iloc[1:], z.shift(1).iloc[1:]).fit()
    vida[c] = np.log(2) / -ar.params.iloc[0] / 12      # años
pd.Series(vida).round(1).sort_values().to_frame("vida_anos").T
```
```output
           QLB  QFR  QSK  QEV  QCD  QAD  QZD  QNK  QZR  QMP  QYN  QBR
vida_anos  0.9  1.1  1.1  1.2  1.2  1.7  1.8  2.2  2.5  3.2  4.9  5.1
```

Las vidas medias van de 0,9 años (`QLB`) a 5,1 (`QBR`), con una mediana de 1,75: casi todas por debajo de los tres
plantados y con una dispersión enorme. Las cortas lo son porque el tipo real lleva encima ruido que revierte deprisa
(el del IPC, los movimientos del momentum), y el AR(1) mezcla las dos velocidades. Las más largas son las de divisas con diferenciales extremos (`QBR` muy alto, `QYN` muy bajo): la deriva del carry, que
mueve el tipo real año tras año en una dirección, parece persistencia. Es el mismo problema que tiene la PPP en los
datos reales, donde las estimaciones de la vida media de las desviaciones del tipo real son de varios años y muy
imprecisas: una señal de value en divisas trabaja con una reversión lenta y medida con mucho ruido.

### El control

`sorpresas_macro` es una serie AR(1) por divisa que no entra en ninguna ecuación. Una cartera de tres contra tres con
ella como señal debería no ganar nada:

```python
sorpresas = tabla("sorpresas_macro")
control, _ = cartera(sorpresas)
resumen(control).round(2).to_frame("control").T
```
```output
         sharpe  media_pct  vol_pct  asim_mensual  max_dd_pct  peor_mes_pct
control     0.1       0.71     6.99          0.45      -28.69         -5.17
```

Sharpe de 0,10: un 0,71 % anual con una caída máxima del 28,7 %. Sin ningún efecto plantado, veinte años de una
cartera de divisas rinden algo por azar. Es la vara de medir para el momentum (0,20) y el value (0,18): están por
encima, pero no muy lejos. El carry (0,52) sí se separa.

## Costes: el giro decide

Las tres señales cambian a ritmos muy distintos. El carry depende de los tipos de los bancos centrales, que se mueven
poco; el momentum de 63 sesiones cambia de orden casi cada mes. Con un coste por lado de 3 pb del nominal en las
divisas del G10 y de 10 pb en las emergentes (`QMP`, `QBR`, `QZR`), un supuesto razonable para un cliente
institucional que habrá que contrastar con los precios propios (lecciones 2.4.7 y 3.3.1):

```python
coste_lado = pd.Series(3e-4, index=X.columns)
coste_lado[["QMP", "QBR", "QZR"]] = 10e-4
brutas = {"carry": (carry, w_carry), "momentum": (mom, w_mom),
          "value": (val, w_val)}
netas, filas = {}, {}
for nom, (bruta, w) in brutas.items():
    giro = w.diff().abs().fillna(w.abs())
    coste = (giro * coste_lado).sum(axis=1)
    netas[nom] = bruta - coste
    anos = len(w) / 260
    filas[nom] = {"giro_anual": giro.sum(axis=1).sum() / anos,
                  "coste_pct": 100 * 260 * coste.mean(),
                  "sharpe_bruto": resumen(bruta)["sharpe"],
                  "sharpe_neto": resumen(netas[nom])["sharpe"]}
pd.DataFrame(filas).T.round(2)
```
```output
          giro_anual  coste_pct  sharpe_bruto  sharpe_neto
carry           1.60       0.06          0.52         0.51
momentum       20.38       1.02          0.20         0.08
value           5.69       0.26          0.18         0.15
```

El carry gira 1,6 veces al año y paga un 0,06 % anual: su Sharpe pasa de 0,52 a 0,51. El value, 5,7 veces y un
0,26 % (de 0,18 a 0,15). El momentum gira **20 veces al año** y paga un 1,02 % anual, más de la mitad de su rendimiento bruto: su Sharpe baja de
0,20 a 0,08, por debajo del control. Una prima de momentum que en un backtest sin costes parece pequeña pero real se
queda en nada con costes razonables; en divisas emergentes, con horquillas más anchas, peor.

## Una cesta de carry, momentum y value

Las tres primas tienen poco que ver entre sí:

```python
N = pd.DataFrame(netas).dropna()
N.resample("ME").sum().corr().round(2)
```
```output
          carry  momentum  value
carry      1.00      0.12   0.02
momentum   0.12      1.00  -0.23
value      0.02     -0.23   1.00
```

Correlación de 0,12 entre carry y momentum, de 0,02 entre carry y value, y de −0,23 entre momentum y value. La
correlación negativa entre value y momentum es la que Asness, Moskowitz y Pedersen (2013) documentan en todas las
clases de activos: una divisa que ha subido mucho (momentum alto) se ha encarecido (value bajo). La cesta las combina
con el mismo riesgo: cada estrategia se escala a un 10 % de volatilidad con su desviación típica de las 252 sesiones
anteriores (no la de toda la muestra, que sería anticipación) y la cesta es la media de las tres.

```python
vol_ant = N.rolling(252, min_periods=126).std().shift(1)
escaladas = (N * 0.10 / (vol_ant * np.sqrt(260))).dropna()
cesta = escaladas.mean(axis=1)
tabla_cesta = pd.DataFrame({c: resumen(escaladas[c])
                            for c in escaladas})
tabla_cesta["cesta"] = resumen(cesta)
print("desde", cesta.index[0].date())
tabla_cesta.round(2)
```
```output
desde 2011-08-24
              carry  momentum  value  cesta
sharpe         0.82      0.32   0.31   0.91
media_pct      8.38      3.24   3.16   4.93
vol_pct       10.16     10.25  10.30   5.39
asim_mensual   0.28      0.09  -0.09  -0.02
max_dd_pct   -24.67    -35.12 -23.63 -12.31
peor_mes_pct  -8.79    -10.30  -6.98  -4.78
```

*Fig. — Carry, momentum y value netos de costes, cada uno escalado al 10 % de volatilidad con datos pasados, y la cesta de los tres (agosto de 2011 a 2025).* Cuatro líneas de rendimiento acumulado mensual desde agosto de 2011. El carry sube de forma irregular hasta un 121 %, con un tramo plano de 2016 a 2020. Momentum y value terminan en un 47 % y un 46 % con caídas largas. La cesta, destacada, sube de forma más regular hasta un 71 %, con la mitad de volatilidad que cada estrategia y una caída máxima del 12 %.

Desde agosto de 2011 (cuando las tres tienen al menos medio año de historia para estimar su volatilidad), la cesta tiene un Sharpe de 0,91 con un 5,39 % de
volatilidad y una caída máxima del 12,3 %. El carry escalado solo, en el mismo periodo, 0,82 y un 24,7 % de caída; el
momentum, 0,32; el value, 0,31. La cesta mejora poco el Sharpe del carry, porque desde 2011 el carry ha sido la mejor
de las tres y no ha tenido un octubre de 2008; donde se nota es en la caída máxima, que se divide por dos, y en la
asimetría, que pasa a ser casi nula.

```python
periodos = [("2011", "2015"), ("2016", "2020"), ("2021", "2025")]
pd.DataFrame({f"{a}-{b}": {**{c: resumen(escaladas[c][a:b])["sharpe"]
                              for c in escaladas},
                           "cesta": resumen(cesta[a:b])["sharpe"]}
              for a, b in periodos}).round(2)
```
```output
          2011-2015  2016-2020  2021-2025
carry          1.12       0.18       1.23
momentum       0.04       0.31       0.55
value          0.77       0.19       0.03
cesta          0.95       0.53       1.28
```

Ninguna estrategia gana en todos los subperiodos. El carry tiene un Sharpe de 0,18 en 2016-2020 y de 1,23 en
2021-2025; el value, de 0,77 en 2011-2015 y de 0,03 en 2021-2025; el momentum, de 0,04 al principio y 0,55 al
final. La cesta tiene el Sharpe más
estable: 0,95, 0,53 y 1,28. Esa estabilidad es lo que se compra al diversificar entre primas que no dependen de lo
mismo, más que un Sharpe medio mayor.

<aside class="callout" data-kind="riesgo">

La cesta no se puede medir en 2008, porque el value necesita cinco años de historia. Su caída máxima del 12 % no
incluye el peor episodio del carry. Una cesta de carry y momentum, que sí se puede medir desde 2006, enseña lo que
habría pasado (ejercicio 1). Y todo esto son datos sintéticos con los efectos plantados: los Sharpes no son evidencia
de que la cesta funcione en divisas reales.

</aside>

## Lo que una cesta de divisas exige en real

- **Dimensionar por el peor episodio, no por la volatilidad.** El carry tiene una volatilidad del 11 % y una caída del
  52 %. La cesta reduce la segunda, pero no la elimina.
- **Costes por divisa.** El momentum muere por costes; en divisas emergentes la horquilla es varias veces la del G10, y
  en los crashes se abre más (lección 3.3.1).
- **Ventanas y fechas de rebalanceo.** El value cambia de 0,05 a 0,60 con la ventana. Cualquier parámetro que no se
  pueda justificar antes de mirar el resultado es un grado de libertad que infla el backtest (lección 2.5.4).
- **Anticipación.** IPC con retraso de publicación, señal al cierre de fin de mes y posición desde la sesión
  siguiente, pesos de volatilidad con datos pasados. Los tres errores aparecen en backtests publicados.
- **Implementación.** Las posiciones se toman con forwards o swaps de divisas, no con depósitos: el carry se cobra en
  los puntos forward, con la base incluida. La lección 3.3.3 trata la ejecución y la cobertura del riesgo de divisa de
  una cartera.

## Ejercicios

1. Construye una cesta solo de carry y momentum netos, que se puede medir desde 2006, con el mismo escalado por
   volatilidad pasada. Compara con el carry solo escalado: Sharpe, caída máxima y resultado en octubre de 2008.

**Solución.**

```python
dos = pd.DataFrame({k: netas[k] for k in ("carry", "momentum")})
dos = dos.dropna()
v2 = dos.rolling(252, min_periods=126).std().shift(1)
esc2 = (dos * 0.10 / (v2 * np.sqrt(260))).dropna()
cesta2 = esc2.mean(axis=1)
oct08 = {c: 100 * esc2[c]["2008-10"].sum() for c in esc2}
oct08["cesta"] = 100 * cesta2["2008-10"].sum()
t = pd.DataFrame({"carry": resumen(esc2["carry"]),
                  "cesta": resumen(cesta2)}).T
t["oct_2008_pct"] = [oct08["carry"], oct08["cesta"]]
t.round(2)
```
```output
       sharpe  media_pct  vol_pct  asim_mensual  max_dd_pct  peor_mes_pct  oct_2008_pct
carry    0.53       5.48    10.32         -1.93      -46.06        -27.05        -27.05
cesta    0.37       3.01     8.06         -2.08      -43.39        -20.84        -20.84
```

La cesta de dos estrategias empieza en septiembre de 2006 (medio año de historia para la volatilidad) e incluye
octubre de 2008. Su
Sharpe es **peor** que el del carry solo (0,37 frente a 0,53): el momentum neto de costes apenas rinde y ocupa la mitad
del riesgo. En octubre de 2008 pierde un 20,8 % frente al 27,1 % del carry, porque solo la mitad está en carry, pero
el momentum también pierde ese mes: en un crash, las divisas que venían subiendo son las de tipo alto. La caída máxima
casi no cambia (−43,4 % frente a −46,1 %) y la asimetría empeora (−2,08). Diversificar con una prima débil y correlada
en el peor mes no protege: la caída del 12 % de la cesta de tres, medida desde 2011, no dice nada de 2008.

2. El factor dólar mezcla la prima del carry con la exposición al USD. Construye una cartera de carry «contra el
   dólar»: larga en las tres de diferencial más alto, sin cortos. Compara su correlación con el factor dólar y con la
   cartera de tres contra tres.

**Solución.**

```python
puesto_d = dif.loc[fin].rank(axis=1)
w_d = ((puesto_d > 9).astype(float) / 3).reindex(
    X.index, method="ffill").shift(1)
carry_usd = (w_d * r).sum(axis=1)[w_d.sum(axis=1) > 0]
comp = pd.DataFrame({"carry_usd": carry_usd, "carry_3x3": carry,
                     "dolar": dolar}).dropna()
print(comp.resample("ME").sum().corr().round(2).to_string())
resumen(carry_usd).round(2).to_frame("carry_usd").T
```
```output
           carry_usd  carry_3x3  dolar
carry_usd       1.00       0.77   0.80
carry_3x3       0.77       1.00   0.28
dolar           0.80       0.28   1.00
           sharpe  media_pct  vol_pct  asim_mensual  max_dd_pct  peor_mes_pct
carry_usd    0.51       5.95    11.59          0.12      -53.44        -14.65
```

La cartera larga solo en las de tipo alto tiene una correlación mensual de 0,80 con el factor dólar y de 0,77 con el
carry de tres contra tres, que a su vez solo tiene 0,28 con el dólar. Su rendimiento es casi el mismo (5,95 % anual,
Sharpe de 0,51) y su caída máxima algo mayor (53,4 %), pero su peor mes es de −14,7 %, no de −27,6 %, y su asimetría
es positiva (+0,12). La diferencia está en los cortos: en un crash, las divisas de tipo bajo son refugios que suben, y
la cartera de tres contra tres pierde por los dos lados; la larga contra el USD solo por uno, a cambio de cargar con el
riesgo del dólar todo el tiempo. Por eso los estudios separan el factor dólar del HML: son dos riesgos distintos con
dos perfiles de cola distintos.

3. Un compañero propone la ventana de 72 meses para el value porque da un Sharpe de 0,60. ¿Qué tres comprobaciones le
   pedirías antes de aceptarla?

**Solución.**

Primero, que la ventana se justifique antes de mirar el resultado: la vida media plantada de tres años o la convención
de cinco años de la literatura, no el Sharpe. Segundo, que el resultado sea estable alrededor de la ventana elegida
(66 y 78 meses deberían dar algo parecido) y por subperiodos; una cifra que salta de 0,34 a 0,18 y a 0,60 en ventanas
vecinas es ruido. Tercero, que se corrija por el número de ventanas probadas: el Sharpe deflactado de la lección 2.5.4
con cuatro pruebas y unos quince años de datos deja 0,60 lejos de ser concluyente. Y una cuarta, específica: que la
ventana de 72 meses empieza en 2012, un año después que la de 60, y no es la misma muestra.

[^1]: Menkhoff, Sarno, Schmeling y Schrimpf (2017), [Currency Value](https://doi.org/10.1093/rfs/hhw067), *Review of Financial Studies* 30(2).

## Autoevaluación

1. En los datos, la base de la paridad cubierta del QYN es de −30 pb. ¿Qué significa para una estrategia de carry que use los puntos forward como señal?

   - A. Que el carry del QYN es 30 pb mejor de lo que dicen los depósitos
   - B. Que el diferencial implícito en el forward se separa del de los depósitos en 30 pb; ordena las divisas casi igual y, en los datos, la base no predice nada (t = −0,39 con el diferencial en la regresión)
   - C. Que hay un arbitraje sin riesgo de 30 pb al año
   - D. Que el forward está mal calculado

   *Respuesta B: Que el diferencial implícito en el forward se separa del de los depósitos en 30 pb; ordena las divisas casi igual y, en los datos, la base no predice nada (t = −0,39 con el diferencial en la regresión).* La base es la diferencia entre el tipo en USD implícito en el forward y el del depósito. Existe desde 2008 en las divisas reales (Du, Tepper y Verdelhan, 2018) porque arbitrarla consume balance de los bancos. Para el carry casi no cambia el orden de las divisas, y en estos datos es un control: no entra en ninguna ecuación de rentabilidad.

2. La cartera de carry de tres contra tres tiene un Sharpe de 0,52 desde 2006; escalada por volatilidad y neta de costes, de 0,82 desde agosto de 2011. ¿Qué explica sobre todo la diferencia?

   - A. Que la estrategia mejoró con el tiempo
   - B. Que el periodo corto no incluye el crash de octubre de 2008, el peor mes (−27,6 %): el Sharpe del carry depende de si la muestra tiene o no un crash grande
   - C. Que los costes bajaron
   - D. Un error de cálculo

   *Respuesta B: Que el periodo corto no incluye el crash de octubre de 2008, el peor mes (−27,6 %): el Sharpe del carry depende de si la muestra tiene o no un crash grande.* El carry gana de forma regular y lo devuelve en pocos meses. Una muestra sin su peor episodio da una asimetría positiva (+0,28) y un Sharpe mucho mayor. Es la razón por la que el carry se presenta siempre con su peor episodio, no solo con su Sharpe.

3. La pendiente medida del tramo de estrés de 2018 es +2,62, con k = 0,6 plantado (las divisas de tipo alto deberían caer). ¿Qué ocurre?

   - A. El generador tiene un error
   - B. El tramo dura 105 sesiones y la caída plantada, unos 0,6 × 5 puntos ≈ 3 %, queda enterrada bajo movimientos del 20–30 % de las divisas de tipo alto por otras fuentes; los tramos cortos y grandes (2008, 2020) se recuperan bien
   - C. Que en 2018 el carry no tenía riesgo
   - D. Que hay que quitar 2018 de la muestra

   *Respuesta B: El tramo dura 105 sesiones y la caída plantada, unos 0,6 × 5 puntos ≈ 3 %, queda enterrada bajo movimientos del 20–30 % de las divisas de tipo alto por otras fuentes; los tramos cortos y grandes (2008, 2020) se recuperan bien.* Un efecto pequeño repartido en cinco meses tiene una relación señal-ruido muy baja. En 2008 (k = 3,0) se mide −3,14 con error 0,17, y en 2020 (k = 2,5), −2,38. Lo que no se ve en un tramo no deja de existir: se ve agregando muchos.

4. Escalar la cartera de carry por su volatilidad de los 63 días anteriores reduce la caída máxima del 51,8 % al 45,3 %, pero el peor mes solo pasa de −27,6 % a −23,7 %. ¿Por qué no protege más?

   - A. Porque el escalado usa la volatilidad futura
   - B. Porque los crashes del carry llegan después de periodos tranquilos: la volatilidad pasada era baja y la posición estaba en su tamaño máximo cuando empezó la caída
   - C. Porque el escalado aumenta los costes
   - D. Porque la volatilidad no cambia en las crisis

   *Respuesta B: Porque los crashes del carry llegan después de periodos tranquilos: la volatilidad pasada era baja y la posición estaba en su tamaño máximo cuando empezó la caída.* El escalado reacciona a la volatilidad que ya ha ocurrido. Ayuda en crisis largas, en las que la volatilidad sube y la posición se reduce a tiempo para el resto, pero no en el primer golpe. El seguro contra el primer golpe es otro instrumento (opciones, módulos 3.4 y 3.5) o un tamaño que lo sobreviva.

5. La señal de value con una ventana de 36 meses da un Sharpe de 0,05; con 48, 0,34; con 60, 0,18; con 72, 0,60. ¿Qué haces?

   - A. Usar 72 meses
   - B. Promediar o fijar la ventana por razones previas (la vida media plantada es de 3 años) y tratar la dispersión como la incertidumbre del método, no como un parámetro que optimizar
   - C. Descartar el value
   - D. Usar la ventana del último año

   *Respuesta B: Promediar o fijar la ventana por razones previas (la vida media plantada es de 3 años) y tratar la dispersión como la incertidumbre del método, no como un parámetro que optimizar.* Con 12 divisas y unos 15 años de señal, el Sharpe de una ventana concreta tiene un error típico de alrededor de 0,25. Elegir la mejor de cuatro es sobreajuste (lecciones 2.5.4 y 2.5.6). La dispersión entre ventanas es la información útil: el value de estos datos es real pero débil.

## Ideas clave

- El carry se puede leer en los forwards: el diferencial implícito coincide con el de los depósitos salvo la base de la paridad cubierta, que en los datos se recupera exacta (−30 pb en el QYN, −15 en el QEV) y no predice rentabilidades.
- Ordenadas por diferencial, las carteras ganan casi todo por el interés: la de tipo más alto cobra un 6,25 % anual y pierde un 0,31 % en el tipo de cambio. Su diferencia con la de tipo más bajo es el HML de divisas: el carry 3 contra 3.
- El carry pierde de golpe en los tramos de estrés: −28,4 % en octubre de 2008, con una pendiente medida de −3,14 frente a k = 3,0 plantado. Los tramos pequeños y largos no se distinguen del ruido.
- Momentum y value son primas más débiles y frágiles: el momentum transversal (Sharpe 0,20 bruto) se queda casi sin nada tras costes (0,08) por su giro de 20 veces al año, y el value cambia de 0,05 a 0,60 según la ventana.
- La cesta de los tres con pesos por volatilidad pasada y costes tiene un Sharpe de 0,91 y una caída máxima del 12 % desde 2011, frente al 0,82 y el 25 % del carry solo, escalado igual, en el mismo periodo: su ventaja está en las caídas y en los subperiodos malos de cada factor, no en el Sharpe.
- Los datos son sintéticos y los efectos están plantados: las cifras enseñan los métodos y sus trampas, no prueban que estas estrategias funcionen en mercados reales; para eso está la literatura citada.

## Recursos

### Research

- [Volatility Targeting en Python](https://pythonparatrading.com/volatility-targeting/) · Research-0004 · 8 min

### Documentación

- [Lustig, Roussanov y Verdelhan (2011): Common Risk Factors in Currency Markets, Review of Financial Studies 24(11)](https://doi.org/10.1093/rfs/hhr068) · doi.org
- [Menkhoff, Sarno, Schmeling y Schrimpf (2012): Carry Trades and Global Foreign Exchange Volatility, Journal of Finance 67(2)](https://doi.org/10.1111/j.1540-6261.2012.01728.x) · doi.org
- [Menkhoff, Sarno, Schmeling y Schrimpf (2012): Currency momentum strategies, Journal of Financial Economics 106(3)](https://doi.org/10.1016/j.jfineco.2012.06.009) · doi.org
- [Asness, Moskowitz y Pedersen (2013): Value and Momentum Everywhere, Journal of Finance 68(3)](https://doi.org/10.1111/jofi.12021) · doi.org
- [Du, Tepper y Verdelhan (2018): Deviations from Covered Interest Rate Parity, Journal of Finance 73(3)](https://doi.org/10.1111/jofi.12620) · doi.org

### Datos

- [Datos del nivel 3: doce divisas con forwards, tipos e IPC (Parquet)](https://pythonparatrading.com/curso/datos/nivel-3/fx3_diario.parquet) · Descarga · fx3_diario.parquet

Lección anterior: [3.3.1 · Microestructura FX: OTC, ECN, last look y sesiones](https://pythonparatrading.com/curso-python-trading/nivel-3/microestructura-fx-otc-ecn-y-last-look/)

Lección siguiente: [3.3.3 · Riesgo de divisa en carteras multi-moneda; ejecución vía OANDA, IBKR o MT5](https://pythonparatrading.com/curso-python-trading/nivel-3/riesgo-de-divisa-y-ejecucion-fx/)
