﻿//+------------------------------------------------------------------+
//|                                              ReturnMatrix.mqh    |
//|               Intraday Return Heatmap — Matrix Aggregation Layer |
//+------------------------------------------------------------------+
#ifndef RETURN_MATRIX_MQH
#define RETURN_MATRIX_MQH

//--- Matrix dimensions
#define HEATMAP_DAYS  5   // Monday through Friday
#define HEATMAP_HOURS 24  // Hours 0 through 23

//+------------------------------------------------------------------+
//| CReturnMatrix                                                    |
//| Accumulates percentage bar returns into a 5x24 matrix indexed    |
//| by day-of-week (0=Monday..4=Friday) and hour-of-day (0..23).     |
//| Provides arithmetic average computation per cell after the       |
//| full historical scan is complete.                                |
//+------------------------------------------------------------------+
class CReturnMatrix
  {
private:
   double            m_sum[HEATMAP_DAYS][HEATMAP_HOURS];    // Accumulated returns
   int               m_count[HEATMAP_DAYS][HEATMAP_HOURS];  // Sample counts
   double            m_avg[HEATMAP_DAYS][HEATMAP_HOURS];    // Computed averages
   int               m_total_samples;                       // Valid bars processed

public:
                     CReturnMatrix(void);
                    ~CReturnMatrix(void);

   void              Reset(void);
   bool              Accumulate(int day_index, int hour_index, double ret);
   void              ComputeAverages(void);

   double            GetAverage(int day_index, int hour_index) const;
   int               GetCount(int day_index, int hour_index)   const;
   int               GetTotalSamples(void)                     const;
  };

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CReturnMatrix::CReturnMatrix(void)
  {
   m_total_samples = 0;
   Reset();
  }

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CReturnMatrix::~CReturnMatrix(void)
  {
  }

//+------------------------------------------------------------------+
//| Clear all accumulators and counters                              |
//+------------------------------------------------------------------+
void CReturnMatrix::Reset(void)
  {
   m_total_samples = 0;

   for(int d = 0; d < HEATMAP_DAYS; d++)
     {
      for(int h = 0; h < HEATMAP_HOURS; h++)
        {
         m_sum[d][h]   = 0.0;
         m_count[d][h] = 0;
         m_avg[d][h]   = 0.0;
        }
     }
  }

//+------------------------------------------------------------------+
//| Accumulate one bar return into the correct cell                  |
//+------------------------------------------------------------------+
bool CReturnMatrix::Accumulate(int day_index, int hour_index, double ret)
  {
//--- validate cell indices before writing
   if(day_index < 0 || day_index >= HEATMAP_DAYS)
      return(false);
   if(hour_index < 0 || hour_index >= HEATMAP_HOURS)
      return(false);

//--- add return to accumulator and increment sample count
   m_sum[day_index][hour_index]   += ret;
   m_count[day_index][hour_index] += 1;
   m_total_samples++;

   return(true);
  }

//+------------------------------------------------------------------+
//| Compute average returns for all cells after the full scan        |
//+------------------------------------------------------------------+
void CReturnMatrix::ComputeAverages(void)
  {
   for(int d = 0; d < HEATMAP_DAYS; d++)
     {
      for(int h = 0; h < HEATMAP_HOURS; h++)
        {
         if(m_count[d][h] > 0)
            m_avg[d][h] = m_sum[d][h] / (double)m_count[d][h];
         else
            m_avg[d][h] = 0.0; // Neutral for cells with no samples
        }
     }
  }

//+------------------------------------------------------------------+
//| Return the computed average for a given cell                     |
//+------------------------------------------------------------------+
double CReturnMatrix::GetAverage(int day_index, int hour_index) const
  {
   if(day_index < 0 || day_index >= HEATMAP_DAYS)
      return(0.0);
   if(hour_index < 0 || hour_index >= HEATMAP_HOURS)
      return(0.0);
   return(m_avg[day_index][hour_index]);
  }

//+------------------------------------------------------------------+
//| Return the sample count for a given cell                         |
//+------------------------------------------------------------------+
int CReturnMatrix::GetCount(int day_index, int hour_index) const
  {
   if(day_index < 0 || day_index >= HEATMAP_DAYS)
      return(0);
   if(hour_index < 0 || hour_index >= HEATMAP_HOURS)
      return(0);
   return(m_count[day_index][hour_index]);
  }

//+------------------------------------------------------------------+
//| Return the total number of valid bars accumulated                |
//+------------------------------------------------------------------+
int CReturnMatrix::GetTotalSamples(void) const
  {
   return(m_total_samples);
  }

#endif // RETURN_MATRIX_MQH
//+------------------------------------------------------------------+