mt5-clear-wing26-scalper/WinFutLib/wing26Lib.mqh

418 lines
27 KiB
MQL5
Raw Permalink Normal View History

2026-01-30 07:34:05 -03:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| wing26Lib.mqh.mq5 |
//| Copyright 2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\AccountInfo.mqh>
#include <WinfutLib\wing26Envs.mqh>
#include <WinFutLib\wing26Config.mqh>
#include <WinFutLib\wing26Indicadores.mqh>
CTrade setMagicNumber(CTrade &trade) {
trade.SetExpertMagicNumber(MagicNumber);
return trade;
}
int setMediaMovel() {
//--- 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;
}
return 1;
}
void setLogsOnInit() {
Print(Simbolo +" Scalper Clear inicializado com sucesso!");
Print("Lote padr<00>o: ", LotePadrao);
Print("Lote alta volatilidade: ", LoteAltaVolatilidade);
}
void setDeInit(int reason) {
//--- Liberar handles
if(handleMA != INVALID_HANDLE) IndicatorRelease(handleMA);
Print(Simbolo + "Scalper Clear finalizado. Motivo: ", reason);
}
//+------------------------------------------------------------------+
//| 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 ===");
Print("Saldo inicial: R$ ", DoubleToString(saldoInicialDia, 2));
Print("Perda m<00>xima permitida: R$ ", DoubleToString(perdaMaximaDia, 2));
}
//+------------------------------------------------------------------+
//| 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("M<00>ximo de trades por dia atingido: ", MaxTradesPorDia);
tradingPermitido = false;
}
return false;
}
//--- Verificar m<EFBFBD>ximo de opera<EFBFBD><EFBFBD>es perdedoras consecutivas
if(tradesPerdedoresConsecutivos >= MaxOperacoesPerdedoras)
{
Print("M<00>ximo de opera<00><00>es perdedoras consecutivas atingido: ", MaxOperacoesPerdedoras);
tradingPermitido = false;
return false;
}
//--- Verificar perda m<EFBFBD>xima di<EFBFBD>ria
double perdaAtual = saldoInicialDia - account.Balance();
if(perdaAtual >= perdaMaximaDia)
{
Print("Perda m<00>xima di<00>ria atingida: R$ ", DoubleToString(perdaAtual, 2));
tradingPermitido = false;
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Verificar hor<EFBFBD>rio de trading permitido |
//+------------------------------------------------------------------+
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 de trading (Bras<EFBFBD>lia)
// 09:15-10:00: Ap<EFBFBD>s leil<EFBFBD>o abertura BMF
if(OperarAberturaBMF && horaMinuto >= 915 && horaMinuto < 1000)
return true;
// 10:15-10:30: Ap<EFBFBD>s leil<EFBFBD>o abertura Bovespa
if(OperarAberturaBovespa && horaMinuto >= 1015 && horaMinuto < 1030)
return true;
// 10:30-12:00: Abertura mercado americano
if(OperarAberturaEUA && horaMinuto >= 1030 && horaMinuto < 1200)
return true;
// 14:00-16:45: Per<EFBFBD>odo da tarde
if(OperarTarde && horaMinuto >= 1400 && horaMinuto < 1645)
return true;
// 17:00-18:00: Ap<EFBFBD>s fechamento Bovespa
if(OperarFechamento && horaMinuto >= 1700 && horaMinuto < 1800)
return true;
return false;
}
//+------------------------------------------------------------------+
//| Verificar se <EFBFBD> hor<EFBFBD>rio de alta volatilidade |
//+------------------------------------------------------------------+
bool HorarioAltaVolatilidade() {
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
int hora = dt.hour;
int minuto = dt.min;
int horaMinuto = hora * 100 + minuto;
//--- Hor<EFBFBD>rios de alta volatilidade
// 09:15-10:00: Ap<EFBFBD>s leil<EFBFBD>o BMF
if(horaMinuto >= 915 && horaMinuto < 1000)
return true;
// 10:00-11:00: Abertura Bovespa + EUA
if(horaMinuto >= 1000 && horaMinuto < 1100)
return true;
// 17:00-18:00: Fechamento
if(horaMinuto >= 1700 && horaMinuto < 1800)
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;
//--- Aqui voc<EFBFBD> pode adicionar l<EFBFBD>gica adicional de gest<EFBFBD>o
//--- Por exemplo, trailing stop, breakeven, etc.
}
//+------------------------------------------------------------------+
//| Analisar entrada baseada em price action |
//+------------------------------------------------------------------+
void AnalisarEntrada() {
//--- Obter dados das velas
MqlRates velas[];
if(CopyRates(Simbolo, PERIOD_M1, 0, VelasAnalise + 1, velas) <= 0)
return;
//--- Obter dados da m<EFBFBD>dia m<EFBFBD>vel
double ma[];
if(CopyBuffer(handleMA, 0, 0, VelasAnalise + 1, ma) <= 0)
return;
ArraySetAsSeries(velas, true);
ArraySetAsSeries(ma, true);
//--- An<EFBFBD>lise de price action para entrada
ENUM_ORDER_TYPE tipoOrdem = AnalisarPriceAction(velas, ma);
if(tipoOrdem == ORDER_TYPE_BUY || tipoOrdem == ORDER_TYPE_SELL)
{
ExecutarOrdem(tipoOrdem);
}
}
//+------------------------------------------------------------------+
//| Analisar price action para determinar dire<EFBFBD><EFBFBD>o |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE AnalisarPriceAction(const MqlRates &velas[], const double &ma[]) {
double precoAtual = SymbolInfoDouble(Simbolo, SYMBOL_BID);
//--- Verificar movimento m<EFBFBD>nimo
double range = velas[0].high - velas[0].low;
if(range < MinimoPontosMovimento * SymbolInfoDouble(Simbolo, SYMBOL_POINT))
return -1;
//--- An<EFBFBD>lise baseada na m<EFBFBD>dia m<EFBFBD>vel e price action
bool acimaDaMedia = precoAtual > ma[0];
bool tendenciaAlta = ma[0] > ma[1] && ma[1] > ma[2];
bool tendenciaBaixa = ma[0] < ma[1] && ma[1] < ma[2];
//--- Padr<EFBFBD>o de compra: pre<EFBFBD>o acima da m<EFBFBD>dia em tend<EFBFBD>ncia de alta
if(acimaDaMedia && tendenciaAlta)
{
//--- Verificar se vela anterior foi de baixa e atual <EFBFBD> de alta
if(velas[1].close < velas[1].open && velas[0].close > velas[0].open)
{
//--- Verificar se n<EFBFBD>o estamos em topo
if(velas[0].high < velas[1].high)
return ORDER_TYPE_BUY;
}
}
//--- Padr<EFBFBD>o de venda: pre<EFBFBD>o abaixo da m<EFBFBD>dia em tend<EFBFBD>ncia de baixa
if(!acimaDaMedia && tendenciaBaixa)
{
//--- Verificar se vela anterior foi de alta e atual <EFBFBD> de baixa
if(velas[1].close > velas[1].open && velas[0].close < velas[0].open)
{
//--- Verificar se n<EFBFBD>o estamos em fundo
if(velas[0].low > velas[1].low)
return ORDER_TYPE_SELL;
}
}
return -1; // Nenhum sinal
}
//+------------------------------------------------------------------+
//| Executar ordem |
//+------------------------------------------------------------------+
void ExecutarOrdem(ENUM_ORDER_TYPE tipo) {
//--- Determinar lote baseado na volatilidade
double lote = HorarioAltaVolatilidade() ? LoteAltaVolatilidade : LotePadrao;
//--- Determinar take profit baseado na volatilidade
int tp = HorarioAltaVolatilidade() ? TakeProfitAltaVol : TakeProfitPadrao;
//--- Calcular stop loss (50% do take profit)
int sl = (int)(tp * (StopLossPercentual / 100.0));
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,
Simbolo + "Scalper - Compra");
}
else
{
resultado = trade.Sell(
lote,
Simbolo,
preco,
precoSL,
precoTP,
Simbolo + "Scalper - Venda");
}
if(resultado)
{
tradesHoje++;
Print("=== NOVA OPERA<00><00>O ===");
Print("Tipo: ", (tipo == ORDER_TYPE_BUY) ? "COMPRA" : "VENDA");
Print("Lote: ", lote);
Print("Pre<00>o: ", preco);
Print("Take Profit: ", precoTP, " (", tp, " pontos)");
Print("Stop Loss: ", precoSL, " (", sl, " pontos)");
Print("Trade n<00>: ", tradesHoje);
}
else
{
Print("Erro ao executar ordem: ", trade.ResultRetcode());
}
}
void setOnTickTrader() {
//--- 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
AnalisarEntrada();
}
void setOnTrade() {
//--- 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 ===");
Print("Lucro: R$ ", DoubleToString(lucro, 2));
}
else
{
tradesPerdedoresConsecutivos++;
Print("=== TRADE PERDEDOR ===");
Print("Perda: R$ ", DoubleToString(lucro, 2));
Print("Perdedores consecutivos: ", tradesPerdedoresConsecutivos);
}
//--- Estat<EFBFBD>sticas do dia
double winRate = (tradesHoje > 0) ? (tradesVencedoresHoje * 100.0 / tradesHoje) : 0;
Print("=== ESTAT<00>STICAS DO DIA ===");
Print("Trades realizados: ", tradesHoje);
Print("Trades vencedores: ", tradesVencedoresHoje);
Print("Win Rate: ", DoubleToString(winRate, 2), "%");
Print("Saldo atual: R$ ", DoubleToString(account.Balance(), 2));
}
}
}
}