//+------------------------------------------------------------------+ //| ADA_USD_Robot.mq5 | //| Copyright 2024, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" //--- Parâmetros de entrada input group "=== Configurações Gerais ===" input double InpLotSize = 0.01; // Tamanho do lote input int InpMagicNumber = 123456; // Número mágico input double InpStopLoss = 50; // Stop Loss em pontos input double InpTakeProfit = 100; // Take Profit em pontos input double InpMaxRisk = 2.0; // Risco máximo por trade (%) input group "=== Indicadores ===" input int InpMAPeriod = 21; // Período da Média Móvel input int InpMAFast = 12; // MA Rápida input int InpMASlow = 26; // MA Lenta input int InpRSIPeriod = 14; // Período do RSI input double InpRSIBuy = 30; // RSI nível de compra input double InpRSISell = 70; // RSI nível de venda input group "=== Configurações de Horário ===" input int InpStartHour = 8; // Hora de início (GMT) input int InpEndHour = 22; // Hora de fim (GMT) //--- Variáveis globais CTrade trade; CPositionInfo position; CSymbolInfo symbolInfo; int handleMA; int handleMAFast; int handleMASlow; int handleRSI; double ma[]; double maFast[]; double maSlow[]; double rsi[]; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Configurar símbolo if(!symbolInfo.Name(_Symbol)) { Print("Erro: Não foi possível inicializar o símbolo ", _Symbol); return(INIT_FAILED); } //--- Configurar trade trade.SetExpertMagicNumber(InpMagicNumber); trade.SetMarginMode(); trade.SetTypeFillingBySymbol(_Symbol); //--- Criar indicadores handleMA = iMA(_Symbol, PERIOD_H1, InpMAPeriod, 0, MODE_EMA, PRICE_CLOSE); handleMAFast = iMA(_Symbol, PERIOD_H1, InpMAFast, 0, MODE_EMA, PRICE_CLOSE); handleMASlow = iMA(_Symbol, PERIOD_H1, InpMASlow, 0, MODE_EMA, PRICE_CLOSE); handleRSI = iRSI(_Symbol, PERIOD_H1, InpRSIPeriod, PRICE_CLOSE); if(handleMA == INVALID_HANDLE || handleMAFast == INVALID_HANDLE || handleMASlow == INVALID_HANDLE || handleRSI == INVALID_HANDLE) { Print("Erro ao criar indicadores"); return(INIT_FAILED); } //--- Configurar arrays ArraySetAsSeries(ma, true); ArraySetAsSeries(maFast, true); ArraySetAsSeries(maSlow, true); ArraySetAsSeries(rsi, true); Print("ADA/USD Robot inicializado com sucesso!"); Print("Configurações da conta FXPro:"); Print("- Alavancagem: 50x"); Print("- Tamanho mínimo: 0.01 lot"); Print("- 1 lote = 1 ADA"); Print("- Valor do tick: 0.00001"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Liberar indicadores if(handleMA != INVALID_HANDLE) IndicatorRelease(handleMA); if(handleMAFast != INVALID_HANDLE) IndicatorRelease(handleMAFast); if(handleMASlow != INVALID_HANDLE) IndicatorRelease(handleMASlow); if(handleRSI != INVALID_HANDLE) IndicatorRelease(handleRSI); Print("ADA/USD Robot finalizado"); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Verificar se é um novo candle static datetime lastBarTime = 0; datetime currentBarTime = iTime(_Symbol, PERIOD_H1, 0); if(currentBarTime == lastBarTime) return; lastBarTime = currentBarTime; //--- Verificar horário de trading if(!IsTimeToTrade()) return; //--- Atualizar dados dos indicadores if(!UpdateIndicators()) return; //--- Verificar se já temos posição aberta bool hasPosition = false; for(int i = 0; i < PositionsTotal(); i++) { if(position.SelectByIndex(i)) { if(position.Symbol() == _Symbol && position.Magic() == InpMagicNumber) { hasPosition = true; break; } } } //--- Se não temos posição, procurar sinais de entrada if(!hasPosition) { CheckForBuySignal(); CheckForSellSignal(); } else { //--- Gerenciar posições existentes ManagePositions(); } } //+------------------------------------------------------------------+ //| Verificar se é horário de trading | //+------------------------------------------------------------------+ bool IsTimeToTrade() { MqlDateTime timeStruct; TimeToStruct(TimeCurrent(), timeStruct); return (timeStruct.hour >= InpStartHour && timeStruct.hour < InpEndHour); } //+------------------------------------------------------------------+ //| Atualizar dados dos indicadores | //+------------------------------------------------------------------+ bool UpdateIndicators() { if(CopyBuffer(handleMA, 0, 0, 3, ma) < 3 || CopyBuffer(handleMAFast, 0, 0, 3, maFast) < 3 || CopyBuffer(handleMASlow, 0, 0, 3, maSlow) < 3 || CopyBuffer(handleRSI, 0, 0, 3, rsi) < 3) { Print("Erro ao copiar dados dos indicadores"); return false; } return true; } //+------------------------------------------------------------------+ //| Verificar sinal de compra | //+------------------------------------------------------------------+ void CheckForBuySignal() { //--- Condições para compra: //--- 1. MA rápida cruzou acima da MA lenta //--- 2. RSI estava abaixo do nível de compra //--- 3. Preço está acima da MA principal bool maCrossUp = (maFast[1] > maSlow[1]) && (maFast[2] <= maSlow[2]); bool rsiOversold = rsi[1] < InpRSIBuy; bool priceAboveMA = iClose(_Symbol, PERIOD_H1, 1) > ma[1]; if(maCrossUp && rsiOversold && priceAboveMA) { double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double sl = ask - InpStopLoss * _Point; double tp = ask + InpTakeProfit * _Point; double lotSize = CalculateLotSize(); if(trade.Buy(lotSize, _Symbol, ask, sl, tp, "ADA/USD Buy Signal")) { Print("Ordem de compra executada: Lote=", lotSize, " Preço=", ask); } else { Print("Erro ao executar ordem de compra: ", GetLastError()); } } } //+------------------------------------------------------------------+ //| Verificar sinal de venda | //+------------------------------------------------------------------+ void CheckForSellSignal() { //--- Condições para venda: //--- 1. MA rápida cruzou abaixo da MA lenta //--- 2. RSI estava acima do nível de venda //--- 3. Preço está abaixo da MA principal bool maCrossDown = (maFast[1] < maSlow[1]) && (maFast[2] >= maSlow[2]); bool rsiOverbought = rsi[1] > InpRSISell; bool priceBelowMA = iClose(_Symbol, PERIOD_H1, 1) < ma[1]; if(maCrossDown && rsiOverbought && priceBelowMA) { double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double sl = bid + InpStopLoss * _Point; double tp = bid - InpTakeProfit * _Point; double lotSize = CalculateLotSize(); if(trade.Sell(lotSize, _Symbol, bid, sl, tp, "ADA/USD Sell Signal")) { Print("Ordem de venda executada: Lote=", lotSize, " Preço=", bid); } else { Print("Erro ao executar ordem de venda: ", GetLastError()); } } } //+------------------------------------------------------------------+ //| Calcular tamanho do lote baseado no risco | //+------------------------------------------------------------------+ double CalculateLotSize() { double balance = AccountInfoDouble(ACCOUNT_BALANCE); double riskAmount = balance * InpMaxRisk / 100.0; double pointValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE); if(pointValue == 0) pointValue = 0.00001; // Valor padrão para ADA/USD double lotSize = riskAmount / (InpStopLoss * pointValue); //--- Ajustar para o tamanho mínimo e máximo permitido double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); if(minLot == 0) minLot = 0.01; // Padrão FXPro para ADA if(maxLot == 0) maxLot = 1000; if(lotStep == 0) lotStep = 0.01; lotSize = MathMax(lotSize, minLot); lotSize = MathMin(lotSize, maxLot); lotSize = NormalizeDouble(lotSize / lotStep, 0) * lotStep; return lotSize; } //+------------------------------------------------------------------+ //| Gerenciar posições existentes | //+------------------------------------------------------------------+ void ManagePositions() { for(int i = 0; i < PositionsTotal(); i++) { if(position.SelectByIndex(i)) { if(position.Symbol() == _Symbol && position.Magic() == InpMagicNumber) { //--- Implementar trailing stop ou outras estratégias de saída ManageTrailingStop(); } } } } //+------------------------------------------------------------------+ //| Gerenciar trailing stop | //+------------------------------------------------------------------+ void ManageTrailingStop() { double currentPrice; double sl = position.StopLoss(); double newSL; if(position.PositionType() == POSITION_TYPE_BUY) { currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); newSL = currentPrice - InpStopLoss * _Point; if(newSL > sl && newSL < currentPrice) { if(trade.PositionModify(position.Ticket(), newSL, position.TakeProfit())) { Print("Trailing stop atualizado para posição BUY: ", newSL); } } } else if(position.PositionType() == POSITION_TYPE_SELL) { currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK); newSL = currentPrice + InpStopLoss * _Point; if((sl == 0 || newSL < sl) && newSL > currentPrice) { if(trade.PositionModify(position.Ticket(), newSL, position.TakeProfit())) { Print("Trailing stop atualizado para posição SELL: ", newSL); } } } } //+------------------------------------------------------------------+ //| Função para logs detalhados | //+------------------------------------------------------------------+ void LogTradeInfo(string action, double price, double lotSize) { Print("=== ", action, " ==="); Print("Símbolo: ", _Symbol); Print("Preço: ", DoubleToString(price, _Digits)); Print("Lote: ", DoubleToString(lotSize, 2)); Print("Saldo: ", DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE), 2)); Print("Equity: ", DoubleToString(AccountInfoDouble(ACCOUNT_EQUITY), 2)); Print("Margem Livre: ", DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN_FREE), 2)); Print("Alavancagem: 50x"); }