Transfer Entropy: Which Way Does Information Flow Between Crypto Assets?
Este blog ya ha establecido que las criptomonedas se parecen a un mercado de un solo factor: la correlación de señales entre pares sitúa a PC1 (el factor BTC) en el 65 % de la varianza y muestra que cuatro factores explican el 90 %, por lo que diez pares "diversificados" contienen la información de tres o cuatro pares independientes. También ha establecido que la estructura de dependencia ni siquiera es constante: DCC-GARCH modela la matriz de correlaciones como una serie temporal con sus propios regímenes, y su sección de Limitaciones dice en voz alta la parte incómoda — "la correlación no es causalidad ni dirección".
Esa última cláusula es la brecha que aborda este artículo. DCC te dice cuándo se estrecha la dependencia. No puede decirte hacia dónde apunta. La entropía de transferencia sí puede: es una medida sin modelo e inherentemente asimétrica de cuántos bits aporta el pasado de una serie para predecir el futuro de otra, más allá de lo que ya explica el propio pasado del objetivo. Si ETH envía información de forma constante a AAVE antes de que AAVE se reajuste, la entropía de transferencia detecta la asimetría que ninguna matriz de correlación puede representar.
Lo que sigue es la medida, su estimador y —lo que importa más que la medida— la calibración del nulo y el análisis de sensibilidad que determinan si una red de flujo de información medida es señal o decoración.
La red medida

Estado: aún no ejecutado. El flujo de trabajo de abajo está implementado, pero todavía no se ha ejecutado con datos reales para este artículo. Hasta que se ejecute, este artículo es una descripción del método, no un resultado. El estándar del propio blog —véanse el resultado negativo honesto y Sharpe deflacionado y pruebas múltiples— exige considerar que una red no calibrada es ruido hasta demostrar lo contrario.
Aquí hay que informar cuatro cosas, en este orden, y ninguna puede afirmarse a partir de la literatura:
- La matriz de TE efectiva. Universo, exchange, intervalo de fechas, tamaño de barra, TE efectiva en bits por cada par ordenado, valor p por par y el grafo dirigido que sobrevive al filtro de significancia. Esto sustituye la habitual afirmación vaga ("BTC es la fuente dominante y los tokens DeFi son sumideros") por una tabla de fuerza de salida, fuerza de entrada y flujo neto.
- La tasa de falsos positivos de la prueba de significancia, medida ejecutando todo el flujo de trabajo sobre series barajadas y sobre series sintéticas independientes. Véase Calibración del nulo más abajo.
- Un barrido de sensibilidad sobre los dos parámetros libres:
n_binsen {3, 5} cruzado conken {1, 2, 3, 5}. Si la clasificación líder/seguidora solo se mantiene en una celda de esa cuadrícula, ese es el hallazgo. - Estabilidad en el tiempo. ¿La clasificación medida persiste fuera de muestra o se reorganiza en cada ventana? No merece la pena escribir nada posterior hasta responder esto.
La maquinaria

Tres bloques de construcción
La entropía de Shannon mide la incertidumbre de una variable aleatoria :
Una moneda equilibrada tiene 1 bit; un dado justo tiene bits; una variable determinista tiene 0.
La entropía condicional mide cuánta incertidumbre sobre permanece después de conocer :
Es 0 cuando determina , y es igual a cuando son independientes.
La información mutua es la información compartida entre ambas:
Es simétrica — — y esa simetría es exactamente lo que hay que romper.
Entropía de transferencia
La entropía de transferencia, introducida por Schreiber (2000), rompe la simetría condicionando sobre el propio pasado del objetivo. Mide cuánto reduce el pasado de la fuente la incertidumbre sobre el futuro del objetivo , más allá de lo que ya explica el pasado de .
Sea el historial de longitud , , y el historial de la fuente de longitud :
De forma equivalente, como diferencia de entropías condicionales:
Si el pasado de no ayuda a predecir más allá del propio pasado de , . Si sí ayuda, la magnitud es el número de bits de información predictiva que fluye.
Propiedades principales:
- No negativa: .
- Asimétrica: en general . Este es precisamente el objetivo.
- No paramétrica: no hace suposiciones sobre el modelo; recoge dependencias lineales y no lineales por igual.
- Unidades: bits con , nats con .
La entropía de transferencia neta proporciona la dirección dominante:
Un valor positivo significa que es un emisor neto hacia ; uno negativo significa que lidera.
Entropía de transferencia frente a causalidad de Granger

La causalidad de Granger (GC) pregunta si el pasado de mejora una predicción autorregresiva lineal de . No es la prueba de cointegración de Engle-Granger tratada en arbitraje estadístico y trading de pares: tienen el mismo apellido, pero son conceptos no relacionados. Engle-Granger pregunta si una combinación lineal de dos series no estacionarias es estacionaria; la causalidad de Granger pregunta si una serie ayuda a pronosticar otra. Los lectores de este blog las confundirán, así que conviene decirlo claramente.
Equivalencia teórica para procesos gaussianos
Barnett, Barrett y Seth (2009) demostraron que para procesos conjuntamente gaussianos, la causalidad de Granger y la entropía de transferencia son equivalentes salvo una transformación monótona:
donde es el estadístico de causalidad de Granger (una razón de log-verosimilitudes). Para datos gaussianos lineales se recupera exactamente la misma estructura causal con cualquiera de los dos métodos. Por tanto, la entropía de transferencia no compite con la GC tanto como la generaliza de forma no paramétrica: se reduce a la GC exactamente donde se cumplen las suposiciones de esta.
Dónde divergen
| Propiedad | Causalidad de Granger | Entropía de transferencia |
|---|---|---|
| Suposición del modelo | VAR lineal | Ninguna (sin modelo) |
| Dependencias no lineales | No las detecta | Las captura |
| Suposición de distribución | Gaussiana (para la prueba F) | Ninguna |
| Requisitos de muestra | Moderados | Altos |
| Cómputo | Rápido (OLS) | Lento (estimación de densidad) |
| Interpretación | Mejora predictiva | Transferencia de información (bits) |
La brecha importa en principio para las criptomonedas: los rendimientos tienen colas pesadas, la volatilidad se agrupa y las relaciones dependen del régimen, aspectos que un VAR lineal aplana. Si la brecha es lo bastante grande como para cambiar la clasificación de líderes en datos reales es una pregunta empírica que este artículo debe responder, no suponer.
Dimpfl y Peter (2013) informan de que la entropía de transferencia detecta flujos que la causalidad de Granger no detecta en series financieras, especialmente bajo estrés; Keskin y Aste (2020) informan de una red más rica a partir de TE no lineal en criptomonedas. Aquí se citan como motivación, no como evidencia para este conjunto de datos.
Entropía de transferencia efectiva: la corrección del sesgo

Esta es la parte en la que es fácil equivocarse. Las estimaciones de TE bruta están sesgadas al alza en muestras finitas: introduce dos series independientes y aun así estimarás , únicamente por el ruido muestral de la distribución conjunta empírica. El sesgo crece con el número de estados conjuntos, que crece exponencialmente en .
La entropía de transferencia efectiva resta ese sesgo:
donde el sustituto destruye la estructura temporal de mientras conserva su distribución marginal. Observa qué es esto y qué no es: la media de los sustitutos es una estimación del sesgo del propio estimador, y se la restamos. No es un intervalo de confianza y la TE efectiva no es "TE con barras de error". El mismo conjunto de sustitutos cumple una doble función como distribución nula para un valor p, pero la resta y la prueba son usos separados.
El sustituto se genera mediante un bootstrap por bloques para que la autocorrelación de dentro de un bloque sobreviva —la mecánica general y la justificación del remuestreo por bloques se explican en Monte Carlo y bootstrap para backtests.
Implementación

Datos: rendimientos logarítmicos horarios para un universo fijo de perpetuos principales en USDT de un solo exchange, durante un intervalo de fechas contiguo indicado. La obtención estándar de OHLCV y la construcción de rendimientos logarítmicos son código repetitivo tratado en arbitraje estadístico y trading de pares y no se repiten aquí.
Discretización y advertencia sobre filtración
La entropía de transferencia necesita estados discretos. La discretización por cuantiles es la opción habitual, y también es el lugar habitual donde se filtra el futuro.
import numpy as np
import pandas as pd
def discretize_trailing(series, n_bins=3, warmup=500):
"""Discretize using bin edges estimated on a TRAILING window only.
Computing quantile edges over the full sample is whole-series
normalization leakage: every bar's label depends on the entire
future distribution. See the look-ahead bias taxonomy.
"""
x = np.asarray(series, dtype=float)
out = np.full(len(x), -1, dtype=int)
qs = np.linspace(0, 1, n_bins + 1)[1:-1]
for t in range(warmup, len(x)):
edges = np.quantile(x[:t], qs) # strictly past data
out[t] = np.digitize(x[t], edges)
return out
La versión ingenua con muestra completa es adecuada para una afirmación descriptiva —"durante este periodo la información fluyó en esta dirección"— y está contaminada para cualquier afirmación operable. Esa distinción es todo el tema de la taxonomía del sesgo de anticipación. Si usas bordes de muestra completa, dilo y detente antes de la palabra "señal".
Entropía de transferencia desde cero
from collections import Counter
def transfer_entropy(source, target, k=1, l=1):
"""Transfer entropy T_{source -> target} in bits.
source, target : 1-D integer arrays of discrete states
k : history length for the target
l : history length for the source
"""
source = np.asarray(source)
target = np.asarray(target)
n = len(target)
max_lag = max(k, l)
y_future = target[max_lag:]
y_past = np.column_stack([target[max_lag - i - 1:n - i - 1] for i in range(k)])
x_past = np.column_stack([source[max_lag - i - 1:n - i - 1] for i in range(l)])
N = len(y_future)
yf = y_future.tolist()
yp = [tuple(row) for row in y_past]
xp = [tuple(row) for row in x_past]
c_yf_yp_xp = Counter(zip(yf, yp, xp))
c_yp_xp = Counter(zip(yp, xp))
c_yf_yp = Counter(zip(yf, yp))
c_yp = Counter(yp)
te = 0.0
for (yf_val, yp_val, xp_val), count in c_yf_yp_xp.items():
p_joint = count / N
p_yf_given_yp_xp = count / c_yp_xp[(yp_val, xp_val)]
p_yf_given_yp = c_yf_yp[(yf_val, yp_val)] / c_yp[yp_val]
if p_yf_given_yp > 0 and p_yf_given_yp_xp > 0:
te += p_joint * np.log2(p_yf_given_yp_xp / p_yf_given_yp)
return te
TE efectiva con un nulo de bootstrap por bloques
def effective_transfer_entropy(source, target, k=1, l=1,
n_shuffles=200, block_size=5, rng=None):
"""Effective TE plus a surrogate p-value.
Returns dict: te, ete, p_value, null_mean, null_std
"""
rng = rng or np.random.default_rng(0)
te_observed = transfer_entropy(source, target, k, l)
n = len(source)
n_blocks = int(np.ceil(n / block_size))
null_tes = np.empty(n_shuffles)
for b in range(n_shuffles):
starts = rng.integers(0, n, size=n_blocks)
shuffled = np.concatenate(
[np.take(source, range(s, s + block_size), mode='wrap')
for s in starts]
)[:n]
null_tes[b] = transfer_entropy(shuffled, target, k, l)
null_mean = null_tes.mean()
return {
'te': te_observed,
'ete': max(te_observed - null_mean, 0.0),
'p_value': (np.sum(null_tes >= te_observed) + 1) / (n_shuffles + 1),
'null_mean': null_mean,
'null_std': null_tes.std(),
}
La matriz por pares
def compute_te_matrix(disc_returns, k=1, n_shuffles=200):
cols = list(disc_returns.columns)
m = len(cols)
te_matrix = np.zeros((m, m))
pval_matrix = np.ones((m, m))
for i in range(m):
for j in range(m):
if i == j:
continue
r = effective_transfer_entropy(
disc_returns[cols[i]].values,
disc_returns[cols[j]].values,
k=k, n_shuffles=n_shuffles,
)
te_matrix[i, j] = r['ete']
pval_matrix[i, j] = r['p_value']
return (pd.DataFrame(te_matrix, index=cols, columns=cols),
pd.DataFrame(pval_matrix, index=cols, columns=cols))
La vía rápida
pyinform envuelve una implementación C optimizada:
from pyinform.transferentropy import transfer_entropy as te_pyinform
te_btc_to_eth = te_pyinform(btc_disc, eth_disc, k=2)
te_eth_to_btc = te_pyinform(eth_disc, btc_disc, k=2)
Calibración del nulo

Esta es la parte de mayor valor del análisis y la que más a menudo se omite. Antes de creer en cualquier arista de la red medida, ejecuta todo el flujo de trabajo —discretización, TE efectiva, prueba con sustitutos y filtro de significancia— sobre datos en los que se sabe que la respuesta verdadera es cero:
- Rendimientos reales barajados. Destruye la sincronización entre series manteniendo la distribución marginal de cada una.
- Series sintéticas independientes. Simula procesos independientes de colas pesadas y volatilidad agrupada, sin dependencia cruzada por construcción.
Después informa de la fracción de pares ordenados que la prueba marca con . Si esa fracción no está cerca de 0.05, la prueba está mal calibrada y toda arista de la red real resulta sospechosa.
Las pruebas múltiples lo agravan. Un universo de 8 activos contiene pruebas por pares ordenados; 20 activos contienen 380. Las correcciones —Bonferroni, Holm, FDR de Benjamini-Yekutieli— se derivan por completo en Sharpe deflacionado y pruebas múltiples, junto con el estudio de calibración donde el FDR de la prueba ingenua es 1.000 frente a 0.007 para BHY.
Pero no te detengas en un Bonferroni bruto, porque estas 56 pruebas no son 56 observaciones independientes. Los activos cripto están fuertemente correlacionados entre sí —este blog midió PC1 en el 65 % de la varianza—, precisamente el modo de fallo de cuadrícula correlacionada documentado en el Acto 5 de ese artículo, donde tratar el recuento bruto de celdas de una cuadrícula correlacionada como el número de ensayos desinfla en exceso y rechaza falsamente una arista genuina. El resultado entregable allí era una banda de estimaciones de ensayos efectivos, no un punto: la fórmula de una línea basada en la correlación media en el extremo flexible, y los estimadores basados en valores propios (ratio de participación, PCA-95 %, Kaiser) en el centro defendible. Informa de la banda de efectivo para la cuadrícula de TE y comprueba si las aristas supervivientes son estables en toda ella.
Sensibilidad: los dos parámetros libres

Ambos parámetros suelen fijarse por regla general y después no se vuelven a revisar. En su lugar, hay que barrerlos e informar de la clasificación líder/seguidora en cada celda.
Longitud del historial
controla cuánto del propio pasado del objetivo condicionas. Si es demasiado pequeño, atribuyes a la fuente la autocorrelación propia del objetivo; si es demasiado grande, la distribución conjunta se vuelve demasiado dispersa para estimarla —el número de estados conjuntos es , por lo que con 3 bins, y tienes estados, mientras que te lleva a frente a unos pocos miles de observaciones.
Los puntos de partida convencionales son para datos horarios y para datos diarios, con una comprobación cruzada opcional mediante AIC/BIC sobre el retardo VAR equivalente. Trátalos como la cuadrícula que hay que barrer, no como la respuesta.
Discretización
- 3 bins (bajada / plano / subida): robustos, funcionan con datos limitados y capturan solo la estructura direccional.
- 5 bins: capturan la magnitud, pero necesitan muchos más datos.
- Bordes por cuantiles: ocupación aproximadamente igual, sin bins vacíos —pero consulta la advertencia sobre filtración anterior.
- Codificación ordinal/simbólica: al estilo de la entropía de permutación, robusta frente a transformaciones monótonas.
La TE continua basada en kernels evita por completo la pérdida de discretización, a costa de seleccionar el ancho de banda y de un cómputo mucho más pesado.
El barrido
for n_bins in (3, 5):
for k in (1, 2, 3, 5):
disc = discretize_all(returns, n_bins=n_bins)
te_df, p_df = compute_te_matrix(disc, k=k)
rank = net_flow_ranking(te_df, p_df)
report(n_bins, k, rank)
La pregunta no es "¿cuál es la clasificación?", sino "¿es la clasificación la misma en cada celda?". Si un activo solo es emisor neto en , , esa inestabilidad es el resultado y debe informarse como tal.
Confusión: entropía de transferencia condicional

Si tanto como están impulsados por un factor latente , la TE por pares informará de un flujo entre ellos que es enteramente un artefacto del impulsor común. En un mercado de un solo factor no es un caso extremo; es la expectativa por defecto. La entropía de transferencia condicional lo condiciona:
Cualquier afirmación de que SOL envía información a AVAX debe volver a probarse condicionando sobre BTC. Si el flujo desaparece, el resultado por pares era el factor de mercado disfrazado.
te_sol_avax_given_btc = te_pyinform(sol_disc, avax_disc, k=2,
condition=btc_disc)
Condicionar no es gratis: cada variable de condicionamiento multiplica el espacio de estados conjuntos por , por lo que la TE condicional necesita muchos más datos que la versión por pares con el mismo .
Estabilidad y si algo de esto se puede negociar

El flujo de información no es estático —y nada más lo es en este mercado, que es la premisa inicial de detección de regímenes con HMM y la razón por la que cada estimación aquí debe calcularse por ventanas en lugar de ajustarse una sola vez. Sin embargo, la versión de este análisis con ventanas móviles hereda un resultado conocido en vez de descubrir uno. Que la dependencia cripto se estrecha durante una crisis ya está publicado con cifras: la correlación de señales entre pares tabula una correlación de señal media de 0.15 en mercados laterales hasta 0.90 en pánico, con colapsando de 4.2 a 1.1, y DCC-GARCH, en su Aplicación 3, convierte la correlación media por pares en una señal de régimen de aversión al riesgo con un indicador de cuantiles móviles y una advertencia explícita de "esto es una señal de riesgo, no una señal alfa".
La centralización de Freeman de la fuerza de salida de TE es un escalar diferente sobre una matriz diferente, pero es el mismo movimiento: reducir un objeto de dependencia a un número y observar cómo aumenta. Por tanto, la vara de medir no es "¿aumenta la centralización antes de las caídas?", sino ¿supera a la correlación media por pares como señal de aversión al riesgo?, medida cara a cara, en las mismas ventanas y frente a las mismas caídas.
def network_centralization(G):
"""Freeman centralization of out-strength. High = one dominant source."""
if G.number_of_nodes() < 2:
return 0.0
s = [sum(d['weight'] for _, _, d in G.out_edges(v, data=True)) for v in G.nodes()]
total = sum(s)
if total == 0:
return 0.0
n = len(s)
return sum(max(s) - x for x in s) / ((n - 1) * total)
Hay que responder dos preguntas antes de que merezca la pena escribir cualquier aplicación posterior:
- ¿La clasificación de líderes persiste fuera de muestra? Ajusta la red en la ventana y comprueba la clasificación en la ventana . Informa de la correlación de rangos entre ventanas. Una clasificación que se reorganiza cada semana describe ruido.
- ¿El filtro de TE aporta algo a una operación de adelanto-retraso? El experimento correcto es una única comparación controlada: la misma maquinaria de entrada/salida mediante z-score móvil descrita en arbitraje estadístico y trading de pares y el enfoque de distancia, ejecutada dos veces, con la presencia del filtro de significancia de TE como única diferencia e incluyendo las comisiones.
Ninguna de las dos se ha ejecutado para este artículo. No hay backtest de adelanto-retraso, ni cartera de momentum de información, ni comparación de detección de regímenes. La maquinaria de construcción de pesos para una hipotética cartera de momentum de información se trata en algoritmos de optimización de carteras comparados, pero ten en cuenta que un softmax sobre la fuerza neta bruta en bits tiene una escala arbitraria y necesitaría un argumento de normalización antes de significar algo. Aquí no se publica código de estrategia sin probar.
Coste

La TE es por par, pero la constante viene determinada por el número de estados conjuntos y por el número de sustitutos. Para activos y réplicas de bootstrap necesitas evaluaciones de TE —con 50 activos y 200 sustitutos son 490.000. El coste por evaluación depende por completo de tu hardware, la versión de pyinform y ; mídelo en tu propia máquina en lugar de confiar en una cifra citada. Tres palancas si es demasiado lento:
- Paraleliza. Cada par es independiente —
joblibomultiprocessing. - Haz una preselección. Calcula primero la TE bruta; ejecuta los sustitutos solo para los pares por encima de un umbral. (Ten en cuenta que esto hace que la prueba de significancia sea condicional a superar la preselección, lo que requiere un ajuste.)
- Reduce el universo. Agrupa primero y calcula la TE entre representantes de los grupos.
Resumen

La entropía de transferencia es una medida fundamentada y sin modelo del flujo de información dirigido, y cubre una brecha real en el conjunto de herramientas de este blog: DCC-GARCH dice cuándo se estrecha la dependencia; la TE dice hacia dónde apunta. Para procesos gaussianos se reduce exactamente a la causalidad de Granger mediante , lo que la convierte en una generalización y no en una rival.
Lo que todavía no es es un resultado. El flujo de trabajo está implementado y los modos de fallo están enumerados —sesgo de muestra finita corregido mediante sustitutos, discretización de toda la serie como filtración por anticipación, una cuadrícula correlacionada de 56 pruebas que rompe las correcciones ingenuas de pruebas múltiples, confusión por un impulsor común en un mercado de un solo factor y parámetros libres que bien podrían determinar la respuesta. Cada uno de ellos es motivo para desconfiar de una red de TE no calibrada. Publicar la red sin la calibración del nulo, el barrido de sensibilidad y la comprobación de estabilidad fuera de muestra sería publicar los modos de fallo como si fueran hallazgos.
Referencias
- Schreiber, T. (2000). "Measuring Information Transfer." Physical Review Letters, 85(2), 461-464.
- Barnett, L., Barrett, A.B., Seth, A.K. (2009). "Granger Causality and Transfer Entropy Are Equivalent for Gaussian Variables." Physical Review Letters, 103(23), 238701.
- Marschinski, R., Kantz, H. (2002). "Analysing the information flow between financial time series." European Physical Journal B, 30(2), 275-281.
- Dimpfl, T., Peter, F.J. (2013). "Using Transfer Entropy to Measure Information Flows Between Financial Markets." Studies in Nonlinear Dynamics & Econometrics, 17(1), 85-102.
- Keskin, Z., Aste, T. (2020). "Information-theoretic measures for nonlinear causality detection: application to social media sentiment and cryptocurrency prices." Royal Society Open Science, 7(9), 200863.
- Jang, S.M. et al. (2022). "Using transfer entropy to measure information flows between cryptocurrencies." Physica A, 586, 126476.
- Nicola, G. et al. (2020). "Network Analysis of Multivariate Transfer Entropy of Cryptocurrencies in Times of Turbulence." Entropy, 22(7), 760.
Authors
Trading-systems engineer
Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.