A ProfitDLL oferece um conjunto de funções para roteamento completo de ordens nos mercados B3 (BM&F e Bovespa): envio, acompanhamento, modificação, cancelamento e zeragem de posição. Todas operam sobre as mesmas estruturas básicas (TConnectorAccountIdentifier, TConnectorAssetIdentifier, TConnectorOrderIdentifier) e seguem um modelo único, você monta uma struct descrevendo a operação e chama a função correspondente.
Este artigo é o guia de referência para tudo que envolve roteamento. Está organizado em seções independentes, você pode ler do início ao fim ou pular direto para o tópico desejado.
Estruturas base
- TConnectorSendOrder
- TConnectorAccountIdentifier
- TConnectorAssetIdentifier
- TConnectorOrderIdentifierEnums
- Tipos de ordem (OrderType)
- Lados (OrderSide)
- Status de ordem (OrderStatus)
- Códigos de resultado de mensagem (TradingMessageResultCode)Enviando ordens
- Montagem básica da estrutura
- Ordem limitada (Limit)
- Ordem a mercado (Market)
- Ordem stop limit (StopLimit)Acompanhando o ciclo de vida
- Callback de ordem (TConnectorOrderCallback)
- Callback de resultado de mensagem (TConnectorTradingMessageResultCallback)
- Consultando detalhes de uma ordem (GetOrderDetails)Cancelando ordens
- Cancelando uma ordem específica
- Cancelando todas as ordens de um ativo
- Cancelando todas as ordens da contaZerando posição
- Estrutura: TConnectorZeroPosition
- Tipos de posição (PositionType)
- Exemplo: zerar posição a mercado
Pré-requisitos
Para usar funções de roteamento, sua aplicação precisa estar em três condições:
-
DLL inicializada com roteamento. Use DLLInitializeLogin (não DLLInitializeMarketLogin, que sobe apenas Market Data).
-
Conexão completa. É necessário receber LOGIN_CONNECTED, ROTEAMENTO_CONNECTED, MARKET_CONNECTED e CONNECTION_ACTIVATE_VALID no TStateCallback antes do envio.
- Conta de roteamento ativa. Sua autenticação precisa ter permissão de trading, e a corretora precisa estar conectada (ROTEAMENTO_BROKER_CONNECTED).
Atenção: A senha usada nas operações não é a senha de login. O campo Password nas estruturas de roteamento espera a senha de roteamento da conta, configurada na corretora. Confundir as duas é a causa mais comum de rejeição na primeira tentativa.
Visão geral do fluxo
Toda operação de roteamento segue o mesmo padrão geral:
- Você monta uma estrutura descrevendo a operação (TConnectorSendOrder para envio, TConnectorCancelOrder para cancelamento, etc.).
- Você chama a função correspondente (SendOrder, SendCancelOrderV2, etc.).
- A DLL retorna imediatamente um valor síncrono. Em envio e zeragem (SendOrder, SendZeroPositionV2) o retorno é Int64: positivo (o LocalOrderID da ordem) em caso de sucesso, negativo em caso de erro. Em modificação e cancelamento (SendChangeOrderV2, SendCancelOrderV2, SendCancelOrdersV2, SendCancelAllOrdersV2) o retorno é Integer: **0 (NL_OK) em caso de sucesso, negativo** em caso de erro.
- O resultado assíncrono (aceitação pela corretora, controle de risco e mercado) chega depois pelos callbacks SetOrderCallback e SetTradingMessageResultCallback.
Funções e callbacks principais
| Item | Tipo | Finalidade |
| SendOrder | Função | Envia uma ordem (todos os tipos) |
| SendChangeOrderV2 | Função | Modifica uma ordem ativa (preço/quantidade) |
| SendCancelOrderV2 | Função | Cancela uma ordem específica |
| SendCancelOrdersV2 | Função | Cancela todas as ordens de um ativo |
| SendCancelAllOrdersV2 | Função | Cancela todas as ordens da conta |
| SendZeroPositionV2 | Função | Envia ordem de zeragem de posição |
| GetOrderDetails | Função | Consulta o estado atual de uma ordem |
| GetAccountCount / GetAccounts | Função | Descobre as contas de roteamento disponíveis |
| SetOrderCallback | Função | Registra callback de mudança em ordem |
| SetTradingMessageResultCallback | Função | Registra callback de resposta de mensagens de roteamento |
| TConnectorOrderCallback | Callback | Disparado quando uma ordem muda de estado |
| TConnectorTradingMessageResultCallback | Callback | Disparado com o resultado de cada mensagem enviada |
Estruturas base
TConnectorSendOrder
Descreve uma ordem a ser enviada.
from ctypes import Structure, c_ubyte, c_double, c_int64, c_wchar_p
from profitTypes import TConnectorAccountIdentifier, TConnectorAssetIdentifier
class TConnectorSendOrder(Structure):
_fields_ = [
("Version", c_ubyte),
("AccountID", TConnectorAccountIdentifier),
("AssetID", TConnectorAssetIdentifier),
("Password", c_wchar_p),
("OrderType", c_ubyte),
("OrderSide", c_ubyte),
("Price", c_double),
("StopPrice", c_double),
("Quantity", c_int64),
("MessageID", c_int64),
] | Campo | Tipo nativo | Significado |
| Version | Byte | Versão da estrutura. Recomendado: 2 |
| AccountID | TConnectorAccountIdentifier | Conta de roteamento |
| AssetID | TConnectorAssetIdentifier | Ativo a negociar |
| Password | PWideChar | Senha de roteamento (não a senha de login) |
| OrderType | Byte | 1=Market, 2=Limit, 4=StopLimit |
| OrderSide | Byte | 1=Compra, 2=Venda |
| Price | Double | Preço da ordem. Use -1 em ordens a mercado |
| StopPrice | Double | Preço de disparo. Use -1 em ordens não-stop |
| Quantity | Int64 | Quantidade de ativos |
| MessageID | Int64 | Identificador opcional retornado pelo servidor |
TConnectorAccountIdentifier
class TConnectorAccountIdentifier(Structure):
_fields_ = [
("Version", c_ubyte),
("BrokerID", c_int),
("AccountID", c_wchar_p),
("SubAccountID", c_wchar_p),
("Reserved", c_int64),
] | Campo | Significado |
| Version | Preencha com 0 |
| BrokerID | ID numérico da corretora (vem de GetAccounts) |
| AccountID | Identificador da conta como string |
| SubAccountID | ID da sub-conta. Para conta principal, deixe None |
| Reserved | Preencha com 0 |
TConnectorAssetIdentifier
class TConnectorAssetIdentifier(Structure):
_fields_ = [
("Version", c_ubyte),
("Ticker", c_wchar_p),
("Exchange", c_wchar_p),
("FeedType", c_ubyte),
] | Campo | Significado |
| Version | Preencha com 0 |
| Ticker | Código do contrato/ativo vigente (ex: "WINM26", "PETR4") |
| Exchange | Código da bolsa (ex: "F" para BM&F, "B" para Bovespa) |
| FeedType | Fonte do dado. Preencha com 0 (Nelogica) |
Atenção: Use sempre o ticker do contrato vigente, nunca códigos genéricos como WINFUT, WDOFUT ou INDFUT.** As funções de roteamento exigem o código exato do contrato em vigor (ex: "WINM26", "WDOK26", "PETR4"). A ProfitDLL não faz substituição automática (cross-order) para o contrato corrente, então tickers agregadores não são aceitos no envio de ordens. Os exemplos neste artigo usam contratos específicos apenas como ilustração, substitua sempre pelo código em vigor na data da operação.
TConnectorOrderIdentifier
Identifica uma ordem específica para operações de consulta, modificação ou cancelamento.
class TConnectorOrderIdentifier(Structure):
_fields_ = [
("Version", c_ubyte),
("LocalOrderID", c_int64),
("ClOrderID", c_wchar_p),
]
| Campo | Significado |
| LocalOrderID | Identificador interno da sessão atual. Retornado por SendOrder |
| ClOrderID | Identificador permanente atribuído pela corretora. Chega via callback |
Atenção: LocalOrderID vs ClOrderID**: o LocalOrderID é gerado pela DLL e válido apenas na sessão atual, você o tem imediatamente após SendOrder. O ClOrderID é o identificador definitivo da corretora e chega depois, no callback. Para a maioria das operações você pode usar qualquer um dos dois (preenchendo o outro como zero/None).
Atenção também aos tipos numéricos: Quantity, MessageID e LocalOrderID são Int64. Em Python use c_int64 (ou c_longlong) — não c_long, que em Windows x64 é apenas 32 bits e causa truncamento silencioso. Version, OrderType e OrderSide são Byte, ou seja, c_ubyte.
Enums
Tipos de ordem (OrderType)
| Valor | Constante | Significado |
| 1 | cotMarket | Ordem a mercado |
| 2 | cotLimit | Ordem limitada |
| 4 | cotStopLimit | Stop limit |
Lados (OrderSide)
| Valor | Constante | Significado |
| 1 | cosBuy | Compra |
| 2 | cosSell | Venda |
Status de ordem (OrderStatus)
| Valor | Constante | Significado |
| 0 | cosNew | Ordem nova, ainda não confirmada pela bolsa |
| 1 | cosPartiallyFilled | Parcialmente executada |
| 2 | cosFilled | Totalmente executada |
| 4 | cosCanceled | Cancelada |
| 5 | cosReplaced | Substituída (após modificação) |
| 6 | cosPendingCancel | Cancelamento solicitado, aguardando confirmação |
| 7 | cosStopped | Disparada (stop) |
| 8 | cosRejected | Rejeitada |
| 9 | cosSuspended | Suspensa |
| 10 | cosPendingNew | Aguardando aceitação inicial |
| 12 | cosExpired | Expirada |
| 14 | cosPendingReplace | Modificação solicitada, aguardando confirmação |
| 15 | cosPartiallyFilledCanceled | Cancelada após execução parcial |
| 16 | cosReceived | Recebida pela DLL |
| 18 | cosPartiallyFilledRejected | Rejeitada após execução parcial |
| 200 | cosUnknown | Estado desconhecido |
| 205 | cosCanceledByAdmin | Cancelada por administrador |
Códigos de resultado de mensagem (TradingMessageResultCode)
Recebidos no callback SetTradingMessageResultCallback:
| Valor | Constante | Significado |
| 0 | mrcStarting | Iniciando processamento |
| 1 | mrcNotConnected | Não há conexão de roteamento |
| 2 | mrcSentToHadesProxy | Enviada ao proxy interno |
| 3 | mrcRejectedMercury | Rejeitada pelo servidor Mercury |
| 4 | mrcSentToHades | Enviada ao servidor de roteamento |
| 5 | mrcRejectedHades | Rejeitada pelo servidor de roteamento |
| 6 | mrcSentToBroker | Enviada à corretora |
| 7 | mrcRejectedBroker | Rejeitada pela corretora |
| 8 | mrcSentToMarket | Enviada ao mercado |
| 9 | mrcRejectedMarket | Rejeitada pelo mercado |
| 10 | mrcAccepted | Aceita pelo mercado |
| 11 | mrcMarginTypeChangeRejected | Mudança de tipo de margem rejeitada |
| 12 | mrcPositionModeChangeRejected | Mudança de modo de posição rejeitada |
| 13 | mrcNeedUpdateFromServer | É necessária uma atualização do servidor |
| 17 | mrcSentToWallet | Enviada à carteira |
| 24 | mrcBlockedByRisk | Bloqueada pelo controle de risco |
| 200 | mrcUnknown | Resultado desconhecido |
Os valores entre 50 e 80 são reservados a operações de sub-conta e controle de risco, fora do escopo de roteamento de ordens.
Registrando as funções
Antes de chamar qualquer função de roteamento, declare o tipo de retorno (restype) e os argumentos (argtypes) de cada uma. Esse passo é obrigatório: por padrão o ctypes assume que toda função retorna c_int (32 bits). Como SendOrder e SendZeroPositionV2 retornam **Int64**, omitir o restype faz o LocalOrderID ser truncado silenciosamente — o valor lido fica incorreto e você perde a referência da ordem.
from ctypes import POINTER, c_int, c_int64
# Retornam Int64 (LocalOrderID) — restype obrigatório
profit_dll.SendOrder.argtypes = [POINTER(TConnectorSendOrder)]
profit_dll.SendOrder.restype = c_int64
profit_dll.SendZeroPositionV2.argtypes = [POINTER(TConnectorZeroPosition)]
profit_dll.SendZeroPositionV2.restype = c_int64
# Retornam Integer (32 bits) — código de erro ou 0 em sucesso
profit_dll.SendChangeOrderV2.argtypes = [POINTER(TConnectorChangeOrder)]
profit_dll.SendChangeOrderV2.restype = c_int
profit_dll.SendCancelOrderV2.argtypes = [POINTER(TConnectorCancelOrder)]
profit_dll.SendCancelOrderV2.restype = c_int
profit_dll.SendCancelOrdersV2.argtypes = [POINTER(TConnectorCancelOrders)]
profit_dll.SendCancelOrdersV2.restype = c_int
profit_dll.SendCancelAllOrdersV2.argtypes = [POINTER(TConnectorCancelAllOrders)]
profit_dll.SendCancelAllOrdersV2.restype = c_int
# Consulta e contas
profit_dll.GetOrderDetails.argtypes = [POINTER(TConnectorOrderOut)]
profit_dll.GetOrderDetails.restype = c_int
profit_dll.GetAccountCount.argtypes = []
profit_dll.GetAccountCount.restype = c_int
profit_dll.GetAccounts.argtypes = [c_int, c_int, c_int,
POINTER(TConnectorAccountIdentifierOut)]
profit_dll.GetAccounts.restype = c_int Atenção: SendOrder e SendZeroPositionV2 retornam Int64.** O LocalOrderID é um número grande (muito acima do limite de 32 bits). Sem restype = c_int64 o valor é truncado e deixa de corresponder à ordem real.
Obtendo a conta de roteamento
Antes do envio da primeira ordem, descubra qual BrokerID e AccountID usar:
from ctypes import byref
from profitTypes import TConnectorAccountIdentifierOut
# 1. Descobrir quantas contas existem
total = profit_dll.GetAccountCount()
if total <= 0:
raise RuntimeError("Nenhuma conta de roteamento disponível")
# 2. Buscar os identificadores
contas = (TConnectorAccountIdentifierOut * total)()
for c in contas:
c.Version = 0
profit_dll.GetAccounts(0, 0, total, contas)
# 3. Inspecionar a primeira conta
conta = contas[0]
print(f"Broker: {conta.BrokerID} | Conta: {conta.AccountID}") Em ambientes com múltiplas corretoras, total será maior que 1. Selecione a conta correta pelo BrokerID ou AccountID.
Enviando ordens
Montagem básica da estrutura
from profitTypes import TConnectorAccountIdentifier, TConnectorAssetIdentifier
account = TConnectorAccountIdentifier()
account.Version = 0
account.BrokerID = conta.BrokerID
account.AccountID = conta.AccountID
account.SubAccountID = None
account.Reserved = 0
asset = TConnectorAssetIdentifier()
asset.Version = 0
asset.Ticker = "WINM26"
asset.Exchange = "F"
asset.FeedType = 0
Ordem limitada (Limit)
order = TConnectorSendOrder()
order.Version = 2
order.AccountID = account
order.AssetID = asset
order.Password = "SENHA_DE_ROTEAMENTO"
order.OrderType = 2 # 2 = Limit
order.OrderSide = 1 # 1 = Buy
order.Price = 130000.0
order.StopPrice = -1
order.Quantity = 5
order.MessageID = 0
result = profit_dll.SendOrder(byref(order))
if result > 0:
local_order_id = result
print(f"Ordem enviada. LocalOrderID = {local_order_id}")
else:
print(f"Falha ao enviar ordem. Código de erro: {result}")
Ordem a mercado (Market)
order.OrderType = 1 # 1 = Market
order.Price = -1 # -1 obrigatório em market
order.StopPrice = -1
order.Quantity = 5
Ordem stop limit (StopLimit)
order.OrderType = 4 # 4 = StopLimit
order.OrderSide = 2 # 2 = Sell (stop loss típico)
order.Price = 129500.0 # preço da ordem limitada disparada
order.StopPrice = 129700.0 # preço de disparo
order.Quantity = 5 Atenção: StopPrice × Price em ordens stop limit**: o StopPrice é o gatilho. Quando o mercado bate nesse preço, uma ordem limitada com o Price é enviada. Em stops de venda, Price costuma ser menor que StopPrice; em stops de compra, maior. Inverter os dois é uma das fontes mais comuns de rejeição.
Acompanhando o ciclo de vida
O retorno síncrono de SendOrder confirma apenas que a DLL aceitou a ordem para enviar — não que a corretora ou o mercado aceitaram. Para acompanhar o que acontece de verdade, sua aplicação precisa registrar dois callbacks complementares:
- SetOrderCallback — disparado a cada mudança de estado em uma ordem. Entrega apenas o identificador; para detalhes, sua aplicação consulta com GetOrderDetails.
- SetTradingMessageResultCallback — disparado com o resultado de cada mensagem enviada (envio, modificação, cancelamento, zeragem). Permite saber rapidamente se a mensagem foi aceita, rejeitada e por quem.
Callback de ordem (TConnectorOrderCallback)
from ctypes import WINFUNCTYPE
from profitTypes import TConnectorOrderIdentifier
# Assinatura: o callback recebe TConnectorOrderIdentifier por valor.
TConnectorOrderCallback = WINFUNCTYPE(
None,
TConnectorOrderIdentifier,
)
def order_callback(order_id):
print(f"Ordem alterada: LocalOrderID={order_id.LocalOrderID}, "
f"ClOrderID={order_id.ClOrderID}")
# Para detalhes (preço, status, qty executada, etc.), chame GetOrderDetails
order_cb_ref = TConnectorOrderCallback(order_callback)
profit_dll.SetOrderCallback(order_cb_ref)
Callback de resultado de mensagem (TConnectorTradingMessageResultCallback)
from ctypes import WINFUNCTYPE, POINTER
from profitTypes import TConnectorTradingMessageResult
# Assinatura: recebe PONTEIRO para a estrutura — use .contents para acessar
TConnectorTradingMessageResultCallback = WINFUNCTYPE(
None,
POINTER(TConnectorTradingMessageResult),
)
def trading_message_callback(result_ptr):
r = result_ptr.contents
print(f"MessageID={r.MessageID} | BrokerID={r.BrokerID} | "
f"ResultCode={r.ResultCode} | Message={r.Message}")
result_cb_ref = TConnectorTradingMessageResultCallback(trading_message_callback)
profit_dll.SetTradingMessageResultCallback(result_cb_ref) Atenção à assinatura dos dois callbacks: o TConnectorOrderCallback recebe o TConnectorOrderIdentifier por valor — acesse os campos diretamente. O TConnectorTradingMessageResultCallback recebe um ponteiro para a struct — use .contents para acessar os campos. Trocar uma forma pela outra causa travamento silencioso.
Consultando detalhes de uma ordem (GetOrderDetails)
Após receber a notificação no TConnectorOrderCallback, consulte o estado completo:
from profitTypes import TConnectorOrderOut
order_out = TConnectorOrderOut()
order_out.Version = 0
order_out.OrderID.Version = 0
order_out.OrderID.LocalOrderID = local_order_id
order_out.OrderID.ClOrderID = None # identifique a ordem pelo LocalOrderID
ret = profit_dll.GetOrderDetails(byref(order_out))
if ret == 0:
print(f"Status: {order_out.OrderStatus}")
print(f"Executado: {order_out.TradedQuantity} de {order_out.Quantity}")
print(f"Resta: {order_out.LeavesQuantity}")
print(f"Preço médio: {order_out.AveragePrice}")
Modificando uma ordem
Use SendChangeOrderV2 para alterar preço, preço de stop ou quantidade de uma ordem ainda ativa.
Estrutura: TConnectorChangeOrder
class TConnectorChangeOrder(Structure):
_fields_ = [
("Version", c_ubyte),
("AccountID", TConnectorAccountIdentifier),
("OrderID", TConnectorOrderIdentifier),
("Password", c_wchar_p),
("Price", c_double),
("StopPrice", c_double),
("Quantity", c_int64),
("MessageID", c_int64),
] Exemplo: alterar preço de uma ordem limitada
change = TConnectorChangeOrder()
change.Version = 1
change.AccountID = account
change.OrderID.Version = 0
change.OrderID.LocalOrderID = local_order_id_recebido
change.OrderID.ClOrderID = None
change.Password = "SENHA_DE_ROTEAMENTO"
change.Price = 129800.0 # novo preço
change.StopPrice = -1
change.Quantity = 5 # mesma quantidade
change.MessageID = 0
ret = profit_dll.SendChangeOrderV2(byref(change))
if ret != 0:
print(f"Falha ao modificar ordem: código {ret}") A confirmação da modificação chega depois nos callbacks. O status passa por cosPendingReplace antes de virar cosReplaced ou voltar ao estado anterior se rejeitada.
Cancelando ordens
A DLL oferece três funções de cancelamento, escolhidas pelo escopo:
| Função | Escopo |
| SendCancelOrderV2 | Uma ordem específica |
| SendCancelOrdersV2 | Todas as ordens abertas de um ativo |
| SendCancelAllOrdersV2 | Todas as ordens abertas da conta |
Cancelando uma ordem específica
class TConnectorCancelOrder(Structure):
_fields_ = [
("Version", c_ubyte),
("AccountID", TConnectorAccountIdentifier),
("OrderID", TConnectorOrderIdentifier),
("Password", c_wchar_p),
("MessageID", c_int64),
] cancel = TConnectorCancelOrder()
cancel.Version = 1
cancel.AccountID = account
cancel.OrderID.Version = 0
cancel.OrderID.LocalOrderID = local_order_id_recebido
cancel.OrderID.ClOrderID = None
cancel.Password = "SENHA_DE_ROTEAMENTO"
cancel.MessageID = 0
ret = profit_dll.SendCancelOrderV2(byref(cancel))
Cancelando todas as ordens de um ativo
class TConnectorCancelOrders(Structure):
_fields_ = [
("Version", c_ubyte),
("AccountID", TConnectorAccountIdentifier),
("AssetID", TConnectorAssetIdentifier),
("Password", c_wchar_p),
] cancel_all_asset = TConnectorCancelOrders()
cancel_all_asset.Version = 0
cancel_all_asset.AccountID = account
cancel_all_asset.AssetID = asset
cancel_all_asset.Password = "SENHA_DE_ROTEAMENTO"
ret = profit_dll.SendCancelOrdersV2(byref(cancel_all_asset)) Cada ordem cancelada gera um evento separado nos callbacks.
Cancelando todas as ordens da conta
class TConnectorCancelAllOrders(Structure):
_fields_ = [
("Version", c_ubyte),
("AccountID", TConnectorAccountIdentifier),
("Password", c_wchar_p),
] cancel_all = TConnectorCancelAllOrders()
cancel_all.Version = 0
cancel_all.AccountID = account
cancel_all.Password = "SENHA_DE_ROTEAMENTO"
ret = profit_dll.SendCancelAllOrdersV2(byref(cancel_all)) Útil em rotinas de "kill switch" — corte tudo, em todos os ativos, de uma vez.
Zerando posição
SendZeroPositionV2 envia uma ordem para fechar uma posição existente. A ordem é executada como limit (informe Price) ou como market (informe Price = -1).
Estrutura: TConnectorZeroPosition
class TConnectorZeroPosition(Structure):
_fields_ = [
("Version", c_ubyte),
("AccountID", TConnectorAccountIdentifier),
("AssetID", TConnectorAssetIdentifier),
("Password", c_wchar_p),
("Price", c_double),
("PositionType", c_ubyte),
("MessageID", c_int64),
]
Tipos de posição (PositionType)
| Valor | Constante | Significado |
| 1 | cptDayTrade | Posição de day trade (intraday) |
| 2 | cptConsolidated | Posição consolidada (custódia) |
Exemplo: zerar posição a mercado
zero = TConnectorZeroPosition()
zero.Version = 2
zero.AccountID = account
zero.AssetID = asset
zero.Password = "SENHA_DE_ROTEAMENTO"
zero.Price = -1 # -1 = zerar a mercado
zero.PositionType = 1 # 1 = DayTrade
zero.MessageID = 0
result = profit_dll.SendZeroPositionV2(byref(zero))
if result > 0:
print(f"Ordem de zeragem enviada. LocalOrderID = {result}")
else:
print(f"Falha ao zerar posição: código {result}") A função retorna Int64 (positivo = LocalOrderID da ordem de zeragem; negativo = código de erro), mesmo padrão do SendOrder.
Códigos de erro mais comuns
Retornos negativos das funções de roteamento indicam falha de validação dentro da DLL, antes da mensagem chegar à corretora:
| Código | Constante | Causa típica |
| -2147483646 | NL_NOT_INITIALIZED | DLLInitializeLogin não foi chamado ou não completou |
| -2147483645 | NL_INVALID_ARGS | Algum campo da estrutura está inválido |
| -2147483644 | NL_WAITING_SERVER | Conexão de roteamento ainda não está pronta |
| -2147483643 | NL_NO_LOGIN | Login não autenticado |
| -2147483638 | NL_MARKET_ONLY | Licença não permite trading |
| -2147483637 | NL_NO_POSITION | Não há posição para zerar (em SendZeroPositionV2) |
| -2147483636 | NL_NOT_FOUND | Ordem não encontrada (em modificação/cancelamento) |
| -2147483635 | NL_VERSION_NOT_SUPPORTED | Campo Version da estrutura inválido para esta versão da DLL |
| -2147483630 | NL_LICENSE_NOT_ALLOWED | Funcionalidade não permitida pela licença |
| -2147483617 | NL_INVALID_TICKER | Ticker ou exchange não reconhecido |
Atenção: O retorno síncrono não é confirmação de execução. Um retorno de sucesso (LocalOrderID positivo em envio/zeragem, ou 0 em modificação/cancelamento) significa apenas que a DLL aceitou a operação. A aprovação real chega pelos callbacks. Sempre acompanhe TConnectorOrderCallback e TConnectorTradingMessageResultCallback para conhecer o resultado final.
Boas práticas
- **Use Version = 2** sempre que a estrutura suportar. Isso mantém alinhamento entre os enums usados no envio e os retornados nos callbacks e em GetOrderDetails.
- **Trate Price = -1 como obrigatório em ordens a mercado e zeragem a mercado.** Valores diferentes (mesmo 0) geram rejeição.
- **Trate StopPrice = -1 como obrigatório em ordens não-stop.** Mesma lógica.
- **Valide Quantity > 0 antes de enviar.** Quantidades zero ou negativas são rejeitadas com NL_INVALID_ARGS.
- **Armazene o mapeamento LocalOrderID → identificador interno da sua aplicação** assim que SendOrder retornar. Isso facilita correlacionar com os eventos posteriores.
- **Guarde o ClOrderID** assim que ele chegar no primeiro callback. Ele é o identificador permanente da ordem e o único que sobrevive entre sessões.
- Mantenha vivos os ponteiros dos callbacks. Atribua a callback_ref em escopo durável (atributo de classe, variável global). Se o GC liberar, a DLL chama um ponteiro inválido e o processo trava sem aviso.
- Nunca envie ordens, modifique, cancele ou zere posição dentro de um callback. Callbacks rodam na ConnectorThread; bloqueá-los compromete todo o pipeline de mensagens. O padrão recomendado é enfileirar o evento e processar em outra thread.
- Guarde a senha de roteamento de forma segura. Use variáveis de ambiente, cofre de senhas ou prompt interativo — nunca hardcode no script.
- Use sempre o ticker do contrato vigente no roteamento. Códigos agregadores como WINFUT, WDOFUT ou INDFUT não são aceitos pelas funções de roteamento — a ProfitDLL não faz cross-order. Mantenha sua aplicação consciente do contrato em vigor (por exemplo, atualizando o ticker a cada vencimento).
- Implemente um kill switch. Sempre tenha um caminho rápido para SendCancelAllOrdersV2 em situações de emergência (perda de conexão prolongada, exceção crítica não tratada, etc.).
- **Trate cosPendingNew, cosPendingReplace e cosPendingCancel como estados de transição.** Não considere a operação concluída até receber o status terminal correspondente (cosNew, cosReplaced, cosCanceled, cosRejected, etc.).
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!