Morbid MFI Overhedger

peg it to an hourly chart.

One thing should normally not happen: an upside fractal should not have a 7-sample MFI read below 54.

This places a pending order 2 pips beyond the fractal and targets the Volatility Breakout level plus 5 pips, with the missing hedge, plus 20% extra.

To test it, I run it for the last fractal without MFI. Here’s the result:

// Morbid MFI Overhedger by Macdulio for Automated Trading

#include <stdlib.mqh>
extern int percentage = 20;
extern int magic_number = 87;
extern int magic_number2 = 88;
extern int magic_number3 = 89;
extern double Ratio = 0.6;
#property copyright "by Macdulio in 2025" 
#property link      "https://forexfore.blog" 
#property description "Morbid MFI Overhedger"  

int profits;

  double nakedshorts[];
  double nakedlongs[];
  
  
  double open_price;
  double stop_loss_price;
  double take_profit_price;
  
  double open_price2;
  double stop_loss_price2;
  double take_profit_price2;
  double RSI2[];
  double ATRAVG[]; 
 double OrderOpenPrice;
 double OrderProfit;
double ExtUpperBuffer[], mfi[];
double ExtLowerBuffer[];
double ExtUpperBuffer_[],ExtLowerBuffer_[];
double ExtUpperBuffer_d[],ExtLowerBuffer_d[];
double ExtMapBuffer[];
double ufractals[],dfractals[];
  string symbol = Symbol();   
int init() {
   return(0);
}

int deinit() {
  return(0);
}

int start() {

  ArrayResize(ATRAVG, Bars);   
ArrayInitialize(ATRAVG, 0); 
  ArrayResize(RSI2, 600);   
ArrayInitialize(RSI2, 0); 
  ArrayResize(ExtMapBuffer, Bars);
  ArrayInitialize(ExtMapBuffer,EMPTY_VALUE); 
  ArrayResize(ExtUpperBuffer, Bars);
  ArrayInitialize(ExtUpperBuffer,EMPTY_VALUE); 
     ArrayResize(ExtLowerBuffer, Bars);
  ArrayInitialize(ExtLowerBuffer, EMPTY_VALUE); 
 ArrayResize(ExtUpperBuffer_, Bars);
  ArrayInitialize(ExtUpperBuffer_,EMPTY_VALUE); 
     ArrayResize(ExtLowerBuffer_, Bars);
  ArrayInitialize(ExtLowerBuffer_, EMPTY_VALUE);  
ArrayResize(ExtUpperBuffer_d, Bars);
  ArrayInitialize(ExtUpperBuffer_d,EMPTY_VALUE); 
     ArrayResize(ExtLowerBuffer_d, Bars);
  ArrayInitialize(ExtLowerBuffer_d, EMPTY_VALUE); 
ArrayResize(ufractals, Bars);
  ArrayInitialize(ufractals, EMPTY_VALUE); 
ArrayResize(dfractals, Bars);
  ArrayInitialize(dfractals, EMPTY_VALUE); 
ArrayResize(mfi, 600);   
ArrayInitialize(mfi, 0); 


int i, counter;
int counted_bars=IndicatorCounted();
int longcount, shortcount;
double nlongs;
double nshorts;
double longsize = 0;
double shortsize = 0;
double longaveragebuffer;
double shortaveragebuffer;
double buylevel=1000;
double sellevel=0;
double weight;
int order_type;
  
profits = 0;
 int hstTotal=OrdersHistoryTotal();

 counter = 0;
 
double    ATRA = 0;
   for (i=1; i<=3; i++){ 
     ATRA = ATRA+iATR(NULL,1440,14,i);}
   
   for (i=0; i<=160; i++){ 
     ATRAVG[i] = ATRA/3; }
    
   i=0;
   while (i<200){
      if (ChoppinessIndex(12*4,i)>53 && ChoppinessIndex(12*4,i+1)<53) break;
   i++;

  }
 
   
   if (i<200) weight=iClose(symbol,15,i);
 

 // Print("Ratio = ", Ratio);


for(i=100; i>=0; i--){
   if (iFractals(symbol,60,MODE_UPPER,i)) ufractals[i]=iHigh(symbol,60,i);
   else ufractals[i]=ufractals[i+1];
if (iFractals(symbol,60,MODE_LOWER,i)) dfractals[i]=iLow(symbol,60,i);
   else dfractals[i]=dfractals[i+1];

  RSI2[i]=iRSI(symbol,60,2,PRICE_MEDIAN,i);
    mfi[i]=iMFI(symbol,60,7,i);  
   ExtUpperBuffer[i]=iLow(symbol,0,iLowest(symbol,0,MODE_LOW,12,i))+460*Point;
       ExtLowerBuffer[i]=iHigh(symbol,0,iHighest(symbol,0,MODE_HIGH,12,i))-460*Point;
         
         if (ExtUpperBuffer[i]>ExtLowerBuffer[i]) {ExtUpperBuffer_[i]=ExtUpperBuffer[i]; ExtLowerBuffer_[i]=ExtLowerBuffer[i];
         
         ExtUpperBuffer_d[i]=ExtUpperBuffer_[i]+450*Point; ExtLowerBuffer_d[i]=ExtLowerBuffer_[i]-450*Point;
         }

} 

 for(i=OrdersTotal()-1; i>=0 ; i--)
 {   
   
   if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false)
        { 
           Print("Access to orders list failed with error (",GetLastError(),")");
           break;
        }
          // if ( Symbol()=="EURUSD" && OrderStopLoss()==0 ) {
          // Print("OderProfit: ", OrderProfit());
          
          //Print("AB:",AccountBalance()*-1*.025);
             if (OrderType() == OP_BUY) 
             {
               nlongs = nlongs+OrderLots();
               longcount = longcount+1;
               longaveragebuffer = longaveragebuffer+(OrderOpenPrice()*OrderLots()); 
                  
             }  
               
             if (OrderType() == OP_SELL )
             {
               nshorts = nshorts+OrderLots(); 
               shortcount = shortcount+1;         
               shortaveragebuffer = shortaveragebuffer+(OrderOpenPrice()*OrderLots()); 
             }
         // }
   }
   
   if (nlongs!=nshorts){
   
   
   double comparison = (AccountEquity()/AccountBalance())*100;
   
 //   Print("comparison = ", comparison);


i=1;
while (i<21){

if (iFractals(symbol,60,MODE_UPPER,i) && mfi[i]<54 && High[i]>ufractals[i+1]) break;
// && mfi[i]<54
i++;
} 
if (iFractals(symbol,60,MODE_UPPER,i) && mfi[i]<54 && High[i]>ufractals[i+1]) buylevel = High[i]+20*Point;


longsize = (nshorts-nlongs)*(100+percentage)/100;              
              

  // Overghedge for shorts
  if (nlongs<nshorts && buylevel!=1000 && i<21) {
  
  // if (comparison<Ratio) RemoveStopsandTargets();
    open_price2 = NormalizeDouble(buylevel, Digits);
    stop_loss_price2 = NormalizeDouble(0,Digits);
    take_profit_price2 = NormalizeDouble(weight+1010*Point,Digits);

 for (i = OrdersTotal() - 1; i >= 0; i--)

      if (OrderSelect(i, SELECT_BY_POS))
        if (OrderMagicNumber() == magic_number2) {
          order_type = OrderType();
          if (order_type == ORDER_TYPE_BUY_STOP) {
            if ((NormalizeDouble(OrderOpenPrice(), Digits) != open_price2) || (NormalizeDouble(OrderStopLoss(), Digits) != stop_loss_price2) || (NormalizeDouble(OrderTakeProfit(), Digits) != take_profit_price2)) {
              if (!OrderModify(OrderTicket(), open_price2, stop_loss_price2, take_profit_price2, OrderExpiration()))
                Print("Error: ", ErrorDescription(_LastError));
                
            }
            break;
          }
          else if (order_type == ORDER_TYPE_BUY)
            break;
        }
    if (i < 0)
      if (OrderSend(symbol, OP_BUYSTOP,  NormalizeDouble(longsize,2), open_price2, 3, stop_loss_price2, take_profit_price2, magic_number2+" Morbid MFI Overhedger BUY STOP",  magic_number2) < 0)
        
               Print("Error: ", ErrorDescription(_LastError));
  }
  else
    for (i = OrdersTotal() - 1; i >= 0; i--)

      if (OrderSelect(i, SELECT_BY_POS))
        if (OrderMagicNumber() == magic_number2 )
          if (OrderType() == ORDER_TYPE_BUY_STOP)
            if (!OrderDelete(OrderTicket()))
              Print("Error: ", ErrorDescription(_LastError));              
              
 
 
i=1;
while (i<21){

if (iFractals(symbol,60,MODE_LOWER,i)  && mfi[i]>46 && Low[i]<dfractals[i+1]) break;

i++;
} 
if (iFractals(symbol,60,MODE_LOWER,i) && mfi[i]>46 && Low[i]<dfractals[i+1]) sellevel = Low[i]-20*Point;

              

shortsize = (nlongs-nshorts)*(100+percentage)/100;             
              
              
// Overhedge For Longs
 if (nshorts<nlongs && sellevel!=0 && i<21 ) {
  
 // if (comparison<Ratio) RemoveStopsandTargets();
    open_price2 = NormalizeDouble(sellevel, Digits);
    stop_loss_price2 = NormalizeDouble(0,Digits);
    take_profit_price2 = NormalizeDouble(weight-1010*Point,Digits);
    for (i = OrdersTotal() - 1; i >= 0; i--)
      if (OrderSelect(i, SELECT_BY_POS))
        if (OrderMagicNumber() == magic_number2) {
          order_type = OrderType();
          if (order_type == ORDER_TYPE_SELL_STOP) {
            if ((NormalizeDouble(OrderOpenPrice(), Digits) != open_price2) || (NormalizeDouble(OrderStopLoss(), Digits) != stop_loss_price2) || (NormalizeDouble(OrderTakeProfit(), Digits) != take_profit_price2)) {
              if (!OrderModify(OrderTicket(), open_price2, stop_loss_price2, take_profit_price2, OrderExpiration()))
                Print("Error: ", ErrorDescription(_LastError));
            }
            break;
          }
                    else if (order_type == ORDER_TYPE_SELL)
            break;
        }
    if (i < 0)
      if (OrderSend(symbol, OP_SELLSTOP, NormalizeDouble(shortsize,2), open_price2, 3, stop_loss_price2, take_profit_price2, magic_number2+"  Morbid MFI Overhedger SELL STOP", magic_number2) < 0)
        Print("Error: ", ErrorDescription(_LastError));
  }
  else
    for (i = OrdersTotal() - 1; i >= 0; i--)
      if (OrderSelect(i, SELECT_BY_POS))
        if (OrderMagicNumber() == magic_number2)
          if (OrderType() == ORDER_TYPE_SELL_STOP)
            if (!OrderDelete(OrderTicket()))
              Print("Error: ", ErrorDescription(_LastError));              
 
 

        
  return(0);
}
}

double RemoveStopsandTargets()
{
   int i;
   for (i = OrdersTotal() - 1; i >= 0; i--){
   if( OrderSelect(i,SELECT_BY_POS, MODE_TRADES)) 
    if( OrderType()==OP_BUYSTOP && MathAbs(OrderOpenPrice()-Ask)<.003) 
       OrderDelete( OrderTicket() );
       else if( OrderType()==OP_SELLSTOP && MathAbs(OrderOpenPrice()-Bid)<.003) 
                 OrderDelete(OrderTicket());}
                 
 
 
 return(0);
 
}



double ChoppinessIndex(int period, int bar)
  {
    double Low0 = 0, High0 = 0, Close1 = 0;
    double TrueRangeLow = 0, TrueRangeHigh = 0, TrueRangeSum = 0, Input = 0;
    double PeriodTrueRangeLow = 999999999, PeriodTrueRangeHigh = 0, PeriodTrueRange = 0;

    for(int k=bar; k<bar+period; k++)
    {
      Low0   = iLow(NULL,15,k);
      High0  = iHigh(NULL,15,k);
      Close1 = iClose(NULL,15,k+1);

      if (Low0<Close1)  TrueRangeLow  = Low0;  else TrueRangeLow  = Close1;
      if (High0>Close1) TrueRangeHigh = High0; else TrueRangeHigh = Close1;
      
      if (TrueRangeLow <PeriodTrueRangeLow)  PeriodTrueRangeLow  = TrueRangeLow;  // find true low of period
      if (TrueRangeHigh>PeriodTrueRangeHigh) PeriodTrueRangeHigh = TrueRangeHigh; // find true high of period

      TrueRangeSum += TrueRangeHigh;
      TrueRangeSum -= TrueRangeLow;
    }

    PeriodTrueRange = PeriodTrueRangeHigh - PeriodTrueRangeLow;
    if (PeriodTrueRange==0) PeriodTrueRange = MathPow(10, -12); // avoid possibility of division by zero
    Input = TrueRangeSum / PeriodTrueRange;
    return ((logN(Input, 10, MathPow(10, -12)) / logN(period, 10, MathPow(10, -12))) * 100);
  }
  

double logN(double x, double base, double epsilon)
  {
    double integer = 0.0;
    if ((x < 1) || (base < 1)) return(0);

    while (x < 1)
    {
      integer -= 1;
      x *= base;
    }
  
    while (x >= base)
    {
      integer += 1;
      x /= base;
    }
  
    double partial = 0.5;
    x *= x;
    double decimal = 0.0;

    while (partial > epsilon)
    {
      if (x >= base)
      {
        decimal += partial;
        x = x / base;
      }
      partial *= 0.5;
      x *= x;
    }
    
    return (integer + decimal);
  } 


double StdDev(int shift, int samples)
  {
  double x0=0, x1=0, x2=0;
  for (int m=0; m<samples; m++)
    {
    x0 = ExtMapBuffer[m+shift];
    x1 += x0;
    x2 += MathPow(x0,2);
    }
  return(MathSqrt((x2-(x1*x1/samples))/(samples-1))); // minimum samples is 2, enforced in the init section
}

Here’s a gray divergence…