Todos os posts
Engenharia · 4 min

Histórico de ações em Python: como paginar sem repetir datas

Duas páginas de TOTS3, dez datas distintas e uma conferência contra a consulta maior. Um exemplo executado de cursor exclusivo.

Por Crivo · Dados até 09 de out. de 2026 · Produzido com assistência de IA

TOTS3 · dez fechamentos em ordem cronológica. 28/09 a 09/10/2026. Duas páginas de cinco registros; preço bruto sem certificação de ajuste por eventos ou retorno total.
Crivo · gráfico próprio com dados de Crivo

O histórico OHLC do Crivo é retornado da data mais recente para a mais antiga e usa um cursor exclusivo para continuar a consulta. Envie o cursor devolvido pela página anterior; não acrescente um dia, não subtraia segundos e não use o número da página como substituto.

No teste com TOTS3, duas páginas de cinco registros produziram dez datas distintas, de 28 de setembro a 9 de outubro de 2026. Conferimos esses registros contra os primeiros dez de uma consulta maior: datas, preços e volumes coincidiram.

Leia o cursor devolvido, sem reconstruí-lo

A resposta de /ohlc/TOTS3 contém o array ohlc_data e o objeto pagination. O cursor é um timestamp UTC numérico usado para continuar o histórico. A página seguinte traz observações anteriores ao limite exclusivo.

O fato de a primeira resposta ter cinco registros não diz que só existem cinco no banco. Da mesma forma, uma data ausente não prova um erro de coleta: pode ser um dia sem pregão ou sem observação na cobertura disponível. Paginação e completude de mercado são verificações diferentes.

import json
import os
from urllib.error import HTTPError
from urllib.request import Request, build_opener, HTTPRedirectHandler

class NoRedirect(HTTPRedirectHandler):
    def redirect_request(self, *args):
        return None

key = os.environ["CRIVO_API_KEY"].strip()
if not key:
    raise ValueError("CRIVO_API_KEY está vazia")
client = build_opener(NoRedirect())

def get_json(path):
    req = Request("https://api.crivo.ai" + path,
                  headers={"X-API-Key": key, "Accept": "application/json"})
    try:
        with client.open(req, timeout=30) as response:
            return json.load(response)
    except HTTPError as error:
        raise RuntimeError(f"Consulta interrompida: HTTP {error.code}") from None

bars, dates, cursors = [], set(), set()
cursor = None
for page in range(2):
    path = "/ohlc/TOTS3?limit=5"
    if cursor is not None:
        path += f"&cursor={cursor}"
    data = get_json(path)
    chunk = data["ohlc_data"]
    if not chunk:
        break
    for row in chunk:
        if row["date"] in dates:
            raise ValueError("Data repetida entre páginas")
        if row["close"] is None:
            raise ValueError("Fechamento ausente")
        dates.add(row["date"])
        bars.append(row)
    next_cursor = data["pagination"]["cursor"]
    if next_cursor is None:
        break
    if next_cursor in cursors:
        raise ValueError("Cursor repetido")
    cursors.add(next_cursor)
    cursor = next_cursor
bars.sort(key=lambda row: row["date"])
print(json.dumps(bars, ensure_ascii=False, indent=2))

O exemplo é deliberadamente limitado a duas páginas. Esse limite deixa o teste pequeno e reproduzível; não promete coletar todo o histórico da B3. Para uma janela maior, continue enquanto houver registros e um cursor novo, parando ao atingir a data desejada. Respeite os limites do acesso e interrompa em erro, em vez de tratar uma falha como fim do histórico.

Detecte repetição antes de ordenar

Um conjunto de datas detecta sobreposição entre páginas. Se a mesma data aparecer novamente, o código encerra com erro. Apenas remover a repetição esconderia uma falha de paginação ou uma alteração de cobertura durante a coleta.

Também confira a progressão do cursor. Um cursor que se repete pode criar um ciclo infinito em um coletor sem limite. A ordenação cronológica deve ocorrer depois dessas verificações, para transformar o formato de consulta em uma sequência adequada ao gráfico.

Duas páginas, dez registros distintos
PáginaMais antigaMais recenteRegistros
12026-10-052026-10-095
22026-09-282026-10-025
TOTS3; ordem de resposta decrescente. Cursor exclusivo e ausência de duplicação foram conferidos contra uma consulta maior.Fontes: Crivo · histórico OHLC

Na captura, a primeira página ia de 5 a 9 de outubro; a segunda, de 28 de setembro a 2 de outubro. Ambas vieram em ordem decrescente. Para o gráfico, reunimos as dez observações e ordenamos da mais antiga para a mais recente.

TOTS3 · dez fechamentos em ordem cronológica
Fechamento bruto
R$ por ação32,7335,2737,8240,3642,92026-09-282026-09-302026-10-022026-10-062026-10-08
Ver dados do gráfico
ReferênciaFechamento bruto (R$ por ação)
2026-09-2833,98
2026-09-2934,64
2026-09-3033,43
2026-10-0134,58
2026-10-0235,35
2026-10-0536,82
2026-10-0638,46
2026-10-0739,32
2026-10-0840,81
2026-10-0942,2
28/09 a 09/10/2026. Duas páginas de cinco registros; preço bruto sem certificação de ajuste por eventos ou retorno total.Fontes: Crivo · histórico OHLC

Confira null, campos e unidade

O exemplo exige uma data e um fechamento para cada ponto que será exportado. Se um fechamento for null, a execução para, em vez de convertê-lo em zero. Essa transformação criaria uma queda artificial de preço.

A verificação das datas também não substitui a conferência dos demais campos. Se sua aplicação usa máxima, mínima, abertura ou volume, valide os campos necessários e preserve a unidade retornada. Uma página com datas corretas ainda pode estar incompleta para o uso que você pretende fazer.

Preço bruto não é retorno total

Os fechamentos do gráfico são cotações brutas do histórico. A série não certifica ajustes por desdobramentos, grupamentos, proventos ou outros eventos. Sua variação não é automaticamente a rentabilidade de um investidor que manteve a ação.

Um estudo de patrimônio ou backtest precisa tratar eventos, dividendos, custos e critérios de universo, além de evitar informação futura. Conseguir paginar todos os registros não resolve esses requisitos econômicos.

Para uma integração de preços, guarde as páginas originais, parâmetros e horário da coleta. Assim, um gráfico pode ser reproduzido e uma divergência pode ser investigada. O teste de TOTS3 confirma o funcionamento do cursor naquele recorte; não certifica todo o histórico, todas as ações ou a continuidade de cada pregão.

Metodologia e limites

TOTS3, duas páginas de cinco barras OHLC com cursor UTC exclusivo; dez datas distintas de 28/09 a 09/10/2026. Comparação exata de datas, preços e volumes contra os primeiros dez registros de uma consulta de 15 barras; ordenação crescente somente para exibição. Código executado novamente com credencial comercial em 11/10/2026. Não certifica continuidade de todo o histórico ou ajustes de eventos.

  • Teste restrito a TOTS3 e dez registros. Não certifica cobertura de todas as datas, todos os ativos ou todo o histórico.
  • OHLC bruto não certifica ajuste por eventos nem retorno total; não é um backtest de patrimônio.

Fontes

  1. Crivo · histórico OHLC

    Fechamentos brutos e cursor UTC; TOTS3 com observações até 09/10/2026. · Consultado em 11 de out. de 2026

  2. Crivo · documentação e acesso

    Autenticação, catálogos, dados HTTP e ferramentas MCP; documentação consultada em 11/10/2026. · Consultado em 11 de out. de 2026

Com sua permissão, usamos Google Analytics para entender visitas, leitura dos posts e cadastros. Você pode recusar e continuar usando o Crivo. Sobre cookies