//+------------------------------------------------------------------+
//|                                           CompositeScore.mqh     |
//+------------------------------------------------------------------+
#ifndef COMPOSITE_SCORE_MQH
#define COMPOSITE_SCORE_MQH

//+------------------------------------------------------------------+
//| Composite Score Class                                            |
//+------------------------------------------------------------------+
class CCompositeScore
  {
public:
                      CCompositeScore(void);
                     ~CCompositeScore(void);
   bool               Calculate(const double &body_scores[],
                                const double &upper_scores[],
                                const double &lower_scores[],
                                const double &volume_scores[],
                                int count,
                                double &composite[]);
   int                CountOutliers(const double &composite[],
                                    int count,
                                    double threshold);
  };

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CCompositeScore::CCompositeScore(void)
  {
  }

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CCompositeScore::~CCompositeScore(void)
  {
  }

//+------------------------------------------------------------------+
//| Compute mean absolute composite score across four features       |
//+------------------------------------------------------------------+
bool CCompositeScore::Calculate(const double &body_scores[],
                                const double &upper_scores[],
                                const double &lower_scores[],
                                const double &volume_scores[],
                                int count,
                                double &composite[])
  {
   if(count <= 0)
      return(false);

   ArrayResize(composite, count);

   for(int i = 0; i < count; i++)
     {
      double sum = MathAbs(body_scores[i])     // Body contribution
                   + MathAbs(upper_scores[i])  // Upper wick contribution
                   + MathAbs(lower_scores[i])  // Lower wick contribution
                   + MathAbs(volume_scores[i]);// Volume contribution

      composite[i] = sum * 0.25;               // Mean absolute score
     }

   return(true);
  }

//+------------------------------------------------------------------+
//| Count bars whose composite score exceeds the threshold           |
//+------------------------------------------------------------------+
int CCompositeScore::CountOutliers(const double &composite[],
                                   int count,
                                   double threshold)
  {
   int outlier_count = 0;

   for(int i = 0; i < count; i++)
     {
      if(composite[i] > threshold)
         outlier_count++; // Increment outlier counter
     }

   return(outlier_count);
  }

#endif // COMPOSITE_SCORE_MQH
//+------------------------------------------------------------------+