📝

Draft article

This draft is visible to admins and superusers only. Sign in with an authorized account.

← 返回文章列表
August 24, 2026
5 分钟阅读

Transfer Entropy: Which Way Does Information Flow Between Crypto Assets?

Transfer Entropy: Which Way Does Information Flow Between Crypto Assets?
#causal-inference
#transfer-entropy
#information-theory
#crypto
#network

本文已经说明,加密货币接近一个单因素市场:成对信号相关性显示,PC1(BTC 因子)占方差的 65%,四个因子则能解释 90%,因此十个所谓的“多元化”交易对承载的信息量,等同于三四个相互独立的交易对。本文也已经说明,依赖结构并非恒定不变:DCC-GARCH将相关矩阵建模为一个有自身状态的时间序列,而其“局限性”一节直截了当地说出了关键事实——“相关性不是因果关系,也不是方向”。

最后这句话正是本文要填补的空白。DCC 告诉你依赖关系何时收紧,却无法告诉你它指向哪一方。传递熵可以做到:它是一种无需模型、且天然不对称的度量,用来衡量一个序列的过去有多少信息位能够帮助预测另一个序列的未来,超出目标序列自身过去已经解释的部分。如果 ETH 总是在 AAVE 重新定价之前向 AAVE 发送信息,传递熵就能捕捉到相关矩阵无法表达的不对称性。

下文将介绍这一度量及其估计器,以及比度量本身更重要的部分——零假设校准和敏感性分析。正是它们决定了一个测得的信息流网络究竟是信号,还是装饰。

测得的网络

有向信息网络

**状态:尚未运行。**下方的管道已经实现,但尚未在本文的真实数据上执行。在执行之前,本文是一篇方法说明,而不是结果报告。本博客自己的标准——参见诚实的负面结果去膨胀夏普比率与多重检验——是:未经校准的网络在证明可靠之前都应视为噪声。

这里必须按以下顺序报告四件事,而且不能从文献中替代性地断言其中任何一件:

  1. **有效 TE 矩阵。**报告资产集合、交易所、日期范围、K 线周期、每个有序资产对的有效 TE(单位为比特)、每对的 p 值,以及通过显著性筛选后得到的有向图。这将用出强度/入强度/净流量表,替代通常那种含糊的说法(“BTC 是主要来源,DeFi 代币是汇”)。
  2. **显著性检验的假阳性率。**在打乱序列和合成独立序列上运行完整管道来测量。见下文的零假设校准
  3. 对两个自由参数进行敏感性扫描n_bins 取 {3, 5},与 k 取 {1, 2, 3, 5} 交叉组合。如果领导者/跟随者排名只在网格的一个单元格中成立,这本身就是结果。
  4. **随时间的稳定性。**测得的排名能否在样本外保持,还是会在每个窗口重新洗牌?在回答这个问题之前,任何下游结论都不值得写。

计算机制

穿过状态空间的信息路径

三个构件

香农熵衡量随机变量 XX 的不确定性:

H(X)=i=1np(xi)log2p(xi)H(X) = -\sum_{i=1}^{n} p(x_i) \log_2 p(x_i)

一次公平的抛硬币是 1 比特;一个公平骰子是 log262.58\log_2 6 \approx 2.58 比特;确定性变量是 0。

条件熵衡量关于 YY 的不确定性在知道 XX 后还剩多少:

H(YX)=x,yp(x,y)log2p(x,y)p(x)H(Y|X) = -\sum_{x,y} p(x,y) \log_2 \frac{p(x,y)}{p(x)}

XX 决定 YY 时它为 0;当二者独立时,它等于 H(Y)H(Y)

互信息是二者共享的信息:

I(X;Y)=H(Y)H(YX)=H(X)H(XY)I(X;Y) = H(Y) - H(Y|X) = H(X) - H(X|Y)

它是对称的——I(X;Y)=I(Y;X)I(X;Y) = I(Y;X)——而这正是必须打破的对称性。

传递熵

Schreiber(2000)提出的传递熵通过以目标序列自身的过去为条件,打破了这种对称性。它衡量源序列 XX 的过去在多大程度上降低了对目标序列 YY 未来的不确定性,超出 YY 的过去已经解释的部分

Yt(k)Y_t^{(k)} 表示长度为 kk 的历史 (Yt1,,Ytk)(Y_{t-1}, \dots, Y_{t-k}),令 Xt(l)X_t^{(l)} 表示长度为 ll 的源序列历史:

TXY=p(Yt+1,Yt(k),Xt(l))log2p(Yt+1Yt(k),Xt(l))p(Yt+1Yt(k))T_{X \to Y} = \sum p(Y_{t+1}, Y_t^{(k)}, X_t^{(l)}) \log_2 \frac{p(Y_{t+1} \mid Y_t^{(k)}, X_t^{(l)})}{p(Y_{t+1} \mid Y_t^{(k)})}

等价地,它可以写成条件熵之差:

TXY=H(Yt+1Yt(k))H(Yt+1Yt(k),Xt(l))T_{X \to Y} = H(Y_{t+1} \mid Y_t^{(k)}) - H(Y_{t+1} \mid Y_t^{(k)}, X_t^{(l)})

如果 XX 的过去在预测 YY 时,超出 YY 自身的过去仍未提供帮助,则 TXY=0T_{X \to Y} = 0。如果有帮助,其大小就是流动的预测信息量,以比特计。

它的关键性质如下:

  • 非负TXY0T_{X \to Y} \geq 0
  • 不对称:一般而言 TXYTYXT_{X \to Y} \neq T_{Y \to X}。这正是传递熵的核心。
  • 非参数:不作模型假设,线性和非线性依赖都可以捕捉。
  • 单位:使用 log2\log_2 时单位为比特,使用 ln\ln 时单位为纳特。

净传递熵给出主导方向:

TXYnet=TXYTYXT_{X \to Y}^{\text{net}} = T_{X \to Y} - T_{Y \to X}

正值表示 XX 是向 YY 的净发送方;负值表示 YY 领先。

传递熵与格兰杰因果关系

线性与非线性因果机制

格兰杰因果关系(GC)考察 XX 的过去是否能改善对 YY 的线性自回归预测。这不是本文在统计套利与配对交易中介绍的 Engle-Granger 协整检验——姓氏相同,但概念无关。Engle-Granger 检验两个非平稳序列的线性组合是否平稳;格兰杰因果关系则考察一个序列是否有助于预测另一个序列。本博客的读者很容易将二者混淆,因此有必要明确说明。

高斯过程下的理论等价性

Barnett、Barrett 和 Seth(2009)证明,对于联合高斯过程,格兰杰因果关系与传递熵只相差一个单调变换,因此二者等价

TXY=12ln(1+FXY)T_{X \to Y} = \frac{1}{2} \ln\left(1 + F_{X \to Y}\right)

其中 FXYF_{X \to Y} 是格兰杰因果统计量(对数似然比)。对于线性高斯数据,两种方法会得到完全相同的因果结构。因此,与其说传递熵是 GC 的竞争者,不如说它是 GC 的非参数推广:在 GC 的假设成立之处,传递熵恰好退化为 GC。

二者的分歧

属性 格兰杰因果关系 传递熵
模型假设 线性 VAR 无(无需模型)
非线性依赖 无法捕捉 可以捕捉
分布假设 高斯(用于 F 检验)
样本要求 中等
计算 快(OLS) 慢(密度估计)
解释 预测改善 信息传递(比特)

从原理上说,这一差异在加密市场很重要:收益具有厚尾,波动率会聚集,关系还依赖于市场状态,而线性 VAR 会把这些都压平。这个差异是否足以改变真实数据上的领导者排名,是本文必须回答的经验问题,不能预先假定。Dimpfl 和 Peter(2013)报告称,传递熵能够发现金融序列中格兰杰因果关系遗漏的流动,尤其是在压力时期;Keskin 和 Aste(2020)报告称,非线性 TE 在加密市场中得到的网络更丰富。这里引用二者是为了说明研究动机,而不是把它们当作本数据集的证据。

有效传递熵:偏差校正

经偏差校正的信息流

这是最容易出错的部分。原始 TE 估计在有限样本中会向上偏:即使输入两个独立序列,经验联合分布中的抽样噪声也会让你估计出 TXY>0T_{X \to Y} > 0。联合状态数量随 k+lk + l 指数增长,因此偏差也会随之增大。

有效传递熵会减去这一偏差:

TXYeff=TXYE ⁣[TXsurrogateY]T_{X \to Y}^{\text{eff}} = T_{X \to Y} - \mathbb{E}\!\left[T_{X_{\text{surrogate}} \to Y}\right]

其中,替代序列会破坏 XX 的时间结构,同时保留其边际分布。需要明确它是什么、又不是什么:**替代序列均值是对估计器自身偏差的估计,我们将其减去。**它不是置信区间,有效 TE 也不是“带误差条的 TE”。同一组替代序列还可兼作 p 值的零分布,但减偏和检验是两种不同用途。

替代序列通过分块自助法生成,从而保留 XX 在块内的自相关;关于分块重采样的一般机制和理由,见回测的蒙特卡洛与自助法

实现

传递熵研究管道

数据:从单一交易所选取的固定主要 USDT 永续合约集合,在明确的连续日期范围内使用小时对数收益。标准 OHLCV 获取和对数收益构造属于统计套利与配对交易中介绍的样板流程,本文不再重复。

离散化——以及关于信息泄漏的警告

传递熵需要离散状态。分位数分箱是通常的选择,也正是最容易泄漏未来信息的地方。

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

朴素的全样本版本适合用于描述性表述——“在这段时期内,信息朝这个方向流动”——但用于任何可交易表述时都会受到污染。这一区分正是前视偏差分类的主题。如果使用全样本边界,请明确说明,并在写到“信号”之前停下。

从零实现传递熵

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

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(),
    }

成对矩阵

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))

快速路径

pyinform 封装了经过优化的 C 实现:

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)

零假设校准

零分布校准

这是分析中价值最高、也最常被跳过的部分。在相信测得网络中的任何一条边之前,应在真实答案已知为零的数据上运行完整管道——离散化、有效 TE、替代序列检验和显著性筛选:

  1. **打乱真实收益。**在保留每个序列边际分布的同时,破坏序列之间的时间对应关系。
  2. **合成独立序列。**模拟 MM 个独立的厚尾、波动率聚集过程,从构造上排除跨序列依赖。

然后报告检验在 α=0.05\alpha = 0.05 下判定为显著的有序资产对比例。如果该比例不接近 0.05,检验就是未校准的,真实网络中的每一条边都应受到怀疑。

**多重检验会使问题进一步恶化。**8 个资产的资产集合包含 8×7=568 \times 7 = 56 个有序成对检验;20 个资产则有 380 个。Bonferroni、Holm、Benjamini-Yekutieli FDR 等校正方法,已在去膨胀夏普比率与多重检验中完整推导;该文还给出了校准研究:朴素检验的 FDR 为 1.000,而 BHY 为 0.007。

但不要止步于原始 Bonferroni,因为这 56 个检验并不是 56 次相互独立的观察。加密资产彼此高度相关——本博客测得 PC1 占方差的 65%——这正是该文 Act 5 所记录的相关网格失效模式:把相关网格的原始单元格数当作试验次数,会过度收缩并错误地拒绝真实边。那篇文章交付的是有效试验次数估计的区间,而不是一个点估计:软约束端是平均相关性的一行公式 Neff=N/(1+(N1)ρˉ)N_{\text{eff}} = N/(1 + (N-1)\bar\rho);更稳妥的中间位置则是特征值估计器(参与率、PCA-95%、Kaiser)。请报告 TE 网格的有效 NN 区间,并检查存留下来的边在整个区间内是否稳定。

敏感性:两个自由参数

信息景观敏感性控制

下面两个参数通常凭经验设定,之后就再也不回头检查。相反,必须对它们进行扫描,并报告每个单元格中的领导者/跟随者排名。

历史长度 kk

kk 控制你对目标序列自身过去进行条件化的程度。太小,会把目标自身的自相关归因于源序列;太大,联合分布会稀疏到无法估计——联合状态数为 Ak+l+1|\mathcal{A}|^{k+l+1},因此使用 3 个分箱、k=2k=2l=1l=1 时有 34=813^4 = 81 个状态,而 k=5k=5 时则达到 37=21873^7 = 2187 个(而观测值只有几千个)。

对于小时数据,传统起点是 k{1,2}k \in \{1, 2\};对于日数据,则是 k{1,,5}k \in \{1, \dots, 5\},也可以用等价 VAR 滞后阶数上的 AIC/BIC 进行交叉检查。应把这些看作需要扫描的网格,而不是预先给出的答案。

离散化

  • 3 个分箱(下跌/持平/上涨):稳健,适用于有限数据,但只能捕捉方向结构。
  • 5 个分箱:能捕捉幅度,需要明显更多的数据。
  • 分位数边界:占用率大致相等,不会出现空分箱——但请参见上面的信息泄漏警告。
  • 序数/符号编码:排列熵风格,对单调变换具有稳健性。

连续的基于核的 TE完全避免离散化损失,但代价是带宽选择和大幅增加的计算量。

扫描

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)

问题不是“排名是什么”,而是“每个单元格中的排名是否相同”。如果某个资产只有在 k=2k=2nbins=3n_{\text{bins}}=3 时才是净发送方,那么这种不稳定性就是结果,应当如实报告。

混杂:条件传递熵

条件信息流

如果 XXYY 都由潜在因子 ZZ 驱动,成对 TE 会报告它们之间存在流动,而这完全可能只是共同驱动因素造成的假象。在单因素市场中,这不是特殊情况,而是默认预期。条件传递熵通过条件化来消除它:

TXYZ=H(Yt+1Yt(k),Zt(l))H(Yt+1Yt(k),Xt(l),Zt(l))T_{X \to Y | Z} = H(Y_{t+1} \mid Y_t^{(k)}, Z_t^{(l)}) - H(Y_{t+1} \mid Y_t^{(k)}, X_t^{(l)}, Z_t^{(l)})

任何关于 SOL 向 AVAX 发送信息的说法,都应在以 BTC 为条件的情况下重新检验。如果流动消失,成对结果不过是披着伪装的市场因子。

te_sol_avax_given_btc = te_pyinform(sol_disc, avax_disc, k=2,
                                    condition=btc_disc)

条件化并非没有代价:每加入一个条件变量,联合状态空间就会乘以 Al|\mathcal{A}|^{l},因此在相同 kk 下,条件 TE 需要的数据量明显多于成对版本。

稳定性,以及它是否可交易

跨状态的稳定因果桥

信息流不是静态的——这个市场中的其他东西也都不是,这正是使用 HMM 进行状态检测与自适应交易的开场前提,也是这里的每个估计都必须使用窗口而非一次性拟合的原因。不过,这项分析的滚动窗口版本继承的是一个已知结果,而非发现新结果。加密市场的依赖关系会在危机中收紧,这一点已经有带数字的研究发表:成对信号相关性将平均信号相关性从横盘市场的 0.15 列到恐慌市场的 0.90,同时 NeffN_{\text{eff}} 从 4.2 降至 1.1;DCC-GARCH的应用 3 将平均成对相关性转换为风险规避状态信号,使用尾部分位数标记,并明确提醒“这是风险信号,不是 alpha 信号”。

TE 出强度的 Freeman 集中度是在另一矩阵上定义的不同标量,但它采取的是同一种做法:把一个 d×dd \times d 的依赖对象压缩成一个数字,然后观察它上升。因此标准不是“集中度是否在回撤前上升”,而是它作为风险规避信号是否胜过平均成对相关性,在相同窗口、针对相同回撤进行正面对比。

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)

在值得撰写任何下游应用之前,必须回答两个问题:

  1. **领导者排名能否在样本外保持?**在窗口 tt 上拟合网络,并在窗口 t+1t+1 上检查排名。报告跨窗口的排名相关性。如果排名每周都重新洗牌,那描述的就是噪声。
  2. **TE 筛选是否为超前滞后交易增加了价值?**正确的实验是一次受控比较:使用统计套利与配对交易距离法中介绍的相同滚动 z 分数进出场机制,运行两次,唯一差异是是否存在 TE 显著性筛选,并计入手续费。

**本文尚未执行这两项研究。**没有超前滞后回测,没有信息动量组合,也没有状态检测比较。假设的信息动量仓位所需的权重构造机制,见投资组合优化算法比较——但请注意,对原始净强度(单位为比特)使用 softmax 是尺度任意的,在它有意义之前需要先给出归一化论证。这里不发布未经检验的策略代码。

成本

计算流约束

TE 对每个资产对的复杂度是 O(N)O(N),但常数由联合状态数 Ak+l+1|\mathcal{A}|^{k+l+1} 和替代序列数量决定。对于 MM 个资产和 BB 次自助法重复,需要进行 M(M1)BM(M-1)B 次 TE 评估——50 个资产、200 个替代序列就是 490,000 次。单次评估的成本完全取决于硬件、pyinform 版本和 NN;不要相信引用的数字,应在自己的机器上测量。若速度太慢,有三个调节手段:

  • **并行化。**每个资产对彼此独立——使用 joblibmultiprocessing
  • **预筛选。**先计算原始 TE,只对超过阈值的资产对运行替代序列。(注意,这会使显著性检验以通过筛选为条件,需要对此进行校正。)
  • **缩小资产集合。**先聚类,再在聚类代表之间计算 TE。

总结

已解析的有向信息网络

传递熵是一种有原则、无需模型的有向信息流度量,填补了本博客工具箱中的一个真实空白:DCC-GARCH 说明依赖关系何时收紧,TE 则说明它朝哪个方向指向。对于高斯过程,它通过 T=12ln(1+F)T = \tfrac{1}{2}\ln(1 + F) 恰好退化为格兰杰因果关系,因此它是推广,而不是竞争者。

但它目前还不是一个结果。这里的管道已经实现,失效模式也已列举:由替代序列校正有限样本偏差;将全序列分箱视为前视泄漏;由 56 个检验组成的相关网格会破坏朴素的多重检验校正;单因素市场中的共同驱动混杂;以及很可能决定答案的自由参数。每一项都足以让人不信任未经校准的 TE 网络。如果没有零假设校准、敏感性扫描和样本外稳定性检查就发布网络,就等于把失效模式当成发现发布。

参考文献

  • 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

Eugen Soloviov
Eugen Soloviov

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.

Newsletter

紧跟市场步伐

订阅我们的时事通讯,获取独家 AI 交易见解、市场分析和平台更新。

我们尊重您的隐私。您可以随时退订。