SSA implementation

Posted By: SFF

SSA implementation - 02/06/13 23:16

Hi,

I want to use SSA in Zorro so please teach me how to implement it.
My base code is a MQL file which is libSSA.zip
SSA normalized end-pointed & alert advanced.mq4

Here are files to download.
http://worldwide-invest.org/threads/2376-REQ-CCI-alert?p=15394&viewfull=1#post15394

Thanks in advance.
Posted By: jcl

Re: SSA implementation - 02/07/13 12:42

You need to open the SSA function from the DLL, and feed it with the price data that it needs. I've uploaded the DLL file here separately so that other users can reproduce the script whithout the need to register on other forums.

This is the mq4 file where we can see how the DLL function is called:

Code:
//+--------------------------------------------------------------------------------------+
//|                                                                                      |
//+--------------------------------------------------------------------------------------+
#property copyright "www.forex-tsd.com"
#property link      "www.forex-tsd.com"

#property indicator_separate_window
#property indicator_buffers 6
#property indicator_color1  DimGray
#property indicator_color2  DeepSkyBlue
#property indicator_color3  PaleVioletRed
#property indicator_color4  DeepSkyBlue
#property indicator_color5  PaleVioletRed
#property indicator_color6  PaleVioletRed
#property indicator_width2  2
#property indicator_width3  2
#property indicator_width4  2
#property indicator_width5  2
#property indicator_width6  2
#property indicator_style1 STYLE_DOT

#import "libSSA.dll"
   void fastSingular(double& sourceArray[],int arraySize, int lag, int numberOfComputationLoops, double& destinationArray[]);
#import

//
//
//
//
//

extern int    SSAPrice                =  PRICE_CLOSE;
extern int    SSALag                  = 25;
extern int    SSANumberOfComputations =  2;
extern int    SSAPeriodNormalization  = 10;
extern int    SSANumberOfBars         = 300;
extern int    FirstBar                = 400; 
extern bool   MultiColor              = true;
extern double alertsLevel             = 0.25;
extern bool   alertsOn                = false;
extern bool   alertsOnCurrent         = true;
extern bool   alertsMessage           = true;
extern bool   alertsSound             = false;
extern bool   alertsEmail             = false;

//
//
//
//
//

double in[];
double inDa[];
double inDb[];
double inDotu[];
double inDotd[];
double ssaCurrent[];
double no[];
double ssaIn[];
double ssaOut[];

//+--------------------------------------------------------------------------------------+
//|                                                                                      |
//+--------------------------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   IndicatorBuffers(7);
      SetIndexBuffer(0,ssaCurrent);
      SetIndexBuffer(1,inDotu); SetIndexStyle(1,DRAW_ARROW); SetIndexArrow(1,159);
      SetIndexBuffer(2,inDotd); SetIndexStyle(2,DRAW_ARROW); SetIndexArrow(2,159);
      SetIndexBuffer(3,in);
      SetIndexBuffer(4,inDa);
      SetIndexBuffer(5,inDb);
      SetIndexBuffer(6,no);
         SetLevelValue(0, alertsLevel);
         SetLevelValue(1,-alertsLevel);
         SetLevelValue(2,           0);
   IndicatorShortName("SSA normalized end-pointed");
   return(0);
}
int deinit(){return(0);}

//+--------------------------------------------------------------------------------------+
//|                                                                                      |
//+--------------------------------------------------------------------------------------+
//
//
//
//
//

double trend[];
double slope[];

int start()
{
   int i,r,limit,counted_bars = IndicatorCounted();

      if(counted_bars < 0) return(-1);
      if(counted_bars > 0) counted_bars--;
         limit = MathMin(Bars-counted_bars,Bars-1);
         if (ArrayRange(trend,0)!=Bars)
            {
               ArrayResize(trend,Bars);
               ArrayResize(slope,Bars);
            }

   //
   //
   //
   //
   //
      
   if (MultiColor && slope[Bars-limit-1]==-1) CleanPoint(limit,inDa,inDb);
   for(i=limit, r=Bars-i-1; i>=0; i--,r++)
   {
      double ma    = iMA(NULL,0,SSAPeriodNormalization,0,MODE_SMA,SSAPrice,i);
      double dev   = iStdDev(NULL,0,SSAPeriodNormalization,0,MODE_SMA,SSAPrice,i)*3.0;
      double price = iMA(NULL,0,1,0,MODE_SMA,SSAPrice,i);
             no[i] = (price-ma)/(MathMax(dev,0.000001));
            
         //
         //
         //
         //
         //
 
         trend[r] = trend[r-1];
         slope[r] = slope[r-1];
         if (i<=FirstBar)
         {
            int ssaBars = MathMin(Bars-i,SSANumberOfBars);
            if (ssaBars<SSALag) continue;
               if (ArraySize(ssaIn) != ssaBars)
               {
                  ArrayResize(ssaIn ,ssaBars);
                  ArrayResize(ssaOut,ssaBars);
               }
               ArrayCopy(ssaIn,no,0,i,ssaBars);
 
            fastSingular(ssaIn,ssaBars,SSALag,SSANumberOfComputations,ssaOut);
            in[i]     = ssaOut[0];
            inDa[i]   = EMPTY_VALUE;
            inDb[i]   = EMPTY_VALUE;
            inDotu[i] = EMPTY_VALUE;
            inDotd[i] = EMPTY_VALUE;

            //
            //
            //
            //
            //
            
            if (in[i]> alertsLevel)                      trend[r] =  1;
            if (in[i]<-alertsLevel)                      trend[r] = -1;
            if (in[i]>-alertsLevel && in[i]<alertsLevel) trend[r] =  0;
            if (in[i]>in[i+1])                           slope[r] =  1;
            if (in[i]<in[i+1])                           slope[r] = -1;
            if (trend[r] != trend[r-1])
            {
               if (in[i]>0)
                  if (trend[r]==1)
                        inDotu[i] = alertsLevel;
                  else  inDotd[i] = alertsLevel;
               if (in[i]<0)
                  if (trend[r]==-1)
                        inDotd[i] = -alertsLevel;
                  else  inDotu[i] = -alertsLevel;
            }               
            if (MultiColor && slope[r]==-1) PlotPoint(i,inDa,inDb,in);
         }                   
   }

   //
   //
   //
   //
   //
   
   ArrayCopy(ssaCurrent,ssaOut);

   //
   //
   //
   //
   //

   if (alertsOn)
   {
      if (alertsOnCurrent)
           int whichBar = 0;
      else     whichBar = 1; whichBar = Bars-whichBar-1;
      if (trend[whichBar] != trend[whichBar-1])
      {
         if (trend[whichBar]   == 1)                        doAlert("level "+DoubleToStr( alertsLevel,2)+" crossed up");
         if (trend[whichBar]   ==-1)                        doAlert("level "+DoubleToStr(-alertsLevel,2)+" crossed down");
         if (trend[whichBar-1] == 1 && trend[whichBar]!= 1) doAlert("level "+DoubleToStr( alertsLevel,2)+" crossed down");
         if (trend[whichBar-1] ==-1 && trend[whichBar]!=-1) doAlert("level "+DoubleToStr(-alertsLevel,2)+" crossed up");
      }         
   }
   
   //
   //
   //
   //
   //
   
   SetIndexDrawBegin(0,Bars-ssaBars);
   return(0); 
}


//+--------------------------------------------------------------------------------------+
//|                                                                                      |
//+--------------------------------------------------------------------------------------+
//
//
//
//
//

void doAlert(string doWhat)
{
   static string   previousAlert="nothing";
   static datetime previousTime;
   string message;
   
      if (previousAlert != doWhat || previousTime != Time[0]) {
          previousAlert  = doWhat;
          previousTime   = Time[0];

          //
          //
          //
          //
          //

          message =  StringConcatenate(Symbol()," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," normalized end-point SSA ",doWhat);
             if (alertsMessage) Alert(message);
             if (alertsEmail)   SendMail(StringConcatenate(Symbol()," normalized end-point SSA "),message);
             if (alertsSound)   PlaySound("alert2.wav");
      }
}

//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------
//
//
//
//
//

void CleanPoint(int i,double& first[],double& second[])
{
   if ((second[i]  != EMPTY_VALUE) && (second[i+1] != EMPTY_VALUE))
        second[i+1] = EMPTY_VALUE;
   else
      if ((first[i] != EMPTY_VALUE) && (first[i+1] != EMPTY_VALUE) && (first[i+2] == EMPTY_VALUE))
          first[i+1] = EMPTY_VALUE;
}

//
//
//
//
//

void PlotPoint(int i,double& first[],double& second[],double& from[])
{
   if (first[i+1] == EMPTY_VALUE)
      {
         if (first[i+2] == EMPTY_VALUE) {
                first[i]   = from[i];
                first[i+1] = from[i+1];
                second[i]  = EMPTY_VALUE;
            }
         else {
                second[i]   =  from[i];
                second[i+1] =  from[i+1];
                first[i]    = EMPTY_VALUE;
            }
      }
   else
      {
         first[i]  = from[i];
         second[i] = EMPTY_VALUE;
      }
}



I presume that you have the author's permission to use his stuff. We'll have to make a Zorro script from the mq4. It will be far shorter because all the MQL4 Indexbuffers, loops and other workarounds are not required in C. We'll do that step by step in the next days.

Attached File
libSSA.zip  (19 downloads)
Posted By: SFF

Re: SSA implementation - 02/08/13 01:41

So basically do we need to call that DLL in Zorro script?
Posted By: jcl

Re: SSA implementation - 02/08/13 08:19

Yes. For using a function inside a DLL, we define the function prototype and use the API macro:

Code:
void __stdcall fastSingular(double* sourceArray,int arraySize, int lag, int numberOfComputationLoops, double* destinationArray);
API(fastSingular,libSSA)



The libSSA.dll must be copied into the Zorro folder.

Next, we're going to reproduce what the EA does. All the complicated stuff with Indexbuffers, loops, ArrayCopy etc. is only required in MQL4, which does not natively support data series. It's not needed in a C script. The only needed part is the code where the data input to the SSA function is calculated:

Code:
double ma    = iMA(NULL,0,SSAPeriodNormalization,0,MODE_SMA,SSAPrice,i);
      double dev   = iStdDev(NULL,0,SSAPeriodNormalization,0,MODE_SMA,SSAPrice,i)*3.0;
      double price = iMA(NULL,0,1,0,MODE_SMA,SSAPrice,i);
             no[i] = (price-ma)/(MathMax(dev,0.000001));


no[i] is normalized data, calculated similar to Zorro's Fisher transform function from Workshop 5. The same code in lite-C:

Code:
vars close = series(priceClose());
var ma = SMA(close,SSAPeriodNormalization);
var dev = StdDev(close,SSAPeriodNormalization,1)*3.0;
vars no = series((close[0]-ma)/max(dev,0.000001));



You can now plot the normalized data for checking if it looks correct:

Code:
plot("Normalized",no[0],NEW,RED);



This is the input to the fastSingular function from the SSA DLL. Unfortunately I just found that the function does not work - it crashes when called. So, either the DLL has a bug, or more likely, fastSingular must be called with different parameters than I expected. It's sort of nontrivial to figure out the parameters of a function without having either the source code of the DLL or a proper documentation of it. But I'll experiment a little and think that I can find the correct parameters for getting the function not to crash.

Anyway, this is the basic way when you want to call functions from an external DLL in Zorro.
Posted By: SFF

Re: SSA implementation - 02/08/13 09:58

Great, thank you for your help.

Doesn't this code need in Zorro?

double price = iMA(NULL,0,1,0,MODE_SMA,SSAPrice,i);
Posted By: jcl

Re: SSA implementation - 02/08/13 10:41

No, because it's a MA with a 1-bar period, which is identical to the price itself. I have no idea why this line was required in the mq4 file, but programming in MQL4 is often a matter of trial and error. You find many strange things in mq4 EAs.
Posted By: jcl

Re: SSA implementation - 02/08/13 13:37

The reason of the crash was a size requirement for the output array.

Only one element of the fastSingular output array is used and it is unknown what that element really contains, as there is no documentation or source code. So it's up to you what you do with that SSA function. From the original EA above I assume that the output contains the basic trend of the price series. The alerts are triggered by that signal.

Anyway here's the complete code for the SSA implementation:
Code:
#define SSALag			25
#define SSANumberOfComputations	2
#define SSAPeriodNormalization	10
#define SSANumberOfBars 	300

void __stdcall fastSingular(double* sourceArray,int arraySize, int lag, int numberOfComputationLoops, double* destinationArray);
API(fastSingular,libSSA)

// helper function to reverse a series
vars reverse(vars Data)
{
	vars Reversed = series();
	int i;
	for(i=0; i<LookBack; i++)
		Reversed[i] = Data[LookBack-i-1];
	return Reversed;
}


function run()
{
	LookBack = SSANumberOfBars;
	StartDate = 20121001;
	EndDate = 20130101;

	vars close = series(priceClose());
	var ma = SMA(close,SSAPeriodNormalization);
	var dev = StdDev(close,SSAPeriodNormalization,1);
	vars no = series((close[0]-ma)/max(dev,0.000001));
	
	var out[SSANumberOfBars];
	fastSingular(reverse(no),SSANumberOfBars,SSALag,SSANumberOfComputations,out);
	
	plot("Normalized",no[0],NEW,RED);
	plot("SSA",out[0],AXIS2,BLUE);
	set(PLOTPRICE+PLOTNOW);
}



The fastSingular function expects the series in reverse order, that's why we need the additional "reverse" function for reversing a series. The blue line in the chart is the SSA output.
Posted By: SFF

Re: SSA implementation - 02/08/13 23:30

Thank you very much for writing the full code for me.
It will be useful for someone.

By the way I got error in my old Zorro.

'EndDate' undeclared identifier

Is it because of the old version?

Updata:

I just copied and pasted your code above but I got another error.

SSA run..
Undefined function called!
Generate Chart - please wait... ok

Updata 2:
I got the code working by editing the code like below.

var __stdcall

Is it possible to color the line in plot?

The original script is just 1 color line but Zorro version is not.
Could you please make the exact same line?
Also, The line of 0.25 and -0.25 needed.
Posted By: Petra

Re: SSA implementation - 02/09/13 17:07

The color of lines is the last parameter in the plot call, use something different than "BLUE", and a black line at -0.25 goes like this: plot("Line",-0.25,0,BLACK). Hope I could help.
Posted By: SFF

Re: SSA implementation - 02/10/13 00:11

There is 2 color in the one line. How to define it?
Posted By: jcl

Re: SSA implementation - 02/11/13 09:17

Define what?
Posted By: SFF

Re: SSA implementation - 02/11/13 10:28

2 color line of SSA as the original.
Posted By: jcl

Re: SSA implementation - 02/11/13 10:44

A line can have only one color, so for two colors plot two alternating lines. The color is however irrelevant for trading.
Posted By: SFF

Re: SSA implementation - 02/21/13 09:53

Another SSA version converted.
Please check if it is identical to the original code.

The Zorro code.
Code:
#define SSALag			25
#define SSANumberOfComputations	2
#define SSANumberOfBars 	300

var __stdcall fastSingular(double* sourceArray,int arraySize, int lag,int numberOfComputationLoops, double* destinationArray);
API(fastSingular,libSSA)

// helper function to reverse a series
vars reverse(vars Data)
{
	vars Reversed = series();
	int i;
	for(i=0; i<LookBack; i++)
		Reversed[i] = Data[LookBack-i-1];
	return Reversed;
}


function run()
{
	LookBack = SSANumberOfBars;
	BarPeriod = 15;
LookBack = 500;
StartDate = 20121031;
NumDays = 1;
	

	vars close = series(priceClose());

	
	var out[SSANumberOfBars];
	fastSingular(reverse(close),SSANumberOfBars,SSANumberOfComputations,SSALag,out);
	
	plot("Normalized",close[0],0,RED);
	set(PLOTPRICE+PLOTNOW);
}



The original code.
Code:
//+--------------------------------------------------------------------------------------+
//|                                                                                      |
//+--------------------------------------------------------------------------------------+
#property copyright "www.forex-tsd.com"
#property link      "www.forex-tsd.com"

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 PaleVioletRed
#property indicator_width1 2

#import "libSSA.dll"
   void fastSingular(double& sourceArray[],int arraySize, int lag, int numberOfComputationLoops, double& destinationArray[]);
#import

//
//
//
//
//

extern int SSAPrice                =  PRICE_CLOSE;
extern int SSALag                  =  25;
extern int SSANumberOfComputations =   2;
extern int SSANumberOfBars         = 300;
extern int FirstBar                = 300; 

//
//
//
//
//

double in[];
double pr[];
double ssaIn[];
double ssaOut[];

//+--------------------------------------------------------------------------------------+
//|                                                                                      |
//+--------------------------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   IndicatorBuffers(2);
      SetIndexBuffer(0,in);
      SetIndexBuffer(1,pr);
   IndicatorShortName("SSA end-pointed");
   return(0);
}
int deinit(){return(0);}

//+--------------------------------------------------------------------------------------+
//|                                                                                      |
//+--------------------------------------------------------------------------------------+
//
//
//
//
//

int start()
{
   int i,limit,counted_bars = IndicatorCounted();

   if(counted_bars < 0) return(-1);
   if(counted_bars > 0) counted_bars--;
      limit = MathMin(Bars-counted_bars,Bars-1);

   //
   //
   //
   //
   //

   for(i=limit; i>=0; i--)
   {
      pr[i] = iMA(NULL,0,1,0,MODE_SMA,SSAPrice,i);

      //
      //
      //
      //
      //
      
      if (i<=FirstBar)
      {
         int ssaBars = MathMin(Bars-i,SSANumberOfBars);
         if (ssaBars<SSALag) continue;
               if (ArraySize(ssaIn) != ssaBars)
               {
                  ArrayResize(ssaIn ,ssaBars);
                  ArrayResize(ssaOut,ssaBars);
               }
               ArrayCopy(ssaIn,pr,0,i,ssaBars);
      
         fastSingular(ssaIn,ssaBars,SSALag,SSANumberOfComputations,ssaOut);
         in[i]=ssaOut[0];
      }                   
   }                  
   return(0); 
}

Posted By: jcl

Re: SSA implementation - 02/21/13 10:05

The lag is different. But from what I understood, fastSingular needs normalized input data - so how can that code work?
Posted By: SFF

Re: SSA implementation - 02/21/13 10:08

Hi,

It seems same plot that if I have put normalized input data.
I notice that my code just plots a MA of priceClose().

By the way, is it possible to use an up/down arrow in plot?
Posted By: SFF

Re: SSA implementation - 02/22/13 09:49

Could you post a complete correct code for it?
I only plot just MA not SSA line.
Posted By: xeim

Re: SSA implementation - 04/03/19 22:27

Hi guys,

How do I get a source code of libssa.dll?
I want to compile it as 64-bit library.
Posted By: AndrewAMD

Re: SSA implementation - 04/04/19 12:54

Originally Posted By: xeim
Hi guys,

How do I get a source code of libssa.dll?
I want to compile it as 64-bit library.
Step 1: find the author of libssa.dll.
Step 2: Kindly ask the author to supply source.
Step 3: If author refuses, kindly ask the author to recompile in 64-bit.
Step 4: If that fails, you are S.O.L. (Unless you know how decompilers work. cool )
© 2024 lite-C Forums