mt5-fxpro-crypto/ADA_USD_Robot.mq5
2025-07-31 08:03:35 -03:00

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");
}