// More information about this indicator can be found at:
// https://fxcodebase.com/code/viewtopic.php?f=38&p=148754

//+------------------------------------------------------------------------------------------------+
//|                                                            Copyright © 2023, Gehtsoft USA LLC  |
//|                                                                         http://fxcodebase.com  |
//+------------------------------------------------------------------------------------------------+
//|                                                                   Developed by : Mario Jemic   |
//|                                                                       mario.jemic@gmail.com    |
//|                                                        https://AppliedMachineLearning.systems  |
//|                                                                       https://mario-jemic.com/ |
//+------------------------------------------------------------------------------------------------+

//+------------------------------------------------------------------------------------------------+
//|                                           Our work would not be possible without your support. |
//+------------------------------------------------------------------------------------------------+
//|                                                               Paypal: https://goo.gl/9Rj74e    |
//|                                                             Patreon :  https://goo.gl/GdXWeN   |
//+------------------------------------------------------------------------------------------------+


#property copyright "Copyright © 2023, Gehtsoft USA LLC"
#property link      "http://fxcodebase.com"
#property version "1.0"

#property   strict
#property   indicator_separate_window

#include <stdlib.mqh>

#property   indicator_buffers 8
#property   indicator_color1  clrWhite
#property   indicator_color2  clrRed
#property   indicator_color3  clrOrange
#property   indicator_color4  clrYellow
#property   indicator_color5  clrGreen
#property   indicator_color6  clrBlue
#property   indicator_color7  clrIndigo
#property   indicator_color8  clrViolet

#define  NUMBER_OF_SYMBOLS_CONTAIN_A_SPECIFIC_CURRENCY   10

#define  INDEX_LABEL_WIDTH       50
#define  INDEX_LABEL_HEIGHT      20
#define  INDEX_LABEL_FONT        "Arial"
#define  INDEX_LABEL_FONT_SIZE   10

enum alert
  {
   Off = 0, // Off
   Current = 1,  // At current bar
   Previous = 2   // At previous closed bar
  };

//--- input variables
input ENUM_TIMEFRAMES   TimeFrame = PERIOD_D1;

input color Color_AUDX = clrRed;
input color Color_CADX = clrOrange;
input color Color_CHFX = clrYellow;
input color Color_EURX = clrGreen;
input color Color_GBPX = clrBlue;
input color Color_JPYX = clrIndigo;
input color Color_NZDX = clrViolet;
input color Color_USDX = clrWhite;
//
input alert  notificationsOn       = 1;                      // Notifications
input bool   crossEachAlert        = true;                   // Alert if currencies cross each other
input bool   crossZeroAlert        = true;                   // Alert if currency cross zero
input bool   desktop_notifications = true;                   // Desktop MT4 notifications
input bool   email_notifications   = false;                  // Email notifications
input bool   push_notifications    = false;                  // Push mobile notifications
input bool   sound_notifications   = false;                  // Sound notifications
input string sound_file = "Tick.wav";                        // Choose a sound file for notifications

//--- buffers
double   AUDX[];
double   CADX[];
double   CHFX[];
double   EURX[];
double   GBPX[];
double   JPYX[];
double   NZDX[];
double   USDX[];

//--- variables
ENUM_TIMEFRAMES   TimeFrameNormalized;

string   CurrencyIndex_List[] =
  {
   "AUD",
   "CAD",
   "CHF",
   "EUR",
   "GBP",
   "JPY",
   "NZD",
   "USD"
  };

string   SymbolList[] =
  {
   "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"
  };

int      CurrencyIndex_Cnt;
int      SymbolCnt;

string   CurrencyIndex_SymbolList[][NUMBER_OF_SYMBOLS_CONTAIN_A_SPECIFIC_CURRENCY];
double   CurrencyIndex_SymbolWeight[][NUMBER_OF_SYMBOLS_CONTAIN_A_SPECIFIC_CURRENCY];
int         CurrencyIndex_SymbolCnt[];

color CurrencyIndex_Color[];

string   ShortName;
string   ObjectPrefix = "";

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int   OnInit()
  {
   if(TimeFrame == PERIOD_CURRENT)
     {
      TimeFrameNormalized  = Period();
     }
   else
     {
      TimeFrameNormalized  = TimeFrame;
      if(TimeFrameNormalized < Period())
        {
         Alert("[Warning] - [" + __FUNCTION__ + "]: TimeFrame setting is lower than chart's time frame so that chart's time frame will be used for calculation!");
         TimeFrameNormalized  = Period();
        }
     }
   CurrencyIndex_Cnt = ArraySize(CurrencyIndex_List);
   SymbolCnt   = ArraySize(SymbolList);
   for(int i = 0; i < SymbolCnt; i++)
     {
      if(!SymbolSelect(SymbolList[i], true))
        {
         Alert("[Error] - [" + __FUNCTION__ + "]: Could not select symbol " + SymbolList[i] + "!Error: " + ErrorDescription(GetLastError()) + "!");
         return   INIT_PARAMETERS_INCORRECT;
        }
      datetime tmp1 = iTime(SymbolList[i], TimeFrameNormalized, 0);
      datetime tmp2 = iTime(SymbolList[i], 0, 0);
     }
   ArrayResize(CurrencyIndex_SymbolList, CurrencyIndex_Cnt);
   ArrayResize(CurrencyIndex_SymbolWeight, CurrencyIndex_Cnt);
   ArrayResize(CurrencyIndex_SymbolCnt, CurrencyIndex_Cnt);
   for(int i = 0; i < CurrencyIndex_Cnt; i++)
     {
      string   currency = CurrencyIndex_List[i];
      int   cnt = 0;
      for(int j = 0; j < SymbolCnt; j++)
        {
         string   symbol = SymbolList[j];
         if(StringSubstr(symbol, 0, 3) == currency)
           {
            if(cnt >= NUMBER_OF_SYMBOLS_CONTAIN_A_SPECIFIC_CURRENCY)
              {
               Alert("[Error] - [" + __FUNCTION__ + "]: Currency " + currency + " is involved in too many symbols! Exiting...");
               return   INIT_FAILED;
              }
            else
              {
               CurrencyIndex_SymbolList[i][cnt] = symbol;
               CurrencyIndex_SymbolWeight[i][cnt]  = +1;
               cnt++;
              }
           }
         else
            if(StringSubstr(symbol, 3, 3) == currency)
              {
               if(cnt >= NUMBER_OF_SYMBOLS_CONTAIN_A_SPECIFIC_CURRENCY)
                 {
                  Alert("[Error] - [" + __FUNCTION__ + "]: Currency " + currency + " is involved in too many symbols! Exiting...");
                  return   INIT_FAILED;
                 }
               else
                 {
                  CurrencyIndex_SymbolList[i][cnt] = symbol;
                  CurrencyIndex_SymbolWeight[i][cnt]  = -1;
                  cnt++;
                 }
              }
        }
      CurrencyIndex_SymbolCnt[i] = cnt;
     }
   ArrayResize(CurrencyIndex_Color, CurrencyIndex_Cnt);
   CurrencyIndex_Color[0]  = Color_AUDX;
   CurrencyIndex_Color[1]  = Color_CADX;
   CurrencyIndex_Color[2]  = Color_CHFX;
   CurrencyIndex_Color[3]  = Color_EURX;
   CurrencyIndex_Color[4]  = Color_GBPX;
   CurrencyIndex_Color[5]  = Color_JPYX;
   CurrencyIndex_Color[6]  = Color_NZDX;
   CurrencyIndex_Color[7]  = Color_USDX;
   MathSrand(GetTickCount());
   if(!FindUnusedShortName("Daily Currency Strength Indicator #", ShortName))
     {
      Alert("[Error] - [" + __FUNCTION__ + "]: Could not find a suitable short name for the indicator! Exiting...");
      return   INIT_FAILED;
     }
   IndicatorShortName(ShortName);
   int   subWindow = ChartWindowFind(0, ShortName);
   if(!FindUnusedObjectPrefix("FXCodeBase", ObjectPrefix))
     {
      Alert("[Error] - [" + __FUNCTION__ + "]: Could not find a suitable prefix for graphical objects! Exiting...");
      return   INIT_FAILED;
     }
   for(int i = 0; i < CurrencyIndex_Cnt; i++)
     {
      if(!LabelCreate(0, ObjectPrefix + " - Label - " + CurrencyIndex_List[i] + "X", subWindow,
                      (8 - i) * INDEX_LABEL_WIDTH, INDEX_LABEL_HEIGHT, CORNER_RIGHT_UPPER,
                      CurrencyIndex_List[i] + "X", INDEX_LABEL_FONT, INDEX_LABEL_FONT_SIZE, CurrencyIndex_Color[i]))
        {
         return   INIT_FAILED;
        }
     }
//--- indicator buffers mapping
   IndicatorDigits(5);
   SetIndexShift(0, 0);
   SetIndexDrawBegin(0, 0);
   SetIndexBuffer(0, AUDX);
   SetIndexStyle(0, DRAW_LINE, EMPTY, EMPTY, Color_AUDX);
   SetIndexEmptyValue(0, EMPTY_VALUE);
   SetIndexLabel(0, "AUDX");
   SetIndexShift(1, 0);
   SetIndexDrawBegin(1, 0);
   SetIndexBuffer(1, CADX);
   SetIndexStyle(1, DRAW_LINE, EMPTY, EMPTY, Color_CADX);
   SetIndexEmptyValue(1, EMPTY_VALUE);
   SetIndexLabel(1, "CADX");
   SetIndexShift(2, 0);
   SetIndexDrawBegin(2, 0);
   SetIndexBuffer(2, CHFX);
   SetIndexStyle(2, DRAW_LINE, EMPTY, EMPTY, Color_CHFX);
   SetIndexEmptyValue(2, EMPTY_VALUE);
   SetIndexLabel(2, "CHFX");
   SetIndexShift(3, 0);
   SetIndexDrawBegin(3, 0);
   SetIndexBuffer(3, EURX);
   SetIndexStyle(3, DRAW_LINE, EMPTY, EMPTY, Color_EURX);
   SetIndexEmptyValue(3, EMPTY_VALUE);
   SetIndexLabel(3, "EURX");
   SetIndexShift(4, 0);
   SetIndexDrawBegin(4, 0);
   SetIndexBuffer(4, GBPX);
   SetIndexStyle(4, DRAW_LINE, EMPTY, EMPTY, Color_GBPX);
   SetIndexEmptyValue(4, EMPTY_VALUE);
   SetIndexLabel(4, "GBPX");
   SetIndexShift(5, 0);
   SetIndexDrawBegin(5, 0);
   SetIndexBuffer(5, JPYX);
   SetIndexStyle(5, DRAW_LINE, EMPTY, EMPTY, Color_JPYX);
   SetIndexEmptyValue(5, EMPTY_VALUE);
   SetIndexLabel(5, "JPYX");
   SetIndexShift(6, 0);
   SetIndexDrawBegin(6, 0);
   SetIndexBuffer(6, NZDX);
   SetIndexStyle(6, DRAW_LINE, EMPTY, EMPTY, Color_NZDX);
   SetIndexEmptyValue(6, EMPTY_VALUE);
   SetIndexLabel(6, "NZDX");
   SetIndexShift(7, 0);
   SetIndexDrawBegin(7, 0);
   SetIndexBuffer(7, USDX);
   SetIndexStyle(7, DRAW_LINE, EMPTY, EMPTY, Color_USDX);
   SetIndexEmptyValue(7, EMPTY_VALUE);
   SetIndexLabel(7, "USDX");
//---
   return (INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void  OnDeinit(const int reason)
  {
   if(ObjectPrefix != "")
     {
      ObjectsDeleteAll(0, ObjectPrefix);
      ObjectPrefix   = "";
     }
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   bool  isDataReady = true;
   for(int i = 0; i < SymbolCnt; i++)
     {
      if((iTime(SymbolList[i], TimeFrameNormalized, 0) == 0) || (iClose(SymbolList[i], TimeFrameNormalized, 0) == 0) ||
         (iTime(SymbolList[i], 0, 0) == 0) || (iClose(SymbolList[i], 0, 0) == 0))
        {
         isDataReady = false;
         if(!SymbolSelect(SymbolList[i], true))
           {
            Alert("[Error] - [" + __FUNCTION__ + "]: Could not select symbol " + SymbolList[i] + "!Error: " + ErrorDescription(GetLastError()) + "!");
           }
        }
     }
   if(!isDataReady)
     {
      return   prev_calculated;
     }
   int   limit = rates_total - prev_calculated + 1;
   if((prev_calculated <= 0) || (prev_calculated > rates_total))
     {
      ArrayInitialize(AUDX, EMPTY_VALUE);
      ArrayInitialize(CADX, EMPTY_VALUE);
      ArrayInitialize(CHFX, EMPTY_VALUE);
      ArrayInitialize(EURX, EMPTY_VALUE);
      ArrayInitialize(GBPX, EMPTY_VALUE);
      ArrayInitialize(JPYX, EMPTY_VALUE);
      ArrayInitialize(NZDX, EMPTY_VALUE);
      ArrayInitialize(USDX, EMPTY_VALUE);
     }
   if((limit >= rates_total) || (limit < 0))
     {
      limit = rates_total - 1;
     }
   double   tmp_CurrencyIndex[];
   ArrayResize(tmp_CurrencyIndex, CurrencyIndex_Cnt);
   for(int i = limit; i >= 0; i--)
     {
      for(int j = 0; j < CurrencyIndex_Cnt; j++)
        {
         double   tmp = 0;
         for(int k = 0; k < CurrencyIndex_SymbolCnt[j]; k++)
           {
            string   symbol = CurrencyIndex_SymbolList[j][k];
            double   weight = CurrencyIndex_SymbolWeight[j][k];
            int         shift = iBarShift(symbol, TimeFrameNormalized, time[i]);
            double   priceOpen = iOpen(symbol, TimeFrameNormalized, shift);
            double   priceClose = iClose(symbol, 0, i);
            double   changeInPercentage = (priceClose - priceOpen) / priceOpen * 100;
            tmp   += weight * changeInPercentage;
           }
         if(CurrencyIndex_SymbolCnt[j] > 0)
           {
            tmp_CurrencyIndex[j] = tmp / CurrencyIndex_SymbolCnt[j];
           }
         else
           {
            tmp_CurrencyIndex[j] = 0;
           }
        }
      AUDX[i]  = tmp_CurrencyIndex[0];
      CADX[i]  = tmp_CurrencyIndex[1];
      CHFX[i]  = tmp_CurrencyIndex[2];
      EURX[i]  = tmp_CurrencyIndex[3];
      GBPX[i]  = tmp_CurrencyIndex[4];
      JPYX[i]  = tmp_CurrencyIndex[5];
      NZDX[i]  = tmp_CurrencyIndex[6];
      USDX[i]  = tmp_CurrencyIndex[7];
     }
//--- return value of prev_calculated for next call
   if(notificationsOn > 0)
     {
      checkAlert();
     }
   return (rates_total);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Create a text label                                              |
//+------------------------------------------------------------------+
bool  LabelCreate(const long                    chart_ID = 0,                       // chart's ID
                  const string                  name = "Label",                     // label name
                  const int                        sub_window = 0,                     // subwindow index
                  const int                        x = 0,                                 // X coordinate
                  const int                        y = 0,                                 // Y coordinate
                  const ENUM_BASE_CORNER  corner = CORNER_LEFT_UPPER,   // chart corner for anchoring
                  const string                  text = "Label",                     // text
                  const string                  font = "Arial",                     // font
                  const int                        font_size = 10,                     // font size
                  const color                   clr = clrNONE,                   // color
                  const double                  angle = 0.0,                        // text slope
                  const ENUM_ANCHOR_POINT anchor = ANCHOR_LEFT_UPPER,   // anchor type
                  const bool                    back = false,                       // in the background
                  const bool                    selection = false,               // highlight to move
                  const bool                    hidden = true,                   // hidden in the object list
                  const long                    z_order = 0)                        // priority for mouse click
  {
//--- reset the error value
   ResetLastError();
//--- create a text label
   if(!ObjectCreate(chart_ID, name, OBJ_LABEL, sub_window, 0, 0))
     {
      Alert("[Error] - [" + __FUNCTION__ + "]: Could not create the label! Error: " + ErrorDescription(GetLastError()) + "!");
      return   false;
     }
//--- set label coordinates
   ObjectSetInteger(chart_ID, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(chart_ID, name, OBJPROP_YDISTANCE, y);
//--- set the chart's corner, relative to which point coordinates are defined
   ObjectSetInteger(chart_ID, name, OBJPROP_CORNER, corner);
//--- set the text
   ObjectSetString(chart_ID, name, OBJPROP_TEXT, text);
//--- set text font
   ObjectSetString(chart_ID, name, OBJPROP_FONT, font);
//--- set font size
   ObjectSetInteger(chart_ID, name, OBJPROP_FONTSIZE, font_size);
//--- set the slope angle of the text
   ObjectSetDouble(chart_ID, name, OBJPROP_ANGLE, angle);
//--- set anchor type
   ObjectSetInteger(chart_ID, name, OBJPROP_ANCHOR, anchor);
//--- set color
   ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);
//--- display in the foreground (false) or background (true)
   ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back);
//--- enable (true) or disable (false) the mode of moving the label by mouse
   ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection);
   ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection);
//--- hide (true) or display (false) graphical object name in the object list
   ObjectSetInteger(chart_ID, name, OBJPROP_HIDDEN, hidden);
//--- set the priority for receiving the event of a mouse click in the chart
   ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order);
//--- successful execution
   return (true);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool  FindUnusedShortName(string initStr, string &shortNameStr)
  {
   shortNameStr   = "";
   for(int i = 0; i < 1000; i++)
     {
      string   str = initStr + IntegerToString(MathRand());
      if(ChartWindowFind(0, str) < 0)
        {
         shortNameStr   = str;
         return   true;
        }
     }
   return   false;
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool  FindUnusedObjectPrefix(string initStr, string &prefixStr)
  {
   prefixStr   = "";
   for(int i = 0; i < 1000; i++)
     {
      string   str = initStr + IntegerToString(MathRand());
      if(ObjectFind(0, str) < 0)
        {
         prefixStr   = str;
         return   true;
        }
     }
   return   false;
  }
//+------------------------------------------------------------------+
/*
double   AUDX[];
double   CADX[];
double   CHFX[];
double   EURX[];
double   GBPX[];
double   JPYX[];
double   NZDX[];
double   USDX[];

string   CurrencyIndex_List[] =
  {
   "AUD",
   "CAD",
   "CHF",
   "EUR",
   "GBP",
   "JPY",
   "NZD",
   "USD"
  };

string   SymbolList[] =
  {
   "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"
  };
*/
bool alerted[28];
bool alertedZC[8];
double valC[8];
double valP[8];


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void checkAlert()
  {
   int ccc = 0;
   bool nb = IsNewBar();
   if(nb)
     {
      ArrayInitialize(alerted, false);
      ArrayInitialize(alertedZC, false);
     }
   if(notificationsOn == Current)
     {
      valC[0] = AUDX[0];
      valC[1] = CADX[0];
      valC[2] = CHFX[0];
      valC[3] = EURX[0];
      valC[4] = GBPX[0];
      valC[5] = JPYX[0];
      valC[6] = NZDX[0];
      valC[7] = USDX[0];
      //
      valP[0] = AUDX[1];
      valP[1] = CADX[1];
      valP[2] = CHFX[1];
      valP[3] = EURX[1];
      valP[4] = GBPX[1];
      valP[5] = JPYX[1];
      valP[6] = NZDX[1];
      valP[7] = USDX[1];
      //
      if(crossEachAlert)
        {
         for(int i = 0; i < 8; i++)
           {
            for(int j = i + 1; j < 8; j++)
              {
               if((valC[i] >= valC[j] && valP[i] < valP[j]) || (valC[i] <= valC[j] && valP[i] > valP[j]))
                 {
                  if(!alerted[ccc])
                    {
                     Notify(CurrencyIndex_List[i], CurrencyIndex_List[j], 0);
                     alerted[ccc] = true;
                    }
                 }
               ccc++;
              }
           }
        }
      if(crossZeroAlert)
        {
         for(int i = 0; i < 8; i++)
           {
            if(valP[i] < 0 && valC[i] >= 0 && !alertedZC[i])
              {
               Notify(CurrencyIndex_List[i], "", 1);
               alertedZC[i] = true;
              }
            if(valP[i] > 0 && valC[i] <= 0 && !alertedZC[i])
              {
               Notify(CurrencyIndex_List[i], "", 2);
               alertedZC[i] = true;
              }
           }
        }
     }
   if(notificationsOn == Previous && nb)
     {
      valC[0] = AUDX[1];
      valC[1] = CADX[1];
      valC[2] = CHFX[1];
      valC[3] = EURX[1];
      valC[4] = GBPX[1];
      valC[5] = JPYX[1];
      valC[6] = NZDX[1];
      valC[7] = USDX[1];
      //
      valP[0] = AUDX[2];
      valP[1] = CADX[2];
      valP[2] = CHFX[2];
      valP[3] = EURX[2];
      valP[4] = GBPX[2];
      valP[5] = JPYX[2];
      valP[6] = NZDX[2];
      valP[7] = USDX[2];
      //
      if(crossEachAlert)
        {
         for(int i = 0; i < 8; i++)
           {
            for(int j = i + 1; j < 8; j++)
              {
               if((valC[i] >= valC[j] && valP[i] < valP[j]) || (valC[i] <= valC[j] && valP[i] > valP[j]))
                  Notify(CurrencyIndex_List[i], CurrencyIndex_List[j], 0);
              }
           }
        }
      if(crossZeroAlert)
        {
         for(int i = 0; i < 8; i++)
           {
            if(valP[i] < 0 && valC[i] >= 0)
               Notify(CurrencyIndex_List[i], "", 1);
            if(valP[i] > 0 && valC[i] <= 0)
               Notify(CurrencyIndex_List[i], "", 2);
           }
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsNewBar()
  {
   static datetime lastbar;
   datetime curbar = (datetime)SeriesInfoInteger(_Symbol, _Period, SERIES_LASTBAR_DATE);
   if(lastbar != curbar)
     {
      lastbar = curbar;
      return true;
     }
   return false;
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Notify(string curr1, string curr2, int act)
  {
   string text = "Daily Currency Strength: ";
   if(notificationsOn == Current && act == 0)
      text += curr1 + " and " + curr2 + " cross each other before bar closes - " + _Symbol + " " + GetTimeFrame(_Period);
   if(notificationsOn == Previous && act == 0)
      text += curr1 + " and " + curr2 + " crossed each other after bar closed - " + _Symbol + " " + GetTimeFrame(_Period);
   if(notificationsOn == Current && act == 1)
      text += curr1 + " cross UP zero before bar closes - " + _Symbol + " " + GetTimeFrame(_Period);
   if(notificationsOn == Previous && act == 1)
      text += curr1 + " cross UP zero after bar closed - " + _Symbol + " " + GetTimeFrame(_Period);
   if(notificationsOn == Current && act == 2)
      text += curr1 + " cross DOWN zero before bar closes - " + _Symbol + " " + GetTimeFrame(_Period);
   if(notificationsOn == Previous  && act == 2)
      text += curr1 + " cross DOWN zero after bar closed - " + _Symbol + " " + GetTimeFrame(_Period);
   text += " ";
   if(desktop_notifications)
      Alert(text);
   if(push_notifications)
      SendNotification(text);
   if(email_notifications)
      SendMail("MetaTrader Notification", text);
   if(sound_notifications)
      PlaySound(sound_file);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string GetTimeFrame(int lPeriod)
  {
   switch(lPeriod)
     {
      case PERIOD_M1:
         return ("M1");
      case PERIOD_M5:
         return ("M5");
      case PERIOD_M15:
         return ("M15");
      case PERIOD_M30:
         return ("M30");
      case PERIOD_H1:
         return ("H1");
      case PERIOD_H4:
         return ("H4");
      case PERIOD_D1:
         return ("D1");
      case PERIOD_W1:
         return ("W1");
      case PERIOD_MN1:
         return ("MN1");
     }
   return IntegerToString(lPeriod);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------------------------------------+
//|                                                                    We appreciate your support. |
//+------------------------------------------------------------------------------------------------+
//|                                                               Paypal: https://goo.gl/9Rj74e    |
//|                                                             Patreon :  https://goo.gl/GdXWeN   |
//+------------------------------------------------------------------------------------------------+
//|                                                                   Developed by : Mario Jemic   |
//|                                                                       mario.jemic@gmail.com    |
//|                                                        https://AppliedMachineLearning.systems  |
//|                                                                       https://mario-jemic.com/ |
//+------------------------------------------------------------------------------------------------+

//+------------------------------------------------------------------------------------------------+
//|BitCoin                    : 15VCJTLaz12Amr7adHSBtL9v8XomURo9RF                                 |
//|Ethereum                   : 0x8C110cD61538fb6d7A2B47858F0c0AaBd663068D                         |
//|SOL Address                : 4tJXw7JfwF3KUPSzrTm1CoVq6Xu4hYd1vLk3VF2mjMYh                       |
//|Cardano/ADA                : addr1v868jza77crzdc87khzpppecmhmrg224qyumud6utqf6f4s99fvqv         |
//|Dogecoin Address           : DBGXP1Nc18ZusSRNsj49oMEYFQgAvgBVA8                                 |
//|SHIB Address               : 0x1817D9ebb000025609Bf5D61E269C64DC84DA735                         |
//|Binance(ERC20 & BSC only)  : 0xe84751063de8ade7c5fbff5e73f6502f02af4e2c                         |
//|BitCoin Cash               : 1BEtS465S3Su438Kc58h2sqvVvHK9Mijtg                                 |
//|LiteCoin                   : LLU8PSY2vsq7B9kRELLZQcKf5nJQrdeqwD                                 |
//+------------------------------------------------------------------------------------------------+
