mt4-forex-xau-scalper-m5/XAU_USD_Scalper_M5.mq4

519 lines
18 KiB
MQL4

//+------------------------------------------------------------------+
//| XAU_USD_Scalper_M5.mq4 |
//| Copyright 2024, Forex Scalper Bot |
//| https://www.fbs.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Forex Scalper Bot"
#property link "https://www.fbs.com"
#property version "2.00"
#property strict
//--- Input Parameters
input double LotSize = 0.01; // Tamanho do lote
input int StopLoss = 25; // Stop Loss em pontos
input int TrailingStop = 15; // Trailing Stop em pontos
input double TakeProfitMultiplier = 2.0; // Multiplicador para Take Profit (spread + SL) * multiplicador
input int MagicNumber = 54321; // Número mágico
input int MaxSpread = 50; // Spread máximo permitido (pontos)
input int MinDistance = 30; // Distância mínima entre ordens (pontos)
input bool UseTrailingStop = true; // Usar Trailing Stop
input bool UseBreakEven = true; // Usar Break Even
input int BreakEvenPoints = 15; // Pontos para ativar Break Even
input int MaxOrders = 5; // Máximo de ordens simultâneas
input int RSI_Period = 14; // Período do RSI
input int RSI_Overbought = 70; // Nível de sobrecompra RSI
input int RSI_Oversold = 30; // Nível de sobrevenda RSI
input int MA_Fast = 8; // Média móvel rápida (ajustada para M5)
input int MA_Medium = 21; // Média móvel média
input int MA_Slow = 50; // Média móvel lenta (detecção de tendência)
input int MA_Method = MODE_EMA; // Tipo de média móvel
input double MinTrendStrength = 0.3; // Força mínima da tendência (em pontos por período)
input int TrendLookback = 20; // Períodos para calcular força da tendência
input bool UsePriceAction = true; // Usar sinais de Price Action
input double CandleBodyRatio = 0.6; // Ratio mínimo corpo/sombra para candles válidos
input bool UseMultipleOrders = true; // Permitir múltiplas ordens
//--- Global Variables
double g_point;
int g_digits;
datetime g_lastBarTime = 0;
int g_lastOrderCount = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Configurações básicas
g_digits = (int)MarketInfo(Symbol(), MODE_DIGITS);
g_point = MarketInfo(Symbol(), MODE_POINT);
// Ajustar para corretoras com 5 dígitos
if(g_digits == 5 || g_digits == 3)
{
g_point *= 10;
}
// Verificar se é XAU/USD
if(StringFind(Symbol(), "XAUUSD") < 0 && StringFind(Symbol(), "GOLD") < 0)
{
Print("Este EA foi projetado para XAU/USD. Símbolo atual: ", Symbol());
return(INIT_FAILED);
}
// Verificar timeframe
if(Period() != PERIOD_M5)
{
Print("Este EA foi projetado para timeframe M5. Timeframe atual: ", Period());
return(INIT_FAILED);
}
Print("XAU/USD Scalper M5 inicializado com sucesso!");
Print("Lot Size: ", LotSize);
Print("Stop Loss: ", StopLoss, " pontos");
Print("Take Profit Multiplier: ", TakeProfitMultiplier);
Print("Spread máximo: ", MaxSpread, " pontos");
Print("Magic Number: ", MagicNumber);
Print("Múltiplas ordens: ", UseMultipleOrders ? "Habilitado" : "Desabilitado");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Print("XAU/USD Scalper M5 finalizado. Razão: ", reason);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Verificar se é uma nova barra
if(g_lastBarTime == Time[0])
{
// Mesmo sem nova barra, gerenciar ordens abertas
ManageOpenOrders();
return;
}
g_lastBarTime = Time[0];
// Verificar spread
double currentSpread = MarketInfo(Symbol(), MODE_SPREAD);
if(currentSpread > MaxSpread)
{
Print("Spread muito alto: ", currentSpread, " - Aguardando melhores condições");
return;
}
// Verificar se já há muitas ordens abertas
int openOrders = CountOpenOrders();
if(!UseMultipleOrders && openOrders >= 1) return;
if(UseMultipleOrders && openOrders >= MaxOrders) return;
// Verificar condições de mercado e tendência
int marketCondition = AnalyzeMarketCondition();
if(marketCondition == 0) // Lateral - não operar
{
Print("Mercado em lateralidade - Aguardando tendência");
return;
}
// Verificar sinais de entrada
int signal = GetEntrySignal(marketCondition);
if(signal != 0)
{
double takeProfit = CalculateDynamicTakeProfit(currentSpread);
OpenOrder(signal, takeProfit);
}
// Gerenciar ordens abertas
ManageOpenOrders();
}
//+------------------------------------------------------------------+
//| Função para calcular Take Profit dinâmico |
//+------------------------------------------------------------------+
double CalculateDynamicTakeProfit(double spread)
{
// TP = (Spread + Stop Loss) * Multiplicador
double tpPoints = (spread + StopLoss) * TakeProfitMultiplier;
// Garantir TP mínimo
if(tpPoints < StopLoss * 1.5)
{
tpPoints = StopLoss * 1.5;
}
Print("Take Profit calculado: ", tpPoints, " pontos (Spread: ", spread, ")");
return tpPoints;
}
//+------------------------------------------------------------------+
//| Função para analisar condições do mercado |
//+------------------------------------------------------------------+
int AnalyzeMarketCondition()
{
double ma_slow = iMA(Symbol(), Period(), MA_Slow, 0, MA_Method, PRICE_CLOSE, 1);
double ma_slow_prev = iMA(Symbol(), Period(), MA_Slow, 0, MA_Method, PRICE_CLOSE, TrendLookback);
// Calcular força da tendência
double trendStrength = MathAbs(ma_slow - ma_slow_prev) / TrendLookback / g_point;
if(trendStrength < MinTrendStrength)
{
return 0; // Lateral
}
// Determinar direção da tendência
if(ma_slow > ma_slow_prev)
{
return 1; // Tendência de alta
}
else
{
return -1; // Tendência de baixa
}
}
//+------------------------------------------------------------------+
//| Função para obter sinal de entrada com Price Action |
//+------------------------------------------------------------------+
int GetEntrySignal(int trendDirection)
{
double rsi = iRSI(Symbol(), Period(), RSI_Period, PRICE_CLOSE, 1);
double ma_fast = iMA(Symbol(), Period(), MA_Fast, 0, MA_Method, PRICE_CLOSE, 1);
double ma_medium = iMA(Symbol(), Period(), MA_Medium, 0, MA_Method, PRICE_CLOSE, 1);
double ma_slow = iMA(Symbol(), Period(), MA_Slow, 0, MA_Method, PRICE_CLOSE, 1);
// Verificar alinhamento das médias móveis
bool bullishMA = (ma_fast > ma_medium && ma_medium > ma_slow);
bool bearishMA = (ma_fast < ma_medium && ma_medium < ma_slow);
// Price Action - analisar candles
bool bullishPA = false;
bool bearishPA = false;
if(UsePriceAction)
{
bullishPA = IsBullishPriceAction();
bearishPA = IsBearishPriceAction();
}
else
{
// Usar apenas RSI se Price Action estiver desabilitado
bullishPA = (rsi < RSI_Oversold);
bearishPA = (rsi > RSI_Overbought);
}
// Sinal de compra
if(trendDirection >= 0 && bullishMA && bullishPA && rsi < 60)
{
return 1; // Compra
}
// Sinal de venda
if(trendDirection <= 0 && bearishMA && bearishPA && rsi > 40)
{
return -1; // Venda
}
return 0; // Sem sinal
}
//+------------------------------------------------------------------+
//| Função para detectar Price Action de alta |
//+------------------------------------------------------------------+
bool IsBullishPriceAction()
{
double open1 = Open[1];
double high1 = High[1];
double low1 = Low[1];
double close1 = Close[1];
double open2 = Open[2];
double close2 = Close[2];
// Candle de alta (corpo verde)
if(close1 <= open1) return false;
// Verificar ratio do corpo
double bodySize = close1 - open1;
double totalRange = high1 - low1;
if(totalRange > 0 && (bodySize / totalRange) < CandleBodyRatio) return false;
// Padrões de Price Action
// 1. Hammer ou Doji de alta após queda
bool isHammer = (bodySize < (totalRange * 0.3) && (close1 - low1) > (high1 - close1) * 2);
// 2. Candle de engolfo de alta
bool isBullishEngulfing = (close2 < open2 && close1 > open1 && open1 < close2 && close1 > open2);
// 3. Candle de alta forte
bool isStrongBullish = (bodySize > (totalRange * 0.7) && close1 > open2);
return (isHammer || isBullishEngulfing || isStrongBullish);
}
//+------------------------------------------------------------------+
//| Função para detectar Price Action de baixa |
//+------------------------------------------------------------------+
bool IsBearishPriceAction()
{
double open1 = Open[1];
double high1 = High[1];
double low1 = Low[1];
double close1 = Close[1];
double open2 = Open[2];
double close2 = Close[2];
// Candle de baixa (corpo vermelho)
if(close1 >= open1) return false;
// Verificar ratio do corpo
double bodySize = open1 - close1;
double totalRange = high1 - low1;
if(totalRange > 0 && (bodySize / totalRange) < CandleBodyRatio) return false;
// Padrões de Price Action
// 1. Shooting Star ou Doji de baixa após alta
bool isShootingStar = (bodySize < (totalRange * 0.3) && (high1 - close1) > (close1 - low1) * 2);
// 2. Candle de engolfo de baixa
bool isBearishEngulfing = (close2 > open2 && close1 < open1 && open1 > close2 && close1 < open2);
// 3. Candle de baixa forte
bool isStrongBearish = (bodySize > (totalRange * 0.7) && close1 < open2);
return (isShootingStar || isBearishEngulfing || isStrongBearish);
}
//+------------------------------------------------------------------+
//| Função para abrir ordem |
//+------------------------------------------------------------------+
void OpenOrder(int signal, double tpPoints)
{
double price, sl, tp;
int cmd;
string comment;
if(signal == 1) // Compra
{
cmd = OP_BUY;
price = Ask;
sl = price - StopLoss * g_point;
tp = price + tpPoints * g_point;
comment = "XAU M5 Buy";
}
else if(signal == -1) // Venda
{
cmd = OP_SELL;
price = Bid;
sl = price + StopLoss * g_point;
tp = price - tpPoints * g_point;
comment = "XAU M5 Sell";
}
else
{
return;
}
// Verificar distância mínima se múltiplas ordens estiverem habilitadas
if(UseMultipleOrders && !CheckMinDistance(price, cmd))
{
Print("Distância mínima não atendida para nova ordem");
return;
}
int ticket = OrderSend(Symbol(), cmd, LotSize, price, 5, sl, tp, comment, MagicNumber, 0, clrGreen);
if(ticket > 0)
{
Print("Ordem aberta: ", cmd == OP_BUY ? "Compra" : "Venda",
" Ticket: ", ticket, " Preço: ", DoubleToStr(price, g_digits),
" SL: ", DoubleToStr(sl, g_digits), " TP: ", DoubleToStr(tp, g_digits));
}
else
{
Print("Erro ao abrir ordem: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Função para verificar distância mínima |
//+------------------------------------------------------------------+
bool CheckMinDistance(double price, int cmd)
{
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
double orderPrice = OrderOpenPrice();
double distance = MathAbs(price - orderPrice) / g_point;
if(distance < MinDistance)
{
return false;
}
}
}
}
return true;
}
//+------------------------------------------------------------------+
//| Função para contar ordens abertas |
//+------------------------------------------------------------------+
int CountOpenOrders()
{
int count = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() <= OP_SELL)
{
count++;
}
}
}
return count;
}
//+------------------------------------------------------------------+
//| Função para gerenciar ordens abertas |
//+------------------------------------------------------------------+
void ManageOpenOrders()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
// Break Even
if(UseBreakEven)
{
ManageBreakEven();
}
// Trailing Stop
if(UseTrailingStop)
{
ManageTrailingStop();
}
}
}
}
}
//+------------------------------------------------------------------+
//| Função para gerenciar Break Even |
//+------------------------------------------------------------------+
void ManageBreakEven()
{
double currentPrice = (OrderType() == OP_BUY) ? Bid : Ask;
double openPrice = OrderOpenPrice();
double currentSL = OrderStopLoss();
double profit = (OrderType() == OP_BUY) ? (currentPrice - openPrice) : (openPrice - currentPrice);
if(profit >= BreakEvenPoints * g_point)
{
double newSL = openPrice + (OrderType() == OP_BUY ? 3 * g_point : -3 * g_point);
// Verificar se o novo SL é melhor que o atual
bool shouldUpdate = false;
if(OrderType() == OP_BUY && (currentSL == 0 || newSL > currentSL))
shouldUpdate = true;
else if(OrderType() == OP_SELL && (currentSL == 0 || newSL < currentSL))
shouldUpdate = true;
if(shouldUpdate)
{
if(OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrBlue))
{
Print("Break Even ativado para ticket: ", OrderTicket(), " Novo SL: ", DoubleToStr(newSL, g_digits));
}
}
}
}
//+------------------------------------------------------------------+
//| Função para gerenciar Trailing Stop |
//+------------------------------------------------------------------+
void ManageTrailingStop()
{
double currentPrice = (OrderType() == OP_BUY) ? Bid : Ask;
double currentSL = OrderStopLoss();
double newSL;
if(OrderType() == OP_BUY)
{
newSL = currentPrice - TrailingStop * g_point;
if(currentSL == 0 || newSL > currentSL + g_point)
{
if(OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrRed))
{
Print("Trailing Stop atualizado para compra - Ticket: ", OrderTicket(),
" Novo SL: ", DoubleToStr(newSL, g_digits));
}
}
}
else if(OrderType() == OP_SELL)
{
newSL = currentPrice + TrailingStop * g_point;
if(currentSL == 0 || newSL < currentSL - g_point)
{
if(OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrRed))
{
Print("Trailing Stop atualizado para venda - Ticket: ", OrderTicket(),
" Novo SL: ", DoubleToStr(newSL, g_digits));
}
}
}
}
//+------------------------------------------------------------------+
//| Função para monitorar ordens executadas |
//+------------------------------------------------------------------+
void OnTrade()
{
static datetime lastCheckTime = 0;
if(TimeCurrent() != lastCheckTime)
{
lastCheckTime = TimeCurrent();
// Verificar ordens fechadas recentemente
for(int i = OrdersHistoryTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if(OrderCloseTime() >= TimeCurrent() - 300) // Últimos 5 minutos
{
string orderType = (OrderType() == OP_BUY) ? "Compra" : "Venda";
double profit = OrderProfit() + OrderSwap() + OrderCommission();
Print("===== ORDEM FECHADA =====");
Print("Tipo: ", orderType, " | Ticket: ", OrderTicket());
Print("Preço Abertura: ", DoubleToStr(OrderOpenPrice(), g_digits));
Print("Preço Fechamento: ", DoubleToStr(OrderClosePrice(), g_digits));
Print("Lucro: ", DoubleToStr(profit, 2), " USD");
Print("========================");
}
}
}
}
}
}