//+------------------------------------------------------------------+ //| 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ô Scalper WinQ25 - Perfil CONSERVADOR - Mercado Brasileiro BMF" //--- Includes #include #include #include //--- Objetos globais CTrade trade; CPositionInfo position; CAccountInfo account; //+------------------------------------------------------------------+ //| Parâmetros CONSERVADORES pré-configurados | //+------------------------------------------------------------------+ input group "=== PERFIL CONSERVADOR ===" input string InfoPerfil = "Baixo risco, operações menores"; input group "=== CONFIGURAÇÕES BÁSICAS ===" input double LotePadrao = 1.0; // Lote padrão para baixa volatilidade input double LoteAltaVolatilidade = 2.0; // Lote para alta volatilidade input int TakeProfitPadrao = 30; // Take Profit padrão (pontos) input int TakeProfitAltaVol = 80; // Take Profit alta volatilidade (pontos) input int MagicNumber = 111111; // Número mágico (conservador) input string Simbolo = "WINQ25"; // Símbolo a ser operado input group "=== GESTÃO DE RISCO CONSERVADORA ===" input double RiscoMaximoDiario = 1.0; // Risco máximo diário (% do saldo) input int MaxOperacoesPerdedoras = 2; // Máximo de operações perdedoras consecutivas input int MaxTradesPorDia = 10; // Má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íodo da média móvel input double MinimoPontosMovimento = 40.0; // Mínimo de pontos para considerar movimento input int VelasAnalise = 5; // Número de velas para análise (mais confirmação) input group "=== HORÁRIOS DE TRADING ===" input bool OperarAberturaBMF = true; // Operar abertura BMF (09:15-10:00) input bool OperarAberturaBovespa = false; // NÃO operar abertura Bovespa (muito volátil) input bool OperarAberturaEUA = false; // NÃO operar abertura EUA (muito volátil) input bool OperarTarde = true; // Operar período tarde (14:00-16:45) input bool OperarFechamento = false; // NÃO operar fechamento (muito volátil) //+------------------------------------------------------------------+ //| Variá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ção de inicialização | //+------------------------------------------------------------------+ int OnInit() { //--- Configurar Magic Number trade.SetExpertMagicNumber(MagicNumber); //--- Criar handle da média móvel handleMA = iMA(Simbolo, PERIOD_M1, PeriodoMedia, 0, MODE_SMA, PRICE_CLOSE); if(handleMA == INVALID_HANDLE) { Print("Erro ao criar handle da média móvel"); return INIT_FAILED; } //--- Inicializar dados do dia InicializarDadosDia(); Print("=== WinQ25 Scalper CONSERVADOR ==="); Print("✅ Robô inicializado com sucesso!"); Print("📊 Perfil: CONSERVADOR (Baixo Risco)"); Print("💰 Lote padrão: ", LotePadrao); Print("🎯 Take Profit padrão: ", TakeProfitPadrao, " pontos"); Print("🛡️ Risco máximo diário: ", RiscoMaximoDiario, "%"); Print("⏰ Horários ativos: BMF + Tarde (horários menos voláteis)"); return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Função de desinicialização | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Liberar handles if(handleMA != INVALID_HANDLE) IndicatorRelease(handleMA); Print("WinQ25 Scalper CONSERVADOR finalizado. Motivo: ", reason); } //+------------------------------------------------------------------+ //| Função principal - executada a cada tick | //+------------------------------------------------------------------+ void OnTick() { //--- Verificar se é um novo dia if(VerificarNovoDia()) { InicializarDadosDia(); } //--- Verificar se trading está permitido if(!TradingPermitido()) return; //--- Verificar horário de trading if(!HorarioTradingPermitido()) return; //--- Verificar se já temos posição aberta if(TemPosicaoAberta()) { GerenciarPosicao(); return; } //--- Procurar oportunidades de entrada (mais conservadora) AnalisarEntradaConservadora(); } //+------------------------------------------------------------------+ //| Verificar se é 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("🛡️ Perda máxima permitida: R$ ", DoubleToString(perdaMaximaDia, 2)); Print("📈 Estratégia: Conservadora (foco em segurança)"); } //+------------------------------------------------------------------+ //| Verificar se trading está permitido | //+------------------------------------------------------------------+ bool TradingPermitido() { //--- Verificar se trading foi desabilitado por gestão de risco if(!tradingPermitido) return false; //--- Verificar máximo de trades por dia if(tradesHoje >= MaxTradesPorDia) { if(tradesHoje == MaxTradesPorDia) { Print("🛑 Máximo de trades CONSERVADOR por dia atingido: ", MaxTradesPorDia); tradingPermitido = false; } return false; } //--- Verificar máximo de operações perdedoras consecutivas (mais restritivo) if(tradesPerdedoresConsecutivos >= MaxOperacoesPerdedoras) { Print("⚠️ Máximo de operações perdedoras CONSERVADOR atingido: ", MaxOperacoesPerdedoras); Print("🛡️ Parando trading por segurança até amanhã"); tradingPermitido = false; return false; } //--- Verificar perda máxima diária double perdaAtual = saldoInicialDia - account.Balance(); if(perdaAtual >= perdaMaximaDia) { Print("🚨 ATENÇÃO: Perda máxima CONSERVADORA atingida: R$ ", DoubleToString(perdaAtual, 2)); Print("🛑 Trading interrompido por segurança!"); tradingPermitido = false; return false; } return true; } //+------------------------------------------------------------------+ //| Verificar horário de trading permitido (CONSERVADOR) | //+------------------------------------------------------------------+ bool HorarioTradingPermitido() { MqlDateTime dt; TimeToStruct(TimeCurrent(), dt); //--- Verificar se é dia ú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ários CONSERVADORES (evita alta volatilidade) // 09:30-09:45: Apenas 15 min após abertura BMF (mais seguro) if(OperarAberturaBMF && horaMinuto >= 930 && horaMinuto < 945) return true; // 14:30-16:30: Período da tarde (menos volátil) if(OperarTarde && horaMinuto >= 1430 && horaMinuto < 1630) return true; return false; } //+------------------------------------------------------------------+ //| Verificar se tem posição aberta | //+------------------------------------------------------------------+ bool TemPosicaoAberta() { return position.SelectByMagic(Simbolo, MagicNumber); } //+------------------------------------------------------------------+ //| Gerenciar posição aberta | //+------------------------------------------------------------------+ void GerenciarPosicao() { if(!position.SelectByMagic(Simbolo, MagicNumber)) return; //--- Gestão conservadora: breakeven mais rá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("🔒 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("🔒 Breakeven CONSERVADOR ativado na venda"); } } } //+------------------------------------------------------------------+ //| Analisar entrada CONSERVADORA | //+------------------------------------------------------------------+ void AnalisarEntradaConservadora() { //--- Obter mais velas para análise conservadora MqlRates velas[]; if(CopyRates(Simbolo, PERIOD_M1, 0, VelasAnalise + 3, velas) <= 0) return; //--- Obter dados da média móvel double ma[]; if(CopyBuffer(handleMA, 0, 0, VelasAnalise + 3, ma) <= 0) return; ArraySetAsSeries(velas, true); ArraySetAsSeries(ma, true); //--- Análise CONSERVADORA (mais filtros) ENUM_ORDER_TYPE tipoOrdem = AnalisarPriceActionConservador(velas, ma); if(tipoOrdem == ORDER_TYPE_BUY || tipoOrdem == ORDER_TYPE_SELL) { ExecutarOrdemConservadora(tipoOrdem); } } //+------------------------------------------------------------------+ //| Análise Price Action CONSERVADORA | //+------------------------------------------------------------------+ ENUM_ORDER_TYPE AnalisarPriceActionConservador(const MqlRates &velas[], const double &ma[]) { double precoAtual = SymbolInfoDouble(Simbolo, SYMBOL_BID); //--- Verificar movimento mí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áximo de 2 pontos //--- Análise mais conservadora baseada na média móvel bool acimaDaMedia = precoAtual > ma[0]; bool tendenciaAlta = ma[0] > ma[1] && ma[1] > ma[2] && ma[2] > ma[3]; // Tendência mais confirmada bool tendenciaBaixa = ma[0] < ma[1] && ma[1] < ma[2] && ma[2] < ma[3]; //--- Verificar volatilidade nã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átil (>100 pontos média) ou muito parado (<20 pontos) if(volatilidadePontos > 100.0 || volatilidadePontos < 20.0) return -1; //--- Padrão CONSERVADOR de compra if(acimaDaMedia && tendenciaAlta) { // Precisar de 2 velas consecutivas na direção bool sequenciaAlta = velas[1].close > velas[1].open && velas[0].close > velas[0].open; // E preço não muito longe da média double distanciaMedia = MathAbs(precoAtual - ma[0]) / pontoValor; if(sequenciaAlta && distanciaMedia < 50.0) return ORDER_TYPE_BUY; } //--- Padrão CONSERVADOR de venda if(!acimaDaMedia && tendenciaBaixa) { // Precisar de 2 velas consecutivas na direção bool sequenciaBaixa = velas[1].close < velas[1].open && velas[0].close < velas[0].open; // E preço não muito longe da mé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ÇÃO CONSERVADORA ==="); Print("🔵 Tipo: ", (tipo == ORDER_TYPE_BUY) ? "COMPRA" : "VENDA"); Print("💎 Lote: ", lote, " (sempre conservador)"); Print("💰 Preço: ", preco); Print("🎯 Take Profit: ", precoTP, " (", tp, " pontos)"); Print("🛡️ Stop Loss: ", precoSL, " (", sl, " pontos - conservador)"); Print("📊 Trade nº: ", tradesHoje, "/", MaxTradesPorDia); Print("⚡ Perfil: CONSERVADOR (baixo risco)"); } else { Print("❌ Erro ao executar ordem conservadora: ", trade.ResultRetcode()); } } //+------------------------------------------------------------------+ //| Função chamada quando há negociação | //+------------------------------------------------------------------+ void OnTrade() { //--- Verificar se a posição foi fechada if(!TemPosicaoAberta()) { //--- Analisar resultado da última operação HistorySelect(TimeCurrent() - 86400, TimeCurrent()); // Ú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égia conservadora funcionando!"); } else { tradesPerdedoresConsecutivos++; Print("=== TRADE PERDEDOR CONSERVADOR ==="); Print("🔴 Perda: R$ ", DoubleToString(lucro, 2)); Print("⚠️ Perdedores consecutivos: ", tradesPerdedoresConsecutivos, "/", MaxOperacoesPerdedoras); if(tradesPerdedoresConsecutivos >= MaxOperacoesPerdedoras) { Print("🛑 ATENÇÃO: Limite conservador de perdas atingido!"); Print("🛡️ Trading suspenso até amanhã por segurança"); } } //--- Estatí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ÍSTICAS CONSERVADOR ==="); Print("📊 Trades realizados: ", tradesHoje, "/", MaxTradesPorDia); Print("✅ Trades vencedores: ", tradesVencedoresHoje); Print("📈 Win Rate: ", DoubleToString(winRate, 2), "%"); Print("💰 Saldo atual: R$ ", DoubleToString(account.Balance(), 2)); Print("📉 Perda atual: ", DoubleToString(perdaPercentual, 2), "%/", RiscoMaximoDiario, "%"); Print("🔵 Perfil: CONSERVADOR - Prioriza segurança"); } } } }