//+------------------------------------------------------------------+
//|                                              ModifiedZScore.mqh  |
//+------------------------------------------------------------------+
#ifndef MODIFIED_Z_SCORE_MQH
#define MODIFIED_Z_SCORE_MQH

//+------------------------------------------------------------------+
//| Modified Z-Score Calculator Class                                |
//+------------------------------------------------------------------+
class CModifiedZScore
  {
private:
   static const double K_CONSTANT; // 0.6745

public:
                     CModifiedZScore(void);
                    ~CModifiedZScore(void);
   bool               Calculate(const double &values[],
                                int count,
                                double median_value,
                                double mad_value,
                                double &scores[]);
  };

//--- Normalization constant: reciprocal of Phi^{-1}(0.75) for standard normal
const double CModifiedZScore::K_CONSTANT = 0.6745;

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CModifiedZScore::CModifiedZScore(void)
  {
  }

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CModifiedZScore::~CModifiedZScore(void)
  {
  }

//+------------------------------------------------------------------+
//| Calculate Modified Z-Scores for all observations                 |
//+------------------------------------------------------------------+
bool CModifiedZScore::Calculate(const double &values[],
                                int count,
                                double median_value,
                                double mad_value,
                                double &scores[])
  {
   if(count <= 0)
      return(false);

//--- Guard against zero MAD which would produce division by zero
   if(mad_value <= DBL_EPSILON)
     {
      ArrayResize(scores, count);
      ArrayInitialize(scores, 0.0);
      return(false);
     }

   ArrayResize(scores, count);

   for(int i = 0; i < count; i++)
      scores[i] = K_CONSTANT * (values[i] - median_value) / mad_value; // Modified Z-Score

   return(true);
  }

#endif // MODIFIED_Z_SCORE_MQH
//+------------------------------------------------------------------+