//+------------------------------------------------------------------+
//|                                                  scan_arrows.mqh |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
enum typ_sygan
  {
   off_syyg=0,
   up_syyg=1,
   down_syyg=2
  };
struct cons_data
  {
                     cons_data();
   double            prices[];
   bool              sign_s[];
   double            price_1;
   double            price_2;
   double            price_3;
   bool              sign_1;
   bool              sign_2;
   bool              sign_3;
   void              reset();
   int               get_dots_summ();
   void              set_dots(const int ddo);
private:
   int               dots;
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
cons_data::cons_data(void)
  {
   this.price_1=-1;;
   this.price_2=-1;
   this.price_3=-1;
   this.sign_1=false;
   this.sign_2=false;
   this.sign_3=false;
   this.dots=0;
   ArrayResize(this.prices,0);
   ArrayResize(this.sign_s,0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int cons_data::get_dots_summ(void)
  {
   return this.dots;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void cons_data::set_dots(const int ddo)
  {
   this.dots=ddo;
   ArrayResize(this.prices,this.dots);
   ArrayResize(this.sign_s,this.dots);
   ArrayInitialize(this.prices,-1.0);
   ArrayInitialize(this.sign_s,false);
  }
//+------------------------------------------------------------------+

void cons_data::reset(void)
  {
   this.dots=0;
   ArrayResize(this.prices,0);
   ArrayResize(this.sign_s,0);
   this.price_1=-1;;
   this.price_2=-1;
   this.price_3=-1;
   this.sign_1=false;
   this.sign_2=false;
   this.sign_3=false;
  }
//+------------------------------------------------------------------+

class scan_arrows
  {
private:
   int               how_much_pixel;
   int               how_much_dot;
   typ_sygan         typ_sygnal;
   double            heigt_signal;
   int               num_last_bar;
   datetime          t_signal;
   int               maxbar;
   bool              b_scan;
   double            get_siz_pix();
public:
   void              shift_bufer_dn(const int shi,const int sizz,double &buf[],double &buf_res[]);
   void              shift_bufer_up(const int shi,const int sizz,double &buf[],double &buf_res[]);
   typ_sygan         get_typ_syg();
   void              set_time_signal(const datetime tsy);
   datetime          get_time_signal();
   double            shift_price();
   int               get_num_bar_last();
   void              set_para_b(const int dots);
   void              set_para_c(const int ccpix);
   void              set_para(const int barr,const bool bsca);
   void              scan_bufers(double &buf_1up[],double &buf_2up[],
                                 double &buf_3up[],double &buf_4up[],
                                 double &buf_1down[],double &buf_2down[],
                                 double &buf_3down[],double &buf_4down[],
                                 double &buf_destin_up[],double &buf_destin_down[]);
                     scan_arrows();
                    ~scan_arrows();
  };
//+------------------------------------------------------------------+

scan_arrows::scan_arrows()
  {
   this.how_much_pixel=30;
   this.how_much_dot=2;
   this.typ_sygnal=off_syyg;
   this.heigt_signal=0;
   this.num_last_bar=Bars-1;
   this.t_signal=0;
   this.maxbar=0;
   this.b_scan=true;
  }
//+------------------------------------------------------------------+

void scan_arrows::shift_bufer_up(const int shi,const int sizz,double &buf[],double &buf_res[])
  {
   int raz=sizz;
   if(Bars<=sizz)
     {
      raz=Bars-1;
     }
   if(shi==0)
     {
      for(int i=raz; i>=0; i--)
        {
         buf_res[i]=buf[i];
        }
      return;
     }
   for(int i=raz-1; i>=shi; i--)
     {
      if(buf[i]>0)
        {
         buf_res[i-shi]=Low[i-shi];
        }
      else
        {
         buf_res[i-shi]=0;
        }
     }
  }
//+------------------------------------------------------------------+

void scan_arrows::shift_bufer_dn(const int shi,const int sizz,double &buf[],double &buf_res[])
  {
   int raz=sizz;
   if(Bars<=sizz)
     {
      raz=Bars-1;
     }
   if(shi==0)
     {
      for(int i=raz; i>=0; i--)
        {
         buf_res[i]=buf[i];
        }
      return;
     }
   for(int i=raz; i>=shi; i--)
     {
      if(buf[i]>0)
        {
         buf_res[i-shi]=High[i-shi];
        }
      else
        {
         buf_res[i-shi]=0;
        }
     }
  }
//+------------------------------------------------------------------+

void scan_arrows::set_para_c(const int ccpix)
  {
   this.how_much_pixel=ccpix;
  }
//+------------------------------------------------------------------+

void scan_arrows::set_para_b(const int dots)
  {
   this.how_much_dot=dots>1?dots:1;
//Alert(__FUNCTION__+" dots sum : ",this.how_much_dot);
  }
//+------------------------------------------------------------------+

typ_sygan scan_arrows::get_typ_syg(void)
  {
   return this.typ_sygnal;
  }
//+------------------------------------------------------------------+

void scan_arrows::set_time_signal(const datetime tsy)
  {
   this.t_signal=tsy;
  }

//+------------------------------------------------------------------+
datetime scan_arrows::get_time_signal(void)
  {
   return this.t_signal;
  }

//+------------------------------------------------------------------+
double scan_arrows::shift_price(void)
  {
   return this.heigt_signal;
  }

//+------------------------------------------------------------------+
int scan_arrows::get_num_bar_last(void)
  {
   return this.num_last_bar;
  }

//+------------------------------------------------------------------+
double scan_arrows::get_siz_pix()
  {
   double siiz=0;
   datetime tt=0;
   double ppr=0;
   double ppr2=0;
   int ssu=0;
   int ssu2=0;
   bool bb=ChartXYToTimePrice(0,10,20,ssu,tt,ppr);
   bool bb2=ChartXYToTimePrice(0,10,21,ssu2,tt,ppr2);
   if(bb&&bb2&&ssu==ssu2)
     {
      siiz=MathAbs(ppr-ppr2);
     }
   return siiz*this.how_much_pixel;
  }
//+------------------------------------------------------------------+
void scan_arrows::scan_bufers(double &buf_1up[],double &buf_2up[],
                              double &buf_3up[],double &buf_4up[],
                              double &buf_1down[],double &buf_2down[],
                              double &buf_3down[],double &buf_4down[],
                              double &buf_destin_up[],double &buf_destin_down[])
  {
   int i=this.maxbar;
   double v_hift=get_siz_pix();
   typ_sygan tysy=off_syyg;
   cons_data dataup;
   cons_data datadown;
   dataup.set_dots(this.how_much_dot);
   datadown.set_dots(this.how_much_dot);
   for(int t=0; t<3; t++)
      buf_destin_up[t]=0;
   for(int t=0; t<3; t++)
      buf_destin_down[t]=0;
   for(i; i>=0; i--)
     {
      if(buf_1down[i]>0||
         buf_2down[i]>0||
         buf_3down[i]>0||
         buf_4down[i]>0)
        {
         int doots=datadown.get_dots_summ()-1;
         if(datadown.sign_s[doots])
           {
            for(int j=0; j<doots; j++)
              {
               datadown.prices[j]=datadown.prices[j+1];
              }
            if(buf_1down[i]>0)
               datadown.prices[doots]=buf_1down[i];
            if(buf_2down[i]>0)
               datadown.prices[doots]=buf_2down[i];
            if(buf_3down[i]>0)
               datadown.prices[doots]=buf_3down[i];
            if(buf_4down[i]>0)
               datadown.prices[doots]=buf_4down[i];
           }
         if(!datadown.sign_s[doots])
           {
            int z_num=0;
            for(int j=0; j<=doots; j++)
              {
               if(!datadown.sign_s[j])
                 {
                  z_num=j;
                  break;
                 }
              }
            datadown.sign_s[z_num]=true;
            if(buf_1down[i]>0)
               datadown.prices[z_num]=buf_1down[i];
            if(buf_2down[i]>0)
               datadown.prices[z_num]=buf_2down[i];
            if(buf_3down[i]>0)
               datadown.prices[z_num]=buf_3down[i];
            if(buf_4down[i]>0)
               datadown.prices[z_num]=buf_4down[i];
           }

         if(datadown.sign_s[doots])
           {
            bool resu_good=true;
            for(int j=0; j<doots; j++)
              {
               if(datadown.prices[j]>datadown.prices[doots])
                  resu_good=false;
              }
            if(!resu_good)
              {
               continue;
              }
            if(tysy==down_syyg&&!this.b_scan)
              {
               continue;
              }
            buf_destin_down[i]=datadown.prices[doots]+v_hift;
            tysy=down_syyg;
            this.typ_sygnal=tysy;
            double pricc=datadown.prices[0];
            for(int j=0; j<=doots; j++)
              {
               if(pricc<datadown.prices[j])
                  pricc=datadown.prices[j];
              }
            this.heigt_signal=datadown.prices[doots]-pricc;
            this.num_last_bar=i;
            continue;
           }
        }

      if(buf_1up[i]>0||
         buf_2up[i]>0||
         buf_3up[i]>0||
         buf_4up[i]>0)
        {
         int doots=dataup.get_dots_summ()-1;
         if(dataup.sign_s[doots])
           {
            for(int j=0; j<doots; j++)
              {
               dataup.prices[j]=dataup.prices[j+1];
              }
            if(buf_1up[i]>0)
               dataup.prices[doots]=buf_1up[i];
            if(buf_2up[i]>0)
               dataup.prices[doots]=buf_2up[i];
            if(buf_3up[i]>0)
               dataup.prices[doots]=buf_3up[i];
            if(buf_4up[i]>0)
               dataup.prices[doots]=buf_4up[i];
           }
         if(!dataup.sign_s[doots])
           {
            int z_num=0;
            for(int j=0; j<=doots; j++)
              {
               if(!dataup.sign_s[j])
                 {
                  z_num=j;
                  break;
                 }
              }
            dataup.sign_s[z_num]=true;
            if(buf_1up[i]>0)
               dataup.prices[z_num]=buf_1up[i];
            if(buf_2up[i]>0)
               dataup.prices[z_num]=buf_2up[i];
            if(buf_3up[i]>0)
               dataup.prices[z_num]=buf_3up[i];
            if(buf_4up[i]>0)
               dataup.prices[z_num]=buf_4up[i];
           }

         if(dataup.sign_s[doots])
           {
            bool resu_good=true;
            for(int j=0; j<doots; j++)
              {
               if(dataup.prices[j]<dataup.prices[doots])
                  resu_good=false;
              }
            if(!resu_good)
              {
               continue;
              }
            if(tysy==up_syyg&&!this.b_scan)
              {
               continue;
              }
            buf_destin_up[i]=dataup.prices[doots]-v_hift;
            tysy=up_syyg;
            this.typ_sygnal=tysy;
            double pricc=dataup.prices[0];
            for(int j=0; j<=doots; j++)
              {
               if(pricc>dataup.prices[j])
                  pricc=dataup.prices[j];
              }
            this.heigt_signal=pricc-dataup.prices[doots];
            this.num_last_bar=i;
            continue;
           }
        }
     }
  }

//+------------------------------------------------------------------+
void scan_arrows::set_para(const int barr,const bool bsca)
  {
   this.maxbar=barr>0?barr:1;
   this.b_scan=bsca;
//Alert(__FUNCSIG__+" this.maxbar ",this.maxbar," this.b_scan ",this.b_scan);
  }

//+------------------------------------------------------------------+
scan_arrows::~scan_arrows()
  {
  }
//+------------------------------------------------------------------+
