//+------------------------------------------------------------------+
//|                                                  Accelerator.mq4 |
//|                   Copyright 2005-2022, MetaQuotes Software Corp. |
//|                                              http://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright   "2005-2022, MetaQuotes Software Corp."
#property link        "http://www.mql4.com"
#property description "Accelerator/Decelerator"
#property strict

#include <MovingAverages.mqh>

//--- indicator settings
#property  indicator_separate_window
#property  indicator_buffers 3
#property  indicator_color1  clrBlack
#property  indicator_color2  clrOlive
#property  indicator_color3  clrMagenta

#property  indicator_width2  2
#property  indicator_width3  2

//Forex-Station button template start41; copy and paste
input string             button_note1          = "------------------------------";
input int                btn_Subwindow         = 0;
input ENUM_BASE_CORNER   btn_corner            = CORNER_LEFT_UPPER; 
input string             btn_text              = "ACCEL";
input string             btn_Font              = "Arial";
input int                btn_FontSize          = 9;                        
input color              btn_text_ON_color     = clrLime;
input color              btn_text_OFF_color    = clrRed;
input color              btn_background_color  = clrDimGray;
input color              btn_border_color      = clrBlack;
input int                button_x              = 260;                                   
input int                button_y              = 45;                                   
input int                btn_Width             = 80;                                
input int                btn_Height            = 20;
input string             soundBT               = "tick.wav";        // sound file when the button is pressed
input string             UniqueButtonID        = "AcceleratorButton";                               
input string             button_note2          = "------------------------------";

bool show_data = true, recalc = true;
string indicatorFileName, IndicatorName, IndicatorObjPrefix,buttonId;
//Forex-Station button template end41; copy and paste

//--- indicator buffers
double     ExtACBuffer[],ExtUpBuffer[],ExtDnBuffer[],ExtMacdBuffer[],ExtSignalBuffer[];
//---
#define PERIOD_FAST  5
#define PERIOD_SLOW 34
//--- bars minimum for calculation
#define DATA_LIMIT  38
//+------------------------------------------------------------------------------------------------------------------+
//Forex-Station button template start42; copy and paste
string GenerateIndicatorName(const string target) 
{
   string name = target;
   int try = 2;
   while (WindowFind(name) != -1)
      name = target + " #" + IntegerToString(try++);
   return name;
}
//+------------------------------------------------------------------------------------------------------------------+
int OnInit()
{
   IndicatorName = GenerateIndicatorName(btn_text);
   IndicatorObjPrefix = "__" + IndicatorName + "__";
   
   double val;
   if (GlobalVariableGet(IndicatorName + "_visibility", val))
      show_data = val != 0;

   indicatorFileName = WindowExpertName();
   
   ChartSetInteger(ChartID(), CHART_EVENT_MOUSE_MOVE, 1);
   buttonId = IndicatorObjPrefix + UniqueButtonID;
   createButton(buttonId, btn_text, btn_Width, btn_Height, btn_Font, btn_FontSize, btn_background_color, btn_border_color, btn_text_ON_color);
   ObjectSetInteger(ChartID(), buttonId, OBJPROP_YDISTANCE, button_y);
   ObjectSetInteger(ChartID(), buttonId, OBJPROP_XDISTANCE, button_x);
   
// put init() here
   init2();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------------------------------------------------------+
void OnDeinit(const int reason) { 
     ObjectsDeleteAll(ChartID(), buttonId);
}
//+------------------------------------------------------------------+
void createButton(string buttonID,string buttonText,int width2,int height,string font,int fontSize,color bgColor,color borderColor,color txtColor)
{
      ObjectDelete    (ChartID(),buttonID);
      ObjectCreate    (ChartID(),buttonID,OBJ_BUTTON,btn_Subwindow,0,0);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_COLOR,txtColor);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_BGCOLOR,bgColor);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_BORDER_COLOR,borderColor);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_BORDER_TYPE,BORDER_RAISED);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_XSIZE,width2);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_YSIZE,height);
      ObjectSetString (ChartID(),buttonID,OBJPROP_FONT,font);
      ObjectSetString (ChartID(),buttonID,OBJPROP_TEXT,buttonText);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_FONTSIZE,fontSize);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_SELECTABLE,0);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_CORNER,btn_corner);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_HIDDEN,1);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_XDISTANCE,9999);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_YDISTANCE,9999);
}
//+------------------------------------------------------------------+
void handleButtonClicks()
{
   if (ObjectGetInteger(ChartID(), buttonId, OBJPROP_STATE))
   {
      ObjectSetInteger(ChartID(), buttonId, OBJPROP_STATE, false);
      show_data = !show_data;
      GlobalVariableSet(IndicatorName + "_visibility", show_data ? 1.0 : 0.0);
      recalc = true;
   }
}
//+------------------------------------------------------------------------------------------------------------------+
void OnChartEvent(const int id, 
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   handleButtonClicks();
   if (id==CHARTEVENT_OBJECT_CLICK && ObjectGet(sparam,OBJPROP_TYPE)==OBJ_BUTTON)
      if (soundBT!="") PlaySound(soundBT);     

      if (show_data)
         {
          ObjectSetInteger(ChartID(),buttonId,OBJPROP_COLOR,btn_text_ON_color);
          init2();
         }
      else
      {
       ObjectSetInteger(ChartID(),buttonId,OBJPROP_COLOR,btn_text_OFF_color);
       for (int banzai=0; banzai<indicator_buffers; banzai++)
           SetIndexStyle(banzai,DRAW_NONE);
      }
}
//Forex-Station button template end42; copy and paste
//+------------------------------------------------------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init2(void)
  {
   IndicatorShortName("AC");
//--- 2 additional buffers are used for counting.
   IndicatorBuffers(5);
//--- drawing settings
   SetIndexStyle(0,DRAW_NONE);
   SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexStyle(2,DRAW_HISTOGRAM);
   IndicatorDigits(Digits+2);
   SetIndexDrawBegin(0,DATA_LIMIT);
   SetIndexDrawBegin(1,DATA_LIMIT);
   SetIndexDrawBegin(2,DATA_LIMIT);
//--- all indicator buffers mapping
   SetIndexBuffer(0,ExtACBuffer);
   SetIndexBuffer(1,ExtUpBuffer);
   SetIndexBuffer(2,ExtDnBuffer);
   SetIndexBuffer(3,ExtMacdBuffer);
   SetIndexBuffer(4,ExtSignalBuffer);
//--- name for DataWindow and indicator subwindow label
   SetIndexLabel(1,NULL);
   SetIndexLabel(2,NULL);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Accelerator/Decelerator Oscillator                               |
//+------------------------------------------------------------------+
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[])
  {
   int    i,limit;
   double prev=0.0,current;
//--- check for rates total
   if(rates_total<=DATA_LIMIT)
      return(0);
//--- last counted bar will be recounted
   limit=rates_total-prev_calculated;
   if(prev_calculated>0)
     {
      limit++;
      prev=ExtMacdBuffer[limit]-ExtSignalBuffer[limit];
     }
//--- macd counted in the 1-st additional buffer
   for(i=0; i<limit; i++)
      ExtMacdBuffer[i]=iMA(NULL,0,PERIOD_FAST,0,MODE_SMA,PRICE_MEDIAN,i)-
                       iMA(NULL,0,PERIOD_SLOW,0,MODE_SMA,PRICE_MEDIAN,i);
//--- signal line counted in the 2-nd additional buffer
   SimpleMAOnBuffer(rates_total,prev_calculated,0,5,ExtMacdBuffer,ExtSignalBuffer);
//--- dispatch values between 2 buffers
   bool up=true;
   for(i=limit-1; i>=0;)
     {
      current=ExtMacdBuffer[i]-ExtSignalBuffer[i];
      if(current>prev)
         up=true;
      if(current<prev)
         up=false;
      if(!up)
        {
         ExtUpBuffer[i]=0.0;
         ExtDnBuffer[i]=current;
        }
      else
        {
         ExtUpBuffer[i]=current;
         ExtDnBuffer[i]=0.0;
        }
      ExtACBuffer[i]=current;
      i--;
      prev=ExtMacdBuffer[i+1]-ExtSignalBuffer[i+1];
     }
//--- done
   return(rates_total);
  }
//+------------------------------------------------------------------+
