Initialize project in MT5 Experts directory
This commit is contained in:
+185
-40
@@ -1,5 +1,7 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logic/MicroTrigger.mqh |
|
||||
//| Enhanced LTF Entry Logic with Fibonacci, Liquidity, Price Action |
|
||||
//| Higher probability entries using multiple confluences |
|
||||
//+------------------------------------------------------------------+
|
||||
#ifndef __MICRO_TRIGGER_MQH__
|
||||
#define __MICRO_TRIGGER_MQH__
|
||||
@@ -8,6 +10,8 @@
|
||||
#include "../Core/State.mqh"
|
||||
#include "../Data/PriceEngine.mqh"
|
||||
#include "../Data/Volatility.mqh"
|
||||
#include "../Data/FibonacciEngine.mqh"
|
||||
#include "../Data/LiquidityEngine.mqh"
|
||||
#include "../Core/Logger.mqh"
|
||||
|
||||
extern CLogger g_logger;
|
||||
@@ -18,59 +22,176 @@ class CMicroTrigger
|
||||
private:
|
||||
ENUM_TIMEFRAMES m_ltf;
|
||||
CPriceEngine *m_price;
|
||||
CFibonacciEngine m_fib;
|
||||
CLiquidityEngine m_liquidity;
|
||||
|
||||
public:
|
||||
bool Init(ENUM_TIMEFRAMES ltf, CPriceEngine &price)
|
||||
{
|
||||
m_ltf = ltf; m_price = GetPointer(price);
|
||||
Print("[MicroTrigger] LTF entry logic initialized on ", EnumToString(ltf));
|
||||
m_ltf = ltf;
|
||||
m_price = GetPointer(price);
|
||||
|
||||
if(!m_fib.Init(ltf))
|
||||
{
|
||||
Print("[MicroTrigger] FibonacciEngine init failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!m_liquidity.Init(ltf))
|
||||
{
|
||||
Print("[MicroTrigger] LiquidityEngine init failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
Print("[MicroTrigger] LTF entry logic initialized on ", EnumToString(ltf), " (with Fib + Liquidity)");
|
||||
return true;
|
||||
}
|
||||
|
||||
void Release() {}
|
||||
|
||||
void GenerateSignal(SignalData &signal, const EAState &state, CPriceEngine &price)
|
||||
{
|
||||
signal.isValid = false; signal.isBuy = false; signal.pattern = PATTERN_NONE;
|
||||
signal.rejectionReason = ""; signal.signalTime = TimeCurrent(); signal.atrValue = 0;
|
||||
signal.isValid = false;
|
||||
signal.isBuy = false;
|
||||
signal.pattern = PATTERN_NONE;
|
||||
signal.rejectionReason = "";
|
||||
signal.signalTime = TimeCurrent();
|
||||
signal.atrValue = 0;
|
||||
|
||||
// Update fibonacci and liquidity levels
|
||||
m_fib.Calculate();
|
||||
m_liquidity.Update();
|
||||
|
||||
// Check HTF bias validity
|
||||
if(state.currentBias == BIAS_NEUTRAL && state.currentRegime != REGIME_RANGE)
|
||||
{ signal.rejectionReason = "HTF Bias Neutral + Not Range Mode"; return; }
|
||||
{
|
||||
signal.rejectionReason = "HTF Bias Neutral + Not Range Mode";
|
||||
return;
|
||||
}
|
||||
|
||||
MqlRates bars[4];
|
||||
if(!price.GetClosedBar(m_ltf, 1, bars[1]) || !price.GetClosedBar(m_ltf, 2, bars[2]))
|
||||
{ signal.rejectionReason = "Failed to load LTF closed bars"; return; }
|
||||
{
|
||||
signal.rejectionReason = "Failed to load LTF closed bars";
|
||||
return;
|
||||
}
|
||||
|
||||
// === CONFLUENCE SCORING SYSTEM ===
|
||||
// Each confluence adds to score. Need minimum score for valid signal.
|
||||
int confluenceScore = 0;
|
||||
bool isBuy = false;
|
||||
ENUM_PATTERN detectedPattern = PATTERN_NONE;
|
||||
string patternName = "";
|
||||
|
||||
// 1. Check Price Action Patterns (0-3 points)
|
||||
if(CheckPinBar(bars[1], state))
|
||||
{
|
||||
signal.pattern = PATTERN_PIN_BAR; signal.patternName = "Pin Bar";
|
||||
signal.isBuy = (bars[1].close > bars[1].open);
|
||||
if(ValidateDirection(signal, state)) { CalculateLevels(signal, bars[1], state); return; }
|
||||
detectedPattern = PATTERN_PIN_BAR;
|
||||
patternName = "Pin Bar";
|
||||
isBuy = (bars[1].close > bars[1].open);
|
||||
confluenceScore += 2;
|
||||
}
|
||||
if(!price.GetClosedBar(m_ltf, 2, bars[2])) { signal.rejectionReason = "Failed to load bar[2]"; return; }
|
||||
if(CheckEngulfing(bars[1], bars[2]))
|
||||
else if(CheckEngulfing(bars[1], bars[2]))
|
||||
{
|
||||
signal.pattern = PATTERN_ENGULFING; signal.patternName = "Engulfing";
|
||||
signal.isBuy = (bars[1].close > bars[1].open);
|
||||
if(ValidateDirection(signal, state)) { CalculateLevels(signal, bars[1], state); return; }
|
||||
detectedPattern = PATTERN_ENGULFING;
|
||||
patternName = "Engulfing";
|
||||
isBuy = (bars[1].close > bars[1].open);
|
||||
confluenceScore += 2;
|
||||
}
|
||||
if(price.GetClosedBar(m_ltf, 3, bars[3]))
|
||||
else if(price.GetClosedBar(m_ltf, 3, bars[3]) && CheckInsideBarBreakout(bars[1], bars[2], bars[3]))
|
||||
{
|
||||
if(CheckInsideBarBreakout(bars[1], bars[2], bars[3]))
|
||||
detectedPattern = PATTERN_INSIDE_BAR;
|
||||
patternName = "Inside Bar Breakout";
|
||||
isBuy = (bars[1].close > bars[2].high);
|
||||
confluenceScore += 1;
|
||||
}
|
||||
|
||||
if(confluenceScore == 0)
|
||||
{
|
||||
signal.rejectionReason = "No valid price action pattern";
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Check Fibonacci Level (0-2 points)
|
||||
int fibLevel = -1;
|
||||
if(m_fib.IsNearFibLevel(bars[1].close, 0.5, fibLevel))
|
||||
{
|
||||
confluenceScore += 2;
|
||||
patternName += " + Fib" + m_fib.GetLevelName(fibLevel);
|
||||
}
|
||||
else if(m_fib.IsNearFibLevel(bars[1].close, 1.0, fibLevel))
|
||||
{
|
||||
confluenceScore += 1;
|
||||
patternName += " + Fib" + m_fib.GetLevelName(fibLevel);
|
||||
}
|
||||
|
||||
// 3. Check Order Block (0-2 points)
|
||||
OrderBlock ob;
|
||||
if(m_liquidity.IsAtOrderBlock(bars[1].close, isBuy, ob))
|
||||
{
|
||||
confluenceScore += ob.strength;
|
||||
patternName += " + OB";
|
||||
}
|
||||
|
||||
// 4. Check Liquidity Sweep (0-3 points) - STRONG signal
|
||||
bool sweptBuySide;
|
||||
if(m_liquidity.WasLiquiditySwept(3, sweptBuySide))
|
||||
{
|
||||
// If liquidity was swept and we're trading in opposite direction
|
||||
if((isBuy && !sweptBuySide) || (!isBuy && sweptBuySide))
|
||||
{
|
||||
signal.pattern = PATTERN_INSIDE_BAR; signal.patternName = "Inside Bar Breakout";
|
||||
signal.isBuy = (bars[1].close > bars[2].high);
|
||||
if(ValidateDirection(signal, state)) { CalculateLevels(signal, bars[1], state); return; }
|
||||
confluenceScore += 3;
|
||||
patternName += " + Liquidity Sweep";
|
||||
}
|
||||
}
|
||||
signal.rejectionReason = "No valid price action pattern";
|
||||
|
||||
// 5. Check FVG (Fair Value Gap) (0-1 points)
|
||||
bool isBullishFVG;
|
||||
double fvgTop, fvgBottom;
|
||||
if(m_liquidity.HasFVG(10, isBullishFVG, fvgTop, fvgBottom))
|
||||
{
|
||||
if((isBuy && isBullishFVG) || (!isBuy && !isBullishFVG))
|
||||
{
|
||||
confluenceScore += 1;
|
||||
patternName += " + FVG";
|
||||
}
|
||||
}
|
||||
|
||||
// === VALIDATION ===
|
||||
// Minimum confluence score required
|
||||
int minScore = (state.currentRegime == REGIME_TREND) ? 4 : 3;
|
||||
|
||||
if(confluenceScore < minScore)
|
||||
{
|
||||
signal.rejectionReason = StringFormat("Confluence score %d < minimum %d", confluenceScore, minScore);
|
||||
return;
|
||||
}
|
||||
|
||||
// Direction validation
|
||||
if(!ValidateDirection(isBuy, state))
|
||||
{
|
||||
signal.rejectionReason = isBuy ? "Bullish signal rejected (HTF Bias: BEAR)" : "Bearish signal rejected (HTF Bias: BULL)";
|
||||
return;
|
||||
}
|
||||
|
||||
// Build signal
|
||||
signal.isValid = true;
|
||||
signal.isBuy = isBuy;
|
||||
signal.pattern = detectedPattern;
|
||||
signal.patternName = patternName + StringFormat(" [Score:%d]", confluenceScore);
|
||||
|
||||
CalculateLevels(signal, bars[1], state);
|
||||
}
|
||||
|
||||
private:
|
||||
bool ValidateDirection(SignalData &signal, const EAState &state)
|
||||
bool ValidateDirection(bool isBuy, const EAState &state)
|
||||
{
|
||||
if(state.currentRegime == REGIME_RANGE) return true;
|
||||
if(state.currentBias == BIAS_BULL && !signal.isBuy)
|
||||
{ signal.isValid = false; signal.rejectionReason = "Bearish signal rejected (HTF Bias: BULL)"; return false; }
|
||||
if(state.currentBias == BIAS_BEAR && signal.isBuy)
|
||||
{ signal.isValid = false; signal.rejectionReason = "Bullish signal rejected (HTF Bias: BEAR)"; return false; }
|
||||
signal.isValid = true; return true;
|
||||
if(state.currentBias == BIAS_BULL && !isBuy) return false;
|
||||
if(state.currentBias == BIAS_BEAR && isBuy) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckPinBar(const MqlRates &bar, const EAState &state)
|
||||
{
|
||||
double body = MathAbs(bar.close - bar.open);
|
||||
@@ -78,6 +199,7 @@ private:
|
||||
double lowerWick = MathMin(bar.open, bar.close) - bar.low;
|
||||
double range = bar.high - bar.low;
|
||||
if(range == 0 || body == 0) return false;
|
||||
|
||||
bool bullish = (bar.close > bar.open);
|
||||
if(bullish)
|
||||
{
|
||||
@@ -94,6 +216,7 @@ private:
|
||||
return wickOK && closePos && atLevel;
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckEngulfing(const MqlRates &curr, const MqlRates &prev)
|
||||
{
|
||||
bool bullish = (curr.close > prev.open && curr.open < prev.close);
|
||||
@@ -101,6 +224,7 @@ private:
|
||||
if(!bullish && !bearish) return false;
|
||||
return (curr.tick_volume >= prev.tick_volume * ENGULF_VOLUME_MULT);
|
||||
}
|
||||
|
||||
bool CheckInsideBarBreakout(const MqlRates &breakout, const MqlRates &inside, const MqlRates &mother)
|
||||
{
|
||||
bool isInside = (inside.high < mother.high && inside.low > mother.low);
|
||||
@@ -109,41 +233,61 @@ private:
|
||||
bool bearBreak = (breakout.close < inside.low);
|
||||
return (bullBreak || bearBreak);
|
||||
}
|
||||
|
||||
bool IsAtKeyLevel(const MqlRates &bar, const EAState &state, bool isBullish)
|
||||
{
|
||||
double proximity = state.assetProfile.atrMultiplierSL * g_volatility.GetATR() * 0.5;
|
||||
if(MathAbs(bar.close - state.vwapState.vwapValue) <= proximity) return true;
|
||||
if(isBullish && MathAbs(bar.low - state.swingLow) <= proximity) return true;
|
||||
if(!isBullish && MathAbs(bar.high - state.swingHigh) <= proximity) return true;
|
||||
int maHandle = iMA(_Symbol, m_ltf, 50, 0, MODE_EMA, PRICE_CLOSE);
|
||||
if(maHandle != INVALID_HANDLE)
|
||||
{
|
||||
double maBuf[]; ArraySetAsSeries(maBuf, true);
|
||||
if(CopyBuffer(maHandle, 0, 1, 1, maBuf) > 0)
|
||||
{
|
||||
double ema50 = maBuf[0];
|
||||
IndicatorRelease(maHandle);
|
||||
if(MathAbs(bar.close - ema50) <= proximity) return true;
|
||||
}
|
||||
IndicatorRelease(maHandle);
|
||||
}
|
||||
|
||||
// Check fibonacci levels
|
||||
int fibIdx;
|
||||
if(m_fib.IsNearFibLevel(bar.close, 0.3, fibIdx)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CalculateLevels(SignalData &signal, const MqlRates &bar, const EAState &state)
|
||||
{
|
||||
double atr = g_volatility.GetATR();
|
||||
if(atr <= 0) atr = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE) * 10;
|
||||
signal.atrValue = atr;
|
||||
|
||||
if(signal.isBuy) signal.entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
else signal.entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
|
||||
double slMult, tp1Mult, tp2Mult;
|
||||
if(state.currentRegime == REGIME_TREND)
|
||||
{ slMult = InpTrendATRMult; tp1Mult = InpTrendATRMult * 2.0; tp2Mult = InpTrendATRMult * 4.0; }
|
||||
{
|
||||
slMult = InpTrendATRMult;
|
||||
tp1Mult = InpTrendATRMult * 2.0;
|
||||
tp2Mult = InpTrendATRMult * 4.0;
|
||||
}
|
||||
else
|
||||
{ slMult = InpRangeATRMult; tp1Mult = InpRangeATRMult * 1.5; tp2Mult = InpRangeATRMult * 2.5; }
|
||||
{
|
||||
slMult = InpRangeATRMult;
|
||||
tp1Mult = InpRangeATRMult * 1.5;
|
||||
tp2Mult = InpRangeATRMult * 2.5;
|
||||
}
|
||||
|
||||
double slDist = atr * slMult;
|
||||
double tp1Dist = atr * tp1Mult;
|
||||
double tp2Dist = atr * tp2Mult;
|
||||
|
||||
// Adjust TP based on fibonacci extensions if available
|
||||
if(m_fib.IsValid())
|
||||
{
|
||||
double fibExtension = m_fib.GetExtension(1.618);
|
||||
if(fibExtension > 0)
|
||||
{
|
||||
if(signal.isBuy && fibExtension > signal.entryPrice + tp1Dist)
|
||||
tp2Dist = fibExtension - signal.entryPrice;
|
||||
else if(!signal.isBuy && fibExtension < signal.entryPrice - tp1Dist)
|
||||
tp2Dist = signal.entryPrice - fibExtension;
|
||||
}
|
||||
}
|
||||
|
||||
if(signal.isBuy)
|
||||
{
|
||||
signal.slPrice = signal.entryPrice - slDist;
|
||||
@@ -156,6 +300,7 @@ private:
|
||||
signal.tp1Price = signal.entryPrice - tp1Dist;
|
||||
signal.tp2Price = signal.entryPrice - tp2Dist;
|
||||
}
|
||||
|
||||
signal.isValid = true;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user