Tamanho de fonte
Alto contraste
Altura de linha

Como enviar ordens no MetaTrader5 com Python

Avatar de Rodrigo Vanzelotti Rodrigo Vanzelotti
10 minutos de leitura 1 ano atrás

Neste artigo, você irá entender como enviar ordens automaticamente no MetaTrader5 usando Python.

Todas as estratégias de trading exigem que o trader realize compra e venda de ativos em determinados períodos de tempo. Para automatizar as operações utilizando Python, é necessário saber advir ordens por meio de código.

Para enviar uma ordem na plataforma MetaTrader5, além de uma conta já estabelecida, é preciso utilizar duas funções principais que atuam em conjunto para checar e enviar a ordem. Antes de tudo, é importante entender o que é uma ordem, que consiste em instruções a um corretor ou corretora para comprar ou vender um título em nome de um investidor.

Meta trader 5

Introdução ao envio de ordens no MetaTrader5

Antes de prosseguir com o roteamento de ordens no MetaTrader5, é necessário estabelecer uma ação sobre a qual trabalharemos. Para isso, vamos declará-la e verificar sua existência no MT5 em algumas etapas, por questões de segurança de código.

# preparamos o ativo
symbol="ITUB4"
symbol_info = mt5.symbol_info(symbol)
if symbol_info is None:
    error_quit(f"{symbol} não foi encontrado, não é possível chamar order_check()")
   
 
# se o símbolo não estiver disponível no MarketWatch, adicionamos
if not symbol_info.visible:
    print(symbol, "não está visível, tentando conectar...")
    if not mt5.symbol_select(symbol,True):
        error_quit(f"symbol_select({symbol}) falhou, exiting...")

Com isso feito, podemos prosseguir.

O primeiro passo é verificar se temos as condições necessárias para realizar a operação que desejamos. Para isso, é necessário enviar uma requisição para o terminal do MetaTrader5, que verifica a possibilidade. A estrutura básica da função necessária, a order_check(), segue o seguinte padrão:

mt5.order_check(
	request	# estrutura de solicitação
)

Essa função deve retornar se a operação é possível ou não. Mas antes temos que montar um request , que é o objeto interpretado pelo MetaTrader5 para fazer as requisições.

A estrutura de um request

A estrutura básica de um request segue alguns campos necessários que serão organizados em um dicionário. São eles:

ChaveValorTipo
actionCompõe o tipo de trade que será feito. Como esse trade será posto?mt5 object ou inteiro
symbolO ativo que estamos operandomt5 object
volumeVolume da operaçãofloat (é preciso calcular o valor mínimo de volume para evitar o erro 10014 Invalid volume)
typeTipo de ordem: Compra, venda, buy_limit, sell_limit…mt5 object ou inteiro
priceValor de askfloat
slStop loss da operaçãofloat
tpTake-Profit da operaçãofloat
deviationDesvio – Valor da medida de volatilidade do mercadointeiro
magicAtribui um número cada pedido pendente, a fim de usar essa informação para identificá-lointeiro
commentComentário arbitrário do programadorstring
type_timeQuando a operação será realizada?mt5 object ou inteiro
type_fillingTipo de ordem: Fill or Kill, Immediate or Cancel ou Returnmt5 object ou inteiro

Caso queira compreender melhor sobre cada campo necessário para a execução de um request, recomendamos que dê uma olhada na documentação do MLQ5 sobre cada campo específico. Mas, abaixo, cobriremos um caso geral que deve satisfazer as operações.

À primeira vista, podem parecer muitos parâmetros para a realização de uma operação, mas todo trader sabe que são parâmetros necessários, sendo alguns obrigatórios e outros não, como é o exemplo do Stop-Loss e do Take-Profit entre outros.

Verificando fundos para realizar uma operação

Para executar um código de checagem de fundos de uma operação, além da request, é necessário uma série de passos. Porém, antes definiremos duas funções essenciais: uma em caso de erro e outra para checar se o volume de compra que estamos tentando realizar é possível.

# Funções para diminuir repetições de código
def error_quit(message):
    print(message)
    mt5.shutdown(); quit()


def check_volume(vol, symbol):
    maxvol = mt5.symbol_info(symbol).volumehigh
    minvol = mt5.symbol_info(symbol).volumelow
    if vol < minvol or vol > maxvol:
        error_quit(f'Volume Selecionado: {vol}\nVolume Mínimo: {minvol}\nVolume Máximo: {maxvol}')

Para checarmos a nossa ordem, é preciso executar:

point = mt5.symbol_info(symbol).point
ask = mt5.symbol_info_tick(symbol).ask

# estabelecer o volume aqui para mitigar erros
volume = 100.0
check_volume(volume, symbol)

request = {
    "action": mt5.TRADE_ACTION_DEAL,            # TRADE_ACTION_DEAL -> Ordem imediata
    "symbol": symbol,
    "volume": volume,                          
    "type": mt5.ORDER_TYPE_BUY,                 # ORDER_TYPE_BUY -> Ordem para compra
    "price": ask,                               # preço ask
    "sl": ask-100*point,
    "tp": ask+100*point,
    "deviation": 10,
    "magic": 234000,
    "comment": "asimov python script",
    "type_time": mt5.ORDER_TIME_GTC,            # ORDER_TIME_GTC -> A ordem permanecerá na fila até ser tirada
    "type_filling": mt5.ORDER_FILLING_RETURN,   # ORDER_FILLING RETURN -> No caso de uma execução parcial, a ordem de mercado ou limit com um volume residual não é retirada e continua
}

Ao printar o result[‘retcode’] e result[‘comment’], obtemos o código de resposta do programa e o comentário atribuído, compreendendo assim se a operação foi bem sucedida e, caso não, quais foram os resultados obtidos durante a execução.

É importante lembrar que a verificação de fundos para uma operação não envia a ordem. Para enviá-la, é necessário outro comando, o qual cobrimos a seguir.

Como enviar ordens no MetaTrader5

Aqui, utilizaremos a função order_send(), padrão do MT5, para envio de ordens, que segue uma estrutura de requisição semelhante ao do order_check(). A estrutura é a seguinte:

mt5.order_send(
	request	# estrutura de solicitação
)

Para testarmos o envio de ordens, iremos executar uma ordem de compra de um ativo específico (aqui utilizaremos o ITUB4), esperar 2 segundos utilizando a função time.sleep() nativa do Python e executar a ação de venda para que seja confirmada a operação de maneira demonstrativa.

Como operação padrão, antes devemos definir o volume, point, price e deviation. Nesse caso, utilizaremos o price de ask na compra e o preço de bid na venda, como há de ser. Iniciando pela ordem de compra:

volume = 100.0
point = mt5.symbol_info(symbol).point
price = mt5.symbol_info_tick(symbol).ask
deviation = 20

# estrutura de request igual à utilizada no order_check()
request = {
    "action": mt5.TRADE_ACTION_DEAL,    # ação imediata de transação
    "symbol": symbol,
    "volume": volume,
    "type": mt5.ORDER_TYPE_BUY,         # ordem de mercado para compra
    "price": price,                     # preço ask
    "sl": price - 100 * point,          # não é necessário
    "tp": price + 100 * point,          # não é necessário
    "deviation": deviation,
    "magic": 234000,
    "comment": "asimov python script open",
    "type_time": mt5.ORDER_TIME_GTC,            # A ordem permanecerá na fila até ser tirada
    "type_filling": mt5.ORDER_FILLING_RETURN,   # Ordem manual
}
 
# enviamos a solicitação de negociação
result = mt5.order_send(request)

Nesse caso, o resultado é retornado da mesma maneira anterior, porém, para fins didáticos, utilizamos aqui o método de atributos para desmembramento. Primeiro, devemos checar por meio do código de retorno se a ordem foi concluída. Para isso, utilizaremos primeiro uma função pré-definida (para evitar repetição de código posteriormente) e será comparado o retorno do resultado com a constante do MT5 chamada de mt5.TRADE_RETCODE_DONE, que nada mais nada menos é que um inteiro de valor 10009, representando o sucesso da operação.

A função que criaremos serve para dar o retorno em uma espécie de log do resultado de qualquer operação, iterando sobre os campos do objeto de resultado:

def order_result_log(result_object):
    # solicitamos o resultado na forma de dicionário e exibimos elemento por elemento
    result_dict = result_object._asdict()
    for field in result_dict.keys():
        print(f"   {field}={result_dict[field]}")
        #se esta for uma estrutura de uma solicitação de negociação, também a exibiremos elemento a elemento
        if field == "request":
            traderequest_dict = result_dict[field]._asdict()
            for tradereq_filed in traderequest_dict:
                print(f"\ttraderequest: {tradereq_filed}={traderequest_dict[tradereq_filed]}")

Tendo a função definida, podemos checar se a operação de compra foi concluída.

# verificamos o resultado da execução
if result.retcode != mt5.TRADE_RETCODE_DONE:
    order_result_log(result); error_quit()

Caso a operação tenha sido executada corretamente, entregamos alguns retornos, como a posição de compra e, na sequência, aguardamos dois segundos utilizando o time.sleep() para que possamos comprar novamente, dessa vez ao preço de bid.

# resultados da ordem de compra
position_id = result.order
print('POSIÇÃO:', position_id)
print(f"1. order_send(): by {symbol} {volume} lots at {price} desvio={deviation} points")
print("2. order_send() executada:")
print(f"   posição aberta: POSITION_TICKET={position_id}")

# tempo de processamento e redefinição da posição
time.sleep(2)
print(f"   timer 2s antes de fechar a posição #{position_id}")

Abaixo iniciamos o processo de fechamento, seguindo a mesma lógica anterior de `requests`.

# ORDEM DE FECHAMENTO =================
price = mt5.symbol_info_tick(symbol).bid
deviation = 20

request = {
    "action": mt5.TRADE_ACTION_DEAL,    # ação imediata de transação
    "symbol": symbol,
    "volume": volume,
    "type": mt5.ORDER_TYPE_SELL,        # ordem de mercado para venda
    "position": position_id,            # ticket
    "price": price,                     # preço bid
    "deviation": deviation,            
    "magic": 234000,
    "comment": "asimov python script close",
    "type_time": mt5.ORDER_TIME_GTC,    # A ordem permanecerá na fila até ser tirada
    "type_filling": mt5.ORDER_FILLING_RETURN,   # Ordem manual
}

# enviamos a solicitação de negociação
result = mt5.order_send(request)

Tendo o resultado em mãos, devemos verificar o resultado e disponibilizar para o usuário:

# verificamos o resultado da execução
print(f"3. close position #{position_id}: sell {symbol} {volume} lots at {price} desvio={deviation} points")

if result.retcode != mt5.TRADE_RETCODE_DONE:
    print(f"4. order_send falhou, retcode={result.retcode}")
    print("   resultado",result)
else:
    print(f"4. posição #{position_id} closed, {result}")
    order_result_log(result)

Ordens e registros temporais

Em resumo, é assim que se executa uma ordem e checa seus parâmetros derivados. No entanto, se você também deseja aprender a checar as ordens já realizadas, as posições abertas e abduzir de maneira conclusiva a qualidade de uma série de trades para validar uma estratégia, recomendamos a leitura do seguinte artigo:

Inclusive, existem outras tantas possibilidades dentro do MT5 para manejar o seu capital e expandir as suas estratégias como um Trader Quantitativo. Também há diversas técnicas para manipular dados do mercado e facilitar a visualização, como explicamos nestes dois artigos:

Boa leitura e, em caso de dúvida, deixe-a nos comentários!

Imagem de um notebook

Cursos de programação gratuitos com certificado

Aprenda a programar e desenvolva soluções para o seu trabalho com Python para alcançar novas oportunidades profissionais. Aqui na Asimov você encontra:

  • Conteúdos gratuitos
  • Projetos práticos
  • Certificados
  • +20 mil alunos e comunidade exclusiva
  • Materiais didáticos e download de código
Inicie agora

Comentários

Comentar
Faça parte da discussão Crie sua conta gratuita e compartilhe
sua opinião nos comentários
Entre para a Asimov