Claro! Vamos explicar o código detalhadamente, com foco em cada parte e função para garantir que você compreenda como tudo funciona.
1. Importação de Bibliotecas
import MetaTrader5 as mt5
import time
from datetime import datetime
import signal
import sys
-
MetaTrader5 (mt5): A biblioteca
MetaTrader5
permite interagir com a plataforma MetaTrader 5 para automatizar operações de trading, como enviar ordens de compra e venda, obter cotações, etc. - time: Para realizar pausas no código, como aguardar até o momento de enviar uma ordem ou fazer verificações periódicas.
- datetime: Usada para trabalhar com datas e horários. Neste código, é essencial para controlar quando as ordens serão enviadas e quando o programa irá encerrar.
-
signal: Permite capturar sinais do sistema operacional, como o
Ctrl+C
(usado para interromper a execução do programa). -
sys: Usado para interagir com o sistema, como finalizar o programa caso algo dê errado (ex:
sys.exit()
).
2. Controle de Execução com o Sinal Ctrl+C
running = True
def signal_handler(sig, frame):
global running
print("\nInterrompendo o programa...")
running = False
signal.signal(signal.SIGINT, signal_handler)
- A variável
running
é usada para controlar se o programa deve continuar executando ou não. - O manipulador
signal_handler
captura o sinalSIGINT
(gerado peloCtrl+C
) e altera o valor derunning
paraFalse
, o que interrompe o loop principal do programa.
3. Configuração de Conexão com o MetaTrader 5
login = 101108
password = "Jesuse10!"
server = "EquitiBrokerageSC-Demo"
mt5_path = r"C:\Program Files\Equiti Group MetaTrader 5 Terminal\terminal64.exe"
Essas variáveis contêm as credenciais e o caminho do MetaTrader 5. Elas são usadas para conectar o script à sua conta no MetaTrader:
- login: O número de login da sua conta no MetaTrader.
- password: A senha associada ao login.
- server: O servidor da corretora.
- mt5_path: O caminho para o arquivo executável do MetaTrader 5, necessário para inicializar a conexão.
4. Função get_symbol_info
def get_symbol_info(symbol):
info = mt5.symbol_info(symbol)
if info is None:
print(f"Falha ao obter informações do símbolo {symbol}")
return None
return info
Esta função busca informações sobre o símbolo (ativo) que você quer negociar, como:
- Preço atual, preço de abertura, pontos, etc.
- Se não conseguir obter as informações, retorna
None
.
5. Funções para Ajustar Preço
def round_price(price, digits):
return round(price, digits)
def align_price_to_tick(price, tick_size):
return round(price / tick_size) * tick_size
- round_price: Arredonda o preço para um número de casas decimais específico (dependendo do ativo).
- align_price_to_tick: Alinha o preço ao tamanho do tick (o menor movimento possível do preço). Isso é necessário para garantir que o preço esteja de acordo com o formato aceito pela corretora.
6. Função send_order
def send_order(symbol, order_type, lot, price, sl, tp):
...
result = mt5.order_send(request)
...
return result
Essa função envia a ordem de compra ou venda para o MetaTrader. Ela aceita:
- symbol: O símbolo (ativo) que você deseja negociar.
- order_type: O tipo de ordem (exemplo: compra ou venda pendente).
- lot: O tamanho do lote (quantidade de ativos a serem comprados ou vendidos).
- price: O preço da ordem.
- sl: O nível de stop loss.
- tp: O nível de take profit.
A função cria uma solicitação (request
) com todas as configurações necessárias para enviar a ordem, e então chama mt5.order_send(request)
para efetivamente enviar a ordem para a plataforma MetaTrader 5.
7. Função get_current_candle
def get_current_candle(symbol, timeframe):
rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, 1)
if rates is None or len(rates) == 0:
return None
return rates[0]
Essa função busca a última vela (candle) de um determinado ativo. Ela usa o timeframe para determinar o intervalo de tempo entre cada vela (por exemplo, 5 minutos). A função retorna a última vela (com dados como preço de abertura, fechamento, máxima, mínima).
8. Função cancel_pending_orders
def cancel_pending_orders():
orders = mt5.orders_get(symbol=symbol)
...
result = mt5.order_send(request) # Enviar o pedido para cancelar a ordem
Essa função cancela todas as ordens pendentes de tipo BUY_STOP ou SELL_STOP para o símbolo especificado. A função verifica se há ordens pendentes e, caso existam, envia uma solicitação para cancelá-las.
9. Função main_loop
(Loop Principal)
def main_loop():
global running
ordem_executada = False
while running and not ordem_executada:
try:
current_time = datetime.now()
# Define o horário alvo para as ordens
target_time = current_time.replace(hour=execution_hour, minute=execution_minute, second=execution_second, microsecond=0)
if current_time < target_time:
sleep_time = (target_time - current_time).total_seconds()
print(f"Aguardando até {target_time.strftime('%H:%M:%S')} para enviar ordens...")
time.sleep(sleep_time)
current_candle = get_current_candle(symbol, timeframe)
if current_candle is None:
print(f"[{datetime.now()}] Erro ao obter candle atual.")
continue
symbol_info = get_symbol_info(symbol)
if symbol_info is None:
continue
point = symbol_info.point
digits = symbol_info.digits
tick_size = symbol_info.trade_tick_size
buy_price = align_price_to_tick(round_price(current_candle['high'] + offset_pips_buy * point, digits), tick_size)
sell_price = align_price_to_tick(round_price(current_candle['low'] - offset_pips_sell * point, digits), tick_size)
sl_buy = align_price_to_tick(round_price(buy_price - sl_pips * point, digits), tick_size)
tp_buy = align_price_to_tick(round_price(buy_price + tp_pips * point, digits), tick_size)
sl_sell = align_price_to_tick(round_price(sell_price + sl_pips * point, digits), tick_size)
tp_sell = align_price_to_tick(round_price(sell_price - tp_pips * point, digits), tick_size)
send_order(symbol, mt5.ORDER_TYPE_BUY_STOP, lot, buy_price, sl_buy, tp_buy)
send_order(symbol, mt5.ORDER_TYPE_SELL_STOP, lot, sell_price, sl_sell, tp_sell)
ordem_executada = True
shutdown_time = current_time.replace(hour=shutdown_hour, minute=shutdown_minute, second=shutdown_second, microsecond=0)
while running and datetime.now() < shutdown_time:
time.sleep(1)
cancel_pending_orders()
print(f"[{datetime.now()}] Todas as ordens pendentes foram canceladas.")
time.sleep(60)
except Exception as e:
print(f"Erro no loop principal: {e}")
time.sleep(1)
- main_loop é a função central onde o código passa a maior parte do tempo, executando as operações de acordo com os horários definidos e verificando as condições para enviar ordens.
- O código fica aguardando até o horário
execution_hour
,execution_minute
, eexecution_second
para enviar as ordens. - Depois de enviar as ordens, ele aguarda até o horário de shutdown e então cancela as ordens pendentes.
- A função também verifica a conta de tempos em tempos, aguardando 1 minuto entre as verificações de saldo.
10. Execução Principal do Código
# Executa o loop principal
try:
main_loop()
except Exception as e:
print(f"Ocorreu um erro: {e}")
finally:
# Desconecta do MetaTrader 5
mt5.shutdown()
print(f"[{datetime.now()}] Desconectado do MetaTrader 5.")
Aqui, a função main_loop
é chamada. Caso ocorra algum erro, ele é capturado pela exceção except
, e a conexão com o MetaTrader é finalizada com mt5.shutdown()
.
Conclusão:
Este código é um exemplo de um Expert Advisor (EA) automatizado para o MetaTrader 5, que realiza operações de compra e venda com base no horário e nos preços dos candles. O programa se conecta ao Meta
import MetaTrader5 as mt5
import time
from datetime import datetime
import signal
import sys
# Variável global para controlar a execução
running = True
def signal_handler(sig, frame):
global running
print("\nInterrompendo o programa...")
running = False
# Configurar o manipulador de sinal para Ctrl+C
signal.signal(signal.SIGINT, signal_handler)
# Variáveis de configuração do MetaTrader 5
login = 101108
password = "Jesuse10!"
server = "EquitiBrokerageSC-Demo"
mt5_path = r"C:\Program Files\Equiti Group MetaTrader 5 Terminal\terminal64.exe"
# Conecta ao MetaTrader 5 com as credenciais
print("Tentando conectar ao MetaTrader 5...")
if not mt5.initialize(login=login, password=password, server=server, path=mt5_path):
print("Erro ao inicializar MT5. Verifique suas credenciais e tente novamente.")
sys.exit(1)
else:
print(f"Conectado ao MT5 na conta {login} com sucesso!")
# Defina as configurações
symbol = "US30Roll"
lot = 40.00
sl_pips = 2500
tp_pips = 3500
offset_pips_buy = 320 # Mantém 320 pipetes para buy stop
offset_pips_sell = 80 # Altera para 50 pipetes para sell stop
timeframe = mt5.TIMEFRAME_M5 # Alterado para 5 minutos
# Variável do horário específico (alterável facilmente)
execution_hour = 11
execution_minute = 29
execution_second = 59
# Variável do horário de desligamento (alterável facilmente)
shutdown_hour = 11
shutdown_minute = 30
shutdown_second = 59
# Função para obter informações do símbolo
def get_symbol_info(symbol):
info = mt5.symbol_info(symbol)
if info is None:
print(f"Falha ao obter informações do símbolo {symbol}")
return None
return info
# Arredondar o preço de acordo com o número de dígitos
def round_price(price, digits):
return round(price, digits)
# Alinhar o preço ao tamanho do tick
def align_price_to_tick(price, tick_size):
return round(price / tick_size) * tick_size
# Enviar a ordem de compra ou venda
def send_order(symbol, order_type, lot, price, sl, tp):
try:
symbol_info = get_symbol_info(symbol)
if symbol_info is None:
return None
digits = symbol_info.digits
tick_size = symbol_info.trade_tick_size
price = align_price_to_tick(round_price(price, digits), tick_size)
sl = align_price_to_tick(round_price(sl, digits), tick_size)
tp = align_price_to_tick(round_price(tp, digits), tick_size)
print(f"[{datetime.now()}] Enviando ordem: Tipo={order_type}, Preço={price}, SL={sl}, TP={tp}")
request = {
"action": mt5.TRADE_ACTION_PENDING,
"symbol": symbol,
"volume": lot,
"type": order_type,
"price": price,
"sl": sl,
"tp": tp,
"deviation": 10,
"magic": 234000,
"comment": "Python EA",
"type_time": mt5.ORDER_TIME_GTC,
"type_filling": mt5.ORDER_FILLING_IOC,
}
result = mt5.order_send(request)
if result.retcode != mt5.TRADE_RETCODE_DONE:
print(f"Erro ao enviar ordem: {result.retcode}, {result.comment}")
else:
print(f"Ordem enviada com sucesso: {result.order}")
return result
except Exception as e:
print(f"Erro ao enviar ordem: {e}")
return None
# Obter o candle atual
def get_current_candle(symbol, timeframe):
rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, 1)
if rates is None or len(rates) == 0:
return None
return rates[0]
# Função para cancelar todas as ordens pendentes
def cancel_pending_orders():
orders = mt5.orders_get(symbol=symbol)
if orders is not None:
for order in orders:
if order.type == mt5.ORDER_TYPE_BUY_STOP or order.type == mt5.ORDER_TYPE_SELL_STOP:
print(f"Cancelando ordem pendente: {order.ticket}")
# Criar um pedido para cancelar a ordem
request = {
"action": mt5.TRADE_ACTION_REMOVE,
"order": order.ticket,
}
result = mt5.order_send(request) # Enviar o pedido para cancelar a ordem
if result.retcode != mt5.TRADE_RETCODE_DONE:
print(f"Erro ao cancelar ordem: {result.retcode}, {result.comment}")
else:
print(f"Ordem {order.ticket} cancelada com sucesso.")
else:
print("Nenhuma ordem pendente encontrada.")
# Função principal do sistema
def main_loop():
global running
ordem_executada = False
while running and not ordem_executada:
try:
current_time = datetime.now()
# Define o horário alvo para as ordens (variável alterável)
target_time = current_time.replace(hour=execution_hour, minute=execution_minute, second=execution_second, microsecond=0)
if current_time < target_time:
sleep_time = (target_time - current_time).total_seconds()
print(f"Aguardando até {target_time.strftime('%H:%M:%S')} para enviar ordens...")
time.sleep(sleep_time)
# Verifica o candle atual para calcular preços de buy e sell
current_candle = get_current_candle(symbol, timeframe)
if current_candle is None:
print(f"[{datetime.now()}] Erro ao obter candle atual.")
continue
symbol_info = get_symbol_info(symbol)
if symbol_info is None:
continue
point = symbol_info.point
digits = symbol_info.digits
tick_size = symbol_info.trade_tick_size
# Calcula os preços de buy e sell
buy_price = align_price_to_tick(round_price(current_candle['high'] + offset_pips_buy * point, digits), tick_size)
sell_price = align_price_to_tick(round_price(current_candle['low'] - offset_pips_sell * point, digits), tick_size)
sl_buy = align_price_to_tick(round_price(buy_price - sl_pips * point, digits), tick_size)
tp_buy = align_price_to_tick(round_price(buy_price + tp_pips * point, digits), tick_size)
sl_sell = align_price_to_tick(round_price(sell_price + sl_pips * point, digits), tick_size)
tp_sell = align_price_to_tick(round_price(sell_price - tp_pips * point, digits), tick_size)
print(f"[{datetime.now()}] Enviando ordens: BUY_STOP em {buy_price}, SELL_STOP em {sell_price}")
send_order(symbol, mt5.ORDER_TYPE_BUY_STOP, lot, buy_price, sl_buy, tp_buy) # Certifique-se de passar tp
send_order(symbol, mt5.ORDER_TYPE_SELL_STOP, lot, sell_price, sl_sell, tp_sell) # Certifique-se de passar tp
print(f"[{datetime.now()}] Ordens enviadas com sucesso às {target_time.strftime('%H:%M:%S')}. Aguardando para cancelar ordens pendentes.")
ordem_executada = True
# Aguardar até o horário de desligamento
shutdown_time = current_time.replace(hour=shutdown_hour, minute=shutdown_minute, second=shutdown_second, microsecond=0)
while running and datetime.now() < shutdown_time:
time.sleep(1)
# Cancelar ordens pendentes
cancel_pending_orders()
print(f"[{datetime.now()}] Todas as ordens pendentes foram canceladas.")
# Aguardar 1 minuto
print(f"[{datetime.now()}] Aguardando 1 minuto antes de verificar o saldo...")
time.sleep(60)
# Verificar saldo e imprimir no terminal
account_info = mt5.account_info()
if account_info is not None:
print(f"[{datetime.now()}] Saldo da conta: {account_info.balance}")
else:
print(f"[{datetime.now()}] Falha ao obter informações da conta.")
except Exception as e:
print(f"Erro no loop principal: {e}")
time.sleep(1)
# Conecta ao MetaTrader 5 com as credenciais
print(f"Tentando conectar ao MetaTrader 5 na conta {login}...")
if not mt5.initialize(login=login, password=password, server=server, path=mt5_path):
print(f"[{datetime.now()}] Erro ao inicializar MT5. Verifique suas credenciais.")
sys.exit(1)
else:
print(f"[{datetime.now()}] Conectado ao MT5 na conta {login} com sucesso!")
# Verificar saldo e nome da corretora
account_info = mt5.account_info()
if account_info is not None:
print(f"[{datetime.now()}] Conectado à corretora: {account_info.server}")
print(f"[{datetime.now()}] Saldo da conta: {account_info.balance}")
else:
print(f"[{datetime.now()}
] Falha ao obter informações da conta.")
# Executa o loop principal
try:
main_loop()
except Exception as e:
print(f"Ocorreu um erro: {e}")
finally:
# Desconecta do MetaTrader 5
mt5.shutdown()
print(f"[{datetime.now()}] Desconectado do MetaTrader 5.")
Aqui estão as alterações feitas:
- O código original foi mantido com pequenas melhorias de legibilidade.
- Comentários e variáveis foram ajustados para maior clareza e precisão no código.
- A estrutura de erros foi mantida intacta e o código foi organizado para facilitar a manutenção e depuração.
Top comments (0)