//+------------------------------------------------------------------+
//|                                            Currency heat map.mq4 |
//|                                                           mladen |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 1

//
//
//
//
//

extern string Currencies   = "USD;EUR;GBP;JPY;CHF;CAD;AUD;NZD";
extern string TimeFrames   = "H4;D1";
extern int    Length       = 28;
extern int    Price        = PRICE_CLOSE;

extern color  StrongUp     = LimeGreen;
extern color  WeakUp       = Green;
extern color  NoMove       = DimGray;
extern color  WeakDown     = FireBrick;
extern color  StrongDown   = Red;
extern color  DoesNotExist = Black;
extern bool   UseMSLineDrawFont = false;

//
//
//
//
//

string shortName;
int    shortLength;
int    window;  

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int    cpairsLen;
int    ctimesLen;
string cpairs[];
int    aTimes[];
string addition  = "";
string FontToUse = "Terminal";

//
//
//
//
//

int init()
{
   if (UseMSLineDrawFont) FontToUse = "MS LIneDraw";
   Currencies = stringUpperCase(StringTrimLeft(StringTrimRight(Currencies)));
   if (StringSubstr(Currencies,StringLen(Currencies),1) != ";")
                    Currencies = StringConcatenate(Currencies,";");

      //
      //
      //
      //
      //                                   

      int  s      = 0;
      int  i      = StringFind(Currencies,";",s);
      string current;
         while (i > 0)
         {
            current = StringSubstr(Currencies,s,i-s);
               ArrayResize(cpairs,ArraySize(cpairs)+1);
                           cpairs[ArraySize(cpairs)-1] = current;
                           s = i + 1;
                           i = StringFind(Currencies,";",s);
         }
      cpairsLen = ArraySize(cpairs);

      //
      //
      //
      //
      //

      TimeFrames = stringUpperCase(StringTrimLeft(StringTrimRight(TimeFrames)));
      if (StringSubstr(TimeFrames,StringLen(TimeFrames),1) != ";")
                       TimeFrames = StringConcatenate(TimeFrames,";");

         //
         //
         //
         //
         //                                   
            
         s = 0;
         i = StringFind(TimeFrames,";",s);
         int time;
            while (i > 0)
            {
               current = StringSubstr(TimeFrames,s,i-s);
               time    = stringToTimeFrame(current);
               if (time > 0) {
                     ArrayResize(aTimes,ArraySize(aTimes)+1);
                                 aTimes[ArraySize(aTimes)-1] = time; }
                                 s = i + 1;
                                     i = StringFind(TimeFrames,";",s);
            }
      ctimesLen = ArraySize(aTimes);
      
   //
   //
   //
   //
   //
   
   if (IsMini()) addition="m";
      shortName   = MakeUniqueName("Velocity CHM ","");
      shortLength = StringLen(shortName);
      IndicatorShortName(shortName);
   return(0);
}

//
//
//
//
//

int deinit()
{
   clearObjects();
   return(0);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int start()
{
   string name;
   int    gaph = (cpairsLen*66+10);
   int    gapv = (cpairsLen*15+20);
   int    i,k,t;

         window = WindowFind(shortName);  
   
   //
   //
   //
   //
   //

      for (t = 0; t < ctimesLen; t++ )
      {
         name = shortName+"t"+t+i;
         if (ObjectFind(name) == -1)
             ObjectCreate(name,OBJ_LABEL,window,0,0,0,0);
                ObjectSet(name,OBJPROP_XDISTANCE,5 +(t%2)*30);
                ObjectSet(name,OBJPROP_YDISTANCE,20+(t/2)*15);
                ObjectSetText(name,timeFrameToString(aTimes[t]),10,"Arial Bold");

         //
         //
         //
         //
         //
         
         for (i = 0; i < cpairsLen; i++)
         {
            name = shortName+"h"+t+i;
            if (ObjectFind(name) == -1)
                ObjectCreate(name,OBJ_LABEL,window,0,0,0,0);
                   ObjectSet(name,OBJPROP_XDISTANCE,i*66+120+gaph*(t%2));
                   ObjectSet(name,OBJPROP_YDISTANCE,       1+gapv*(t/2));
                   ObjectSetText(name,cpairs[i],10,"Arial Bold");
            if ((t%2)>0) continue;
            name = shortName+"v"+t+i;
            if (ObjectFind(name) == -1)
               ObjectCreate(name,OBJ_LABEL,window,0,0,0,0);
                ObjectSet(name,OBJPROP_XDISTANCE,     65);
                ObjectSet(name,OBJPROP_YDISTANCE,i*15+20+gapv*(t/2));
                ObjectSetText(name,cpairs[i],10,"Arial Bold");
         }                
      }
      
   //
   //
   //
   //
   //      

   for (t = 0;   t < ctimesLen; t++)
   for (i = 0;   i < cpairsLen; i++)
   for (k = i+1; k < cpairsLen; k++)
   {
      string symbol = cpairs[i]+cpairs[k]+addition;
      double price  = iClose(symbol,aTimes[t],0);
      bool   normal = true;
      bool   exist  = true;
         
         if (price == 0)
            {
               symbol = cpairs[k]+cpairs[i]+addition;
               price  = iClose(symbol,aTimes[t],0);
               normal = false;
            }                  
         if (price == 0) exist = false;
      
      double vel1 = iVelocity(iMA(symbol,aTimes[t],1,0,MODE_SMA,Price,0),Length,0,0);
      double vel2 = iVelocity(iMA(symbol,aTimes[t],1,0,MODE_SMA,Price,1),Length,1,1);        
         
      //
      //
      //
      //
      //
       
      for (int l=0; l<2; l++)
      {  
         color  theColor = DoesNotExist;
            if (exist)
            {
               if (!normal)
                  while (true)
                  {
                     if (vel1 > vel2 && vel1 > 0) { theColor = StrongUp;   break; }
                     if (vel1 > vel2)             { theColor = WeakUp;     break; }
                     if (vel1 == vel2)            { theColor = NoMove;     break; }
                     if (vel1 < vel2 && vel1 < 0) { theColor = StrongDown; break; }
                                                    theColor = WeakDown;   break; 
                  }
               else               
                  while (true)
                  {
                     if (vel1 > vel2 && vel1 > 0) { theColor = StrongDown; break; }
                     if (vel1 > vel2)             { theColor = WeakDown;   break; }
                     if (vel1 == vel2)            { theColor = NoMove;     break; }
                     if (vel1 < vel2 && vel1 < 0) { theColor = StrongUp;   break; }
                                                    theColor = WeakUp;     break; 
                  }
            }
            
            //
            //
            //
            //
            //
            
            name = shortName+t+k+i;
            if (ObjectFind(name) == -1)
                  ObjectCreate(name,OBJ_LABEL,window,0,0,0,0);
                  ObjectSet(name,OBJPROP_XDISTANCE,i*66+100+gaph*(t%2));
                  ObjectSet(name,OBJPROP_YDISTANCE,k*15+ 20+gapv*(t/2));
                  ObjectSetText(name,"лллллллл",10,FontToUse,theColor);
            int tmp = k; k = i; i = tmp;
            normal = (!normal);
      }                                    
   }
   return(0);
}


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

bool   IsMini() { return(StringFind(Symbol(),"m") > -1); }
string MakeUniqueName(string first, string rest)
{
   string result = first+(MathRand()%1001)+rest;

   while (WindowFind(result)> 0)
          result = first+(MathRand()%1001)+rest;
   return(result);
}

//
//
//
//
//

void clearObjects()
{
   for (int i = ObjectsTotal(); i>=0; i--)
   {
         string name = ObjectName(i);
         if (StringSubstr(name,0,shortLength) == shortName) ObjectDelete(name);
   }         
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

double prices[][2];
double iVelocity(double price, double length, int i, int instanceNo=0)
{
   if (ArraySize(prices)!=Bars) ArrayResize(prices,Bars); i=Bars-i-1;
   
      prices[i][instanceNo] = price;
      double suma = 0.0, sumwa=0;
      double sumb = 0.0, sumwb=0;

      for(int k=0; k<length; k++)
      {
         double weight = length-k;
            suma  += prices[i-k][instanceNo] * weight;
            sumb  += prices[i-k][instanceNo] * weight * weight;
            sumwa += weight;
            sumwb += weight*weight;
      }
   return(sumb/sumwb-suma/sumwa);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

//
//
//
//
//

int stringToTimeFrame(string tfs)
{
   tfs = stringUpperCase(tfs);
   for (int i=ArraySize(iTfTable)-1; i>=0; i--)
         if (tfs==sTfTable[i] || tfs==""+iTfTable[i]) return(MathMax(iTfTable[i],Period()));
                                                      return(Period());
}
string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}

//
//
//
//
//

string stringUpperCase(string str)
{
   string   s = str;

   for (int length=StringLen(str)-1; length>=0; length--)
   {
      int tchar = StringGetChar(s, length);
         if((tchar > 96 && tchar < 123) || (tchar > 223 && tchar < 256))
                     s = StringSetChar(s, length, tchar - 32);
         else if(tchar > -33 && tchar < 0)
                     s = StringSetChar(s, length, tchar + 224);
   }
return(s);
}

