Mercado, Preços e Alertas¶
Endpoints para consulta de cotações do boi gordo (Boi Gordo Futuro B3 — BGI), candles OHLC, histórico de preços e gerenciamento de alertas de preço.
Autenticação Obrigatória
Todos os endpoints desta seção requerem header Authorization: Bearer {token}.
Provider de Market Data¶
A API usa uma abstração IMarketDataProvider que pode ser trocada via configuração MarketData:Provider:
| Provider | Status | Símbolo principal | Observação |
|---|---|---|---|
tradingview | Ativo | BGI1! (Boi Gordo Futuro continuous, BMFBOVESPA) | Usa sidecar Node.js tepconfina-tv-scraper (porta 3001 na task ECS). Preço da arroba real (~R$ 360). |
brapi | Disponível | BBOI11 (ETF Boi Gordo) | Cota do ETF, não é preço da arroba (~R$ 11). Usado quando o sidecar TV não responde. |
stonex | Stub | — | Implementação preparada para integração paga futura. |
mock | Dev | — | Dados sintéticos para testes locais. |
A migração entre providers é transparente para o frontend e o schema do banco — só muda a configuração e o registro de DI.
Resumo dos Endpoints¶
| Método | Rota | Roles | Descrição |
|---|---|---|---|
GET | /api/market/contracts | Todos | Lista contratos disponíveis no provider ativo |
GET | /api/market/quote | Todos | Cotação atual de um contrato |
GET | /api/market/quotes/history | Todos | Histórico de cotações |
GET | /api/market/candles | Todos | Candles OHLC para gráfico |
GET | /api/market/provider/health | Todos | Status do provider ativo |
GET | /api/precos-mercado/resumo | Todos | Resumo legacy (alimenta dashboard) |
GET | /api/precos-mercado/historico | Todos | Histórico legacy |
POST | /api/precos-mercado | Admin, Gerente | Criar registro manual de preço |
GET | /api/alertas-preco | Todos | Listar alertas |
POST | /api/alertas-preco | Todos | Criar alerta |
PUT | /api/alertas-preco/{id} | Todos | Atualizar alerta |
DELETE | /api/alertas-preco/{id} | Todos | Remover alerta |
Market Data (novo — pipeline TradingView)¶
GET /api/market/contracts¶
Lista os contratos disponíveis no provider ativo.
Resposta 200:
[
{
"id": "f7a8b9c0-1234-5678-9abc-def012345678",
"symbol": "BOI",
"contractCode": "BGI1!",
"description": "Boi Gordo Futuro — Continuous Front Month (B3)",
"expirationDate": null,
"isActive": true
},
{
"id": "...",
"symbol": "BOI",
"contractCode": "BGIK26",
"description": "Boi Gordo Maio 2026",
"expirationDate": "2026-05-31T00:00:00Z",
"isActive": true
}
]
GET /api/market/quote¶
Cotação atual de um contrato.
Query Parameters:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
symbol | string | Sim | Ex: BOI |
contractCode | string | Não | Ex: BGI1!. Se omitido, usa o símbolo principal do provider. |
Exemplo:
Resposta 200:
{
"symbol": "BOI",
"contractCode": "BGI1!",
"price": 360.00,
"openPrice": 359.90,
"highPrice": 360.00,
"lowPrice": 359.90,
"variationPercent": 0.0,
"volume": 11,
"source": "tradingview",
"quoteTimestamp": "2026-04-19T14:01:20Z"
}
| Código | Descrição |
|---|---|
404 | Contrato não encontrado |
502 | Provider indisponível (sidecar TV offline, BRAPI 5xx) |
GET /api/market/candles¶
Retorna candles OHLC para construção de gráfico.
Query Parameters:
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
symbol | string | — | Ex: BOI |
contractCode | string | — | Ex: BGI1! |
timeframe | string | 1d | 1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w, 1M |
limit | int | 90 | Máximo 500 |
Exemplo:
Resposta 200:
[
{
"symbol": "BOI",
"contractCode": "BGI1!",
"timeframe": "1d",
"open": 362.50,
"high": 362.60,
"low": 358.50,
"close": 360.00,
"volume": 1144,
"source": "tradingview",
"candleTime": "2026-04-16T20:05:00Z"
}
]
GET /api/market/quotes/history¶
Histórico de cotações (último N registros).
Query Parameters:
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
symbol | string | — | Ex: BOI |
contractCode | string | — | Ex: BGI1! |
limit | int | 100 | Quantidade de registros |
Resposta 200: Array de MarketQuote (mesma estrutura de /quote).
GET /api/market/provider/health¶
Status do provider ativo. Útil para alarmes CloudWatch.
Resposta 200:
Preços de Mercado (legacy — alimenta dashboard)¶
Os endpoints abaixo continuam servindo o dashboard com dados agregados (preço atual, médias móveis 7d/30d). Internamente, o MarketIngestionHostedService grava o primeiro contrato configurado em ActiveContracts na tabela PrecosMercado (1 registro por dia/fonte) para alimentá-los.
GET /api/precos-mercado/resumo¶
Query Parameters:
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
fonte | string | TRADINGVIEW | TRADINGVIEW, BRAPI, CEPEA (legacy), MANUAL |
Resposta 200:
{
"ultimoPreco": {
"id": "...",
"data": "2026-04-19",
"precoArroba": 360.00,
"variacao": 0.50,
"variacaoPercentual": 0.14
},
"mediaMovel7d": 361.20,
"mediaMovel30d": 358.45,
"historico": [
{ "id": "...", "data": "2026-04-19", "precoArroba": 360.00, "variacao": 0.50, "variacaoPercentual": 0.14 }
]
}
GET /api/precos-mercado/historico¶
Histórico para gráficos legacy do dashboard.
Query Parameters:
| Parâmetro | Tipo | Padrão |
|---|---|---|
fonte | string | TRADINGVIEW |
dias | int | 90 |
POST /api/precos-mercado¶
Permissão
Requer role Admin ou Gerente.
Cria registro manual (ex: anotação de preço regional). Salvo com Fonte=MANUAL.
Request Body:
| Código | Descrição |
|---|---|
400 | Duplicado para data/fonte |
403 | Sem permissão |
Alertas de Preço¶
GET /api/alertas-preco¶
Lista os alertas do usuário autenticado.
Resposta 200:
[
{
"id": "b8c9d0e1-f2a3-4567-b890-123456789012",
"tipo": "PrecoAcima",
"valorAlvo": 365.00,
"fonte": "TRADINGVIEW",
"ativo": true,
"criadoEm": "2026-04-01T10:00:00Z"
}
]
POST /api/alertas-preco¶
Resposta 201: alerta criado.
PUT /api/alertas-preco/{id}¶
DELETE /api/alertas-preco/{id}¶
Remove o alerta. Resposta 204.
Pipeline de Ingestão¶
graph LR
TV[TradingView WebSocket] -->|@mathieuc/tradingview| SIDECAR[tv-scraper Node :3001]
SIDECAR -->|HTTP /candles /quote| API[.NET API]
API --> PROVIDER[TradingViewMarketDataProvider]
PROVIDER --> INGEST[MarketIngestionHostedService cada 5 min]
INGEST --> DB[(MarketCandles + MarketQuotes + PrecosMercado)]
DB --> CTRL[MarketController + PrecosMercadoController]
CTRL --> WEB[CandleChart.tsx no frontend] - Intervalo de ingestão:
MarketData:SyncIntervalSeconds(default 300s). - Contratos puxados:
MarketData:ActiveContracts(default["BGI1!"]). - Falha silenciosa por contrato: se um contrato falhar, os outros continuam.
- Deduplicação:
SaveCandlesAsynceSaveQuoteAsyncchecam por chave única (Symbol+ContractCode+Timeframe+CandleTime).
Quando trocar para Cedro Technologies¶
Plano de migração futura quando houver receita (~R$ 440/mês):
- Criar
CedroMarketDataProvider.csimplementandoIMarketDataProvider. - Registrar em
DependencyInjection.cscomMarketData:Provider=cedro. - Setar env var na task ECS, force-new-deployment.
- Desligar
tv-scraper(essential=false na task def, basta remover do containerDefinitions).
Nada muda no schema, nas rotas ou no frontend.