---
title: "2.2.3 Frecuencias de trading y capacidad de una estrategia"
description: "Intradía, swing y posicional: rotación, sensibilidad a los costes, Sharpe neto y capacidad con la ley de la raíz cuadrada del impacto, en Python."
url: "https://pythonparatrading.com/curso-python-trading/nivel-2/frecuencias-y-capacidad-de-una-estrategia/"
lang: "es"
image: "https://pythonparatrading.com/og/curso-python-trading/nivel-2/frecuencias-y-capacidad-de-una-estrategia.png"
---

# 2.2.3 · Frecuencias: intradía, swing y posicional, y la capacidad de una estrategia

> Cuanto más corto es el horizonte de una estrategia, más operaciones hace, antes se puede comprobar si funciona y más le cuestan los costes y el impacto. Esta lección mide las tres cosas con barras de 5 minutos y con datos diarios, y estima cuánto capital admite cada horizonte antes de que el impacto se coma la ventaja.

- Curso: [Nivel 2: Estrategias sistemáticas y backtesting riguroso](https://pythonparatrading.com/curso-python-trading/nivel-2/)
- Módulo: 2.2 · Anatomía de un sistema de trading
- Duración: 65 min
- Requisitos: [2.2.2 · Universo, señal, filtro, entrada, salida, sizing y gestión del riesgo](https://pythonparatrading.com/curso-python-trading/nivel-2/universo-senal-filtro-entrada-salida-y-sizing/), [1.1.5 · Costes, liquidación, apalancamiento y margen](https://pythonparatrading.com/curso-python-trading/nivel-1/costes-liquidacion-apalancamiento-y-margen/), [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/)

## Al terminar esta lección

- Distinguir los horizontes intradía, swing y posicional por su rotación, sus costes, su error de estimación y sus competidores.
- Medir la rotación anual de una estrategia y su Sharpe neto con varios niveles de coste, y comprobar la aproximación SR neto ≈ SR bruto − coste anual / volatilidad.
- Estimar el impacto de mercado con la ley de la raíz cuadrada, con sus parámetros declarados como supuestos.
- Calcular la curva de capacidad de una estrategia (rentabilidad neta frente al capital) y el capital en que su ventaja se anula.

## Tres horizontes

El **horizonte** de una estrategia es el tiempo típico que mantiene una posición. Se suelen distinguir tres grupos,
sin fronteras exactas:

| Horizonte | Tenencia típica | Datos que necesita | Contra quién compite | Su problema principal |
|---|---|---|---|---|
| Intradía | Minutos a horas; sin posición por la noche | Barras de minutos, ticks, libro | Creadores de mercado, HFT, algoritmos de ejecución | Costes e impacto: cada punto básico cuenta |
| Swing | Días a semanas | Barras diarias, a veces horarias | Fondos cuantitativos, traders discrecionales | Ruido: las señales de días son débiles |
| Posicional | Semanas a meses | Diarias y semanales, fundamentales | CTA, gestoras | Pocas apuestas: hacen falta muchos años para comprobarla |

El horizonte no es una preferencia de estilo: decide casi todo lo demás. Una cadena de consecuencias que esta lección
mide eslabón a eslabón:

```mermaid
flowchart TB
  H[Horizonte corto] --> N[Más operaciones]
  N --> T[Más rotación]
  N --> A[Más apuestas]
  T --> C[Más coste anual]
  T --> K[Menos capacidad]
  A --> E[Menos años de test]
```

Dos eslabones van en contra y uno a favor. Más rotación significa más costes y menos capital admisible; más apuestas
significa que el azar se promedia antes y la ventaja se distingue con menos años de datos. Las tres cosas dependen
del mismo número: cuántas veces al año la estrategia negocia su capital.

## Un efecto intradía: el hueco de apertura de KAPA

Los datos de este apartado son barras de 5 minutos de **KAPA**, un ETF ficticio sobre un índice, en 1.003 sesiones de
la NYSE de 2022 a 2025. Llevan un efecto plantado pequeño (README del nivel 2, sección e): en la primera media hora el
precio recupera, de media, un 10 % del **hueco** de apertura (la diferencia entre la apertura y el cierre anterior).
Fuera de la primera media hora, los rendimientos no tienen autocorrelación: es el control.

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

b = pd.read_parquet("indice2_5min.parquet")
ny = b["ts"].dt.tz_convert("America/New_York")
b["dia"] = ny.dt.date
b["k"] = b.groupby("dia").cumcount()        # barra del día, desde 0
g = b.groupby("dia")
d = pd.DataFrame({
    "apertura": g["apertura"].first(),
    "cierre": g["cierre"].last(),
    "volumen": g["volumen"].sum(),
    "vol_30m": b[b["k"] < 6].groupby("dia")["volumen"].sum(),
    "c_10h": b[b["k"] == 5].set_index("dia")["cierre"],
    "c_12h": b[b["k"] == 29].set_index("dia")["cierre"],
    "c_1230": b[b["k"] == 35].set_index("dia")["cierre"],
    "c_1130": b[b["k"] == 23].set_index("dia")["cierre"],
})
d["hueco"] = np.log(d["apertura"] / d["cierre"].shift())
d["r_30m"] = np.log(d["c_10h"] / d["apertura"])
d = d.dropna()
print(len(d), "sesiones con hueco")
d[["hueco", "r_30m"]].describe().loc[["mean", "std"]].mul(1e4).round(1)
```
```output
1002 sesiones con hueco
      hueco  r_30m
mean    3.8   -0.3
std    60.8   47.9
```

Las cifras están en puntos básicos (pb, centésimas de punto porcentual). El hueco medio es casi cero, pero su
desviación típica es de unos 60 pb: KAPA abre cada día lejos del cierre anterior. Las medias sesiones (barras 0 a 41)
no tienen barra de las 12:30, por eso caen del control más abajo.

```python
import statsmodels.api as sm

def pendiente(y, x):
    m = sm.OLS(y, sm.add_constant(x)).fit(cov_type="HC1")
    return round(float(m.params.iloc[1]), 3), round(
        float(m.tvalues.iloc[1]), 2)

print("primera media hora sobre el hueco:",
      pendiente(d["r_30m"], d["hueco"]))
ctrl = d.dropna(subset=["c_1230"])
r_antes = np.log(ctrl["c_12h"] / ctrl["c_1130"])
r_despues = np.log(ctrl["c_1230"] / ctrl["c_12h"])
print("12:00-12:30 sobre 11:30-12:00 (control):",
      pendiente(r_despues, r_antes))

# estrategia: contra el hueco desde la apertura hasta las 10:00
contra = -np.sign(d["hueco"]) * d["r_30m"]
sr_bruto = contra.mean() / contra.std() * np.sqrt(252)
print(f"por operación: {1e4 * contra.mean():.2f} pb "
      f"(desv. típica {1e4 * contra.std():.1f} pb)")
print(f"Sharpe bruto anual: {sr_bruto:.2f}")
```
```output
primera media hora sobre el hueco: (-0.132, -3.52)
12:00-12:30 sobre 11:30-12:00 (control): (-0.01, -0.31)
por operación: 4.69 pb (desv. típica 47.6 pb)
Sharpe bruto anual: 1.56
```

La pendiente de la regresión del rendimiento de la primera media hora sobre el hueco es de −0,132 con t de −3,52 (con
errores robustos a la heterocedasticidad, lección 2.1.1): un error típico de 0,04, así que el −0,10 plantado está a
menos de uno. La del control, con los mismos datos y otra hora del día, es de −0,01 con t de −0,31: no se distingue de
cero. La estrategia más simple que explota el efecto (vender en la
apertura si el hueco es al alza, comprar si es a la baja, cerrar a las 10:00) gana unos 4,7 pb por operación de
media con una desviación típica diez veces mayor, y un Sharpe bruto anual de 1,56: la cifra de una estrategia
excelente. Falta pagar.

*Fig. — KAPA, 2022–2025: rendimiento medio de la primera media hora por deciles del hueco de apertura (izquierda) y, como control, el de 12:00 a 12:30 por deciles del de 11:30 a 12:00 (derecha), con su pendiente de regresión.* Dos paneles de puntos por deciles. A la izquierda, el hueco de apertura va de −83 a +113 pb y el rendimiento de la primera media hora cae de +3 a −12 pb: la recta de regresión, destacada, tiene pendiente −0,13 (efecto plantado −0,10). A la derecha, el control de mediodía: los puntos oscilan entre −2,5 y +3 pb sin dirección y la pendiente es −0,01.

## Lo que cuesta operar cada día

Los costes de una operación son la mitad de la horquilla (se compra en el ask y se vende en el bid) más la comisión.
KAPA cotiza en torno a 370 USD; con una horquilla de un céntimo (un supuesto: los datos no traen cotizaciones) y la
tarifa escalonada del broker ficticio Alcor de `costes2_brokers.csv`:

```python
brokers = pd.read_csv("costes2_brokers.csv")
comision = brokers.query("plan == 'escalonado'")["tarifa"].iloc[1]
precio = d["apertura"].median()
coste_lado = (0.01 / 2 + comision) / precio      # en tanto por uno

def neto(r_op, coste, lados=2):
    x = r_op - lados * coste
    return x.mean() / x.std() * np.sqrt(252)

print(f"comisión {comision} USD/acción; precio mediano {precio:.0f}")
print(f"coste por lado: {1e4 * coste_lado:.2f} pb")
for mult in (1, 5, 10):
    print(f"coste x{mult:<2}: Sharpe neto "
          f"{neto(contra, mult * coste_lado):.2f}")
print(f"coste por lado que anula la ventaja: "
      f"{1e4 * contra.mean() / 2:.2f} pb")
```
```output
comisión 0.002 USD/acción; precio mediano 370
coste por lado: 0.19 pb
coste x1 : Sharpe neto 1.44
coste x5 : Sharpe neto 0.93
coste x10: Sharpe neto 0.30
coste por lado que anula la ventaja: 2.34 pb
```

Con los costes del supuesto, apenas 0,2 pb por lado, el Sharpe neto sigue alto. Pero el margen es estrecho: con 2,3
pb por lado la ventaja desaparece. Una horquilla de dos o tres céntimos, un deslizamiento de un tick al abrir (cuando
la horquilla de la apertura es más ancha que la del resto de la sesión, lección 1.1.3) o una comisión minorista
bastan para llegar ahí. La estrategia vive en el último decimal de los costes.

## La misma idea a distintas velocidades

Para ver el efecto del horizonte sobre una sola familia de estrategias, se toma la tendencia de la lección 2.2.2 en su
versión más simple: signo de la rentabilidad de L sesiones, con el mismo riesgo por mercado, en los 24 futuros. Al
bajar L, la estrategia cambia de opinión más a menudo. El coste de cada mercado es el de su fichero de
especificaciones (deslizamiento típico más comisión por contrato) dividido por el nocional del contrato:

```python
fut = pd.read_parquet("futuros2_continuos.parquet")
spec = pd.read_csv("futuros2_especificaciones.csv",
                   index_col="mercado")
aj = fut.pivot(index="fecha", columns="mercado",
               values="cierre_ajustado")
ci = fut.pivot(index="fecha", columns="mercado", values="cierre")
spec = spec.loc[aj.columns]
r = aj.pct_change()
c_contrato = (spec["coste_tipico_ticks"] * spec["valor_tick"]
              + spec["comision_usd"])
c_frac = (c_contrato / (ci * spec["multiplicador"])).shift(1)
vol = r.ewm(span=60, min_periods=60).std() * np.sqrt(252)

def tendencia(L, mult_coste=1.0):
    s = np.sign(np.log(aj / aj.shift(L)))
    w = (s * 0.10 / np.sqrt(aj.shape[1]) / vol).shift(1)
    bruto = (w * r).sum(axis=1).loc["2001":]
    dw = w.diff().abs()
    coste = (dw * c_frac).sum(axis=1).loc["2001":] * mult_coste
    return bruto, coste, dw.sum(axis=1).loc["2001":]

def fila(bruto, coste, giro):
    sr = lambda x: x.mean() / x.std() * np.sqrt(252)
    v = bruto.std() * np.sqrt(252)
    return {"rotacion": 252 * giro.mean(), "vol": v,
            "sr_bruto": sr(bruto), "coste_anual": 252 * coste.mean(),
            "sr_neto": sr(bruto - coste),
            "aprox": sr(bruto) - 252 * coste.mean() / v}

ventanas = [2, 5, 10, 21, 63, 126, 252]
tabla = pd.DataFrame({L: fila(*tendencia(L)) for L in ventanas}).T
tabla.index.name = "L"
tabla.round(3)
```
```output
     rotacion    vol  sr_bruto  coste_anual  sr_neto  aprox
L
2     751.828  0.149     0.362        0.195   -0.952 -0.952
5     475.550  0.150     0.139        0.122   -0.673 -0.673
10    337.859  0.149     0.119        0.087   -0.466 -0.466
21    224.479  0.149     0.402        0.059    0.010  0.010
63    138.463  0.149     0.640        0.035    0.402  0.402
126   100.789  0.146     0.705        0.025    0.535  0.535
252    66.946  0.147     0.999        0.017    0.884  0.884
```

La rotación es la suma anual de los cambios de peso, en veces el capital. Baja de forma continua con la ventana: de
752 veces al año con L = 2 a 67 con L = 252 (incluye el reajuste diario a la volatilidad, que también
negocia). La columna `aprox` es la regla rápida:

$$
SR_{neto} \approx SR_{bruto} - \frac{T \cdot c}{\sigma}
$$

con $T$ la rotación anual, $c$ el coste por unidad negociada y $\sigma$ la volatilidad anual de la estrategia: el coste
anual en rentabilidad, dividido por la volatilidad, se resta del Sharpe. Coincide con el Sharpe neto calculado en
centésimas. Es la cuenta que conviene hacer **antes** del backtest: con la rotación esperada y un coste realista se
sabe qué Sharpe bruto hace falta para que quede algo.

Las ventanas cortas pierden por los dos lados. Su señal bruta es peor: el Sharpe bruto sube de 0,40 con L = 21 a 1,00
con L = 252, porque el término plantado usa el signo de 252 sesiones y una ventana más corta lo recoge peor; por
debajo de 21 sesiones queda entre 0,12 y 0,36, una señal débil y ruidosa. Y cuestan más: con L = 2 el coste anual es
del 19,5 % del capital y el Sharpe neto, de −0,95. La figura de la cabecera pone las siete ventanas y la estrategia de huecos en
un plano de Sharpe frente a rotación: la línea neta se separa de la bruta cuanto más rota la estrategia, y la de
huecos, con 504 vueltas al año, solo sobrevive porque sus costes por operación son diminutos.

## Sensibilidad a los costes

Los costes de referencia son una estimación. La pregunta útil es cuánto peor pueden ser antes de que la estrategia
deje de valer, y cuántos años hacen falta para distinguir su ventaja del azar:

```python
sens = {}
for L in ventanas:
    bruto, coste, _ = tendencia(L)
    sr = lambda x: x.mean() / x.std() * np.sqrt(252)
    sens[f"L={L}"] = {f"x{m}": sr(bruto - m * coste)
                      for m in (0, 1, 2, 3)}
sens["huecos KAPA"] = {f"x{m}": neto(contra, m * coste_lado)
                       for m in (0, 1, 2, 3)}
sens = pd.DataFrame(sens).T
sens["anos_t2"] = (2 / sens["x0"].clip(lower=0.05)) ** 2
sens.round(2)
```
```output
               x0    x1    x2    x3  anos_t2
L=2          0.36 -0.95 -2.26 -3.56    30.60
L=5          0.14 -0.67 -1.48 -2.29   206.57
L=10         0.12 -0.47 -1.05 -1.63   284.39
L=21         0.40  0.01 -0.38 -0.77    24.71
L=63         0.64  0.40  0.16 -0.07     9.77
L=126        0.71  0.53  0.36  0.19     8.04
L=252        1.00  0.88  0.77  0.65     4.01
huecos KAPA  1.56  1.44  1.31  1.18     1.64
```

*Fig. — Sharpe neto con los costes de referencia multiplicados por 0, 1, 2 y 3: tendencia en futuros con ventanas de 21, 63 y 252 sesiones y estrategia de huecos de KAPA.* Cuatro líneas que bajan con el coste. Huecos de KAPA: de 1,56 a 1,18. Tendencia de 252 sesiones, destacada: de 1,00 a 0,65. De 63: de 0,64 a −0,07, negativa con el triple de coste. De 21: de 0,40 a −0,78, negativa ya con el doble.

Dos lecturas de la tabla:

- **Las ventanas largas aguantan los errores de coste; las cortas, no.** La de 252 sesiones sigue con Sharpe de 0,65 con
  el triple de coste. La de 21 ya está en 0,01 con los costes de referencia y pasa a negativa con el doble. Una estrategia cuyo resultado cambia de signo cuando el
  coste se dobla depende sobre todo de un número, el coste, que el backtest no puede medir bien.
- **Las ventanas cortas se comprueban antes.** La columna `anos_t2` es $(2 / SR)^2$: los años de datos que hacen
  falta para que una ventaja con ese Sharpe bruto dé una t de 2. Con el Sharpe de la estrategia de huecos bastan 1,6
  años; con la tendencia de 252 sesiones, 4; con las de 5 y 10, que casi no tienen señal bruta, más de 200. Por eso las mesas de alta frecuencia pueden validar y
  descartar ideas en semanas, y los gestores de tendencia necesitan décadas de historia (y sufren más el riesgo de
  sobreajuste, lección 2.5.4).

## Capacidad: el impacto de mercado

Los costes de la sección anterior son proporcionales: el mismo porcentaje para 1.000 USD que para 100 millones. El
**impacto de mercado** no: una orden grande mueve el precio contra quien la ejecuta mientras la ejecuta, y cuanto
mayor, más lo mueve. La regularidad empírica más estable es la **ley de la raíz cuadrada**[^1]: el impacto medio de una
orden (en tanto por uno del precio) es

$$
I(Q) = Y \cdot \sigma_D \cdot \sqrt{\frac{Q}{V_D}}
$$

con $Q$ el tamaño de la orden, $V_D$ el volumen diario del activo (en las mismas unidades), $\sigma_D$ su volatilidad
diaria e $Y$ un factor empírico. En esta lección se toma $Y = 1$ como **supuesto**: el valor real depende del activo,
del periodo y de cómo se ejecute la orden, y hay que estimarlo con las ejecuciones propias (lección 2.4.7). El coste
total de la orden es $Q \cdot I(Q)$, que crece como $Q^{1,5}$.

Con impacto, la rentabilidad neta deja de ser constante y cae con el capital $A$. Para una estrategia con ventaja
bruta anual $\alpha$ que negocia cada año $T$ veces su capital, repartido en órdenes diarias de tamaño $Q = A\,T/252$:

$$
\alpha_{neto}(A) = \alpha - T\,c - T \cdot Y \sigma_D \sqrt{\frac{A\,T}{252\,V_D}}
$$

El capital que anula la ventaja, la **capacidad** en sentido estricto, sale de igualar a cero:

$$
A_0 = \frac{252\,V_D}{T} \left(\frac{\alpha - T\,c}{T\,Y\,\sigma_D}\right)^2
$$

La rotación aparece al cubo en el denominador: doblar la rotación con la misma ventaja anual divide la capacidad
entre ocho. Y el beneficio en dólares, $A \cdot \alpha_{neto}(A)$, es máximo en $A^* = \frac{4}{9} A_0$: más allá de ese
capital, cada dólar añadido reduce el beneficio total.

Para la estrategia de huecos, las cantidades salen de los datos de KAPA. Cada día hay dos órdenes del tamaño del
capital (entrada y salida), así que $T = 504$ y $Q = A$:

```python
V_usd = (d["volumen"] * d["cierre"]).median()
sigma_d = np.log(d["cierre"] / d["cierre"].shift()).std()
Y = 1.0                                     # supuesto
alfa_op = contra.mean()                     # por operación

def neto_op(A):
    """Rentabilidad neta por operación (ida y vuelta)."""
    impacto = Y * sigma_d * np.sqrt(A / V_usd)
    return alfa_op - 2 * coste_lado - 2 * impacto

A0 = V_usd * ((alfa_op - 2 * coste_lado) / (2 * Y * sigma_d)) ** 2
print(f"volumen diario mediano: {V_usd / 1e9:.1f} mil M USD")
print(f"sigma diaria: {sigma_d:.4f}")
print(f"capacidad A0: {A0 / 1e6:.1f} M USD; óptimo: "
      f"{4 / 9 * A0 / 1e6:.1f} M USD")
part = A0 / (d["vol_30m"] * d["cierre"]).median()
print(f"participación en la primera media hora con A0: {part:.2%}")
for A in (1e6, 3e6, 1e7):
    print(f"A = {A / 1e6:>4.0f} M: {1e4 * neto_op(A):+.2f} pb "
          f"por operación, {252 * A * neto_op(A) / 1e3:,.0f} mil "
          "USD al año")
```
```output
volumen diario mediano: 20.8 mil M USD
sigma diaria: 0.0109
capacidad A0: 8.2 M USD; óptimo: 3.6 M USD
participación en la primera media hora con A0: 0.27%
A =    1 M: +2.80 pb por operación, 71 mil USD al año
A =    3 M: +1.70 pb por operación, 129 mil USD al año
A =   10 M: -0.45 pb por operación, -114 mil USD al año
```

Es la lección de la sección: una estrategia con Sharpe bruto de 1,56 sobre el ETF más líquido de los datos, con
20.800 millones de USD negociados en una sesión mediana, deja de ganar dinero con 8,2 millones de capital. No por falta
de volumen (con $A_0$ se negocia el 0,27 % del volumen de la primera media hora), sino porque su ventaja por operación
es de 4,7 pb y el impacto de la raíz cuadrada se la come antes. El beneficio en dólares es máximo con 3,6 millones:
129.000 USD al año con 3 millones, y pérdidas con 10.

## Curvas de capacidad por horizonte

Para comparar horizontes con la misma vara, la última celda aplica la fórmula del impacto a las estrategias de
tendencia de 21 y de 252 sesiones, mercado a mercado: con la rotación medida de cada uno, su volatilidad diaria y su
volumen diario mediano en dólares, que sale de la columna `volumen` del fichero de futuros (contratos negociados en el
contrato que se tiene) por el precio y el multiplicador:

```python
# volumen diario en USD y volatilidad diaria de cada futuro
fut["usd"] = (fut["volumen"] * fut["cierre"]
              * fut["mercado"].map(spec["multiplicador"]))
V_m = fut.groupby("mercado")["usd"].median()
sigma_m = r.std()

def curva_tendencia(L, capitales):
    bruto, coste, _ = tendencia(L)
    s = np.sign(np.log(aj / aj.shift(L)))
    w = (s * 0.10 / np.sqrt(aj.shape[1]) / vol).shift(1)
    T_m = 252 * w.diff().abs().loc["2001":].mean()   # por mercado
    alfa = 252 * (bruto - coste).mean()
    out = []
    for A in capitales:
        q = A * T_m / 252                   # orden diaria por mercado
        imp = (T_m * Y * sigma_m * np.sqrt(q / V_m)).sum()
        out.append(alfa - imp)
    return np.array(out)

print("volumen diario mediano (mil M USD):",
      (V_m / 1e9).round(1).agg(["min", "median", "max"]).to_dict())

capitales = np.logspace(6, 11, 11)          # de 1 M a 100.000 M USD
curvas = pd.DataFrame({
    "huecos": [252 * neto_op(A) for A in capitales],
    "L=21": curva_tendencia(21, capitales),
    "L=252": curva_tendencia(252, capitales),
}, index=[f"{A:.0e}" for A in capitales])
(100 * curvas).round(2)
```
```output
volumen diario mediano (mil M USD): {'min': 0.3, 'median': 6.3, 'max': 72.8}
        huecos    L=21  L=252
1e+06     7.06   -0.25  12.95
3e+06     4.11   -0.56  12.90
1e+07    -1.14   -1.11  12.82
3e+07   -10.48   -2.08  12.68
1e+08   -27.08   -3.81  12.42
3e+08   -56.61   -6.88  11.97
1e+09  -109.13  -12.34  11.17
3e+09  -202.51  -22.06   9.75
1e+10  -368.57  -39.34   7.21
3e+10  -663.87  -70.08   2.71
1e+11 -1188.99 -124.72  -5.30
```

*Fig. — Curvas de capacidad con la ley de la raíz cuadrada (Y = 1, supuesto): rentabilidad neta anual frente al capital para la estrategia de huecos de KAPA y la tendencia de 21 y 252 sesiones, con el volumen y la volatilidad de cada futuro.* Eje horizontal logarítmico de 1 millón a 100.000 millones de USD. La estrategia de huecos empieza en un 7,1 % anual y cruza el cero, destacado, en 8,2 millones; la tendencia de 21 sesiones es negativa desde el primer millón (−0,25 %) y baja cada vez más deprisa; la de 252 sesiones empieza en un 12,95 %, baja despacio y cruza el cero entre 30.000 y 100.000 millones.

El volumen de los futuros va de 0,3 a 72,8 mil millones de USD al día según el mercado (mediana de 6,3): los más
pequeños son los primeros en notar el impacto. Las tres curvas caen con el capital y cruzan el cero en puntos muy
distintos. La de huecos rinde un 7,1 % anual con un millón (con una volatilidad del 7,6 %) y pasa a negativa antes de
los 10 millones. La de tendencia de 21 sesiones es negativa desde el primer millón (−0,25 %): sus costes
proporcionales ya se comen toda la ventaja (Sharpe neto de 0,01) y el impacto solo resta. La de 252 sesiones, con la
menor rotación, rinde un 12,95 % con un millón (con un 15 % de volatilidad), todavía un 7,21 % con 10.000 millones y
un 2,71 % con 30.000, y cruza el cero antes de los 100.000 millones con estos supuestos. Es la razón de que los
fondos más grandes del mundo sean posicionales y de que las estrategias de alta frecuencia, con Sharpe muy altos, no
admitan apenas capital externo.

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

Los números absolutos de esta sección dependen de supuestos declarados: $Y = 1$, la horquilla de un céntimo de KAPA y
el volumen mediano de 2000-2025 como volumen disponible (el de los futuros crece un 4,5 % anual en los datos, así que
al final de la muestra hay más que en la mediana). Cambiarlos mueve las curvas (el ejercicio 2 lo hace con $Y$). El orden
entre horizontes, en cambio, sale de la rotación y es robusto: la capacidad cae como $1/T^3$.

</aside>

## Ejercicios

1. La estrategia de huecos entra en la apertura. Si entrara al cierre de la primera barra (09:35), ¿cuánto de la
   ventaja quedaría? Mídelo con los datos.

**Solución.**

```python
c_0935 = b[b["k"] == 0].set_index("dia")["cierre"].reindex(d.index)
tarde = -np.sign(d["hueco"]) * np.log(d["c_10h"] / c_0935)
print(f"desde la apertura: {1e4 * contra.mean():.2f} pb; "
      f"desde las 09:35: {1e4 * tarde.mean():.2f} pb")
print(f"Sharpe neto desde las 09:35: {neto(tarde, coste_lado):.2f}")
```
```output
desde la apertura: 4.69 pb; desde las 09:35: 3.99 pb
Sharpe neto desde las 09:35: 1.44
```

Entrar cinco minutos tarde deja 3,99 pb de los 4,69: la primera barra ya recoge una parte de la vuelta del hueco. Con
estos costes el Sharpe neto apenas cambia (1,44 en los dos casos, porque el rendimiento de la ventana más corta
también es menos volátil), pero el margen sobre el coste que anula la ventaja se estrecha. Entrar en la apertura
exige una orden en la subasta de apertura (lección 1.1.2), con su propia horquilla y su propio riesgo de ejecución.

2. Repite el cálculo de la capacidad de la estrategia de huecos con $Y = 0,5$ y con $Y = 2$. ¿Cómo escala $A_0$ con
   $Y$? Comprueba la respuesta con la fórmula.

**Solución.**

```python
for y in (0.5, 1.0, 2.0):
    a0 = V_usd * ((alfa_op - 2 * coste_lado)
                  / (2 * y * sigma_d)) ** 2
    print(f"Y = {y}: A0 = {a0 / 1e6:6.1f} M USD")
```
```output
Y = 0.5: A0 =   32.8 M USD
Y = 1.0: A0 =    8.2 M USD
Y = 2.0: A0 =    2.0 M USD
```

La capacidad escala como $1/Y^2$: con la mitad de impacto, cuatro veces más capital; con el doble, la cuarta parte.
Como $Y$ es incierto, la capacidad estimada lo es mucho más: un error de un factor 2 en $Y$ es un error de un factor 4
en el capital admisible. Por eso los gestores estiman su propio impacto con sus ejecuciones reales antes de crecer.

3. Una estrategia swing gana un 6 % anual bruto con una rotación de 40 veces el capital. Otra, posicional, gana un 4 %
   con una rotación de 4. Con la fórmula de $A_0$ y el mismo activo, ¿cuántas veces más capacidad tiene la segunda?
   (Ignora los costes proporcionales.)

**Solución.**

Con $c = 0$, $A_0 \propto \frac{1}{T}\left(\frac{\alpha}{T}\right)^2 = \frac{\alpha^2}{T^3}$. Para la swing,
$0,06^2 / 40^3 = 5,6 \times 10^{-8}$; para la posicional, $0,04^2 / 4^3 = 2,5 \times 10^{-5}$. El cociente es de unas
444 veces: con una ventaja anual menor, la estrategia posicional admite más de cuatrocientas veces más capital,
porque su rotación es diez veces menor.

[^1]: Tóth y otros (2011) proponen una explicación de la ley de la raíz cuadrada del impacto a partir de la liquidez
latente del libro y aportan evidencia empírica; Bouchaud, Bonart, Donier y Gould (2018) tratan el impacto y la
ejecución óptima con datos de Nasdaq. Ambos, en los recursos.

## Autoevaluación

1. Una estrategia tiene un Sharpe bruto de 0,8, una volatilidad del 10 % y rota 50 veces su capital al año con un coste de 2 pb por unidad negociada. ¿Qué Sharpe neto aproximado le queda?

   - A. 0,8
   - B. 0,7: el coste anual es 50 × 0,0002 = 1 %, y dividido por la volatilidad resta 0,1 al Sharpe
   - C. 0,4
   - D. Negativo

   *Respuesta B: 0,7: el coste anual es 50 × 0,0002 = 1 %, y dividido por la volatilidad resta 0,1 al Sharpe.* El coste anual en rentabilidad es rotación × coste por unidad: 50 × 2 pb = 100 pb. Dividido por la volatilidad del 10 %, son 0,1 puntos de Sharpe. La aproximación se cumple en la tabla de la lección con un error de centésimas.

2. ¿Por qué una estrategia intradía puede comprobarse con menos años de datos que una posicional?

   - A. Porque los datos intradía son más fiables
   - B. Porque hace muchas más apuestas independientes: con el mismo Sharpe anual por operación pequeña, su Sharpe anual es mayor y la t crece antes con la raíz de los años
   - C. Porque no tiene costes
   - D. Porque no le afecta el sesgo de supervivencia

   *Respuesta B: Porque hace muchas más apuestas independientes: con el mismo Sharpe anual por operación pequeña, su Sharpe anual es mayor y la t crece antes con la raíz de los años.* Los años necesarios para una t de 2 son (2 / Sharpe anual)². Con el Sharpe bruto de 1,56 de la estrategia de huecos bastan 1,6 años; con el 1,00 de la tendencia de 252 sesiones, unos 4. La contrapartida es que los costes y la capacidad castigan mucho más al horizonte corto.

3. Según la ley de la raíz cuadrada, si una orden se multiplica por 4, ¿cómo cambia su impacto medio por acción?

   - A. Se multiplica por 4
   - B. Se multiplica por 2
   - C. No cambia
   - D. Se divide por 2

   *Respuesta B: Se multiplica por 2.* El impacto relativo es Y·σ·raíz(Q/V): proporcional a la raíz del tamaño. El coste total en dólares, impacto por tamaño, crece como Q^1,5: cuatro veces más tamaño, ocho veces más coste.

4. ¿Por qué la capacidad de una estrategia cae tan deprisa con la rotación?

   - A. Porque los brokers cobran más a quien opera mucho
   - B. Porque la rotación multiplica tres veces: reparte la ventaja anual entre más operaciones, hace que cada sesión negocie más y multiplica el número de veces que se paga el impacto
   - C. No cae: la capacidad no depende de la rotación
   - D. Porque las estrategias de alta rotación tienen menos Sharpe

   *Respuesta B: Porque la rotación multiplica tres veces: reparte la ventaja anual entre más operaciones, hace que cada sesión negocie más y multiplica el número de veces que se paga el impacto.* Con la ley de la raíz cuadrada, el capital en que la ventaja se anula es proporcional al volumen dividido por T y por el cuadrado de T·Y·σ entre la ventaja anual; es decir, a 1/T³ con todo lo demás fijo. Doblar la rotación divide la capacidad entre ocho.

5. La estrategia de huecos de KAPA tiene un Sharpe bruto de 1,56 en el ETF más líquido de los datos. ¿Qué limita su capacidad?

   - A. El volumen de la primera media hora: no se puede ejecutar
   - B. El impacto: con una ventaja de unos 4,7 pb por operación y dos operaciones al día, el impacto de la raíz cuadrada se la come con unos pocos millones de USD
   - C. Los costes de comisión
   - D. Nada: admite cualquier capital

   *Respuesta B: El impacto: con una ventaja de unos 4,7 pb por operación y dos operaciones al día, el impacto de la raíz cuadrada se la come con unos pocos millones de USD.* Con el supuesto Y = 1, el impacto de una orden de 5 millones de USD sobre un volumen diario de unos 20.800 millones es σ·raíz(Q/V) ≈ 1,1 % × 0,016 ≈ 1,7 pb por lado. Dos lados ya son 3,4 pb de los 4,7 disponibles. Poder ejecutar la orden (participación del 10 % de la media hora) no es lo que limita.

## Ideas clave

- El horizonte fija la rotación, y la rotación fija lo que cuestan los costes: SR neto ≈ SR bruto − rotación × coste / volatilidad. Con los costes de referencia de los futuros, la tendencia de 2 sesiones pasa de un Sharpe bruto de 0,36 a −0,95; la de 252, de 1,00 a 0,88.
- El horizonte corto tiene una ventaja estadística: más apuestas y menos años para distinguir la ventaja del azar ((2 / Sharpe)² años para una t de 2).
- El impacto de mercado crece con la raíz del tamaño de la orden (Y·σ·raíz(Q/V)); el coste total, con su potencia 1,5. Y es un parámetro empírico: aquí se supone 1 y se dice.
- La capacidad cae como 1/T³ con la rotación. La estrategia de huecos de KAPA, con Sharpe bruto de 1,56, deja de ganar con unos 8 millones de USD; la tendencia de 252 sesiones admite órdenes de magnitud más.
- Las cifras salen de datos sintéticos con efectos plantados y de supuestos de coste e impacto declarados; sirven para ordenar los horizontes, no como estimación de ninguna estrategia real.

## Recursos

### Research

- [Modelos cuantitativos y ejecución algorítmica](https://pythonparatrading.com/modelos-cuantitativos-ejecucion-algoritmica/) · Research-0009 · 11 min
- [Estacionalidad intradía: backtesting](https://pythonparatrading.com/estacionalidad-intradia-backtesting/) · Research-0025 · 8 min

### Libros

- [Tóth, Lempérière, Deremble, de Lataillade, Kockelkoren y Bouchaud (2011): Anomalous Price Impact and the Critical Nature of Liquidity in Financial Markets. Physical Review X 1, 021006](https://doi.org/10.1103/PhysRevX.1.021006) · doi.org
- [Bouchaud, Bonart, Donier y Gould (2018): Trades, Quotes and Prices. Cambridge University Press](https://doi.org/10.1017/9781316659335) · doi.org

### Datos

- [Datos del nivel 2: barras de 5 minutos de KAPA (Parquet)](https://pythonparatrading.com/curso/datos/nivel-2/indice2_5min.parquet) · Descarga · indice2_5min.parquet
- [Datos del nivel 2: tarifas de brokers ficticios (CSV)](https://pythonparatrading.com/curso/datos/nivel-2/costes2_brokers.csv) · Descarga · costes2_brokers.csv

Lección anterior: [2.2.2 · Universo, señal, filtro, entrada, salida, sizing y gestión del riesgo](https://pythonparatrading.com/curso-python-trading/nivel-2/universo-senal-filtro-entrada-salida-y-sizing/)

Lección siguiente: [2.2.4 · Diario de investigación y registro de experimentos contra el data snooping](https://pythonparatrading.com/curso-python-trading/nivel-2/diario-de-investigacion-y-registro-de-experimentos/)
