14 minutos de leitura

Como enviar ordens no MetaTrader5 com Python

Por Rodrigo Vanzelotti
Conteúdos do artigo

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.

MetaTrader5

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...")

MarketWatch é um site que fornece informações financeiras, notícias de negócios, análises e dados do mercado de ações.

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:

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

Caso queira compreender melhor sobre cada campo necessário para a execução de um request, recomendamos que dê uma olhada na documentação direta do MLQ5/MT5 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 int 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 `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. Porém, 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:

Inscreva-se gratuitamente e fique atualizado

Receba toda semana um resumo dos principais conteúdos da Asimov direto no seu e-mail. 100% livre de spam.

Áreas de interesse:
Conteúdos do tutorial