/*
xMeterMTF.mq4     
Copyright © 2007, MetaQuotes Software Corp.     
Price Meter System™ ©GPL     

Hartono Setiono
   5/17/2007 Redsigned based on xMeter_mini.mq4 indicator
*/

#property copyright "x Meter System™ ©GPL"
#property link      "forex-tsd dot com"
#property  indicator_chart_window
#property  indicator_buffers 0

#include <stdlib.mqh>
#include <stderror.mqh> 

#define TABSIZE  19                    // scale of currency's power !!!DON'T CHANGE THIS NUMBER!!!
#define ORDER    2                      // available type of order !!!DON'T CHANGE THIS NUMBER!!!

string Id = "xmeter2";
extern bool AccountIsIBFXmini = false;
/*extern*/ bool LoopOnInit=false;

/* You can change any of the following arrays */
   string aTradePair[]= {"GBPJPY"};
   string aPair[]   = {"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDJPY","USDZAR","USDCHF","USDCAD","EURCAD","USDSEK","GBPCAD","USDMXN",
                       "EURJPY","EURGBP","EURCHF","EURAUD","EURNZD","GBPJPY","GBPCHF","USDNOK","EURNOK","USDTRY","EURTRY","EURSEK"};
                       
/* The following can also be changed but both must have the same dimension */
   string aMajor[] = {"USD","EUR","GBP","CHF","CAD","AUD","NZD","JPY","NOK","SEK","TRY","MXN","ZAR"};
   int    aMajorPos[] = {250,230,210,190,170,150,130, 110, 90, 70, 50, 30, 10};


string aOrder[ORDER]    = {"BUY ","SELL "};
int    aTable[TABSIZE]  = {0,3,10,25,40,50,60,75,90,97,100};                 // grade table for currency's power

int PairCount;
int CurrencyCount;
double aMeter[];
double aHigh[];
double aLow[];
double aBid[];
double aAsk[];
double aRatio[];
double aRange[];
double aLookup[];
double aStrength[];
int aIndex[2][];

//+------------------------------------------------------------------+
//     expert initialization function                                |       
//+------------------------------------------------------------------+
int init()
  {
   int err,lastError, ps;
   PairCount=ArrayRange(aPair,0);
   CurrencyCount=ArrayRange(aMajor,0);
   ps=ArrayRange(aMajorPos,0);
   if(CurrencyCount!=ps) Print("The size of array aMajor is not equals to aMajorPos");

   ArrayResize(aMeter,CurrencyCount);
   ArrayResize(aHigh,PairCount);
   ArrayResize(aLow,PairCount);
   ArrayResize(aBid,PairCount);
   ArrayResize(aAsk,PairCount);
   ArrayResize(aRatio,PairCount);
   ArrayResize(aRange,PairCount);
   ArrayResize(aLookup,PairCount);
   ArrayResize(aStrength,PairCount);
   
   init_tradepair_index();
  
//----
   initGraph();
   if (LoopOnInit)
   {
      while (true)                                                           // infinite loop for main program
      {
        if (IsConnected()) main();
        if (!IsConnected()) objectBlank();
        WindowRedraw();
        Sleep(1000);                                                          // give your PC a breath
      }
   }
//----
   return(0);                                                               // end of init function
  }
//+------------------------------------------------------------------+
//     expert deinitialization function                              |       
//+------------------------------------------------------------------+
int deinit()
  {
//----
//   ObjectsDeleteAll(0,OBJ_LABEL);
   DeleteExistingLabels();
   Print("shutdown error - ",ErrorDescription(GetLastError()));                               // system is detached from platform
//----
   return(0);                                                               // end of deinit function
  }
//+------------------------------------------------------------------+
//     expert start function                                         |       
//+------------------------------------------------------------------+
int start()
  {
//----
   if (!LoopOnInit) main();
//----
   return(0);                                                               // end of start funtion
  }
//+------------------------------------------------------------------+
//     expert custom function                                        |       
//+------------------------------------------------------------------+    
void main()                                                                 // this a control center
  {
//----
   double point;
   int    index, pindex, cnt;
   string mySymbol;
   double cmeter;
     
   for (index = 0; index < PairCount; index++)                                // initialize all pairs required value 
   {
      RefreshRates();                                                       // refresh all currency's instrument
      if (AccountIsIBFXmini)
         mySymbol = aPair[index]+'m';                                       // Add "m for IBFX mini
      else
         mySymbol = aPair[index];                        
      point            = GetPoint(mySymbol);                                // get a point basis
      aHigh[index]     = MarketInfo(mySymbol,MODE_HIGH); //iHigh(mySymbol,mTimeFrame,iHighest(mySymbol,mTimeFrame,MODE_HIGH,mPeriod,0));   // find highest
      aLow[index]      = MarketInfo(mySymbol,MODE_LOW); //iLow(mySymbol,mTimeFrame,iLowest(mySymbol,mTimeFrame,MODE_LOW,mPeriod,0));   // find lowest
      aBid[index]      = MarketInfo(mySymbol,MODE_BID);                 // set a last bid
      aAsk[index]      = MarketInfo(mySymbol,MODE_ASK);                 // set a last ask
      aRange[index]    = MathMax((aHigh[index]-aLow[index])/point,1);       // calculate range today
      aRatio[index]    = (aBid[index]-aLow[index])/aRange[index]/point;     // calculate pair ratio
      aLookup[index]   = iLookup(aRatio[index]*100);                        // set a pair grade
      aStrength[index] = 9.9-aLookup[index];                                  // set a pair strengh
   } 

   // calculate all currencies meter         
   for (pindex=0; pindex<CurrencyCount; pindex++)
   { 
     cnt=0; 
     cmeter=0;
     for (index = 0; index < PairCount; index++)                                // initialize all pairs required value 
     {
       if (StringSubstr(aPair[index],0,3)==aMajor[pindex])
       {
        cnt++;
        cmeter = cmeter + aLookup[index];
       }
       if (StringSubstr(aPair[index],3,3)==aMajor[pindex])
       {
        cnt++;
        cmeter = cmeter + aStrength[index];
       }
       if (cnt>0) aMeter[pindex]=NormalizeDouble(cmeter / cnt,1); else aMeter[pindex]=-1;
     }
   }
             
   objectBlank();
   
   for (pindex=0; pindex<CurrencyCount; pindex++)
   {
     paintCurr(pindex, aMeter[pindex]); 
   }
   paintLine();
                                                                            
//----
  }

void init_tradepair_index()
{
  int i,n,tpcount, m1index, m2index;
  string cpair, m1,m2;
  tpcount=ArraySize(aTradePair);
  
  for(n=0; n<tpcount; n++)
  {
    cpair=aTradePair[0];
    m1=StringSubstr(cpair,0,3);
    m2=StringSubstr(cpair,3,3);
    aIndex[0,n]=-1;
    aIndex[1,n]=-1;
    for(i=0;i<CurrencyCount;i++)
    {
      if(m1==aMajor[i]) aIndex[0,n]=i;
      if(m2==aMajor[i]) aIndex[1,n]=i;
    }
    if(aIndex[0,n]==-1 || aIndex[1,n]==-1) 
      Print("Currency Pair : ",cpair," is not tradeable, check array definition!");
  }
}
  
double GetPoint(string mSymbol)
{
 double myPoint = 0.0001, YenPoint = 0.01;
 string mySymbol;
 if (StringSubstr(mySymbol,3,3) == "JPY") return (YenPoint);
 return(myPoint);
}
  
int iLookup(double ratio)                                                   // this function will return a grade value
  {                                                                         // based on its power.
   int   index=-1, i;
   
   if      (ratio <= aTable[0]) index = 0;
   else {
     for (i=1; i<TABSIZE; i++) if(ratio < aTable[i]) {index=i-1;  break; }
     if(index==-1) index=9.9;
   }
   return(index);                                                           // end of iLookup function
  }
  
void initGraph()
  {
   int pindex;
   DeleteExistingLabels();
//   ObjectsDeleteAll(0,OBJ_LABEL);

   for (pindex=0; pindex<CurrencyCount; pindex++)
   { 
   objectCreate(Id + aMajor[pindex]+"_1",aMajorPos[pindex],43);
   objectCreate(Id + aMajor[pindex]+"_2",aMajorPos[pindex],35);
   objectCreate(Id + aMajor[pindex]+"_3",aMajorPos[pindex],27);
   objectCreate(Id + aMajor[pindex]+"_4",aMajorPos[pindex],19);
   objectCreate(Id + aMajor[pindex]+"_5",aMajorPos[pindex],11);
   objectCreate(Id + aMajor[pindex],aMajorPos[pindex]+2,12,aMajor[pindex],7,"Arial Narrow",SkyBlue);
   objectCreate(Id + aMajor[pindex]+"p",aMajorPos[pindex]+4,21,DoubleToStr(9,1),8,"Arial Narrow",Silver);
   }
   
   objectCreate(Id + "line",15,6,"-------------------------------------------------------------------------",10,"Arial",DimGray);  
   objectCreate(Id + "line1",15,27,"-------------------------------------------------------------------------",10,"Arial",DimGray);  
   objectCreate(Id + "line2",15,69,"-------------------------------------------------------------------------",10,"Arial",DimGray);
   objectCreate(Id + "sign",15,1,"»»» Price Powed Meter System™ ©GPL «««",8,"Arial Narrow",DimGray);
   WindowRedraw();
  }
//+------------------------------------------------------------------+
void objectCreate(string name,int x,int y,string text="-",int size=42,
                  string font="Arial",color colour=CLR_NONE)
  {
   ObjectCreate(name,OBJ_LABEL,0,0,0);
   ObjectSet(name,OBJPROP_CORNER,3);
   ObjectSet(name,OBJPROP_COLOR,colour);
   ObjectSet(name,OBJPROP_XDISTANCE,x);
   ObjectSet(name,OBJPROP_YDISTANCE,y);
   ObjectSetText(name,text,size,font,colour);
  }

void objectBlank()
  {
   int pindex;
   
   for (pindex=0; pindex<CurrencyCount; pindex++)
   { 
   ObjectSet(Id + aMajor[pindex]+"_1",OBJPROP_COLOR,CLR_NONE);
   ObjectSet(Id + aMajor[pindex]+"_2",OBJPROP_COLOR,CLR_NONE);
   ObjectSet(Id + aMajor[pindex]+"_3",OBJPROP_COLOR,CLR_NONE);
   ObjectSet(Id + aMajor[pindex]+"_4",OBJPROP_COLOR,CLR_NONE);
   ObjectSet(Id + aMajor[pindex]+"_5",OBJPROP_COLOR,CLR_NONE);
   ObjectSet(Id + aMajor[pindex],OBJPROP_COLOR,CLR_NONE);
   ObjectSet(Id + aMajor[pindex]+"p",OBJPROP_COLOR,CLR_NONE);
   }
  
   ObjectSet(Id + "line1",OBJPROP_COLOR,CLR_NONE);
   ObjectSet(Id + "line2",OBJPROP_COLOR,CLR_NONE); 
  }
  
void paintCurr(int pindex, double value)
{
  if (value > 0) ObjectSet(Id + aMajor[pindex]+"_5",OBJPROP_COLOR,Red);
  if (value > 2) ObjectSet(Id + aMajor[pindex]+"_4",OBJPROP_COLOR,Orange);
  if (value > 4) ObjectSet(Id + aMajor[pindex]+"_3",OBJPROP_COLOR,Gold);   
  if (value > 6) ObjectSet(Id + aMajor[pindex]+"_2",OBJPROP_COLOR,YellowGreen);
  if (value > 7) ObjectSet(Id + aMajor[pindex]+"_1",OBJPROP_COLOR,Lime);
  ObjectSet(Id + aMajor[pindex],OBJPROP_COLOR,SkyBlue);
  ObjectSetText(Id + aMajor[pindex]+"p",DoubleToStr(value,1),8,"Arial Narrow",Silver);
}
  
void paintLine()
  {
   ObjectSet(Id + "line1",OBJPROP_COLOR,DimGray);
   ObjectSet(Id + "line2",OBJPROP_COLOR,DimGray);
  }
  
void DeleteExistingLabels()
{
   int objLabels = ObjectsTotal(OBJ_LABEL);
   string objName;
   
   if (objLabels > 0)
   {
      for (int i = objLabels; i >= 0;i--)
      {
         objName = ObjectName(i);
         if (StringFind(objName,Id, 0) >= 0) { ObjectDelete(objName); continue; }  
      }
   }
}

