MT4-Forex-XAU-SMA21-M5/MT4-Forex-XAU-SMA21-M5.mq4

188 lines
5.7 KiB
MQL4

//+------------------------------------------------------------------+
//| SMA21_EMA50_EA.mq4 |
//| Exemplo base para MetaTrader 4 |
//+------------------------------------------------------------------+
#property strict
//---- Inputs
input double Lots = 0.10;
input int StopBufferPoints = 50; // buffer extra em pontos abaixo/acima das medias
input int Slippage = 5;
input int MagicNumber = 21050;
input bool UseTakeProfit = false;
input int TakeProfitPoints = 200;
input int MaxSpreadPoints = 50;
//---- Controle de novo candle
datetime lastBarTime = 0;
//+------------------------------------------------------------------+
//| Função: verifica se há ordem aberta no símbolo |
//+------------------------------------------------------------------+
bool HasOpenPosition(string symb)
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == symb && OrderMagicNumber() == MagicNumber)
{
if(OrderType() == OP_BUY || OrderType() == OP_SELL)
return true;
}
}
}
return false;
}
//+------------------------------------------------------------------+
//| Função: retorna spread em pontos |
//+------------------------------------------------------------------+
int GetSpreadPoints()
{
return (int)((Ask - Bid) / Point);
}
//+------------------------------------------------------------------+
//| Função: detectar novo candle |
//+------------------------------------------------------------------+
bool IsNewBar()
{
datetime currentBarTime = Time[0];
if(currentBarTime != lastBarTime)
{
lastBarTime = currentBarTime;
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Função: calcula SMA21 e EMA50 |
//+------------------------------------------------------------------+
void GetMAs(int shift, double &sma21, double &ema50)
{
sma21 = iMA(Symbol(), 0, 21, 0, MODE_SMA, PRICE_CLOSE, shift);
ema50 = iMA(Symbol(), 0, 50, 0, MODE_EMA, PRICE_CLOSE, shift);
}
//+------------------------------------------------------------------+
//| Função: abre compra |
//+------------------------------------------------------------------+
bool OpenBuy(double stopLoss, double takeProfit)
{
double price = NormalizeDouble(Ask, Digits);
int ticket = OrderSend(Symbol(), OP_BUY, Lots, price, Slippage,
stopLoss, takeProfit,
"SMA21_EMA50 Buy", MagicNumber, 0, clrBlue);
if(ticket < 0)
{
Print("Erro ao abrir BUY. Código: ", GetLastError());
return false;
}
Print("BUY aberto com sucesso. Ticket: ", ticket);
return true;
}
//+------------------------------------------------------------------+
//| Função: abre venda |
//+------------------------------------------------------------------+
bool OpenSell(double stopLoss, double takeProfit)
{
double price = NormalizeDouble(Bid, Digits);
int ticket = OrderSend(Symbol(), OP_SELL, Lots, price, Slippage,
stopLoss, takeProfit,
"SMA21_EMA50 Sell", MagicNumber, 0, clrRed);
if(ticket < 0)
{
Print("Erro ao abrir SELL. Código: ", GetLastError());
return false;
}
Print("SELL aberto com sucesso. Ticket: ", ticket);
return true;
}
//+------------------------------------------------------------------+
//| Função principal |
//+------------------------------------------------------------------+
void OnTick()
{
// trabalha apenas em novo candle
if(!IsNewBar())
return;
// checa spread
if(GetSpreadPoints() > MaxSpreadPoints)
{
Print("Spread alto demais: ", GetSpreadPoints(), " pontos.");
return;
}
// se já existe operação, não faz nada
if(HasOpenPosition(Symbol()))
{
Print("Já existe posição aberta. Nenhuma nova operação será executada.");
return;
}
// pega valores das medias no candle fechado
double sma21_1, ema50_1;
double sma21_0, ema50_0;
GetMAs(1, sma21_1, ema50_1); // candle fechado
GetMAs(0, sma21_0, ema50_0); // candle atual
// dados do candle atual
double open0 = Open[0];
double close1 = Close[1];
double high0 = High[0];
double low0 = Low[0];
// regra de compra:
// candle atual abre acima das duas medias
if(open0 > sma21_0 && open0 > ema50_0)
{
double stopRef = MathMin(sma21_0, ema50_0);
double sl = NormalizeDouble(stopRef - StopBufferPoints * Point, Digits);
double tp = 0;
if(UseTakeProfit)
tp = NormalizeDouble(Ask + TakeProfitPoints * Point, Digits);
// evita stop inválido
if(sl >= Ask)
{
Print("Stop loss inválido para BUY. SL >= preço de entrada.");
return;
}
OpenBuy(sl, tp);
return;
}
// regra de venda:
// candle atual abre abaixo das duas medias
if(open0 < sma21_0 && open0 < ema50_0)
{
double stopRef = MathMax(sma21_0, ema50_0);
double sl = NormalizeDouble(stopRef + StopBufferPoints * Point, Digits);
double tp = 0;
if(UseTakeProfit)
tp = NormalizeDouble(Bid - TakeProfitPoints * Point, Digits);
// evita stop inválido
if(sl <= Bid)
{
Print("Stop loss inválido para SELL. SL <= preço de entrada.");
return;
}
OpenSell(sl, tp);
return;
}
}