talib_ruby 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +55 -0
- data/example/ma.rb +21 -0
- data/ext/talib/extconf.rb +6 -0
- data/ext/talib/talib.c +540 -0
- data/lib/talib_ruby.rb +9 -0
- metadata +72 -0
data/README.textile
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
h2. talib-ruby
|
2
|
+
|
3
|
+
Ruby Wrapper for "ta-lib":http://ta-lib.org/
|
4
|
+
|
5
|
+
This project has been started by Timur Adigamov on "Rubyforge":http://rubyforge.org/projects/talib-ruby/,
|
6
|
+
but since it didn't build on my machine and wasn't complete i modified it slightly, et voila.
|
7
|
+
|
8
|
+
h3. Install and build instructions
|
9
|
+
|
10
|
+
Install ta-lib from "MacPorts":http://www.macports.org/ports.php?by=name&substr=ta-lib:
|
11
|
+
|
12
|
+
bc. sudo port install ta-lib
|
13
|
+
|
14
|
+
Install the ruby wrapper talib_ruby:
|
15
|
+
|
16
|
+
bc. sudo env ARCHFLAGS="-arch PLATFORM" gem install talib_ruby -- --with-talib-include=ABSOLUTE_PATH_TO_TALIB_HEADERS --with-talib-lib=ABSOLUTE_PATH_TO_TALIB_LIBS
|
17
|
+
|
18
|
+
* PLATFORM = [i386 | x86_64 | ...]
|
19
|
+
* ABSOLUTE_PATH_TO_TALIB_HEADERS = The path to the ta-lib header files (e.g. /opt/local/var/macports/software/ta-lib/0.4.0_0/opt/local/include/ta-lib)
|
20
|
+
* ABSOLUTE_PATH_TO_TALIB_LIBS = The path to the ta-lib lib files (e.g. /opt/local/var/macports/software/ta-lib/0.4.0_0/opt/local/lib)
|
21
|
+
|
22
|
+
Now ta-lib can be used by using _require 'talib_ruby'_
|
23
|
+
Works on Leopard and Snow Leopard. Has not been tested on Windows.
|
24
|
+
|
25
|
+
h3. Example
|
26
|
+
|
27
|
+
Calculation of Moving Average (MA):
|
28
|
+
|
29
|
+
bc.. require 'rubygems'
|
30
|
+
require 'talib_ruby'
|
31
|
+
|
32
|
+
# init input data
|
33
|
+
a = Array.new
|
34
|
+
10.times { |i| a.push i.to_f }
|
35
|
+
|
36
|
+
10.times do |k|
|
37
|
+
b = Array.new(10)
|
38
|
+
l = TaLib::Function.new("MA")
|
39
|
+
# setup input parameter
|
40
|
+
l.in_real(0,a)
|
41
|
+
# setup optional parameter
|
42
|
+
l.opt_int(0,k+2)
|
43
|
+
# setup output parameter
|
44
|
+
l.out_real(0,b)
|
45
|
+
lookback = l.lookback
|
46
|
+
l.call(0,9)
|
47
|
+
p "k=#{k+2}"
|
48
|
+
p b
|
49
|
+
end
|
50
|
+
|
51
|
+
h3. Useful links
|
52
|
+
|
53
|
+
* "TA-Lib Forum":http://www.tadoc.org/forum/index.php?board=9.0
|
54
|
+
* "XML explanation":http://ta-lib.svn.sourceforge.net/viewvc/ta-lib/trunk/ta-lib/ta_func_api.xml?view=markup of all supported Functions
|
55
|
+
* "C/C++ API Documentation":http://ta-lib.org/d_api/d_api.html
|
data/example/ma.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'talib_ruby'
|
3
|
+
|
4
|
+
# init input data
|
5
|
+
a = Array.new
|
6
|
+
10.times { |i| a.push i.to_f }
|
7
|
+
|
8
|
+
10.times do |k|
|
9
|
+
b = Array.new(10)
|
10
|
+
l = TaLib::Function.new("MA")
|
11
|
+
# setup input parameter
|
12
|
+
l.in_real(0,a);
|
13
|
+
# setup optional parameter
|
14
|
+
l.opt_int(0,k+2)
|
15
|
+
# setup output parameter
|
16
|
+
l.out_real(0,b)
|
17
|
+
lb = l.lookback
|
18
|
+
l.call(0,9)
|
19
|
+
p "k=#{k+2}"
|
20
|
+
p b
|
21
|
+
end
|
data/ext/talib/talib.c
ADDED
@@ -0,0 +1,540 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "ta_abstract.h"
|
3
|
+
|
4
|
+
static VALUE rb_mTaLib;
|
5
|
+
static VALUE rb_cTAFunction;
|
6
|
+
static VALUE rb_sInParamInfo;
|
7
|
+
static VALUE rb_sOptInParamInfo;
|
8
|
+
static VALUE rb_sOutParamInfo;
|
9
|
+
|
10
|
+
#ifndef RUBY_19
|
11
|
+
#ifndef RARRAY_LEN
|
12
|
+
#define RARRAY_LEN(v) (RARRAY(v)->len)
|
13
|
+
#endif
|
14
|
+
#ifndef RARRAY_PTR
|
15
|
+
#define RARRAY_PTR(v) (RARRAY(v)->ptr)
|
16
|
+
#endif
|
17
|
+
#ifndef RSTRING_PTR
|
18
|
+
#define RSTRING_PTR(v) (RSTRING(v)->ptr)
|
19
|
+
#endif
|
20
|
+
#endif
|
21
|
+
|
22
|
+
|
23
|
+
#define TA_INPUT_PARAM 1
|
24
|
+
#define TA_OPTION_INPUT_PARAM 2
|
25
|
+
#define TA_OUTPUT_PARAM 3
|
26
|
+
#define IN_CNT 7 // allow up to 7 arrays of input
|
27
|
+
#define OUT_CNT 3 // allow up to 3 arrays of outputs
|
28
|
+
// combine all heap storage to this struct and free only this on ta_free
|
29
|
+
typedef struct _ph {
|
30
|
+
TA_ParamHolder *p;
|
31
|
+
double* in[IN_CNT]; // johnribera@Hotmail: the usual case (double)
|
32
|
+
double* out[OUT_CNT];
|
33
|
+
} ParamHolder;
|
34
|
+
|
35
|
+
/* :nodoc: */
|
36
|
+
// get TA_FuncInfo by name
|
37
|
+
static const TA_FuncInfo* abstract_layer_get_func_info(VALUE name)
|
38
|
+
{
|
39
|
+
TA_RetCode ret_code;
|
40
|
+
const TA_FuncHandle *handle;
|
41
|
+
const TA_FuncInfo *the_info;
|
42
|
+
|
43
|
+
ret_code = TA_GetFuncHandle( RSTRING_PTR(name), &handle );
|
44
|
+
if ( ret_code == TA_SUCCESS )
|
45
|
+
{
|
46
|
+
ret_code = TA_GetFuncInfo( handle, &the_info );
|
47
|
+
if ( ret_code == TA_SUCCESS )
|
48
|
+
return the_info;
|
49
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_GetFuncInfo");
|
50
|
+
}
|
51
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_GetFuncHandle");
|
52
|
+
}
|
53
|
+
|
54
|
+
// get function parameter info
|
55
|
+
static VALUE ta_func_param_info(int param_type, VALUE self, VALUE name, VALUE index)
|
56
|
+
{
|
57
|
+
TA_RetCode ret_code;
|
58
|
+
const TA_FuncHandle *handle;
|
59
|
+
|
60
|
+
ret_code = TA_GetFuncHandle( StringValuePtr(name), &handle );
|
61
|
+
if ( ret_code == TA_SUCCESS )
|
62
|
+
{
|
63
|
+
switch (param_type)
|
64
|
+
{
|
65
|
+
case TA_INPUT_PARAM:
|
66
|
+
{
|
67
|
+
const TA_InputParameterInfo *param_info;
|
68
|
+
|
69
|
+
ret_code = TA_GetInputParameterInfo( handle, FIX2INT(index), ¶m_info );
|
70
|
+
if (ret_code != TA_SUCCESS)
|
71
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_GetInputParameterInfo");
|
72
|
+
return rb_struct_new(rb_sInParamInfo, INT2FIX(param_info->type), rb_str_new2(param_info->paramName), INT2FIX(param_info->flags),NULL);
|
73
|
+
}
|
74
|
+
break;
|
75
|
+
case TA_OPTION_INPUT_PARAM:
|
76
|
+
{
|
77
|
+
const TA_OptInputParameterInfo *param_info;
|
78
|
+
|
79
|
+
ret_code = TA_GetOptInputParameterInfo( handle, FIX2INT(index), ¶m_info );
|
80
|
+
if (ret_code != TA_SUCCESS)
|
81
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_GetOptInputParameterInfo");
|
82
|
+
// FIXME: helpFile = Qnil
|
83
|
+
// FIXME: dataSet = Qnil
|
84
|
+
return rb_struct_new(rb_sOptInParamInfo, INT2FIX(param_info->type), rb_str_new2(param_info->paramName), INT2FIX(param_info->flags), rb_str_new2(param_info->displayName), Qnil, rb_float_new(param_info->defaultValue), rb_str_new2(param_info->hint), Qnil, NULL);
|
85
|
+
}
|
86
|
+
break;
|
87
|
+
case TA_OUTPUT_PARAM:
|
88
|
+
{
|
89
|
+
const TA_OutputParameterInfo *param_info;
|
90
|
+
|
91
|
+
ret_code = TA_GetOutputParameterInfo( handle, FIX2INT(index), ¶m_info );
|
92
|
+
if (ret_code != TA_SUCCESS)
|
93
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_GetOutputParameterInfo");
|
94
|
+
return rb_struct_new(rb_sOutParamInfo, INT2FIX(param_info->type), rb_str_new2(param_info->paramName), INT2FIX(param_info->flags),NULL);
|
95
|
+
}
|
96
|
+
break;
|
97
|
+
} // switch
|
98
|
+
}
|
99
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_GetFuncHandle");
|
100
|
+
}
|
101
|
+
|
102
|
+
static double* FLT2DBL(double **dest, VALUE in_array)
|
103
|
+
{
|
104
|
+
VALUE *inp;
|
105
|
+
int i;
|
106
|
+
|
107
|
+
if NIL_P(in_array) return 0;
|
108
|
+
|
109
|
+
inp = RARRAY_PTR(in_array);
|
110
|
+
if (*dest) free(*dest); // only on 1st use do we skip this step
|
111
|
+
*dest = calloc(1, sizeof(double) * RARRAY_LEN(in_array));
|
112
|
+
for (i = 0; i < RARRAY_LEN(in_array); i++)
|
113
|
+
(*dest)[i] = NUM2DBL(inp[i]);
|
114
|
+
return *dest;
|
115
|
+
}
|
116
|
+
|
117
|
+
void init_tables()
|
118
|
+
{
|
119
|
+
// temporary variable return code
|
120
|
+
TA_RetCode ret_code;
|
121
|
+
// functions group table
|
122
|
+
TA_StringTable *group_table;
|
123
|
+
// define class variable @@groups - array of function groups
|
124
|
+
// define class variable @@functions - hash of array of functions
|
125
|
+
ret_code = TA_GroupTableAlloc( &group_table );
|
126
|
+
if( ret_code == TA_SUCCESS )
|
127
|
+
{
|
128
|
+
// functions table
|
129
|
+
TA_StringTable *function_table;
|
130
|
+
// ruby array for functions group table
|
131
|
+
VALUE rb_group_table = rb_ary_new();
|
132
|
+
// ruby hash for functions
|
133
|
+
VALUE rb_function_table = rb_hash_new();
|
134
|
+
unsigned i, j;
|
135
|
+
|
136
|
+
for( i=0; i < group_table->size; i++ )
|
137
|
+
{
|
138
|
+
// temporary ruby array for group's function table
|
139
|
+
VALUE rb_temp_func_table = rb_ary_new();
|
140
|
+
|
141
|
+
rb_ary_push(rb_group_table, rb_str_new2(group_table->string[i]));
|
142
|
+
ret_code = TA_FuncTableAlloc( group_table->string[i], &function_table );
|
143
|
+
if( ret_code == TA_SUCCESS )
|
144
|
+
{
|
145
|
+
for ( j=0; j < function_table->size; j++)
|
146
|
+
rb_ary_push(rb_temp_func_table, rb_str_new2(function_table->string[j]));
|
147
|
+
rb_hash_aset(rb_function_table, rb_str_new2(group_table->string[i]), rb_temp_func_table);
|
148
|
+
TA_FuncTableFree ( function_table );
|
149
|
+
}
|
150
|
+
}
|
151
|
+
rb_define_class_variable( rb_cTAFunction, "@@groups", rb_group_table );
|
152
|
+
rb_define_class_variable( rb_cTAFunction, "@@functions", rb_function_table );
|
153
|
+
TA_GroupTableFree( group_table );
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
// free function
|
158
|
+
static void ta_func_free(void *phv)
|
159
|
+
{
|
160
|
+
int i = 0; // this now properly cleans up memory from very last call
|
161
|
+
ParamHolder* ph = (ParamHolder*)phv;
|
162
|
+
for (i = 0; i < IN_CNT; i++) if (ph->in[i]) free(ph->in[i]);
|
163
|
+
for (i = 0; i < OUT_CNT; i++) if (ph->out[i]) free(ph->out[i]);
|
164
|
+
TA_ParamHolderFree( ph->p );
|
165
|
+
free(ph);
|
166
|
+
}
|
167
|
+
|
168
|
+
// allocation function
|
169
|
+
static VALUE ta_func_alloc(VALUE klass)
|
170
|
+
{
|
171
|
+
ParamHolder *param_holder;
|
172
|
+
// call calloc() to ensure we set all values (ptrs to NULL/0)
|
173
|
+
// so if (free(in/out)) returns false only the first time!
|
174
|
+
param_holder = (ParamHolder*)calloc(1, sizeof(struct _ph));
|
175
|
+
return Data_Wrap_Struct(klass, 0, ta_func_free, param_holder);
|
176
|
+
}
|
177
|
+
|
178
|
+
/*
|
179
|
+
* call-seq: initialize(name)
|
180
|
+
*
|
181
|
+
* Create new instance of technical analysis function with given _name_.
|
182
|
+
*
|
183
|
+
*/
|
184
|
+
static VALUE ta_func_initialize(VALUE self, VALUE name)
|
185
|
+
{
|
186
|
+
TA_RetCode ret_code;
|
187
|
+
const TA_FuncHandle *handle;
|
188
|
+
TA_ParamHolder *ta_param_holder;
|
189
|
+
ParamHolder *param_holder;
|
190
|
+
|
191
|
+
Data_Get_Struct(self, ParamHolder, param_holder);
|
192
|
+
|
193
|
+
ret_code = TA_GetFuncHandle( RSTRING_PTR(name), &handle );
|
194
|
+
if ( ret_code == TA_SUCCESS )
|
195
|
+
{
|
196
|
+
ret_code = TA_ParamHolderAlloc( handle, &ta_param_holder );
|
197
|
+
if ( ret_code != TA_SUCCESS )
|
198
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_ParamHolderAlloc");
|
199
|
+
param_holder->p = ta_param_holder;
|
200
|
+
rb_iv_set(self, "@name", name);
|
201
|
+
rb_iv_set(self, "@result", rb_ary_new());
|
202
|
+
return self;
|
203
|
+
}
|
204
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_GetFuncHandle");
|
205
|
+
}
|
206
|
+
|
207
|
+
/*
|
208
|
+
* Return input parameters count.
|
209
|
+
*/
|
210
|
+
static VALUE ta_func_get_input_count(VALUE self)
|
211
|
+
{
|
212
|
+
return INT2NUM((abstract_layer_get_func_info(rb_iv_get(self, "@name")))->nbInput);
|
213
|
+
}
|
214
|
+
|
215
|
+
/*
|
216
|
+
* Return option input parameters count.
|
217
|
+
*/
|
218
|
+
static VALUE ta_func_get_option_input_count(VALUE self)
|
219
|
+
{
|
220
|
+
return INT2NUM((abstract_layer_get_func_info(rb_iv_get(self, "@name")))->nbOptInput);
|
221
|
+
}
|
222
|
+
|
223
|
+
/*
|
224
|
+
* Return output parameters count.
|
225
|
+
*/
|
226
|
+
static VALUE ta_func_get_output_count(VALUE self)
|
227
|
+
{
|
228
|
+
return INT2NUM((abstract_layer_get_func_info(rb_iv_get(self, "@name")))->nbOutput);
|
229
|
+
}
|
230
|
+
|
231
|
+
/*
|
232
|
+
* Return the list of names for technical function groups.
|
233
|
+
*/
|
234
|
+
static VALUE ta_func_get_groups(VALUE self)
|
235
|
+
{
|
236
|
+
return rb_cv_get(self, "@@groups");
|
237
|
+
}
|
238
|
+
|
239
|
+
/*
|
240
|
+
* Return the hash of names for technical functions.
|
241
|
+
* The key is a name of funcion group, and value - is a list of function names.
|
242
|
+
*/
|
243
|
+
static VALUE ta_func_get_functions(VALUE self)
|
244
|
+
{
|
245
|
+
return rb_cv_get(self, "@@functions");
|
246
|
+
}
|
247
|
+
|
248
|
+
/*
|
249
|
+
* call-seq: in(index)
|
250
|
+
*
|
251
|
+
* Return input parameter info for the given input parameter index.
|
252
|
+
*/
|
253
|
+
static VALUE ta_func_input_param_info(VALUE self, VALUE index)
|
254
|
+
{
|
255
|
+
return ta_func_param_info(TA_INPUT_PARAM, self, rb_iv_get(self, "@name"), index);
|
256
|
+
}
|
257
|
+
|
258
|
+
/*
|
259
|
+
* call-seq: opt(index)
|
260
|
+
*
|
261
|
+
* Return option input parameter info for the given option parameter index.
|
262
|
+
*/
|
263
|
+
static VALUE ta_func_option_param_info(VALUE self, VALUE index)
|
264
|
+
{
|
265
|
+
return ta_func_param_info(TA_OPTION_INPUT_PARAM, self, rb_iv_get(self, "@name"), index);
|
266
|
+
}
|
267
|
+
|
268
|
+
/*
|
269
|
+
* call-seq: out(index)
|
270
|
+
*
|
271
|
+
* Return output parameter info for the given output parameter index.
|
272
|
+
*/
|
273
|
+
static VALUE ta_func_output_param_info(VALUE self, VALUE index)
|
274
|
+
{
|
275
|
+
return ta_func_param_info(TA_OUTPUT_PARAM, self, rb_iv_get(self, "@name"), index);
|
276
|
+
}
|
277
|
+
|
278
|
+
/*
|
279
|
+
* call-seq: in_int(index, array)
|
280
|
+
*
|
281
|
+
* Set input parameter (array of integer) for the given parameter index.
|
282
|
+
*/
|
283
|
+
static VALUE ta_func_setup_in_integer(VALUE self, VALUE param_index, VALUE in_array)
|
284
|
+
{
|
285
|
+
TA_RetCode ret_code;
|
286
|
+
ParamHolder *param_holder;
|
287
|
+
|
288
|
+
Data_Get_Struct(self, ParamHolder, param_holder);
|
289
|
+
ret_code = TA_SetInputParamIntegerPtr( param_holder->p, FIX2INT(param_index), (int*)(RARRAY_PTR(in_array)));
|
290
|
+
if ( ret_code != TA_SUCCESS )
|
291
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_SetInputParamIntegerPtr");
|
292
|
+
}
|
293
|
+
|
294
|
+
/*
|
295
|
+
* call-seq: in_real(index, array)
|
296
|
+
*
|
297
|
+
* Set input parameter (array of real) for the given parameter index.
|
298
|
+
*/
|
299
|
+
static VALUE ta_func_setup_in_real(VALUE self, VALUE param_index, VALUE in_array)
|
300
|
+
{
|
301
|
+
TA_RetCode ret_code;
|
302
|
+
ParamHolder *param_holder;
|
303
|
+
|
304
|
+
Data_Get_Struct(self, ParamHolder, param_holder);
|
305
|
+
double** dp = param_holder->in;
|
306
|
+
//FIXME: memory leak fixed: johnribera@hotmail.com (see: FL2DBL())
|
307
|
+
ret_code = TA_SetInputParamRealPtr( param_holder->p, FIX2INT(param_index), FLT2DBL(&dp[FIX2INT(param_index)], in_array));
|
308
|
+
if ( ret_code != TA_SUCCESS )
|
309
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_SetInputParamRealPtr");
|
310
|
+
}
|
311
|
+
|
312
|
+
static VALUE ta_func_setup_in_price(VALUE self, VALUE param_index, VALUE in_open, VALUE in_high, VALUE in_low, VALUE in_close, VALUE in_volume, VALUE in_oi)
|
313
|
+
{
|
314
|
+
TA_RetCode ret_code;
|
315
|
+
ParamHolder *param_holder;
|
316
|
+
Data_Get_Struct(self, ParamHolder, param_holder);
|
317
|
+
double **dp = param_holder->in;
|
318
|
+
|
319
|
+
ret_code = TA_SetInputParamPricePtr(
|
320
|
+
param_holder->p,
|
321
|
+
FIX2INT(param_index),
|
322
|
+
FLT2DBL(&dp[0], in_open),
|
323
|
+
FLT2DBL(&dp[1], in_high),
|
324
|
+
FLT2DBL(&dp[2], in_low),
|
325
|
+
FLT2DBL(&dp[3], in_close),
|
326
|
+
FLT2DBL(&dp[4], in_volume),
|
327
|
+
FLT2DBL(&dp[5], in_oi));
|
328
|
+
if ( ret_code != TA_SUCCESS )
|
329
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_SetInputParamPricePtr");
|
330
|
+
}
|
331
|
+
|
332
|
+
/*
|
333
|
+
* call-seq: opt_int(index, value)
|
334
|
+
*
|
335
|
+
* Set option parameter (integer) for the given parameter index.
|
336
|
+
*/
|
337
|
+
static VALUE ta_func_setup_opt_in_integer(VALUE self, VALUE param_index, VALUE val)
|
338
|
+
{
|
339
|
+
TA_RetCode ret_code;
|
340
|
+
ParamHolder *param_holder;
|
341
|
+
Data_Get_Struct(self, ParamHolder, param_holder);
|
342
|
+
ret_code = TA_SetOptInputParamInteger( param_holder->p, FIX2INT(param_index), FIX2INT(val));
|
343
|
+
if ( ret_code != TA_SUCCESS )
|
344
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_SetOptInputParamIntegerPtr");
|
345
|
+
}
|
346
|
+
|
347
|
+
/*
|
348
|
+
* call-seq: opt_real(index, value)
|
349
|
+
*
|
350
|
+
* Set option parameter (real) for the given parameter index.
|
351
|
+
*/
|
352
|
+
static VALUE ta_func_setup_opt_in_real(VALUE self, VALUE param_index, VALUE val)
|
353
|
+
{
|
354
|
+
TA_RetCode ret_code;
|
355
|
+
ParamHolder *param_holder;
|
356
|
+
|
357
|
+
Data_Get_Struct(self, ParamHolder, param_holder);
|
358
|
+
ret_code = TA_SetOptInputParamReal( param_holder->p, FIX2INT(param_index), NUM2DBL(val));
|
359
|
+
if ( ret_code != TA_SUCCESS )
|
360
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_SetOptInputParamRealPtr");
|
361
|
+
}
|
362
|
+
|
363
|
+
/*
|
364
|
+
* call-seq: out_real(index, array)
|
365
|
+
*
|
366
|
+
* Set output parameter (array of real) for the given parameter index.
|
367
|
+
*/
|
368
|
+
static VALUE ta_func_setup_out_real(VALUE self, VALUE param_index, VALUE out_array)
|
369
|
+
{
|
370
|
+
TA_RetCode ret_code;
|
371
|
+
ParamHolder *param_holder;
|
372
|
+
long idx = FIX2INT(param_index);
|
373
|
+
if (idx > 2)
|
374
|
+
rb_raise(rb_eRuntimeError, "param_index must be 0..2");
|
375
|
+
Data_Get_Struct(self, ParamHolder, param_holder);
|
376
|
+
rb_ary_store(rb_iv_get(self, "@result"), idx, out_array);
|
377
|
+
// FIXME: malloc w/o free: johnribera@hotmail.com fixed
|
378
|
+
double **dp = &(param_holder->out[idx]);
|
379
|
+
if (*dp) free(*dp); // not true only 1st time called (reusing same ptrs)
|
380
|
+
*dp = (double*)malloc(RARRAY_LEN(out_array) * sizeof(double));
|
381
|
+
ret_code = TA_SetOutputParamRealPtr(param_holder->p, idx, *dp);
|
382
|
+
if ( ret_code != TA_SUCCESS )
|
383
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_SetOutputParamRealPtr");
|
384
|
+
}
|
385
|
+
|
386
|
+
static VALUE ta_func_setup_out_integer(VALUE self, VALUE param_index, VALUE out_array)
|
387
|
+
{
|
388
|
+
TA_RetCode ret_code;
|
389
|
+
ParamHolder *param_holder;
|
390
|
+
long idx = FIX2INT(param_index);
|
391
|
+
if (idx > 2)
|
392
|
+
rb_raise(rb_eRuntimeError, "param_index must be 0..2");
|
393
|
+
Data_Get_Struct(self, ParamHolder, param_holder);
|
394
|
+
rb_ary_store(rb_iv_get(self, "@result"), idx, out_array);
|
395
|
+
// FIXME: malloc w/o free FIXED: johnribera@Hotmail.com
|
396
|
+
int **ip = (int**)&(param_holder->out[idx]);
|
397
|
+
if (*ip) free(*ip); // not true only very 1st time in
|
398
|
+
*ip = (int*)malloc(RARRAY_LEN(out_array) * sizeof(int));
|
399
|
+
ret_code=TA_SetOutputParamIntegerPtr( param_holder->p, idx, *ip);
|
400
|
+
if ( ret_code != TA_SUCCESS )
|
401
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_SetOutputParamIntegerPtr");
|
402
|
+
}
|
403
|
+
|
404
|
+
/*
|
405
|
+
* call-seq: call(in_start, in_end)
|
406
|
+
*
|
407
|
+
* Call technical function with input data from in_start..in_end.
|
408
|
+
*/
|
409
|
+
static VALUE ta_func_call(VALUE self, VALUE in_start, VALUE in_end)
|
410
|
+
{
|
411
|
+
TA_RetCode ret_code;
|
412
|
+
ParamHolder *param_holder;
|
413
|
+
TA_Integer out_start, out_num;
|
414
|
+
VALUE ary, sub_ary;
|
415
|
+
int i,j;
|
416
|
+
|
417
|
+
Data_Get_Struct(self, ParamHolder, param_holder);
|
418
|
+
ret_code = TA_CallFunc( param_holder->p, FIX2INT(in_start), FIX2INT(in_end), &out_start, &out_num);
|
419
|
+
if ( ret_code != TA_SUCCESS )
|
420
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_CallFunc");
|
421
|
+
ary = rb_iv_get(self, "@result");
|
422
|
+
for (i = 0; i<RARRAY_LEN(ary); i++)
|
423
|
+
if (TYPE(rb_ary_entry(ary, i)) == T_ARRAY)
|
424
|
+
{
|
425
|
+
sub_ary = rb_ary_entry(ary, i);
|
426
|
+
for (j=0; j<out_num; j++)
|
427
|
+
{
|
428
|
+
double el = ((double*)param_holder->out[i])[j];
|
429
|
+
rb_ary_store(sub_ary, j+out_start, rb_float_new(el));
|
430
|
+
}
|
431
|
+
}
|
432
|
+
return rb_ary_new3(2, INT2FIX(out_start), INT2FIX(out_num));
|
433
|
+
}
|
434
|
+
|
435
|
+
static VALUE ta_func_lookback(VALUE self)
|
436
|
+
{
|
437
|
+
TA_RetCode ret_code;
|
438
|
+
ParamHolder *param_holder;
|
439
|
+
TA_Integer out_lookback;
|
440
|
+
|
441
|
+
Data_Get_Struct(self, ParamHolder, param_holder);
|
442
|
+
ret_code = TA_GetLookback(param_holder->p, &out_lookback);
|
443
|
+
if ( ret_code != TA_SUCCESS )
|
444
|
+
rb_raise(rb_eRuntimeError, "unsuccess return code TA_GetLookback");
|
445
|
+
|
446
|
+
return INT2FIX(out_lookback);
|
447
|
+
}
|
448
|
+
|
449
|
+
void Init_talib()
|
450
|
+
{
|
451
|
+
|
452
|
+
/*
|
453
|
+
* Ruby extension for technical functions library api.
|
454
|
+
*/
|
455
|
+
rb_mTaLib = rb_define_module("TaLib");
|
456
|
+
|
457
|
+
rb_define_const(rb_mTaLib, "TA_Input_Price", INT2FIX(TA_Input_Price));
|
458
|
+
rb_define_const(rb_mTaLib, "TA_Input_Real", INT2FIX(TA_Input_Real));
|
459
|
+
rb_define_const(rb_mTaLib, "TA_Input_Integer", INT2FIX(TA_Input_Integer));
|
460
|
+
rb_define_const(rb_mTaLib, "TA_IN_PRICE_OPEN", INT2FIX(TA_IN_PRICE_OPEN));
|
461
|
+
rb_define_const(rb_mTaLib, "TA_IN_PRICE_HIGH", INT2FIX(TA_IN_PRICE_HIGH));
|
462
|
+
rb_define_const(rb_mTaLib, "TA_IN_PRICE_LOW", INT2FIX(TA_IN_PRICE_LOW));
|
463
|
+
rb_define_const(rb_mTaLib, "TA_IN_PRICE_CLOSE", INT2FIX(TA_IN_PRICE_CLOSE));
|
464
|
+
rb_define_const(rb_mTaLib, "TA_IN_PRICE_VOLUME", INT2FIX(TA_IN_PRICE_VOLUME));
|
465
|
+
rb_define_const(rb_mTaLib, "TA_IN_PRICE_OPENINTEREST", INT2FIX(TA_IN_PRICE_OPENINTEREST));
|
466
|
+
rb_define_const(rb_mTaLib, "TA_IN_PRICE_TIMESTAMP", INT2FIX(TA_IN_PRICE_TIMESTAMP));
|
467
|
+
rb_define_const(rb_mTaLib, "TA_OptInput_RealRange", INT2FIX(TA_OptInput_RealRange));
|
468
|
+
rb_define_const(rb_mTaLib, "TA_OptInput_RealList", INT2FIX(TA_OptInput_RealList));
|
469
|
+
rb_define_const(rb_mTaLib, "TA_OptInput_IntegerRange", INT2FIX(TA_OptInput_IntegerRange));
|
470
|
+
rb_define_const(rb_mTaLib, "TA_OptInput_IntegerList", INT2FIX(TA_OptInput_IntegerList));
|
471
|
+
rb_define_const(rb_mTaLib, "TA_OPTIN_IS_PERCENT", INT2FIX(TA_OPTIN_IS_PERCENT));
|
472
|
+
rb_define_const(rb_mTaLib, "TA_OPTIN_IS_DEGREE", INT2FIX(TA_OPTIN_IS_DEGREE));
|
473
|
+
rb_define_const(rb_mTaLib, "TA_OPTIN_IS_CURRENCY", INT2FIX(TA_OPTIN_IS_CURRENCY));
|
474
|
+
rb_define_const(rb_mTaLib, "TA_OPTIN_ADVANCED", INT2FIX(TA_OPTIN_ADVANCED));
|
475
|
+
rb_define_const(rb_mTaLib, "TA_Output_Real", INT2FIX(TA_Output_Real));
|
476
|
+
rb_define_const(rb_mTaLib, "TA_Output_Integer", INT2FIX(TA_Output_Integer));
|
477
|
+
rb_define_const(rb_mTaLib, "TA_OUT_LINE", INT2FIX(TA_OUT_LINE));
|
478
|
+
rb_define_const(rb_mTaLib, "TA_OUT_DOT_LINE", INT2FIX(TA_OUT_DOT_LINE));
|
479
|
+
rb_define_const(rb_mTaLib, "TA_OUT_DASH_LINE", INT2FIX(TA_OUT_DASH_LINE));
|
480
|
+
rb_define_const(rb_mTaLib, "TA_OUT_DOT", INT2FIX(TA_OUT_DOT));
|
481
|
+
rb_define_const(rb_mTaLib, "TA_OUT_HISTO", INT2FIX(TA_OUT_HISTO));
|
482
|
+
rb_define_const(rb_mTaLib, "TA_OUT_PATTERN_BOOL", INT2FIX(TA_OUT_PATTERN_BOOL));
|
483
|
+
rb_define_const(rb_mTaLib, "TA_OUT_PATTERN_BULL_BEAR", INT2FIX(TA_OUT_PATTERN_BULL_BEAR));
|
484
|
+
rb_define_const(rb_mTaLib, "TA_OUT_PATTERN_STRENGTH", INT2FIX(TA_OUT_PATTERN_STRENGTH));
|
485
|
+
rb_define_const(rb_mTaLib, "TA_OUT_POSITIVE", INT2FIX(TA_OUT_POSITIVE));
|
486
|
+
rb_define_const(rb_mTaLib, "TA_OUT_NEGATIVE", INT2FIX(TA_OUT_NEGATIVE));
|
487
|
+
rb_define_const(rb_mTaLib, "TA_OUT_ZERO", INT2FIX(TA_OUT_ZERO));
|
488
|
+
rb_define_const(rb_mTaLib, "TA_OUT_UPPER_LIMIT", INT2FIX(TA_OUT_UPPER_LIMIT));
|
489
|
+
rb_define_const(rb_mTaLib, "TA_OUT_LOWER_LIMIT", INT2FIX(TA_OUT_LOWER_LIMIT));
|
490
|
+
rb_define_const(rb_mTaLib, "TA_MAType_SMA", INT2FIX((int)(TA_MAType_SMA)));
|
491
|
+
rb_define_const(rb_mTaLib, "TA_MAType_EMA", INT2FIX((int)(TA_MAType_EMA)));
|
492
|
+
rb_define_const(rb_mTaLib, "TA_MAType_WMA", INT2FIX((int)(TA_MAType_WMA)));
|
493
|
+
rb_define_const(rb_mTaLib, "TA_MAType_DEMA", INT2FIX((int)(TA_MAType_DEMA)));
|
494
|
+
rb_define_const(rb_mTaLib, "TA_MAType_TEMA", INT2FIX((int)(TA_MAType_TEMA)));
|
495
|
+
rb_define_const(rb_mTaLib, "TA_MAType_TRIMA", INT2FIX((int)(TA_MAType_TRIMA)));
|
496
|
+
rb_define_const(rb_mTaLib, "TA_MAType_KAMA", INT2FIX((int)(TA_MAType_KAMA)));
|
497
|
+
rb_define_const(rb_mTaLib, "TA_MAType_MAMA", INT2FIX((int)(TA_MAType_MAMA)));
|
498
|
+
rb_define_const(rb_mTaLib, "TA_MAType_T3", INT2FIX((int)(TA_MAType_T3)));
|
499
|
+
|
500
|
+
rb_struct_define("TA_RealRange", "min", "max", "precision", NULL);
|
501
|
+
rb_struct_define("TA_IntegerRange", "min", "max", NULL );
|
502
|
+
rb_struct_define("TA_RealDataPair", "value", "string", NULL );
|
503
|
+
rb_struct_define("TA_IntegerDataPair", "value", "string", NULL );
|
504
|
+
rb_struct_define("TA_RealList", "data", "nb_element", NULL );
|
505
|
+
rb_struct_define("TA_IntegerList", "data", "nb_element", NULL );
|
506
|
+
|
507
|
+
rb_sInParamInfo = rb_struct_define("TA_InputParameterInfo", "type", "param_name", "flags", NULL );
|
508
|
+
rb_sOptInParamInfo = rb_struct_define("TA_OutInputParameterInfo", "type", "param_name", "flags", "display_name", "data_set", "default_value", "hint", "help_file", NULL );
|
509
|
+
rb_sOutParamInfo = rb_struct_define("TA_OutputParameterInfo", "type", "param_name", "flags", NULL );
|
510
|
+
|
511
|
+
/*
|
512
|
+
* Class for technical analysis function.
|
513
|
+
*/
|
514
|
+
rb_cTAFunction = rb_define_class_under(rb_mTaLib, "Function", rb_cObject);
|
515
|
+
rb_define_alloc_func(rb_cTAFunction, ta_func_alloc);
|
516
|
+
rb_define_method(rb_cTAFunction, "initialize", ta_func_initialize, 1);
|
517
|
+
rb_define_attr(rb_cTAFunction, "result", 1, 1);
|
518
|
+
|
519
|
+
rb_define_module_function( rb_cTAFunction, "groups", ta_func_get_groups, 0 );
|
520
|
+
rb_define_module_function( rb_cTAFunction, "functions", ta_func_get_functions, 0 );
|
521
|
+
|
522
|
+
rb_define_method( rb_cTAFunction, "ins", ta_func_get_input_count, 0 );
|
523
|
+
rb_define_method( rb_cTAFunction, "outs", ta_func_get_output_count, 0 );
|
524
|
+
rb_define_method( rb_cTAFunction, "opts", ta_func_get_option_input_count, 0 );
|
525
|
+
|
526
|
+
rb_define_method( rb_cTAFunction, "in", ta_func_input_param_info, 1);
|
527
|
+
rb_define_method( rb_cTAFunction, "opt", ta_func_option_param_info, 1);
|
528
|
+
rb_define_method( rb_cTAFunction, "out", ta_func_output_param_info, 1);
|
529
|
+
|
530
|
+
rb_define_method( rb_cTAFunction, "in_int", ta_func_setup_in_integer, 2);
|
531
|
+
rb_define_method( rb_cTAFunction, "in_real", ta_func_setup_in_real, 2);
|
532
|
+
rb_define_method( rb_cTAFunction, "in_price", ta_func_setup_in_price, 7);
|
533
|
+
rb_define_method( rb_cTAFunction, "opt_int", ta_func_setup_opt_in_integer, 2);
|
534
|
+
rb_define_method( rb_cTAFunction, "opt_real", ta_func_setup_opt_in_real, 2);
|
535
|
+
rb_define_method( rb_cTAFunction, "out_int", ta_func_setup_out_integer, 2);
|
536
|
+
rb_define_method( rb_cTAFunction, "out_real", ta_func_setup_out_real, 2);
|
537
|
+
|
538
|
+
rb_define_method( rb_cTAFunction, "lookback", ta_func_lookback, 0);
|
539
|
+
rb_define_method( rb_cTAFunction, "call", ta_func_call, 2);
|
540
|
+
}
|
data/lib/talib_ruby.rb
ADDED
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: talib_ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 31
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 4
|
10
|
+
version: 1.0.4
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Valentin Treu
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-07-22 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Ruby Wrapper for the Technical Analysis Library ta-lib
|
23
|
+
email: rivella50@gmail.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions:
|
27
|
+
- ext/talib/extconf.rb
|
28
|
+
- ext/talib/extconf.rb
|
29
|
+
extra_rdoc_files:
|
30
|
+
- README.textile
|
31
|
+
files:
|
32
|
+
- example/ma.rb
|
33
|
+
- ext/talib/talib.c
|
34
|
+
- lib/talib_ruby.rb
|
35
|
+
- README.textile
|
36
|
+
- ext/talib/extconf.rb
|
37
|
+
has_rdoc: true
|
38
|
+
homepage: http://github.com/rivella50/talib-ruby
|
39
|
+
licenses: []
|
40
|
+
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
hash: 3
|
52
|
+
segments:
|
53
|
+
- 0
|
54
|
+
version: "0"
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
requirements: []
|
65
|
+
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.3.7
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: Ruby Wrapper for ta-lib
|
71
|
+
test_files: []
|
72
|
+
|