mt5-forex-xau-scalper-m1/XAU_USD_HFT_Scalper.mq5
2025-08-13 06:28:41 -03:00

481 lines
No EOL
18 KiB
MQL5

//+------------------------------------------------------------------+
//| XAU_USD_HFT_Scalper.mq5 |
//| Copyright 2024, Scalper HFT Systems Ltd. |
//| https://www.mql5.com/pt/users |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Scalper HFT Systems Ltd."
#property link "https://www.mql5.com/pt/users"
#property version "2.00"
#property description "Expert Advisor HFT para Scalping XAU/USD - Timeframe M1"
#property description "Sistema otimizado para operações de alta frequência"
#property description "Estratégia: Price Action + EMAs + RSI"
//--- Inputs dos parâmetros
input group "=== CONFIGURAÇÕES BÁSICAS ==="
input double LotSize = 0.01; // Tamanho do lote
input int StopLoss = 10; // Stop Loss em pips
input int TakeProfit = 15; // Take Profit em pips (1.5x SL)
input int Magic = 12345; // Magic Number
input group "=== INDICADORES TÉCNICOS ==="
input int MA_Fast = 5; // EMA Rápida (períodos)
input int MA_Slow = 10; // EMA Lenta (períodos)
input int RSI_Period = 7; // RSI Período
input int RSI_Overbought = 75; // RSI Sobrecompra
input int RSI_Oversold = 25; // RSI Sobrevenda
input group "=== GESTÃO DE RISCO ==="
input double MaxSpread = 5.0; // Spread máximo (pips)
input int MaxOrders = 3; // Máximo de ordens simultâneas
input int MinBarsAfterTrade = 3; // Barras mínimas entre trades
input bool UseTrailingStop = true; // Usar Trailing Stop
input int TrailingStop = 5; // Trailing Stop (pips)
input group "=== FILTROS HFT ==="
input bool UseSpeedFilter = true; // Usar filtro de velocidade
input double MinPriceSpeed = 0.0003; // Velocidade mínima do preço
input bool UseTimeFilter = true; // Usar filtro de horário
input int StartHour = 8; // Hora início (GMT)
input int EndHour = 17; // Hora fim (GMT)
input group "=== CONFIGURAÇÕES AVANÇADAS ==="
input int Slippage = 3; // Slippage máximo
input bool UseProfitLock = true; // Travar lucro em 5 pips
input int ProfitLockPips = 5; // Pips para travar lucro
input bool ReduceLotAfterLoss = true; // Reduzir lote após perdas
input int MaxConsecutiveLosses = 3; // Perdas consecutivas máximas
//--- Variáveis globais
int ema_fast_handle;
int ema_slow_handle;
int rsi_handle;
double ema_fast[];
double ema_slow[];
double rsi[];
datetime last_trade_time = 0;
int consecutive_losses = 0;
bool profit_locked = false;
double current_lot_size;
//--- Estrutura para controle de velocidade
struct PriceSpeed {
double last_price;
datetime last_time;
double speed;
};
PriceSpeed price_speed;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Verificar se o símbolo é XAU/USD
if(Symbol() != "XAUUSD" && Symbol() != "GOLD" && Symbol() != "XAU/USD")
{
Alert("ERRO: Este EA funciona apenas com XAU/USD (GOLD)!");
return(INIT_FAILED);
}
// Verificar timeframe
if(_Period != PERIOD_M1)
{
Alert("AVISO: EA otimizado para timeframe M1. Timeframe atual: ", EnumToString(_Period));
}
// Inicializar handles dos indicadores
ema_fast_handle = iMA(Symbol(), PERIOD_M1, MA_Fast, 0, MODE_EMA, PRICE_CLOSE);
ema_slow_handle = iMA(Symbol(), PERIOD_M1, MA_Slow, 0, MODE_EMA, PRICE_CLOSE);
rsi_handle = iRSI(Symbol(), PERIOD_M1, RSI_Period, PRICE_CLOSE);
if(ema_fast_handle == INVALID_HANDLE || ema_slow_handle == INVALID_HANDLE || rsi_handle == INVALID_HANDLE)
{
Alert("ERRO: Falha ao criar handles dos indicadores!");
return(INIT_FAILED);
}
// Configurar arrays
ArraySetAsSeries(ema_fast, true);
ArraySetAsSeries(ema_slow, true);
ArraySetAsSeries(rsi, true);
// Inicializar variáveis
current_lot_size = LotSize;
price_speed.last_price = SymbolInfoDouble(Symbol(), SYMBOL_BID);
price_speed.last_time = TimeCurrent();
Print("XAU/USD HFT Scalper v2.0 inicializado com sucesso!");
Print("Símbolo: ", Symbol(), " | Timeframe: M1");
Print("Lote: ", current_lot_size, " | SL: ", StopLoss, " | TP: ", TakeProfit);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Print("EA finalizado. Motivo: ", reason);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Atualizar velocidade do preço
UpdatePriceSpeed();
// Verificar filtros básicos
if(!CheckBasicFilters()) return;
// Atualizar indicadores
if(!UpdateIndicators()) return;
// Gerenciar posições abertas
ManageOpenPositions();
// Verificar novas oportunidades de entrada
CheckEntrySignals();
}
//+------------------------------------------------------------------+
//| Atualizar velocidade do preço |
//+------------------------------------------------------------------+
void UpdatePriceSpeed()
{
double current_price = SymbolInfoDouble(Symbol(), SYMBOL_BID);
datetime current_time = TimeCurrent();
if(price_speed.last_time > 0)
{
double price_change = MathAbs(current_price - price_speed.last_price);
double time_diff = (double)(current_time - price_speed.last_time);
if(time_diff > 0)
price_speed.speed = price_change / time_diff;
}
price_speed.last_price = current_price;
price_speed.last_time = current_time;
}
//+------------------------------------------------------------------+
//| Verificar filtros básicos |
//+------------------------------------------------------------------+
bool CheckBasicFilters()
{
// Filtro de spread
double spread = SymbolInfoInteger(Symbol(), SYMBOL_SPREAD) * SymbolInfoDouble(Symbol(), SYMBOL_POINT);
if(spread > MaxSpread * GetPipSize()) return false;
// Filtro de horário
if(UseTimeFilter)
{
MqlDateTime time_struct;
TimeToStruct(TimeCurrent(), time_struct);
if(time_struct.hour < StartHour || time_struct.hour >= EndHour) return false;
}
// Filtro de velocidade do preço
if(UseSpeedFilter && price_speed.speed < MinPriceSpeed) return false;
// Verificar máximo de ordens
if(CountOpenPositions() >= MaxOrders) return false;
// Verificar intervalo entre trades
if(TimeCurrent() - last_trade_time < MinBarsAfterTrade * 60) return false;
return true;
}
//+------------------------------------------------------------------+
//| Atualizar indicadores |
//+------------------------------------------------------------------+
bool UpdateIndicators()
{
if(CopyBuffer(ema_fast_handle, 0, 0, 3, ema_fast) < 0) return false;
if(CopyBuffer(ema_slow_handle, 0, 0, 3, ema_slow) < 0) return false;
if(CopyBuffer(rsi_handle, 0, 0, 3, rsi) < 0) return false;
return true;
}
//+------------------------------------------------------------------+
//| Verificar sinais de entrada |
//+------------------------------------------------------------------+
void CheckEntrySignals()
{
double bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
double ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
// Sinal de compra
if(CheckBuySignal())
{
double sl = bid - StopLoss * GetPipSize();
double tp = bid + TakeProfit * GetPipSize();
if(OpenPosition(ORDER_TYPE_BUY, current_lot_size, ask, sl, tp))
{
last_trade_time = TimeCurrent();
profit_locked = false;
}
}
// Sinal de venda
else if(CheckSellSignal())
{
double sl = ask + StopLoss * GetPipSize();
double tp = ask - TakeProfit * GetPipSize();
if(OpenPosition(ORDER_TYPE_SELL, current_lot_size, bid, sl, tp))
{
last_trade_time = TimeCurrent();
profit_locked = false;
}
}
}
//+------------------------------------------------------------------+
//| Verificar sinal de compra |
//+------------------------------------------------------------------+
bool CheckBuySignal()
{
double bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
// Condições de compra
bool ema_bullish = (ema_fast[0] > ema_slow[0]) ||
(ema_fast[1] <= ema_slow[1] && ema_fast[0] > ema_slow[0]); // Cruzamento bullish
bool price_above_ema = bid > ema_fast[0];
bool rsi_ok = rsi[0] > RSI_Oversold && rsi[0] < RSI_Overbought;
bool momentum = ema_fast[0] > ema_fast[1]; // Momentum ascendente
return ema_bullish && price_above_ema && rsi_ok && momentum;
}
//+------------------------------------------------------------------+
//| Verificar sinal de venda |
//+------------------------------------------------------------------+
bool CheckSellSignal()
{
double bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
// Condições de venda
bool ema_bearish = (ema_fast[0] < ema_slow[0]) ||
(ema_fast[1] >= ema_slow[1] && ema_fast[0] < ema_slow[0]); // Cruzamento bearish
bool price_below_ema = bid < ema_fast[0];
bool rsi_ok = rsi[0] > RSI_Oversold && rsi[0] < RSI_Overbought;
bool momentum = ema_fast[0] < ema_fast[1]; // Momentum descendente
return ema_bearish && price_below_ema && rsi_ok && momentum;
}
//+------------------------------------------------------------------+
//| Abrir posição |
//+------------------------------------------------------------------+
bool OpenPosition(ENUM_ORDER_TYPE type, double volume, double price, double sl, double tp)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = Symbol();
request.volume = volume;
request.type = type;
request.price = price;
request.sl = sl;
request.tp = tp;
request.deviation = Slippage;
request.magic = Magic;
request.comment = "HFT Scalper v2.0";
bool success = OrderSend(request, result);
if(success)
{
Print("Posição aberta: ", EnumToString(type), " | Volume: ", volume,
" | Preço: ", price, " | SL: ", sl, " | TP: ", tp);
}
else
{
Print("ERRO ao abrir posição: ", result.retcode, " - ", result.comment);
// Ajustar lote após falhas consecutivas
if(ReduceLotAfterLoss)
{
consecutive_losses++;
if(consecutive_losses >= MaxConsecutiveLosses)
{
current_lot_size = MathMax(current_lot_size * 0.5, SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MIN));
consecutive_losses = 0;
Print("Lote reduzido para: ", current_lot_size);
}
}
}
return success;
}
//+------------------------------------------------------------------+
//| Gerenciar posições abertas |
//+------------------------------------------------------------------+
void ManageOpenPositions()
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(PositionGetSymbol(i) == Symbol() && PositionGetInteger(POSITION_MAGIC) == Magic)
{
ulong ticket = PositionGetInteger(POSITION_TICKET);
ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
double open_price = PositionGetDouble(POSITION_PRICE_OPEN);
double current_price = (type == POSITION_TYPE_BUY) ?
SymbolInfoDouble(Symbol(), SYMBOL_BID) :
SymbolInfoDouble(Symbol(), SYMBOL_ASK);
double profit_pips = GetProfitInPips(type, open_price, current_price);
// Trailing Stop
if(UseTrailingStop && profit_pips > TrailingStop)
{
ApplyTrailingStop(ticket, type, current_price);
}
// Travamento de lucro
if(UseProfitLock && !profit_locked && profit_pips >= ProfitLockPips)
{
LockProfit(ticket, type, open_price);
profit_locked = true;
}
}
}
}
//+------------------------------------------------------------------+
//| Aplicar trailing stop |
//+------------------------------------------------------------------+
void ApplyTrailingStop(ulong ticket, ENUM_POSITION_TYPE type, double current_price)
{
double new_sl;
double current_sl = PositionGetDouble(POSITION_SL);
if(type == POSITION_TYPE_BUY)
{
new_sl = current_price - TrailingStop * GetPipSize();
if(new_sl > current_sl + GetPipSize())
{
ModifyPosition(ticket, new_sl, PositionGetDouble(POSITION_TP));
}
}
else
{
new_sl = current_price + TrailingStop * GetPipSize();
if(new_sl < current_sl - GetPipSize() || current_sl == 0)
{
ModifyPosition(ticket, new_sl, PositionGetDouble(POSITION_TP));
}
}
}
//+------------------------------------------------------------------+
//| Travar lucro |
//+------------------------------------------------------------------+
void LockProfit(ulong ticket, ENUM_POSITION_TYPE type, double open_price)
{
double lock_sl;
if(type == POSITION_TYPE_BUY)
lock_sl = open_price + (ProfitLockPips / 2) * GetPipSize();
else
lock_sl = open_price - (ProfitLockPips / 2) * GetPipSize();
ModifyPosition(ticket, lock_sl, PositionGetDouble(POSITION_TP));
Print("Lucro travado para posição: ", ticket);
}
//+------------------------------------------------------------------+
//| Modificar posição |
//+------------------------------------------------------------------+
void ModifyPosition(ulong ticket, double sl, double tp)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_SLTP;
request.position = ticket;
request.sl = sl;
request.tp = tp;
OrderSend(request, result);
}
//+------------------------------------------------------------------+
//| Contar posições abertas |
//+------------------------------------------------------------------+
int CountOpenPositions()
{
int count = 0;
for(int i = 0; i < PositionsTotal(); i++)
{
if(PositionGetSymbol(i) == Symbol() && PositionGetInteger(POSITION_MAGIC) == Magic)
count++;
}
return count;
}
//+------------------------------------------------------------------+
//| Obter tamanho do pip |
//+------------------------------------------------------------------+
double GetPipSize()
{
double point = SymbolInfoDouble(Symbol(), SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(Symbol(), SYMBOL_DIGITS);
if(digits == 5 || digits == 3)
return point * 10;
else
return point;
}
//+------------------------------------------------------------------+
//| Calcular lucro em pips |
//+------------------------------------------------------------------+
double GetProfitInPips(ENUM_POSITION_TYPE type, double open_price, double current_price)
{
double diff = (type == POSITION_TYPE_BUY) ?
current_price - open_price :
open_price - current_price;
return diff / GetPipSize();
}
//+------------------------------------------------------------------+
//| Função de evento OnTradeTransaction |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
const MqlTradeRequest& request,
const MqlTradeResult& result)
{
if(trans.symbol == Symbol() && request.magic == Magic)
{
if(trans.type == TRADE_TRANSACTION_DEAL_ADD)
{
if(trans.deal_type == DEAL_TYPE_BUY || trans.deal_type == DEAL_TYPE_SELL)
{
Print("Deal executado: Ticket=", trans.deal,
" | Tipo=", EnumToString(trans.deal_type),
" | Volume=", trans.volume,
" | Preço=", trans.price);
// Resetar contador de perdas em caso de sucesso
if(trans.deal_type == DEAL_TYPE_BUY || trans.deal_type == DEAL_TYPE_SELL)
{
consecutive_losses = 0;
current_lot_size = LotSize; // Resetar lote
}
}
}
}
}