This repository has been archived on 2026-01-19. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
Scalper-WINQ25/WinQ25_Scalper_Conservador.mq5

500 lines
39 KiB
MQL5
Raw Permalink Normal View History

2026-01-19 20:16:10 -03:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| WinQ25_Scalper_Conservador.mq5 |
//| Copyright 2024, Scalper Trading Bot |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Scalper Trading Bot"
#property link "https://www.mql5.com"
#property version "1.00"
#property description "Rob<00> Scalper WinQ25 - Perfil CONSERVADOR - Mercado Brasileiro BMF"
//--- Includes
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\AccountInfo.mqh>
//--- Objetos globais
CTrade trade;
CPositionInfo position;
CAccountInfo account;
//+------------------------------------------------------------------+
//| Par<EFBFBD>metros CONSERVADORES pr<EFBFBD>-configurados |
//+------------------------------------------------------------------+
input group "=== PERFIL CONSERVADOR ==="
input string InfoPerfil = "Baixo risco, opera<00><00>es menores";
input group "=== CONFIGURA<00><00>ES B<00>SICAS ==="
input double LotePadrao = 1.0; // Lote padr<EFBFBD>o para baixa volatilidade
input double LoteAltaVolatilidade = 2.0; // Lote para alta volatilidade
input int TakeProfitPadrao = 30; // Take Profit padr<EFBFBD>o (pontos)
input int TakeProfitAltaVol = 80; // Take Profit alta volatilidade (pontos)
input int MagicNumber = 111111; // N<EFBFBD>mero m<EFBFBD>gico (conservador)
input string Simbolo = "WINQ25"; // S<EFBFBD>mbolo a ser operado
input group "=== GEST<00>O DE RISCO CONSERVADORA ==="
input double RiscoMaximoDiario = 1.0; // Risco m<EFBFBD>ximo di<EFBFBD>rio (% do saldo)
input int MaxOperacoesPerdedoras = 2; // M<EFBFBD>ximo de opera<EFBFBD><EFBFBD>es perdedoras consecutivas
input int MaxTradesPorDia = 10; // M<EFBFBD>ximo de trades por dia
input double StopLossPercentual = 50.0; // Stop Loss como % do Take Profit
input group "=== PRICE ACTION CONSERVADOR ==="
input int PeriodoMedia = 20; // Per<EFBFBD>odo da m<EFBFBD>dia m<EFBFBD>vel
input double MinimoPontosMovimento = 40.0; // M<EFBFBD>nimo de pontos para considerar movimento
input int VelasAnalise = 5; // N<EFBFBD>mero de velas para an<EFBFBD>lise (mais confirma<EFBFBD><EFBFBD>o)
input group "=== HOR<00>RIOS DE TRADING ==="
input bool OperarAberturaBMF = true; // Operar abertura BMF (09:15-10:00)
input bool OperarAberturaBovespa = false; // N<EFBFBD>O operar abertura Bovespa (muito vol<EFBFBD>til)
input bool OperarAberturaEUA = false; // N<EFBFBD>O operar abertura EUA (muito vol<EFBFBD>til)
input bool OperarTarde = true; // Operar per<EFBFBD>odo tarde (14:00-16:45)
input bool OperarFechamento = false; // N<EFBFBD>O operar fechamento (muito vol<EFBFBD>til)
//+------------------------------------------------------------------+
//| Vari<EFBFBD>veis globais |
//+------------------------------------------------------------------+
datetime ultimoDia = 0;
int tradesHoje = 0;
int tradesVencedoresHoje = 0;
int tradesPerdedoresConsecutivos = 0;
double saldoInicialDia = 0;
double perdaMaximaDia = 0;
bool tradingPermitido = true;
//--- Handles dos indicadores
int handleMA;
//+------------------------------------------------------------------+
//| Fun<EFBFBD><EFBFBD>o de inicializa<EFBFBD><EFBFBD>o |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Configurar Magic Number
trade.SetExpertMagicNumber(MagicNumber);
//--- Criar handle da m<EFBFBD>dia m<EFBFBD>vel
handleMA = iMA(Simbolo, PERIOD_M1, PeriodoMedia, 0, MODE_SMA, PRICE_CLOSE);
if(handleMA == INVALID_HANDLE)
{
Print("Erro ao criar handle da m<00>dia m<00>vel");
return INIT_FAILED;
}
//--- Inicializar dados do dia
InicializarDadosDia();
Print("=== WinQ25 Scalper CONSERVADOR ===");
Print("' Rob<00> inicializado com sucesso!");
Print("=<3D><><EFBFBD> Perfil: CONSERVADOR (Baixo Risco)");
Print("<> Lote padr<00>o: ", LotePadrao);
Print("<> Take Profit padr<00>o: ", TakeProfitPadrao, " pontos");
Print("=<3D><><EFBFBD><0F> Risco m<00>ximo di<00>rio: ", RiscoMaximoDiario, "%");
Print("<00># Hor<00>rios ativos: BMF + Tarde (hor<00>rios menos vol<00>teis)");
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Fun<EFBFBD><EFBFBD>o de desinicializa<EFBFBD><EFBFBD>o |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- Liberar handles
if(handleMA != INVALID_HANDLE)
IndicatorRelease(handleMA);
Print("WinQ25 Scalper CONSERVADOR finalizado. Motivo: ", reason);
}
//+------------------------------------------------------------------+
//| Fun<EFBFBD><EFBFBD>o principal - executada a cada tick |
//+------------------------------------------------------------------+
void OnTick()
{
//--- Verificar se <EFBFBD> um novo dia
if(VerificarNovoDia())
{
InicializarDadosDia();
}
//--- Verificar se trading est<EFBFBD> permitido
if(!TradingPermitido())
return;
//--- Verificar hor<EFBFBD>rio de trading
if(!HorarioTradingPermitido())
return;
//--- Verificar se j<EFBFBD> temos posi<EFBFBD><EFBFBD>o aberta
if(TemPosicaoAberta())
{
GerenciarPosicao();
return;
}
//--- Procurar oportunidades de entrada (mais conservadora)
AnalisarEntradaConservadora();
}
//+------------------------------------------------------------------+
//| Verificar se <EFBFBD> um novo dia |
//+------------------------------------------------------------------+
bool VerificarNovoDia()
{
datetime agora = TimeCurrent();
MqlDateTime dt;
TimeToStruct(agora, dt);
datetime diaAtual = StringToTime(StringFormat("%04d.%02d.%02d 00:00", dt.year, dt.mon, dt.day));
if(ultimoDia != diaAtual)
{
ultimoDia = diaAtual;
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Inicializar dados do dia |
//+------------------------------------------------------------------+
void InicializarDadosDia()
{
tradesHoje = 0;
tradesVencedoresHoje = 0;
tradesPerdedoresConsecutivos = 0;
saldoInicialDia = account.Balance();
perdaMaximaDia = saldoInicialDia * (RiscoMaximoDiario / 100.0);
tradingPermitido = true;
Print("=== NOVO DIA DE TRADING CONSERVADOR ===");
Print("<> Saldo inicial: R$ ", DoubleToString(saldoInicialDia, 2));
Print("=<3D><><EFBFBD><0F> Perda m<00>xima permitida: R$ ", DoubleToString(perdaMaximaDia, 2));
Print("=<3D><><EFBFBD> Estrat<00>gia: Conservadora (foco em seguran<00>a)");
}
//+------------------------------------------------------------------+
//| Verificar se trading est<EFBFBD> permitido |
//+------------------------------------------------------------------+
bool TradingPermitido()
{
//--- Verificar se trading foi desabilitado por gest<EFBFBD>o de risco
if(!tradingPermitido)
return false;
//--- Verificar m<EFBFBD>ximo de trades por dia
if(tradesHoje >= MaxTradesPorDia)
{
if(tradesHoje == MaxTradesPorDia)
{
Print("=<3D><><EFBFBD> M<00>ximo de trades CONSERVADOR por dia atingido: ", MaxTradesPorDia);
tradingPermitido = false;
}
return false;
}
//--- Verificar m<EFBFBD>ximo de opera<EFBFBD><EFBFBD>es perdedoras consecutivas (mais restritivo)
if(tradesPerdedoresConsecutivos >= MaxOperacoesPerdedoras)
{
Print("<00>&<0F> M<00>ximo de opera<00><00>es perdedoras CONSERVADOR atingido: ", MaxOperacoesPerdedoras);
Print("=<3D><><EFBFBD><0F> Parando trading por seguran<00>a at<00> amanh<00>");
tradingPermitido = false;
return false;
}
//--- Verificar perda m<EFBFBD>xima di<EFBFBD>ria
double perdaAtual = saldoInicialDia - account.Balance();
if(perdaAtual >= perdaMaximaDia)
{
Print("<> ATEN<00><00>O: Perda m<00>xima CONSERVADORA atingida: R$ ", DoubleToString(perdaAtual, 2));
Print("=<3D><><EFBFBD> Trading interrompido por seguran<00>a!");
tradingPermitido = false;
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Verificar hor<EFBFBD>rio de trading permitido (CONSERVADOR) |
//+------------------------------------------------------------------+
bool HorarioTradingPermitido()
{
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
//--- Verificar se <EFBFBD> dia <EFBFBD>til (Segunda a Sexta)
if(dt.day_of_week == 0 || dt.day_of_week == 6)
return false;
int hora = dt.hour;
int minuto = dt.min;
int horaMinuto = hora * 100 + minuto;
//--- Hor<EFBFBD>rios CONSERVADORES (evita alta volatilidade)
// 09:30-09:45: Apenas 15 min ap<EFBFBD>s abertura BMF (mais seguro)
if(OperarAberturaBMF && horaMinuto >= 930 && horaMinuto < 945)
return true;
// 14:30-16:30: Per<EFBFBD>odo da tarde (menos vol<EFBFBD>til)
if(OperarTarde && horaMinuto >= 1430 && horaMinuto < 1630)
return true;
return false;
}
//+------------------------------------------------------------------+
//| Verificar se tem posi<EFBFBD><EFBFBD>o aberta |
//+------------------------------------------------------------------+
bool TemPosicaoAberta()
{
return position.SelectByMagic(Simbolo, MagicNumber);
}
//+------------------------------------------------------------------+
//| Gerenciar posi<EFBFBD><EFBFBD>o aberta |
//+------------------------------------------------------------------+
void GerenciarPosicao()
{
if(!position.SelectByMagic(Simbolo, MagicNumber))
return;
//--- Gest<EFBFBD>o conservadora: breakeven mais r<EFBFBD>pido
double precoEntrada = position.PriceOpen();
double precoAtual = (position.PositionType() == POSITION_TYPE_BUY) ?
SymbolInfoDouble(Simbolo, SYMBOL_BID) :
SymbolInfoDouble(Simbolo, SYMBOL_ASK);
double ponto = SymbolInfoDouble(Simbolo, SYMBOL_POINT);
double breakeven = 15 * ponto; // Breakeven com apenas 15 pontos de lucro
if(position.PositionType() == POSITION_TYPE_BUY)
{
if(precoAtual >= precoEntrada + breakeven && position.StopLoss() < precoEntrada)
{
trade.PositionModify(position.Ticket(), precoEntrada + (5 * ponto), position.TakeProfit());
Print("=<3D><12> Breakeven CONSERVADOR ativado na compra");
}
}
else if(position.PositionType() == POSITION_TYPE_SELL)
{
if(precoAtual <= precoEntrada - breakeven && position.StopLoss() > precoEntrada)
{
trade.PositionModify(position.Ticket(), precoEntrada - (5 * ponto), position.TakeProfit());
Print("=<3D><12> Breakeven CONSERVADOR ativado na venda");
}
}
}
//+------------------------------------------------------------------+
//| Analisar entrada CONSERVADORA |
//+------------------------------------------------------------------+
void AnalisarEntradaConservadora()
{
//--- Obter mais velas para an<EFBFBD>lise conservadora
MqlRates velas[];
if(CopyRates(Simbolo, PERIOD_M1, 0, VelasAnalise + 3, velas) <= 0)
return;
//--- Obter dados da m<EFBFBD>dia m<EFBFBD>vel
double ma[];
if(CopyBuffer(handleMA, 0, 0, VelasAnalise + 3, ma) <= 0)
return;
ArraySetAsSeries(velas, true);
ArraySetAsSeries(ma, true);
//--- An<EFBFBD>lise CONSERVADORA (mais filtros)
ENUM_ORDER_TYPE tipoOrdem = AnalisarPriceActionConservador(velas, ma);
if(tipoOrdem == ORDER_TYPE_BUY || tipoOrdem == ORDER_TYPE_SELL)
{
ExecutarOrdemConservadora(tipoOrdem);
}
}
//+------------------------------------------------------------------+
//| An<EFBFBD>lise Price Action CONSERVADORA |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE AnalisarPriceActionConservador(const MqlRates &velas[], const double &ma[])
{
double precoAtual = SymbolInfoDouble(Simbolo, SYMBOL_BID);
//--- Verificar movimento m<EFBFBD>nimo (mais restritivo)
double range = velas[0].high - velas[0].low;
if(range < MinimoPontosMovimento * SymbolInfoDouble(Simbolo, SYMBOL_POINT))
return -1;
//--- Verificar spread (conservador)
double ask = SymbolInfoDouble(Simbolo, SYMBOL_ASK);
double bid = SymbolInfoDouble(Simbolo, SYMBOL_BID);
double spread = (ask - bid) / SymbolInfoDouble(Simbolo, SYMBOL_POINT);
if(spread > 2.0) return -1; // Spread m<EFBFBD>ximo de 2 pontos
//--- An<EFBFBD>lise mais conservadora baseada na m<EFBFBD>dia m<EFBFBD>vel
bool acimaDaMedia = precoAtual > ma[0];
bool tendenciaAlta = ma[0] > ma[1] && ma[1] > ma[2] && ma[2] > ma[3]; // Tend<EFBFBD>ncia mais confirmada
bool tendenciaBaixa = ma[0] < ma[1] && ma[1] < ma[2] && ma[2] < ma[3];
//--- Verificar volatilidade n<EFBFBD>o excessiva
double volatilidade = 0;
for(int i = 0; i < 5; i++)
volatilidade += (velas[i].high - velas[i].low);
volatilidade /= 5.0;
double pontoValor = SymbolInfoDouble(Simbolo, SYMBOL_POINT);
double volatilidadePontos = volatilidade / pontoValor;
// Evitar mercado muito vol<EFBFBD>til (>100 pontos m<EFBFBD>dia) ou muito parado (<20 pontos)
if(volatilidadePontos > 100.0 || volatilidadePontos < 20.0)
return -1;
//--- Padr<EFBFBD>o CONSERVADOR de compra
if(acimaDaMedia && tendenciaAlta)
{
// Precisar de 2 velas consecutivas na dire<EFBFBD><EFBFBD>o
bool sequenciaAlta = velas[1].close > velas[1].open && velas[0].close > velas[0].open;
// E pre<EFBFBD>o n<EFBFBD>o muito longe da m<EFBFBD>dia
double distanciaMedia = MathAbs(precoAtual - ma[0]) / pontoValor;
if(sequenciaAlta && distanciaMedia < 50.0)
return ORDER_TYPE_BUY;
}
//--- Padr<EFBFBD>o CONSERVADOR de venda
if(!acimaDaMedia && tendenciaBaixa)
{
// Precisar de 2 velas consecutivas na dire<EFBFBD><EFBFBD>o
bool sequenciaBaixa = velas[1].close < velas[1].open && velas[0].close < velas[0].open;
// E pre<EFBFBD>o n<EFBFBD>o muito longe da m<EFBFBD>dia
double distanciaMedia = MathAbs(precoAtual - ma[0]) / pontoValor;
if(sequenciaBaixa && distanciaMedia < 50.0)
return ORDER_TYPE_SELL;
}
return -1; // Nenhum sinal conservador
}
//+------------------------------------------------------------------+
//| Executar ordem CONSERVADORA |
//+------------------------------------------------------------------+
void ExecutarOrdemConservadora(ENUM_ORDER_TYPE tipo)
{
//--- Sempre usar lote conservador (nunca usar lote alto em perfil conservador)
double lote = LotePadrao;
//--- Take profit conservador
int tp = TakeProfitPadrao;
//--- Stop loss conservador (mais apertado - 40% do TP para ser mais seguro)
int sl = (int)(tp * 0.4);
double preco = (tipo == ORDER_TYPE_BUY) ?
SymbolInfoDouble(Simbolo, SYMBOL_ASK) :
SymbolInfoDouble(Simbolo, SYMBOL_BID);
double ponto = SymbolInfoDouble(Simbolo, SYMBOL_POINT);
double precoTP, precoSL;
if(tipo == ORDER_TYPE_BUY)
{
precoTP = preco + (tp * ponto);
precoSL = preco - (sl * ponto);
}
else
{
precoTP = preco - (tp * ponto);
precoSL = preco + (sl * ponto);
}
//--- Executar ordem
bool resultado = false;
if(tipo == ORDER_TYPE_BUY)
{
resultado = trade.Buy(lote, Simbolo, preco, precoSL, precoTP,
"WinQ25 Scalper CONSERVADOR - Compra");
}
else
{
resultado = trade.Sell(lote, Simbolo, preco, precoSL, precoTP,
"WinQ25 Scalper CONSERVADOR - Venda");
}
if(resultado)
{
tradesHoje++;
Print("=== NOVA OPERA<00><00>O CONSERVADORA ===");
Print("=<3D>5<EFBFBD> Tipo: ", (tipo == ORDER_TYPE_BUY) ? "COMPRA" : "VENDA");
Print("<> Lote: ", lote, " (sempre conservador)");
Print("<> Pre<00>o: ", preco);
Print("<> Take Profit: ", precoTP, " (", tp, " pontos)");
Print("=<3D><><EFBFBD><0F> Stop Loss: ", precoSL, " (", sl, " pontos - conservador)");
Print("=<3D><><EFBFBD> Trade n<00>: ", tradesHoje, "/", MaxTradesPorDia);
Print("<00>& Perfil: CONSERVADOR (baixo risco)");
}
else
{
Print("L' Erro ao executar ordem conservadora: ", trade.ResultRetcode());
}
}
//+------------------------------------------------------------------+
//| Fun<EFBFBD><EFBFBD>o chamada quando h<EFBFBD> negocia<EFBFBD><EFBFBD>o |
//+------------------------------------------------------------------+
void OnTrade()
{
//--- Verificar se a posi<EFBFBD><EFBFBD>o foi fechada
if(!TemPosicaoAberta())
{
//--- Analisar resultado da <EFBFBD>ltima opera<EFBFBD><EFBFBD>o
HistorySelect(TimeCurrent() - 86400, TimeCurrent()); // <EFBFBD>ltimas 24 horas
int totalDeals = HistoryDealsTotal();
if(totalDeals > 0)
{
ulong ticket = HistoryDealGetTicket(totalDeals - 1);
if(HistoryDealGetInteger(ticket, DEAL_MAGIC) == MagicNumber)
{
double lucro = HistoryDealGetDouble(ticket, DEAL_PROFIT);
if(lucro > 0)
{
tradesVencedoresHoje++;
tradesPerdedoresConsecutivos = 0;
Print("=== TRADE VENCEDOR CONSERVADOR ===");
Print("<> Lucro: R$ ", DoubleToString(lucro, 2));
Print("' Estrat<00>gia conservadora funcionando!");
}
else
{
tradesPerdedoresConsecutivos++;
Print("=== TRADE PERDEDOR CONSERVADOR ===");
Print("=<3D>4<EFBFBD> Perda: R$ ", DoubleToString(lucro, 2));
Print("<00>&<0F> Perdedores consecutivos: ", tradesPerdedoresConsecutivos, "/", MaxOperacoesPerdedoras);
if(tradesPerdedoresConsecutivos >= MaxOperacoesPerdedoras)
{
Print("=<3D><><EFBFBD> ATEN<00><00>O: Limite conservador de perdas atingido!");
Print("=<3D><><EFBFBD><0F> Trading suspenso at<00> amanh<00> por seguran<00>a");
}
}
//--- Estat<EFBFBD>sticas do dia
double winRate = (tradesHoje > 0) ? (tradesVencedoresHoje * 100.0 / tradesHoje) : 0;
double perdaAtual = saldoInicialDia - account.Balance();
double perdaPercentual = (saldoInicialDia > 0) ? (perdaAtual * 100.0 / saldoInicialDia) : 0;
Print("=== ESTAT<00>STICAS CONSERVADOR ===");
Print("=<3D><><EFBFBD> Trades realizados: ", tradesHoje, "/", MaxTradesPorDia);
Print("' Trades vencedores: ", tradesVencedoresHoje);
Print("=<3D><><EFBFBD> Win Rate: ", DoubleToString(winRate, 2), "%");
Print("<> Saldo atual: R$ ", DoubleToString(account.Balance(), 2));
Print("=<3D><><EFBFBD> Perda atual: ", DoubleToString(perdaPercentual, 2), "%/", RiscoMaximoDiario, "%");
Print("=<3D>5<EFBFBD> Perfil: CONSERVADOR - Prioriza seguran<00>a");
}
}
}
}