Liquidity_Predator/Strategy/M_SM_WAIT_FVG_INVERTED_LONG.mqh

118 lines
5.4 KiB
MQL5
Raw Permalink Normal View History

2026-04-30 15:51:09 +02:00
void M_SM_WAIT_FVG_INVERTED_LONG()
{
bool BuyTakeout = stGVL.CurrentLiquidity - stGVL.Candle[0].low > stGVL.fMaxDiffTakeOut_Price && stGVL.eCurrentDirection == DIR_LONG && stGVL.fMaxDiffTakeOut_Price!=0;
int LiquCrossIndex = iBarShift(_Symbol, _Period, stGVL.dtCurrentLiquidity_Time);
MqlTick tick;
SymbolInfoTick(_Symbol, tick);
double CurrentEntryPrice = tick.ask;
// -------------------------------------------------------------------------------------------------------------------------------------------------
// Takeout
if(BuyTakeout)
{
string Message = "Buy-Liquidity got taken out " + DoubleToString(stGVL.CurrentLiquidity - stGVL.Candle[0].low);
M_LogWarning(Message);
2026-02-27 14:33:14 +01:00
stGVL.nStateMachine = SM_RESET;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------
// Too many candles formed between Liquidity cross and entry
// - 1 because the index is calced on the bar 0 (current, not closed) but we always use bar 1 (last closed bar) for calulations like cross of liquidity
else if((LiquCrossIndex + 1 > nMaxCandlesLiquEntry && nMaxCandlesLiquEntry != 0) || LiquCrossIndex > 99)
{
string Message = "Too many candles between Liquidity cross and entry, LiquCrossIndex=" + IntegerToString(LiquCrossIndex);
M_LogWarning(Message);
stGVL.nStateMachine = SM_RESET;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------
// Wigs in opposite direction
else if(M_CheckWigsLastCandles(stGVL.eCurrentDirection,LiquCrossIndex) && bNoWigsInOppositeDir)
{
M_LogWarning("Wigs in the wrong direction detected");
stGVL.nStateMachine = SM_RESET;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------
else if(stGVL.Candle[1].close > stGVL.LastFVGTop) // FVG got inverted
{
stGVL.BodyStopLoss = 0; // Reset Stoploss before searching a new one
for(int i = 1; i <= LiquCrossIndex; i++) // Search for the Stoploss at the minimum body between now and liquidity cross
{
if(stGVL.Candle[i].close < stGVL.BodyStopLoss || stGVL.BodyStopLoss == 0)
{
stGVL.BodyStopLoss = stGVL.Candle[i].close;
}
}
2026-02-27 14:33:14 +01:00
if(CurrentEntryPrice - stGVL.BodyStopLoss > stGVL.fMaxStopLossSize_Price && stGVL.fMaxStopLossSize_Price != 0) // Stoploss size too big
{
M_LogWarning("Stoploss too big, Bodystoploss=" + DoubleToString(stGVL.BodyStopLoss) + " Price=" + DoubleToString(stGVL.Candle[1].close));
stGVL.nStateMachine = SM_RESET;
}
else if(!M_RSIBuyAllowed(LiquCrossIndex)) // RSI filter
{
stGVL.nStateMachine = SM_RESET;
}
else if(!M_EMABuyAllowed(true)) // EMA filter
2026-02-27 14:33:14 +01:00
{
stGVL.nStateMachine = SM_RESET;
}
else if(!M_SpreadOK()) // Spread filter
{
stGVL.nStateMachine = SM_RESET;
}
else if(CurrentEntryPrice - stGVL.LastFVGTop > stGVL.fMaxDiffFVGEntry_Price && stGVL.fMaxDiffFVGEntry_Price!=0)
{
M_LogWarning("Difference FVG and Entry to big, Entry=" + DoubleToString(CurrentEntryPrice) + " FVG Top=" + DoubleToString(stGVL.LastFVGTop));
stGVL.nStateMachine = SM_RESET;
}
2026-02-27 14:33:14 +01:00
else
{
if(CurrentEntryPrice - stGVL.BodyStopLoss < stGVL.fMinStopLossSize_Price && stGVL.fMinStopLossSize_Price != 0)
{
stGVL.StopLoss = CurrentEntryPrice - stGVL.fMinStopLossSize_Price;
}
else
{
stGVL.StopLoss = stGVL.BodyStopLoss;
}
2026-02-27 14:33:14 +01:00
stGVL.Entry = CurrentEntryPrice;
stGVL.TakeProfit = stGVL.Entry + (stGVL.Entry - stGVL.StopLoss) * fRiskReward;
stGVL.nNumberOfPositions = 1;
2026-06-09 21:41:18 +02:00
int SLInPoints = (stGVL.Entry - stGVL.StopLoss) / SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
double fLot1 = M_CalculateLotSize(fRiskPerTrade, SLInPoints, 100, ORDER_TYPE_BUY);
double fLot2 = 0;
if(bRunnerPosition)
2026-03-08 10:51:33 +01:00
{
2026-06-09 21:41:18 +02:00
fLot2 = M_CalculateLotSize(fRiskPerTrade, SLInPoints, fPercentageRunner, ORDER_TYPE_BUY);
fLot1 = M_CalculateLotSize(fRiskPerTrade, SLInPoints, (100 - fPercentageRunner), ORDER_TYPE_BUY);
stGVL.nNumberOfPositions = stGVL.nNumberOfPositions + 1;
2026-03-08 10:51:33 +01:00
}
// Enter tradex
2026-06-09 21:41:18 +02:00
Trade.Buy(fLot1, _Symbol, 0, stGVL.StopLoss, stGVL.TakeProfit, "Buy");
M_LogInfo("Long entered with Lot " + DoubleToString(fLot1) + " Entry=" + DoubleToString(stGVL.Entry) + " Stoploss=" + DoubleToString(stGVL.StopLoss) + " Takeprofit=" + DoubleToString(stGVL.TakeProfit));
if(bRunnerPosition && bEMAActive)
{
2026-06-09 21:41:18 +02:00
Trade.Buy(fLot2, _Symbol, 0, stGVL.StopLoss, 0, "Buy");
M_LogInfo("Long entered with Lot " + DoubleToString(fLot2) + " Entry=" + DoubleToString(stGVL.Entry) + " Stoploss=" + DoubleToString(stGVL.StopLoss) + " Takeprofit=0 -> runner position");
}
2026-02-27 14:33:14 +01:00
stGVL.nNumberOfTrades = stGVL.nNumberOfTrades + 1;
stGVL.CurrentLiquidity = 0;
stGVL.dtCurrentLiquidity_Time = 0;
stGVL.nStateMachine = SM_IN_TRADE;
}
}
}