Documentação
Endpoints da API
Visão Geral
Esta documentação descreve todos os endpoints disponíveis no APIController
da aplicação TechChallenge. A API fornece funcionalidades para obter e processar dados de pregão da B3 (Bolsa de Valores do Brasil). Tem 2 endpoints acessíveis pelo método GET para obter os dados do pregão (GetPregaoB3Data e GetPregaoB3ScrapedData) e um endpoint para executar o pipeline completo de processamento de dados da B3, que inclui: obtenção de dados (scraping e caso não consiga, via API
da B3), conversão para modelo interno de dados, geração de arquivo Parquet e upload para AWS S3 com partição diária. Os passos posteriores não são gerenciados pela API e sim por uma funçao AWS Lambda que é disparada assim que os dados brutos chegam no bucket S3. Essa função Lambda chama um job ETL no AWS Glue, executa várias transformações e salvam os dados em formato parquet numa pasta chamada refined
, particionados por data e pela abreviação da ação do pregão. Esses dados são catalogados no Glue Catalog e entra em um banco de dados disponível no Athena.
GetPregaoB3DataAsync
Busca dados de pregão da B3 através da API da B3, recuperando informações completas de negociação, volumes e preços de todos os ativos do índice IBOV. Essa API da B3 foi descoberta após análise das requisições feitas pela página da própria B3 que monta um json como a seguir para solicitar as informações e faz um encode dessas informações para Base64:
{
"language": "pt-br",
"pageNumber": 1,
"pageSize": 20,
"index": "IBOV",
"segment": "1"
}
Esse json ao virar uma string em Base64, é concatenado ao final da url https://sistemaswebb3-listados.b3.com.br/indexProxy/indexCall/GetPortfolioDay/ e usado em uma requisição GET
. Foi criado um método que tenta solicitar uma quantidade extremamente grande de dados por vez (o limite de INT em algumas linguagens), para que venha tudo em uma única página, mas se existirem mais páginas, ocorre um loop até o fim, adicionando os resultados em uma lista.
Detalhes Técnicos
- Método HTTP:
GET
- Rota:
/api/GetPregaoB3Data
- Content-Type:
application/json
Parâmetros de Entrada
Nenhum parâmetro é necessário. O endpoint utiliza configurações padrão:
- Índice: IBOV
- Segmento: 1
- Idioma: pt-br
- Tamanho da página: 99999 registros
Parâmetros de Saída
Sucesso (200 OK):
{
"page": {
"pageNumber": 1,
"pageSize": 99999,
"totalRecords": 1234,
"totalPages": 1
},
"header": {
"date": "2024-01-15",
"text": "Dados do Pregão",
"part": "100.00",
"partAcum": "100.00",
"textReductor": "Redutor",
"reductor": "1.0000",
"theoricalQty": "123456789"
},
"results": [
{
"segment": "1",
"cod": "PETR4",
"asset": "PETROBRAS PN",
"type": "AÇÃO",
"part": "15.23",
"partAcum": "15.23",
"theoricalQty": "12345678"
}
]
}
Erro (500 Internal Server Error):
{
"message": "Erro interno do servidor"
}
Funcionamento Interno
- Inicialização do Serviço: Cria uma instância do
PregaoB3FetchService
comHttpClient
- Construção da Requisição: Utiliza
BuildPregaoB3GetRequestModel(1)
para criar o modelo de requisição - Busca de Dados: Chama
GetAllPagesAsync()
que:- Faz requisição para a API oficial da B3:
https://sistemaswebb3-listados.b3.com.br/indexProxy/indexCall/GetPortfolioDay/
- Codifica os parâmetros em Base64URL
- Busca todas as páginas automaticamente (paginação)
- Combina todos os resultados em uma única resposta
- Faz requisição para a API oficial da B3:
- Serialização: Converte o resultado para JSON
- Retorno: Retorna os dados completos do pregão
Serviços Utilizados
- PregaoB3FetchService: Responsável pela comunicação com a API oficial da B3
- Base64UrlHelper: Para codificação dos parâmetros da requisição
GetPregaoB3ScrapedDataAsync
Executa web scraping do site oficial da B3 para obter dados de pregão que podem não estar disponíveis através da API oficial. Utiliza Playwright para automatizar a navegação e extração de dados.
Detalhes Técnicos
- Método HTTP:
GET
- Rota:
/api/GetPregaoB3ScrapedData
- Content-Type:
application/json
Parâmetros de Entrada
Nenhum parâmetro é necessário.
Parâmetros de Saída
Sucesso (200 OK):
{
"success": true,
"message": "Sucesso",
"data": [
["PETR4", "15.23", "1.2%", "12345678", "15.45"],
["VALE3", "67.89", "0.8%", "9876543", "68.12"]
],
"totalRecords": 1234,
"date": "15/01/2024"
}
Erro (400 Bad Request):
{
"message": "Erro durante o processo de scraping"
}
Funcionamento Interno
- Inicialização do Playwright: Cria uma instância do navegador Chromium em modo headless
- Navegação: Acessa a URL:
https://sistemaswebb3-listados.b3.com.br/indexPage/day/IBOV?language=pt-br
- Aguardar Carregamento: Espera a tabela de dados carregar completamente
- Extração de Metadados:
- Obtém o número total de páginas
- Extrai a data do pregão
- Processamento por Página:
- Para cada página:
- Extrai todas as linhas da tabela
- Captura valores de todas as colunas
- Navega para a próxima página até completar
- Para cada página:
- Limpeza de Dados: Remove espaços em branco e formata os dados
- Retorno: Retorna os dados estruturados com metadados
Serviços Utilizados
- PregaoB3ScrapeService: Serviço estático que executa o web scraping
- Playwright: Framework para automação de navegador
Seletores CSS Utilizados
- Tabela:
table.table.table-responsive-sm.table-responsive-md
- Linhas:
tbody > tr
- Colunas:
td
- Paginação:
ul.ngx-pagination
- Data:
form.ng-untouched.ng-pristine.ng-valid > h2
ExecutePipelineAsync
Executa o pipeline completo de processamento de dados da B3, que inclui: obtenção de dados (primeiro tenta via scraping, mas em caso de erro, utiliza a API), conversão para modelo interno, geração de arquivo Parquet e upload para AWS S3 com partição diária.
Detalhes Técnicos
- Método HTTP:
POST
- Rota:
/api/ExecutePipeline
- Content-Type:
application/json
Parâmetros de Entrada
Query Parameter:
- date (opcional): Data específica para processamento no formato
yyyy-MM-dd
- Exemplo:
?date=2024-01-15
- Se não fornecido, utiliza a data atual
- Exemplo:
Dependency Injection:
- B3PipelineService: Serviço injetado via DI container
Parâmetros de Saída
Sucesso (200 OK):
{
"success": true,
"message": "Pipeline executado com sucesso via Scraping",
"recordsProcessed": 1234,
"dataDate": "2024-01-15",
"s3Key": "raw/dt=2024-01-15/b3_20240115.parquet",
"processingTimeMs": 15420,
"dataSource": "Scraping"
}
Erro (400 Bad Request):
{
"success": false,
"message": "Nenhum dado obtido nem via scraping nem via API da B3",
"recordsProcessed": 0,
"dataDate": "2024-01-15",
"processingTimeMs": 15420
}
Funcionamento Interno
Obtenção de Dados (Estratégia de Fallback)
- Primeira tentativa: Web scraping via
PregaoB3ScrapeService.ScrapeB3DataAsync()
- Fallback: Se scraping falhar, utiliza API oficial via
PregaoB3FetchService
- Primeira tentativa: Web scraping via
Conversão de Dados
- Dados do Scraping: Converte tabela HTML para modelo
Negociacao
- Dados da API: Converte resposta JSON para modelo
Negociacao
- Mapeamento:
DataPregao
: Data fornecida ou atualTicker
: Código do ativoPreco
: Preço de fechamentoQuantidade
: Volume negociado
- Dados do Scraping: Converte tabela HTML para modelo
Geração de Arquivo Parquet
- Serviço:
ParquetWriterService
- Localização: Pasta temporária configurada
- Nome do arquivo:
b3_YYYYMMDD.parquet
- Formato: Apache Parquet otimizado para big data
- Serviço:
Upload para AWS S3
- Serviço:
S3UploaderService
- Bucket: Configurado via
Aws:Bucket
- Estrutura de partição:
raw/dt=YYYY-MM-DD/
- Chave S3:
raw/dt=2024-01-15/b3_20240115.parquet
- Serviço:
Limpeza
- Remove arquivo temporário local após upload bem-sucedido
Serviços Utilizados
- B3PipelineService: Orquestrador principal do pipeline
- PregaoB3ScrapeService: Web scraping da B3
- PregaoB3FetchService: API oficial da B3
- ParquetWriterService: Geração de arquivos Parquet
- S3UploaderService: Upload para AWS S3
Modelo de Dados
- Negociacao
public readonly record struct Negociacao(
DateOnly DataPregao, // Data do pregão
string Ticker, // Código do ativo (ex: PETR4)
decimal Preco, // Preço de fechamento
long Quantidade // Volume negociado
);
- PipelineResultModel
public class PipelineResultModel
{
public bool Success { get; set; } // Status da execução
public string Message { get; set; } // Mensagem descritiva
public int RecordsProcessed { get; set; } // Número de registros processados
public DateOnly? DataDate { get; set; } // Data dos dados
public string? S3Key { get; set; } // Chave do arquivo no S3
public long ProcessingTimeMs { get; set; } // Tempo de processamento
public string? DataSource { get; set; } // Fonte dos dados (Scraping/API)
}