385 lines
No EOL
13 KiB
MQL5
385 lines
No EOL
13 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| WinQ25_Indicadores.mqh |
|
|
//| Copyright 2024, Scalper Trading Bot |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2024, Scalper Trading Bot"
|
|
#property link "https://www.mql5.com"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Classe para análise avançada de Price Action |
|
|
//+------------------------------------------------------------------+
|
|
class PriceActionAnalyzer
|
|
{
|
|
private:
|
|
string simbolo;
|
|
ENUM_TIMEFRAMES timeframe;
|
|
|
|
public:
|
|
PriceActionAnalyzer(string _simbolo = "", ENUM_TIMEFRAMES _timeframe = PERIOD_M1)
|
|
{
|
|
simbolo = (_simbolo == "") ? Symbol() : _simbolo;
|
|
timeframe = _timeframe;
|
|
}
|
|
|
|
//--- Detectar padrão de martelo/doji
|
|
bool IsMartelo(const MqlRates &vela)
|
|
{
|
|
double corpo = MathAbs(vela.close - vela.open);
|
|
double sombraInferior = (vela.close > vela.open) ?
|
|
(vela.open - vela.low) : (vela.close - vela.low);
|
|
double sombraSuperior = (vela.close > vela.open) ?
|
|
(vela.high - vela.close) : (vela.high - vela.open);
|
|
double range = vela.high - vela.low;
|
|
|
|
// Martelo: sombra inferior > 2x corpo e sombra superior pequena
|
|
return (sombraInferior > 2 * corpo && sombraSuperior < corpo * 0.3 && range > 0);
|
|
}
|
|
|
|
//--- Detectar padrão de estrela cadente
|
|
bool IsEstrelaCadente(const MqlRates &vela)
|
|
{
|
|
double corpo = MathAbs(vela.close - vela.open);
|
|
double sombraInferior = (vela.close > vela.open) ?
|
|
(vela.open - vela.low) : (vela.close - vela.low);
|
|
double sombraSuperior = (vela.close > vela.open) ?
|
|
(vela.high - vela.close) : (vela.high - vela.open);
|
|
|
|
// Estrela cadente: sombra superior > 2x corpo e sombra inferior pequena
|
|
return (sombraSuperior > 2 * corpo && sombraInferior < corpo * 0.3);
|
|
}
|
|
|
|
//--- Detectar engolfo de alta
|
|
bool IsEngolfoAlta(const MqlRates &vela1, const MqlRates &vela2)
|
|
{
|
|
// Vela 1 (anterior) deve ser baixista
|
|
bool vela1Baixista = vela1.close < vela1.open;
|
|
// Vela 2 (atual) deve ser altista
|
|
bool vela2Altista = vela2.close > vela2.open;
|
|
// Vela 2 deve engolfar vela 1
|
|
bool engolfa = vela2.open < vela1.close && vela2.close > vela1.open;
|
|
|
|
return vela1Baixista && vela2Altista && engolfa;
|
|
}
|
|
|
|
//--- Detectar engolfo de baixa
|
|
bool IsEngolfoBaixa(const MqlRates &vela1, const MqlRates &vela2)
|
|
{
|
|
// Vela 1 (anterior) deve ser altista
|
|
bool vela1Altista = vela1.close > vela1.open;
|
|
// Vela 2 (atual) deve ser baixista
|
|
bool vela2Baixista = vela2.close < vela2.open;
|
|
// Vela 2 deve engolfar vela 1
|
|
bool engolfa = vela2.open > vela1.close && vela2.close < vela1.open;
|
|
|
|
return vela1Altista && vela2Baixista && engolfa;
|
|
}
|
|
|
|
//--- Calcular força da tendência (baseado em sequência de velas)
|
|
double CalcularForcaTendencia(const MqlRates &velas[], int periodos = 5)
|
|
{
|
|
int contadorAlta = 0;
|
|
int contadorBaixa = 0;
|
|
|
|
for(int i = 0; i < periodos && i < ArraySize(velas); i++)
|
|
{
|
|
if(velas[i].close > velas[i].open)
|
|
contadorAlta++;
|
|
else if(velas[i].close < velas[i].open)
|
|
contadorBaixa++;
|
|
}
|
|
|
|
// Retorna valor entre -1 (forte baixa) e +1 (forte alta)
|
|
return (double)(contadorAlta - contadorBaixa) / periodos;
|
|
}
|
|
|
|
//--- Detectar rompimento de suporte/resistência
|
|
bool IsRompimentoSuporteResistencia(const MqlRates &velas[], double nivel, bool isResistencia)
|
|
{
|
|
if(ArraySize(velas) < 2) return false;
|
|
|
|
double precoAtual = velas[0].close;
|
|
double precoAnterior = velas[1].close;
|
|
|
|
if(isResistencia)
|
|
{
|
|
// Rompimento de resistência (preço cruza acima)
|
|
return (precoAnterior <= nivel && precoAtual > nivel);
|
|
}
|
|
else
|
|
{
|
|
// Rompimento de suporte (preço cruza abaixo)
|
|
return (precoAnterior >= nivel && precoAtual < nivel);
|
|
}
|
|
}
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Classe para análise de volume (quando disponível) |
|
|
//+------------------------------------------------------------------+
|
|
class VolumeAnalyzer
|
|
{
|
|
public:
|
|
//--- Detectar divergência de volume
|
|
static bool IsDivergenciaVolume(const MqlRates &velas[], int periodos = 3)
|
|
{
|
|
if(ArraySize(velas) < periodos) return false;
|
|
|
|
// Verificar se preço subiu mas volume diminuiu (divergência bearish)
|
|
bool precoSubiu = velas[0].close > velas[periodos-1].close;
|
|
bool volumeDiminuiu = velas[0].tick_volume < velas[periodos-1].tick_volume;
|
|
|
|
return precoSubiu && volumeDiminuiu;
|
|
}
|
|
|
|
//--- Calcular volume médio
|
|
static double CalcularVolumeMedia(const MqlRates &velas[], int periodos = 20)
|
|
{
|
|
if(ArraySize(velas) < periodos) return 0;
|
|
|
|
long somaVolume = 0;
|
|
for(int i = 0; i < periodos; i++)
|
|
{
|
|
somaVolume += velas[i].tick_volume;
|
|
}
|
|
|
|
return (double)somaVolume / periodos;
|
|
}
|
|
|
|
//--- Verificar se volume está acima da média
|
|
static bool IsVolumeAcimaDaMedia(const MqlRates &velaAtual, double volumeMedia, double multiplicador = 1.5)
|
|
{
|
|
return velaAtual.tick_volume > (volumeMedia * multiplicador);
|
|
}
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Classe para cálculos de suporte e resistência |
|
|
//+------------------------------------------------------------------+
|
|
class SuporteResistencia
|
|
{
|
|
public:
|
|
//--- Calcular suporte e resistência baseado em pivôs
|
|
struct NiveisSR
|
|
{
|
|
double suporte1;
|
|
double suporte2;
|
|
double resistencia1;
|
|
double resistencia2;
|
|
double pontosPivo;
|
|
};
|
|
|
|
static NiveisSR CalcularNiveisDiarios(string simbolo)
|
|
{
|
|
NiveisSR niveis = {0};
|
|
|
|
// Obter dados do dia anterior
|
|
MqlRates day[];
|
|
if(CopyRates(simbolo, PERIOD_D1, 1, 1, day) > 0)
|
|
{
|
|
double high = day[0].high;
|
|
double low = day[0].low;
|
|
double close = day[0].close;
|
|
|
|
// Calcular ponto pivô
|
|
niveis.pontosPivo = (high + low + close) / 3.0;
|
|
|
|
// Calcular suportes e resistências
|
|
niveis.resistencia1 = (2 * niveis.pontosPivo) - low;
|
|
niveis.suporte1 = (2 * niveis.pontosPivo) - high;
|
|
niveis.resistencia2 = niveis.pontosPivo + (high - low);
|
|
niveis.suporte2 = niveis.pontosPivo - (high - low);
|
|
}
|
|
|
|
return niveis;
|
|
}
|
|
|
|
//--- Encontrar máximas e mínimas locais
|
|
static double EncontrarMaximaLocal(const MqlRates &velas[], int periodos = 10)
|
|
{
|
|
if(ArraySize(velas) < periodos) return 0;
|
|
|
|
double maxima = velas[0].high;
|
|
for(int i = 1; i < periodos; i++)
|
|
{
|
|
if(velas[i].high > maxima)
|
|
maxima = velas[i].high;
|
|
}
|
|
|
|
return maxima;
|
|
}
|
|
|
|
static double EncontrarMinimaLocal(const MqlRates &velas[], int periodos = 10)
|
|
{
|
|
if(ArraySize(velas) < periodos) return 0;
|
|
|
|
double minima = velas[0].low;
|
|
for(int i = 1; i < periodos; i++)
|
|
{
|
|
if(velas[i].low < minima)
|
|
minima = velas[i].low;
|
|
}
|
|
|
|
return minima;
|
|
}
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Classe para detecção de padrões de velas |
|
|
//+------------------------------------------------------------------+
|
|
class PadroesVelas
|
|
{
|
|
public:
|
|
//--- Detectar inside bar (vela interior)
|
|
static bool IsInsideBar(const MqlRates &vela1, const MqlRates &vela2)
|
|
{
|
|
return (vela2.high < vela1.high && vela2.low > vela1.low);
|
|
}
|
|
|
|
//--- Detectar outside bar (vela exterior)
|
|
static bool IsOutsideBar(const MqlRates &vela1, const MqlRates &vela2)
|
|
{
|
|
return (vela2.high > vela1.high && vela2.low < vela1.low);
|
|
}
|
|
|
|
//--- Detectar pin bar
|
|
static bool IsPinBar(const MqlRates &vela, bool isPinBarAlta = true)
|
|
{
|
|
double corpo = MathAbs(vela.close - vela.open);
|
|
double range = vela.high - vela.low;
|
|
double sombra = isPinBarAlta ? (vela.low - MathMin(vela.open, vela.close)) :
|
|
(MathMax(vela.open, vela.close) - vela.high);
|
|
|
|
// Pin bar deve ter sombra > 60% do range e corpo < 30% do range
|
|
return (sombra > range * 0.6 && corpo < range * 0.3);
|
|
}
|
|
|
|
//--- Detectar doji
|
|
static bool IsDoji(const MqlRates &vela)
|
|
{
|
|
double corpo = MathAbs(vela.close - vela.open);
|
|
double range = vela.high - vela.low;
|
|
|
|
// Doji: corpo muito pequeno comparado ao range
|
|
return (corpo < range * 0.1 && range > 0);
|
|
}
|
|
|
|
//--- Detectar vela de indecisão
|
|
static bool IsVelaIndecisao(const MqlRates &vela)
|
|
{
|
|
double corpo = MathAbs(vela.close - vela.open);
|
|
double sombraInferior = MathMin(vela.open, vela.close) - vela.low;
|
|
double sombraSuperior = vela.high - MathMax(vela.open, vela.close);
|
|
|
|
// Vela de indecisão: sombras longas e corpo pequeno
|
|
return (sombraInferior > corpo && sombraSuperior > corpo);
|
|
}
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Classe para análise de momentum |
|
|
//+------------------------------------------------------------------+
|
|
class MomentumAnalyzer
|
|
{
|
|
public:
|
|
//--- Calcular momentum baseado em preços
|
|
static double CalcularMomentum(const MqlRates &velas[], int periodo = 10)
|
|
{
|
|
if(ArraySize(velas) < periodo) return 0;
|
|
|
|
double precoAtual = velas[0].close;
|
|
double precoAnterior = velas[periodo-1].close;
|
|
|
|
return precoAtual - precoAnterior;
|
|
}
|
|
|
|
//--- Calcular taxa de mudança (ROC)
|
|
static double CalcularROC(const MqlRates &velas[], int periodo = 10)
|
|
{
|
|
if(ArraySize(velas) < periodo) return 0;
|
|
|
|
double precoAtual = velas[0].close;
|
|
double precoAnterior = velas[periodo-1].close;
|
|
|
|
if(precoAnterior == 0) return 0;
|
|
|
|
return ((precoAtual - precoAnterior) / precoAnterior) * 100;
|
|
}
|
|
|
|
//--- Detectar divergência de momentum
|
|
static bool IsDivergenciaMomentum(const MqlRates &velas[], int periodo = 5)
|
|
{
|
|
if(ArraySize(velas) < periodo * 2) return false;
|
|
|
|
// Calcular momentum para dois períodos
|
|
double momentum1 = CalcularMomentum(velas, periodo);
|
|
double momentum2 = CalcularMomentum(velas, periodo * 2);
|
|
|
|
// Verificar divergência
|
|
bool precoSubindo = velas[0].close > velas[periodo].close;
|
|
bool momentumDiminuindo = momentum1 < momentum2;
|
|
|
|
return precoSubindo && momentumDiminuindo;
|
|
}
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Classe para filtros de entrada |
|
|
//+------------------------------------------------------------------+
|
|
class FiltrosEntrada
|
|
{
|
|
public:
|
|
//--- Filtro de spread
|
|
static bool IsFiltroSpread(string simbolo, double maxSpreadPontos = 3.0)
|
|
{
|
|
double ask = SymbolInfoDouble(simbolo, SYMBOL_ASK);
|
|
double bid = SymbolInfoDouble(simbolo, SYMBOL_BID);
|
|
double point = SymbolInfoDouble(simbolo, SYMBOL_POINT);
|
|
|
|
double spreadAtual = (ask - bid) / point;
|
|
|
|
return spreadAtual <= maxSpreadPontos;
|
|
}
|
|
|
|
//--- Filtro de volatilidade mínima
|
|
static bool IsFiltroVolatilidadeMinima(const MqlRates &velas[], double minRange = 30.0)
|
|
{
|
|
if(ArraySize(velas) < 5) return false;
|
|
|
|
double rangeMedia = 0;
|
|
for(int i = 0; i < 5; i++)
|
|
{
|
|
rangeMedia += (velas[i].high - velas[i].low);
|
|
}
|
|
rangeMedia /= 5.0;
|
|
|
|
double point = SymbolInfoDouble(Symbol(), SYMBOL_POINT);
|
|
double rangePontos = rangeMedia / point;
|
|
|
|
return rangePontos >= minRange;
|
|
}
|
|
|
|
//--- Filtro de horário de trading
|
|
static bool IsFiltroHorario()
|
|
{
|
|
MqlDateTime dt;
|
|
TimeToStruct(TimeCurrent(), dt);
|
|
|
|
// Evitar primeiros e últimos minutos da sessão
|
|
int horaMinuto = dt.hour * 100 + dt.min;
|
|
|
|
// Evitar 09:15-09:20 e 17:55-18:00
|
|
if((horaMinuto >= 915 && horaMinuto < 920) || (horaMinuto >= 1755))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
//--- Filtro combinado
|
|
static bool TodosFiltrosOK(string simbolo, const MqlRates &velas[])
|
|
{
|
|
return IsFiltroSpread(simbolo) &&
|
|
IsFiltroVolatilidadeMinima(velas) &&
|
|
IsFiltroHorario();
|
|
}
|
|
}; |