Tutorial por bolsai 19 abr 2026 10 min de leitura

Google Sheets com Cotações da B3 em Tempo Real via API

Quem usa google sheets cotações B3 conhece o teto invisível da função GOOGLEFINANCE: cobertura irregular de FIIs, ausência de indicadores fundamentalistas e nenhum histórico de dividendos. Este guia mostra como estender o Google Sheets com Apps Script e a API da bolsai, criando fórmulas personalizadas que consultam preço, P/L, ROE, dividend yield e dados de FII direto de qualquer célula da planilha.

Por que GOOGLEFINANCE não é suficiente para ações brasileiras

A função GOOGLEFINANCE devolve cotação e histórico básicos de ações listadas na B3, mas falha em FIIs, não expõe múltiplos como P/L e P/VP, não cobre dividendos e opera com atraso de 15 a 20 minutos no pregão. Para cotação google sheets brasil completa é preciso chamar uma API dedicada via Apps Script.

O caso mais frequente são os fundos imobiliários. Tickers como HGLG11, MXRF11 e KNRI11 retornam #N/A em muitos ambientes da função, mesmo quando prefixados com BVMF:. A documentação do próprio Google classifica o mercado brasileiro como cobertura parcial, e a atualização é intencionalmente atrasada. Para uma planilha de acompanhamento, o efeito prático é ter células vazias justamente nos papéis de renda mensal que motivaram o esforço.

A segunda lacuna é fundamentalista. GOOGLEFINANCE entrega price, volume, marketcap e pouco mais. Não existe atributo para P/L, P/VP, ROE, margem líquida, dividend yield histórico ou payout. Uma carteira montada no Google Sheets fica dependente de copiar e colar dados de sites de terceiros, processo frágil que quebra quando qualquer layout muda. O guia da API gratuita da B3 detalha os endpoints que substituem esse fluxo manual.

O que a API da bolsai adiciona ao Google Sheets

A bolsai é uma API REST que agrega dados oficiais da B3 e da CVM e entrega preços, 27 indicadores fundamentalistas, FIIs e dividendos em JSON pronto para consumir. Ao conectar essa API ao Google Sheets via Apps Script, a planilha deixa de depender de um único atributo fixo e passa a receber qualquer dado do mercado brasileiro em células comuns. A tabela abaixo resume o contraste entre a função nativa e o caminho via API.

Dado GOOGLEFINANCE API bolsai via Apps Script
Cotação de ações (PETR4, VALE3) Parcial, atraso de 15-20 min Fechamento diário oficial do COTAHIST
Cotação de FIIs (HGLG11, MXRF11) Falhas frequentes, retorna #N/A Cobertura de 400+ FIIs
Indicadores fundamentalistas (P/L, ROE, DY) Não disponível 27 indicadores calculados com TTM
Dividendos e JCP históricos Não disponível Histórico completo por ticker
Histórico de preços longo prazo Limitado, fórmula matricial Séries desde 1986 via COTAHIST
Delay de atualização 15-20 minutos no plano padrão Fechamento D+0 após o pregão

Setup inicial: API key da bolsai e Apps Script

O caminho entre abrir uma planilha nova e ter a primeira fórmula personalizada funcionando leva cerca de cinco minutos. A única dependência externa é a API key obtida no painel em usebolsai.com. O passo a passo abaixo assume um Google Sheets vazio.

  1. Crie uma conta em usebolsai.com, acesse /dashboard e copie a chave pessoal. O plano gratuito libera 200 requisições por dia, suficiente para planilhas de acompanhamento com algumas dezenas de papéis.
  2. No Google Sheets, abra o menu Extensões → Apps Script. Uma aba nova abre com um editor de código vazio. Remova o conteúdo padrão.
  3. Cole o código do editor de funções personalizadas mostrado adiante. Salve com Ctrl+S ou no botão de disquete. Um clique em Executar a primeira vez pedirá autorização OAuth do Google para acessar URLs externas.
  4. Configure a chave em Propriedades do projeto → Propriedades do script, chave BOLSAI_API_KEY, valor igual à API key copiada. Usar PropertiesService evita hard-coding da chave no código da planilha compartilhada.
  5. Volte à planilha e digite =BOLSAI_QUOTE("PETR4") em qualquer célula. O valor aparece em segundos. Se a célula marcar #ERROR!, abra o editor em Execução → Logs para ver a mensagem; o motivo mais comum é chave ausente ou ticker inválido.

A autorização OAuth é exigida pelo Google em qualquer Apps Script que chame domínios externos. O escopo pedido é script.external_request. A aprovação é pontual e fica persistida no projeto; recarregar a planilha não reexibe o prompt.

A documentação completa da API lista todos os endpoints aceitos pelas funções abaixo, os campos retornados no JSON e os parâmetros opcionais para histórico, screener e exportação CSV.

Função customizada: =BOLSAI_QUOTE("PETR4") para cotação

A fórmula mais básica consulta o endpoint /stocks/{ticker}/quote e devolve o preço de fechamento. A implementação abaixo usa UrlFetchApp para a requisição HTTP, PropertiesService para ler a chave e CacheService para poupar chamadas repetidas. Cinco minutos de cache é suficiente porque o pregão oficial da B3 fecha em D+0 e o valor não muda durante a sessão.

/**
 * Retorna o último preço de fechamento de uma ação da B3.
 * @param {string} ticker Ticker da ação (ex: "PETR4").
 * @return {number} Preço de fechamento.
 * @customfunction
 */
function BOLSAI_QUOTE(ticker) {
  if (!ticker) throw new Error("Informe o ticker");
  ticker = String(ticker).toUpperCase().trim();

  const cache = CacheService.getScriptCache();
  const cacheKey = "quote_" + ticker;
  const cached = cache.get(cacheKey);
  if (cached) return Number(cached);

  const key = PropertiesService.getScriptProperties().getProperty("BOLSAI_API_KEY");
  if (!key) throw new Error("BOLSAI_API_KEY ausente em Propriedades do script");

  const url = "https://api.usebolsai.com/api/v1/stocks/" + ticker + "/quote";
  const res = UrlFetchApp.fetch(url, {
    headers: { "X-API-Key": key },
    muteHttpExceptions: true
  });

  if (res.getResponseCode() !== 200) {
    throw new Error("HTTP " + res.getResponseCode() + ": " + res.getContentText());
  }

  const data = JSON.parse(res.getContentText());
  const price = data.close;
  cache.put(cacheKey, String(price), 300); // 5 minutos
  return price;
}

Uso em célula: =BOLSAI_QUOTE("PETR4"), =BOLSAI_QUOTE(A2) ou arrastando a fórmula para baixo em uma coluna com a lista de tickers. Valores retornados já saem como número, então formatações de moeda em R$ no Google Sheets funcionam sem conversão extra.

A B PETR4 32.84 VALE3 58.12 ITUB4 34.52 BBAS3 27.91 WEGE3 41.05

Função para indicadores fundamentalistas: =BOLSAI_FUNDAMENTAL("ITUB4", "pl")

A mesma estrutura serve para qualquer endpoint. O endpoint /fundamentals/{ticker} devolve 27 campos, entre eles pl, pvp, roe, net_margin, ev_ebitda, market_cap e lpa. A função abaixo aceita dois argumentos e retorna o campo solicitado, permitindo que uma planilha cobre múltiplos indicadores do mesmo papel com fórmulas em colunas separadas. Dividend yield vive em endpoint próprio, detalhado na próxima seção.

/**
 * Retorna um indicador fundamentalista de uma ação.
 * @param {string} ticker Ticker da ação.
 * @param {string} field Campo desejado (pl, pvp, roe, ev_ebitda, lpa, vpa, ...).
 * @return {number} Valor do indicador.
 * @customfunction
 */
function BOLSAI_FUNDAMENTAL(ticker, field) {
  if (!ticker || !field) throw new Error("ticker e field são obrigatórios");
  ticker = String(ticker).toUpperCase().trim();
  field = String(field).toLowerCase().trim();

  const cache = CacheService.getScriptCache();
  const cacheKey = "fund_" + ticker;
  let json = cache.get(cacheKey);

  if (!json) {
    const key = PropertiesService.getScriptProperties().getProperty("BOLSAI_API_KEY");
    const url = "https://api.usebolsai.com/api/v1/fundamentals/" + ticker;
    const res = UrlFetchApp.fetch(url, {
      headers: { "X-API-Key": key },
      muteHttpExceptions: true
    });
    if (res.getResponseCode() !== 200) {
      throw new Error("HTTP " + res.getResponseCode());
    }
    json = res.getContentText();
    cache.put(cacheKey, json, 21600); // 6 horas: fundamentos mudam com publicação de DFP/ITR
  }

  const data = JSON.parse(json);
  if (!(field in data)) {
    throw new Error("Campo '" + field + "' não existe. Veja /docs.");
  }
  return data[field];
}

Usos típicos em célula: =BOLSAI_FUNDAMENTAL("ITUB4","pl"), =BOLSAI_FUNDAMENTAL(A2,"roe"), =BOLSAI_FUNDAMENTAL(A2,"ev_ebitda"). A lista completa de campos disponíveis está detalhada em /docs. Para dividend yield usa-se o endpoint /dividends/{ticker}, que expõe o campo dividend_yield_ttm e pode ser lido por uma variação da função acima com base "https://api.usebolsai.com/api/v1/dividends/". Quem está começando e quer uma explicação mais detalhada dos múltiplos encontra o passo a passo no artigo sobre P/L em Python, que aplica a mesma metodologia que alimenta a API.

Função para FIIs: cotação e dividend yield

Os FIIs concentram a maior parte das falhas do GOOGLEFINANCE. O endpoint /fiis/{ticker} devolve cotação (close_price), P/VP, dividend yield de 12 meses (dividend_yield_ttm), valor patrimonial por cota, segmento e número de cotistas. A função abaixo extrai qualquer um desses campos, eliminando a necessidade de consultar múltiplas planilhas externas.

/**
 * Retorna dados de um fundo imobiliário.
 * @param {string} ticker Ticker do FII (ex: "HGLG11").
 * @param {string} field Campo: close_price, pvp, dividend_yield_ttm, book_value_per_share, segment.
 * @return {*} Valor do campo solicitado.
 * @customfunction
 */
function BOLSAI_FII(ticker, field) {
  if (!ticker) throw new Error("Informe o ticker do FII");
  ticker = String(ticker).toUpperCase().trim();
  field = (field || "close_price").toLowerCase().trim();

  const cache = CacheService.getScriptCache();
  const cacheKey = "fii_" + ticker;
  let json = cache.get(cacheKey);

  if (!json) {
    const key = PropertiesService.getScriptProperties().getProperty("BOLSAI_API_KEY");
    const url = "https://api.usebolsai.com/api/v1/fiis/" + ticker;
    const res = UrlFetchApp.fetch(url, {
      headers: { "X-API-Key": key },
      muteHttpExceptions: true
    });
    if (res.getResponseCode() !== 200) {
      throw new Error("HTTP " + res.getResponseCode() + " em /fiis/" + ticker);
    }
    json = res.getContentText();
    cache.put(cacheKey, json, 3600); // 1 hora: informe mensal do FII é pouco frequente
  }

  const data = JSON.parse(json);
  return data[field];
}

Exemplos de uso: =BOLSAI_FII("HGLG11","close_price") devolve a cotação, =BOLSAI_FII("MXRF11","dividend_yield_ttm") devolve o DY anualizado em percentual e =BOLSAI_FII("KNRI11","pvp") devolve o P/VP. A mesma fórmula arrasta por uma coluna com 50 tickers de FII sem cair em #N/A, algo que GOOGLEFINANCE raramente sustenta. Para aprofundar a análise por segmento (logística, lajes, papel, shopping, híbridos), o artigo sobre API de fundos imobiliários mostra variações avançadas de leitura.

Atualização automática com triggers

Funções personalizadas do Apps Script não recalculam a cada tick do mercado. Elas rodam quando a célula é editada, quando a planilha é aberta ou quando algum evento dispara o recálculo. Para manter a carteira atualizada durante o pregão sem intervenção manual, a combinação padrão é um trigger por tempo que sobrescreve uma célula de timestamp, forçando o Google Sheets a reexecutar todas as fórmulas que dependem dela indiretamente.

/**
 * Atualiza célula de controle para forçar recálculo das fórmulas.
 * Criar trigger: no editor, relógio lateral → Adicionar trigger
 * → Função: forceRefresh | Fonte: Por tempo | Tipo: Timer por hora.
 */
function forceRefresh() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName("Carteira");
  if (!sheet) return;

  // Invalida caches para forçar nova chamada à API
  CacheService.getScriptCache().removeAll([]);

  // Escreve timestamp em uma célula auxiliar (ex: Z1)
  sheet.getRange("Z1").setValue(new Date());
}

Para criar o trigger, abre-se o editor de Apps Script, clica-se no ícone de relógio na barra lateral esquerda e adiciona-se uma nova regra: origem Por tempo, tipo Timer por hora, intervalo A cada hora. Uma restrição do Apps Script é que triggers não rodam em contas gratuitas fora do horário comercial em casos raros de cota; o caminho seguro é aceitar o comportamento padrão e limitar o horário via guarda if checando new Date().getUTCHours() entre 13 e 21 UTC, janela que cobre 10h-18h em Brasília. A documentação oficial do Apps Script está em developers.google.com/apps-script.

Exemplo prático: carteira de acompanhamento

Uma planilha de acompanhamento completo nasce combinando as três funções em colunas disciplinadas. A estrutura abaixo é a que tem rendido melhor em uso real: primeira aba com tickers, quantidade e preço médio, colunas seguintes preenchidas automaticamente pelas fórmulas. Cada linha descreve uma posição.

Coluna Fórmula Resultado esperado
A: Ticker PETR4 (manual) Entrada do usuário
B: Quantidade 200 (manual) Entrada do usuário
C: Preço médio 28.50 (manual) Entrada do usuário
D: Preço atual =BOLSAI_QUOTE(A2) Fechamento diário
E: P/L =BOLSAI_FUNDAMENTAL(A2,"pl") Múltiplo TTM
F: Dividend Yield =BOLSAI_FUNDAMENTAL(A2,"dividend_yield") * DY 12m (via /dividends)
G: Valor da posição =B2*D2 R$ na cotação do dia
H: Lucro/Prejuízo =(D2-C2)*B2 Resultado financeiro
I: Variação % =(D2/C2)-1 Formatar como porcentagem

Para a coluna F funcionar como descrita, a função BOLSAI_FUNDAMENTAL precisa de uma variação específica para dividendos: basta duplicar a função trocando o endpoint de /fundamentals/ para /dividends/, ou criar uma função BOLSAI_DIVIDEND_YIELD(ticker) dedicada que retorne data.dividend_yield_ttm. A linha de rodapé usa =SUM(G:G) para patrimônio total, =SUMPRODUCT(F:F,G:G)/SUM(G:G) para DY ponderado e =SUM(H:H) para lucro acumulado. Uma carteira de 30 papéis atualizada de hora em hora consome cerca de 90 requisições por dia com cache de 5-60 min, cabendo confortavelmente no free tier. O comparativo bolsai vs brapi traz números detalhados sobre cobertura e limites, útil antes de fixar a planilha em um fornecedor.

Perguntas frequentes

É possível usar a bolsai sem o Apps Script?

Sim. Qualquer linguagem ou ferramenta que faça requisições HTTP consome a API: Python, Node, Excel com Power Query, Notion com blocos de código, n8n, Zapier e assistentes como Claude via MCP. O Apps Script é apenas a via mais direta dentro do próprio Google Sheets porque permite escrever funções personalizadas que atuam como fórmulas de célula, sem precisar de add-on externo nem de servidor intermediário.

A API funciona com IMPORTDATA direto?

Não de forma recomendada. IMPORTDATA exige URL pública que retorne CSV e não envia cabeçalhos HTTP personalizados. A chave de API da bolsai viaja no cabeçalho X-API-Key, o que torna IMPORTDATA inadequado. O caminho estável é Apps Script com UrlFetchApp, que aceita headers arbitrários, respeita o limite de chamadas e permite cache via CacheService. Dito isso, quem insiste em usar importdata ações brasileiras sem Apps Script pode expor um endpoint proxy próprio em Cloud Functions ou similar que injete a chave no header e devolva CSV público, fluxo que funciona, mas aumenta a complexidade.

Qual o limite de chamadas no plano gratuito?

O plano gratuito libera 200 requisições por dia. Para uma planilha com 30 papéis consultando cotação e um indicador a cada hora durante o pregão, o volume cabe no limite desde que o CacheService seja utilizado. O plano Pro (R$ 49/mês) sobe o teto para 10.000 chamadas diárias, adequado para planilhas compartilhadas ou múltiplas abas de acompanhamento. Os detalhes e comparativo estão em /#pricing.

O Google Sheets atualiza em tempo real?

Funções personalizadas do Apps Script não disparam a cada tick. O recálculo ocorre quando a célula é editada, quando a planilha é reaberta ou quando um trigger programado força a atualização. O padrão que funciona bem é combinar CacheService (evita chamar a API toda vez que a célula recalcula) com um trigger horário durante o pregão que sobrescreve uma célula de timestamp, forçando as fórmulas a recalcularem. A B3 publica o COTAHIST oficial após o fechamento, então cotação intradia pura está fora do escopo da função BOLSAI_QUOTE. Detalhes sobre o pregão e o calendário oficial da bolsa estão em b3.com.br.

Leia também

Disclaimer

O conteúdo deste artigo tem caráter informativo e educacional. Não constitui recomendação de compra ou venda. Indicadores são insumos para análise e não substituem due diligence nem avaliação compatível com o perfil do investidor. Valores ilustrativos refletem a base pública disponível em 2026-04-01 e podem variar após novos ITRs, DFPs e avisos de proventos.

por bolsai • 19 de abril de 2026 • 10 min de leitura

Comece agora

Planilhas construídas em cima de google sheets cotações B3 via API ganham autonomia imediata: cobertura de FIIs que o GOOGLEFINANCE não entrega, fundamentalistas calculados com TTM e dividendos históricos, tudo dentro da mesma célula. O plano gratuito libera 200 requisições diárias, suficiente para uma carteira de 30 a 50 papéis com atualização horária.