//+------------------------------------------------------------------+
//|                                                 ^X_Parabolic.mq4 |
//|                                                      Version 1.2 |
//|                                                                  |
//|                     Copyright © 2007, Mr.WT, Senior Linux Hacker |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+

#property copyright "Copyright © 2007, Mr.WT, Senior Linux Hacker"
#property link      "http://www.metaquotes.net/"

#property indicator_chart_window
#property indicator_color1 Aqua
#property indicator_color2 Orange
#property indicator_color3 DeepSkyBlue
#property indicator_color4 Red

extern int _RegressionDegree = 3;
extern color _TrendLineColor = Gold;
extern color _ResLineColor = OrangeRed;
extern color _SupLineColor = DeepSkyBlue;
extern color _RegressionColor1 = Yellow;
extern color _RegressionColor2 = Lime;
extern color _RegressionColor3 = Red;
extern color _RegressionColor4 = RoyalBlue;
//------------------------------------------
double fx,fx1;
double a[10,10],b[10],x[10],sx[20];
double sum,sum1,sq; 
int p,nn,kt;
//---------------------
int i0,ip,pn,i0n,ipn;
int t0,tp,te,te1;
int _N_Time, _Cur_Period;
double _K_L.Dev.min = 1.73;
double _K_N.L.Dev = 2.73;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init() {
//----
IndicatorShortName("Stop And Reverse");

if(Period() == PERIOD_MN1) {
 p = 13;
} else if(Period() == PERIOD_W1) {
 p = 21;
} else if(Period() == PERIOD_D1) {
 p = 89;
} else if(Period() == PERIOD_H4) {
 p = 144;
} else p = 233;
//--- too small history
if(p>Bars) {
  Comment("\n\n                    ERROR - TOO SMALL HISTORY, RETURN NOW!");
  return(-1); // then exit
}

//----------------------ar------------------------------
  kt=Period()*60;
  nn=_RegressionDegree+1; 
  //----------------------
  t0=Time[0];
  i0=iBarShift(Symbol(),Period(),t0);
  ip=i0+p;
  tp=Time[ip];
  pn=p;
  //----------------------ar------------------------------
  for (int j=-p/2; j<p; j++)
  {
    ObjectCreate("ar"+j,2,0,Time[i0+1+j],0,Time[i0+j],0); 
    ObjectSet("ar"+j,OBJPROP_RAY,0);  
    ObjectCreate("arH"+j,2,0,Time[i0+1+j],0,Time[i0+j],0); 
    ObjectSet("arH"+j,OBJPROP_RAY,0);
    ObjectCreate("arL"+j,2,0,Time[i0+1+j],0,Time[i0+j],0); 
    ObjectSet("arL"+j,OBJPROP_RAY,0);  
  }
  //----------------------LR------------------------------
  ObjectCreate("LR",OBJ_TREND,0,Time[0],0,Time[0],0);
  ObjectSet("LR",OBJPROP_COLOR,_TrendLineColor); 
  ObjectSet("LR",OBJPROP_RAY,1);
  ObjectSet("LR",OBJPROP_STYLE,STYLE_SOLID);

  ObjectCreate("1-st Level ResLine",OBJ_TREND,0,Time[0],0,Time[0],0);
  ObjectSet("1-st Level ResLine",OBJPROP_COLOR,_ResLineColor);
  ObjectSet("1-st Level ResLine",OBJPROP_RAY,1);
  ObjectSet("1-st Level ResLine",OBJPROP_STYLE,STYLE_SOLID);

  ObjectCreate("1-st Level SupLine",OBJ_TREND,0,Time[0],0,Time[0],0);
  ObjectSet("1-st Level SupLine",OBJPROP_COLOR,_SupLineColor);
  ObjectSet("1-st Level SupLine",OBJPROP_RAY,1);
  ObjectSet("1-st Level SupLine",OBJPROP_STYLE,STYLE_SOLID);

  ObjectCreate("2-nd Level ResLine",OBJ_TREND,0,Time[0],0,Time[0],0);
  ObjectSet("2-nd Level ResLine",OBJPROP_COLOR,_ResLineColor);
  ObjectSet("2-nd Level ResLine",OBJPROP_RAY,1);
  ObjectSet("2-nd Level ResLine",OBJPROP_STYLE,STYLE_DASH);

  ObjectCreate("2-nd Level SupLine",OBJ_TREND,0,Time[0],0,Time[0],0);
  ObjectSet("2-nd Level SupLine",OBJPROP_COLOR,_SupLineColor);
  ObjectSet("2-nd Level SupLine",OBJPROP_RAY,1);
  ObjectSet("2-nd Level SupLine",OBJPROP_STYLE,STYLE_DASH);
//----
_N_Time = 0;
_Cur_Period = 0;
return(0);
}

int deinit() {
  for (int j=p; j>=-p/2; j--)
  { 
    ObjectDelete("ar"+j);
    ObjectDelete("arH"+j);
    ObjectDelete("arL"+j);
  }
  ObjectDelete("LR");
  ObjectDelete("1-st Level ResLine");
  ObjectDelete("1-st Level SupLine");
  ObjectDelete("2-nd Level ResLine");
  ObjectDelete("2-nd Level SupLine");
  Comment("");
return(0);
}

//+------------------------------------------------------------------+

int start() {

if( _N_Time != Time[0] || _Cur_Period != Period() ) {
//=================================================================
  int i,n,k;
  double std.dev;
  //---- 
    if (i0n!=i0 || ipn!=ip)
    {
      p=ip-i0;
      i0n=ip;
      ipn=ip;
      //--------------------------------------------------------
      if (pn<p)
      {
        for(int j=pn; j<=p; j++) {
          ObjectCreate("ar"+j,2,0,Time[i0+1+j],0,Time[i0+j],0);
          ObjectSet("ar"+j,OBJPROP_RAY,0);
          ObjectCreate("arH"+j,2,0,Time[i0+1+j],0,Time[i0+j],0);
          ObjectSet("arH"+j,OBJPROP_RAY,0);
          ObjectCreate("arL"+j,2,0,Time[i0+1+j],0,Time[i0+j],0);
          ObjectSet("arL"+j,OBJPROP_RAY,0);
        }  
        
        for (j=-pn/2; j>=-p/2; j--) {
          ObjectCreate("ar"+j,2,0,Time[i0+1+j],0,Time[i0+j],0); 
          ObjectSet("ar"+j,OBJPROP_RAY,0); 
          ObjectCreate("arH"+j,2,0,Time[i0+1+j],0,Time[i0+j],0); 
          ObjectSet("arH"+j,OBJPROP_RAY,0); 
          ObjectCreate("arL"+j,2,0,Time[i0+1+j],0,Time[i0+j],0); 
          ObjectSet("arL"+j,OBJPROP_RAY,0);
        } 
        pn=p;    
      }
      if (pn>p)
      {
        for(j=pn; j>=p; j--) {
          ObjectDelete("ar"+j); 
          ObjectDelete("arH"+j); 
          ObjectDelete("arL"+j);
        }
        
        for (j=-p/2; j>=-pn/2; j--) {
          ObjectDelete("ar"+j); 
          ObjectDelete("arH"+j); 
          ObjectDelete("arL"+j);
        }   
        pn=p;
      }
    }
    //======================PR================================================
    sx[1]=p+1;
    //----------------------sx------------------------------------------------
    for(i=1; i<=nn*2-2; i++) 
    {
      sum=0.0; 
      for(n=i0; n<=i0+p; n++) sum+=MathPow(n,i); 
      sx[i+1]=sum;
    }  
    //----------------------syx-----------------------------------------------
    for(i=1; i<=nn; i++) 
    {
      sum=0.0; 
      for(n=i0; n<=i0+p; n++) 
      {
        if (i==1) sum+=Close[n]; 
        else 
        sum+=Close[n]*MathPow(n,i-1);
      } 
      b[i]=sum;
    } 
    //===============Matrix==================================================
    for(j=1; j<=nn; j++) 
    {
      for(i=1; i<=nn; i++) {k=i+j-1; a[i,j]=sx[k];}
    }  
    //===============Gauss===================================================
    af_Gauss(nn,a,b,x);
    //=======================SQ==============================================
    sq=0.0;
    for (n=p; n>=0; n--)
    {
      sum=0.0;
      for(k=1; k<=_RegressionDegree; k++) {
        sum+=x[k+1]*MathPow(i0+n,k); 
        sum1+=x[k+1]*MathPow(i0+n+1,k);
      }
      fx=x[1]+sum;
      sq+=MathPow(Close[n+i0]-fx,2);
    }
    std.dev = MathSqrt(sq/(p+1));

// regression calculation
int end.bar = 1, start.bar = p + 1, q = p;
//---- calculate price values
   double xvalue,a,b,c,sumy=0.0,sumx=0.0,sumxy=0.0,sumx2=0.0;
   for(int xx=0; xx<q; xx++)
     {
      xvalue=Close[end.bar+xx];
      sumy+=xvalue;
      sumxy+=xvalue*xx;
      sumx+=xx;
      sumx2+=xx*xx;
     }
   c=sumx2*q-sumx*sumx;
   if(c==0.0) return;
   b=(sumxy*q-sumx*sumy)/c;
   a=(sumy-sumx*b)/q;
   double LR.price.2=a;
   double LR.price.1=a+b*q;
   double _K1 = MathAbs(LR.price.1-LR.price.2); _K1 /= std.dev; _K1 /= 2;
   if(_K1 < _K_L.Dev.min) {
     sq = _K_L.Dev.min * std.dev;
   } else sq = _K1 * std.dev;
   //---
   ObjectMove("LR", 0, Time[start.bar], LR.price.1);
   ObjectMove("LR", 1, Time[end.bar],LR.price.2);
   ObjectMove("2-nd Level ResLine", 0, Time[start.bar], LR.price.1 + sq);
   ObjectMove("2-nd Level ResLine", 1, Time[end.bar], LR.price.2 + sq);
   ObjectMove("2-nd Level SupLine", 0, Time[start.bar], LR.price.1 - sq);
   ObjectMove("2-nd Level SupLine", 1, Time[end.bar], LR.price.2 - sq);
   sq = _K_L.Dev.min * std.dev;
   ObjectMove("1-st Level ResLine", 0, Time[start.bar], LR.price.1 + sq);
   ObjectMove("1-st Level ResLine", 1, Time[end.bar], LR.price.2 + sq);
   ObjectMove("1-st Level SupLine", 0, Time[start.bar], LR.price.1 - sq);
   ObjectMove("1-st Level SupLine", 1, Time[end.bar], LR.price.2 - sq);
   //---
   sq = _K_N.L.Dev * std.dev;
//=======================================================================
    for (n=p; n>=-p/2; n--) 
    {
      sum=0.0; 
      sum1=0.0; 
      for(k=1; k<=_RegressionDegree; k++) {
        sum+=x[k+1]*MathPow(i0+n,k); 
        sum1+=x[k+1]*MathPow(i0+n+1,k);
      }  
      fx=x[1]+sum;
      fx1=x[1]+sum1;
        
      if (n>=0 && n<p)
      {
        ObjectMove("ar"+n,0,Time[n+i0+1],fx1); 
        ObjectMove("ar"+n,1,Time[n+i0],fx);
        ObjectMove("arH"+n,0,Time[n+i0+1],fx1+sq); 
        ObjectMove("arH"+n,1,Time[n+i0],fx+sq);
        ObjectMove("arL"+n,0,Time[n+i0+1],fx1-sq); 
        ObjectMove("arL"+n,1,Time[n+i0],fx-sq);
        
        if (fx>fx1) {
          ObjectSet("ar"+n,OBJPROP_COLOR,_RegressionColor1); 
          ObjectSet("arH"+n,OBJPROP_COLOR,_RegressionColor1); 
          ObjectSet("arL"+n,OBJPROP_COLOR,_RegressionColor1);
        }
        if (fx<fx1) {
          ObjectSet("ar"+n,OBJPROP_COLOR,_RegressionColor2); 
          ObjectSet("arH"+n,OBJPROP_COLOR,_RegressionColor2); 
          ObjectSet("arL"+n,OBJPROP_COLOR,_RegressionColor2);
        }  
      }
        
      if (n<0)
      {
        if ((n+i0)>=0) 
        {
          ObjectMove("ar"+n,0,Time[n+i0+1],fx1); 
          ObjectMove("ar"+n,1,Time[n+i0],fx);
          ObjectMove("arH"+n,0,Time[n+i0+1],fx1+sq); 
          ObjectMove("arH"+n,1,Time[n+i0],fx+sq);
          ObjectMove("arL"+n,0,Time[n+i0+1],fx1-sq); 
          ObjectMove("arL"+n,1,Time[n+i0],fx-sq);
        }
        if ((n+i0)<0) 
        {
          te=Time[0]-(n+i0)*kt; 
          te1=Time[0]-(n+i0+1)*kt;
          ObjectMove("ar"+n,0,te1,fx1); 
          ObjectMove("ar"+n,1,te,fx);
          ObjectMove("arH"+n,0,te1,fx1+sq); 
          ObjectMove("arH"+n,1,te,fx+sq);
          ObjectMove("arL"+n,0,te1,fx1-sq); 
          ObjectMove("arL"+n,1,te,fx-sq);
        } 
        
        if (fx>fx1) {
          ObjectSet("ar"+n,OBJPROP_COLOR,_RegressionColor3); 
          ObjectSet("arH"+n,OBJPROP_COLOR,_RegressionColor3); 
          ObjectSet("arL"+n,OBJPROP_COLOR,_RegressionColor3);
        }
        if (fx<fx1) {
          ObjectSet("ar"+n,OBJPROP_COLOR,_RegressionColor4); 
          ObjectSet("arH"+n,OBJPROP_COLOR,_RegressionColor4); 
          ObjectSet("arL"+n,OBJPROP_COLOR,_RegressionColor4);
        }
      }
    }
//=================================================================
_N_Time = Time[0];
_Cur_Period = Period();
}//main if()
return(0);
}//end of program
//+------------------------------------------------------------------+

void af_Gauss(int n, double& a[][],double& b[], double& x[]) {
  int i,j,k,l;
  double q,m,t;

  for(k=1; k<=n-1; k++) 
  {
    l=0; 
    m=0; 
    for(i=k; i<=n; i++) 
    {
      if (MathAbs(a[i,k])>m) {m=MathAbs(a[i,k]); l=i;}
    } 
    if (l==0) return(0);   

    if (l!=k) 
    {
      for(j=1; j<=n; j++) 
      {
        t=a[k,j]; 
        a[k,j]=a[l,j]; 
        a[l,j]=t;
      } 
      t=b[k]; 
      b[k]=b[l]; 
      b[l]=t;
    }  

    for(i=k+1;i<=n;i++) 
    {
      q=a[i,k]/a[k,k]; 
      for(j=1;j<=n;j++) 
      {
        if (j==k) a[i,j]=0; 
        else 
        a[i,j]=a[i,j]-q*a[k,j];
      } 
      b[i]=b[i]-q*b[k];
    }
  }  
  
  x[n]=b[n]/a[n,n]; 
  
  for(i=n-1;i>=1;i--) 
  {
    t=0; 
    for(j=1;j<=n-i;j++) 
    {
      t=t+a[i,i+j]*x[i+j]; 
      x[i]=(1/a[i,i])*(b[i]-t);
    }
  }
}
//===========================================================================

