﻿//+------------------------------------------------------------------+
//|                                            HeatmapStatistics.mqh |
//|              Intraday Return Heatmap — Statistical Summary Layer |
//+------------------------------------------------------------------+
#ifndef HEATMAP_STATISTICS_MQH
#define HEATMAP_STATISTICS_MQH

#include "ReturnMatrix.mqh"

//+------------------------------------------------------------------+
//| CHeatmapStatistics                                               |
//| Scans a completed CReturnMatrix to extract the summary values    |
//| required for color normalization and diagnostic logging:         |
//| minimum average return, maximum average return, and maximum      |
//| absolute average return used as the normalization denominator.   |
//+------------------------------------------------------------------+
class CHeatmapStatistics
  {
private:
   double            m_min_avg;    // Minimum average return in matrix
   double            m_max_avg;    // Maximum average return in matrix
   double            m_max_abs;    // Maximum absolute average return
   int               m_cell_count; // Number of cells with samples

public:
                     CHeatmapStatistics(void);
                    ~CHeatmapStatistics(void);

   void              Compute(CReturnMatrix &ret_matrix);

   double            MinAvg(void)    const;
   double            MaxAvg(void)    const;
   double            MaxAbs(void)    const;
   int               CellCount(void) const;

   void              PrintDiagnostics(int total_samples) const;
  };

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CHeatmapStatistics::CHeatmapStatistics(void)
  {
   m_min_avg    =  1e38;
   m_max_avg    = -1e38;
   m_max_abs    =  0.0;
   m_cell_count =  0;
  }

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CHeatmapStatistics::~CHeatmapStatistics(void)
  {
  }

//+------------------------------------------------------------------+
//| Scan the matrix and compute summary statistics                   |
//+------------------------------------------------------------------+
void CHeatmapStatistics::Compute(CReturnMatrix &ret_matrix)
  {
//--- reset before scan to avoid accumulation from prior calls
   m_min_avg    =  1e38;
   m_max_avg    = -1e38;
   m_max_abs    =  0.0;
   m_cell_count =  0;

   for(int d = 0; d < HEATMAP_DAYS; d++)
     {
      for(int h = 0; h < HEATMAP_HOURS; h++)
        {
         if(ret_matrix.GetCount(d, h) == 0)
            continue; // Skip empty cells to avoid distorting extremes

         double avg = ret_matrix.GetAverage(d, h);
         m_cell_count++;

         if(avg < m_min_avg)
            m_min_avg = avg;
         if(avg > m_max_avg)
            m_max_avg = avg;

         double abs_avg = MathAbs(avg);
         if(abs_avg > m_max_abs)
            m_max_abs = abs_avg;
        }
     }

//--- guard against a matrix where no cells had any samples
   if(m_cell_count == 0)
     {
      m_min_avg = 0.0;
      m_max_avg = 0.0;
      m_max_abs = 0.0;
     }
  }

//+------------------------------------------------------------------+
//| Return the minimum average return observed in the matrix          |
//+------------------------------------------------------------------+
double CHeatmapStatistics::MinAvg(void) const
  {
   return(m_min_avg);
  }

//+------------------------------------------------------------------+
//| Return the maximum average return observed in the matrix          |
//+------------------------------------------------------------------+
double CHeatmapStatistics::MaxAvg(void) const
  {
   return(m_max_avg);
  }

//+------------------------------------------------------------------+
//| Return the maximum absolute average return for normalization      |
//+------------------------------------------------------------------+
double CHeatmapStatistics::MaxAbs(void) const
  {
   return(m_max_abs);
  }

//+------------------------------------------------------------------+
//| Return the number of non-empty cells in the matrix                |
//+------------------------------------------------------------------+
int CHeatmapStatistics::CellCount(void) const
  {
   return(m_cell_count);
  }

//+------------------------------------------------------------------+
//| Print diagnostic statistics to the Experts tab                   |
//+------------------------------------------------------------------+
void CHeatmapStatistics::PrintDiagnostics(int total_samples) const
  {
   PrintFormat("[ReturnHeatmap] Processed Bars    = %d", total_samples);
   PrintFormat("[ReturnHeatmap] Max Avg Return    = %s%%",
               DoubleToString(m_max_avg, 4));
   PrintFormat("[ReturnHeatmap] Min Avg Return    = %s%%",
               DoubleToString(m_min_avg, 4));
   PrintFormat("[ReturnHeatmap] Max Abs Return    = %s%%",
               DoubleToString(m_max_abs, 4));
   PrintFormat("[ReturnHeatmap] Cells Rendered    = %d", m_cell_count);
  }

#endif // HEATMAP_STATISTICS_MQH
//+------------------------------------------------------------------+