Toda-Yamamoto vs Differenced Granger: Does the BTC Lead-Lag Survive?
Quase todos os resultados publicados de causalidade de Granger em criptografia são calculados em retornos de log. Essa escolha não é gratuita. A diferenciação torna a série estacionária, o que o teste F padrão exige, mas também descarta a relação de nível – e se duas moedas são cointegradas, o VAR diferenciado é especificado incorretamente e o teste responde a uma pergunta ligeiramente diferente daquela que você fez.
Toda e Yamamoto (1995) oferecem uma saída: ajustar o VAR em níveis com defasagens extras, testar apenas os originais e obter um valor válido. independentemente de raízes unitárias ou cointegração. É bem conhecido em econometria e quase nunca aplicado ao cripto lead-lag.
Portanto, este artigo faz uma coisa: executar ambos os testes nos mesmos pares, na mesma janela, e relatar se eles discordam. Em seguida, aplique o acompanhamento honesto - uma correção de múltiplos testes de família correlacionada na matriz resultante e um valor p contínuo para ver se o atraso "significativo" é estável o suficiente para negociar ou apenas oscila além do limite.
A teoria abaixo é apenas a necessária para tornar a comparação legível. O blog já cobre raízes unitárias, cointegração, carregamento de dados, dimensionamento e custos; esses são links, não seções.
O que a causalidade de Granger realmente afirma

A causalidade de Granger é precedência preditiva, não mecanismo: Causas Granger se passado reduz a variação do erro de previsão de além do que passado já explica.
Causas Granger se
Duas séries impulsionadas por um fator oculto comum podem mostrar causalidade de Granger sem ligação direta entre elas. Na criptografia, essa advertência não é acadêmica - BTC é um único fator dominante em todo o complexo altcoin, então quase qualquer "causalidade" alt-to-alt é um artefato candidato de diferentes velocidades de resposta ao mesmo choque BTC.
A estrutura VAR
O teste reside dentro de uma autoregressão vetorial. Para duas variáveis com atrasos:
Na forma de matriz, um VAR(p) com variáveis:
Testando se Causas Granger está testando a restrição conjunta na primeira equação. A rota padrão é um teste F em somas de quadrados residuais restritas versus irrestritas,
com a forma de Wald assintoticamente equivalente . Tudo o que se segue é uma questão sobre a quais coeficientes essa restrição é aplicada e em quais dados o VAR foi ajustado.
Seleção de atraso
é mais importante do que a maioria dos artigos admite: poucos atrasos perdem a dinâmica, muitos queimam graus de liberdade e destroem o poder.
Intervalos de pesquisa razoáveis: 1-60 em dados de segundos, 1-30 em dados de minutos, 1-48 em dados de hora em hora. O BIC é o padrão certo aqui – é o critério mais parcimonioso, e o lead-lag em pares criptográficos líquidos é um fenômeno de memória curta. Cada resultado abaixo reporta o selecionado pelo BIC por par, em vez de fixar um atraso em todo o universo, porque um atraso fixo converte silenciosamente uma escolha de seleção de atraso em uma afirmação de significância.
Por que o teste diferenciado é o padrão errado

As séries de preços criptográficos são I(1). A solução usual – obter retornos logarítmicos – compra estacionariedade ao custo do nível de cointegração, e se o par compartilha um equilíbrio de longo prazo, o VAR diferenciado é mal especificado. A máquina de raiz unitária e de cointegração por trás dessa sentença (ADF, Engle-Granger com seus valores críticos de Monte-Carlo, Johansen em um sistema VAR) já é abordada em arbitragem estatística e negociação de pares; assuma isso aqui. A questão é apenas que o remédio habitual – diferença e depois teste – é uma decisão modelar com consequências, e Toda-Yamamoto é a maneira de evitar tomá-lo.
O procedimento Toda-Yamamoto
Coloque um VAR com atrasos, onde é a ordem de atraso ideal e é a ordem máxima de integração da série, então teste as restrições somente no primeiro atrasos. O extra as defasagens absorvem a não estacionariedade; a estatística Wald no primeiro coeficientes seguem um padrão independentemente de as séries serem I(0), I(1) ou cointegradas.
- Determinar — ADF e KPSS em cada série. Para preços criptográficos quase sempre.
- Selecione — ajuste de VAR por níveis, escolha por BIC.
- Estimar o VAR aumentado() em níveis, sem diferenciação.
- ** Teste Wald o primeiro apenas atrasos **, ignorando o extras. O resultado é .
A recompensa: nenhum pré-teste de cointegração, nenhuma diferenciação e tamanho de teste correto – a taxa de rejeição sob o valor nulo permanece próxima do nominal, quaisquer que sejam as propriedades de integração. O custo é que a etapa 4 não é o que test_causality faz por padrão, que é onde a maioria das implementações erram silenciosamente.
Implementação

Suponha que você já tenha barras de minutos alinhadas em um DataFrame - o padrão de busca e índice ccxt está em detecção de regime com HMM, e o wrapper ADF que você usaria para a etapa 1 está em arbitragem estatística e negociação de pares.
Uma nota de versão antes de qualquer coisa ser executada: grangercausalitytests(..., verbose=False) foi descontinuado e removido no statsmodels 0.15. Elimine o argumento (a função não é mais impressa por padrão) ou fixe statsmodels<0.15. O código abaixo assume a assinatura moderna.
Toda-Yamamoto, feito corretamente
A restrição deve ser construída manualmente. VARResults.test_causality testa todos os atrasos da variável causadora no modelo ajustado - em um VAR aumentado () que inclui o atraso na restrição, que é exatamente o que Toda-Yamamoto diz para não fazer. A correção é explícita matriz contra a covariância do coeficiente completo:
import numpy as np
from scipy.stats import chi2
from statsmodels.tsa.api import VAR
def toda_yamamoto_test(data, target, predictor, max_lag=15, d_max=1,
significance=0.05):
"""
Toda-Yamamoto Granger causality on levels (no differencing).
Fits VAR(p + d_max) and applies a Wald test to the predictor's
coefficients at lags 1..p ONLY, leaving the d_max augmenting lags
unrestricted. Statistic is chi2(p).
"""
pair = data[[target, predictor]].dropna()
n_vars = pair.shape[1]
target_idx = list(pair.columns).index(target)
pred_idx = list(pair.columns).index(predictor)
model = VAR(pair)
p = model.select_order(maxlags=max_lag).bic or 1
res = model.fit(p + d_max)
beta = res.params.values.ravel(order="F")
cov = res.cov_params()
cov = cov.values if hasattr(cov, "values") else np.asarray(cov)
n_per_eq = res.params.shape[0]
idx = [target_idx * n_per_eq + 1 + lag * n_vars + pred_idx
for lag in range(p)] # first p lags only
R = np.zeros((p, beta.size))
R[np.arange(p), idx] = 1.0
Rb = R @ beta
V = R @ cov @ R.T
wald = float(Rb @ np.linalg.solve(V, Rb)) # no pinv: V must be PD
p_value = float(chi2.sf(wald, df=p))
return {
"target": target, "predictor": predictor,
"p": p, "augmented_lag": p + d_max, "d_max": d_max,
"wald_stat": wald, "p_value": p_value,
"significant": p_value < significance,
}
Dois detalhes que são fáceis de errar e que invalidam o teste se você fizer isso. Primeiro, a aritmética do índice deve corresponder à forma como os modelos estatísticos se nivelam params — verificar em um modelo ajustado que beta[target_idx * n_per_eq + 1] é igual res.params.iloc[1, target_idx] antes de confiar em qualquer valor p. Em segundo lugar, use np.linalg.solve, não pinv: se é singular, a restrição é degenerada e a execução deve falhar ruidosamente em vez de retornar um número de aparência plausível. Um pseudo-inverso aqui é como os testes Wald quebrados sobrevivem à revisão de código.
Granger diferenciado padrão, para comparação
A linha de base contra a qual a comparação se baseia - retornos logarítmicos, mesmos pares, mesmo atraso de BIC:
from statsmodels.tsa.stattools import grangercausalitytests
def differenced_granger(data, target, predictor, p):
"""Standard Granger test on log-returns at a fixed lag p."""
pair = data[[target, predictor]].dropna() # returns, not levels
out = grangercausalitytests(pair, maxlag=[p]) # statsmodels >= 0.15
f_stat, p_value = out[p][0]["ssr_ftest"][:2]
return {"target": target, "predictor": predictor, "lag": p,
"f_stat": f_stat, "p_value": p_value}
Observação maxlag=[p] em vez de maxlag=p: passar um int executa cada atraso de 1 a e tenta você a relatar o melhor, que é um teste múltiplo não registrado além do teste múltiplo que você já está executando.
A comparação
Para cada par, execute o teste diferenciado nos retornos e Toda-Yamamoto nos níveis, no mesmo nível selecionado pelo BIC. e tabule onde os dois discordam. A discordância é a célula interessante: um par significativo nas diferenças, mas não nos níveis, é um artefato candidato à diferenciação de um relacionamento de cointegração; o inverso sugere que o relacionamento de nível carrega informações que o teste de retorno não pode ver.
Múltiplas comparações em uma matriz de causalidade

O completo Matrix é onde isso se torna perigoso. Uma varredura de 20 ativos e 10 atrasos equivale a 3.800 testes de hipóteses, e Bonferroni é a correção errada para uma família tão correlacionada – os testes compartilham dados, compartilham o fator BTC e estão longe de ser independentes, então Bonferroni é simultaneamente muito conservador no agregado e enganoso sobre quais células sobrevivem. Use o maquinário N efetivo do artigo desinflado de Sharpe, que é construído exatamente para esta situação: agrupar a família de testes correlacionados, contar ensaios independentes em vez de brutos, e estabelecer limites contra isso.
def granger_matrix(data, max_lag=15, d_max=1):
"""Toda-Yamamoto p-value matrix. Entry (i, j): does col_j cause col_i?"""
cols = list(data.columns)
out = pd.DataFrame(np.nan, index=cols, columns=cols, dtype=float)
for target in cols:
for predictor in cols:
if target == predictor:
continue
r = toda_yamamoto_test(data, target, predictor,
max_lag=max_lag, d_max=d_max)
out.loc[target, predictor] = r["p_value"]
return out
O número que importa não é quantas células estão abaixo de 0,05 – é quantas sobrevivem ao limite corrigido do N efetivo.
Leia a matriz sobrevivente estruturalmente, não célula por célula: linhas onde um ativo causa muitos outros confirmam uma hierarquia de informações; uma coluna causada por nada sugere uma dinâmica idiossincrática e específica do token, em vez de uma descoberta.
O teste honesto: estabilidade de rolamento

Um único valor p na amostra é quase inútil para negociação. A questão relevante é se a significância persiste. As relações entre ativos em criptomoedas são dependentes do regime — a estrutura de correlação difere acentuadamente entre calma e pânico, e o regime em si é estimável (detecção de regime HMM) — portanto, um lead-lag estimado em uma janela é uma declaração sobre essa janela.
def rolling_granger(data, target, predictor, window=500, lag=5, step=50):
"""Rolling-window p-value: when is the lead-lag active vs dormant?"""
rows = []
for start in range(0, len(data) - window, step):
chunk = data.iloc[start:start + window][[target, predictor]].dropna()
if len(chunk) < window * 0.8:
continue
try:
out = grangercausalitytests(chunk, maxlag=[lag])
f_stat, p_value = out[lag][0]["ssr_ftest"][:2]
except Exception:
f_stat, p_value = np.nan, np.nan
rows.append({"timestamp": data.index[start + window - 1],
"f_stat": f_stat, "p_value": p_value})
return pd.DataFrame(rows).set_index("timestamp")
Relate duas coisas desta série: a fração de janelas abaixo de 0,05 e o número de cruzamentos de limiares. Uma relação significativa em 80% das janelas com três cruzamentos é um objeto diferente de uma relação significativa em 55% das janelas com quarenta cruzamentos, mesmo que o valor p agrupado seja idêntico. O segundo não é negociável – você não pode dimensionar uma posição em um sinal cuja existência muda a cada poucas centenas de barras, e o atraso na reestimativa garante que você estará sempre negociando no regime anterior.
A armadilha de dados específica de Granger

A higiene genérica de dados criptográficos é abordada em outro lugar - lacunas e velas ausentes em paridade backtest-live, disciplina de carimbo de data/hora na taxonomia de viés de antecipação e provando que não há previsão em intervalos de tempo. Um modo de falha, porém, é específico de Granger e grave o suficiente para ser nomeado:
O preenchimento direto produz o resultado. Uma vela preenchida para frente repete o fechamento anterior, o que injeta autocorrelação pura na série - e autocorrelação lag-1 em que está mecanicamente alinhado com é indistinguível, para o teste F, de uma relação causal de uma defasagem. O mesmo se aplica a todos os locais: um deslocamento de relógio de 1 segundo entre duas trocas nas barras de minutos pode criar ou destruir a importância do lag-1 de uma vez, porque muda o lado do limite da barra em que um movimento ocorre. Antes de executar qualquer uma dessas etapas, verifique se as lacunas foram eliminadas em vez de preenchidas e se ambas as séries foram registradas no mesmo relógio.
Descobertas de lead-lag relatadas na literatura

Estas são citações, não medições deste artigo. Eles estão aqui para dizer o que o registro publicado afirma, para que a comparação acima tenha algo com que concordar ou discordar.
- BTC para altcoins. Um estudo de 2026 nos Mercados Financeiros da Ásia-Pacífico (Springer) relata transmissão de preços de alta frequência do Bitcoin para altcoins, com moedas de pequena capitalização mostrando respostas significativamente atrasadas e menor liquidez associada a reações mais lentas. As magnitudes de atraso comumente citadas nesta linha de trabalho – cerca de 1-3 minutos de BTC para ETH, mais longas para empresas de média e pequena capitalização, cada vez mais unidirecionais à medida que a capitalização de mercado cai – são descobertas citadas, não re-derivadas aqui. O nível de capitalização de mercado em que eles se baseiam é a mesma escada usada na validação multisímbolo.
- CEX lidera DEX. Pesquisa sobre microestrutura criptográfica (MDPI) relata locais centralizados que dominam a descoberta de preços, com fluxo de informações executando CEX para DEX e nenhuma causalidade reversa significativa – consistente com mecanismos de correspondência abaixo de milissegundos versus liquidação em tempo de bloco.
- ETH como moeda independente. Trabalho VAR-SVAR (MDPI) encontra regimes nos quais o Ethereum atua como fonte e o Bitcoin como receptor de repercussão, principalmente durante as fases orientadas por DeFi e NFT.
Intercâmbio, brevemente
O atraso da mesma moeda e dois locais é uma configuração real, mas a economia disso - limites de taxas, a escada de latência, por que o atraso existe - já é trabalhada em arbitragem estatística e negociação de pares e o kimchi premium. A única coisa que Granger acrescenta é uma questão de estabilidade: a causalidade Binance-Coinbase é persistentemente significativa ou ela oscila como todo o resto? Execute o teste contínuo no par de locais; a resposta é uma série temporal de valor p, não um sim.
Transformando um atraso de sobrevivência em uma posição

Se um par ultrapassar o limite corrigido e o teste contínuo, o sinal em si é trivial: retorno cumulativo do preditor ao longo da janela de atraso, com limite.
def lead_lag_signal(btc_returns, alt_returns, lag=5, threshold=0.001):
"""+1 / -1 / 0 on ALT from BTC's cumulative return over `lag` bars."""
btc_cum = btc_returns.rolling(lag).sum()
signal = pd.Series(0, index=alt_returns.index)
signal[btc_cum > threshold] = 1
signal[btc_cum < -threshold] = -1
return signal
Três coisas que não fazem parte deste artigo porque já estão resolvidas aqui:
- Os custos decidem. Um sinal de atraso em escala de minuto em altcoins precisa eliminar spread, impacto e taxas - consulte modelos de derrapagem e custo e economia do maker-taker, e o que acontece quando os custos são aplicados a um determinado vencedor.
- O dimensionamento não é uma transformação de valor p. O dimensionamento da exposição inversamente ao valor p de Granger está errado: um valor p é uma evidência contra um valor nulo, não um tamanho de efeito, e se move com o comprimento da amostra. Tamanho do efeito estimado e sua incerteza — consulte Dimensionamento de Kelly.
- A validação é feita passo a passo. Reestimar de forma contínua e avaliar fora da amostra; otimização walk-forward é o protocolo.
Limitações

Causalidade de Granger não é causalidade. Confundidores (um evento macro movendo ambas as pernas com ligeiro desalinhamento de carimbo de data/hora), motivadores comuns (dois alts seguindo BTC em velocidades diferentes) e variáveis omitidas (testando BTC para DOGE sem ETH no sistema) produzem estatísticas significativas sem fluxo direto de informações. Restringir os testes bivariados, como faz este artigo, torna o problema da variável omitida pior, e não melhor.
Linearidade. O teste vê apenas estrutura preditiva linear na média condicional. A criptografia tem agrupamento de volatilidade, efeitos de alavancagem e mudanças de regime - consulte previsão de volatilidade GARCH e correlação dinâmica DCC-GARCH para a história do segundo momento. Alternativas não lineares que vale a pena conhecer: o teste de kernel de Diks-Panchenko (2006), a entropia de transferência como o análogo da teoria da informação e a causalidade de Granger da cópula em toda a distribuição conjunta completa.
Quebras estruturais. Qualquer relação estimada em uma janela está condicionada ao regime dessa janela; o teste contínuo acima é o diagnóstico mínimo e é um diagnóstico, não uma solução.
Resumo

- Ajuste o VAR em níveis, selecione por BIC por par, aumentar por , e teste de Wald o primeiro apenas atrasos. Construa a matriz de restrição manualmente - a biblioteca
test_causalityrestringe também o atraso de aumento, o que não é Toda-Yamamoto. - Execute o teste de retorno diferenciado como linha de base nos mesmos pares e defasagem e relate as divergências. Essa tabela é a descoberta; uma matriz de asteriscos não é.
- Corrija a matriz para uma família de testes correlacionada via N efetivo, não Bonferroni, e relate quantas células sobrevivem.
- Role. Relate a fração de janelas significativas e a contagem de cruzamentos. A significância de que as oscilações não são um atraso negociável, não importa quão pequeno seja o valor p agrupado.
- Elimine lacunas em vez de preencher antecipadamente e verifique o alinhamento do relógio entre os locais, antes de acreditar em qualquer resultado de lag-1.
Um resultado perfeitamente bom deste procedimento é negativo – uma relação BTC-alt que seja significativa na amostra, sobreviva à correção e ainda cruze a linha 0,05 em ambas as direções a cada poucas centenas de barras é um resultado real sobre a negociabilidade e vale a pena publicar como tal.
Referências
- Granger, C.W.J. (1969). "Investigando relações causais por modelos econométricos e métodos espectrais cruzados." Econométrica, 37(3), 424-438. -Toda, H.Y. e Yamamoto, T. (1995). "Inferência estatística em autorregressões vetoriais com processos possivelmente integrados." Jornal de Econometria, 66(1-2), 225-250.
- Diks, C. e Panchenko, V. (2006). "Uma nova estatística e diretrizes práticas para testes não paramétricos de causalidade de Granger." Journal of Economic Dynamics and Control, 30(9-10), 1647-1669.
- Sifat, IM, Mohamad, A. (2019). "Relação Lead-Lag entre Bitcoin e Ethereum: evidências de dados horários e diários." Pesquisa em Negócios e Finanças Internacionais, 50, 306-321.
- "Transmissão de preços de Bitcoin para Altcoins: evidências de alta frequência e implicações para estratégia de negociação." Mercados Financeiros da Ásia-Pacífico, Springer, 2026.
- "Riscos de repercussão nos mercados de criptomoedas: uma análise da causalidade VAR-SVAR Granger." Jornal de Risco e Gestão Financeira, MDPI.
- "A estrutura de dois níveis dos mercados de taxas de financiamento de criptomoedas." Matemática, MDPI.
- "Trocas descentralizadas e centralizadas: quais tokens digitais apresentam maior risco de contágio?" ScienceDirect, 2023.
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.