---
title: "2.3.4 Carry, estacionalidad y efectos calendario"
description: "Carry en divisas, futuros y bonos con ejecución al día siguiente y costes, sus crashes y la regresión de Fama; efectos calendario como control."
url: "https://pythonparatrading.com/curso-python-trading/nivel-2/carry-estacionalidad-y-efectos-calendario/"
lang: "es"
image: "https://pythonparatrading.com/og/curso-python-trading/nivel-2/carry-estacionalidad-y-efectos-calendario.png"
---

# 2.3.4 · Carry en divisas, futuros y bonos; estacionalidad y efectos calendario

> El carry es lo que gana una posición si los precios no se mueven: el diferencial de tipos de una divisa, la pendiente de la curva de un futuro, el cupón y el deslizamiento por la curva de un bono. Esta lección lo mide en los datos sintéticos del nivel, donde la prima está plantada con su valor real, lo convierte en carteras con ejecución al día siguiente y costes, enseña por qué cae de golpe y prueba los efectos calendario en series donde no hay ninguno.

- Curso: [Nivel 2: Estrategias sistemáticas y backtesting riguroso](https://pythonparatrading.com/curso-python-trading/nivel-2/)
- Módulo: 2.3 · Familias de estrategias
- Duración: 70 min
- Requisitos: [1.2.3 · Futuros: especificaciones, margen, roll y contango](https://pythonparatrading.com/curso-python-trading/nivel-1/futuros-especificaciones-margen-y-roll/), [1.2.4 · Forex: pares, pips, lotes, rollover y CFD](https://pythonparatrading.com/curso-python-trading/nivel-1/forex-pares-pips-lotes-y-rollover/), [1.6.3 · Estacionalidad: día de la semana, mes, cambio de mes y sesiones intradía](https://pythonparatrading.com/curso-python-trading/nivel-1/estacionalidad-y-efectos-calendario/), [2.1.1 · Contrastes de hipótesis, p-valores, bootstrap y regresión con errores robustos](https://pythonparatrading.com/curso-python-trading/nivel-2/contrastes-bootstrap-y-errores-robustos/)

## Al terminar esta lección

- Definir el carry de una divisa, de un futuro y de un bono, y calcularlo con los datos de cada mercado.
- Construir una cartera de carry en divisas y otra en futuros con la señal al cierre, la posición desde la sesión siguiente y costes por lado.
- Estimar la regresión de Fama y la pendiente del carry de futuros con errores agrupados por fecha, y compararlas con la respuesta conocida.
- Medir el riesgo de crash del carry: asimetría, peores meses y pérdidas en los tramos de estrés.
- Contrastar efectos calendario en series sin ninguno plantado y reconocer los falsos positivos.

## Qué es el carry

El **carry** de una posición es lo que rinde si los precios no se mueven. Koijen, Moskowitz, Pedersen y Vrugt (2018)
lo definen así para cualquier activo y lo descomponen en dos partes: el rendimiento esperado si nada cambia (el carry)
y el cambio de precio, que nadie conoce de antemano. La definición es útil porque el carry **se conoce hoy**: es una
señal sin estimación, sin parámetros que optimizar y sin anticipación posible.

```mermaid
flowchart TB
  C[Carry] --> FX[Divisas]
  C --> FU[Futuros]
  C --> BO[Bonos]
  FX --> D1[Diferencial tipos]
  FU --> D2[Pendiente curva]
  BO --> D3[Cupón y roll-down]
```

| Activo | Carry | Qué tiene que pasar para cobrarlo |
|---|---|---|
| Divisa (largo frente al USD) | Tipo de la divisa − tipo del USD | Que el tipo de cambio no se deprecie tanto como el diferencial |
| Futuro (largo) | Pendiente de la curva: ln(F₁ / F₂) / (τ₂ − τ₁) | Que la curva no cambie y el contrato converja hacia el contado |
| Bono (largo, financiado) | Rendimiento − tipo de financiación + roll-down | Que la curva de tipos no se mueva |

La teoría dice que el carry no debería ganar nada: si una divisa paga más interés, el mercado debería esperar que se
deprecie lo mismo (**paridad descubierta de tipos**), y si un futuro está en backwardation, el contado debería caer
hasta compensarlo. Lo que se observa en la literatura es que esa compensación es solo parcial, y que el carry rinde una
prima con un riesgo concreto: pierde de golpe en las crisis. Brunnermeier, Nagel y Pedersen (2008) documentan que las
divisas de tipo alto tienen una asimetría negativa, ligada a las salidas de posiciones en episodios de estrés.

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

Los datos de esta lección son **sintéticos** y la prima del carry está **plantada** con un valor conocido: las divisas
ganan el 70 % de su diferencial, los futuros rinden la mitad de la parte exógena de su carry y una décima de la que es
reversión a la media, y hay cinco crashes con fecha fija. Sirven para comprobar si los métodos recuperan lo que se
puso. Ninguna cifra de aquí es evidencia de que el carry funcione en mercados reales: para eso está la literatura
citada.

</aside>

## Carry en divisas: el diferencial de tipos

`fx2_carry.parquet` tiene diez divisas ficticias frente al USD, en días laborables de 2005 a 2025: el precio en USD
de una unidad (`spot`) y los tipos a corto de la divisa y del USD, en % anual. Quien está largo de una divisa (la
compra con dólares prestados y la deposita) gana su variación más el diferencial de tipos, con la convención de 360
días del mercado monetario:

$$
r_{t} = \Delta \ln S_{t} + \left(i_{t-1} - i^{\ast}_{t-1}\right)\frac{d_t}{360}
$$

con $S$ el spot, $i$ el tipo de la divisa, $i^{\ast}$ el del USD y $d_t$ los días naturales desde la sesión anterior
(3 los lunes). El diferencial que cuenta es el del día anterior: es el que se conocía al abrir la posición.

```python
import numpy as np
import pandas as pd

fx = pd.read_parquet("fx2_carry.parquet")
spot = fx.pivot(index="fecha", columns="divisa", values="spot")
dif = (fx.pivot(index="fecha", columns="divisa", values="tipo_divisa")
       - fx.pivot(index="fecha", columns="divisa", values="tipo_usd"))
dias = spot.index.to_series().diff().dt.days
d_spot = np.log(spot).diff()
interes = dif.shift(1).div(100).mul(dias / 360, axis=0)
r_fx = d_spot + interes

anual = pd.DataFrame({
    "diferencial_pct": dif.mean(),
    "interes_pct": 100 * interes.mean() * 260,
    "spot_pct": 100 * d_spot.mean() * 260,
    "total_pct": 100 * r_fx.mean() * 260,
})
anual.round(2)
```
```output
        diferencial_pct  interes_pct  spot_pct  total_pct
divisa
ALV                7.32         7.40      0.43       7.83
BOR                5.10         5.16     -5.45      -0.29
CAS                2.92         2.95     -0.81       2.14
DUN                2.93         2.96      0.35       3.31
EST                1.20         1.21     -0.34       0.88
FOR                0.59         0.60     -2.82      -2.23
GAL               -0.41        -0.41      2.09       1.68
HUR               -1.06        -1.07     -0.19      -1.26
ISL               -0.81        -0.81      2.43       1.61
JAR               -1.77        -1.79      2.54       0.75
```

La columna `interes_pct` es el diferencial cobrado (algo mayor que el diferencial medio por la convención de 360
días) y `spot_pct`, lo que se movió el tipo de cambio. `ALV`, la de tipo más alto (7,3 puntos sobre el USD), cobró
un 7,40 % anual de interés y además se apreció un 0,43 %: un 7,83 % anual estando largo. `BOR`, la segunda, cobró un
5,16 % y perdió un 5,45 % en el spot, casi todo en un solo mes (febrero de 2009, abajo). Las de tipo bajo (`GAL`,
`ISL`, `JAR`) pagaron interés y se apreciaron. El patrón medio es el de la respuesta conocida, pero divisa a divisa el
ruido del tipo de cambio, de un 10 % a un 15 % anual, es mucho mayor que el diferencial.

La **regresión de Fama** (1984) es la forma clásica de contrastar la paridad descubierta. Fama usó la prima del tipo a
plazo (forward), que por la paridad cubierta es el diferencial de tipos; aquí se usa el diferencial directamente: el
cambio del tipo de cambio del mes siguiente sobre el diferencial de hoy.

$$
\Delta \ln S_{t+1} = a + b\,\left(i_t - i^{\ast}_t\right) + \varepsilon_{t+1}
$$

Con la paridad, $b = -1$: la divisa se deprecia lo mismo que paga de más. Si el tipo de cambio fuera un paseo
aleatorio, $b = 0$ y el carry se cobraría entero. En los datos, la respuesta conocida es $b = -0{,}3$ fuera de los
crashes, que añaden pérdidas proporcionales al diferencial. Con diez divisas que comparten los mismos meses, los
residuos de un mismo mes están correlados: el error típico tiene que agruparse por fecha (lección 2.1.1).

```python
import statsmodels.api as sm

fin_mes = (spot.index.to_series()
           .groupby(spot.index.to_period("M")).max())
s_mes = np.log(spot.loc[fin_mes])
x_mes = dif.loc[fin_mes] / 100 / 12      # diferencial del mes
y_mes = s_mes.diff().shift(-1)           # cambio del mes siguiente

panel = pd.DataFrame({"y": y_mes.stack(), "x": x_mes.stack()}).dropna()
meses = panel.index.get_level_values("fecha").to_period("M")
fama = sm.OLS(panel["y"], sm.add_constant(panel["x"])).fit(
    cov_type="cluster", cov_kwds={"groups": meses.astype(str)})
b, eb = fama.params["x"], fama.bse["x"]
print(f"b = {b:.2f}  (error típico {eb:.2f})")
print(f"IC 95 %: [{b - 1.96 * eb:.2f}, {b + 1.96 * eb:.2f}]")

crash = meses.isin(pd.PeriodIndex(
    ["2008-09", "2008-10", "2008-11", "2008-12", "2010-05",
     "2011-08", "2011-09", "2015-08", "2015-09", "2020-02",
     "2020-03"], freq="M") - 1)   # x de fin de mes, y del siguiente
sin = sm.OLS(panel["y"][~crash], sm.add_constant(panel["x"][~crash]))
sin = sin.fit(cov_type="cluster",
              cov_kwds={"groups": meses[~crash].astype(str)})
print(f"sin los meses de crash: b = {sin.params['x']:.2f} "
      f"(error típico {sin.bse['x']:.2f})")
```
```output
b = -0.53  (error típico 0.36)
IC 95 %: [-1.24, 0.18]
sin los meses de crash: b = -0.09 (error típico 0.34)
```

La pendiente es −0,53, y su intervalo al 95 % va de −1,24 a +0,18: incluye la paridad descubierta (−1), el paseo
aleatorio (0) y la respuesta conocida (−0,3). Sin los meses de crash, la pendiente sube a −0,09 con un error típico de
0,34: unos pocos meses mueven la estimación casi media unidad. Es la lección general del nivel aplicada a una
regresión famosa: el método es correcto, pero con diez divisas y 251 meses no tiene potencia para separar las
hipótesis que importan. Por eso la rentabilidad de una cartera de carry, que agrega todas las divisas y todos los
meses en una sola serie, es una medida más directa de la prima.

## Una cartera de carry con ejecución al día siguiente

La estrategia clásica ordena las divisas por diferencial y compra las de tipo alto con las de tipo bajo. Aquí, con
diez divisas: al cierre del último día de cada mes se ordenan por diferencial, se compran las tres de tipo más alto y
se venden las tres de tipo más bajo, con un tercio del capital en cada una. La posición entra en la **sesión
siguiente** (`shift(1)` sobre los pesos diarios) y se mantiene hasta el siguiente fin de mes. Cada cambio de peso paga
un coste de 3 puntos básicos por lado sobre el nominal negociado, una horquilla razonable para divisas líquidas de un
cliente institucional; en las de tipo alto de países emergentes suele ser mayor.

```python
puesto = dif.loc[fin_mes].rank(axis=1)
pesos_mes = ((puesto >= 8).astype(float)
             - (puesto <= 3).astype(float)) / 3
# señal al cierre del fin de mes, posición desde la sesión siguiente
pesos = pesos_mes.reindex(spot.index, method="ffill").shift(1)

COSTE = 3 / 1e4                                   # por lado
giro = pesos.diff().abs().sum(axis=1).fillna(pesos.abs().sum(axis=1))
bruto = (pesos * r_fx).sum(axis=1)
neto = (bruto - COSTE * giro)[pesos.abs().sum(axis=1) > 0]

def resumen(r, n=260):
    eq = (1 + r).cumprod()
    mensual = r.resample("ME").sum()
    return pd.Series({
        "rent_anual_pct": 100 * r.mean() * n,
        "vol_anual_pct": 100 * r.std() * np.sqrt(n),
        "sharpe": r.mean() / r.std() * np.sqrt(n),
        "asimetria_mensual": mensual.skew(),
        "peor_mes_pct": 100 * mensual.min(),
        "max_dd_pct": 100 * (eq / eq.cummax() - 1).min(),
    })

pd.DataFrame({"bruto": resumen(bruto[neto.index]),
              "neto": resumen(neto)}).round(2)
```
```output
                   bruto   neto
rent_anual_pct      3.56   3.50
vol_anual_pct       9.24   9.24
sharpe              0.38   0.38
asimetria_mensual  -1.85  -1.85
peor_mes_pct      -22.72 -22.72
max_dd_pct        -49.61 -49.68
```

Neta de costes, la cartera rinde un 3,50 % anual con una volatilidad del 9,24 %: un Sharpe de 0,38. Los costes casi
no importan (de 3,56 % a 3,50 %), porque el orden por tipos cambia poco de un mes a otro y se negocia muy poco. Lo que
sí importa son las otras tres filas: una **asimetría mensual de −1,85**, un peor mes de −22,7 % y una caída máxima del
49,7 %. Con una volatilidad del 9 % y rentabilidades normales, una caída de la mitad del capital sería casi imposible;
el carry la tiene porque sus pérdidas no son normales.

```python
partes = pd.DataFrame({
    "interes": (pesos * interes).sum(axis=1),
    "divisa": (pesos * d_spot).sum(axis=1),
    "costes": -COSTE * giro,
}).loc[neto.index]
(100 * partes.mean() * 260).round(2)
```
```output
interes    6.56
divisa    -3.00
costes    -0.05
dtype: float64
```

La cartera cobra un 6,56 % anual de diferencial y pierde un 3,00 % en los tipos de cambio: se queda con algo más de la
mitad del carry. La respuesta conocida (el spot se lleva un 30 % del diferencial, más los crashes) predice algo
parecido. Los costes, 0,05 puntos al año, son irrelevantes con esta frecuencia.

## Los crashes del carry

La figura de la cabecera es la curva de la cartera neta, con los cinco tramos de crash del generador sombreados. El
mecanismo plantado es el que describe la literatura: en una huida hacia la calidad, las divisas de tipo alto caen y
las de tipo bajo, que hacen de refugio, suben. La cartera está larga de las primeras y corta de las segundas, así que
pierde por los dos lados a la vez.

```python
crashes = {"2008 T4": ("2008-09-15", "2008-12-31"),
           "2010 may": ("2010-05-03", "2010-05-31"),
           "2011 ago-sep": ("2011-08-01", "2011-09-30"),
           "2015 ago-sep": ("2015-08-17", "2015-09-30"),
           "2020 feb-mar": ("2020-02-24", "2020-03-31")}
en_crash = {k: 100 * neto[a:b].sum() for k, (a, b) in crashes.items()}
print(pd.Series(en_crash).round(1).to_string())
print()
mensual = neto.resample("ME").sum()
print((100 * mensual.nsmallest(5)).round(1).to_string())
```
```output
2008 T4        -23.4
2010 may        -7.6
2011 ago-sep    -8.0
2015 ago-sep    -4.4
2020 feb-mar   -15.6

fecha
2009-02-28   -22.7
2020-03-31   -13.2
2008-11-30    -8.6
2022-08-31    -8.3
2010-05-31    -7.6
```

En el último trimestre de 2008 la cartera pierde un 23,4 %, y en febrero y marzo de 2020 un 15,6 %: dos episodios que
se llevan, cada uno, varios años de diferencial. El peor mes, sin embargo, no está en ningún tramo plantado: febrero
de 2009, con −22,7 %, es la caída del 37 % de `BOR` en un mes, una cola de las innovaciones t de Student del modelo de
volatilidad. Es un recordatorio útil: el riesgo de cola de una cartera concentrada en pocas divisas no se limita a los
crashes que uno conoce, y un backtest con los tramos de estrés quitados «porque fueron excepcionales» sobrestima lo que
se puede ganar.

```mermaid
flowchart TB
  E[Estrés en mercados] --> V[Ventas de riesgo]
  V --> A[Caen tipo alto]
  V --> B[Suben refugio]
  A --> P[Pierde el carry]
  B --> P
  P --> L[Cierre forzado]
  L --> A
```

El bucle del diagrama es lo que hace que los crashes del carry sean bruscos: las pérdidas fuerzan a reducir
posiciones, y las ventas empujan aún más abajo las mismas divisas. Para un sistema, la consecuencia práctica es que el
Sharpe y la volatilidad no describen el riesgo: hay que mirar la asimetría, el peor mes y las pérdidas en episodios
concretos, y dimensionar la posición para sobrevivirlos (lección 2.2.2).

## Carry en futuros: la pendiente de la curva

En un futuro, el carry es la pendiente de la curva entre el contrato que se tiene y el siguiente (lección 1.2.3). Si
el primero cotiza por encima del segundo (backwardation), el carry es positivo: con la curva quieta, el contrato que se
tiene sube hacia el contado a medida que vence. `futuros2_carry.parquet` lo trae calculado para los 24 mercados:

$$
c_t = \frac{\ln\left(F_{1,t} / F_{2,t}\right)}{\tau_2 - \tau_1}
$$

```python
cont = pd.read_parquet("futuros2_continuos.parquet")
carry = pd.read_parquet("futuros2_carry.parquet")
spec = pd.read_csv("futuros2_especificaciones.csv",
                   index_col="mercado")

px = cont.pivot(index="fecha", columns="mercado",
                values="cierre_ajustado")
c_anual = carry.pivot(index="fecha", columns="mercado",
                      values="carry_anual")
r_fut = np.log(px).diff()
(100 * c_anual.mean()).groupby(spec["sector"]).agg(
    ["mean", "min", "max"]).round(1)
```
```output
                mean   min  max
sector
agricolas       -3.6  -5.4 -1.4
bonos            1.1   0.3  2.2
divisas          0.6  -1.3  1.9
energia         -2.4 -10.3  4.0
metales         -2.7  -4.7 -0.6
renta_variable  -0.0  -0.1  0.1
```

El carry medio depende del sector. Los bonos tienen carry positivo (un 1,1 % de media), mayor cuanto más largo el
plazo; los agrícolas y los metales, negativo (−3,6 % y −2,7 %), como el contango por almacenamiento y financiación de
muchas materias primas; la energía va del −10,3 % del gas al +4,0 % del crudo pesado; los índices, casi cero, porque
su carry en el generador es un 2 % menos el tipo libre, que de media está cerca del 2 %. Ordenar los 24 mercados por
carry es en parte ordenar sectores, y en parte algo que cambia con el tiempo: el carry de una materia prima se mueve
con su precio.

En estos datos el carry tiene dos partes, y no pagan lo mismo. Los precios de las materias primas, las divisas y los
bonos revierten hacia un nivel de referencia (un ancla que crece despacio), como en el modelo de un factor de Schwartz
(1997)[^1]. Cuando el contado está muy por encima del ancla, la curva entra en backwardation porque el mercado ya espera
que baje; cuando está muy por debajo, en contango. Esa parte del carry, la de **reversión**, es «justa»: descuenta un
movimiento esperado del contado y casi no predice el rendimiento del futuro. La otra, la **exógena** (almacenamiento,
financiación, presión de las coberturas), es la que lleva la prima. La respuesta conocida del generador, en términos
anuales, es:

$$
E[r] = 0{,}5\,c^{\text{exo}} + 0{,}1\,c^{\text{rev}} + 0{,}15\,\sigma\,\operatorname{signo}\left(r_{252}\right)
$$

más la prima de la renta variable en los índices y una caída de los bonos en 2022. El último término es una prima de
tendencia: la volatilidad del mercado por el signo de su rendimiento de las 252 sesiones anteriores. Solo se observa
la suma $c = c^{\text{exo}} + c^{\text{rev}}$, y la parte de reversión está correlada con la tendencia: un mercado que
lleva un año subiendo está por encima de su ancla, en backwardation y con tendencia positiva. Una regresión sobre el
carry solo mezcla las tres cosas; con la tendencia a la vez, separa al menos la última.

```python
fin_f = px.index.to_series().groupby(px.index.to_period("M")).max()
r_sig = np.log(px.loc[fin_f]).diff().shift(-1) * 12
sigma = r_fut.std() * np.sqrt(252)          # σ de cada mercado
tend = sigma * np.sign(np.log(px).diff(252)).loc[fin_f]
datos_c = pd.DataFrame({"y": r_sig.stack(),
                        "carry": c_anual.loc[fin_f].stack(),
                        "tend": tend.stack()}).dropna()
grupos = datos_c.index.get_level_values("fecha").astype(str)
for x in (["carry"], ["carry", "tend"]):
    m = sm.OLS(datos_c["y"], sm.add_constant(datos_c[x])).fit(
        cov_type="cluster", cov_kwds={"groups": grupos})
    print(", ".join(f"{k} {m.params[k]:.2f} (et {m.bse[k]:.2f})"
                    for k in x))
print(f"n = {len(datos_c)}; correlación carry-tendencia: "
      f"{datos_c['carry'].corr(datos_c['tend']):.2f}")
```
```output
carry 0.27 (et 0.13)
carry 0.17 (et 0.14), tend 0.11 (et 0.08)
n = 7176; correlación carry-tendencia: 0.49
```

Sola, la pendiente del carry es 0,27 con un error típico de 0,13: ni el 0,5 de la parte exógena ni el 0,1 de la
reversión, sino una mezcla de las dos. Con la tendencia en la regresión, el carry baja a 0,17 y la tendencia sale 0,11
(verdad: 0,15). Parte de lo que la regresión simple atribuía al carry era momentum, porque las dos variables tienen una
correlación de 0,49 a fin de mes. El README de los datos da 0,26, 0,15 y 0,12 con la volatilidad de su tabla y otra
anualización: la misma conclusión. La $\sigma$ de la celda es la volatilidad de toda la muestra de cada mercado, un
factor de escala constante como el de la tabla; para medir vale, para operar habría que usar la de la ventana anterior.

Los errores típicos están agrupados por mes porque los 24 mercados comparten sus sorpresas, y son grandes: con el
carry y la tendencia juntos, ninguno de los dos coeficientes llega a dos errores típicos. Los 7.176 meses-mercado
parecen muchos, pero son 299 meses de 24 mercados correlados. Y la regresión no puede separar las dos partes del
carry, porque solo ve la suma: el 0,5 plantado en la parte exógena no se recupera con una regresión sobre el carry
observado.

*Fig. — Carry de fin de mes y rentabilidad del mes siguiente en los 24 futuros, en veinte grupos por carry.* Dispersión de veinte puntos: cada uno es la media de unos 360 meses-mercado agrupados por su carry, de -39 % a +28 % anual en el eje horizontal, frente a su rentabilidad anualizada del mes siguiente. Los puntos suben de izquierda a derecha con mucho ruido. Una recta destacada marca el ajuste de la regresión, con pendiente 0,27; una discontinua, más empinada, la pendiente de 0,5 que se vería si todo el carry fuera la parte exógena, la que lleva la prima en el generador.

La figura agrupa las observaciones en veinte grupos por carry y pinta la rentabilidad media del mes siguiente de cada
uno, con la recta ajustada y, discontinua, la de pendiente 0,5 que se vería si todo el carry fuera exógeno. La relación
se ve, pero también su ruido: cada punto es la media de unos 360 meses-mercado y aun así se separa de la recta varios
puntos porcentuales.

### Una cartera de carry en futuros con costes por tick

La cartera compra los ocho mercados de carry más alto y vende los ocho de carry más bajo, con un peso inverso a su
volatilidad de 63 sesiones para que cada posición aporte un riesgo parecido (un 2,5 % anual). Se rehace al cierre de
cada mes y entra en la sesión siguiente. Los costes salen de las especificaciones: `coste_tipico_ticks` ticks de
deslizamiento más la comisión, por contrato y lado, divididos por el nominal del contrato (precio × multiplicador).
Además, cada **roll** (el cambio de contrato) paga dos lados sobre toda la posición.

```python
precio = cont.pivot(index="fecha", columns="mercado", values="cierre")
contrato = cont.pivot(index="fecha", columns="mercado",
                      values="contrato")
coste_pb = ((spec["coste_tipico_ticks"] * spec["valor_tick"]
             + spec["comision_usd"])
            / (precio * spec["multiplicador"]) * 1e4)
coste_pb.median().sort_values().round(1).iloc[[0, 1, 2, -3, -2, -1]]
```
```output
mercado
IDB     0.7
DIA     0.8
BOA     0.9
AGA    10.9
AGB    11.3
MEB    13.2
dtype: float64
```

En los mercados financieros, un lado cuesta menos de un punto básico del nominal: 0,7 en el índice `IDB`, 0,8 en la
divisa `DIA` y 0,9 en el bono a 2 años `BOA`. En los contratos cuyo tick y comisión pesan más frente al nominal, el
coste se multiplica por más de diez: 10,9 puntos básicos en el maíz `AGA`, 11,3 en el trigo `AGB` y 13,2 en la plata
`MEB`. Además, un coste que se mide en ticks depende del precio: si el precio de un contrato cae a la mitad, su coste
en porcentaje se duplica. Es un detalle que un backtest con un coste fijo en puntos básicos no ve (lección 2.4.7).

```python
vol = r_fut.rolling(63).std() * np.sqrt(252)
puesto_f = c_anual.loc[fin_f].rank(axis=1)
n_f = puesto_f.notna().sum(axis=1)
lado = ((puesto_f > n_f.to_numpy()[:, None] - 8).astype(float)
        - (puesto_f <= 8).astype(float))
pesos_f = (lado * 0.025 / vol.loc[fin_f]).fillna(0)
pesos_f = pesos_f.reindex(px.index, method="ffill").shift(1)

roll = contrato.ne(contrato.shift(1)) & contrato.shift(1).notna()
coste = (pesos_f.diff().abs() * coste_pb
         + 2 * pesos_f.abs() * coste_pb * roll) / 1e4
bruto_f = (pesos_f * r_fut).sum(axis=1)["2001":]
neto_f = bruto_f - coste.sum(axis=1)["2001":]
pd.DataFrame({"bruto": resumen(bruto_f, 252),
              "neto": resumen(neto_f, 252)}).round(2)
```
```output
                   bruto   neto
rent_anual_pct      7.36   5.71
vol_anual_pct      11.64  11.64
sharpe              0.63   0.49
asimetria_mensual   0.01   0.01
peor_mes_pct      -12.67 -12.78
max_dd_pct        -32.03 -33.71
```

Bruta, la cartera rinde un 7,36 % anual con un Sharpe de 0,63; neta, un 5,71 % y 0,49. Los costes, 1,65 puntos al año,
se llevan algo más de una quinta parte de la prima: el rebalanceo mensual cambia pocas posiciones, pero cada roll paga
dos lados sobre toda la posición, y en los mercados caros de la celda anterior eso suma. A diferencia del carry de
divisas, la asimetría mensual es casi cero (0,01): en estos futuros, los mercados de carry alto y bajo no caen todos
a la vez en las crisis del guion. La caída máxima es del 33,7 %, y el resultado no es estable en el tiempo:

```python
periodos = [("2001", "2009"), ("2010", "2019"), ("2020", "2025")]
sh = {f"{a}-{b}": resumen(neto_f[a:b], 252)["sharpe"]
      for a, b in periodos}
print(pd.Series(sh).round(2).to_dict())
sector = spec["sector"].reindex(px.columns)
peso_22 = pesos_f.loc["2022"].mean().groupby(sector).sum()
res_22 = (pesos_f * r_fut).loc["2022"].sum().groupby(sector).sum()
pd.DataFrame({"peso_medio_2022": peso_22,
              "resultado_2022_pct": 100 * res_22}).round(2)
```
```output
{'2001-2009': 0.79, '2010-2019': 0.58, '2020-2025': -0.06}
                peso_medio_2022  resultado_2022_pct
sector
agricolas                 -0.08                0.50
bonos                      1.35              -23.90
divisas                   -0.15                2.23
energia                    0.03               -4.42
metales                   -0.21               -1.56
renta_variable             0.06                0.31
```

El Sharpe neto es de 0,79 en 2001-2009, de 0,58 en 2010-2019 y de −0,06 en 2020-2025. El último tramo tiene un
culpable claro: en 2022 la cartera está larga de bonos con un peso medio del 135 % del capital, y los bonos pierden
23,9 puntos ese año (el generador planta una caída de los bonos en 2022, como la de los mercados reales). Ese peso no
lo eligió nadie: sale de ponderar por la inversa de la volatilidad. Un bono a 2 años con una volatilidad del 2 %
recibe un nominal unas diecisiete veces mayor que un crudo con un 35 % para aportar el mismo riesgo en calma, y cuando
los bonos caen a la vez, como en 2022, el riesgo que se suponía repartido estaba concentrado. El README de los
datos mide una cartera algo distinta (la mitad de los mercados contra la otra mitad, pesos del 10 % entre la
volatilidad) y encuentra lo mismo: Sharpe de 0,45 en toda la muestra y negativo en 2020-2025.

La cartera, además, no es una apuesta pura por el carry. Con la reversión «justa» dentro de la señal y una correlación
de 0,49 con la tendencia, parte de lo que gana es momentum disfrazado, y parte de lo que paga es reversión que la curva
ya había descontado. Saber qué prima se está cobrando importa para combinarla con otras estrategias (lección 2.3.1).

## Bonos: carry y roll-down

En un bono financiado, el carry tiene dos partes. La primera es el rendimiento menos el tipo al que se financia la
posición. La segunda, el **roll-down**: con una curva de pendiente positiva, un bono a 10 años es al cabo de un año un
bono a 9 años, que se valora con un rendimiento más bajo, y su precio sube aunque la curva no se haya movido. Para un
horizonte $h$ (en años), con la curva quieta y la duración modificada $D$:

$$
\text{carry} \approx (y_T - r)\,h + D_{T-h}\,\left(y_T - y_{T-h}\right)
$$

Los futuros de bonos del nivel no traen una curva de rendimientos, así que el cálculo se hace con una curva de
ejemplo: un bono a 10 años con cupón igual a su rendimiento, valorado hoy y dentro de un año con la misma curva.

```python
plazos = np.array([1, 2, 5, 7, 9, 10, 30])
curva = np.array([3.50, 3.55, 3.80, 3.98, 4.16, 4.25, 4.70]) / 100
r_fin = 0.034                         # financiación a un año

def precio_bono(cupon, rend, anos):
    t = np.arange(1, anos + 1)
    return (cupon / (1 + rend) ** t).sum() + 1 / (1 + rend) ** anos

y10 = np.interp(10, plazos, curva)
y9 = np.interp(9, plazos, curva)
hoy = precio_bono(y10, y10, 10)                  # = 1 (a la par)
en_un_ano = precio_bono(y10, y9, 9)              # misma curva
total = (en_un_ano + y10) / hoy - 1
print(f"cupón {100 * y10:.2f} %, roll-down "
      f"{100 * (en_un_ano / hoy - 1):.2f} %, "
      f"menos financiación {100 * r_fin:.2f} %")
print(f"carry total a un año: {100 * (total - r_fin):.2f} %")
```
```output
cupón 4.25 %, roll-down 0.66 %, menos financiación 3.40 %
carry total a un año: 1.51 %
```

El bono cobra su cupón del 4,25 % y gana un 0,66 % de precio al rodar de 10 a 9 años; financiado al 3,40 %, el carry
total a un año es del 1,51 %. La aproximación de la fórmula da lo mismo: (4,25 − 3,40) % por un año, más una duración
cercana a 7,4 por los 9 puntos básicos que separan los rendimientos a 10 y a 9 años.

*Fig. — Roll-down de un bono a 10 años: con la curva quieta, en un año pasa a valorarse con el rendimiento a 9 años (esquema).* Curva de rendimientos de ejemplo, del 3,50 % a 1 año al 4,70 % a 30, con pendiente positiva. Un punto destacado marca el bono hoy, a 10 años y 4,25 %; otro, el mismo bono dentro de un año, a 9 años y 4,16 %. El tramo entre los dos es el roll-down, una ganancia de precio del 0,66 %. Una línea discontinua horizontal marca la financiación al 3,40 %.

La figura lo dibuja sobre la curva de ejemplo: el bono empieza en el plazo de 10 años y, con la curva quieta, termina
el año en el de 9, con un rendimiento más bajo. Cuanto más empinado el tramo por el que rueda, mayor el roll-down, y
cuanto más larga la duración, más precio da cada punto básico. Una estrategia de carry en bonos elige plazos con el
mayor carry más roll-down por unidad de duración. En los futuros de bonos ese carry ya está en la pendiente de la curva
de futuros: es lo que miden las filas `bonos` del carry por sector.

## Estacionalidad y efectos calendario: el control

La lección 1.6.3 midió los efectos calendario clásicos (día de la semana, mes, cambio de mes) y enseñó por qué casi
ninguno resiste. Aquí sirven de **control**: el generador del nivel 2 no planta ningún efecto calendario en los
índices de renta variable. Todo lo que aparezca es azar o un artefacto de los datos. Se prueban los cinco futuros de
índices (`IDA` a `IDE`), comparando cada día con el resto, no con cero:

```python
from scipy import stats

indices = ["IDA", "IDB", "IDC", "IDD", "IDE"]
ri = r_fut[indices].dropna()
dia = ri.index.dayofweek
filas = []
for m in indices:
    for d, nombre in enumerate(["lun", "mar", "mié", "jue", "vie"]):
        t, p = stats.ttest_ind(ri[m][dia == d], ri[m][dia != d],
                               equal_var=False)
        filas.append({"indice": m, "dia": nombre, "t": t, "p": p})
dow = pd.DataFrame(filas)
print("p < 0,05:", (dow["p"] < 0.05).sum(), "de", len(dow),
      "| esperados por azar:", 0.05 * len(dow))
print(dow.nsmallest(3, "p").round(3).to_string(index=False))
print("correlación media entre índices:",
      round(ri.corr().to_numpy()[np.triu_indices(5, 1)].mean(), 2))
```
```output
p < 0,05: 1 de 25 | esperados por azar: 1.25
indice dia      t     p
   IDD jue  2.132 0.033
   IDE jue  1.571 0.116
   IDD lun -1.402 0.161
correlación media entre índices: 0.81
```

Uno de los 25 contrastes tiene p < 0,05 (`IDD` los jueves, p = 0,033), donde el azar espera 1,25. Y los 25 no son
independientes: los cinco índices tienen una correlación media de 0,81, así que cuando uno sale «casi significativo» un
día, los otros suelen apuntar en la misma dirección. El número efectivo de pruebas es menor de lo que parece, y el de
falsos positivos, más variable.

```python
g = ri.groupby(ri.index.to_period("M"))
cambio = (g.cumcount() < 3) | (g.cumcount(ascending=False) == 0)
estres = pd.Series(False, index=ri.index)
for a, b in [("2000-09-01", "2002-10-09"), ("2008-09-02", "2009-03-09"),
             ("2010-04-26", "2010-07-05"), ("2011-07-25", "2011-10-03"),
             ("2015-08-17", "2016-02-11"), ("2018-10-01", "2018-12-25"),
             ("2020-02-20", "2020-03-23"), ("2022-01-04", "2022-10-12"),
             ("2025-02-20", "2025-04-08")]:
    estres[a:b] = True

def tom(r, sel):
    a, b = r[cambio & sel], r[~cambio & sel]
    p = stats.ttest_ind(a, b, equal_var=False).pvalue
    return 1e4 * a.mean(), 1e4 * b.mean(), p

filas = {}
for m in indices:
    for nombre, sel in [("todo", estres | ~estres),
                        ("calma", ~estres), ("estrés", estres)]:
        filas[(m, nombre)] = tom(ri[m], sel)
pd.DataFrame(filas, index=["cambio_pb", "resto_pb", "p"]).T.round(3)
```
```output
            cambio_pb  resto_pb      p
IDA todo       -3.918     4.029  0.061
    calma       3.925     8.931  0.192
    estrés    -37.550   -18.249  0.202
IDB todo       -3.288     4.062  0.146
    calma       6.372     7.828  0.757
    estrés    -44.710   -13.054  0.069
IDC todo       -1.426     3.165  0.337
    calma       8.367     8.104  0.954
    estrés    -43.421   -19.280  0.122
IDD todo       -4.112     4.007  0.079
    calma       3.014     9.480  0.126
    estrés    -34.670   -20.870  0.400
IDE todo       -2.185     3.622  0.208
    calma       7.813     7.804  0.998
    estrés    -45.058   -15.388  0.064
```

El cambio de mes (el último día y los tres primeros de cada mes) rinde menos que el resto en los cinco índices, aunque
en ninguno con p < 0,05 (el menor, `IDA`, con 0,061). Separado por tramos, la diferencia casi desaparece en calma
(ningún p baja de 0,12) y se concentra en los tramos de estrés, donde las sesiones de cambio de mes caen de media entre
35 y 45 puntos básicos, de 1,7 a 3,4 veces lo que caen las demás. Son unas pocas sesiones de crisis con caídas grandes,
y varios tramos de estrés del guion empiezan el primer día de un mes. Cinco diferencias del mismo signo parecen una
confirmación, pero con índices correlados en 0,81 son casi la misma prueba repetida cinco veces. Un artefacto de los
datos con aspecto de efecto calendario: justo lo que hay que saber reconocer.

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

Un efecto calendario que se descubre en los datos y no se había formulado antes es una hipótesis, no un resultado. Si
se quiere operar, hay que escribir la hipótesis con su mecanismo (flujos de nóminas, rebalanceos de fondos, horarios
de publicación), registrarla (lección 2.2.4) y contrastarla en datos que no se usaron para encontrarla. La lección
2.1.8 da las correcciones para cuando se prueban muchas a la vez.

</aside>

## Lo que el carry exige en real

- **Ejecución y costes.** La señal se conoce al cierre y la posición entra en la sesión siguiente. En divisas, la
  horquilla de las de tipo alto se abre justo en los crashes; en futuros, los contratos de precio bajo pagan mucho por
  tick, y cada roll es un coste fijo que el carry tiene que pagar (lección 2.4.7).
- **Financiación real.** El diferencial que se cobra es el de los tipos a los que el bróker o el banco remunera y cobra,
  no el oficial. En un CFD o una cuenta de forex minorista, el rollover descuenta un margen sobre los dos tipos
  (lección 1.2.4) que puede comerse buena parte del carry.
- **Riesgo de cola.** El resultado medio esconde una distribución con asimetría negativa. Una cartera de carry tiene
  que dimensionarse por su peor mes, no por su volatilidad, y conviene combinarla con estrategias que ganen en las
  crisis (la tendencia de la lección 2.3.1 lo hace en estos datos).
- **Concentración por sector y por nominal.** El carry de futuros ordenado sin más es en parte una apuesta por
  sectores, y con pesos inversos a la volatilidad los bonos acaparan el nominal: en 2022, la cartera de la lección
  tenía de media el 135 % del capital en bonos. Neutralizar por sector (ejercicio 1) y limitar el nominal por sector
  cambian mucho la cartera.

## Ejercicios

1. Repite la cartera de carry en futuros ordenando el carry **dentro de cada sector** (resta la media del sector en
   cada fecha antes de ordenar). ¿Cambian el Sharpe y la asimetría?

**Solución.**

```python
sector = spec["sector"].reindex(c_anual.columns)
c_rel = c_anual.loc[fin_f] - c_anual.loc[fin_f].T.groupby(
    sector).transform("mean").T
puesto_s = c_rel.rank(axis=1)
lado_s = ((puesto_s > n_f.to_numpy()[:, None] - 8).astype(float)
          - (puesto_s <= 8).astype(float))
pesos_s = (lado_s * 0.025 / vol.loc[fin_f]).fillna(0)
pesos_s = pesos_s.reindex(px.index, method="ffill").shift(1)
coste_s = (pesos_s.diff().abs() * coste_pb
           + 2 * pesos_s.abs() * coste_pb * roll) / 1e4
neto_s = ((pesos_s * r_fut).sum(axis=1)
          - coste_s.sum(axis=1))["2001":]
pd.DataFrame({"global": resumen(neto_f, 252),
              "por_sector": resumen(neto_s, 252)}).round(2)
```
```output
                   global  por_sector
rent_anual_pct       5.71        2.33
vol_anual_pct       11.64        8.99
sharpe               0.49        0.26
asimetria_mensual    0.01        0.21
peor_mes_pct       -12.78       -7.17
max_dd_pct         -33.71      -34.07
```

Neutral por sector, el Sharpe baja de 0,49 a 0,26 y la rentabilidad, del 5,71 % al 2,33 % anual. Algo más de la mitad
de la prima de estos datos está **entre** sectores: los carry exógenos medios son distintos (el gas en contango
profundo, los bonos con carry positivo) y la cartera global los aprovecha. El resto está **dentro** de cada sector,
donde el carry de cada mercado se mueve con su precio. Baja la volatilidad (del 11,64 % al 8,99 %) y el peor mes
(del −12,78 % al −7,17 %), pero no la caída máxima (34,07 %), y la asimetría mensual pasa a ser positiva (0,21). En
mercados reales, Koijen y coautores (2018) encuentran la prima del carry también dentro de cada clase de activo.

2. En la cartera de carry en divisas, sube el coste a 10 puntos básicos por lado y cambia el rebalanceo a semanal
   (último día de cada semana). ¿Cuánto Sharpe se pierde en cada caso?

**Solución.**

```python
def cartera_fx(fechas, coste):
    pt = dif.loc[fechas].rank(axis=1)
    pm = ((pt >= 8).astype(float) - (pt <= 3).astype(float)) / 3
    w = pm.reindex(spot.index, method="ffill").shift(1)
    giro = w.diff().abs().sum(axis=1)
    r = (w * r_fx).sum(axis=1) - coste / 1e4 * giro
    return r[w.abs().sum(axis=1) > 0]

fin_sem = (spot.index.to_series()
           .groupby(spot.index.to_period("W")).max())
casos = {"mensual, 3 pb": cartera_fx(fin_mes, 3),
         "mensual, 10 pb": cartera_fx(fin_mes, 10),
         "semanal, 3 pb": cartera_fx(fin_sem, 3),
         "semanal, 10 pb": cartera_fx(fin_sem, 10)}
pd.Series({k: resumen(v)["sharpe"] for k, v in casos.items()}).round(2)
```
```output
mensual, 3 pb     0.38
mensual, 10 pb    0.37
semanal, 3 pb     0.35
semanal, 10 pb    0.33
dtype: float64
```

El Sharpe apenas se mueve: de 0,38 a 0,37 con 10 puntos básicos, y a 0,35 o 0,33 con rebalanceo semanal. La cartera
cambia de divisas tan pocas veces que los costes no la deciden; el rebalanceo semanal añade giro sin información
nueva, porque los tipos solo cambian una vez al mes. En una estrategia de carry, la frecuencia natural es la de la
señal: rebalancear más rápido que ella solo paga costes.

3. Un compañero encuentra que `IDA` sube de media un 3 % en noviembre (t = 2,5) y propone comprar el índice solo ese
   mes. Explica qué falta antes de tomárselo en serio.

**Solución.**

Es uno de doce meses probados en un índice, y el mismo contraste en los otros cuatro índices, que tienen una
correlación de 0,8 con él, no es una prueba independiente: el número efectivo de contrastes es grande y uno con t = 2,5
es lo esperable por azar (con doce contrastes al 5 %, la probabilidad de al menos uno significativo es del 46 %). Un
efecto mensual se mide con un dato por año: 26 noviembres, de los que uno o dos años de rebote tras una crisis bastan
para mover la media. Falta una hipótesis previa con mecanismo, la corrección por pruebas múltiples (lección 2.1.8) y
un contraste fuera de la muestra. En estos datos, además, se sabe la respuesta: el generador no planta ningún efecto
calendario.

[^1]: Eduardo S. Schwartz, «The Stochastic Behavior of Commodity Prices: Implications for Valuation and Hedging»,
    The Journal of Finance 52(3), 1997, <https://doi.org/10.1111/j.1540-6261.1997.tb02721.x>.

## Autoevaluación

1. En la regresión de Fama de los datos, el cambio del tipo de cambio sobre el diferencial de tipos da una pendiente de −0,53 con un error típico de 0,36. ¿Qué concluyes?

   - A. Que se cumple la paridad descubierta de tipos (pendiente −1)
   - B. Que el tipo de cambio es un paseo aleatorio (pendiente 0)
   - C. Que la regresión es demasiado imprecisa para separar −1, −0,3 y 0 con 21 años de datos; la rentabilidad de la cartera es una medida más directa
   - D. Que el carry no gana dinero

   *Respuesta C: Que la regresión es demasiado imprecisa para separar −1, −0,3 y 0 con 21 años de datos; la rentabilidad de la cartera es una medida más directa.* Con un error típico de 0,36, el intervalo al 95 % va de −1,24 a +0,18: incluye la paridad (−1), la respuesta conocida (−0,3) y el paseo aleatorio (0). Los crashes, además, empujan la pendiente hacia valores más negativos. La regresión de Fama es la referencia académica, pero con diez divisas y veinte años no decide nada por sí sola.

2. La cartera de carry en divisas tiene una asimetría mensual de −1,8. ¿Qué significa para quien la opera?

   - A. Que gana poco y a menudo y pierde mucho de golpe: los peores meses coinciden con las huidas hacia la calidad
   - B. Que pierde dinero casi todos los meses
   - C. Que el Sharpe está sobrestimado por un error de cálculo
   - D. Que sus rentabilidades son normales

   *Respuesta A: Que gana poco y a menudo y pierde mucho de golpe: los peores meses coinciden con las huidas hacia la calidad.* Una asimetría negativa grande es la firma del carry: el diferencial se cobra día a día y las divisas de tipo alto caen todas a la vez cuando el mercado busca refugio. En los datos, el último trimestre de 2008 y febrero de 2009 se llevan varios años de ganancias.

3. Un futuro cotiza a 100 con vencimiento en 2 meses y el siguiente a 101 con vencimiento en 5 meses. ¿Cuál es su carry anual con la definición de la lección?

   - A. +4 % (backwardation)
   - B. +1 %
   - C. 0 %
   - D. −4 % (contango: el largo pierde si la curva no cambia)

   *Respuesta D: −4 % (contango: el largo pierde si la curva no cambia).* c = ln(100/101) / (5/12 − 2/12) = −0,00995 / 0,25 ≈ −4 % anual. La curva sube con el plazo (contango): si no se mueve, el contrato que se tiene pasa a valorarse en un plazo más corto, más barato, y el largo pierde ese 4 % anual.

4. En cinco índices bursátiles se contrasta el efecto día de la semana: 25 contrastes y uno sale con p = 0,04. ¿Qué haces?

   - A. Operar ese día
   - B. Nada: con 25 contrastes al 5 % se esperan 1,25 significativos por azar, y además los cinco índices tienen una correlación de 0,8, así que no son 25 pruebas independientes
   - C. Repetir el contraste con más decimales
   - D. Quitar los años malos y volver a probar

   *Respuesta B: Nada: con 25 contrastes al 5 % se esperan 1,25 significativos por azar, y además los cinco índices tienen una correlación de 0,8, así que no son 25 pruebas independientes.* Un único p = 0,04 entre 25 contrastes es justo lo que da el azar. En estos datos no hay ningún efecto calendario plantado: es el control. La corrección por pruebas múltiples (lección 2.1.8) lo deja muy lejos de cualquier umbral.

5. ¿Qué parte del rendimiento de un bono a 10 años es roll-down?

   - A. El cupón
   - B. El cambio de los tipos del banco central
   - C. La ganancia de precio que se obtiene, con la curva sin cambios, porque el bono envejece y pasa a valorarse con el rendimiento más bajo de un plazo más corto
   - D. La diferencia entre el precio limpio y el sucio

   *Respuesta C: La ganancia de precio que se obtiene, con la curva sin cambios, porque el bono envejece y pasa a valorarse con el rendimiento más bajo de un plazo más corto.* Con una curva con pendiente positiva, un bono a 10 años es un año después un bono a 9 años. Si la curva no se mueve, su rendimiento baja del de 10 al de 9 años y su precio sube: eso es el roll-down. El cupón menos la financiación es el carry en sentido estricto.

## Ideas clave

- Carry es la rentabilidad de una posición si los precios no cambian: diferencial de tipos en divisas, pendiente de la curva en futuros, cupón menos financiación más roll-down en bonos.
- En los datos, el carry de divisas gana el 70 % del diferencial (la respuesta conocida); la cartera de tres contra tres rinde un Sharpe de 0,38 neto de costes, con asimetría mensual de −1,85 y una caída máxima del 50 %.
- La pendiente del rendimiento de los futuros sobre su carry sale 0,27 (error típico 0,13), menos que el 0,5 de la parte exógena: buena parte del carry es reversión a la media que la curva ya descuenta; con la tendencia en la regresión, baja a 0,17.
- El carry pierde de golpe en las huidas hacia la calidad: el riesgo está en las colas, no en la volatilidad, y el Sharpe lo esconde.
- La señal se calcula al cierre y la posición empieza en la sesión siguiente. La cartera de carry en futuros da un Sharpe neto de 0,49, pero negativo en 2020-2025: larga de bonos con pesos inversos a la volatilidad, pierde en 2022 cuando los bonos caen.
- Los efectos calendario de los datos son el control: los pocos significativos que aparecen son los que da el azar entre decenas de contrastes correlados.

## Recursos

### Research

- [Impacto del factor estacional sobre los bonos americanos](https://pythonparatrading.com/estacionalidad-usa-yields/) · Research-0017 · 3 min
- [Bancos Centrales y Política Monetaria en Python](https://pythonparatrading.com/politica-monetaria-en-python/) · Research-0010 · 15 min

### Documentación

- [Koijen, Moskowitz, Pedersen y Vrugt (2018): Carry, Journal of Financial Economics 127(2)](https://doi.org/10.1016/j.jfineco.2017.11.002) · doi.org
- [Fama (1984): Forward and spot exchange rates, Journal of Monetary Economics 14(3)](https://doi.org/10.1016/0304-3932(84)90046-1) · doi.org
- [Brunnermeier, Nagel y Pedersen (2008): Carry Trades and Currency Crashes, NBER Macroeconomics Annual 23](https://doi.org/10.1086/593088) · doi.org
- [statsmodels: OLS con errores agrupados (cov_type="cluster")](https://www.statsmodels.org/stable/generated/statsmodels.regression.linear_model.RegressionResults.get_robustcov_results.html) · statsmodels.org

### Datos

- [Datos del nivel 2: divisas con tipos de interés (Parquet)](https://pythonparatrading.com/curso/datos/nivel-2/fx2_carry.parquet) · Descarga · fx2_carry.parquet

Lección anterior: [2.3.3 · Pairs trading y arbitraje estadístico: distancia, cointegración y Kalman](https://pythonparatrading.com/curso-python-trading/nivel-2/pairs-trading-y-arbitraje-estadistico/)

Lección siguiente: [2.3.5 · Factores (value, calidad, baja volatilidad, tamaño) y estrategias de eventos](https://pythonparatrading.com/curso-python-trading/nivel-2/factores-y-estrategias-de-eventos/)
