SWIG typemap for ta-lib

B

BENI

I was trying to swig a function in ta-lib (TA-Lib provides common
functions for the technical analysis of financial market data)
http://ta-lib.org/index.html

the c functuon api

TA_RetCode TA_MA( int startIdx,
int endIdx,
const double inReal[],
int optInTimePeriod,
int optInMAType,
int *outBegIdx,
int *outNbElement,
double outReal[],
)

===========

the c call
==========

TA_Real closePrice[400];
TA_Real out[400];
TA_Integer outBeg;
TA_Integer outNbElement;

/* ... initialize your closing price here... */

retCode = TA_MA( 0, 399,
&closePrice[0],
30,TA_MAType_SMA,
&outBeg, &outNbElement, &out[0] );

/* The output is displayed here */
for( i=0; i < outNbElement; i++ )
printf( "Day %d = %f\n", outBeg+i, out );

================



the query''''''

what should be the typemap

for argument

1>const double inReal[],
2>int *outBegIdx,
3>int *outNbElement,
4>double outReal[],



=============

regards
 
B

barabba

I was trying to swig a function in ta-lib (TA-Lib provides common
functions for the technical analysis of financial market data)http://ta-lib.org/index.html

the c functuon api

TA_RetCode TA_MA( int startIdx,
int endIdx,
const double inReal[],
int optInTimePeriod,
int optInMAType,
int *outBegIdx,
int *outNbElement,
double outReal[],
)

===========

the c call
==========

TA_Real closePrice[400];
TA_Real out[400];
TA_Integer outBeg;
TA_Integer outNbElement;

/* ... initialize your closing price here... */

retCode = TA_MA( 0, 399,
&closePrice[0],
30,TA_MAType_SMA,
&outBeg, &outNbElement, &out[0] );

/* The output is displayed here */
for( i=0; i < outNbElement; i++ )
printf( "Day %d = %f\n", outBeg+i, out );

================

the query''''''

what should be the typemap

for argument

1>const double inReal[],
2>int *outBegIdx,
3>int *outNbElement,
4>double outReal[],

=============

regards


in ruby use it as
closePrice = Array.new(<your data>)
data_inp = closePrice[0..399]
data_arr = ModuleExp::TA_MA( data_inp, 30, ModuleExp::TA_MAType_SMA)

In .i file you should define
%typemap(in)(int startIdx,
int endIdx,
const double inReal[]
)
{

Check_Type($input, T_ARRAY);

/* Get the length of the array */
int size = RARRAY($input)->len;
int i;
$3 = (unsigned char*) malloc(size * sizeof(double));
$2 = size;
$1 = 0;

// copy the ruby array in the new allocated buffer
/* Get the first element in memory */
VALUE *ptr = RARRAY($input)->ptr;
for (i=0; i < size; i++, ptr++)
{
/* Convert Ruby Object Fixnum to unsigned char */
$1= (double)?????(*ptr); // here i don't remember the macro
to convert something like FIX2INT for float
}
}

%typemap(in)(int optInMAType,
int *outBegIdx,
int *outNbElement,
double outReal[]
)
{
int out_beg_ix = 0;
int out_n_ele = 0;
double arr_res[400];

$1 = NUM2INT(optInMAType);
$2 = &out_beg_ix;
$3 = &out_n_ele;
&4 = arr_res;

}

%typemap(freearg) (int startIdx,
int endIdx,
const double inReal[],
int optInTimePeriod,
int optInMAType,
int *outBegIdx,
int *outNbElement,
double outReal[]) {
free((double *) $1);
}

%typemap(out)TA_RetCode TA_MA( int startIdx,
int endIdx,
const double inReal[],
int optInTimePeriod,
int optInMAType,
int *outBegIdx,
int *outNbElement,
double outReal[]
{

int iStartIx = *arg6;
int iLen = iStartIx + *arg7;

VALUE arr = rb_ary_new2(iLen);

for ( int i = iStartIx; i < iLen; i++ )
rb_ary_push(arr, INT2FIX((*arg8)));
$result = arr;
}


it is not tested but this give you the idea how to make the i file.

Regards
 
B

BENI

Thanks for your lead.
It is lot clear now ... how to go about it.
Still I am fuzzy on a couple of things.
Could you pl guide....

in ruby use it as
closePrice = Array.new(<your data>)
data_inp = closePrice[0..399]
data_arr = ModuleExp::TA_MA( data_inp, 30, ModuleExp::TA_MAType_SMA)


So are you suggesting that i need not pass startIdx,endIdx in the
input. But these values I understand is required .. this is to
sometimes specify a range on which to run the function .
What I am confused about is ...ModuleExp::TA_MAType_SMA... is this a
constant that you are suggesting to pass along?


In .i file you should define
%typemap(in)(int startIdx,
int endIdx,
const double inReal[]
)
{

Check_Type($input, T_ARRAY);

/* Get the length of the array */
int size = RARRAY($input)->len;
int i;
$3 = (unsigned char*) malloc(size * sizeof(double));
$2 = size;
$1 = 0;

// copy the ruby array in the new allocated buffer
/* Get the first element in memory */
VALUE *ptr = RARRAY($input)->ptr;
for (i=0; i < size; i++, ptr++)
{
/* Convert Ruby Object Fixnum to unsigned char */
$1= (double)?????(*ptr); // here i don't remember the macro
to convert something like FIX2INT for float
}



here I used $1= NUM2DBL(*ptr);
is that OK?

}

%typemap(in)(int optInMAType,
int *outBegIdx,
int *outNbElement,
double outReal[]
)
{
int out_beg_ix = 0;
int out_n_ele = 0;
double arr_res[400];


Here I need to dimensionise the arr_res to the size of the input
array instead of 400. So i need to get the size variable in the
previous typemap declaration. But how can i use the size variable
here... it was a local variable only.


$1 = NUM2INT(optInMAType);
$2 = &out_beg_ix;
$3 = &out_n_ele;
&4 = arr_res;

}

%typemap(freearg) (int startIdx,
int endIdx,
const double inReal[],
int optInTimePeriod,
int optInMAType,
int *outBegIdx,
int *outNbElement,
double outReal[]) {
free((double *) $1);
}

%typemap(out)TA_RetCode TA_MA( int startIdx,
int endIdx,
const double inReal[],
int optInTimePeriod,
int optInMAType,
int *outBegIdx,
int *outNbElement,
double outReal[])


I did not get this one clearly.... TA_Retcode is the output type.
Can't i get it in ruby?Only thing that i am getting back here is the
outReal[] array i think.
{

int iStartIx = *arg6;
int iLen = iStartIx + *arg7;

VALUE arr = rb_ary_new2(iLen);

for ( int i = iStartIx; i < iLen; i++ )
rb_ary_push(arr, INT2FIX((*arg8)));
$result = arr;




the *arg8 contains floating point number so will INT2FIX work?

}


it is not tested but this give you the idea how to make the i file.

Regards


Thanks again ..

Regards
 
B

barabba

Thanks for your lead.
It is lot clear now ... how to go about it.
Still I am fuzzy on a couple of things.
Could you pl guide....


in ruby use it as
closePrice = Array.new(<your data>)
data_inp = closePrice[0..399]
data_arr = ModuleExp::TA_MA( data_inp, 30, ModuleExp::TA_MAType_SMA)

So are you suggesting that i need not pass startIdx,endIdx in the
input. But these values I understand is required .. this is to
sometimes specify a range on which to run the function .
What I am confused about is ...ModuleExp::TA_MAType_SMA... is this a
constant that you are suggesting to pass along?




In .i file you should define
%typemap(in)(int startIdx,
int endIdx,
const double inReal[]
)
{
Check_Type($input, T_ARRAY);
/* Get the length of the array */
int size = RARRAY($input)->len;
int i;
$3 = (unsigned char*) malloc(size * sizeof(double));
$2 = size;
$1 = 0;
// copy the ruby array in the new allocated buffer
/* Get the first element in memory */
VALUE *ptr = RARRAY($input)->ptr;
for (i=0; i < size; i++, ptr++)
{
/* Convert Ruby Object Fixnum to unsigned char */
$1= (double)?????(*ptr); // here i don't remember the macro
to convert something like FIX2INT for float
}


here I used $1= NUM2DBL(*ptr);
is that OK?
%typemap(in)(int optInMAType,
int *outBegIdx,
int *outNbElement,
double outReal[]
)
{
int out_beg_ix = 0;
int out_n_ele = 0;
double arr_res[400];

Here I need to dimensionise the arr_res to the size of the input
array instead of 400. So i need to get the size variable in the
previous typemap declaration. But how can i use the size variable
here... it was a local variable only.




$1 = NUM2INT(optInMAType);
$2 = &out_beg_ix;
$3 = &out_n_ele;
&4 = arr_res;

%typemap(freearg) (int startIdx,
int endIdx,
const double inReal[],
int optInTimePeriod,
int optInMAType,
int *outBegIdx,
int *outNbElement,
double outReal[]) {
free((double *) $1);
}
%typemap(out)TA_RetCode TA_MA( int startIdx,
int endIdx,
const double inReal[],
int optInTimePeriod,
int optInMAType,
int *outBegIdx,
int *outNbElement,
double outReal[])

I did not get this one clearly.... TA_Retcode is the output type.
Can't i get it in ruby?Only thing that i am getting back here is the
outReal[] array i think.
int iStartIx = *arg6;
int iLen = iStartIx + *arg7;
VALUE arr = rb_ary_new2(iLen);
for ( int i = iStartIx; i < iLen; i++ )
rb_ary_push(arr, INT2FIX((*arg8)));
$result = arr;


the *arg8 contains floating point number so will INT2FIX work?
it is not tested but this give you the idea how to make the i file.

Thanks again ..

Regards


Sorry for some errors.
Your questions.
If you use TA_MAType_SMA in the C function and you want to use it
also in ruby, you have to export it.
In Ruby I like to use all input parameters as function parameters.
Out parameters on the left side as result. If you are also interested
an TA_Retcode you have to change the typemap(out). Afterwards you can
use in ruby this:
ta_res, data_arr_out = ModuleExp::TA_MA( data_inp, 30,
ModuleExp::TA_MAType_SMA)

in .i file:
%typemap(out)TA_RetCode TA_MA( int startIdx,
int endIdx,
const double inReal[],
int optInTimePeriod,
int optInMAType,
int *outBegIdx,
int *outNbElement,
double outReal[]
{

int iStartIx = *arg6;
int iLen = iStartIx + *arg7;
VALUE arr_results = rb_ary_new2(2) // 2 elements as result
rb_ary_push(arr_results, INT2FIX(result)); // first is
TA_Retcode

VALUE arr_data = rb_ary_new2(iLen); // data array

for ( int i = iStartIx; i < iLen; i++ )
rb_ary_push(arr_data, rb_float_new((*arg8)));

rb_ary_push(arr_results, arr_data); // second array of data

$result = arr_results

}

here you are right, INT2FIX doesn't work but rb_float_new should be.
NUM2DBL for inputs should be also ok.

If you need to pass startIdx,endIdx as input, you have to modify the
typemap(in)

%typemap(in)(const double inReal[])
{

Check_Type($input, T_ARRAY);

/* Get the length of the array */
int size = RARRAY($input)->len;
int i;
$1 = (unsigned char*) malloc(size * sizeof(double));

// copy the ruby array in the new allocated buffer
/* Get the first element in memory */
VALUE *ptr = RARRAY($input)->ptr;
for (i=0; i < size; i++, ptr++)
{
/* Convert Ruby Object Fixnum to unsigned char */
$1= (double)NUM2DBL(*ptr);
}
}

If you don't like a maxsize for output array, like double
arr_res[MAX_OUT_DATA];
you can use:
arg8 = (unsigned char*) malloc(size * sizeof(double));
inside %typemap(in)(const double inReal[])
I don't know if it is exact, but you can look inside the generated
code if all is set like you want (I use swig with c++ and I expect a
function called _wrap_TA_MA inside generated code).
Don't forget to free arg8 in the typemap.

Cheers
Igor
 
B

BENI

I got most of your points.

I am still confused with TA_RetCode

I am being bugged by the compiler

C:\talib\ta-lib\swig\ide\msvc\talibruby\rubytalibdll
\rubytalib_wrap.c(1623) : error C2065: 'TA_RetCode' : undeclared
identifier


How do I make SWIG aware of my TA_Retcode type?

am I making some mistake pertaining to header inclusion in .i file ?


a snap of my wrap fn

===========================================
==========================================
SWIGINTERN VALUE
_wrap_TA_MA(int argc, VALUE *argv, VALUE self) {
int arg1 ;
int arg2 ;
double *arg3 ;
int arg4 ;
int arg5 ;
int *arg6 = (int *) 0 ;
int *arg7 = (int *) 0 ;
double *arg8 ;
TA_RetCode result; /* I did not get it here */
int val4 ;
int ecode4 = 0 ;
VALUE vresult = Qnil;

if ((argc < 3) || (argc > 3)) {
rb_raise(rb_eArgError, "wrong # of arguments(%d for 3)",argc);
SWIG_fail;
}
{
Check_Type(argv[0], T_ARRAY);

/* Get the length of the array */
int size = RARRAY(argv[0])->len;
int i;
arg3 = (unsigned char*) malloc(size * sizeof(double));
arg2 = size;
arg1 = 0;

// copy the ruby array in the new allocated buffer
/* Get the first element in memory */
VALUE *ptr = RARRAY(argv[0])->ptr;
for (i=0; i < size; i++, ptr++)
{
/* Convert Ruby Object Fixnum to unsigned char */
arg1= NUM2DBL(*ptr);
}

}
ecode4 = SWIG_AsVal_int(argv[1], &val4);
if (!SWIG_IsOK(ecode4)) {
SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "TA_MA"
"', argument " "4"" of type '" "int""'");
}
arg4 = (int)(val4);
{
int out_beg_ix = 0;
int out_n_ele = 0;
double arr_res[400];

arg5 = NUM2INT(optInMAType);
arg6 = &out_beg_ix;
arg7 = &out_n_ele;
arg8 = arr_res;

}
result = TA_MA(arg1,arg2,(double const
(*))arg3,arg4,arg5,arg6,arg7,arg8);
{
int iStartIx = *arg6;
int iLen = iStartIx + *arg7;

VALUE arr = rb_ary_new2(iLen);

for ( int i = iStartIx; i < iLen; i++ )
rb_ary_push(arr, INT2FIX((*arg8)));
vresult = arr;

}
return vresult;
fail:
return Qnil;
}

Thanks

Regards
 
B

barabba

I got most of your points.

I am still confused with TA_RetCode

I am being bugged by the compiler

C:\talib\ta-lib\swig\ide\msvc\talibruby\rubytalibdll
\rubytalib_wrap.c(1623) : error C2065: 'TA_RetCode' : undeclared
identifier

How do I make SWIG aware of my TA_Retcode type?

am I making some mistake pertaining to header inclusion in .i file ?

a snap of my wrap fn

===========================================
==========================================
SWIGINTERN VALUE
_wrap_TA_MA(int argc, VALUE *argv, VALUE self) {
int arg1 ;
int arg2 ;
double *arg3 ;
int arg4 ;
int arg5 ;
int *arg6 = (int *) 0 ;
int *arg7 = (int *) 0 ;
double *arg8 ;
TA_RetCode result; /* I did not get it here */
int val4 ;
int ecode4 = 0 ;
VALUE vresult = Qnil;

if ((argc < 3) || (argc > 3)) {
rb_raise(rb_eArgError, "wrong # of arguments(%d for 3)",argc);
SWIG_fail;
}
{
Check_Type(argv[0], T_ARRAY);

/* Get the length of the array */
int size = RARRAY(argv[0])->len;
int i;
arg3 = (unsigned char*) malloc(size * sizeof(double));
arg2 = size;
arg1 = 0;

// copy the ruby array in the new allocated buffer
/* Get the first element in memory */
VALUE *ptr = RARRAY(argv[0])->ptr;
for (i=0; i < size; i++, ptr++)
{
/* Convert Ruby Object Fixnum to unsigned char */
arg1= NUM2DBL(*ptr);
}

}
ecode4 = SWIG_AsVal_int(argv[1], &val4);
if (!SWIG_IsOK(ecode4)) {
SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "TA_MA"
"', argument " "4"" of type '" "int""'");
}
arg4 = (int)(val4);
{
int out_beg_ix = 0;
int out_n_ele = 0;
double arr_res[400];

arg5 = NUM2INT(optInMAType);
arg6 = &out_beg_ix;
arg7 = &out_n_ele;
arg8 = arr_res;

}
result = TA_MA(arg1,arg2,(double const
(*))arg3,arg4,arg5,arg6,arg7,arg8);
{
int iStartIx = *arg6;
int iLen = iStartIx + *arg7;

VALUE arr = rb_ary_new2(iLen);

for ( int i = iStartIx; i < iLen; i++ )
rb_ary_push(arr, INT2FIX((*arg8)));
vresult = arr;

}
return vresult;
fail:
return Qnil;

}

Thanks

Regards


for TA_RetCode you have to declare in .i file the header file where
TA_RetCode is defined. After %module declaration in .i you can use
%{

#include "xxxxxTA_RetCodeincludefile.h"
This to avoid compiler error in your wrap function.

To export TA_RetCode to ruby you can use, at the end of .i file, this
declaration:
%include "xxxxxTA_RetCodeincludefile.h"
 
B

BENI

Thanks a lot for your help.

I have been able to port all the functions .

For the group info..... i have built the dll .

i am writing the test cases now....

Testing will be a long affair i feel...

btw :::: if any one is interested in using it pl send me mail... i
will attach the dll

#########################################################################
just a sample of a couple of functions
#########################################################################


C:\talib\ta-lib\swig\ide\msvc\talibruby\rubytalibdll\Debug>ruby
rubytalibtest.rb

TOTAL DATA POINTS FOR TEST: 252
################################################################################

Start of Rubytalib test.... Rubytalib version:0.3.0 (Mar 20 2007
07:33:13)
################################################################################

TA_MAX OUTPUT Maximum price ======>137.88
TA_MAXINDEX OUTPUT Max Index =======>131
TA_SUM of the lot ==========>27133.035
TA_MIDPOINTof the lot ==========>109.6275
TA_MA of the lot(Simple over 200 days) ==========>[108.900525,
108.882808333333,
108.864073922056, 108.686321942732, 108.539592371163,
108.393626277918, 108.265
331489083, 108.11343764342, 107.982358661893, 107.885519272223,
107.774718085435
, 107.64571591543, 107.513619239655, 107.354876759658,
107.184678980955, 107.052
891130398, 106.919230522136, 106.82053171097, 106.702914480015,
106.595124286184
, 106.470396681347, 106.352482286507, 106.227084452811,
106.145222915967, 106.12
328039939, 106.140660693924, 106.139858099954, 106.123541103935,
106.11236159046
3, 106.093233614438, 106.063052185439, 106.036753158718,
106.029123774054, 106.0
87241945457, 106.18587635396, 106.289698479791, 106.409004962579,
106.4782685947
92, 106.50336044957, 106.535167808281, 106.56218106392,
106.566537471244, 106.59
2641576008, 106.626545639928, 106.652152150974, 106.68665809972,
106.69972617833
, 106.718833380536, 106.748994242421, 106.779452011153,
106.801547016017, 106.82
0934607898, 106.831373069511]
TA_MA of the lot(Exponential over 200 days)
==========>[117.055064179104, 117.03
7347512438, 117.017659701493, 116.838161691542, 116.688085323383,
116.5373699004
97, 116.402868905473, 116.243448756219, 116.103308706468,
115.995995024876, 115.
87336119403, 115.731210945274, 115.58474800995, 115.410468159204,
115.2234987562
19, 115.073227114428, 114.919625124378, 114.799614925373,
114.659313930348, 114.
527388308458, 114.377241542289, 114.232458706468, 114.078708457711,
113.96694203
9801, 113.91362238806, 113.898365422886, 113.863886069652,
113.812656218905, 113
..765403482587, 113.709307462687, 113.641081343284, 113.575600995025,
113.5276246
26866, 113.544417164179, 113.601007960199, 113.662423134328,
113.738955223881, 1
13.765069154229, 113.746379353234, 113.733454477612, 113.714782835821,
113.67246
0696517, 113.650754228856, 113.635928855721, 113.612107960199,
113.596458208955,
113.558767412935, 113.526387562189, 113.504396766169,
113.481970646766, 113.450
549004975, 113.415719402985, 113.371152487562]

#################################################################################

Regards.

Rajib
 
B

barabba

Thanks a lot for your help.

I have been able to port all the functions .

For the group info..... i have built the dll .

i am writing the test cases now....

Testing will be a long affair i feel...

btw :::: if any one is interested in using it pl send me mail... i
will attach the dll

#########################################################################
just a sample of a couple of functions
#########################################################################

C:\talib\ta-lib\swig\ide\msvc\talibruby\rubytalibdll\Debug>ruby
rubytalibtest.rb

TOTAL DATA POINTS FOR TEST: 252
################################################################################

Start of Rubytalib test.... Rubytalib version:0.3.0 (Mar 20 2007
07:33:13)
################################################################################

TA_MAX OUTPUT Maximum price ======>137.88
TA_MAXINDEX OUTPUT Max Index =======>131
TA_SUM of the lot ==========>27133.035
TA_MIDPOINTof the lot ==========>109.6275
TA_MA of the lot(Simple over 200 days) ==========>[108.900525,
108.882808333333,
108.864073922056, 108.686321942732, 108.539592371163,
108.393626277918, 108.265
331489083, 108.11343764342, 107.982358661893, 107.885519272223,
107.774718085435
, 107.64571591543, 107.513619239655, 107.354876759658,
107.184678980955, 107.052
891130398, 106.919230522136, 106.82053171097, 106.702914480015,
106.595124286184
, 106.470396681347, 106.352482286507, 106.227084452811,
106.145222915967, 106.12
328039939, 106.140660693924, 106.139858099954, 106.123541103935,
106.11236159046
3, 106.093233614438, 106.063052185439, 106.036753158718,
106.029123774054, 106.0
87241945457, 106.18587635396, 106.289698479791, 106.409004962579,
106.4782685947
92, 106.50336044957, 106.535167808281, 106.56218106392,
106.566537471244, 106.59
2641576008, 106.626545639928, 106.652152150974, 106.68665809972,
106.69972617833
, 106.718833380536, 106.748994242421, 106.779452011153,
106.801547016017, 106.82
0934607898, 106.831373069511]
TA_MA of the lot(Exponential over 200 days)
==========>[117.055064179104, 117.03
7347512438, 117.017659701493, 116.838161691542, 116.688085323383,
116.5373699004
97, 116.402868905473, 116.243448756219, 116.103308706468,
115.995995024876, 115.
87336119403, 115.731210945274, 115.58474800995, 115.410468159204,
115.2234987562
19, 115.073227114428, 114.919625124378, 114.799614925373,
114.659313930348, 114.
527388308458, 114.377241542289, 114.232458706468, 114.078708457711,
113.96694203
9801, 113.91362238806, 113.898365422886, 113.863886069652,
113.812656218905, 113
.765403482587, 113.709307462687, 113.641081343284, 113.575600995025,
113.5276246
26866, 113.544417164179, 113.601007960199, 113.662423134328,
113.738955223881, 1
13.765069154229, 113.746379353234, 113.733454477612, 113.714782835821,
113.67246
0696517, 113.650754228856, 113.635928855721, 113.612107960199,
113.596458208955,
113.558767412935, 113.526387562189, 113.504396766169,
113.481970646766, 113.450
549004975, 113.415719402985, 113.371152487562]

#################################################################################

Regards.

Rajib

Great!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,052
Latest member
LucyCarper

Latest Threads

Top