🚀 AI One-Click Generation of mql4 Strategy Code

Automating the Bill Williams Market Facilitation Index (BWFMI) in an Mql4 EA

mql4 | Published on: 2025/12/4
The following content is generated by EasyQuant .

Problem Description

Can you code a trading strategy that uses the Market Facilitation Index and volume to make decisions?

Solution

Here is a complete, fully functional Expert Advisor (EA) for MetaTrader 4.

This strategy utilizes Bill Williams' Market Facilitation Index (MFI) combined with Volume to identify "Green" bars. A Green Bar occurs when both MFI and Volume increase, indicating that the market is moving directionally and new players are entering the market.

Strategy Logic

  1. Green Bar Condition: Current MFI > Previous MFI AND Current Volume > Previous Volume.
  2. Trend Filter: A Simple Moving Average (SMA) is used to determine the overall trend direction.
  3. Buy Signal: Green Bar formed + Close Price > Moving Average + Bullish Candle.
  4. Sell Signal: Green Bar formed + Close Price < Moving Average + Bearish Candle.

MQL4 Code

//+------------------------------------------------------------------+
//|                                                MFI_Volume_EA.mq4 |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative AI"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

//--- Input Parameters
input double InpLots          = 0.1;      // Lot Size
input int    InpStopLoss      = 50;       // Stop Loss in points
input int    InpTakeProfit    = 100;      // Take Profit in points
input int    InpMagicNumber   = 123456;   // Magic Number ID
input int    InpMAPeriod      = 50;       // Moving Average Period (Trend Filter)
input int    InpSlippage      = 3;        // Max Slippage in points

//--- Global Variables
double m_point;
int    m_digits;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // Adjust point values for 3/5 digit brokers
   if(Digits == 3 || Digits == 5)
   {
      m_point = Point * 10;
      m_digits = Digits;
   }
   else
   {
      m_point = Point;
      m_digits = Digits;
   }

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // Clean up if necessary
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // Check if we have enough bars to calculate
   if(Bars < InpMAPeriod + 2) return;

   // Define shift (1 = closed bar, 0 = current forming bar)
   // We use 1 and 2 to ensure we trade on confirmed signals
   int shiftCurr = 1;
   int shiftPrev = 2;

   // --- 1. Get MFI Values ---
   double mfiCurr = iBWMFI(NULL, 0, shiftCurr);
   double mfiPrev = iBWMFI(NULL, 0, shiftPrev);

   // --- 2. Get Volume Values ---
   long volCurr = iVolume(NULL, 0, shiftCurr);
   long volPrev = iVolume(NULL, 0, shiftPrev);

   // --- 3. Get Trend Filter (MA) ---
   double maValue = iMA(NULL, 0, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE, shiftCurr);
   double closePrice = iClose(NULL, 0, shiftCurr);
   double openPrice  = iOpen(NULL, 0, shiftCurr);

   // --- 4. Determine "Green Bar" State ---
   // Green Bar: MFI is UP and Volume is UP
   bool isGreenBar = (mfiCurr > mfiPrev) && (volCurr > volPrev);

   // --- 5. Check for Open Positions ---
   if(CountOrders() == 0)
   {
      // --- Buy Logic ---
      // Green Bar + Price above MA + Bullish Candle
      if(isGreenBar && closePrice > maValue && closePrice > openPrice)
      {
         OpenTrade(OP_BUY);
      }
      // --- Sell Logic ---
      // Green Bar + Price below MA + Bearish Candle
      else if(isGreenBar && closePrice < maValue && closePrice < openPrice)
      {
         OpenTrade(OP_SELL);
      }
   }
}

//+------------------------------------------------------------------+
//| Helper: Count Open Orders for this EA                            |
//+------------------------------------------------------------------+
int CountOrders()
{
   int count = 0;
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == InpMagicNumber)
         {
            count++;
         }
      }
   }
   return(count);
}

//+------------------------------------------------------------------+
//| Helper: Open Trade Execution                                     |
//+------------------------------------------------------------------+
void OpenTrade(int type)
{
   double price, sl, tp;
   color clr;

   if(type == OP_BUY)
   {
      price = Ask;
      sl = (InpStopLoss > 0) ? price - InpStopLoss * m_point : 0;
      tp = (InpTakeProfit > 0) ? price + InpTakeProfit * m_point : 0;
      clr = clrBlue;
   }
   else
   {
      price = Bid;
      sl = (InpStopLoss > 0) ? price + InpStopLoss * m_point : 0;
      tp = (InpTakeProfit > 0) ? price - InpTakeProfit * m_point : 0;
      clr = clrRed;
   }

   // Normalize prices
   price = NormalizeDouble(price, m_digits);
   sl = NormalizeDouble(sl, m_digits);
   tp = NormalizeDouble(tp, m_digits);

   // Send Order
   int ticket = OrderSend(Symbol(), type, InpLots, price, InpSlippage, sl, tp, "MFI_Vol_EA", InpMagicNumber, 0, clr);

   if(ticket < 0)
   {
      Print("OrderSend failed with error #", GetLastError());
   }
}
//+------------------------------------------------------------------+

Key Components Explained

  1. iBWMFI Function: This is the native MQL4 function to retrieve the Market Facilitation Index. We compare index 1 (the last closed bar) with index 2 (the bar before that) to determine if MFI is rising.
  2. iVolume Function: Retrieves the tick volume. We compare index 1 and 2 to determine if Volume is rising.
  3. Green Bar Logic: The boolean variable isGreenBar becomes true only if both MFI and Volume are higher than the previous bar. This indicates strong market participation facilitating price movement.
  4. Trend Filter: To avoid entering during choppy "Squat" bars or counter-trend corrections, we use a Simple Moving Average (iMA). We only buy if the price is above the MA and sell if it is below.
  5. Point Adjustment: The OnInit function calculates m_point to ensure Stop Loss and Take Profit work correctly on both 4-digit and 5-digit brokers (e.g., JPY pairs).

How to Test

  1. Save the code as MFI_Volume_EA.mq4 in your MQL4/Experts folder.
  2. Compile it in MetaEditor.
  3. Open the Strategy Tester in MT4 (Ctrl+R).
  4. Select the EA, choose a symbol (e.g., EURUSD), and a timeframe (H1 or H4 is recommended for Bill Williams' strategies).
  5. Start the test.

Q&A

Q: What is the significance of a "Green" bar in this strategy?
A: A Green bar (MFI Up, Volume Up) signifies that the market is moving freely and new volume is entering the market to support that move. It is generally considered a trend continuation signal.

Q: Why is a Moving Average included in the code?
A: MFI and Volume are volatility and momentum indicators, not directional indicators. Without the Moving Average, the EA might buy a Green bar that occurs during a bearish retracement. The MA ensures we trade in the direction of the broader trend.

Q: Can I use this on any timeframe?
A: Yes, the code is timeframe independent. However, Volume/MFI strategies tend to generate fewer false signals on H1, H4, and Daily charts compared to M1 or M5 due to market noise.

Q: How does the EA handle 5-digit brokers?
A: The code includes a logic block in OnInit that detects if Digits is 3 or 5. It adjusts the m_point multiplier by 10, so a 50-point Stop Loss entered in the inputs remains 50 pips (500 points) or 5 pips (50 points) depending on your intent, ensuring consistency.