//+------------------------------------------------------------------+
//|                                                      FullSSA.mq4 |
//|                                           Copyright © 2007, klot |
//|                                                     klot@mail.ru |
//|                                                changes by mladen |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, klot"
#property copyright "mladen"
#property link      ""


#import "libSSA.dll"
   void fastSingular(double& sourceArray[],int arraySize, int lag, int numberOfComputationLoops, double& destinationArray[]);
#import

#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color1 LimeGreen
#property indicator_color2 Orange
#property indicator_color3 DarkSlateGray
#property indicator_color4 LimeGreen
#property indicator_color5 DarkOrange
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 2
#property indicator_width4 2
#property indicator_width5 2
#property indicator_level1 0.0

//----
   extern string TimeFrame   = "Current time frame";
   extern int    Lag         = 25;
   extern int    NumComps    = 2;
   extern  int   PeriodNorm  = 10;
   extern int    N           = 400;
   extern double HighLowStep = 0.005;
   extern int    Price       = PRICE_CLOSE;
   
   double arryTimeSeries[];
   double ssaWork[];
//---- buffers
double SSA[];
double SSAda[];
double SSAdb[];
double max[];
double min[];
double slope[];

int    timeFrame;
string indicatorFileName;
bool   calculateValue;


//------------------------------------------------------------------
//
//------------------------------------------------------------------
int init()
{
   IndicatorBuffers(6);
   SetIndexBuffer(0,max);
   SetIndexBuffer(1,min);
   SetIndexBuffer(2,SSA);
   SetIndexBuffer(3,SSAda); SetIndexStyle(3,DRAW_HISTOGRAM);
   SetIndexBuffer(4,SSAdb); SetIndexStyle(4,DRAW_HISTOGRAM);
   SetIndexBuffer(5,slope);
         indicatorFileName = WindowExpertName();
         calculateValue    = (TimeFrame=="calculateValue"); if (calculateValue) return(0);
         timeFrame         = stringToTimeFrame(TimeFrame);
   IndicatorShortName(timeFrameToString(timeFrame)+" Corridor FullSSA normalize");
   return(0);
}
int deinit()
{
   ObjectDelete("Sell");
   ObjectDelete("Buy");
   return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
int start()
{

   //
   //
   //
   //
   //
   
   if (calculateValue || timeFrame==Period())
   {
      int n = MathMin(Bars-1,N);   
      ArrayResize(arryTimeSeries,n);
      ArrayResize(ssaWork,n);
      for(int i=n-1; i>=0; i--) 
      {
         double ma=iMA(NULL,0,PeriodNorm,0,MODE_SMA,Price,i);
         double dev=3*iStdDev(NULL,0,PeriodNorm,0,MODE_SMA,Price,i);
            if(dev==0) dev=0.1;
               arryTimeSeries[i]=(Close[i]-ma)/dev;
      }
   
      fastSingular(arryTimeSeries,n,Lag,NumComps,ssaWork);
         ArrayCopy(SSA,ssaWork);
            max[n-1]=SSA[n-1];
            min[n-1]=SSA[n-1];
            for(i=n-2; i>=0; i--)
            {
               max[i] = MathMax(SSA[i],max[i+1]-HighLowStep);
               min[i] = MathMin(SSA[i],min[i+1]+HighLowStep);
               SSAda[i] = EMPTY_VALUE;
               SSAdb[i] = EMPTY_VALUE;
               slope[i] = slope[i+1];
                  if (SSA[i]>SSA[i+1]) slope[i] =  1;
                  if (SSA[i]<SSA[i+1]) slope[i] = -1;
         	      if (slope[i] == 1)   SSAda[i] = SSA[i]; 
         	      if (slope[i] ==-1)   SSAdb[i] = SSA[i]; 
            }   
      
            int nmax=ArrayMaximum(SSA,3,1);
            int nmin=ArrayMinimum(SSA,3,1);
            if(nmax==2) { ObjectDelete("Sell"); ObjectCreate("Sell",OBJ_ARROW,0,Time[0],Open[0]); ObjectSet("Sell",OBJPROP_ARROWCODE,226); }
            if(nmin==2) { ObjectDelete("Buy");  ObjectCreate("Buy",OBJ_ARROW,0,Time[0],Open[0]);  ObjectSet("Buy",OBJPROP_ARROWCODE,225);  }
            
            SetIndexDrawBegin(0,Bars-n);
            SetIndexDrawBegin(1,Bars-n);
            SetIndexDrawBegin(2,Bars-n);
            SetIndexDrawBegin(3,Bars-n);
            SetIndexDrawBegin(4,Bars-n);
            return(0);
   }
   
   //
   //
   //
   //
   //
   
   int limit = MathMin(N*timeFrame/Period(),Bars-1);
   for(i=limit; i>=0; i--) 
   {
      int y = iBarShift(NULL,timeFrame,Time[i]);
         SSA[i]   = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",Lag,NumComps,PeriodNorm,N,HighLowStep,2,y);
         SSAda[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",Lag,NumComps,PeriodNorm,N,HighLowStep,3,y);
         SSAdb[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",Lag,NumComps,PeriodNorm,N,HighLowStep,4,y);
         max[i]   = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",Lag,NumComps,PeriodNorm,N,HighLowStep,0,y);
         min[i]   = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",Lag,NumComps,PeriodNorm,N,HighLowStep,1,y);
         slope[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",Lag,NumComps,PeriodNorm,N,HighLowStep,5,y);
     	      
   }
   SetIndexDrawBegin(0,Bars-limit);
   SetIndexDrawBegin(1,Bars-limit);
   SetIndexDrawBegin(2,Bars-limit);
   SetIndexDrawBegin(3,Bars-limit);
   SetIndexDrawBegin(4,Bars-limit);
   return(0);
}

//-------------------------------------------------------------------
//
//-------------------------------------------------------------------
//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

//
//
//
//
//

int stringToTimeFrame(string tfs)
{
   tfs = stringUpperCase(tfs);
   for (int i=ArraySize(iTfTable)-1; i>=0; i--)
         if (tfs==sTfTable[i] || tfs==""+iTfTable[i]) return(MathMax(iTfTable[i],Period()));
                                                      return(Period());
}
string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}

//
//
//
//
//

string stringUpperCase(string str)
{
   string   s = str;

   for (int length=StringLen(str)-1; length>=0; length--)
   {
      int tchar = StringGetChar(s, length);
         if((tchar > 96 && tchar < 123) || (tchar > 223 && tchar < 256))
                     s = StringSetChar(s, length, tchar - 32);
         else if(tchar > -33 && tchar < 0)
                     s = StringSetChar(s, length, tchar + 224);
   }
   return(s);
}

