188 lines
5.7 KiB
MQL4
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;
|
|
}
|
|
}
|