A ProfitDLL é uma biblioteca nativa do Windows que dá à sua aplicação acesso direto à infraestrutura de Market Data e Roteamento da Nelogica, a mesma usada pelo Profit. Com ela, você pode receber cotações tick a tick, livros de ofertas, dados históricos e enviar ordens diretamente aos mercados B3 (BM&F e Bovespa), tudo em uma única biblioteca.
Este artigo é o ponto de partida para usar a ProfitDLL. Cobre o ambiente, o carregamento da biblioteca, os dois modos de inicialização, como verificar o estado da conexão e o modelo de callbacks. Os demais artigos sobre funcionalidades específicas (livro de profundidade, trades históricos, roteamento de ordens) assumem que você já passou por estes primeiros passos.
Dois modos de uso
A ProfitDLL opera em dois modos, escolhidos no momento da inicialização:
| Modo | Função de inicialização | O que disponibiliza |
| Market Data | DLLInitializeMarketLogin | Cotações em tempo real, livro de ofertas e profundidade, histórico de trades, ajustes |
| Roteamento + Market Data | DLLInitializeLogin | Tudo do Market Data mais envio, modificação, cancelamento e zeragem de ordens; consulta de contas e posições |
A diferença entre os dois é importante porque envolve permissões: para usar roteamento sua conta precisa estar habilitada para trading na corretora. Para apenas consumir Market Data, basta a licença correspondente.
Pré-requisitos do ambiente
A ProfitDLL é uma biblioteca Windows (.dll nativa, convenção de chamada stdcall). O pacote traz duas versões da biblioteca, ambas com o mesmo nome de arquivo — **ProfitDLL.dll** — separadas em pastas conforme a arquitetura:
- Win64/ProfitDLL.dll** — para aplicações 64 bits. Recomendado para a maioria dos casos.
- Win32/ProfitDLL.dll** — para aplicações 32 bits. Útil apenas se sua aplicação for forçadamente 32 bits.
A escolha tem consequências práticas:
- Em 64 bits, o processo tem acesso a toda a memória RAM disponível. Sem restrições conhecidas.
- Em 32 bits, o processo é limitado a 4 GB de memória — compartilhados entre sua aplicação e a DLL. Requisições grandes (histórico de muitos dias em ativos voláteis) podem estourar esse limite.
Atenção: Python 32 bits exige versão específica. Há um bug conhecido no ctypes do Python 32 bits (issue 41021 no bugtracker do Python) que faz callbacks com tipos maiores que 32 bits falharem com exceção. Se você precisa rodar em 32 bits com Python, use a versão 3.6.2 especificamente. Em 64 bits, qualquer versão recente funciona normalmente.
Carregando a DLL
A ProfitDLL usa a convenção de chamada stdcall. No Python, isso significa usar WinDLL, não CDLL:
from ctypes import WinDLL
# Aponte para a ProfitDLL.dll da arquitetura correta (pasta Win64 ou Win32)
profit_dll = WinDLL(r"C:\caminho\para\Win64\ProfitDLL.dll") Usar CDLL (que assume a convenção cdecl) provoca corrupção de pilha silenciosa, o processo pode travar imediatamente ou apresentar comportamento errático após alguns segundos.
Antes de chamar qualquer função, defina os tipos de retorno (restype) e argumentos (argtypes) de cada uma. O ctypes assume c_int por padrão, o que trunca retornos Int64 (como o LocalOrderID de SendOrder). Cada artigo deste guia mostra os tipos esperados para as funções que cobre.
Inicialização
DLLInitializeLogin (Market Data + Roteamento)
result = profit_dll.DLLInitializeLogin(
c_wchar_p("CHAVE_DE_ATIVACAO"), # licença fornecida pela Nelogica
c_wchar_p("USUARIO_NELOGICA"), # usuário da conta Nelogica
c_wchar_p("SENHA_LOGIN"), # senha de login (NÃO é a senha de roteamento)
state_callback, # TStateCallback — obrigatório
history_callback, # THistoryCallback — pode ser None se não usado
order_change_callback, # TOrderChangeCallback — pode ser None
account_callback, # TAccountCallback — recebe lista de contas
new_trade_callback, # TNewTradeCallback — trades em tempo real
new_daily_callback, # TNewDailyCallback — dados diários agregados
price_book_callback, # TPriceBookCallback — pode ser None
offer_book_callback, # TOfferBookCallback — pode ser None
history_trade_callback, # THistoryTradeCallback — histórico de trades
progress_callback, # TProgressCallback — progresso de requisições
tiny_book_callback, # TTinyBookCallback — topo do livro
) A função retorna 0 (NL_OK) quando o pedido de inicialização é aceito. A conexão em si é assíncrona e seu progresso é informado via TStateCallback.
DLLInitializeMarketLogin (apenas Market Data)
Equivalente, mas sem os callbacks relacionados a roteamento:
result = profit_dll.DLLInitializeMarketLogin(
c_wchar_p("CHAVE_DE_ATIVACAO"),
c_wchar_p("USUARIO_NELOGICA"),
c_wchar_p("SENHA_LOGIN"),
state_callback,
new_trade_callback,
new_daily_callback,
price_book_callback,
offer_book_callback,
history_trade_callback,
progress_callback,
tiny_book_callback,
) Atenção: A senha de login não é a senha de roteamento. A senha passada para DLLInitializeLogin é a senha de acesso à Nelogica (a mesma usada para entrar no Profit). A senha de roteamento, exigida nas funções de envio de ordens, é configurada à parte na corretora. Confundir as duas é uma das principais causas de rejeição de ordem.
Callbacks: dois momentos para registrar
O modelo de callbacks da ProfitDLL tem duas vias:
- Na inicialização — alguns callbacks são informados como parâmetros das funções de inicialização (acima). São os mais usados e os obrigatórios.
- Depois da inicialização, via funções Set*Callback — para callbacks específicos não cobertos na inicialização, ou para sobrescrever um já definido. Exemplos: SetPriceDepthCallback, SetTradeCallbackV2, SetOrderCallback, SetTradingMessageResultCallback, SetChangeCotationCallback, SetAdjustHistoryCallback.
A regra prática: o que você precisa para começar entra na inicialização; o resto, conforme você habilita funcionalidades específicas, entra com Set*Callback.
Atenção: Toda referência de callback precisa ser mantida viva. Em Python, atribua o resultado de WINFUNCTYPE(...)(i) a uma variável de escopo durável (atributo de classe ou global). Se o garbage collector liberar a função, a DLL chamará um ponteiro inválido e o processo travará sem aviso.
Verificando o estado da conexão
A conexão da ProfitDLL com a infraestrutura da Nelogica passa por quatro tipos independentes de estado. Sua aplicação só está pronta para operar quando todos os relevantes estiverem confirmados.
Os estados chegam pelo TStateCallback, que recebe dois inteiros: nConnStateType (qual conexão mudou) e nResult (o novo estado dela).
Tipos de conexão (nConnStateType)
| Valor | Constante | O que representa |
| 0 | CONNECTION_STATE_LOGIN | Conexão com o servidor de login da Nelogica |
| 1 | CONNECTION_STATE_ROTEAMENTO | Conexão com o servidor de roteamento (e com a corretora) |
| 2 | CONNECTION_STATE_MARKET_DATA | Conexão com o servidor de Market Data |
| 3 | CONNECTION_STATE_MARKET_LOGIN | Validação da ativação no servidor de Market Data |
Estados de login (nResult quando nConnStateType = 0)
| Valor | Constante | Significado |
| 0 | LOGIN_CONNECTED | Login conectado com sucesso |
| 1 | LOGIN_INVALID | Usuário inválido |
| 2 | LOGIN_INVALID_PASS | Senha inválida |
| 3 | LOGIN_BLOCKED_PASS | Senha bloqueada |
| 4 | LOGIN_EXPIRED_PASS | Senha expirada |
| 200 | LOGIN_UNKNOWN_ERR | Erro interno de login |
Estados de roteamento (nResult quando nConnStateType = 1)
| Valor | Constante | Significado |
| 0 | ROTEAMENTO_DISCONNECTED | Desconectado |
| 1 | ROTEAMENTO_CONNECTING | Conectando |
| 2 | ROTEAMENTO_CONNECTED | Conectado ao servidor de roteamento |
| 3 | ROTEAMENTO_BROKER_DISCONNECTED | Corretora desconectada |
| 4 | ROTEAMENTO_BROKER_CONNECTING | Conectando à corretora |
| 5 | ROTEAMENTO_BROKER_CONNECTED | Corretora conectada — pronto para enviar ordens |
Estados de Market Data (nResult quando nConnStateType = 2)
| Valor | Constante | Significado |
| 0 | MARKET_DISCONNECTED | Desconectado |
| 1 | MARKET_CONNECTING | Conectando |
| 2 | MARKET_WAITING | Aguardando conexão |
| 3 | MARKET_NOT_LOGGED | Conectado, mas ainda não autenticado |
| 4 | MARKET_CONNECTED | Market Data conectado |
Estados de ativação (nResult quando nConnStateType = 3)
| Valor | Constante | Significado |
| 0 | CONNECTION_ACTIVATE_VALID | Ativação válida |
| 1 | CONNECTION_ACTIVATE_INVALID | Ativação inválida |
O que esperar antes de operar
A combinação de estados que define "pronto para operar" depende do modo:
- Apenas Market Data: aguarde LOGIN_CONNECTED, MARKET_CONNECTED e CONNECTION_ACTIVATE_VALID.
- Roteamento + Market Data: tudo do acima mais ROTEAMENTO_BROKER_CONNECTED (com o broker correto).
Implementação em Python: aguardando a conexão completa
from ctypes import WINFUNCTYPE, c_int
import threading
# Constantes (subset)
CONNECTION_STATE_LOGIN = 0
CONNECTION_STATE_ROTEAMENTO = 1
CONNECTION_STATE_MARKET_DATA = 2
CONNECTION_STATE_MARKET_LOGIN = 3
LOGIN_CONNECTED = 0
ROTEAMENTO_BROKER_CONNECTED = 5
MARKET_CONNECTED = 4
CONNECTION_ACTIVATE_VALID = 0
# Eventos sinalizam quando cada conexão fica pronta
estado = {
"login": threading.Event(),
"broker": threading.Event(),
"market": threading.Event(),
"ativacao": threading.Event(),
}
@WINFUNCTYPE(None, c_int, c_int)
def state_callback(state_type, result):
if state_type == CONNECTION_STATE_LOGIN and result == LOGIN_CONNECTED:
estado["login"].set()
elif state_type == CONNECTION_STATE_ROTEAMENTO and result == ROTEAMENTO_BROKER_CONNECTED:
estado["broker"].set()
elif state_type == CONNECTION_STATE_MARKET_DATA and result == MARKET_CONNECTED:
estado["market"].set()
elif state_type == CONNECTION_STATE_MARKET_LOGIN and result == CONNECTION_ACTIVATE_VALID:
estado["ativacao"].set()
def aguardar_conexao_completa(usar_roteamento=True, timeout=30):
eventos = [estado["login"], estado["market"], estado["ativacao"]]
if usar_roteamento:
eventos.append(estado["broker"])
for ev in eventos:
if not ev.wait(timeout):
raise TimeoutError(f"Conexão não estabelecida em {timeout}s") Após chamar DLLInitializeLogin (ou DLLInitializeMarketLogin), chame aguardar_conexao_completa() e só prossiga quando ele retornar.
Importante: Reconexão é automática. A ProfitDLL gerencia internamente eventuais quedas de conexão e tenta reconectar sozinha. Sua aplicação não precisa de lógica de reconexão — apenas continuar reagindo aos eventos do TStateCallback para saber quando os serviços voltaram.
Modelo de callbacks e threading
Todos os callbacks da ProfitDLL são invocados na **ConnectorThread** — uma thread interna que também processa o pipeline de mensagens da DLL. Isso tem três consequências práticas:
- Callbacks são concorrentes com sua thread principal. Variáveis compartilhadas precisam de threading.Lock ou estruturas thread-safe (queue.Queue, collections.deque).
- Bloquear um callback bloqueia a fila inteira. Se sua função demora 200ms para processar um trade, e chegam 50 trades por segundo, a fila acumula e os dados começam a chegar com atraso.
- Não chame funções da DLL de dentro de um callback. A única exceção é TranslateTrade (no callback de trade V2), que é projetada para isso.
O padrão recomendado é o produtor-consumidor: o callback apenas enfileira o dado, e uma thread separada processa.
from queue import Queue
import threading
fila_de_trades = Queue()
# Callback enfileira — operação rápida, não bloqueia a ConnectorThread
def trade_callback(...):
fila_de_trades.put({...})
# Thread consumidora processa em paralelo
def processar_trades():
while True:
trade = fila_de_trades.get()
# ... persistir, calcular indicadores, atualizar UI, etc.
fila_de_trades.task_done()
threading.Thread(target=processar_trades, daemon=True).start()
Encerrando a DLL
Ao terminar o uso, chame DLLFinalize para liberar conexões e recursos internos:
profit_dll.DLLFinalize() Se sua aplicação registrou subscriptions (tickers, livro de profundidade, etc.), cancelá-las antes de finalizar é uma boa prática mas não estritamente necessário — DLLFinalize libera tudo.
Próximos passos
Com a DLL inicializada e a conexão estabelecida, você está pronto para usar as funcionalidades específicas:
- Livro de profundidade (price depth) — veja Como utilizar o Livro de Profundidade (Price Depth) via DLL Real Time.
- Histórico de trades — veja Como requisitar trades históricos com a ProfitDLL.
- Envio, modificação e cancelamento de ordens — veja Como rotear ordens com a ProfitDLL
Para mais informações, encaminhe um e-mail para corporativo@nelogica.com.br.
Achou útil este conteúdo?
Não esqueça de nos avaliar abaixo.
Desejamos bons trades!