﻿//+------------------------------------------------------------------+
//|                                              HeatmapColorMap.mqh |
//|              Intraday Return Heatmap — Color Interpolation Layer |
//+------------------------------------------------------------------+
#ifndef HEATMAP_COLOR_MAP_MQH
#define HEATMAP_COLOR_MAP_MQH

#include <Canvas\Canvas.mqh>

//+------------------------------------------------------------------+
//| CHeatmapColorMap                                                 |
//| Converts an average return value into an ARGB color suitable     |
//| for CCanvas rendering. Normalization is relative to the maximum  |
//| absolute return observed in the full matrix, ensuring the color  |
//| scale uses its full dynamic range for any instrument.             |
//+------------------------------------------------------------------+
class CHeatmapColorMap
  {
public:
                     CHeatmapColorMap(void);
                    ~CHeatmapColorMap(void);

   static uint       ReturnToColor(double avg_return, double max_abs_return);
   static uint       NeutralColor(void);
  };

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CHeatmapColorMap::CHeatmapColorMap(void)
  {
  }

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CHeatmapColorMap::~CHeatmapColorMap(void)
  {
  }

//+------------------------------------------------------------------+
//| Map an average return to an ARGB color value                      |
//+------------------------------------------------------------------+
uint CHeatmapColorMap::ReturnToColor(double avg_return, double max_abs_return)
  {
//--- if no meaningful range exists, return neutral color
   if(max_abs_return < 1e-10)
      return(NeutralColor());

//--- normalize return to [-1, +1] range relative to observed maximum
   double norm = avg_return / max_abs_return;

//--- clamp to valid interpolation range
   if(norm > 1.0)
      norm = 1.0;
   if(norm < -1.0)
      norm = -1.0;

   int r = 0;
   int g = 0;
   int b = 0;

   if(norm >= 0.0)
     {
      //--- positive: interpolate from gray toward pure green as norm → 1
      r = (int)(50.0 + (1.0 - norm) * 150.0);
      g = 200;
      b = (int)(50.0 + (1.0 - norm) * 150.0);
     }
   else
     {
      //--- negative: interpolate from gray toward pure red as norm → -1
      r = 200;
      g = (int)(50.0 + (1.0 + norm) * 150.0);
      b = (int)(50.0 + (1.0 + norm) * 150.0);
     }

//--- clamp RGB components to valid byte range
   if(r < 0)
      r = 0;
   if(r > 255)
      r = 255;
   if(g < 0)
      g = 0;
   if(g > 255)
      g = 255;
   if(b < 0)
      b = 0;
   if(b > 255)
      b = 255;

//--- return as ARGB with full opacity
   return(ARGB(255, r, g, b));
  }

//+------------------------------------------------------------------+
//| Return the neutral color used for zero-return or empty cells     |
//+------------------------------------------------------------------+
uint CHeatmapColorMap::NeutralColor(void)
  {
   return(ARGB(255, 200, 200, 200)); // Light gray
  }

#endif // HEATMAP_COLOR_MAP_MQH
//+------------------------------------------------------------------+