← Voltar aos artigos
March 20, 2026
5 min read

LLM Alpha Mining: como extrair sinais de trading de earnings calls e documentos financeiros

LLM Alpha Mining: como extrair sinais de trading de earnings calls e documentos financeiros
#llm
#alpha
#earnings
#nlp
#gpt
#financial-analysis
#algo-trading
🤖
Part 5 of 5 · Collection
AI Agents for Trading

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

From sentiment to semantics

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,006/min.Umagovernancecalldeumahoracusta 0,006/min. Uma governance call de uma hora custa ~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

Signal extraction pipeline

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

Event study results

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

  1. Definir o evento — a data da earnings call
  2. Janela de estimação — [-250, -30] dias de negociação antes do evento para estimar retornos "normais"
  3. Janela do evento — [-1, +60] dias ao redor do evento
  4. Calcular retornos normais através do modelo de mercado: Rit=αi+βiRmt+ϵitR_{it} = \alpha_i + \beta_i R_{mt} + \epsilon_{it}
  5. Retorno anormal — a diferença entre o retorno real e o "normal"
  6. 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 4.0004.000-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:

  1. Uma earnings call dura de 45 a 60 minutos — há tempo
  2. O PEAD se estende por 60 dias — não há necessidade de entrar no primeiro segundo
  3. 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:

  1. Menos players institucionais — o que significa mais ineficiência a explorar
  2. Governança = earnings call — as decisões da DAO afetam diretamente a tokenomics
  3. Mercado 24/7 — é possível negociar a reação imediatamente
  4. 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:

  1. Agora (2026) — poucos usam LLMs sistematicamente para earnings calls. O alfa é significativo
  2. Em 2-3 anos — ampla adoção, o alfa diminui
  3. 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:

  1. Comece com dados gratuitos — SEC EDGAR + EdgarTools para arquivamentos 8-K/10-Q
  2. Use extração estruturada — esquemas Pydantic via OpenAI Structured Outputs
  3. Faça backtesting via event study — CAR em dados históricos, mínimo de 200 eventos
  4. Adicione exemplos few-shot — 5-10 exemplos rotulados melhoram radicalmente a qualidade
  5. Verifique de forma determinística — o LLM extrai, o regex verifica, o humano audita
  6. Comece com mid-cap — mais alfa, menos concorrência com grandes fundos
  7. 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

  1. Ball, R., Brown, P. (1968). An Empirical Evaluation of Accounting Income Numbers. Journal of Accounting Research, 6(2), 159-178. — Primeira descoberta do PEAD.

  2. 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.

  3. 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.

  4. 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.

  5. Wu, S. et al. (2023). BloombergGPT: A Large Language Model for Finance. arXiv:2303.17564. — Modelo de 50B parâmetros da Bloomberg.

  6. 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.

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

  8. 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.

  9. 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.

  10. 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.

  11. 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.

  12. 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.

blog.disclaimer

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

Fique à frente do mercado

Assine nossa newsletter para insights exclusivos sobre trading com IA, análises de mercado e atualizações da plataforma.

Respeitamos sua privacidade. Cancele a inscrição a qualquer momento.