BTC × Altcoin correlation — análise empírica

Gerado por scripts/btc_alt_correlation.py — 2026-04-25T14:03:23.730385+00:00

Dados: capile-vault/sources/backtests/data/ (Binance klines cached).

1. Pearson global (log-returns)

altcoin 15m 30m 1h 4h 1d 1w 1M
ETHUSDT +0.896 +0.890 +0.833 +0.812 +0.841 +0.760 +0.744
XRPUSDT +0.812 +0.805 +0.747 +0.635 +0.809 +0.742 +0.440
ADAUSDT +0.825 +0.814 +0.755 +0.714 +0.804 +0.739 +0.623
DOGEUSDT +0.809 +0.806 +0.733 +0.756 +0.749 +0.772 +0.453
SOLUSDT +0.867 +0.846 +0.797 +0.778 +0.828 +0.760 +0.581
LINKUSDT +0.866 +0.844 +0.752 +0.725 +0.793 +0.707 +0.615

2. Lead-lag em 4h: corr(BTC.shift(k), alt)

k > 0 = BTC do passado prediz alt do agora (BTC lidera com lag=k bars)

altcoin k=-3 k=-2 k=-1 k=0 k=+1 k=+2 k=+3 argmax
ETHUSDT -0.006 -0.005 +0.005 +0.812 +0.030 +0.009 -0.003 k=+0 (+0.812)
XRPUSDT -0.007 -0.008 +0.026 +0.635 -0.015 -0.002 -0.011 k=+0 (+0.635)
ADAUSDT -0.004 -0.003 +0.027 +0.714 +0.011 -0.008 -0.028 k=+0 (+0.714)
DOGEUSDT -0.005 +0.002 +0.003 +0.756 +0.006 +0.011 -0.012 k=+0 (+0.756)
SOLUSDT +0.003 -0.001 +0.027 +0.778 +0.017 -0.020 -0.007 k=+0 (+0.778)
LINKUSDT -0.005 -0.013 +0.014 +0.725 +0.008 +0.001 -0.017 k=+0 (+0.725)

3. Rolling 30-bar correlation (4h, estabilidade)

altcoin median p10 p90 min max
ETHUSDT +0.849 +0.626 +0.936 +0.005 +0.976
XRPUSDT +0.748 +0.429 +0.888 -0.172 +0.962
ADAUSDT +0.776 +0.555 +0.897 +0.117 +0.963
DOGEUSDT +0.804 +0.592 +0.910 +0.180 +0.969
SOLUSDT +0.805 +0.600 +0.906 +0.061 +0.960
LINKUSDT +0.788 +0.508 +0.913 -0.172 +0.974

4. Correlação BTC×alt por regime BTC (4h, regime_detector do projeto)

altcoin trending_up (n) trending_down (n) ranging (n) volatile (n)
ETHUSDT +0.738 (833) +0.866 (998) +0.800 (987) — (4)
XRPUSDT +0.541 (833) +0.757 (998) +0.539 (987) — (4)
ADAUSDT +0.645 (833) +0.769 (998) +0.694 (987) — (4)
DOGEUSDT +0.680 (833) +0.841 (998) +0.742 (987) — (4)
SOLUSDT +0.679 (833) +0.827 (998) +0.772 (987) — (4)
LINKUSDT +0.649 (833) +0.822 (998) +0.694 (987) — (4)

volatile tem n≤4 porque o threshold ATR%≥4% raramente é atingido em 720d de BTC 4h. Não dá pra concluir nada desse bucket. Alternativa: baixar ATR_PCT_VOLATILE_BY_INTERVAL["4h"] para 3% ou usar BBwidth alto como proxy.


Achados-chave

  1. Correlação Pearson é sempre positiva e forte em todos TFs — mín +0.44 (XRP em 1M), máx +0.90 (ETH em 15m). Não há "decoupling estrutural" — Boss tinha razão.

  2. XRP é o menos correlacionado em quase todos TFs (4h: 0.635; 1M: 0.44). DOGE e ADA seguem. Faz sentido com o WF: as únicas três alts WF-validadas em bollinger_breakout (XRP, ADA, DOGE) são também as menos arrastadas pelo BTC. Edge é justamente o pedaço de movimento NÃO explicado por BTC — daí passar o teste OOS.

  3. ETH/SOL muito mais correlacionados com BTC (~0.81-0.83 em 4h). Em uma estratégia de alt breakout, o sinal próprio do alt é abafado pela gravidade do BTC. Confirma por que falharam o WF.

  4. Lead-lag em 4h: argmax = k=0 para TODAS as moedas. Nenhuma correlação significativa em k≠0 (todos < 0.03 absoluto). Não há lag intra-4h explorável. Bate com a literatura. Usar BTC como leading signal em barras de 4h é fake edge.

  5. Per-regime (4h) — surpresa contraintuitiva: correlação é MAIOR em trending_down (0.76-0.87) que em trending_up (0.54-0.74). Inversa do paper MF-ADCCA. Possíveis razões: período pós-ETF (paper é pré), definição de regime via ADX vs decomposição assimétrica, ou simplesmente "risk-off correlations spike" — quando BTC despenca, alts despencam mais junto.

  6. Em trending_up BTC, alts têm MAIOR autonomia (corr 0.54-0.74). Sinal de breakout próprio fica menos abafado. Frame plausível: "alt rali em paralelo a BTC bull, mas com narrative própria."

  7. Rolling p10: XRP=0.43, p10 mais baixo, e mín=−0.17 (decoupling real existe). 10% das janelas de 30 barras (~5d em 4h) têm correlação < 0.43. Decoupling acontece, não é mito — só é minoritário.

Implicações pra parâmetros do bot

A. Não vale filtrar trending_down BTC (já testado: marginal). Razão revelada agora: alta correlação em trending_down NÃO significa que alt sempre cai junto — pode estar tendo seu próprio breakout. Filtro perde wins.

B. Vale testar filtro inverso "BTC NÃO em trending_down" OU filtro BTC trending_up apenas — esperado que dê edge porque correlação é menor lá → sinal próprio do alt é mais limpo. Hipótese 3 do agente literário.

C. Filtro de drawdown agudo de BTC (e.g. BTC fechou < −3% no dia) provavelmente captura o "risk-off" sem perder os wins de breakout próprio do alt. Diferente de filtro por regime ADX-based.

D. BTC.D não tá no nosso dataset — Binance não publica diretamente, mas dá pra calcular como BTC_marketcap / TOTAL via CoinGecko/CoinMarketCap. Vale o esforço se filtros locais (B, C) não derem edge.

E. Sizing por correlação rolling: quando rolling-30 corr está em p10 (alt decoupled), aumentar size; em p90 (alt arrastado), diminuir. Hipótese acionável — mas exige tracking de rolling corr no live runner.

Hipóteses concretas pra próximo WF

# Hipótese Implementação Esperado
H1 Filtro BTC trending_up aumenta expectancy de bb_breakout em XRP/ADA/DOGE 4h Adapter já existe (BtcFilteredAdapter) — inverter lógica para skip-if-NOT-trending_up mean WF +5-10% vs setup atual
H2 Filtro abs(BTC daily return) < 3% (sem dump grande) Novo adapter checando BTC 1d return menos drawdown, n similar
H3 Sizing inverso à corr rolling 30 (BTC×alt) Wrapper no compute_size lendo corr sharpe maior, return similar
H4 Adicionar BTC.D externo via CoinGecko Cron diário pulling BTC.D, threshold 60%/45% só vale se H1-H3 falharem
H5 Re-WF com volatile threshold 3% (em vez de 4%) Bump em ATR_PCT_VOLATILE_BY_INTERVAL["4h"] regime breakdown mais informativo

Recomendação: começar por H1 (custo zero, infra existe). Depois H2 (custo baixo). H3 e H4 são mais work, deixar pra depois.

H1, H2, H2b testadas — TODAS DESCARTADAS (2026-04-25)

Implementado BtcFilteredAdapter(mode="only_trending_up") e rodado WF em XRP/ADA/DOGE 4h bollinger_breakout, 720d, 6 windows. Comparado com baseline (sem filtro) e skip_trending_down (legacy).

setup wins mean_ret total_trades per-window
XRP baseline 5/6 +28.2% 289 -1 +26 +58 +41 +32 +13
XRP skip_down 6/6 +29.3% 372 +13 +29 +62 +36 +14 +21
XRP H1 only_up 4/6 +9.0% 92 -4 +19 -1 +26 +6 +8
ADA baseline 5/6 +14.4% 392 +3 +45 +31 +5 -21 +24
ADA skip_down 4/6 +16.8% 305 -2 +57 +32 +6 -4 +12
ADA H1 only_up 4/6 +12.9% 102 -5 +51 +7 +25 +3 -3
DOGE baseline 5/6 +17.1% 411 -1 +10 +48 +24 +6 +16
DOGE skip_down 5/6 +17.2% 324 -7 +20 +46 +11 +22 +11
DOGE H1 only_up 4/6 +8.5% 107 -3 +29 +12 +2 +17 -6

H1 cortou ~70% dos trades em todas 3 moedas e destruiu retorno (XRP −67%, DOGE −50%). Inferência: trending_up de BTC é janela estreita (~25-30% do tempo), e a maioria dos breakouts vencedores em alt acontece em ranging/volatile ou trending_down de BTC.

H2 testada (2026-04-25 16:26 UTC)

BtcMagnitudeAdapter(threshold=0.03, direction="both") — abstém quando |BTC 1d return| ≥ 3%. Em 365d de cache BTC 1d, isso cobre 12% dos dias (extremos simétricos: dumps E rallies).

moeda baseline H2
XRP 5/6 +28.2% (n=289) 5/6 +13.5% (n=280)
ADA 5/6 +14.4% (n=392) 2/6 −4.8% (n=287)
DOGE 5/6 +17.1% (n=411) 3/6 −5.3% (n=304)

Pior que baseline em todas. Negativo em ADA e DOGE. Trades similar (~290), então não cortou volume — cortou os trades certos. Hipótese: o filtro está removendo dias de rally BTC, que são quando alts disparam mais (alt vai ainda mais que BTC, breakout vence). Filtro simétrico tira wins.

H2b testada (2026-04-25 16:28 UTC)

Variante assimétrica: direction="down_only" — só abstém em DUMP (ret ≤ −3%), permite rallies. Hipótese: dumps são risk-off (alts caem junto), rallies são bull-confirm (alts disparam).

moeda baseline H2b
XRP 5/6 +28.2% 3/6 +18.0%
ADA 5/6 +14.4% 4/6 +1.8%
DOGE 5/6 +17.1% 3/6 +2.3%

Melhor que H2 em todos, mas ainda pior que baseline. XRP perdeu wins (5→3), ADA/DOGE caíram pra perto de zero. Refuta a hipótese de que abster em dump BTC ajuda — provavelmente porque os 12% de dumps já são pequena minoria, e quando um dump acontece o alt também já está caindo, o BB não dispara mesmo. Filtrar não muda nada e remove uns trades winning de mid-recovery.

Resumo: 5 testes, 0 wins

moeda baseline skip_down H1 only_up H2 both H2b down
XRP 5/6 +28.2% 6/6 +29.3% 4/6 +9.0% 5/6 +13.5% 3/6 +18.0%
ADA 5/6 +14.4% 4/6 +16.8% 4/6 +12.9% 2/6 −4.8% 4/6 +1.8%
DOGE 5/6 +17.1% 5/6 +17.2% 4/6 +9.0% 3/6 −5.3% 3/6 +2.3%

Único filtro com melhora sobre baseline: skip_trending_down, mas o ganho é marginal (+1% XRP, +2% ADA, neutro DOGE) e pode ser ruído amostral.

Conclusão definitiva

A intuição "BTC lidera, podemos filtrar usando isso" foi REFUTADA empiricamente para bb_breakout em XRP/ADA/DOGE 4h.

Por quê? A correlação BTC↔alt 4h é alta (0.6-0.8), mas o edge do bb_breakout é o pedaço NÃO explicado por BTC — exatamente o movimento idiossincrático do alt na cauda da banda Bollinger. Filtrar por estado do BTC remove tanto trades influenciados por BTC quanto trades realmente independentes — net negativo.

A correlação alta diz "alts seguem BTC em retorno médio". O bb_breakout não opera retorno médio — opera ruptura acima da banda. Ruptura acontece quando há sinal próprio do alt, e isso pode ocorrer em qualquer regime BTC.

Decisão: manter live em XRP 4h bb_breakout sem filtro forte. skip_trending_down dá +1% marginal, não vale a complexidade.

Próximas direções de pesquisa (movendo PARA LONGE de filtros BTC)

# Direção Custo Justificativa
A Promover ADA + DOGE pra live (multi-symbol BB runner) médio (eng) edge já validado, triplica oportunidade
B Refinar BB params (period 25/30, std 2.5) em XRP/ADA/DOGE baixo otimização local sem risk de overfit grande
C Filtro de volume no próprio alt (volume spike ≥ X% do médio) baixo sinal endógeno, não cross-asset
D WF em moedas novas (DOT, TRX, ATOM, SUI) médio expandir universo de candidatos
E H3 (sizing inverso à corr rolling) alto (mexe live) risk/sharpe, não return
F H4 (BTC.D externo CoinGecko) médio só se A-E falharem

Recomendação: A (promover ADA+DOGE) → C (volume filter) → D (novas moedas WF). E e F deprioritizadas.

Fontes

Cross-references

Entities: [[../entities/ADAUSDT]], [[../entities/XRPUSDT]] Strategies: [[../strategy/bollinger_breakout]] Regimes: [[../regimes/ranging]], [[../regimes/trending_up]], [[../regimes/volatile]]