//+------------------------------------------------------------------+
//|                                                  CM_Strength.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window

#define BullColor Lime
#define BearColor Red

#define NONE 0
#define DOWN -1
#define UP 1

enum fractal {basic_type=0,pyramide_type=1};


sinput string masterPreamble = "FR_Vol_111_BO_Counter_";
sinput int UpdateInSeconds  = 2;
sinput int xAnchor = 600;
sinput int yAnchor = 100;
sinput int TF_1 = 15;

sinput fractal fractalType = pyramide_type;

int panelWidth = 500;
int panelHeight = 400;

int xWidth = 50;
int yHeight = 20;
int xSpace = 10;
int ySpace = 5;
color ClrText = clrWhiteSmoke;
color ClrBackground = clrBlack;
color ClrBorder = clrBlack;
int fontSize = 8;

bool                      UseDefaultPairs            = true;              // Use the default 28 pairs
string                    OwnPairs                   = "";                // Comma seperated own pair list

string DefaultPairs[28] = {"AUDCAD","AUDCHF","AUDJPY","AUDNZD","AUDUSD","CADCHF","CADJPY","CHFJPY","EURAUD","EURCAD","EURCHF","EURGBP","EURJPY","EURNZD","EURUSD","GBPAUD","GBPCAD","GBPCHF","GBPJPY","GBPNZD","GBPUSD","NZDCAD","NZDCHF","NZDJPY","NZDUSD","USDCAD","USDCHF","USDJPY"};
string TradePairs[];
string curr[8] = {"EUR", "GBP", "AUD", "NZD", "CHF", "CAD", "JPY", "USD"};


double currstrength[8];
double prevstrength[8];
string postfix=StringSubstr(Symbol(),6,6);

struct pairinf {
   string   Quoted;
   double PairPip;
   int pipsfactor;
   double Pips;
   double PipsSig;
   double Pipsprev;
   double Spread;
   double point;
   int lastSignal;
   string    base;
   string    quote;   
}; pairinf pairinfo[28];

struct currency 
  {
   string            curr;
   double            strength;
   double            prevstrength;
   double            crs;
   int               sync;
   datetime          lastbar;
   int               fractalCounter;
   
  }
; currency currencies[8];

struct signal { 
   string symbol;

   double bid;
   double point;   

   double fractalUp;
   double fractalDn;
   
}; signal signals[28];

string panelName;

static datetime _timer;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping

  string s;
  string name;
    s = masterPreamble; //_symbolPair;
    //s = Symbol();
    for (int i = ObjectsTotal() - 1; i >= 0; i--)
    {
        name = ObjectName(i);
        if (StringSubstr(name, 0, StringLen(s)) == s)
        {
            ObjectDelete(name);
        }
    }
   
  for (int i=0;i<8;i++)
      currencies[i].curr = curr[i];
      
       
   for (int i = 0; i < 28; i++)
   {
      pairinfo[i].base = StringSubstr(DefaultPairs[i],0,3);
      pairinfo[i].quote = StringSubstr(DefaultPairs[i],3,3);
      
      //Alert("base-  " + pairinfo[i].base);
   
      if (MarketInfo(pairinfo[i].Quoted ,MODE_DIGITS) == 4 || MarketInfo(pairinfo[i].Quoted ,MODE_DIGITS) == 2) {
         pairinfo[i].PairPip = MarketInfo(pairinfo[i].Quoted ,MODE_POINT);
         pairinfo[i].pipsfactor = 1;
      } else { 
         pairinfo[i].PairPip = MarketInfo(pairinfo[i].Quoted ,MODE_POINT)*10;
         pairinfo[i].pipsfactor = 10;
      }
 
   }
   
   for (int q = 0; q < 28; q++)
   {

      signals[q].fractalUp = 0;
      signals[q].fractalDn = 0;
      signals[q].fractalUp = getUpperFractal(pairinfo[q].Quoted, TF_1, fractalType);
      signals[q].fractalDn = getLowerFractal(pairinfo[q].Quoted, TF_1, fractalType);
   }

   _timer = 0;
   displayMeter();

   EventSetTimer(2);




//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
  
  
  //+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
  string s;
  string name;
    s = masterPreamble; //_symbolPair;
    //s = Symbol();
    for (int i = ObjectsTotal() - 1; i >= 0; i--)
    {
        name = ObjectName(i);
        if (StringSubstr(name, 0, StringLen(s)) == s)
        {
            ObjectDelete(name);
        }
    }

   EventKillTimer();
   //ObjectsDeleteAll();
      
  }

//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   
   if (_timer != iTime("EURUSD", TF_1, 0))
   {
      _timer = iTime("EURUSD", TF_1, 0);
      
      for (int y=0; y < 28; y++)
      {
         signals[y].fractalUp = getUpperFractal(pairinfo[y].Quoted, TF_1, fractalType);
         signals[y].fractalDn = getLowerFractal(pairinfo[y].Quoted, TF_1, fractalType);
      }
      displayMeter();
   
   }
   //GetSignals();
   //displayMeter();
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
   
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+ 
void displayMeter() {
   
   string labelName = masterPreamble + "Header";
   string headerText = "Fractal BO volume"; //"TF: " + IntegerToString(TF_1,1) + ", P: " + IntegerToString(Period_1);
   
   // set the panel
   panelWidth = 0;
   panelWidth = panelWidth + 100;

   panelWidth = panelWidth + 3 * xSpace; // + xWidth;
   panelHeight = 9 * yHeight + 10 * ySpace;
   panelName = masterPreamble + "MainPanel";
   SetPanel(panelName,0,xAnchor, yAnchor - 20,panelWidth,panelHeight + 20,clrBlack,clrWhiteSmoke,3);
   SetText(masterPreamble + "_label_indiName","Fractal BO volume",xAnchor + xSpace,yAnchor - 15,ClrText, fontSize);
   SetText(masterPreamble + "_label_indiName2","TF: " + IntegerToString(TF_1,1),xAnchor + xSpace,yAnchor + 5,ClrText, fontSize);
   
   // reset counters
   for (int z=0; z < 8; z++)
   {
      currencies[z].fractalCounter = 0;
   }
   // surf through the pairs and update counters
   for (int y = 0; y < 28; y++)
   {
      for (int yy = 0; yy < 8; yy++)
      {
         if (pairinfo[y].base == curr[yy])
         {
            if ((iVolume(pairinfo[y].Quoted,TF_1,1) > signals[y].fractalUp) &&  (iVolume(pairinfo[y].Quoted,TF_1,2) < signals[y].fractalUp))
            {
               currencies[yy].fractalCounter++;
            }
         }
         if (pairinfo[y].quote == curr[yy])
         {
            if ((iVolume(pairinfo[y].Quoted,TF_1,1) > signals[y].fractalUp) &&  (iVolume(pairinfo[y].Quoted,TF_1,2) < signals[y].fractalUp))
            {
               currencies[yy].fractalCounter--;
            }
         }
         if (pairinfo[y].base == curr[yy])
         {
            if ((iVolume(pairinfo[y].Quoted,TF_1,1) < signals[y].fractalDn) && (iVolume(pairinfo[y].Quoted,TF_1,2) > signals[y].fractalDn))
            {
               currencies[yy].fractalCounter--;
            }
         }
         if (pairinfo[y].quote == curr[yy])
         {
            if ((iVolume(pairinfo[y].Quoted,TF_1,1) < signals[y].fractalDn) && (iVolume(pairinfo[y].Quoted,TF_1,2) > signals[y].fractalDn))
            {
               currencies[yy].fractalCounter++;
            }
         }
      }
   }
   
   // display the values
   for (int m = 0; m < 8; m++) 
   {
      panelName = masterPreamble + "panel_" + curr[m];
      labelName = masterPreamble + "label_" + curr[m];
      SetPanel(panelName, 0, xAnchor + xSpace, yAnchor + (m + 1) * (yHeight + ySpace),xWidth, yHeight, ClrBackground,ClrBorder,1);
      SetText(labelName, curr[m],xAnchor+15, yAnchor + (m + 1) * (yHeight + ySpace) + 2,ClrText,fontSize);
      
      panelName = masterPreamble + "panel_Value_" + curr[m];
      SetPanel(panelName, 0, xAnchor + 2 * xSpace + xWidth, yAnchor + (m + 1) * (yHeight + ySpace),xWidth, yHeight, ClrBackground,ClrBorder,1);
      labelName = masterPreamble + "label_Value_" + curr[m];
      
      if (currencies[m].fractalCounter > 0)
      {
         SetText(labelName, IntegerToString(currencies[m].fractalCounter,1),xAnchor + 2 * xSpace + xWidth + 15, yAnchor + (m + 1) * (yHeight + ySpace) + 3,clrLime,fontSize);
      }
      else if (currencies[m].fractalCounter < 0)
      {
         SetText(labelName, IntegerToString(currencies[m].fractalCounter,1),xAnchor + 2 * xSpace + xWidth + 15, yAnchor + (m + 1) * (yHeight + ySpace) + 3,clrRed,fontSize);
      }
      else
      {
         SetText(labelName, IntegerToString(currencies[m].fractalCounter,1),xAnchor + 2 * xSpace + xWidth + 15, yAnchor + (m + 1) * (yHeight + ySpace) + 3,ClrText,fontSize);
            
      }
   }

   ChartRedraw(); 
}


//+------------------------------------------------------------------+
void SetText(string name,string text,int x,int y,color colour,int fontsize=12)
  {
   if (ObjectFind(0,name)<0)
      ObjectCreate(0,name,OBJ_LABEL,0,0,0);

    ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
    ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
    ObjectSetInteger(0,name,OBJPROP_COLOR,colour);
    ObjectSetInteger(0,name,OBJPROP_FONTSIZE,fontsize);
    ObjectSetInteger(0,name,OBJPROP_CORNER,CORNER_LEFT_UPPER);
    ObjectSetString(0,name,OBJPROP_TEXT,text);
  } 
  
//+------------------------------------------------------------------+
void SetObjText(string name,string CharToStr,int x,int y,color colour,int fontsize=12)
  {
   if(ObjectFind(0,name)<0)
      ObjectCreate(0,name,OBJ_LABEL,0,0,0);

   ObjectSetInteger(0,name,OBJPROP_FONTSIZE,fontsize);
   ObjectSetInteger(0,name,OBJPROP_COLOR,colour);
   ObjectSetInteger(0,name,OBJPROP_BACK,false);
   ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
   ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
   ObjectSetString(0,name,OBJPROP_TEXT,CharToStr);
   ObjectSetString(0,name,OBJPROP_FONT,"Wingdings");
  } 
//-----------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SetPanel(string name,int sub_window,int x,int y,int width,int height,color bg_color,color border_clr,int border_width)
  {
   if(ObjectCreate(0,name,OBJ_RECTANGLE_LABEL,sub_window,0,0))
     {
      ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
      ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
      ObjectSetInteger(0,name,OBJPROP_XSIZE,width);
      ObjectSetInteger(0,name,OBJPROP_YSIZE,height);
      ObjectSetInteger(0,name,OBJPROP_BGCOLOR,bg_color);
      ObjectSetInteger(0,name,OBJPROP_BORDER_TYPE,BORDER_FLAT);
      ObjectSetInteger(0,name,OBJPROP_WIDTH,border_width);
      ObjectSetInteger(0,name,OBJPROP_CORNER,CORNER_LEFT_UPPER);
      //ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
      ObjectSetInteger(0,name,OBJPROP_BACK,true);
      ObjectSetInteger(0,name,OBJPROP_SELECTABLE,0);
      ObjectSetInteger(0,name,OBJPROP_SELECTED,0);
      //ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
      ObjectSetInteger(0,name,OBJPROP_ZORDER,0);
     }
   ObjectSetInteger(0,name,OBJPROP_BGCOLOR,bg_color);
  }
  
double getUpperFractal(string _symbol, int _timeFrame, fractal _fractalType)
{
   double tmpValue;
   if (_fractalType == pyramide_type)
   {
      for (int u = 0; u < 50; u++)
      {
         tmpValue = iVolume(_symbol, _timeFrame, u+3);
         if ((tmpValue > iVolume(_symbol, _timeFrame, u+2))
               && (iVolume(_symbol, _timeFrame, u+2) > iVolume(_symbol, _timeFrame, u+1))
               && (tmpValue > iVolume(_symbol, _timeFrame, u+4))
               && (iVolume(_symbol, _timeFrame, u+4) > iVolume(_symbol, _timeFrame, u+5))
               )
               {
                  return iVolume(_symbol, _timeFrame, u+3);
               }
      }
   }
   else
   {
      for (int u = 0; u < 50; u++)
      {
         tmpValue = iVolume(_symbol, _timeFrame, u+3);
         if ((tmpValue > iVolume(_symbol, _timeFrame, u+2))
               && (tmpValue > iVolume(_symbol, _timeFrame, u+1))
               && (tmpValue > iVolume(_symbol, _timeFrame, u+4))
               && (tmpValue > iVolume(_symbol, _timeFrame, u+5))
               )
               {
                  return iVolume(_symbol, _timeFrame, u+3);
               }
      }
   }
   return 50000;
}

double getLowerFractal(string _symbol, int _timeFrame, fractal _fractalType)
{
   double tmpValue;
   if (_fractalType == pyramide_type)
   {
      for (int u = 0; u < 50; u++)
      {
         tmpValue = iVolume(_symbol, _timeFrame, u+3);
         if ((tmpValue < iVolume(_symbol, _timeFrame, u+2))
               && (iVolume(_symbol, _timeFrame, u+2) < iLow(_symbol, _timeFrame, u+1))
               && (tmpValue < iVolume(_symbol, _timeFrame, u+4))
               && (iVolume(_symbol, _timeFrame, u+4) < iLow(_symbol, _timeFrame, u+5))
               )
               {
                  return iVolume(_symbol, _timeFrame, u+3);
               }
      }
   }
   else
   {
      for (int u = 0; u < 50; u++)
      {
         tmpValue = iVolume(_symbol, _timeFrame, u+3);
         if ((tmpValue < iVolume(_symbol, _timeFrame, u+2))
               && (tmpValue < iVolume(_symbol, _timeFrame, u+1))
               && (tmpValue < iVolume(_symbol, _timeFrame, u+4))
               && (tmpValue < iVolume(_symbol, _timeFrame, u+5))
               )
               {
                  return iVolume(_symbol, _timeFrame, u+3);
               }
      }
   }
   return -50000;
}