ADK, Matrix support


#1

hi, will ADK also support matrix functions in the near future? Thanks


#2

You can work with matrices already. If some function returns matrix you can just pass it to another function that requires matrix the same way as you do with any other type. It is all handled by existing AmiVar. What you can’t do right now is manual manipulation of individual matrix elements inside plugin.


#3

ok thanks. I was actually wanting to use it in such a way that a function can return multiple arrays.

for instance I have a function that calculates peaks and troughs but at the same time (within the same loop) also 4 other arrays are calculated. What I do now is save all arrays in 6 static variable arrays and then define a separate function to get these arrays.

I though maybe I could fill up the matrix with these 6 arrays and get them all at once. But I think I will need to be able to access matrix elements for this.

But no big issue. My knowledge of C++ is too small to do it in another way although I had a look at the Osaka source code


#4

A simple method to return multiple values from one function is passing the variable NAMES to your function and using VarSet (gSite.SetVariable) as explained in the Knowledge Base
http://www.amibroker.com/kb/2014/09/21/a-function-with-multiple-return-values/

6.25 also allows passing references and easily handle returning multiple values, but this is too new.


#5

thanks,

yes this is what I had been using (gSite.Setvariable) but from later comments I understood that the correct way of working with ADK is that one needs to work with functions that (might) have parameters and return a value or array. Maybe I understood that incorrectly. I thought it also had something to do with multi-threading. In any case using a function and ask it for some return is more transparent.

I forgot about this latest addition in 6.25, will check it out


#6

You mixed things a little bit. The advice from the other thread was not to use complex HIDDEN relationships via variables. If you PASS the variables to the function EXPLICITLY there is no “hidden” relationship. Generally best practice is to return single result from any function. But if for some reasons you need to return more, then you can use the technique presented in KB because it is EXPLICIT about which variables get modified. And no, multithreading has nothing to do with that (normal variables are thread-private)


#7

ok thanks a lot for your help


#8

Tomasz, I wonder what you think about adding some AFL statistical functions to support matrix data type, e.g. sum , average, stand deviation, sorting, percentile ranking, etc that are currently available to single-ticker time series. A possibly related functionality is to extend the “AddToComposite” (which computes the sum and can be used to compute average) function to the above mentioned statistical calculations for cross-sectional analysis, e.g. when build portfolio-level trading strategies.
Thank you in advance for sharing your thoughts on this subject.


#9

In practice all of that is already available.

MxSum is available: http://www.amibroker.com/f?mxsum
Average is just a sum divided by number of elements.
Sorting is available
http://www.amibroker.com/f?mxsort
http://www.amibroker.com/f?mxsortrows

Percentile is just picking n-th element from sorted matrix - i.e. already available (via MxSort/MxSortRows).

Standard deviation is just E(X^2)- (EX)^2 - you calculate average of squares minus squared average, i.e. already available.


#10

@Tomasz
Thank you for clearly & simply describing how to calculate statistics for matrices.

I’ve been trying to work out how to calculate Stdev from 5000 element matrix which I mxgetblock() as array so I could use inbuilt AFL function.
Since I wanted to chart a generated distribution (for heck of it).

Converted to array but -1exx or whatever for >200 bars, then changed preference setting to 1000. Should be plenty good enough but asked myself how?
Above post answered.
FE


#11

Sorry, but I don’t understand this sentence. Rephrase please.


#12

Is it planned to add full matrix support? Any ETA? (I would understand if you don’t want to give any public information right now or ever.)


#13

Technically it is just a matter of providing header file, but matrix functionality is being expanded and exposing it via API means locking it from expansion (ADK spec need to be backward compatible), so it will occur not sooner than when I am sure that we don’t need to change the API quickly.


#14

@Tomasz I was too terse and assumed background. Old problem boss (manager not technical) used to get the red pen out.
I’ve been coding matrix with 5000 gaussian variables from mtrandom using Box-Muller transform algo I copied. Then to verify the data, I tried to use superlative PriceVolDistribution() function to display in mode=3 (x-bars, y-pixels).
Function needs array for H, L, Vol vars.
Trying several approaches reduced the samples size from matrix size to barcount size. Default 200 bars or visible bars. That’s normal, but I wanted to convert matrix[5000] to array[5000] inside the function.
I think I’ve confirmed that doesn’t happen. I used debug and _trace.
So accessing bars outside barcount range returns error, -1e31 or some NAN.
Also tried changing bars in settings(new feature) and turned off quickafl.

Now got matrix RandGauss() code (6 lines, amazing matrix functions) working. Now working to display data with gfx. It’ll be interesting to see if chart is any different.
Hope that’s clearer .
FE


#15

@Tomasz, I am stuggling at how to apply your advice.

For example,
First I am initializing matrix

AmiVar arg1[ 3 ];

arg1[ 0 ].type = VAR_FLOAT;	arg1[ 0 ].val = rownum;
arg1[ 1 ].type = VAR_FLOAT;	arg1[ 1 ].val = colnum;
arg1[ 2 ].type = VAR_FLOAT;	arg1[ 2 ].val = EMPTY_VAL;

AmiVar m = gSite.CallFunction( "Matrix", 3, arg1 );	

Now I am trying to fill that matrix by calling MxSetBlock function
The line I am struggling with is arg2[ 0 ] = m;
I do not think that is a correct line of mine since I am not setting any type.

AmiVar arg2[ 6 ];

arg2[ 0 ] = m;

for(int  i = 0; i < rownum; i++ ) 
{

	for( int j = 0; j < colnum; j++ ) 
	{	
		
		arg2[ 1 ].type = VAR_FLOAT;	arg2[ 1 ].val = i ;
		arg2[ 2 ].type = VAR_FLOAT;	arg2[ 2 ].val = i;
		arg2[ 3 ].type = VAR_FLOAT;	arg2[ 3 ].val = j;
		arg2[ 4 ].type = VAR_FLOAT;	arg2[ 4 ].val = j;
		arg2[ 5 ].type = VAR_FLOAT;	arg2[ 5 ].val = i* j ;

	}

}

m = gSite.CallFunction( "MxSetBlock", 6, arg2 );

Can we call MxSetBlock in DLL already or would we have to wait for ADK update?


#16
  1. You can call any function. ADK is designed to be backward and forward compatible so it does NOT require updates when functions are added
  2. AmiVar is a struct. If assign a struct it copies all fields, so type field is copied too.

Recommended reading "C Programming Language" Kernighan and Richie.


#17

Thank you. I wasn't sure because if compiling and calling the DLL function from AFL editor then the AmiBroker engine reports Error 27 for DLL's MxSetBlock
"Invalid number of arguments passed to Call Function (..) from plugin DLL".

The MxSetBlock AFL function reference of AmiBroker guide documents 6 arguments
https://www.amibroker.com/guide/afl/mxsetblock.html
and in my DLL function there are 6 ones also. Is there anything I am missing?


#18

This should work:

m = gSite.CallFunction( "MxSetBlock", 4, arg2 );

The trick is that matrix argument counts as -1.


#19

Thank you. That change together with few other adjustments did the trick. :slightly_smiling_face: