mt5-clear-wing26-scalper/WinFutLib/WinFutLib.mqh
2026-01-30 07:34:05 -03:00

336 lines
26 KiB
MQL5

//+------------------------------------------------------------------+
//| 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 <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\AccountInfo.mqh>
#include <WinfutLib\WinFutEnvs.mqh>
#include <WinFutLib\WinFutConfig.mqh>
#include <WinFutLib\WinFutIndicadores.mqh>
#include <WinFutLib\WinFutLib.mqh>
#include <WinFutLib\WinFutHorarioBovespaLibs.mqh>
#include <WinFutLib\WinFutMsgLogs.mqh>
//WinFutMsgLogs msgLogs;
WinFutHorarioBovespaLibs hBovespaLibs;
class WinFutLib {
public:
WinFutLib(void);
~WinFutLib(void);
CTrade setMagicNumber(CTrade &trade);
int setMediaMovel(void);
void setDeInit(int reason);
void InicializarDadosDia(void);
bool TradingPermitido(void);
bool TemPosicaoAberta(void);
void GerenciarPosicao(void);
void AnalisarEntrada(void);
ENUM_ORDER_TYPE AnalisarPriceAction(const MqlRates &velas[], const double &ma[]);
void ExecutarOrdem(ENUM_ORDER_TYPE tipo);
void setOnTickTrader(void);
void setOnTrade(void);
};
void WinFutLib::WinFutLib(void) { }
void WinFutLib::~WinFutLib(void) { }
CTrade WinFutLib::setMagicNumber(CTrade &trade) {
msgLogs.WinFutMsgLogsSetMagicNumber();
msgLogs.WinFutMsgInfoTrace(MagicNumber);
trade.SetExpertMagicNumber(MagicNumber);
return trade;
}
int WinFutLib::setMediaMovel() {
msgLogs.WinFutMsgLogsSetMediaMovel();
handleMA = iMA(
Simbolo,
PERIOD_M1,
PeriodoMedia,
0,
MODE_SMA,
PRICE_CLOSE
);
if(handleMA == INVALID_HANDLE) {
msgLogs.WinFutMsgInfoTrace("Erro ao criar handle da média móvel");
return INIT_FAILED;
}
return 1;
}
void WinFutLib::setDeInit(int reason) {
msgLogs.WinFutMsgLogsSetDeInit();
msgLogs.WinFutMsgInfoTrace("Liberar handles");
if(handleMA != INVALID_HANDLE) IndicatorRelease(handleMA);
msgLogs.WinFutMsgInfoTrace(Simbolo + "Scalper Clear finalizado. Motivo: " + reason);
}
void WinFutLib::InicializarDadosDia() {
msgLogs.WinFutMsgLogsSetInicializarDadosDia();
tradesHoje = 0;
tradesVencedoresHoje = 0;
tradesPerdedoresConsecutivos = 0;
saldoInicialDia = account.Balance();
perdaMaximaDia = saldoInicialDia * (RiscoMaximoDiario / 100.0);
tradingPermitido = true;
msgLogs.WinFutMsgInfoTrace("=== NOVO DIA DE TRADING ===");
msgLogs.WinFutMsgInfoTrace("Saldo inicial: R$ " + DoubleToString(saldoInicialDia, 2));
msgLogs.WinFutMsgInfoTrace("Perda máxima permitida: R$ " + DoubleToString(perdaMaximaDia, 2));
}
bool WinFutLib::TradingPermitido() {
msgLogs.WinFutMsgLogsSetTradingPermitido();
msgLogs.WinFutMsgInfoTrace("Verificar se trading foi desabilitado por gestão de risco");
if(!tradingPermitido) return false;
msgLogs.WinFutMsgInfoTrace("Verificar máximo de trades por dia");
if(tradesHoje >= MaxTradesPorDia) {
if(tradesHoje == MaxTradesPorDia) {
msgLogs.WinFutMsgInfoTrace("Máximo de trades por dia atingido: " + MaxTradesPorDia);
tradingPermitido = false;
}
return false;
}
msgLogs.WinFutMsgInfoTrace("Verificar máximo de operações perdedoras consecutivas");
if(tradesPerdedoresConsecutivos >= MaxOperacoesPerdedoras) {
msgLogs.WinFutMsgInfoTrace("Máximo de operações perdedoras consecutivas atingido: " + MaxOperacoesPerdedoras);
tradingPermitido = false;
return false;
}
msgLogs.WinFutMsgInfoTrace("Verificar perda máxima diária");
double perdaAtual = saldoInicialDia - account.Balance();
if(perdaAtual >= perdaMaximaDia) {
msgLogs.WinFutMsgInfoTrace("Perda máxima diária atingida: R$ " + DoubleToString(perdaAtual, 2));
tradingPermitido = false;
return false;
}
return true;
}
bool WinFutLib::TemPosicaoAberta() {
msgLogs.WinFutMsgLogsSetTemPosicaoAberta();
return position.SelectByMagic(Simbolo, MagicNumber);
}
void WinFutLib::GerenciarPosicao() {
msgLogs.WinFutMsgLogsSetGerenciarPosicao();
if(!position.SelectByMagic(Simbolo, MagicNumber))
return;
//--- Aqui você pode adicionar lógica adicional de gestão
//--- Por exemplo, trailing stop, breakeven, etc.
}
void WinFutLib::AnalisarEntrada() {
msgLogs.WinFutMsgLogsSetAnalisarEntrada();
msgLogs.WinFutMsgInfoTrace("Obter dados das velas");
MqlRates velas[];
if(CopyRates(Simbolo, PERIOD_M1, 0, VelasAnalise + 1, velas) <= 0) return;
msgLogs.WinFutMsgInfoTrace("Obter dados da média móvel");
double ma[];
if(CopyBuffer(handleMA, 0, 0, VelasAnalise + 1, ma) <= 0) return;
ArraySetAsSeries(velas, true);
ArraySetAsSeries(ma, true);
msgLogs.WinFutMsgInfoTrace("Análise de price action para entrada");
ENUM_ORDER_TYPE tipoOrdem = AnalisarPriceAction(velas, ma);
if(tipoOrdem == ORDER_TYPE_BUY || tipoOrdem == ORDER_TYPE_SELL) {
msgLogs.WinFutMsgInfoTrace("executando boleta de");
msgLogs.WinFutMsgInfoTrace(tipoOrdem);
ExecutarOrdem(tipoOrdem);
}
}
ENUM_ORDER_TYPE WinFutLib::AnalisarPriceAction(const MqlRates &velas[], const double &ma[]) {
msgLogs.WinFutMsgLogsSetAnalisarPriceAction();
double precoAtual = SymbolInfoDouble(Simbolo, SYMBOL_BID);
msgLogs.WinFutMsgInfoTrace("Verificar movimento mínimo");
double range = velas[0].high - velas[0].low;
if(range < MinimoPontosMovimento * SymbolInfoDouble(Simbolo, SYMBOL_POINT))
return -1;
msgLogs.WinFutMsgInfoTrace("Análise baseada na média mó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];
msgLogs.WinFutMsgInfoTrace("Padrão de compra: preço acima da média em tendência de alta");
if(acimaDaMedia && tendenciaAlta) {
msgLogs.WinFutMsgInfoTrace("Verificar se vela anterior foi de baixa e atual é de alta");
if(velas[1].close < velas[1].open && velas[0].close > velas[0].open) {
msgLogs.WinFutMsgInfoTrace("Verificar se não estamos em topo");
if(velas[0].high < velas[1].high)
msgLogs.WinFutMsgInfoTrace("ordem do tipo de compra");
return ORDER_TYPE_BUY;
}
}
msgLogs.WinFutMsgInfoTrace("Padrão de venda: preço abaixo da média em tendência de baixa");
if(!acimaDaMedia && tendenciaBaixa) {
msgLogs.WinFutMsgInfoTrace("Verificar se vela anterior foi de alta e atual é de baixa");
if(velas[1].close > velas[1].open && velas[0].close < velas[0].open) {
msgLogs.WinFutMsgInfoTrace("Verificar se não estamos em fundo");
if(velas[0].low > velas[1].low)
msgLogs.WinFutMsgInfoTrace("ordem tipo de venda");
return ORDER_TYPE_SELL;
}
}
msgLogs.WinFutMsgInfoTrace("Nenhum sinal");
return -1;
}
void WinFutLib::ExecutarOrdem(ENUM_ORDER_TYPE tipo) {
msgLogs.WinFutMsgLogsSetExecutarOrdem();
msgLogs.WinFutMsgInfoTrace("Determinar lote baseado na volatilidade");
double lote = hBovespaLibs.HorarioAltaVolatilidade() ? LoteAltaVolatilidade : LotePadrao;
msgLogs.WinFutMsgInfoTrace("Determinar take profit baseado na volatilidade");
int tp = hBovespaLibs.HorarioAltaVolatilidade() ? TakeProfitAltaVol : TakeProfitPadrao;
msgLogs.WinFutMsgInfoTrace("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;
msgLogs.WinFutMsgInfoTrace("setando TP/SL para tipo de venda");
precoTP = preco - (tp * ponto);
precoSL = preco + (sl * ponto);
if(tipo == ORDER_TYPE_BUY) {
msgLogs.WinFutMsgInfoTrace("setando TP/SL para tipo de compra");
precoTP = preco + (tp * ponto);
precoSL = preco - (sl * ponto);
}
bool resultado = false;
string scalper = "";
if(tipo == ORDER_TYPE_BUY) {
scalper = Simbolo + "Scalper - Compra";
msgLogs.WinFutMsgInfoTrace("executando boletada de compra" + scalper);
resultado = trade.Buy(
lote,
Simbolo,
preco,
precoSL,
precoTP,
scalper
);
} else {
scalper = Simbolo + "Scalper - Venda";
msgLogs.WinFutMsgInfoTrace("executando boletada de venda" + scalper);
resultado = trade.Sell(
lote,
Simbolo,
preco,
precoSL,
precoTP,
scalper
);
}
if(resultado) {
tradesHoje++;
msgLogs.WinFutMsgInfoTrace("=== NOVA OPERAÇÃO ===");
msgLogs.WinFutMsgInfoTrace("Tipo: " + scalper);
msgLogs.WinFutMsgInfoTrace("Lote: " + lote);
msgLogs.WinFutMsgInfoTrace("Preço: " + preco);
msgLogs.WinFutMsgInfoTrace("Take Profit: " + precoTP + " (" + tp + " pontos)");
msgLogs.WinFutMsgInfoTrace("Stop Loss: " + precoSL + " (" + sl + " pontos)");
msgLogs.WinFutMsgInfoTrace("Trade nº: " + tradesHoje);
} else {
msgLogs.WinFutMsgInfoTrace("Erro ao executar ordem: " + trade.ResultRetcode());
}
}
void WinFutLib::setOnTickTrader() {
msgLogs.WinFutMsgLogsSetOnTickTrader();
msgLogs.WinFutMsgInfoTrace("Verificar se é um novo dia");
if(hBovespaLibs.VerificarNovoDia()) {
InicializarDadosDia();
}
msgLogs.WinFutMsgInfoTrace("Verificar se trading está permitido");
if(!TradingPermitido()) return;
msgLogs.WinFutMsgInfoTrace("Verificar horário de trading");
if(!hBovespaLibs.HorarioTradingPermitido()) return;
msgLogs.WinFutMsgInfoTrace("Verificar se já temos posição aberta");
if(TemPosicaoAberta()) {
GerenciarPosicao();
return;
}
msgLogs.WinFutMsgInfoTrace("Procurar oportunidades de entrada");
AnalisarEntrada();
}
void WinFutLib::setOnTrade() {
msgLogs.WinFutMsgLogsSetOnTrade();
msgLogs.WinFutMsgInfoTrace("Verificar se a posição foi fechada");
if(!TemPosicaoAberta()) {
msgLogs.WinFutMsgInfoTrace("Analisar resultado da última operação - Últimas 24 horas");
HistorySelect(TimeCurrent() - 86400, TimeCurrent());
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;
msgLogs.WinFutMsgInfoTrace("=== TRADE VENCEDOR ===");
msgLogs.WinFutMsgInfoTrace("Lucro: R$ " + DoubleToString(lucro, 2));
} else {
tradesPerdedoresConsecutivos++;
msgLogs.WinFutMsgInfoTrace("=== TRADE PERDEDOR ===");
msgLogs.WinFutMsgInfoTrace("Perda: R$ " + DoubleToString(lucro, 2));
msgLogs.WinFutMsgInfoTrace("Perdedores consecutivos: " + tradesPerdedoresConsecutivos);
}
msgLogs.WinFutMsgInfoTrace("Estatísticas do dia");
double winRate = (tradesHoje > 0) ? (tradesVencedoresHoje * 100.0 / tradesHoje) : 0;
msgLogs.WinFutMsgInfoTrace("=== ESTATÍSTICAS DO DIA ===");
msgLogs.WinFutMsgInfoTrace("Trades realizados: " + tradesHoje);
msgLogs.WinFutMsgInfoTrace("Trades vencedores: " + tradesVencedoresHoje);
msgLogs.WinFutMsgInfoTrace("Win Rate: " + DoubleToString(winRate, 2));
msgLogs.WinFutMsgInfoTrace("Saldo atual: R$ " + DoubleToString(account.Balance(), 2));
}
}
}
}