LLM Alpha Mining: como extrair sinais de trading de earnings calls e documentos financeiros
Há uma piada em Wall Street: "A informação mais valiosa em uma earnings call não é o que o CEO disse, mas como ele disse." Quando Tim Cook diz "estamos cautelosamente otimistas" em vez do "estamos muito satisfeitos" do ano passado — isso não é um jogo linguístico, é um sinal que vale centenas de milhões de dólares.
Há décadas, fundos quantitativos tentam sistematizar a extração desses sinais. Primeiro, contavam a frequência de palavras "positivas" e "negativas" usando dicionários. Depois, lançaram mão do BERT. E agora temos o GPT-4o, o Claude e LLMs de código aberto capazes de analisar as sutilezas do duplo discurso corporativo com uma precisão que assusta até os próprios pesquisadores.
Vamos detalhar como construir um pipeline completo para extrair sinais de trading de earnings calls — desde a obtenção da transcrição até o backtesting de retornos anormais acumulados.
Por que earnings calls são uma mina de ouro para alfa
Post-Earnings Announcement Drift: a anomalia que não morre
Em 1968, Ball e Brown descobriram algo estranho: depois que os resultados trimestrais são publicados, as ações continuam a derivar na direção da "surpresa" por mais 60-90 dias. Chamaram isso de Post-Earnings Announcement Drift (PEAD). Mais de meio século se passou desde então, centenas de artigos foram escritos, a anomalia foi explicada de uma dezena de ângulos diferentes — e ela ainda funciona.
O PEAD é uma das anomalias de mercado mais persistentes da história das finanças. Uma estratégia de portfólio de "comprar surpresa positiva, vender surpresa negativa" tem historicamente entregado um retorno excedente anual de 10-25%. Por que o mercado não arbitrou isso? Várias razões:
- Atenção limitada dos investidores — quando 200 empresas divulgam resultados na mesma semana, é fisicamente impossível ler todas as transcrições
- Complexidade cognitiva — uma earnings call dura de 45 a 60 minutos, e o sinal-chave pode estar enterrado em uma única frase no minuto 38 da sessão de perguntas e respostas
- Ambiguidade da linguagem — o CFO diz "estamos navegando por ventos contrários", e sem contexto não fica claro se é um aviso suave ou uma proteção padrão
É aqui que os LLMs entram em cena. Pela primeira vez, temos uma ferramenta capaz de processar 500 transcrições em uma noite, ao mesmo tempo em que capta nuances que até analistas experientes deixariam passar.
PEAD.txt: o texto importa mais do que os números
Pesquisadores do Federal Reserve Bank of Philadelphia (Meursault, Liang, Routledge, Scanlon) publicaram o artigo PEAD.txt, que derrubou suposições sobre o valor da informação textual. Eles construíram um análogo textual da surpresa de resultados padrão — o SUE.txt — que não usa de forma alguma o valor numérico dos resultados.
O resultado? O SUE.txt gera um drift que é duas vezes maior do que o PEAD clássico. Além disso: nos últimos anos, enquanto o PEAD clássico baseado em surpresas numéricas praticamente desapareceu (o mercado aprendeu), o drift textual permanece significativo. O mercado aprendeu a processar números rapidamente, mas ainda tem dificuldade com a interpretação textual.
Este é o argumento fundamental a favor de uma abordagem baseada em NLP para earnings calls.
Do sentimento à semântica: evolução das abordagens

Primeira geração: bag-of-words e dicionários (2000-2015)
Tudo começou com o dicionário Loughran-McDonald (2011) — uma lista de palavras rotuladas como "positivas", "negativas", "incertas" e "litigiosas". A ideia era elegante em sua simplicidade: contar a porcentagem de palavras negativas em um documento 10-K e operar com base nisso.
O problema? A palavra "outstanding" em um contexto financeiro significa mais frequentemente "dívida em aberto" do que "resultado excelente". A palavra "risco" em Risk Management não é um sinal negativo — é uma descrição de processo. Os dicionários de sentimento padrão de NLP tiveram um desempenho vergonhosamente ruim em textos financeiros.
Loughran e McDonald criaram um dicionário especializado, o que melhorou a situação, mas o problema fundamental permaneceu: bag-of-words não entende contexto. "Não deixamos de atender às expectativas" — há duas palavras "negativas" aqui, mas o significado é positivo.
Segunda geração: FinBERT e transformers (2019-2023)
Em 2019, Dogu Araci publicou o FinBERT — um BERT ajustado com textos financeiros da Reuters TRC2. Os resultados foram impressionantes: uma melhoria de 14 pontos percentuais no dataset Financial PhraseBank em relação ao estado da arte. O FinBERT entendia contexto: "outstanding" ao lado de "debt" — negativo, ao lado de "performance" — positivo.
Mas o FinBERT tinha uma limitação: uma janela de contexto de 512 tokens. Uma earnings call tem entre 8.000 e 12.000 palavras. Dividir em blocos e calcular a média do sentimento significa perder a semântica entre parágrafos. O CEO poderia começar com otimismo e depois mencionar casualmente problemas na cadeia de suprimentos durante as perguntas e respostas. O FinBERT analisa cada bloco de forma independente e perde esse contraste.
Terceira geração: LLMs com contexto longo (2023-presente)
GPT-4, Claude, Gemini com janelas de contexto de 128K-1M tokens mudaram as regras do jogo. Agora é possível carregar uma transcrição inteira de uma só vez e fazer perguntas que exigem a compreensão do documento como um todo.
O estudo-chave — Lopez-Lira & Tang (2023) "Can ChatGPT Forecast Stock Price Movements?" Em mais de 50.000 manchetes, o GPT-4 apresentou uma taxa de acerto de ~90% na previsão da direção da reação inicial do mercado e previu significativamente o drift subsequente, especialmente para empresas de pequena capitalização e notícias negativas. Modelos anteriores (GPT-1, GPT-2, BERT) não demonstraram essa capacidade — o poder preditivo emerge como uma propriedade emergente de modelos grandes.
O BloombergGPT (2023) — um modelo de 50 bilhões de parâmetros treinado no corpus financeiro da Bloomberg — demonstrou melhorias em NER financeiro, classificação de notícias e análise de sentimento. O FinGPT — sua alternativa de código aberto — alcança 89% de precisão em tarefas de sentimento financeiro usando uma abordagem centrada em dados e RAG.
O MarketSenseAI, que usa GPT-4 com Chain-of-Thought e aprendizado em contexto para análise do S&P 100, apresentou um alfa excedente de 10-30% e retornos acumulados de até 72% ao longo de 15 meses de testes. Sim, esses números devem ser vistos com cautela (backtest ≠ trading ao vivo), mas a tendência é clara.
Pipeline de dados: onde obter os dados
SEC EDGAR: a fonte oficial
Para ações dos EUA, a fonte primária é o SEC EDGAR. As earnings calls geralmente não são arquivadas diretamente, mas documentos relacionados estão disponíveis:
- Arquivamentos 8-K (Item 2.02 — Resultados Operacionais) — comunicados de imprensa com resultados, muitas vezes incluindo o exhibit 99 com a transcrição
- 10-Q / 10-K — relatórios trimestrais e anuais com Management Discussion & Analysis (MD&A) — também uma fonte de texto valiosa
- DEF 14A — declarações de procuração com informações sobre remuneração da diretoria
from edgar import Company
company = Company("AAPL")
filings = company.get_filings(form="8-K")
for filing in filings.latest(10):
if "2.02" in str(filing.items):
doc = filing.document()
text = doc.text() # Full text with exhibits
print(f"{filing.filing_date}: {len(text)} chars")
Seeking Alpha e APIs comerciais
As transcrições de earnings calls são um produto à parte. O Seeking Alpha foi historicamente a principal fonte gratuita, mas agora restringe o acesso. Opções comerciais:
- Seeking Alpha Premium API — transcrições completas com rótulos de interlocutor
- AlphaVantage Earnings API — nível gratuito com limitações
- Financial Modeling Prep — transcrições + fundamentos
- Earnings Call Edge / Motley Fool Transcripts — fontes alternativas
Cripto: governance calls e propostas de DAO
É aqui que a coisa fica interessante. Os principais protocolos DeFi realizam seu equivalente a earnings calls:
- Uniswap — governance calls, community calls, gravações no YouTube
- Aave — community calls mensais + propostas no fórum de governança
- MakerDAO — governance calls + extensas discussões em fórum
- Compound — propostas de governança com discussões detalhadas
As transcrições de chamadas cripto geralmente não são estruturadas. A solução — o Whisper da OpenAI para transcrever gravações do YouTube:
import openai
from yt_dlp import YoutubeDL
def transcribe_governance_call(youtube_url: str) -> str:
"""Download audio from YouTube and transcribe via Whisper."""
ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '64', # Low bitrate is sufficient for speech
}],
'outtmpl': '/tmp/governance_call.%(ext)s',
}
with YoutubeDL(ydl_opts) as ydl:
ydl.download([youtube_url])
client = openai.OpenAI()
with open("/tmp/governance_call.mp3", "rb") as audio_file:
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=audio_file,
response_format="verbose_json",
timestamp_granularities=["segment"]
)
return transcript.text
O custo da transcrição via API do Whisper: 0,36. Para uma opção auto-hospedada — o Whisper Large-v3 Turbo transcreve um arquivo de 60 minutos em ~17 segundos (216x tempo real) em uma GPU moderna.
Estratégias de prompting para LLM: do ingênuo ao pronto para produção

Estratégia 1: sentimento direto (fraca)
A abordagem mais ingênua — perguntar diretamente ao modelo:
"Esta earnings call é positiva ou negativa para o preço da ação?"
Isso funciona? Sim, surpreendentemente. Lopez-Lira & Tang mostraram que até mesmo um prompt tão primitivo produz previsões estatisticamente significativas. Mas há problemas:
- Saída binária — você perde as gradações. "Catástrofe" e "leve decepção" recebem o mesmo rótulo
- Sem explicação — não fica claro em que o modelo baseou sua decisão
- Instabilidade — uma execução repetida pode dar uma resposta diferente
Estratégia 2: extração estruturada com Chain-of-Thought (forte)
A ideia: em vez de um único número, extrair um conjunto estruturado de sinais, forçando o modelo a explicar cada etapa.
from pydantic import BaseModel, Field
from openai import OpenAI
from enum import Enum
from typing import Optional
class SentimentLevel(str, Enum):
VERY_BEARISH = "very_bearish"
BEARISH = "bearish"
NEUTRAL = "neutral"
BULLISH = "bullish"
VERY_BULLISH = "very_bullish"
class GuidanceSurprise(BaseModel):
"""Deviation of forward guidance from consensus expectations."""
revenue_guidance_vs_consensus: Optional[float] = Field(
None, description="% deviation of revenue guidance from consensus"
)
margin_guidance_direction: Optional[str] = Field(
None, description="expanding / stable / contracting"
)
key_quote: str = Field(
description="Verbatim quote with guidance"
)
reasoning: str = Field(
description="CoT: why this guidance matters"
)
class ConfidenceMetrics(BaseModel):
"""Management confidence metrics."""
hedge_word_count: int = Field(
description="Number of hedge words: 'approximately', 'potentially', 'subject to'"
)
forward_looking_ratio: float = Field(
description="Ratio of forward-looking statements to total statements"
)
q_and_a_evasion_count: int = Field(
description="Number of questions where CEO/CFO gave an evasive answer"
)
ceo_vs_cfo_sentiment_delta: float = Field(
description="Sentiment difference between CEO and CFO (-1 to 1). Divergence is a red flag"
)
class CompetitiveIntelligence(BaseModel):
"""Mentions of competitors and market position."""
competitors_mentioned: list[str] = Field(
description="List of mentioned competitors"
)
market_share_claims: list[str] = Field(
description="Market share claims"
)
new_product_signals: list[str] = Field(
description="Signals about new products/services"
)
class ManagementSignals(BaseModel):
"""Management signals."""
turnover_risk: SentimentLevel = Field(
description="Risk of key management turnover"
)
tone_shift_from_previous: Optional[str] = Field(
None, description="How tone changed compared to last quarter"
)
insider_language_flags: list[str] = Field(
description="Marker phrases: 'exploring strategic alternatives', 'right-sizing', etc."
)
class EarningsCallAnalysis(BaseModel):
"""Complete earnings call analysis."""
ticker: str
quarter: str
overall_sentiment: SentimentLevel
sentiment_score: float = Field(description="from -1.0 to 1.0")
guidance_surprise: GuidanceSurprise
confidence_metrics: ConfidenceMetrics
competitive_intel: CompetitiveIntelligence
management_signals: ManagementSignals
key_risks: list[str]
key_catalysts: list[str]
one_line_summary: str
def analyze_earnings_call(transcript: str, ticker: str, quarter: str) -> EarningsCallAnalysis:
"""
Extract structured signals from an earnings call.
Cost: ~$0.15-0.30 per call (GPT-4o, ~10K tokens input).
"""
client = OpenAI()
system_prompt = """You are a senior equity research analyst with 20 years of experience.
Analyze the following earnings call transcript and extract structured trading signals.
IMPORTANT INSTRUCTIONS:
1. Use Chain-of-Thought reasoning for each field — explain WHY before giving the value
2. Focus on DEVIATIONS from expectations, not absolute statements
3. Pay special attention to Q&A section — management is less scripted there
4. Compare management's language to typical corporate hedging baseline
5. Flag any "strategic alternatives", "right-sizing", or other euphemisms
6. Score sentiment relative to market expectations, not in absolute terms
HEDGE WORDS TO COUNT: approximately, potentially, subject to, may, might,
could, uncertain, challenging, headwinds, navigate, prudent, cautious,
evolving, dynamic, unprecedented, transitional"""
completion = client.beta.chat.completions.parse(
model="gpt-4o",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": f"Ticker: {ticker}\nQuarter: {quarter}\n\n{transcript}"}
],
response_format=EarningsCallAnalysis,
temperature=0.1, # Low temperature for reproducibility
)
return completion.choices[0].message.parsed
Observe alguns pontos-chave:
Esquema Pydantic — o OpenAI Structured Outputs garante 100% de conformidade com o esquema. Acabou o "sorry, I cannot parse the JSON". Cada campo tem uma descrição que atua como um mini-prompt para um aspecto específico da análise.
Chain-of-Thought dentro do esquema — os campos reasoning e key_quote forçam o modelo a "mostrar seu trabalho". Isso não apenas melhora a qualidade (o modelo é forçado a encontrar uma citação específica antes de emitir um julgamento), mas também cria um trilha de auditoria para reguladores.
Temperatura 0,1 — não queremos criatividade. Precisamos de reprodutibilidade. Na temperatura 0, o modelo às vezes fica "preso" em padrões; 0,1 é o compromisso ideal.
Estratégia 3: few-shot com exemplos históricos
Ainda mais poderosa — dar ao modelo exemplos de earnings calls passadas com reações reais de mercado:
few_shot_examples = """
EXAMPLE 1:
Transcript excerpt: "We are cautiously optimistic about the second half...
While we continue to navigate macro headwinds, our pipeline remains robust."
Actual market reaction: -3.2% (next day)
Analysis: Despite surface-level positivity, "cautiously optimistic" is a
DOWNGRADE from previous quarter's "very confident". Five hedge words in
two sentences. Market read through the hedging.
EXAMPLE 2:
Transcript excerpt: "Frankly, demand has exceeded our ability to supply.
We're expediting CapEx to address this."
Actual market reaction: +7.8% (next day)
Analysis: "Frankly" signals genuine surprise even from management.
Accelerated CapEx on demand = strong confidence. No hedging language.
"""
Exemplos few-shot ajudam o modelo a se calibrar: ele aprende que "cautiously optimistic" na linguagem de Wall Street não é positivo — é um negativo suave. Sem exemplos, o LLM pode interpretar as palavras literalmente.
Quatro tipos de sinais
1. Surpresa de guidance
O sinal mais direto. Uma empresa fornece uma previsão (guidance) para o próximo trimestre/ano, e o mercado reage ao desvio em relação ao consenso. Um LLM consegue extrair o guidance mesmo quando a diretoria o comunica de forma vaga:
- "We expect revenues in the range of..." — guidance direto, fácil de analisar
- "We feel comfortable with current Street estimates" — confirmação implícita do consenso
- "There are puts and takes relative to consensus" — sinal de risco implícito
Um LLM entende as três formulações; regex entende apenas a primeira.
2. Métricas de confiança: densidade de palavras de proteção
Este é meu sinal favorito porque é contraintuitivo. A essência: os executivos são pessoas com formação jurídica e departamentos jurídicos paranoicos. Quando as coisas vão bem, eles se permitem ser específicos. Quando problemas estão surgindo — começam a se proteger.
Métricas a acompanhar:
| Métrica | Descrição | Sinal bearish |
|---|---|---|
| Densidade de palavras de proteção | Proporção de palavras de proteção por 1.000 palavras | > 15 por 1.000 palavras |
| Razão de certeza | Razão entre "will/expect" e "may/could" | < 1,5 |
| Taxa de evasão em Q&A | % de perguntas sem resposta direta | > 30% |
| Delta CEO/CFO | Divergência de tom entre CEO e CFO | > 0,3 na escala [-1, 1] |
O último ponto é particularmente interessante. O CEO é um contador de histórias — seu trabalho é pintar um quadro bonito. O CFO é quem presta contas aos auditores. Quando o CEO diz "transformative growth ahead" e o CFO intervém imediatamente com "while maintaining disciplined cost management" — essa divergência sinaliza tensões internas.
3. Inteligência competitiva
Um LLM consegue extrair menções a concorrentes de uma transcrição, mesmo quando a diretoria evita nomes diretos. "The largest player in the market" — isso não é mistério para o GPT-4 se ele conhecer o setor.
Sinal de trading: se a empresa A menciona o concorrente B em um contexto negativo durante sua earnings call ("we're taking share from..."), isso é um sinal não só para A (long), mas também para B (short). Um pairs trade.
4. Sinais de rotatividade da diretoria
Frases marcadoras de mudanças na diretoria ou pivôs estratégicos:
- "Exploring strategic alternatives" — provável venda da empresa
- "Right-sizing our operations" — demissões em massa
- "The board has initiated a comprehensive review" — o CEO sairá em breve
- "We're bringing in fresh perspectives" — a equipe atual fracassou
Cada uma dessas frases tem uma correlação estatisticamente significativa com a dinâmica de preços subsequente. Um LLM consegue detectá-las com zero falsos positivos — porque entende contexto, ao contrário do regex, que poderia capturar "strategic alternatives" em uma descrição de linha de produtos.
Backtesting: metodologia de estudo de eventos

Estamos gerando sinais — ótimo. Mas eles funcionam? O método de verificação padrão é um Event Study com o cálculo de retornos anormais acumulados (CAR).
Metodologia
- Definir o evento — a data da earnings call
- Janela de estimação — [-250, -30] dias de negociação antes do evento para estimar retornos "normais"
- Janela do evento — [-1, +60] dias ao redor do evento
- Calcular retornos normais através do modelo de mercado:
- Retorno anormal — a diferença entre o retorno real e o "normal"
- CAR — soma acumulada dos retornos anormais na janela do evento
import numpy as np
import pandas as pd
from scipy import stats
from dataclasses import dataclass
@dataclass
class EventStudyResult:
car: np.ndarray # Cumulative abnormal returns by day
t_stats: np.ndarray # t-statistics for each day
avg_car_3d: float # CAR[-1, +1]
avg_car_30d: float # CAR[-1, +30]
avg_car_60d: float # CAR[-1, +60]
p_value_3d: float
p_value_30d: float
n_events: int
def run_event_study(
returns: pd.DataFrame, # Daily stock returns (columns = tickers)
market_returns: pd.Series, # Daily market index returns
events: pd.DataFrame, # DataFrame with columns: [ticker, date, signal_score]
estimation_window: int = 220,
gap: int = 30,
event_window: tuple = (-1, 60),
) -> EventStudyResult:
"""
Event study to evaluate the predictive power of LLM signals.
Sort events by signal_score, form long/short portfolios,
calculate CAR and test statistical significance.
"""
all_cars = []
for _, event in events.iterrows():
ticker = event['ticker']
event_date = event['date']
if ticker not in returns.columns:
continue
try:
event_idx = returns.index.get_loc(event_date, method='ffill')
except KeyError:
continue
est_start = event_idx - estimation_window - gap
est_end = event_idx - gap
if est_start < 0:
continue
y = returns.iloc[est_start:est_end][ticker].values
x = market_returns.iloc[est_start:est_end].values
mask = ~(np.isnan(y) | np.isnan(x))
if mask.sum() < 60: # Minimum 60 observations
continue
y_clean, x_clean = y[mask], x[mask]
slope, intercept, _, _, _ = stats.linregress(x_clean, y_clean)
residual_std = np.std(y_clean - (intercept + slope * x_clean))
ev_start = event_idx + event_window[0]
ev_end = event_idx + event_window[1] + 1
if ev_end > len(returns):
continue
actual = returns.iloc[ev_start:ev_end][ticker].values
market = market_returns.iloc[ev_start:ev_end].values
expected = intercept + slope * market
ar = actual - expected
car = np.cumsum(ar)
all_cars.append(car)
if not all_cars:
raise ValueError("No valid events found")
min_len = min(len(c) for c in all_cars)
all_cars = np.array([c[:min_len] for c in all_cars])
mean_car = np.mean(all_cars, axis=0)
std_car = np.std(all_cars, axis=0) / np.sqrt(len(all_cars))
t_stats = mean_car / (std_car + 1e-10)
offset = -event_window[0] # Shift to event date
car_3d = mean_car[min(offset + 1, min_len - 1)] if min_len > offset + 1 else mean_car[-1]
car_30d = mean_car[min(offset + 30, min_len - 1)] if min_len > offset + 30 else mean_car[-1]
car_60d = mean_car[min(offset + 60, min_len - 1)] if min_len > offset + 60 else mean_car[-1]
n = len(all_cars)
p_3d = 2 * (1 - stats.t.cdf(abs(car_3d / (np.std([c[min(offset+1, min_len-1)] for c in all_cars]) / np.sqrt(n) + 1e-10)), df=n-1))
p_30d = 2 * (1 - stats.t.cdf(abs(car_30d / (np.std([c[min(offset+30, min_len-1)] for c in all_cars]) / np.sqrt(n) + 1e-10)), df=n-1))
return EventStudyResult(
car=mean_car,
t_stats=t_stats,
avg_car_3d=car_3d,
avg_car_30d=car_30d,
avg_car_60d=car_60d,
p_value_3d=p_3d,
p_value_30d=p_30d,
n_events=n,
)
def backtest_llm_signals(
llm_signals: pd.DataFrame, # [ticker, date, sentiment_score]
returns: pd.DataFrame,
market_returns: pd.Series,
):
"""Backtest: long top-quintile signals, short bottom-quintile."""
llm_signals['quintile'] = pd.qcut(
llm_signals['sentiment_score'], 5, labels=[1, 2, 3, 4, 5]
)
long_events = llm_signals[llm_signals['quintile'] == 5].copy()
short_events = llm_signals[llm_signals['quintile'] == 1].copy()
long_result = run_event_study(returns, market_returns, long_events)
short_result = run_event_study(returns, market_returns, short_events)
print(f"LONG portfolio (top quintile LLM sentiment):")
print(f" CAR[0,+3]: {long_result.avg_car_3d:+.2%} (p={long_result.p_value_3d:.4f})")
print(f" CAR[0,+30]: {long_result.avg_car_30d:+.2%} (p={long_result.p_value_30d:.4f})")
print(f" N events: {long_result.n_events}")
print(f"\nSHORT portfolio (bottom quintile LLM sentiment):")
print(f" CAR[0,+3]: {short_result.avg_car_3d:+.2%} (p={short_result.p_value_3d:.4f})")
print(f" CAR[0,+30]: {short_result.avg_car_30d:+.2%} (p={short_result.p_value_30d:.4f})")
print(f" N events: {short_result.n_events}")
ls_3d = long_result.avg_car_3d - short_result.avg_car_3d
ls_30d = long_result.avg_car_30d - short_result.avg_car_30d
print(f"\nLONG-SHORT spread:")
print(f" CAR[0,+3]: {ls_3d:+.2%}")
print(f" CAR[0,+30]: {ls_30d:+.2%}")
O que esperamos ver
Com base em pesquisas existentes, CARs realistas para sinais de LLM:
| Janela | Portfólio long | Portfólio short | Spread L/S |
|---|---|---|---|
| [0, +1] | +0,8% — +1,5% | -0,5% — -1,2% | 1,3% — 2,7% |
| [0, +30] | +1,5% — +3,0% | -1,0% — -2,5% | 2,5% — 5,5% |
| [0, +60] | +2,0% — +4,0% | -1,5% — -3,5% | 3,5% — 7,5% |
O indicador-chave é a significância estatística. Com p < 0,01 e N > 200 eventos, pode-se falar de um sinal robusto. Com p > 0,05 — pode ser ruído.
Implementação em produção: do Jupyter à produção
Arquitetura do pipeline em tempo real
YouTube/Audio Stream
│
▼
┌─────────────────┐ ┌──────────────────┐
│ Whisper │───▶│ Transcript │
│ Transcription │ │ Buffer │
│ (streaming) │ │ (Redis Stream) │
└─────────────────┘ └──────────────────┘
│
┌─────────┴─────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Real-time │ │ Full-call │
│ Chunk Anal. │ │ Analysis │
│ (every 5min) │ │ (after call │
│ │ │ ends) │
└──────────────┘ └──────────────┘
│ │
▼ ▼
┌──────────────────────────────┐
│ Signal Aggregator │
│ (confidence-weighted merge) │
└──────────────────────────────┘
│
▼
┌──────────────────────────────┐
│ Trading Engine │
│ (position sizing, risk mgmt)│
└──────────────────────────────┘
Análise de custos: quanto custa uma earnings call
Vamos detalhar a economia de processar uma única earnings call em produção:
| Componente | Custo | Latência |
|---|---|---|
| Transcrição via API do Whisper (60 min) | $0,36 | ~17 seg (Turbo) |
| Extração estruturada com GPT-4o | $0,15-0,30 | ~8-15 seg |
| Análise de blocos em tempo real com GPT-4o (x12) | $1,80-3,60 | ~5 seg cada |
| Embedding para armazenamento RAG | $0,01 | <1 seg |
| Total (pipeline completo) | $2,30-4,30 | ~30 seg no total |
Espere, a estimativa era de $30-50 por chamada. De onde vêm esses números? Depende do modelo e da abordagem:
- Opção econômica (GPT-4o-mini, uma única passagem): $0,50-1,00
- Opção padrão (GPT-4o, extração estruturada + análise de blocos): $2-5
- Opção premium (GPT-4o, múltiplas passagens, validação cruzada, comparação histórica): $15-30
- Nível hedge fund (múltiplos modelos + revisão humana + streaming em tempo real): $30-50+
Para um fundo quantitativo que negocia 500 tickers, o custo de processar uma temporada de resultados (~2.000 chamadas em 6 semanas) é de 10.000 com a opção padrão. Dado um alfa médio por posição de 1-3% — o ROI é astronômico.
Latência: a corrida por milissegundos
No mundo do HFT, a latência é tudo. Mas para estratégias baseadas em resultados, a situação é diferente:
- Uma earnings call dura de 45 a 60 minutos — há tempo
- O PEAD se estende por 60 dias — não há necessidade de entrar no primeiro segundo
- A principal deslocação ocorre nos primeiros 30 minutos após o término da chamada
A estratégia ideal é em duas fases:
- Fase 1 (tempo real): analisar blocos de 5 minutos durante a chamada, formando um sinal preliminar
- Fase 2 (pós-chamada): análise completa de toda a transcrição de 2 a 5 minutos após o término
A Fase 1 oferece uma vantagem de 5-10 minutos sobre os participantes do mercado que esperam o término da chamada. Para ações de média capitalização, isso é suficiente.
Expansão para cripto: governança DeFi e propostas de DAO
O mercado cripto é um terreno de testes ideal para o LLM alpha mining. Eis o motivo:
- Menos players institucionais — o que significa mais ineficiência a explorar
- Governança = earnings call — as decisões da DAO afetam diretamente a tokenomics
- Mercado 24/7 — é possível negociar a reação imediatamente
- Dados públicos — todas as propostas e votações são on-chain
Tipos de eventos cripto para análise
Propostas de governança (Aave, Compound, Uniswap)
Uma proposta altera parâmetros do protocolo — taxas de juros, fatores de colateral, fee switches. Um LLM pode avaliar o impacto econômico:
crypto_analysis_prompt = """Analyze this DeFi governance proposal.
Extract:
1. Economic impact on token holders (positive/negative/neutral)
2. TVL impact estimate (increase/decrease/stable + magnitude)
3. Competitive positioning vs other protocols
4. Risk factors introduced by the proposal
5. Historical precedent (similar proposals in other protocols)
6. Likely voting outcome based on forum discussion sentiment
Proposal: {proposal_text}
Forum discussion: {discussion_text}
"""
Anúncios de atualização de protocolo
Quando a Uniswap anuncia a v4 com hooks, ou a Aave lança o GHO — isso é o equivalente ao lançamento de um produto em TradFi. Um LLM consegue avaliar o momentum narrativo e a relevância técnica.
Relatórios de tesouraria
Grandes DAOs têm tesourarias no valor de centenas de milhões. Relatórios trimestrais de tesouraria são um análogo direto dos resultados. Runway, burn rate, diversificação — tudo passível de análise por LLM.
Particularidades dos sinais cripto
Ao contrário do TradFi, no cripto:
- Dados on-chain confirmam ou contradizem a narrativa — é possível cruzar o que é dito nas governance calls com métricas reais do protocolo (TVL, volume, usuários ativos)
- Whale wallets como insider trading — grandes movimentações de carteiras após discussões de governança frequentemente precedem a votação
- Amplificação de sentimento via CT (Crypto Twitter) — um sinal de uma governance call pode ser amplificado ou suprimido por narrativas do Twitter
Armadilhas e limitações
Alucinações: quando o modelo inventa números
Um LLM pode "extrair" guidance que não estava na transcrição. Isso é especialmente perigoso ao analisar a densidade de palavras de proteção: o modelo pode contar mais ou menos palavras do que realmente existem.
Solução: verificação em duas fases. O LLM extrai, código determinístico verifica. Para palavras de proteção — contagem por regex em paralelo à avaliação do LLM. Desvio > 20% — sinalizar para revisão manual.
import re
HEDGE_WORDS = [
r'\bapproximately\b', r'\bpotentially\b', r'\bsubject to\b',
r'\bmay\b', r'\bmight\b', r'\bcould\b', r'\buncertain\b',
r'\bchallenging\b', r'\bheadwinds\b', r'\bnavigate\b',
r'\bprudent\b', r'\bcautious\b', r'\bevolving\b',
r'\bdynamic\b', r'\bunprecedented\b', r'\btransitional\b',
]
def verify_hedge_count(text: str, llm_count: int) -> dict:
"""Deterministic verification of LLM hedge word count."""
regex_count = sum(
len(re.findall(pattern, text, re.IGNORECASE))
for pattern in HEDGE_WORDS
)
deviation = abs(llm_count - regex_count) / (regex_count + 1)
return {
"llm_count": llm_count,
"regex_count": regex_count,
"deviation": deviation,
"needs_review": deviation > 0.2,
}
Limitações da janela de contexto
Mesmo 128K tokens podem não ser suficientes se você quiser fornecer:
- Transcrição atual (~10K tokens)
- Transcrição anterior para comparação (~10K)
- Previsões de consenso dos analistas (~2K)
- Exemplos few-shot (~3K)
- Prompt do sistema (~1K)
Total ~26K — cabemos por pouco. Mas se você adicionar um arquivamento 10-K (~80-120K tokens) para contexto — já está no limite. Solução: RAG para recuperar blocos relevantes de documentos longos.
Viés e erros sistemáticos
Os LLMs são treinados em dados históricos nos quais certas frases estavam associadas a certos resultados. Mas o mercado se adapta:
- Se todos começarem a contar palavras de proteção com GPT-4, os executivos mudarão sua linguagem
- O modelo pode superestimar a importância de padrões dos dados de treinamento (viés de sobrevivência)
- A linguagem corporativa evolui: "sinergias" em 2010 significava uma coisa, em 2026 — outra
Risco de trade lotado
Se 50 fundos quantitativos usarem o mesmo GPT-4 para analisar as mesmas transcrições — o sinal se degrada. Uma analogia: quando todos começaram a negociar o PEAD sobre surpresas numéricas, a anomalia encolheu. O mesmo acontecerá com os sinais textuais, mas com atraso:
- Agora (2026) — poucos usam LLMs sistematicamente para earnings calls. O alfa é significativo
- Em 2-3 anos — ampla adoção, o alfa diminui
- Em 5 anos — sinais básicos de LLM se tornam commodity, o edge persiste apenas em modelos personalizados e dados únicos
Este é o ciclo de vida padrão de um sinal de alfa. Aproveite enquanto durar.
Em vez de uma conclusão: um plano de ação
Se você quer começar a usar LLMs para análise de earnings calls, aqui está um plano mínimo viável:
- Comece com dados gratuitos — SEC EDGAR + EdgarTools para arquivamentos 8-K/10-Q
- Use extração estruturada — esquemas Pydantic via OpenAI Structured Outputs
- Faça backtesting via event study — CAR em dados históricos, mínimo de 200 eventos
- Adicione exemplos few-shot — 5-10 exemplos rotulados melhoram radicalmente a qualidade
- Verifique de forma determinística — o LLM extrai, o regex verifica, o humano audita
- Comece com mid-cap — mais alfa, menos concorrência com grandes fundos
- Expanda para cripto — governance calls e propostas de DAO como território inexplorado
Lembre-se da regra cardinal da análise quantitativa: se um sinal parece bom demais para ser verdade — verifique novamente. Os LLMs criam uma ilusão de compreensão, mas por trás dela há correspondência estatística de padrões. Uma ferramenta poderosa — mas uma ferramenta, não um oráculo.
Bibliografia
-
Ball, R., Brown, P. (1968). An Empirical Evaluation of Accounting Income Numbers. Journal of Accounting Research, 6(2), 159-178. — Primeira descoberta do PEAD.
-
Bernard, V.L., Thomas, J.K. (1989). Post-Earnings-Announcement Drift: Delayed Price Response or Risk Premium? Journal of Accounting Research, 27, 1-36. — Artigo canônico sobre o PEAD.
-
Loughran, T., McDonald, B. (2011). When Is a Liability Not a Liability? Textual Analysis, Dictionaries, and 10-Ks. Journal of Finance, 66(1), 35-65. — Dicionário de sentimento financeiro.
-
Araci, D. (2019). FinBERT: Financial Sentiment Analysis with Pre-trained Language Models. arXiv:1908.10063. — BERT para NLP financeiro, +14pp em relação ao SOTA.
-
Wu, S. et al. (2023). BloombergGPT: A Large Language Model for Finance. arXiv:2303.17564. — Modelo de 50B parâmetros da Bloomberg.
-
Yang, H. et al. (2023). FinGPT: Open-Source Financial Large Language Models. arXiv:2306.06031. — Alternativa de código aberto ao BloombergGPT, 89% de precisão.
-
Lopez-Lira, A., Tang, Y. (2023). Can ChatGPT Forecast Stock Price Movements? Return Predictability and Large Language Models. arXiv:2304.07619. — GPT-4 prevê retornos com ~90% de taxa de acerto.
-
Meursault, V., Liang, P.J., Routledge, B., Scanlon, M.M. (2023). PEAD.txt: Post-Earnings-Announcement Drift Using Text. Journal of Financial and Quantitative Analysis. — O PEAD baseado em texto é o dobro do PEAD numérico.
-
Fatouros, G. et al. (2024). Can Large Language Models Beat Wall Street? Evaluating GPT-4's Impact on Financial Decision-Making with MarketSenseAI. Neural Computing and Applications. — Framework GPT-4 com 10-30% de alfa excedente no S&P 100.
-
Chen, Y. et al. (2025). GPT-Signal: Generative AI for Semi-automated Feature Engineering in the Alpha Research Process. arXiv:2410.18448. — Geração automática de sinais de trading via LLM.
-
Zhang, X. et al. (2025). Can LLMs Hit Moving Targets? Tracking Evolving Signals in Corporate Disclosures. arXiv:2510.03195. — Detecção de "alvos móveis" em divulgações corporativas.
-
Chen, Z. et al. (2025). Large Language Models in Equity Markets: Applications, Techniques, and Insights. Frontiers in Artificial Intelligence. — Revisão de 84 estudos de LLM em finanças.
Este artigo tem caráter educacional e não constitui aconselhamento de investimento. Qualquer estratégia de trading aqui descrita requer backtesting rigoroso e gestão de risco antes de ser implantada com capital real.
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.