//+------------------------------------------------------------------+
//|                                      DB_GW_TDI_Keltner_V1.01.mq4 |
//|                        Copyright 2017, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window

#define NONE 0
#define DOWN -1
#define UP 1

#define NOTHING 0
#define BUY 1
#define SELL 2

// Constants
#define SYMBOL_ALL                 "-1"   // all symbols
#define OP_ALL                      -1    // all order types
#define CLR_SELL                    clrRed
#define CLR_BUY                     clrSkyBlue
#define CLR_MODIFY                  clrOrange
#define NO_ERROR                    0
#define STD_ERROR                   -1
#define BUY_ORDERS                  1
#define SELL_ORDERS                 2
#define ALL_ORDERS                  3


#include <stdlib.mqh>
#include <WinUser32.mqh>
#include <NewsCalendar_V1.03.mqh>


sinput string        layout                     = "---------------";          // layout settings
sinput int           xAnchor                    = 20;          // x position in pixels
sinput int           yAnchor                    = 50;          // y position in pixels
sinput int           fontSize                   = 7;           // font size
sinput int           rowHeight                  = 25;          // row height in pixels
sinput int           rowSpacing                 = 2;           // space between rows in pixels
sinput int           widthPairButtons           = 110;         // width of the pair buttons in pixels
sinput int           offsetSpreadColumn         = 115;         // offset Spr. column in pixels
sinput int           widthSpread                = 40;          // width of the spread columnin pixels
sinput int           offsetPipsColumn           = 158;         // offset PIPS column in pixels
sinput int           widthPips                  = 40;          // width of the PIPS column in pixels
sinput int           offsetAdrColumn            = 205;         // offset ADR column in pixels
sinput int           widthAdr                   = 40;          // width of the ADR column in pixels
sinput int           offsetTdiColumn_1          = 270;         // offset Tdi TF 1column in pixels
sinput int           widthTdi_1                 = 35;          // width of Tdi TF1 column in pixels
sinput int           offsetKeltColumn_1         = 315;         // offset Keltner TF 1column in pixels
sinput int           widthKelt_1                = 35;          // width of Keltner TF1 column in pixels
sinput int           offsetTdiColumn_2          = 365;         // offset Tdi TF 1column in pixels
sinput int           widthTdi_2                 = 35;          // width of Tdi TF1 column in pixels
sinput int           offsetKeltColumn_2         = 410;         // offset Keltner TF 1column in pixels
sinput int           widthKelt_2                = 35;          // width of Keltner TF1 column in pixels
sinput int           offsetWatchColumn          = 500;         // offset alert enable column in pixels
sinput int           widthWatch                 = 30;          // width of alert enable column in pixels         
sinput ENUM_TIMEFRAMES tfScale                  = PERIOD_M1;   // update time for tdi scaling/calculation
sinput int           textIndent                 = 3;           // text indent in pixels
sinput int           textY_offset               = 3;           // text vertical offset in pixels
sinput string        objectPreamble             = "_gw_RT_";   // object preamble

sinput int           keltnerPeriod              = 50;          // keltner period
sinput double        atrMultiplier_1            = 2.75;        // keltner atr multiplier 1
sinput double        atrMultiplier_2            = 3.75;        // keltner atr multiplier 2
sinput int           tdiLookBackBars_tf1        = 264;         // look back bars for scaling tf 1
sinput int           tdiLookBackBars_tf2        = 224;         // look back bars for scaling tf 2
sinput double        tdiBias                    = 9.0;         // tdi indi bias in percentage
sinput double        tdiLevel                   = 85.0;        // tdi level

sinput int           updateFrequency            = 1;                 // update frequency in seconds
sinput double        spreadLevel                = 4.0;               // spread level
sinput ENUM_TIMEFRAMES  tf_1                    = PERIOD_H1;        // period 1
sinput ENUM_TIMEFRAMES  tf_2                    = PERIOD_H4;        // period 2

sinput bool          alertsActive               = true;              // if true alerts enabled
sinput int           alertResetTime             = 30;                // alert reset time in minutes
//sinput ENUM_TIMEFRAMES  alertUpdateTime         = PERIOD_M30;        // update time for alerts

input string                     s___News					   = "-------      News Calendar Settings      -------";			// --------------------------------------------------
input int	                        minutesBeforeNews  		   = 90;			// Minutes before news
input int	                        minutesAfterNews   		   = 45;			// Minutes after news
sinput int                          newsCalImpactThreshold     = 3;     	// Impact 0=off 1=Low 2=Med 3=High
sinput int                          BrokerGMTOffset    		   = 2; 			// Brokers server offset time from GMT
sinput int                          minutesRefresh     		   = 1; 			// Minutes between Calendar File read
																                        // No need for next 2 inputs if you use defaults
sinput string                       FFcalURL        		      = "http://www.forexfactory.com/ff_calendar_thisweek.xml";   //URL - Forex Factory Calendar
sinput int                          NewsUpdateFreq  		      = 240;		// Minutes between downloading news calendar
sinput bool                         alertEnabled               = true;     // Enable alerts
sinput int                          alertResetInMinutes        = 60;       // Alert reset time in minutes

NewsCalendar newsCalendar(FFcalURL, NewsUpdateFreq);

string DefaultPairs[] = {     "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 curr[8] = {            "USD","EUR","GBP","JPY","AUD","NZD","CAD","CHF"};

string stringToLog;
string fileName;


string TradePairs[];


struct pair_Info
{

   string _pairName;
   double _multiplier;
   double _point;
   int _digits;
   int _pips;
   
   double adr;
   double adr1;
   double adr5;
   double adr10;
   double adr20;
   
   double tdiValue_1;
   double tdiValue_11;
   double tdiValue_21;
   
   double tdiValue_2;
   double tdiValue_12;
   double tdiValue_22;
   
   double keltnerValueUp_11;
   double keltnerValueDown_11;
   double keltnerValueUp_12;
   double keltnerValueDown_12;
   
   double keltnerValueUp_21;
   double keltnerValueDown_21;
   double keltnerValueUp_22;
   double keltnerValueDown_22;
   
   bool disableAlerts;
   bool alertDone;
      
};

pair_Info pairInfo[];

static datetime trendBar;
static datetime tdiScalingTime;
static datetime alertTime[28];

string selectedPair;

string postfix=StringSubstr(Symbol(),6,6);

string selectedPairObject;

                              
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetTimer(updateFrequency);
   
   ArrayCopy(TradePairs,DefaultPairs);
   ArrayResize(pairInfo, ArraySize(TradePairs));
   
   for (int i = 0; i <ArraySize(TradePairs); i++)
   {
      TradePairs[i]=TradePairs[i]+ postfix;
      pairInfo[i]._pairName = TradePairs[i];
      pairInfo[i]._point = MarketInfo(TradePairs[i], MODE_POINT);
      pairInfo[i]._digits = MarketInfo(TradePairs[i], MODE_DIGITS);
      if (pairInfo[i]._digits == 5 || pairInfo[i]._digits == 3 || pairInfo[i]._digits == 1 ) { pairInfo[i]._point *= 10.0;}
      if (pairInfo[i]._digits == 2  ) {pairInfo[i]._point *= 100.0;}
      pairInfo[i]._multiplier = 1.0 / pairInfo[i]._point;
      pairInfo[i].disableAlerts = false;
      pairInfo[i].alertDone = false;
   }
   
  
   string label;
   
   label = objectPreamble + "_pairHeader";
   SetText(label,"PAIR", 0, xAnchor, yAnchor - 25, clrYellow,fontSize);
   label = objectPreamble + "_spreadHeader";
   SetText(label,"Spr.", 0, xAnchor + offsetSpreadColumn, yAnchor - 25, clrYellow, fontSize);
   label = objectPreamble + "_pipsHeader";
   SetText(label,"PIPS", 0, xAnchor + offsetPipsColumn, yAnchor - 25, clrYellow, fontSize);
   label = objectPreamble + "_adrHeader";
   SetText(label,"ADR", 0, xAnchor + offsetAdrColumn, yAnchor - 25, clrYellow, fontSize);
   label = objectPreamble + "_tdiHeader_1";
   SetText(label,"Tdi 1", 0, xAnchor + offsetTdiColumn_1, yAnchor - 25, clrYellow, fontSize);
   label = objectPreamble + "_keltHeader_1";
   SetText(label,"K. 1", 0, xAnchor + offsetKeltColumn_1, yAnchor - 25, clrYellow, fontSize);
   
   label = objectPreamble + "_tdiHeader_2";
   SetText(label,"Tdi 2", 0, xAnchor + offsetTdiColumn_2, yAnchor - 25, clrYellow, fontSize);
   label = objectPreamble + "_keltHeader_2";
   SetText(label,"K. 2", 0, xAnchor + offsetKeltColumn_2, yAnchor - 25, clrYellow, fontSize);
   
   label = objectPreamble + "_alertHeader_e";
   SetText(label,"Alert E.", 0, xAnchor + offsetWatchColumn, yAnchor - 25, clrYellow, fontSize);
   
   displayPairButtons();
   displaySpread();
   displayPips();
   displayAdr();
   displayTdi_1();
   displayTdi_2();
   displayKelt_1();
   displayKelt_2();
   //displayPip();
   displayWatchButtons();
   
   calculateTdi_1();
   calculateTdi_2();
   calculateKeltner_1();
   calculateKeltner_2();
   
   setNews();
      
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- destroy timer
   EventKillTimer();
   
   // delete all objects
   ObjectsDeleteAll();
      
}


//+------------------------------------------------------------------+
//| 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);
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
{
//---
   calculateSpread();
   calculatePips();
   calculateAdr();
   calculateKeltner_1();
   calculateKeltner_2();
   setNews();
   
   if (tdiScalingTime != iTime(Symbol(), tfScale, 0))
   {
      tdiScalingTime = iTime(Symbol(), tfScale, 0);
      calculateTdi_1();
      calculateTdi_2();
   }
}


//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
//---
   string strButtonName;
   if(id == CHARTEVENT_OBJECT_CLICK)
   {
      if (StringFind(sparam,"WatchButton") >= 0)
      {
         for ( int u =0; u < ArraySize(TradePairs); u++)
         {
            strButtonName = objectPreamble + "WatchButton_" + IntegerToString(u);
            
            if (sparam == strButtonName)
            {
               selectedPair = TradePairs[u];
               if (pairInfo[u].disableAlerts)
               {
                  ObjectSetInteger(0, strButtonName, OBJPROP_BGCOLOR, clrGreen);
                  pairInfo[u].disableAlerts = false;
               }
               else
               {
                  ObjectSetInteger(0, strButtonName, OBJPROP_BGCOLOR, clrRed);
                  pairInfo[u].disableAlerts = true;
               }
               ObjectSetInteger(0, strButtonName, OBJPROP_STATE, 0);
            }
         }
         ObjectSetString(0, selectedPairObject, OBJPROP_TEXT, selectedPair);
      }
      
      if (StringFind(sparam,objectPreamble + "Bn_") >=0 )
      {
         for ( int u =0; u < ArraySize(TradePairs); u++)
         {
            strButtonName = objectPreamble + "Bn_" +  IntegerToString(u);
            if (sparam == strButtonName)
            {
               ObjectSetInteger(0, strButtonName, OBJPROP_STATE, 0);
            }
         }
      }
   }
}
//+------------------------------------------------------------------+

void displayPairButtons()
{

   string buttonName;
   for ( int u = 0; u < ArraySize(TradePairs); u++)
   {
      buttonName = objectPreamble + "Bn_" + IntegerToString(u); 
      Create_Button(buttonName, TradePairs[u], 0, widthPairButtons, rowHeight, xAnchor, yAnchor + u * (rowHeight+rowSpacing),
                        clrBlack, clrWhiteSmoke, clrWhite, fontSize);
   }
}

void displaySpread()
{
   string panelName, textName;
   for ( int u = 0; u < ArraySize(TradePairs); u++)
   {
      panelName = objectPreamble + "Spr_Panel_" + IntegerToString(u);
      SetPanel(panelName, 0, xAnchor + offsetSpreadColumn, yAnchor + u * (rowHeight + rowSpacing), widthSpread, rowHeight,clrBlack, clrWhiteSmoke, 1);
      textName = objectPreamble + "Spr_Text_" + IntegerToString(u);
      SetText(textName,"", 0, xAnchor + offsetSpreadColumn + textIndent, yAnchor + u * (rowHeight + rowSpacing) + textY_offset, clrWhiteSmoke, fontSize);
   }
}

void calculateSpread()
{
   string textName;
   double spread;
   for ( int u = 0; u < ArraySize(TradePairs); u++)
   {
      textName = objectPreamble + "Spr_Text_" + IntegerToString(u);
      spread = MathAbs(MarketInfo(TradePairs[u], MODE_ASK) - MarketInfo(TradePairs[u],MODE_BID)) * pairInfo[u]._multiplier;
      ObjectSetString(0, textName, OBJPROP_TEXT, DoubleToString(spread,1));
      if (spread < spreadLevel)
      {
         ObjectSetInteger(0, textName,OBJPROP_COLOR, clrLime);
      }
      else
      {
         ObjectSetInteger(0, textName,OBJPROP_COLOR, clrTomato);
      }
   }
}

void displayPips()
{
   
   string panelName, textName;
   for ( int u = 0; u < ArraySize(TradePairs); u++)
   {
      panelName = objectPreamble + "Pips_Panel_" + IntegerToString(u);
      SetPanel(panelName, 0, xAnchor + offsetPipsColumn, yAnchor + u * (rowHeight + rowSpacing), widthPips, rowHeight,clrBlack, clrWhiteSmoke, 1);
      textName = objectPreamble + "Pips_Text_" + IntegerToString(u);
      SetText(textName,"", 0, xAnchor + offsetPipsColumn + textIndent, yAnchor + u * (rowHeight + rowSpacing) + textY_offset, clrWhiteSmoke, fontSize);
   }
}

void calculatePips()
{
   string textName;
   for ( int i = 0; i < ArraySize(TradePairs); i++)
   {
      pairInfo[i]._pips = (iClose(TradePairs[i],PERIOD_D1,0)-iOpen(TradePairs[i], PERIOD_D1,0)) * pairInfo[i]._multiplier;     
      textName = objectPreamble + "Pips_Text_" + IntegerToString(i);
      
      ObjectSetString(0, textName, OBJPROP_TEXT, IntegerToString(pairInfo[i]._pips));
      if (pairInfo[i]._pips >= 0)
      {
         ObjectSetInteger(0, textName,OBJPROP_COLOR, clrLime);
      }
      else
      {
         ObjectSetInteger(0, textName,OBJPROP_COLOR, clrRed);
      }
   }
}

void displayAdr()
{
   string panelName, textName;
   for ( int u = 0; u < ArraySize(TradePairs); u++)
   {
      panelName = objectPreamble + "Adr_Panel_" + IntegerToString(u);
      SetPanel(panelName, 0, xAnchor + offsetAdrColumn, yAnchor + u * (rowHeight + rowSpacing), widthAdr, rowHeight,clrBlack, clrWhiteSmoke, 1);
      textName = objectPreamble + "Adr_Text_" + IntegerToString(u);
      SetText(textName,"", 0, xAnchor + offsetAdrColumn + textIndent, yAnchor + u * (rowHeight + rowSpacing) + textY_offset, clrWhiteSmoke, fontSize);
   }
}

void calculateAdr()
{
   double s = 0.0;
   for (int i = 0; i < ArraySize(TradePairs); i++) 
   {
      for(int a = 1; a <= 20; a++) 
      {
         if(pairInfo[i]._multiplier != 0)
            s=s+(iHigh(TradePairs[i],PERIOD_D1,a)-iLow(TradePairs[i],PERIOD_D1, a)) * pairInfo[i]._multiplier;
         if(a==1)
            pairInfo[i].adr1=MathRound(s);
         if(a==5)
            pairInfo[i].adr5=MathRound(s/5);
         if(a==10)
            pairInfo[i].adr10=MathRound(s/10);
         if(a==20)
            pairInfo[i].adr20=MathRound(s/20);
      }
      pairInfo[i].adr = MathRound((pairInfo[i].adr1+pairInfo[i].adr5+pairInfo[i].adr10+pairInfo[i].adr20)/4.0);
      
      s=0.0;
      
      ObjectSetString(0, objectPreamble + "Adr_Text_" + IntegerToString(i), OBJPROP_TEXT,IntegerToString(pairInfo[i].adr));
   }
}

void displayTdi_1()
{
   
   string panelName, textName;
   for ( int u = 0; u < ArraySize(TradePairs); u++)
   {
      panelName = objectPreamble + "PTdi1_Panel_" + IntegerToString(u);
      SetPanel(panelName, 0, xAnchor + offsetTdiColumn_1, yAnchor + u * (rowHeight + rowSpacing), widthTdi_1, rowHeight,clrBlack, clrWhiteSmoke, 1);
      textName = objectPreamble + "Tdi1_Text_" + IntegerToString(u);
      SetText(textName,"", 0, xAnchor + offsetTdiColumn_1 + textIndent, yAnchor + u * (rowHeight + rowSpacing) + textY_offset, clrWhiteSmoke, fontSize);
   }
}

void displayTdi_2()
{
   
   string panelName, textName;
   for ( int u = 0; u < ArraySize(TradePairs); u++)
   {
      panelName = objectPreamble + "PTdi2_Panel_" + IntegerToString(u);
      SetPanel(panelName, 0, xAnchor + offsetTdiColumn_2, yAnchor + u * (rowHeight + rowSpacing), widthTdi_2, rowHeight,clrBlack, clrWhiteSmoke, 1);
      textName = objectPreamble + "Tdi2_Text_" + IntegerToString(u);
      SetText(textName,"", 0, xAnchor + offsetTdiColumn_2 + textIndent, yAnchor + u * (rowHeight + rowSpacing) + textY_offset, clrWhiteSmoke, fontSize);
   }
}

void calculateTdi_1()
{
   double maxValue, minValue, resultValue;
   double tmpValue_1, tmpValue_2, tmpValue_3, tmpValue_4, tmpValue_5;
   double minWindow, maxWindow, tmpValue;
   string textName;
   string panelName;
   
   for ( int u = 0; u < ArraySize(TradePairs); u++)
   {
      maxValue = -10000.0;
      minValue = 10000.0;
      
      for ( int uu = 0; uu < tdiLookBackBars_tf1; uu++)
      {
         tmpValue_1 = iCustom(TradePairs[u], tf_1, "TDI_mtf+alerts b600+", 0, uu);
         tmpValue_2 = iCustom(TradePairs[u], tf_1, "TDI_mtf+alerts b600+", 2, uu);
         tmpValue_3 = iCustom(TradePairs[u], tf_1, "TDI_mtf+alerts b600+", 3, uu);
         tmpValue_4 = iCustom(TradePairs[u], tf_1, "TDI_mtf+alerts b600+", 1, uu);
         tmpValue_5 = iCustom(TradePairs[u], tf_1, "TDI_mtf+alerts b600+", 4, uu);
         
         if (tmpValue_1 > maxValue) { maxValue = tmpValue_1;}
         if (tmpValue_2 > maxValue) { maxValue = tmpValue_2;}
         if (tmpValue_3 > maxValue) { maxValue = tmpValue_3;}
         if (tmpValue_4 > maxValue) { maxValue = tmpValue_4;}
         if (tmpValue_5 > maxValue) { maxValue = tmpValue_5;}
         
         if (tmpValue_1 < minValue) { minValue = tmpValue_1;}
         if (tmpValue_2 < minValue) { minValue = tmpValue_2;}
         if (tmpValue_3 < minValue) { minValue = tmpValue_3;}
         if (tmpValue_4 < minValue) { minValue = tmpValue_4;}
         if (tmpValue_5 < minValue) { minValue = tmpValue_5;}
      }
      
      if (TradePairs[u] == "CADJPY")
      {
         //Alert(maxValue);
      }
      
      minWindow = minValue - (maxValue - minValue) * tdiBias * 0.01 / 2;
      maxWindow = maxValue + (maxValue - minValue) * tdiBias * 0.01 / 2;
      resultValue = iCustom(TradePairs[u], tf_1, "TDI_mtf+alerts b600+", 3, 0);
      if ((maxWindow - minWindow) > 0.0)
      {
         tmpValue = (resultValue - minWindow) / (maxWindow - minWindow) * 100.0;
      }
      else
      {
         tmpValue = 0.01;
      }
      
      resultValue = iCustom(TradePairs[u], tf_1, "TDI_mtf+alerts b600+", 3, 1);
      if ((maxWindow - minWindow) > 0.0)
      {
         pairInfo[u].tdiValue_11 = (resultValue - minWindow) / (maxWindow - minWindow) * 100.0;
      }
      else
      {
         pairInfo[u].tdiValue_11 = 0.01;
      }
      resultValue = iCustom(TradePairs[u], tf_1, "TDI_mtf+alerts b600+", 3, 2);
      if ((maxWindow - minWindow) > 0.0)
      {
         pairInfo[u].tdiValue_21 = (resultValue - minWindow) / (maxWindow - minWindow) * 100.0;
      }
      else
      {
         pairInfo[u].tdiValue_21 = 0.01;
      }
      
      textName = objectPreamble + "Tdi1_Text_" + IntegerToString(u);
      panelName = objectPreamble + "PTdi1_Panel_" + IntegerToString(u);
      ObjectSetString(0, textName, OBJPROP_TEXT, DoubleToString(tmpValue, 1));
      
      if (tmpValue >= tdiLevel)
      {
         ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, clrRed);
      }
      else if (tmpValue <= (100 - tdiLevel))
      {
         ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, clrGreen);
      }
      else
      {
         ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, clrBlack);
      }
      
      pairInfo[u].tdiValue_1 = tmpValue;
   }
}

void calculateTdi_2()
{
   double maxValue, minValue, resultValue;
   double tmpValue_1, tmpValue_2, tmpValue_3, tmpValue_4, tmpValue_5;
   double minWindow, maxWindow, tmpValue;
   string textName;
   string panelName;
   
   for ( int u = 0; u < ArraySize(TradePairs); u++)
   {
      maxValue = -10000.0;
      minValue = 10000.0;
      
      for ( int uu = 0; uu < tdiLookBackBars_tf2; uu++)
      {
         tmpValue_1 = iCustom(TradePairs[u], tf_2, "TDI_mtf+alerts b600+", 0, uu);
         tmpValue_2 = iCustom(TradePairs[u], tf_2, "TDI_mtf+alerts b600+", 2, uu);
         tmpValue_3 = iCustom(TradePairs[u], tf_2, "TDI_mtf+alerts b600+", 3, uu);
         tmpValue_4 = iCustom(TradePairs[u], tf_2, "TDI_mtf+alerts b600+", 1, uu);
         tmpValue_5 = iCustom(TradePairs[u], tf_2, "TDI_mtf+alerts b600+", 4, uu);
         
         if (tmpValue_1 > maxValue) { maxValue = tmpValue_1;}
         if (tmpValue_2 > maxValue) { maxValue = tmpValue_2;}
         if (tmpValue_3 > maxValue) { maxValue = tmpValue_3;}
         if (tmpValue_4 > maxValue) { maxValue = tmpValue_4;}
         if (tmpValue_5 > maxValue) { maxValue = tmpValue_5;}
         
         if (tmpValue_1 < minValue) { minValue = tmpValue_1;}
         if (tmpValue_2 < minValue) { minValue = tmpValue_2;}
         if (tmpValue_3 < minValue) { minValue = tmpValue_3;}
         if (tmpValue_4 < minValue) { minValue = tmpValue_4;}
         if (tmpValue_5 < minValue) { minValue = tmpValue_5;}
      }
      
      if (TradePairs[u] == "CADJPY")
      {
         //Alert(maxValue);
      }
      
      minWindow = minValue - (maxValue - minValue) * tdiBias * 0.01 / 2;
      maxWindow = maxValue + (maxValue - minValue) * tdiBias * 0.01 / 2;
      resultValue = iCustom(TradePairs[u], tf_2, "TDI_mtf+alerts b600+", 3, 0);
      if ((maxWindow - minWindow) > 0.0)
      {
         tmpValue = (resultValue - minWindow) / (maxWindow - minWindow) * 100.0;
      }
      else
      {
         tmpValue = 0.01;
      }
      
      resultValue = iCustom(TradePairs[u], tf_2, "TDI_mtf+alerts b600+", 3, 1);
      if ((maxWindow - minWindow) > 0.0)
      {
         pairInfo[u].tdiValue_12 = (resultValue - minWindow) / (maxWindow - minWindow) * 100.0;
      }
      else
      {
         pairInfo[u].tdiValue_12 = 0.01;
      }
      resultValue = iCustom(TradePairs[u], tf_2, "TDI_mtf+alerts b600+", 3, 2);
      if ((maxWindow - minWindow) > 0.0)
      {
         pairInfo[u].tdiValue_22 = (resultValue - minWindow) / (maxWindow - minWindow) * 100.0;
      }
      else
      {
         pairInfo[u].tdiValue_22 = 0.01;
      }
      
      textName = objectPreamble + "Tdi2_Text_" + IntegerToString(u);
      panelName = objectPreamble + "PTdi2_Panel_" + IntegerToString(u);
      ObjectSetString(0, textName, OBJPROP_TEXT, DoubleToString(tmpValue, 1));
      
      if (tmpValue >= tdiLevel)
      {
         ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, clrRed);
      }
      else if (tmpValue <= (100 - tdiLevel))
      {
         ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, clrGreen);
      }
      else
      {
         ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, clrBlack);
      }
      
      pairInfo[u].tdiValue_2 = tmpValue;
   }
}

void displayKelt_1()
{
   string panelName, textName;
   for ( int u = 0; u < ArraySize(TradePairs); u++)
   {
      panelName = objectPreamble + "PKelt1_Panel_" + IntegerToString(u);
      SetPanel(panelName, 0, xAnchor + offsetKeltColumn_1, yAnchor + u * (rowHeight + rowSpacing), widthKelt_1, rowHeight,clrBlack, clrWhiteSmoke, 1);
      textName = objectPreamble + "Kelt1_Text_" + IntegerToString(u);
      SetText(textName,"", 0, xAnchor + offsetKeltColumn_1 + textIndent, yAnchor + u * (rowHeight + rowSpacing) + textY_offset, clrWhiteSmoke, fontSize);
   }
}

void displayKelt_2()
{
   string panelName, textName;
   for ( int u = 0; u < ArraySize(TradePairs); u++)
   {
      panelName = objectPreamble + "PKelt2_Panel_" + IntegerToString(u);
      SetPanel(panelName, 0, xAnchor + offsetKeltColumn_2, yAnchor + u * (rowHeight + rowSpacing), widthKelt_2, rowHeight,clrBlack, clrWhiteSmoke, 1);
      textName = objectPreamble + "Kelt2_Text_" + IntegerToString(u);
      SetText(textName,"", 0, xAnchor + offsetKeltColumn_2 + textIndent, yAnchor + u * (rowHeight + rowSpacing) + textY_offset, clrWhiteSmoke, fontSize);
   }
}



void calculateKeltner_1()
{
   double ma, atr, KU, KL;
   string panelName;
   for ( int u = 0; u < ArraySize(TradePairs); u++)
   {
      ma = iMA(TradePairs[u], tf_1, keltnerPeriod, 0,  MODE_SMA, PRICE_CLOSE,  0);
      atr = iATR(TradePairs[u], tf_1, keltnerPeriod, 1);
      KU = ma + atr * atrMultiplier_1;
      KL = ma - atr * atrMultiplier_1;
      pairInfo[u].keltnerValueUp_11 = KU;
      pairInfo[u].keltnerValueDown_11 = KL;
      
      ma = iMA(TradePairs[u], tf_1, keltnerPeriod, 0,  MODE_SMA, PRICE_CLOSE,  0);
      atr = iATR(TradePairs[u], tf_1, keltnerPeriod, 1);
      KU = ma + atr * atrMultiplier_2;
      KL = ma - atr * atrMultiplier_2;
      pairInfo[u].keltnerValueUp_12 = KU;
      pairInfo[u].keltnerValueDown_12 = KL;
      
      panelName = objectPreamble + "PKelt1_Panel_" + IntegerToString(u);
      if (iHigh(TradePairs[u], tf_1, 0) > KU)
      {
         ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, clrRed);
         if (alertsActive && !pairInfo[u].alertDone && !pairInfo[u].disableAlerts)
         {
            Alert("Keltner upper level for pair: " + TradePairs[u]);
            pairInfo[u].alertDone = true;
            alertTime[u] = LocalTime();
         }  
      
      }
      else if (iLow(TradePairs[u], tf_1, 0) < KL)
      {
         ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, clrGreen);
         if (alertsActive && !pairInfo[u].alertDone && !pairInfo[u].disableAlerts)
         {
            Alert("Keltner lower level for pair: " + TradePairs[u]);
            pairInfo[u].alertDone = true;
            alertTime[u] = LocalTime();
         }
      }
      else
      {
         ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, clrBlack);
      }
      
      // check for resetting alert time
      if (pairInfo[u].alertDone)
      {
         if (LocalTime() > alertTime[u] + alertResetTime * 60)
         {
            pairInfo[u].alertDone = false;
            alertTime[u] = 0;
         }
      }
   }
}

void calculateKeltner_2()
{
   double ma, atr, KU, KL;
   string panelName;
   for ( int u = 0; u < ArraySize(TradePairs); u++)
   {
      ma = iMA(TradePairs[u], tf_2, keltnerPeriod, 0,  MODE_SMA, PRICE_CLOSE,  0);
      atr = iATR(TradePairs[u], tf_2, keltnerPeriod, 1);
      KU = ma + atr * atrMultiplier_1;
      KL = ma - atr * atrMultiplier_1;
      pairInfo[u].keltnerValueUp_21 = KU;
      pairInfo[u].keltnerValueDown_21 = KL;
      
      ma = iMA(TradePairs[u], tf_2, keltnerPeriod, 0,  MODE_SMA, PRICE_CLOSE,  0);
      atr = iATR(TradePairs[u], tf_2, keltnerPeriod, 1);
      KU = ma + atr * atrMultiplier_2;
      KL = ma - atr * atrMultiplier_2;
      pairInfo[u].keltnerValueUp_22 = KU;
      pairInfo[u].keltnerValueDown_22 = KL;
      
      panelName = objectPreamble + "PKelt2_Panel_" + IntegerToString(u);
      if (iHigh(TradePairs[u], tf_2, 0) > KU)
      {
         ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, clrRed);
         if (alertsActive && !pairInfo[u].alertDone && !pairInfo[u].disableAlerts)
         {
            Alert("Keltner upper level for pair: " + TradePairs[u]);
            pairInfo[u].alertDone = true;
            alertTime[u] = LocalTime();
         }  
      }
      else if (iLow(TradePairs[u], tf_2, 0) < KL)
      {
         ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, clrGreen);
         if (alertsActive && !pairInfo[u].alertDone && !pairInfo[u].disableAlerts)
         {
            Alert("Keltner lower level for pair: " + TradePairs[u]);
            pairInfo[u].alertDone = true;
            alertTime[u] = LocalTime();
         }
      }
      else
      {
         ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, clrBlack);
      }
      
      // check for resetting alert time
      if (pairInfo[u].alertDone)
      {
         if (LocalTime() > alertTime[u] + alertResetTime * 60)
         {
            pairInfo[u].alertDone = false;
            alertTime[u] = 0;
         }
      }
      
   }
}

void displayWatchButtons()
{
   string buttonName;
   for (int u =0; u < ArraySize(TradePairs); u++)
   {
      buttonName = objectPreamble + "WatchButton_" + IntegerToString(u);
      Create_Button(buttonName, "", 0, widthWatch, rowHeight, xAnchor + offsetWatchColumn, yAnchor + u * (rowHeight+rowSpacing),
                        clrGreen, clrWhiteSmoke, clrWhiteSmoke, fontSize);
   }

}


void Create_Button(string but_name, string label, int window, int xsize, int ysize, 
                     int xdist, int ydist, int bgcolor, int fcolor, int bcolor, int _fontSize)
{
    
   if(ObjectFind(0,but_name)<0)
   {
      if(!ObjectCreate(0,but_name,OBJ_BUTTON, window,0,0))
        {
         Print(__FUNCTION__,
               ": failed to create the button! Error code = ",GetLastError());
         return;
        }
      ObjectSetString(0,but_name,OBJPROP_TEXT,label);
      ObjectSetInteger(0,but_name,OBJPROP_XSIZE,xsize);
      ObjectSetInteger(0,but_name,OBJPROP_YSIZE,ysize);
      ObjectSetInteger(0,but_name,OBJPROP_CORNER,CORNER_LEFT_UPPER);     
      ObjectSetInteger(0,but_name,OBJPROP_XDISTANCE,xdist);      
      ObjectSetInteger(0,but_name,OBJPROP_YDISTANCE,ydist);         
      ObjectSetInteger(0,but_name,OBJPROP_BGCOLOR,bgcolor);
      ObjectSetInteger(0,but_name,OBJPROP_COLOR,fcolor);
      ObjectSetInteger(0,but_name,OBJPROP_BORDER_COLOR,bcolor);
      ObjectSetInteger(0,but_name,OBJPROP_FONTSIZE,_fontSize);
      ObjectSetInteger(0,but_name,OBJPROP_HIDDEN,true);
      ObjectSetInteger(0,but_name, OBJPROP_CORNER,5);
      //ObjectSetInteger(0,but_name,OBJPROP_BORDER_COLOR,ChartGetInteger(0,CHART_COLOR_FOREGROUND));
      ObjectSetInteger(0,but_name,OBJPROP_BORDER_TYPE,BORDER_FLAT);
      
      ChartRedraw();      
   }
}

//+------------------------------------------------------------------+
void SetText(string name,string text, int window, int x,int y,color colour,int fontsize=12)
  {
   if (ObjectFind(0,name)<0)
      ObjectCreate(0,name,OBJ_LABEL,window,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(long window, string name,string CharToStr,int x,int y,color colour,int fontsize=12)
  {
   if(ObjectFind(0,name)<0)
      ObjectCreate(0,name,OBJ_LABEL,window,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_COLOR,border_clr);
      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_CORNER,5);
     }
   ObjectSetInteger(0,name,OBJPROP_BGCOLOR,bg_color);
}

int getPairIndex(string _pair)
{

   for (int u = 0; u < ArraySize(TradePairs); u++)
   {
      if (_pair == TradePairs[u])
      {
         return u;
      }
   }
   
   return 0;

}

void setNews()
{
   int tmpLevel;
   string objectname;
   datetime gmt;
   color tmpColor;
   
   for ( int z = 0; z < 28; z++)
   {
      objectname = objectPreamble + "Bn_" + IntegerToString(z); 
      gmt = LocalTime() - BrokerGMTOffset * 3600;
      tmpLevel = newsCalendar.getNewsImpactLevel(DefaultPairs[z], gmt, minutesBeforeNews, minutesAfterNews);
      tmpColor = getImpactColor(tmpLevel,clrDarkGray);

      ObjectSetInteger(0,objectname,OBJPROP_BGCOLOR, tmpColor);
      ObjectSetInteger(0, objectname,OBJPROP_COLOR,clrBlack);
   }
}

color getImpactColor(int value, color _default)
{
   if (value == 0) {return _default;}
   if (value == 3) {return clrRed;}
   if (value == 2) {return clrOrange;}
   if (value == 1) {return clrYellow;}
   return _default;
}

