349 lines
No EOL
12 KiB
MQL5
349 lines
No EOL
12 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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");
|
|
} |