//+------------------------------------------------------------------+
//|                                                    MPO Indicator  |
//|                                          ©2023 Your Name or Firm  |
//+------------------------------------------------------------------+
#property copyright "©2023 Your Name or Firm"
#property link      "yourwebsite.com"
#property version   "1.01"
#property description "Market Phase Oscillator (MPO)"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
#property indicator_minimum 0

//--- plot MPO
#property indicator_label1  "MPO"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

//--- input parameters
input int InpPeriodADX = 14; // Period for ADX
input int InpPeriodATR = 14; // Period for ATR

//--- indicator buffers
double MPOBuffer[];

//--- indicator handles
int ATR_Handle;
int ADX_Handle;

//--- arrays for indicator data
double ATRBuffer[];
double ADXBuffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- Set the buffer as indicator buffer
   SetIndexBuffer(0, MPOBuffer, INDICATOR_DATA);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, InpPeriodATR);
   PlotIndexSetInteger(0, PLOT_SHOW_DATA, true);
   IndicatorSetInteger(INDICATOR_DIGITS, _Digits + 2);

   //--- Create ATR handle
   ATR_Handle = iATR(_Symbol, PERIOD_CURRENT, InpPeriodATR);
   if(ATR_Handle == INVALID_HANDLE)
     {
      Print("Failed to create ATR indicator handle");
      return(INIT_FAILED);
     }

   //--- Create ADX handle
   ADX_Handle = iADX(_Symbol, PERIOD_CURRENT, InpPeriodADX);
   if(ADX_Handle == INVALID_HANDLE)
     {
      Print("Failed to create ADX indicator handle");
      return(INIT_FAILED);
     }

   //--- Set indicator levels (Optional: Add threshold lines)
   IndicatorSetInteger(INDICATOR_LEVELS, 2);
   IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, 15.0);
   IndicatorSetDouble(INDICATOR_LEVELVALUE, 1, 30.0);
   IndicatorSetInteger(INDICATOR_LEVELCOLOR, 0, clrRed);
   IndicatorSetInteger(INDICATOR_LEVELCOLOR, 1, clrGreen);
   IndicatorSetInteger(INDICATOR_LEVELWIDTH, 0, 1);
   IndicatorSetInteger(INDICATOR_LEVELWIDTH, 1, 1);
   IndicatorSetInteger(INDICATOR_LEVELSTYLE, 0, STYLE_DASH);
   IndicatorSetInteger(INDICATOR_LEVELSTYLE, 1, STYLE_DASH);

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   //--- Release indicator handles
   if(ATR_Handle != INVALID_HANDLE)
      IndicatorRelease(ATR_Handle);
   if(ADX_Handle != INVALID_HANDLE)
      IndicatorRelease(ADX_Handle);
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime& time[],
                const double& open[],
                const double& high[],
                const double& low[],
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[])
  {
   //--- Check for sufficient bars
   if(rates_total < InpPeriodATR || rates_total < InpPeriodADX)
      return(0);

   int bars_needed = MathMax(InpPeriodATR, InpPeriodADX);
   int limit = rates_total - prev_calculated;

   if(prev_calculated > 0)
      limit++; // To recalculate the last bar

   //--- Copy ATR data
   if(CopyBuffer(ATR_Handle, 0, 0, rates_total, ATRBuffer) <= 0)
     {
      Print("Failed to copy ATR data, error code: ", GetLastError());
      return(0);
     }

   //--- Copy ADX data
   if(CopyBuffer(ADX_Handle, 0, 0, rates_total, ADXBuffer) <= 0)
     {
      Print("Failed to copy ADX data, error code: ", GetLastError());
      return(0);
     }

   //--- Calculate MPO
   for(int i = rates_total - limit; i < rates_total; i++)
     {
      if(ATRBuffer[i] != 0.0)
        {
         MPOBuffer[i] = (ADXBuffer[i] / ATRBuffer[i])/100;
        }
      else
        {
         MPOBuffer[i] = 0.0;
        }
     }

   return(rates_total);
  }

create a better version of this strategy at detecting a consilidation amrket