//+------------------------------------------------------------------+
//|                                       Display Info All Pairs.mq4 |
//+------------------------------------------------------------------+
//#property strict
#property indicator_chart_window

#include <hanover --- function header b600 (np).mqh>

//extern string   Currencies                   = "AUD,CAD,CHF,EUR,GBP,JPY,NZD,USD,TRY,SGD,DKK,HKD,NOK,SEK,PLN,HUF,CZK,ZAR";
extern string   Currencies                   = "AUD,CAD,CHF,EUR,GBP,JPY,NZD,USD";
extern string   Suffix                       = "";
extern string   FontNameAndSize              = "Courier New,11";
extern string   FontColors                   = "White,Yellow,DodgerBlue,LimeGreen,Tomato,MediumOrchid";
extern string   WindowCornerHposVposVspacing = "0,TL,20,4,14";  // Window, Corner, Start Hpos, Start Vpos, Vert Spacing
extern string   ADRdays                      = "30";
extern string   RefreshPeriod                = "T";
extern bool     FullSymbolIDs                = false;
extern string   ShowBidPriceJPY              = ";':'R4.2";
extern string   ShowBidPriceOther            = ";':'R2.4";
extern string   ShowDailyMove                = ";R+4";
extern string   ShowDailyMovePercent         = ";";
extern string   ShowTodaysRange              = ";R5";
extern string   ShowADR                      = ";'/'R3";
extern string   ShowADRpercent               = ";R4%";
extern string   ShowSpread                   = ";3.1";
extern string   ShowSpreadPercent            = ";' ='R~1.1%";
extern string   ShowTickval                  = ";R4.1";
extern string   ShowSwapLong                 = ";R+3.1";
extern string   ShowSwapShort                = ";R+3.1";
extern string   OutputFile                   = "Info_all_pairs.TXT";
extern string   UniqueID                     = "0";

double   spr, pnt, tickval, bidp, askp, lswap, sswap, Value[12], Testval[12];
int      dig, tf, nC, RefreshEveryXMins, Oper[12], SortField, nFC, FontSize, Window, Corner, HorizPos, VertPos, VertSpacing, alert[12];
string   IndiName, ccy, sym, C[300], sort[300], Mask[12], arr[5], FC[10], FontName;
datetime prev_time;
bool     pairflag;

//+------------------------------------------------------------------+
int init()  {
//+------------------------------------------------------------------+
  RefreshEveryXMins = StrToTF(RefreshPeriod);

  pairflag = false;
  if (Currencies == "")  Currencies = Symbol();
  nC = StrToStringArray(Currencies,C);
  for (int i=0; i<nC; i++)   {
    C[i] = ExpandCcy(C[i]);
    if (StringLen(C[i])>3)   pairflag = true;
  }  
    
  nFC = StrToStringArray(FontColors,FC);  

  StrToStringArray(FontNameAndSize,arr);
  FontName = arr[0];
  FontSize = StrToInteger(arr[1]);

  StrToStringArray(WindowCornerHposVposVspacing,arr);
  Window      = StrToInteger(arr[0]);
  Corner      = 2*(StringFind(StringUpper(arr[1]),"B")>=0) + (StringFind(StringUpper(arr[1]),"R")>=0);
  HorizPos    = StrToInteger(arr[2]);
  VertPos     = StrToInteger(arr[3]);
  VertSpacing = StrToInteger(arr[4]);

  SortField = 1;
  ArrayInitialize(alert,0);
  Mask[00] = extract_mask(ShowBidPriceJPY);         Oper[00] = extract_op( 2,ShowBidPriceJPY);         Testval[00] = extract_val(ShowBidPriceJPY);
  Mask[01] = extract_mask(ShowBidPriceOther);       Oper[01] = extract_op( 2,ShowBidPriceOther);       Testval[01] = extract_val(ShowBidPriceOther);
  Mask[02] = extract_mask(ShowDailyMove);           Oper[02] = extract_op( 3,ShowDailyMove);           Testval[02] = extract_val(ShowDailyMove);
  Mask[03] = extract_mask(ShowDailyMovePercent);    Oper[03] = extract_op( 4,ShowDailyMovePercent);    Testval[03] = extract_val(ShowDailyMovePercent);
  Mask[04] = extract_mask(ShowTodaysRange);         Oper[04] = extract_op( 5,ShowTodaysRange);         Testval[04] = extract_val(ShowTodaysRange);
  Mask[05] = extract_mask(ShowADR);                 Oper[05] = extract_op( 6,ShowADR);                 Testval[05] = extract_val(ShowADR);
  Mask[06] = extract_mask(ShowADRpercent);          Oper[06] = extract_op( 7,ShowADRpercent);          Testval[06] = extract_val(ShowADRpercent);
  Mask[07] = extract_mask(ShowSpread);              Oper[07] = extract_op( 8,ShowSpread);              Testval[07] = extract_val(ShowSpread);
  Mask[08] = extract_mask(ShowSpreadPercent);       Oper[08] = extract_op( 9,ShowSpreadPercent);       Testval[08] = extract_val(ShowSpreadPercent);
  Mask[09] = extract_mask(ShowTickval);             Oper[09] = extract_op(10,ShowTickval);             Testval[09] = extract_val(ShowTickval);
  Mask[10] = extract_mask(ShowSwapLong);            Oper[10] = extract_op(11,ShowSwapLong);            Testval[10] = extract_val(ShowSwapLong);
  Mask[11] = extract_mask(ShowSwapShort);           Oper[11] = extract_op(12,ShowSwapShort);           Testval[11] = extract_val(ShowSwapShort);

  IndiName = "DisplayInfo-" + UniqueID;
  IndicatorShortName(IndiName);

  ccy     = Symbol();
  sym     = Symbol();
  tf      = Period();
  bidp    = MarketInfo(ccy,MODE_BID);
  askp    = MarketInfo(ccy,MODE_ASK);
  pnt     = MarketInfo(ccy,MODE_POINT);
  dig     = MarketInfo(ccy,MODE_DIGITS);
  spr     = MarketInfo(ccy,MODE_SPREAD);
  tickval = MarketInfo(ccy,MODE_TICKVALUE);
  if (dig == 3 || dig == 5) {
    pnt     *= 10;
    spr     /= 10;
    tickval *= 10;
  }  

  prev_time = -9999;
  del_obj();
  int rc=plot_obj();
//  prev_time = -9999;

  if(rc < 0) 
  {
     string possible_suffix = StringSubstr(Symbol(),6,0);
     // Alerts in reverse for readability in the popup.   
     if(StringLen(possible_suffix)> 0 && possible_suffix != Suffix) Alert("...Did you set 'Suffix( =\"",Suffix,"\") correctly?  Should it be \"",possible_suffix,"\" ?");
     Alert("ERROR. No labels were created in init() function.  Problem?");
  }

  return(0);
}

//+------------------------------------------------------------------+
int deinit()  {
//+------------------------------------------------------------------+
  del_obj();
  return(0);
}

//+------------------------------------------------------------------+
int start()  {
//+------------------------------------------------------------------+
  if (RefreshEveryXMins < 0)
    return(0);
  if (RefreshEveryXMins == 0) {
    del_obj();
    plot_obj();    
  }
  else {
    if(prev_time != iTime(sym,RefreshEveryXMins,0))  {
      del_obj();
      plot_obj();
      prev_time = iTime(sym,RefreshEveryXMins,0);
  } }      
  return(0);
}

//+------------------------------------------------------------------+
void del_obj()  {
//+------------------------------------------------------------------+
  int k=0;
  while (k<ObjectsTotal())   {
    string objname = ObjectName(k);
    if (stringSubstrOld(objname,0,StringLen(IndiName)) == IndiName)  
      ObjectDelete(objname);
    else
      k++;
  }    
  return;
}

//+------------------------------------------------------------------+
int plot_obj()   {
//+------------------------------------------------------------------+
  bool valid_pair_found=false;
  ArrayInitializeString(sort);    // array used for sorting
  int h = -1;
  if (StringLen(OutputFile) > 0)
    h = FileOpen(OutputFile,FILE_CSV|FILE_WRITE,'~');
  int c = 0;   // counter for number of valid pairs/instruments
  for (int i=0; i<50; i++)  {
    if (StringLen(C[i]) < 1)   continue;
    for (int j=0; j<50; j++)  {
      if (pairflag)  {
        if (j>0)   continue;
        ccy = C[i] + Suffix;
      } else {
         if (i==j)   continue;
         if (StringLen(C[j]) < 1)   continue;
         ccy = C[i] + C[j] + Suffix;
      }   
      bidp    = MarketInfo(ccy,MODE_BID);
      askp    = MarketInfo(ccy,MODE_ASK);
      pnt     = MarketInfo(ccy,MODE_POINT);
      dig     = MarketInfo(ccy,MODE_DIGITS);
      spr     = MarketInfo(ccy,MODE_SPREAD);
      tickval = MarketInfo(ccy,MODE_TICKVALUE);
      lswap   = MarketInfo(ccy,MODE_SWAPLONG);
      sswap   = MarketInfo(ccy,MODE_SWAPSHORT);
      if (dig == 3 || dig == 5) {
        pnt     *= 10;
        spr     /= 10;
        tickval *= 10;
      }
      if (bidp == 0)  continue;    // not a valid pair/instrument
      valid_pair_found=true;
      c++;
      double sum=0, cnt=0;
      for (int k=1; k<=StrToNumber(ADRdays); k++)   {
        datetime dt = iTime(ccy,PERIOD_D1,k);
        if (TimeDayOfWeek(dt)==0 && StringFind(StringUpper(ADRdays),"S")<0)   continue;
        sum += DivZero(iHigh(ccy,PERIOD_D1,k)-iLow(ccy,PERIOD_D1,k),pnt);
        cnt++;
      }
      double tdy    = DivZero(iHigh(ccy,PERIOD_D1,0)-iLow(ccy,PERIOD_D1,0),pnt);
      double adr    = DivZero(sum,cnt);
      double pctadr = DivZero(100*tdy*cnt,sum);
      double pctspr = DivZero(100*spr*cnt,sum);
      string ast = " ";
      if (ccy == sym)    ast = "*";
      bidp    = MarketInfo(ccy,MODE_BID);
      askp    = MarketInfo(ccy,MODE_ASK);
      double dmove = DivZero(bidp-iOpen(ccy,PERIOD_D1,0),pnt);
      double pmove = 100*DivZero((bidp-iOpen(ccy,PERIOD_D1,0)),iOpen(ccy,PERIOD_D1,0));
/*
      //double pmove = 100*(bidp-iOpen(ccy,PERIOD_D1,0))/iOpen(ccy,PERIOD_D1,0);
      double denom = iOpen(ccy,PERIOD_D1,0); // P4L
      if (denom != 0.0) double pmove = 100*(bidp-iOpen(ccy,PERIOD_D1,0))/denom; // P4L
      else Print("Error. Prevented divide-by-zero. Open=0.0 on PERIOD_D1 for ccy=",ccy,"  Missing data? (Open that chart to force initial load)");
*/
      Value[00] = 0.0;     Value[01] = 0.0;      Value[02] = dmove;      Value[03] = pmove;
      Value[04] = tdy;     Value[05] = adr;      Value[06] = pctadr;     Value[07] = spr;
      Value[08] = pctspr;  Value[09] = tickval;  Value[10] = lswap;      Value[11] = sswap;

      // Build display string (disp)......
      string disp = ast + ReduceCcy(ccy);
      if (FullSymbolIDs)       disp = ast + ccy;
      if (dig>3) {
         Value[01] = bidp;
         if (Mask[01] > "")    disp = disp + NumberToStr(bidp,Mask[01]);
      } else {
         Value[00] = bidp;
         if (Mask[00] > "")    disp = disp + NumberToStr(bidp,Mask[00]);
      }   
      for (int z=2; z<12; z++)
        if (Mask[z] > "")      disp = disp + NumberToStr(Value[z],Mask[z]);

      // Test filter, skip pair/instrument and decrement c, if test fails......
      string alert_string = "";
      bool skip=false;
      for (z=0; z<12; z++)   {
        if (dig>3 && z==0)    continue;
        if (dig<4 && z==1)    continue;
        switch (Oper[z])  {
          case 1 :  if (Value[z] != Testval[z])   skip=true;   break;     // fails =  test
          case 2 :  if (Value[z] >= Testval[z])   skip=true;   break;     // fails <  test
          case 3 :  if (Value[z] >  Testval[z])   skip=true;   break;     // fails <= test
          case 4 :  if (Value[z] <= Testval[z])   skip=true;   break;     // fails >  test
          case 5 :  if (Value[z] <  Testval[z])   skip=true;   break;     // fails >= test
          case 6 :  if (Value[z] == Testval[z])   skip=true;   break;     // fails != test
        }
        if (skip)   break;
      }
      if (skip)  {
        c--;
        continue;
      }

      // Add pair/instrument to sort array.....
      string sortf = StrToStr(ccy,"L13");
      if (pairflag)
        sortf = NumberToStr(c,"Z13");
      z = MathAbs(SortField);
      if (z==2)           sortf = NumberToStr(999999+bidp,"8.4"); 
      if (z>=3 && z<=12)  sortf = NumberToStr(999999+Value[z-1],"8.4"); 
      sort[c-1] = sortf + disp;   // sort element: first 13 chars = sort key; rest = display string
  } }

  // Sort and output the items.....
  int stype=0, cnum=0;
  if (SortField<0)
    stype = 1;
  if (Corner>1)
    stype = 1-stype;  
  ShellsortStringArray(sort,c,stype);
  for (i=0; i<c; i++)  {
    disp = stringSubstrOld(sort[i],13);
    string objname = IndiName + NumberToStr(-(i+1)-1,"T-6");
    cnum = MathMod(cnum,nFC);
    PlotLabel (objname, false, Window, Corner, HorizPos, VertPos+(i+1)*VertSpacing, disp, StrToColor(FC[cnum]), FontSize, FontName, 0, false, 0);      // Plot text label
    if (h>0)   FileWrite(h,disp);
    cnum++;
  }
  
  if (h>0)   FileClose(h);
  
  if(!valid_pair_found) return(-1);
  
  return(0);
}

//+------------------------------------------------------------------+
string extract_mask(string inp)   {
//+------------------------------------------------------------------+
  int x1 = StringFind(inp,";");
  if (x1>=0)
    return(stringSubstrOld(inp,x1+1));
  else
    return(inp);  
}

//+------------------------------------------------------------------+
string extract_cond(string inp)   {
//+------------------------------------------------------------------+
  int x1 = StringFind(inp,";");
  if (x1>0)
    return(stringSubstrOld(inp,0,x1));
  else
    return(" ");  
}

//+------------------------------------------------------------------+
int extract_op(int fld, string inp)   {
//+------------------------------------------------------------------+
  string s1 = ExtractAlpha(extract_cond(inp),"<=>!/"+"\x5c");
  int x1=0;
  if (StringFind(s1,"=") >= 0)       x1+=1;
  if (StringFind(s1,"<") >= 0)       x1+=2;
  if (StringFind(s1,">") >= 0)       x1+=4;
  if (StringFind(s1,"!") >= 0)       x1+=5;
  if (StringFind(s1,"/") >= 0)       SortField = fld;
  if (StringFind(s1,"\x5c") >= 0)    SortField = -fld;
  return(x1);
}

//+------------------------------------------------------------------+
double extract_val(string inp)   {
//+------------------------------------------------------------------+
  return(StrToNumber(extract_cond(inp)));
}

//+------------------------------------------------------------------+
#include <hanover --- extensible functions b600 (np).mqh>