/*
https://forex-station.com/viewtopic.php?t=8473101&p=1295449705#p1295449705
Half-Trend-buy-sell-indicator:
https://forex-station.com/viewtopic.php?f=579495&t=8413842&start=320
https://forex-station.com/viewtopic.php?t=8413842&p=1295419838#p1295419838
*/
//+------------------------------------------------------------------+
//|                                                Half Trend BT.mq5 |
//|                                  Copyright © 2020, Forex-Station |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2020, Forex-Station"
#property link      "https://forex-station.com/post1295586866.html#p1295586866"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 11
#property indicator_plots   5
//--- plot
#property indicator_label1 "UP"
#property indicator_color1 clrDeepSkyBlue // up[] DodgerBlue
#property indicator_type1  DRAW_LINE
#property indicator_width1 3

#property indicator_label2 "DN"
#property indicator_color2 clrTomato       // down[]
#property indicator_type2  DRAW_LINE
#property indicator_width2 3

#property indicator_label3 "ATR-LH"
#property indicator_color3 clrDodgerBlue,clrRed  // atrlo[], atrhi[]
#property indicator_type3  DRAW_COLOR_HISTOGRAM2
#property indicator_width3 1

#property indicator_label4 "ARR-UP"
#property indicator_color4 clrLime  // arrup[]
#property indicator_type4  DRAW_ARROW
#property indicator_width4 1

#property indicator_label5 "ARR-DOWN"
#property indicator_color5 clrRed  // arrdwn[]
#property indicator_type5  DRAW_ARROW
#property indicator_width5 1

input group "=== Half Trend Settings ==="
input int    Amplitude        = 7;
input bool   ShowBars         = true;
input bool   ShowArrows       = true;
input bool   alertsOn         = false;
input bool   alertsOnCurrent  = false;
input bool   alertsMessage    = false;
input bool   alertsSound      = false;
input bool   alertsEmail      = false;
input bool   alertsNotify     = false;

//Forex-Station copy & paste code; Button code start 11
input group "=== Toggle Button Settings ==="
input string             button_note1          = "------------------------------"; // ------------------------------
input int                btn_Subwindow         = 0;                  // What window to put the button on
input ENUM_BASE_CORNER   btn_corner            = CORNER_LEFT_UPPER;  // chart btn_corner for anchoring
input string             btn_text              = "HalfTrend: ON";    // Display label
input string             btn_Font              = "Arial";            // button font name
input int                btn_FontSize          = 9;                  // btn__font size
input color              btn_text_ON_color     = clrLime;            // ON color when the button is turned on
input color              btn_text_OFF_color    = clrRed;             // OFF color when the button is turned off
input color              btn_background_color  = clrDimGray;         // background color of the button
input color              btn_border_color      = clrBlack;           // border color the button
input int                button_x              = 20;                 // Horizontal location
input int                button_y              = 80;                 // Vertical location
input int                btn_Width             = 80;                 // btn__width
input int                btn_Height            = 20;                 // btn__height
input string             UniqueButtonID        = "HalfTrend_BT";     // Unique Button ID                      
input string             button_note2          = "------------------------------"; // ------------------------------
//Forex-Station copy & paste code; Button code end 11

bool nexttrend;
double minhighprice, maxlowprice;
double up[], down[], atrlo[], atrhi[], atrclr[], trend[];
double arrup[], arrdwn[];
int ind_mahi, ind_malo, ind_atr;
double iMAHigh[], iMALow[], iATRx[];

//+------------------------------------------------------------------+
//| Button State Tracking Variables                                  |
//+------------------------------------------------------------------+
bool    IndicatorEnabled = true;
bool    IndicatorHidden  = false; // True when indicator is turned OFF via toggle button
string  ToggleButtonName;
string  g_gvHidden;
string  g_prefix;
string  IndicatorName, IndicatorObjPrefix, buttonId;

//+------------------------------------------------------------------+
//| Forward Declarations                                             |
//+------------------------------------------------------------------+
string GetButtonText(bool isEnabled);
void   CreateToggleButton();
void   UpdateToggleButton();
void   SavePlotStyles();
void   RestorePlotStyles();
void   ApplyPlotsStyle();
void   ToggleIndicatorVisibility();
void   BringButtonsToFront();

//+------------------------------------------------------------------+
//| Save current plot widths & styles from chart to GlobalVariables  |
//+------------------------------------------------------------------+
void SavePlotStyles()
{
   if(g_prefix == "") return;
   for(int k = 0; k < 5; k++)
   {
      int w = (int)PlotIndexGetInteger(k, PLOT_LINE_WIDTH);
      int s = (int)PlotIndexGetInteger(k, PLOT_LINE_STYLE);
      if(w > 0)
         GlobalVariableSet(g_prefix + IntegerToString(ChartID()) + "_W" + IntegerToString(k), (double)w);
      if(s >= 0)
         GlobalVariableSet(g_prefix + IntegerToString(ChartID()) + "_S" + IntegerToString(k), (double)s);
   }
}

//+------------------------------------------------------------------+
//| Restore plot widths & styles after timeframe switch              |
//+------------------------------------------------------------------+
void RestorePlotStyles()
{
   if(g_prefix == "") return;
   for(int k = 0; k < 5; k++)
   {
      string gvW = g_prefix + IntegerToString(ChartID()) + "_W" + IntegerToString(k);
      string gvS = g_prefix + IntegerToString(ChartID()) + "_S" + IntegerToString(k);

      if(GlobalVariableCheck(gvW))
      {
         int w = (int)GlobalVariableGet(gvW);
         if(w > 0) PlotIndexSetInteger(k, PLOT_LINE_WIDTH, w);
      }
      if(GlobalVariableCheck(gvS) && k < 2)
      {
         int s = (int)GlobalVariableGet(gvS);
         if(s >= 0) PlotIndexSetInteger(k, PLOT_LINE_STYLE, s);
      }
   }
}

//+------------------------------------------------------------------+
//| Helper to resolve button text based on state                     |
//+------------------------------------------------------------------+
string GetButtonText(bool isEnabled)
{
   string t = btn_text;
   if(isEnabled)
   {
      if(StringFind(t, "OFF") >= 0) StringReplace(t, "OFF", "ON");
      else if(StringFind(t, "Off") >= 0) StringReplace(t, "Off", "On");
      else if(StringFind(t, "off") >= 0) StringReplace(t, "off", "on");
   }
   else
   {
      if(StringFind(t, "ON") >= 0) StringReplace(t, "ON", "OFF");
      else if(StringFind(t, "On") >= 0) StringReplace(t, "On", "Off");
      else if(StringFind(t, "on") >= 0) StringReplace(t, "on", "off");
   }
   return t;
}

//+------------------------------------------------------------------+
//| Create Toggle Button                                             |
//+------------------------------------------------------------------+
void CreateToggleButton()
{
   if(ObjectFind(0, buttonId) < 0)
   {
      int y_pos = button_y;
      int obj_total = ObjectsTotal(0, -1, OBJ_BUTTON);
      bool collision = true;
      while(collision)
      {
         collision = false;
         for(int i = 0; i < obj_total; i++)
         {
            string name = ObjectName(0, i, -1, OBJ_BUTTON);
            if(name == buttonId) continue;
            if((ENUM_BASE_CORNER)ObjectGetInteger(0, name, OBJPROP_CORNER) != btn_corner) continue;
            if(ObjectGetInteger(0, name, OBJPROP_XDISTANCE) == button_x &&
               ObjectGetInteger(0, name, OBJPROP_YDISTANCE) == y_pos)
            {
               y_pos += btn_Height + 4;
               collision = true;
               break;
            }
         }
      }

      ObjectCreate(0, buttonId, OBJ_BUTTON, btn_Subwindow, 0, 0);

      ObjectSetInteger(0, buttonId, OBJPROP_CORNER,       btn_corner);
      ObjectSetInteger(0, buttonId, OBJPROP_XDISTANCE,    button_x);
      ObjectSetInteger(0, buttonId, OBJPROP_YDISTANCE,    y_pos);
      ObjectSetInteger(0, buttonId, OBJPROP_XSIZE,        btn_Width);
      ObjectSetInteger(0, buttonId, OBJPROP_YSIZE,        btn_Height);
      ObjectSetString (0, buttonId, OBJPROP_FONT,         btn_Font);
      ObjectSetInteger(0, buttonId, OBJPROP_FONTSIZE,     btn_FontSize);
      ObjectSetInteger(0, buttonId, OBJPROP_BGCOLOR,      btn_background_color);
      ObjectSetInteger(0, buttonId, OBJPROP_BORDER_COLOR, btn_border_color);
      ObjectSetInteger(0, buttonId, OBJPROP_BORDER_TYPE,  BORDER_RAISED);
      ObjectSetInteger(0, buttonId, OBJPROP_SELECTABLE,   false);
      ObjectSetInteger(0, buttonId, OBJPROP_HIDDEN,       true);
      ObjectSetInteger(0, buttonId, OBJPROP_TIMEFRAMES,   OBJ_ALL_PERIODS);
      ObjectSetInteger(0, buttonId, OBJPROP_ZORDER,       100);
   }

   UpdateToggleButton();
}

//+------------------------------------------------------------------+
//| Update Toggle Button Appearance                                  |
//+------------------------------------------------------------------+
void UpdateToggleButton()
{
   if(ObjectFind(0, buttonId) < 0) return;

   IndicatorEnabled = !IndicatorHidden;

   string labelText  = GetButtonText(IndicatorEnabled);
   color  textColor  = IndicatorEnabled ? btn_text_ON_color : btn_text_OFF_color;

   ObjectSetString (0, buttonId, OBJPROP_TEXT,         labelText);
   ObjectSetString (0, buttonId, OBJPROP_FONT,         btn_Font);
   ObjectSetInteger(0, buttonId, OBJPROP_FONTSIZE,     btn_FontSize);
   ObjectSetInteger(0, buttonId, OBJPROP_COLOR,        textColor);
   ObjectSetInteger(0, buttonId, OBJPROP_BGCOLOR,      btn_background_color);
   ObjectSetInteger(0, buttonId, OBJPROP_BORDER_COLOR, btn_border_color);
   ObjectSetInteger(0, buttonId, OBJPROP_CORNER,       btn_corner);
   ObjectSetInteger(0, buttonId, OBJPROP_XDISTANCE,    button_x);
   ObjectSetInteger(0, buttonId, OBJPROP_XSIZE,        btn_Width);
   ObjectSetInteger(0, buttonId, OBJPROP_YSIZE,        btn_Height);
   ObjectSetInteger(0, buttonId, OBJPROP_STATE,        IndicatorEnabled);
   ObjectSetInteger(0, buttonId, OBJPROP_ZORDER,       100);

   ChartRedraw(0);
}

//+------------------------------------------------------------------+
//| Apply Plot Styles based on Button Toggle State                   |
//+------------------------------------------------------------------+
void ApplyPlotsStyle()
{
   bool showIndicator = !IndicatorHidden;

   // Plot 0: UP
   PlotIndexSetInteger(0, PLOT_DRAW_TYPE, showIndicator ? DRAW_LINE : DRAW_NONE);
   PlotIndexSetString (0, PLOT_LABEL, showIndicator ? "UP" : "");
   PlotIndexSetInteger(0, PLOT_SHOW_DATA, showIndicator);
   PlotIndexSetDouble (0, PLOT_EMPTY_VALUE, 0.0);

   // Plot 1: DN
   PlotIndexSetInteger(1, PLOT_DRAW_TYPE, showIndicator ? DRAW_LINE : DRAW_NONE);
   PlotIndexSetString (1, PLOT_LABEL, showIndicator ? "DN" : "");
   PlotIndexSetInteger(1, PLOT_SHOW_DATA, showIndicator);
   PlotIndexSetDouble (1, PLOT_EMPTY_VALUE, 0.0);

   // Plot 2: ATR-LH
   bool showHist = showIndicator && ShowBars;
   PlotIndexSetInteger(2, PLOT_DRAW_TYPE, showHist ? DRAW_COLOR_HISTOGRAM2 : DRAW_NONE);
   PlotIndexSetString (2, PLOT_LABEL, showHist ? "ATR-LH" : "");
   PlotIndexSetInteger(2, PLOT_SHOW_DATA, showHist);
   if(!ShowBars)
   {
      PlotIndexSetInteger(2, PLOT_LINE_COLOR, 0, clrNONE);
      PlotIndexSetInteger(2, PLOT_LINE_COLOR, 1, clrNONE);
   }
   else
   {
      PlotIndexSetInteger(2, PLOT_LINE_COLOR, 0, clrDodgerBlue);
      PlotIndexSetInteger(2, PLOT_LINE_COLOR, 1, clrRed);
   }

   // Plot 3 & 4: ARR-UP (221) & ARR-DOWN (222)
   bool showArr = showIndicator && ShowArrows;
   PlotIndexSetInteger(3, PLOT_DRAW_TYPE, showArr ? DRAW_ARROW : DRAW_NONE);
   PlotIndexSetInteger(4, PLOT_DRAW_TYPE, showArr ? DRAW_ARROW : DRAW_NONE);
   PlotIndexSetInteger(3, PLOT_ARROW, 221);
   PlotIndexSetInteger(4, PLOT_ARROW, 222);
   PlotIndexSetString (3, PLOT_LABEL, showArr ? "ARR-UP" : "");
   PlotIndexSetString (4, PLOT_LABEL, showArr ? "ARR-DOWN" : "");
   PlotIndexSetInteger(3, PLOT_SHOW_DATA, showArr);
   PlotIndexSetInteger(4, PLOT_SHOW_DATA, showArr);
   PlotIndexSetDouble (3, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble (4, PLOT_EMPTY_VALUE, EMPTY_VALUE);
}

//+------------------------------------------------------------------+
//| Toggle Indicator Visibility                                      |
//+------------------------------------------------------------------+
void ToggleIndicatorVisibility()
{
   IndicatorHidden  = !IndicatorHidden;
   IndicatorEnabled = !IndicatorHidden;

   if(g_gvHidden != "")
      GlobalVariableSet(g_gvHidden, IndicatorHidden ? 1.0 : 0.0);

   ApplyPlotsStyle();
   UpdateToggleButton();

   BringButtonsToFront();
   ChartRedraw(0);
}

//+------------------------------------------------------------------+
//| Ensure all buttons on chart have higher ZORDER                   |
//+------------------------------------------------------------------+
void BringButtonsToFront()
{
   int total = ObjectsTotal(0, -1, OBJ_BUTTON);
   for(int i = 0; i < total; i++)
   {
      string name = ObjectName(0, i, -1, OBJ_BUTTON);
      if(name != "")
      {
         if(ObjectGetInteger(0, name, OBJPROP_ZORDER) < 100)
            ObjectSetInteger(0, name, OBJPROP_ZORDER, 100);
      }
   }
}

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   //--- Set up unique IDs and global variables for state tracking
   IndicatorObjPrefix = "__" + btn_text + "__";
   buttonId           = IndicatorObjPrefix + UniqueButtonID;
   ToggleButtonName   = buttonId;
   IndicatorName      = "Half Trend BT [" + UniqueButtonID + "]";
   g_prefix           = "HalfTrend_BT_" + UniqueButtonID + "_";
   g_gvHidden         = g_prefix + IntegerToString(ChartID()) + "_Hidden";

   // Clean up any old duplicate or phantom buttons
   int total_objs = ObjectsTotal(0, -1, OBJ_BUTTON);
   for(int i = total_objs - 1; i >= 0; i--)
   {
      string bName = ObjectName(0, i, -1, OBJ_BUTTON);
      if(StringFind(bName, UniqueButtonID) >= 0 || StringFind(bName, "HalfTrend_BT") >= 0)
      {
         if(bName != buttonId)
            ObjectDelete(0, bName);
      }
   }

   // When parameters are changed by user in properties dialog, delete old global variables and respect inputs strictly
   bool isParamChange = (UninitializeReason() == REASON_PARAMETERS);
   if(isParamChange && g_gvHidden != "")
   {
      GlobalVariableDel(g_gvHidden);
      for(int k = 0; k < 5; k++)
      {
         GlobalVariableDel(g_prefix + IntegerToString(ChartID()) + "_W" + IntegerToString(k));
         GlobalVariableDel(g_prefix + IntegerToString(ChartID()) + "_S" + IntegerToString(k));
      }
   }

   // Restore toggle state across timeframe/symbol changes
   bool hasSavedState = false;
   bool savedHidden   = false;

   if(!isParamChange)
   {
      if(ObjectFind(0, buttonId) >= 0)
      {
         string btnTxt = ObjectGetString(0, buttonId, OBJPROP_TEXT);
         long   btnSt  = ObjectGetInteger(0, buttonId, OBJPROP_STATE);

         if(StringFind(btnTxt, "OFF") >= 0 || StringFind(btnTxt, "Off") >= 0 || btnSt == 0)
            savedHidden = true;
         else if(StringFind(btnTxt, "ON") >= 0 || StringFind(btnTxt, "On") >= 0 || btnSt != 0)
            savedHidden = false;
         hasSavedState = true;
      }

      if(!hasSavedState && GlobalVariableCheck(g_gvHidden))
      {
         savedHidden   = (GlobalVariableGet(g_gvHidden) > 0.5);
         hasSavedState = true;
      }
   }

   if(hasSavedState)
      IndicatorHidden = savedHidden;
   else
      IndicatorHidden = false;

   IndicatorEnabled = !IndicatorHidden;

   if(g_gvHidden != "")
      GlobalVariableSet(g_gvHidden, IndicatorHidden ? 1.0 : 0.0);

   SetIndexBuffer(0, up, INDICATOR_DATA);
   SetIndexBuffer(1, down, INDICATOR_DATA);
   SetIndexBuffer(2, atrlo, INDICATOR_DATA);
   SetIndexBuffer(3, atrhi, INDICATOR_DATA);
   SetIndexBuffer(4, atrclr, INDICATOR_COLOR_INDEX);
   SetIndexBuffer(5, arrup, INDICATOR_DATA);
   SetIndexBuffer(6, arrdwn, INDICATOR_DATA);
   SetIndexBuffer(7, trend, INDICATOR_CALCULATIONS);
   SetIndexBuffer(8, iMAHigh, INDICATOR_CALCULATIONS);
   SetIndexBuffer(9, iMALow, INDICATOR_CALCULATIONS);
   SetIndexBuffer(10, iATRx, INDICATOR_CALCULATIONS);

   ArraySetAsSeries(up, true);
   ArraySetAsSeries(down, true);
   ArraySetAsSeries(atrlo, true);
   ArraySetAsSeries(atrhi, true);
   ArraySetAsSeries(atrclr, true);
   ArraySetAsSeries(arrup, true);
   ArraySetAsSeries(arrdwn, true);
   ArraySetAsSeries(trend, true);
   ArraySetAsSeries(iMAHigh, true);
   ArraySetAsSeries(iMALow, true);
   ArraySetAsSeries(iATRx, true);

   ApplyPlotsStyle();
   if(!isParamChange)
      RestorePlotStyles();
   SavePlotStyles();
   CreateToggleButton();
   BringButtonsToFront();

   IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
   IndicatorSetString(INDICATOR_SHORTNAME, IndicatorName);

   ind_mahi = iMA(NULL, 0, Amplitude, 0, MODE_SMA, PRICE_HIGH);
   ind_malo = iMA(NULL, 0, Amplitude, 0, MODE_SMA, PRICE_LOW);
   ind_atr = iATR(NULL, 0, 100);
   if(ind_mahi == INVALID_HANDLE || ind_malo == INVALID_HANDLE || ind_atr == INVALID_HANDLE)
   {
      PrintFormat("Failed to create handle of the indicators, error code %d", GetLastError());
      return(INIT_FAILED);
   }
   nexttrend = 0;
   minhighprice = iHigh(NULL, 0, Bars(NULL, 0) - 1);
   maxlowprice = iLow(NULL, 0, Bars(NULL, 0) - 1);
   return (INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   if(reason == REASON_CHARTCHANGE)
   {
      SavePlotStyles();
   }

   if(reason == REASON_REMOVE || reason == REASON_CHARTCLOSE || reason == REASON_PARAMETERS)
   {
      ObjectDelete(0, buttonId);
      ObjectDelete(0, ToggleButtonName);
      if(g_gvHidden != "")
         GlobalVariableDel(g_gvHidden);

      if(reason == REASON_REMOVE || reason == REASON_CHARTCLOSE)
      {
         for(int k = 0; k < 5; k++)
         {
            GlobalVariableDel(g_prefix + IntegerToString(ChartID()) + "_W" + IntegerToString(k));
            GlobalVariableDel(g_prefix + IntegerToString(ChartID()) + "_S" + IntegerToString(k));
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int  OnCalculate(
   const int        rates_total,       // size of input time series
   const int        prev_calculated,   // number of handled bars at the previous call
   const datetime&  time[],            // Time array
   const double&    open[],            // Open array
   const double&    high[],            // High array
   const double&    low[],             // Low array
   const double&    close[],           // Close array
   const long&      tick_volume[],     // Tick Volume array
   const long&      volume[],          // Real Volume array
   const int&       spread[]           // Spread array
)
{
   if(rates_total < 2)
      return(0);

   if(prev_calculated <= 0)
   {
      CreateToggleButton();
      ApplyPlotsStyle();
   }

   int i, limit, to_copy;
   double atr, lowprice_i, highprice_i, lowma, highma;
   ArraySetAsSeries(time, true);
   ArraySetAsSeries(high, true);
   ArraySetAsSeries(low, true);
   ArraySetAsSeries(close, true);
   if(prev_calculated > rates_total || prev_calculated < 0) to_copy = rates_total;
   else
   {
      to_copy = rates_total - prev_calculated;
      if(prev_calculated > 0)
         to_copy += 10;
   }
   if(!RefreshBuffers(iMAHigh, iMALow, iATRx, ind_mahi, ind_malo, ind_atr, to_copy))
      return(0);
   if(prev_calculated == 0)
   {
      limit = rates_total - 2;
      up[rates_total - 1]     = 0.0;
      down[rates_total - 1]   = 0.0;
      atrlo[rates_total - 1]  = 0.0;
      atrhi[rates_total - 1]  = 0.0;
      atrclr[rates_total - 1] = 0.0;
      arrup[rates_total - 1]  = EMPTY_VALUE;
      arrdwn[rates_total - 1] = EMPTY_VALUE;
      trend[rates_total - 1]  = 0.0;
   }
   else
      limit = rates_total - prev_calculated + 1;
   for(i = limit; i >= 0; i--)
   {
      lowprice_i = iLow(NULL, 0, iLowest(NULL, 0, MODE_LOW, Amplitude, i));
      highprice_i = iHigh(NULL, 0, iHighest(NULL, 0, MODE_HIGH, Amplitude, i));
      lowma = NormalizeDouble(iMALow[i], _Digits);
      highma = NormalizeDouble(iMAHigh[i], _Digits);
      trend[i] = trend[i + 1];
      atr = iATRx[i] / 2;
      arrup[i]  = EMPTY_VALUE;
      arrdwn[i] = EMPTY_VALUE;
      if(trend[i + 1] != 1.0)
      {
         maxlowprice = MathMax(lowprice_i, maxlowprice);
         if(highma < maxlowprice && close[i] < low[i + 1])
         {
            trend[i] = 1.0;
            nexttrend = 0;
            minhighprice = highprice_i;
         }
      }
      else
      {
         minhighprice = MathMin(highprice_i, minhighprice);
         if(lowma > minhighprice && close[i] > high[i + 1])
         {
            trend[i] = 0.0;
            nexttrend = 1;
            maxlowprice = lowprice_i;
         }
      }
      //---
      if(trend[i] == 0.0)
      {
         if(trend[i + 1] != 0.0)
         {
            up[i] = down[i + 1];
            up[i + 1] = up[i];
            arrup[i] = up[i] - 2 * atr;
         }
         else
         {
            up[i] = MathMax(maxlowprice, up[i + 1]);
         }
         atrhi[i] = up[i] - atr;
         atrlo[i] = up[i];
         atrclr[i] = 0;
         down[i] = 0.0;
      }
      else
      {
         if(trend[i + 1] != 1.0)
         {
            down[i] = up[i + 1];
            down[i + 1] = down[i];
            arrdwn[i] = down[i] + 2 * atr;
         }
         else
         {
            down[i] = MathMin(minhighprice, down[i + 1]);
         }
         atrhi[i] = down[i] + atr;
         atrlo[i] = down[i];
         atrclr[i] = 1;
         up[i] = 0.0;
      }
   }
   if(!IndicatorHidden)
      manageAlerts();
   return (rates_total);
}

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   if(id == CHARTEVENT_OBJECT_CLICK)
   {
      string altId = "_" + UniqueButtonID + IndicatorObjPrefix + "_BT_";
      if(sparam == buttonId || sparam == ToggleButtonName || sparam == altId)
      {
         ToggleIndicatorVisibility();
         return;
      }
   }

   if(id == CHARTEVENT_CHART_CHANGE)
   {
      SavePlotStyles();
      BringButtonsToFront();
   }
}

//+------------------------------------------------------------------+
//| Filling indicator buffers from the indicators                    |
//+------------------------------------------------------------------+
bool RefreshBuffers(double &hi_buffer[],
                    double &lo_buffer[],
                    double &atr_buffer[],
                    int hi_handle,
                    int lo_handle,
                    int atr_handle,
                    int amount
                   )
{
//--- reset error code
   ResetLastError();
//--- fill a part of the iMACDBuffer array with values from the indicator buffer that has 0 index
   if(CopyBuffer(hi_handle, 0, 0, amount, hi_buffer) < 0)
   {
      //--- if the copying fails, tell the error code
      PrintFormat("Failed to copy data from the MaHigh indicator, error code %d", GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
   }
//--- fill a part of the SignalBuffer array with values from the indicator buffer that has index 1
   if(CopyBuffer(lo_handle, 0, 0, amount, lo_buffer) < 0)
   {
      //--- if the copying fails, tell the error code
      PrintFormat("Failed to copy data from the MaLow indicator, error code %d", GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
   }
//--- fill a part of the StdDevBuffer array with values from the indicator buffer
   if(CopyBuffer(atr_handle, 0, 0, amount, atr_buffer) < 0)
   {
      //--- if the copying fails, tell the error code
      PrintFormat("Failed to copy data from the ATR indicator, error code %d", GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
   }
//--- everything is fine
   return(true);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void manageAlerts()
{
   int whichBar;
   if (alertsOn)
   {
      if (alertsOnCurrent)
         whichBar = 0;
      else
         whichBar = 1;
      if (arrup[whichBar]  != EMPTY_VALUE) doAlert(whichBar, "up");
      if (arrdwn[whichBar] != EMPTY_VALUE) doAlert(whichBar, "down");
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void doAlert(int forBar, string doWhat)
{
   static string   previousAlert = "nothing";
   static datetime previousTime;
   string message;
   if (previousAlert != doWhat || previousTime != iTime(NULL, 0, forBar))
   {
      previousAlert  = doWhat;
      previousTime   = iTime(NULL, 0, forBar);
      message = StringFormat("%s at %s", Symbol(), TimeToString(TimeLocal(), TIME_SECONDS), " HalfTrend signal ", doWhat);
      if (alertsMessage) Alert(message);
      if (alertsEmail)   SendMail(Symbol(), StringFormat("HalfTrend %s", message));
      if (alertsSound)   PlaySound("alert2.wav");
      if (alertsNotify)  SendNotification(message);
   }
}

//+------------------------------------------------------------------+
