2026-04-30 15:51:09 +02:00
void M_SM_WAIT_FVG_INVERTED_LONG ( )
2026-02-20 18:54:37 +01:00
{
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
2026-02-20 18:54:37 +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 ;
}
2026-03-22 20:47:42 +01:00
// -------------------------------------------------------------------------------------------------------------------------------------------------
// Wigs in opposite direction
2026-03-23 18:34:53 +01:00
else if ( M_CheckWigsLastCandles ( stGVL . eCurrentDirection , LiquCrossIndex ) & & bNoWigsInOppositeDir )
2026-03-22 20:47:42 +01:00
{
2026-03-23 18:34:53 +01:00
M_LogWarning ( " Wigs in the wrong direction detected " ) ;
2026-03-22 20:47:42 +01:00
stGVL . nStateMachine = SM_RESET ;
}
2026-02-20 18:54:37 +01:00
// -------------------------------------------------------------------------------------------------------------------------------------------------
2026-02-22 12:04:54 +01:00
else if ( stGVL . Candle [ 1 ] . close > stGVL . LastFVGTop ) // FVG got inverted
2026-02-20 18:54:37 +01:00
{
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 ;
}
2026-03-14 10:04:14 +01:00
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 ;
}
2026-03-17 19:40:57 +01:00
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
2026-02-20 18:54:37 +01:00
{
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 ;
2026-03-14 10:04:14 +01:00
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 ;
2026-03-14 10:04:14 +01:00
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 ) ;
2026-03-14 10:04:14 +01:00
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 ) ) ;
2026-03-14 10:04:14 +01:00
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-03-14 10:04:14 +01:00
}
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 ;
2026-02-20 18:54:37 +01:00
}
}
}