Cartilha de boas práticas para APIs públicas de exchanges de ativos digitais
Este documento propõe um modelo de padronização dos dados públicos fornecidos pelas Interfaces de Programação de Aplicativos das plataformas brasileiras de criptoativos.
Por Elói Pattaro*
As APIs públicas
Interfaces de Programação de Aplicativos (APIs, na sigla em inglês) públicas são pontos de acesso de dados que não requerem autenticação.
As informações fornecidas pelas APIs de cada exchange variam, mas a maioria apresenta informações em comum, como por exemplo:
- Ticker (últimas 24h de negociação)
- High (maior preço)
- Low (menor preço)
- Vol (volume total)
- Last (último preço)
- Livro de ofertas (preço e volume, no momento presente)
- Bids (ordens de compra)
- Asks (ordens de venda)
- Histórico de negócios realizados*
- Id (identificador único)
- Date (momento de execução)
- Price (preço unitário)
- Amount (quantia executada)
- Side (quem foi o taker)
*Algumas exchanges fornecem apenas o histórico parcial, ou seja, as “N” trades mais recentes.
Identificação de deficiências
Basicamente, existem dois problemas quando nos referimos às APIs públicas das exchanges de ativos digitais:
1 ) Informações incompletas:
- O histórico completo de ordens de compra e venda não é fornecido;
- As ordens de compra e venda não possuem “user_id” associado a elas;
- As ordens de compra e venda não possuem “order_id” associado a elas;
- As negociações realizadas (trades) não são associadas às ordens.
2 ) Ausência de padrão:
- Apesar de alguns dados disponibilizados serem comuns entre as exchanges, não é adotado um padrão de aquisição e/ou fornecimento desta informação. Cada exchange o faz de maneira arbitrária e utiliza formato próprio;
- Consequentemente, o objetivo maior das APIs públicas, que é o de prover transparência ao usuário e ao mercado, fica comprometido;
- Devido às informações incompletas, não é possível auditar os dados apresentados pelas exchanges;
- A falta de padronização por sua vez dificulta a validação e manuseio das informações — sintaxes diferentes, tanto de requisição como no fornecimento dos dados, fazem a experiência do usuário ser desnecessariamente penosa.
Modelo de solução proposta
Visando melhorar a experiência do usuário e também garantir maior transparência ao mercado, propomos que as exchanges:
- Forneçam o histórico completo de ordens de compra e venda, e:
- Associem order_id a cada ordem;
- Associem user_id a cada ordem (sugerimos usar um hash único para o user_id);
- Associem status de “finalizada/cancelada/em aberto” a cada ordem;
- Disponibilizem timestamp inicial e final (no caso de finalizada/cancelada).
Além disso, também propomos que:
- Associem as trades executadas às ordens por meio de order_id;
- Forneçam listagem de pares negociados;
- Sigam padrão amigável para as requisições das APIs determinado a seguir neste documento;
- Forneçam datas sempre em unix timestamp milliseconds;
A partir da implementação dessas simples mudanças, torna-se possível a realização de auditoria descentralizada das exchanges pela própria comunidade, aumentando assim a credibilidade de cada exchange e do mercado como um todo.
Padrão BRIX-PAPI (v1)
Sugerimos usar essa seção do documento como linhas gerais para um ponto de partida, de maneira a se iniciar uma discussão bem informada sobre o assunto com os principais interessados e, assim, se definir uma solução que atenda a todos.
Este padrão de documentação foi inspirado nos modelos utilizados pelas exchanges bittrex & bitcambio:
- A requisição da API pública deve ser do tipo RESTful API;
- Deve existir um base url endpoint, referido posteriormente aqui apenas por url;
- O primeiro termo posterior a url deve ser sempre a versão da API. No caso, contemplemos v1.
As chamadas estão listadas a seguir:
url/v1/assets
Volta a listagem dos ativos negociados e meta informações pertinentes.
[{ “market_currency” : “LTC”,
“base_currency” : “BTC”,
“market_currency_name” : “Litecoin”,
“base_currency_name” : “Bitcoin”,
“min_trade_size” : 0.01000000,
“pair” : “BTC-LTC”,
“is_active” : True,
“created” : 1262911460002
}, {
“market_currency” : “DOGE”,
“base_currency” : “BTC”,
“market_currency_name” : “Dogecoin”,
“base_currency_name” : “Bitcoin”,
“min_trade_size” : 100.00000000,
“pair” : “BTC-DOGE”,
“is_active” : False,
“created” : 1399912265501
},{…},…
]
url/v1/ticker?pair=<PAIR>
Volta dados atuais e compilados referente às últimas 24h do par referenciado.
PAIR é necessário.
{
“pair”: “BTC-BRL”,
“last”: 2280.0,
“high”: 2306.0,
“low”: 2205.0,
“vol”: 113.17267938,
“buy”: 2263.0,
“sell”: 2279.77,
“timestamp”: 1467990302001
}
Quando “buy” e “sell” são os melhores valores do livro de ofertas no momento da requisição.
Timestamp é referente ao momento da última atualização.
url/v1/orderbook?pair=<PAIR>?length=<SIZE>
Volta as primeiras SIZE entradas dos livros de ofertas de bid & ask do par referenciado.
SIZE deve ser um inteiro não limitado.
PAIR é necessário.
SIZE é opcional, valor default de 100.
{
“pair”: “BTC-BRL”,
“bids”: [
[2257.89, 0.20752212, 90852987],
[2257.88, 1.01201126, 90800395],
[2249.98, 0.05052466, 90806289],
….
],
“asks”: [
[2272.14, 2.3648572, 90803493],
[2279.63, 0.08722052, 90840584],
[2279.75, 0.04118941, 90823262],
…
]
}
url/v1/trades?since=<UNIX_TIMESTAMP>&limit=<NUMBER>&pair=<PAIR>
PAIR é necessário.
UNIX_TIMESTAMP é opcional, se não utilizado volta as trades desde a inicial.
LIMIT é opcional, capado em mil, se não especificado seu valor default é 100.
[
{
“pair”: “BTC-BRL”,
“tid”: 404681,
“buyer_order_id”: 1732,
“seller_order_id”: 1717,
“seller_user_id”: “3A1208DE7E66F1706C65C2715C6C3….”,
“buyer_user_id”: “3A1208DE7E66F1706C65C2715C6C3….”,
“timestamp”: 1467990492191,
“price”: 2280.89,
“amount”: 0.53487892,
“side”: “buy”
},
{
“pair”: “BTC-BRL”,
“tid”: 404682,
“buyer_order_id”: 1752,
“seller_order_id”: 1721,
“seller_user_id”: “3A1208DE7E66F1706C65C2715C6C3….”,
“buyer_user_id”: “3A1208DE7E66F1706C65C2715C6C3….”,
“timestamp”: 1467990492493,
“price”: 2261.01,
“amount”: 0.0373,
“side”: “sell”
}
]
url/v1/orders?since=<UNIX_TIMESTAMP>&limit=<NUMBER>&pair=<PAIR>
PAIR é necessário.
UNIX_TIMESTAMP é opcional, se não utilizado volta as ordens desde a inicial.
LIMIT é opcional, capado em mil, se não especificado seu valor default é 100.
[
{
“pair”: “BTC-BRL”,
“user_id”: “3A1208DE7E66F1706C65C2715C6C3….”,
“order_id”: 4857,
“initial_timestamp”: 1467990492191,
“final_timestamp”: 1467990530032,
“price”: 2280.00,
“amount”: 0.5,
“type”: “buy”,
“status”: “open”,
},
{
“pair”: “BTC-BRL”,
“user_id”: “3A1208DE7E66F1706C65C2715C6C3….”,
“order_id”: 4863,
“inital_timestamp”: 1467990492493,
“final_timestamp”: 1467990530032,
“price”: 2262.5,
“amount”: 0.3,
“type”: “sell”
“status”: “cancelled”,
},
…
]
É importante notar que os preços e quantias listados nas ordens são os valores pedidos nas próprias ordens e não necessariamente os executados posteriormente nas trades.
A auditoria das ordens para trades executadas não é trivial, mas é factível.
Em caso de exchanges adotarem esse padrão, a equipe do Bitcoin Real Index (BRIX) irá desenvolver, dentro de sua competência, scripts open para efetuar tal auditoria.
* Eloi Pattaro é bacharel em física pela Universidade de São Paulo. Estuda e está envolvido com crypto desde 2016. Atuou no mercado com ciência de dados em diversas startups, entre elas Nubank, Mira Educação e Foxbit.
Hoje atua como consultor e gestor de projetos em ciência de dados pela cognitivo.ai e como Senior Data Scientist na Nexa Digital.