Ir para o conteúdo

API CEPEA

O módulo CEPEA fornece acesso aos indicadores de preços do Centro de Estudos Avançados em Economia Aplicada (ESALQ/USP).

Funções

indicador

Obtém série histórica de indicadores de preço.

A página publica uma janela recente, normalmente cerca de 15 pregões; o período anterior vem da série histórica do CEPEA, baixada inteira na primeira vez e guardada no cache (a laranja não tem série; ver a fonte). Etanol é semanal; leite é mensal, com data no primeiro dia do mês de referência e praca por UF.

async def indicador(
    produto: str,
    praca: str | None = None,
    inicio: str | date | None = None,
    fim: str | date | None = None,
    *,
    as_polars: bool = False,
    validate_sanity: bool = False,
    force_refresh: bool = False,
    offline: bool = False,
    return_meta: bool = False,
) -> pd.DataFrame | pl.DataFrame  # (df, MetaInfo) se return_meta=True

Parâmetros:

Parâmetro Tipo Descrição
produto str Produto CEPEA (22 disponíveis). Veja produtos() para lista completa
praca str \| None Praça de cotação. Aceita o slug de pracas() ou o rótulo exibido pela fonte; None retorna todas
inicio str \| date \| None Data inicial: date, datetime (a hora é descartada) ou texto AAAA-MM-DD ou DD/MM/AAAA. Default: 365 dias antes de fim
fim str \| date \| None Data final, nos mesmos formatos de inicio. Default: hoje
as_polars bool Retornar como polars.DataFrame
validate_sanity bool Conferir unidade, faixa de preço e variação temporal quando houver regra. Default: False
force_refresh bool Ignorar cache e buscar dados frescos
offline bool Usar apenas cache/histórico local
return_meta bool Retorna tupla (df, MetaInfo) com proveniência

Retorno:

DataFrame com colunas: - data: Data do indicador - produto: Nome do produto - praca: Praça de cotação - valor: Valor em R$ por unidade da coluna unidade; no algodão, em centavos de R$ por libra-peso (cBRL/lb) - unidade: Unidade (ex: 'BRL/sc60kg') - fonte: Fonte dos dados ('cepea' ou 'noticias_agricolas') - metodologia: Metodologia do indicador - anomalies: Texto JSON com a lista de anomalias/marcadores (ex: ["out_of_range: valor"]); None quando vazio. Use json.loads() para recuperar a lista. O modelo Indicador retornado por ultimo() mantém list[str]. Dois marcadores de proveniência saem sem validate_sanity: media_semanal (etanol do Notícias Agrícolas, que publica a média da semana) e valor_mantido (soja Paranaguá antes de 04/05/2015, pregão que repete o valor do anterior; veja a fonte) - valor_usd: Preço em US$ publicado na mesma linha pelo CEPEA; NaN quando a fonte não divulga (fallback Notícias Agrícolas, histórico em cache anterior à migração 10) - peso_medio_kg: Peso médio do animal na tabela auxiliar da página (bezerro MS); NaN para os demais produtos

As colunas e os tipos são os do contrato preco_diario, e meta.schema_version traz a versão dele. A chave é data, produto e praca: sem praca=, a função devolve todas as praças publicadas (no trigo, Paraná e Rio Grande do Sul na mesma data). O contrato tem a chave data e produto do dataset preco_diario, que reduz a uma praça por data; por isso validate_dataset(df, "preco_diario") reprova a saída com mais de uma praça por data.

Exemplo:

from agrobr import cepea

# Básico
df = await cepea.indicador('soja')

# Com período
df = await cepea.indicador(
    'soja',
    inicio='2024-01-01',
    fim='2024-06-30'
)

# Filtrar pela praça retornada por pracas(); o DataFrame preserva "Paranaguá/PR"
df = await cepea.indicador('soja', praca='paranagua')

# Forçar atualização
df = await cepea.indicador('soja', force_refresh=True)

# Modo offline (sem network)
df = await cepea.indicador('soja', offline=True)

ultimo

Obtém o indicador mais recente disponível.

Para leite, considera a defasagem mensal e retorna o mês de referência mais recente, não a data de publicação. Use praca para selecionar o estado.

async def ultimo(
    produto: str,
    praca: str | None = None,
    offline: bool = False,
) -> Indicador

Parâmetros:

Parâmetro Tipo Descrição
produto str Produto desejado
praca str \| None Praça de cotação. Aceita o slug de pracas() ou o rótulo exibido pela fonte; None não filtra, exceto no leite, em que None devolve o BRASIL
offline bool Usar apenas cache local

Retorno:

Objeto Indicador com: - data: Data do indicador - valor: Valor em Decimal - unidade: Unidade (ex: 'BRL/sc60kg') - produto: Nome do produto - fonte: Fonte dos dados

Sem rede e sem indicador no cache recente, levanta SourceUnavailableError, com attempted_sources (até a 1.1.0, ParseError). Com offline=True e sem indicador no cache, o mesmo erro, com o motivo "offline sem dado no cache". Se a busca falhar e houver indicador no cache, ultimo() devolve o do cache e emite StaleDataWarning; com offline=True, não avisa.

Exemplo:

from agrobr import cepea

ultimo = await cepea.ultimo('soja')
print(f"Soja em {ultimo.data}: R$ {ultimo.valor}/sc")

produtos

Lista produtos disponíveis.

async def produtos() -> list[str]

Retorno:

Lista de strings com nomes dos produtos.

Exemplo:

from agrobr import cepea

prods = await cepea.produtos()
# ['soja', 'soja_parana', 'milho', 'bezerro', 'cafe', 'cafe_arabica', 'cafe_robusta',
#  'boi', 'boi_gordo', 'trigo', 'algodao', 'arroz', 'acucar', 'acucar_refinado',
#  'frango_congelado', 'frango_resfriado', 'suino', 'etanol_hidratado',
#  'etanol_anidro', 'leite', 'laranja_industria', 'laranja_in_natura']
# 'bezerro' = animal de 8–12 meses, Mato Grosso do Sul, BRL/cabeca; expõe valor_usd e peso_medio_kg
# 'cafe'/'cafe_arabica' = Arábica (SP); 'cafe_robusta' = Robusta/Conilon (ES)
# Aliases: boi_gordo → boi, cafe_arabica → cafe

pracas

Lista praças disponíveis para um produto.

async def pracas(produto: str) -> list[str]

Parâmetros:

Parâmetro Tipo Descrição
produto str Produto

Retorno:

Lista de praças mapeadas pelo parser, como slugs normalizados aceitos por indicador() e ultimo(). O DataFrame e o modelo Indicador preservam o rótulo exibido pela fonte. A lista é vazia para produto válido sem praça mapeada; produto desconhecido levanta InvalidParameterError.

pracas_soja = await cepea.pracas('soja')
# ['paranagua'] — corresponde ao rótulo "Paranaguá/PR" nos dados

pracas_trigo = await cepea.pracas('trigo')
# ['parana', 'rio_grande_do_sul'] — a página publica uma tabela por praça, e o
# indicador() traz as duas; datasets.preco_diario usa o Paraná

Modelos

Indicador

class Indicador(BaseModel):
    fonte: Fonte
    produto: str = Field(..., min_length=2)
    praca: str | None = None
    data: date
    valor: Decimal = Field(..., gt=0)
    unidade: str
    metodologia: str | None = None
    revisao: int = Field(default=0, ge=0)
    meta: dict[str, Any] = Field(default_factory=dict)
    parsed_at: datetime = Field(default_factory=utcnow)
    parser_version: int = Field(default=1)
    anomalies: list[str] = Field(default_factory=list)

No Indicador coletado do CEPEA, o meta traz as variações como texto publicado: variacao é a do dia ("Var./Dia"), variacao_mes a do mês ("Var./Mês") e variacao_semana a da semana ("Var./semana", nos indicadores semanais do etanol). As variações vêm só no Indicador recém-coletado da fonte. A leitura do cache, morna ou offline, traz valor, unidade, anomalies e, no meta, só valor_usd e peso_medio_kg.

Versão Síncrona

from agrobr.sync import cepea

# Mesmas funções, sem async/await
df = cepea.indicador('soja')
ultimo = cepea.ultimo('milho')
produtos = cepea.produtos()

Comportamento de Cache

  1. Cache fresh: Retorna imediatamente do cache. A última coleta do produto vale até a próxima virada das 18h BRT em dia útil (horário de atualização do CEPEA; no mesmo dia, se a coleta foi antes das 18h; sábado e domingo não contam)
  2. Cache stale: Busca de novo; se a fonte falhar, devolve o cache com StaleDataWarning e source="cache_fallback"
  3. Sem cache: Busca da fonte e salva no cache

Com return_meta=True, o MetaInfo de uma resposta do cache traz em fetched_at e fetch_timestamp a coleta real (a mais recente entre as linhas devolvidas), não o instante da chamada, e cache_expires_at é a virada das 18h BRT seguinte a essa coleta. ultimo() segue a mesma virada. Com fim anterior à janela recente de 25 dias corridos (período fechado, que não consulta a página), cache_expires_at sai nulo: a validade não se aplica.

O histórico é acumulado progressivamente no DuckDB local, permitindo consultas a períodos antigos sem novas requisições.

Fallback

Quando o CEPEA está indisponível (Cloudflare), o agrobr automaticamente usa o Notícias Agrícolas como fonte alternativa, que republica os mesmos indicadores CEPEA/ESALQ.

Na primeira chamada de indicador() ou ultimo(), o módulo emite um UserWarning: dados CEPEA sob CC BY-NC 4.0 exigem atribuição, e uso comercial depende de autorização expressa do CEPEA. O fallback Notícias Agrícolas emite seu aviso de zona_cinza; a licença nc da origem permanece. Consulte Licenças.

Leite mensal usa somente a coleta CEPEA e seu cache: o fallback Notícias Agrícolas está desabilitado para esse produto. Seu parser autônomo expõe a data de fechamento, enquanto CEPEA usa o mês de referência. Linhas NA de leite já armazenadas ficam preservadas em quarentena na migração 9. O histórico do leite vem da série com 2 casas; a página, com 4, prevalece quando os 2 existem.

A atualização do cache preserva os originais afetados em indicadores_quarentena; falhas da migração levantam CacheMigrationError sem concluir a retirada das linhas. Consulte auditoria e recuperação.

Com return_meta=True, selected_source="cache" identifica leitura local, attempted_sources distingue cache normal de uso após falha, e data_sources informa as fontes das linhas retornadas. Cache quente/offline do Notícias Agrícolas não é apresentado como coleta CEPEA. Numa resposta do cache, parser_version é a versão do parser gravada nas linhas devolvidas (a maior, se houver mais de uma); quando as linhas trazem outra versão além da informada, source_details["parser_versions"] lista as versões por fonte, por exemplo {"cepea": [2], "noticias_agricolas": [3]}. A API direta emite StaleDataWarning ao usar cache após falha; datasets.preco_diario emite também SourceFallbackWarning, que pode ser convertido em erro.

Para a mesma data, produto e praça normalizada, a observação CEPEA tem precedência sobre Notícias Agrícolas, inclusive no cache quente e offline. Uma nova coleta da mesma fonte substitui sua observação anterior. O DuckDB preserva as observações dos dois provedores; a seleção ocorre na consulta. indicador() mantém todas as praças distintas, e data_sources descreve somente as linhas retornadas. force_refresh=True continua ignorando a leitura inicial do cache e retornando a coleta solicitada.

Normalização e avisos do parser

Os produtos aceitam caixa, espaços externos e aliases com acento, como " CAFÉ ". O nome é normalizado antes da consulta ao cache ou à fonte, preservando os códigos já aceitos. Produto fora do catálogo levanta InvalidParameterError.

Quando o parser selecionado reconhece o layout com confiança abaixo do limiar recomendado, indicador() emite UserWarning e registra a mensagem em meta.validation_warnings em cada aquisição. O aviso identifica a versão e a confiança observada; uma leitura só do cache não recebe uma confiança inferida. Os valores e unidades publicados permanecem os mesmos.