1 /* TA-LIB Copyright (c) 1999-2007, Mario Fortier
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the following
6 * conditions are met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * - Neither name of author nor the names of its contributors
17 * may be used to endorse or promote products derived from this
18 * software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /* List of contributors:
35 *
36 * Initial Name/description
37 * -------------------------------------------------------------------
38 * MF Mario Fortier
39 *
40 *
41 * Change history:
42 *
43 * MMDDYY BY Description
44 * -------------------------------------------------------------------
45 * 112400 MF First version.
46 *
47 */
48
49 /* Description:
50 * Regression test of Bollinger Bands (BBANDS).
51 */
52
53 /**** Headers ****/
54 #include <stdio.h>
55 #include <string.h>
56
57 #include "ta_test_priv.h"
58 #include "ta_test_func.h"
59 #include "ta_utility.h"
60 #include "ta_memory.h"
61
62 /**** External functions declarations. ****/
63 /* None */
64
65 /**** External variables declarations. ****/
66 /* None */
67
68 /**** Global variables definitions. ****/
69 /* None */
70
71 /**** Local declarations. ****/
72 typedef struct
73 {
74 TA_Integer doRangeTestFlag;
75
76 TA_Integer startIdx;
77 TA_Integer endIdx;
78
79 TA_Integer optInTimePeriod;
80 TA_Real optInNbDevUp;
81 TA_Real optInNbDevDn;
82 TA_Integer optInMethod_3;
83 TA_Integer compatibility;
84
85 TA_RetCode expectedRetCode;
86
87 TA_Integer expectedBegIdx;
88 TA_Integer expectedNbElement;
89
90 TA_Integer oneOfTheExpectedOutRealIndex0;
91 TA_Real oneOfTheExpectedOutReal0;
92
93 TA_Integer oneOfTheExpectedOutRealIndex1;
94 TA_Real oneOfTheExpectedOutReal1;
95
96 TA_Integer oneOfTheExpectedOutRealIndex2;
97 TA_Real oneOfTheExpectedOutReal2;
98
99 } TA_Test;
100
101 typedef struct
102 {
103 const TA_Test *test;
104 const TA_Real *close;
105 } TA_RangeTestParam;
106
107 /**** Local functions declarations. ****/
108 static ErrorNumber do_test( const TA_History *history,
109 const TA_Test *test );
110
111 /**** Local variables definitions. ****/
112 static TA_Test tableTest[] =
113 {
114
115 /****************************/
116 /* BBANDS - CLASSIC - EMA */
117 /****************************/
118
119 /* No multiplier */
120 /* With upper band multiplier only. */
121 /* With lower band multiplier only. */
122 /* With identical upper/lower multiplier. */
123 { 0, 0, 251, 20, 2.0, 2.0, TA_MAType_EMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS,
124 19, 252-19,
125 13, 93.674, /* Upper */
126 13, 87.679, /* Middle */
127 13, 81.685 }, /* Lower */
128
129 { 0, 0, 251, 20, 2.0, 2.0, TA_MAType_EMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS,
130 19, 252-19,
131 0, 98.0734, /* Upper */
132 0, 92.8910, /* Middle */
133 0, 87.7086 }, /* Lower */
134 /* With distinctive upper/lower multiplier. */
135
136 /****************************/
137 /* BBANDS - CLASSIC - SMA */
138 /****************************/
139 /* No multiplier */
140 /* With upper band multiplier only. */
141 /* With lower band multiplier only. */
142 /* With identical upper/lower multiplier. */
143 { 1, 0, 251, 20, 2.0, 2.0, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS,
144 19, 252-19,
145 0, 98.0734, /* Upper */
146 0, 92.8910, /* Middle */
147 0, 87.7086 }, /* Lower */
148 /* With distinctive upper/lower multiplier. */
149
150
151 /******************************/
152 /* BBANDS - METASTOCK - SMA */
153 /******************************/
154
155 /* No multiplier */
156 /* With upper band multiplier only. */
157 /* With lower band multiplier only. */
158
159 /* With identical upper/lower multiplier. */
160 { 1, 0, 251, 20, 2.0, 2.0, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
161 19, 252-19,
162 0, 98.0734, /* Upper */
163 0, 92.8910, /* Middle */
164 0, 87.7086 }, /* Lower */
165
166 /* With distinctive upper/lower multiplier. */
167
168 /******************************/
169 /* BBANDS - METASTOCK - EMA */
170 /******************************/
171
172 /* No multiplier */
173 { 1, 0, 251, 20, 1.0, 1.0, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
174 19, 252-19,
175 0, 94.6914, /* Upper */
176 0, 92.1002, /* Middle */
177 0, 89.5090 }, /* Lower */
178 { 0, 0, 251, 20, 1.0, 1.0, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
179 19, 252-19,
180 3, 94.0477, /* Upper */
181 3, 90.7270, /* Middle */
182 3, 87.4063 }, /* Lower */
183 { 0, 0, 251, 20, 1.0, 1.0, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
184 19, 252-19,
185 252-20, 111.5415, /* Upper */
186 252-20, 108.5265, /* Middle */
187 252-20, 105.5115 }, /* Lower */
188
189 /* With upper band multiplier only. */
190 { 0, 0, 251, 20, 1.5, 1.0, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
191 19, 252-19,
192 0, 95.9870, /* Upper */
193 0, 92.1002, /* Middle */
194 0, 89.5090}, /* Lower */
195 { 0, 0, 251, 20, 1.5, 1.0, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
196 19, 252-19,
197 3, 95.7080, /* Upper */
198 3, 90.7270, /* Middle */
199 3, 87.4063}, /* Lower */
200 { 0, 0, 251, 20, 1.5, 1.0, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
201 19, 252-19,
202 252-20, 113.0490, /* Upper */
203 252-20, 108.5265, /* Middle */
204 252-20, 105.5115 }, /* Lower */
205
206 /* With lower band multiplier only. */
207 { 1, 0, 251, 20, 1.0, 1.5, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
208 19, 252-19,
209 0, 94.6914, /* Upper */
210 0, 92.1002, /* Middle */
211 0, 88.2134 }, /* Lower */
212 { 0, 0, 251, 20, 1.0, 1.5, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
213 19, 252-19,
214 3, 94.0477, /* Upper */
215 3, 90.7270, /* Middle */
216 3, 85.7460}, /* Lower */
217 { 0, 0, 251, 20, 1.0, 1.5, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
218 19, 252-19,
219 252-20, 111.5415, /* Upper */
220 252-20, 108.5265, /* Middle */
221 252-20, 104.0040}, /* Lower */
222
223 /* With identical upper/lower multiplier. */
224 { 0, 0, 251, 20, 2.0, 2.0, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
225 19, 252-19,
226 0, 97.2826, /* Upper */
227 0, 92.1002, /* Middle */
228 0, 86.9178}, /* Lower */
229 { 0, 0, 251, 20, 2.0, 2.0, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
230 19, 252-19,
231 1, 97.2637, /* Upper */
232 1, 91.7454, /* Middle */
233 1, 86.2271}, /* Lower */
234 { 0, 0, 251, 20, 2.0, 2.0, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
235 19, 252-19,
236 252-20, 114.5564, /* Upper */
237 252-20, 108.5265, /* Middle */
238 252-20, 102.4965}, /* Lower */
239
240 /* With distinctive upper/lower multiplier. */
241 { 0, 0, 251, 20, 2.0, 1.5, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
242 19, 252-19,
243 0, 97.2826, /* Upper */
244 0, 92.1002, /* Middle */
245 0, 88.2134 }, /* Lower */
246 { 0, 0, 251, 20, 2.0, 1.5, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
247 19, 252-19,
248 3, 97.3684, /* Upper */
249 3, 90.7270, /* Middle */
250 3, 85.7460}, /* Lower */
251 { 0, 0, 251, 20, 2.0, 1.5, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS,
252 19, 252-19,
253 252-20, 114.5564, /* Upper */
254 252-20, 108.5265, /* Middle */
255 252-20, 104.0040} /* Lower */
256
257 };
258
259 #define NB_TEST (sizeof(tableTest)/sizeof(TA_Test))
260
261 /**** Global functions definitions. ****/
test_func_bbands(TA_History * history)262 ErrorNumber test_func_bbands( TA_History *history )
263 {
264 unsigned int i;
265 ErrorNumber retValue;
266
267 for( i=0; i < NB_TEST; i++ )
268 {
269
270 if( (int)tableTest[i].expectedNbElement > (int)history->nbBars )
271 {
272 printf( "%s Failed Bad Parameter for Test #%d (%d,%d)\n", __FILE__,
273 i,
274 tableTest[i].expectedNbElement,
275 history->nbBars );
276 return TA_TESTUTIL_TFRR_BAD_PARAM;
277 }
278
279 retValue = do_test( history, &tableTest[i] );
280 if( retValue != 0 )
281 {
282 printf( "%s Failed Test #%d (Code=%d)\n", __FILE__, i, retValue );
283 return retValue;
284 }
285 }
286
287 /* All test succeed. */
288 return TA_TEST_PASS;
289 }
290
291 /**** Local functions definitions. ****/
rangeTestFunction(TA_Integer startIdx,TA_Integer endIdx,TA_Real * outputBuffer,TA_Integer * outputBufferInt,TA_Integer * outBegIdx,TA_Integer * outNbElement,TA_Integer * lookback,void * opaqueData,unsigned int outputNb,unsigned int * isOutputInteger)292 static TA_RetCode rangeTestFunction( TA_Integer startIdx,
293 TA_Integer endIdx,
294 TA_Real *outputBuffer,
295 TA_Integer *outputBufferInt,
296 TA_Integer *outBegIdx,
297 TA_Integer *outNbElement,
298 TA_Integer *lookback,
299 void *opaqueData,
300 unsigned int outputNb,
301 unsigned int *isOutputInteger )
302 {
303 TA_RetCode retCode;
304 TA_RangeTestParam *testParam;
305 TA_Real *dummyBuffer1, *dummyBuffer2;
306 TA_Real *out1, *out2, *out3;
307
308 (void)outputBufferInt;
309
310 *isOutputInteger = 0;
311
312 testParam = (TA_RangeTestParam *)opaqueData;
313
314 dummyBuffer1 = TA_Malloc( ((endIdx-startIdx)+1)*sizeof(TA_Real));
315 if( !dummyBuffer1 )
316 return TA_ALLOC_ERR;
317
318 dummyBuffer2 = TA_Malloc( ((endIdx-startIdx)+1)*sizeof(TA_Real));
319 if( !dummyBuffer2 )
320 {
321 TA_Free( dummyBuffer1 );
322 return TA_ALLOC_ERR;
323 }
324
325 switch( outputNb )
326 {
327 case 0:
328 out1 = outputBuffer;
329 out2 = dummyBuffer1;
330 out3 = dummyBuffer2;
331 break;
332 case 1:
333 out2 = outputBuffer;
334 out1 = dummyBuffer1;
335 out3 = dummyBuffer2;
336 break;
337 case 2:
338 out3 = outputBuffer;
339 out2 = dummyBuffer1;
340 out1 = dummyBuffer2;
341 break;
342 default:
343 TA_Free( dummyBuffer1 );
344 TA_Free( dummyBuffer2 );
345 return TA_BAD_PARAM;
346 }
347
348 retCode = TA_BBANDS( startIdx,
349 endIdx,
350 testParam->close,
351 testParam->test->optInTimePeriod,
352 testParam->test->optInNbDevUp,
353 testParam->test->optInNbDevDn,
354 (TA_MAType)testParam->test->optInMethod_3,
355 outBegIdx, outNbElement,
356 out1, out2, out3 );
357
358 *lookback = TA_BBANDS_Lookback( testParam->test->optInTimePeriod,
359 testParam->test->optInNbDevUp,
360 testParam->test->optInNbDevDn,
361 (TA_MAType)testParam->test->optInMethod_3 );
362
363 TA_Free( dummyBuffer1 );
364 TA_Free( dummyBuffer2 );
365
366 return retCode;
367 }
368
369
do_test(const TA_History * history,const TA_Test * test)370 static ErrorNumber do_test( const TA_History *history,
371 const TA_Test *test )
372 {
373 TA_RetCode retCode;
374 ErrorNumber errNb;
375 TA_Integer outBegIdx;
376 TA_Integer outNbElement;
377 TA_RangeTestParam testParam;
378
379 retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_EMA, 0 );
380 if( retCode != TA_SUCCESS )
381 return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL;
382
383 /* Set to NAN all the elements of the gBuffers. */
384 clearAllBuffers();
385
386 /* Build the input. */
387 setInputBuffer( 0, history->close, history->nbBars );
388 setInputBuffer( 1, history->close, history->nbBars );
389 setInputBuffer( 2, history->close, history->nbBars );
390 setInputBuffer( 3, history->close, history->nbBars );
391
392 TA_SetCompatibility( (TA_Compatibility)test->compatibility );
393
394 /* Make a simple first call. */
395 retCode = TA_BBANDS( test->startIdx,
396 test->endIdx,
397 gBuffer[0].in,
398 test->optInTimePeriod,
399 test->optInNbDevUp,
400 test->optInNbDevDn,
401 (TA_MAType)test->optInMethod_3,
402
403 &outBegIdx, &outNbElement,
404 gBuffer[0].out0,
405 gBuffer[0].out1,
406 gBuffer[0].out2 );
407
408 errNb = checkDataSame( gBuffer[0].in, history->close, history->nbBars );
409 if( errNb != TA_TEST_PASS )
410 return errNb;
411
412 CHECK_EXPECTED_VALUE( gBuffer[0].out0, 0 );
413 CHECK_EXPECTED_VALUE( gBuffer[0].out1, 1 );
414 CHECK_EXPECTED_VALUE( gBuffer[0].out2, 2 );
415
416 outBegIdx = outNbElement = 0;
417
418 /* Make another call where the input and the output are the
419 * same buffer.
420 */
421 retCode = TA_BBANDS( test->startIdx,
422 test->endIdx,
423 gBuffer[1].in,
424 test->optInTimePeriod,
425 test->optInNbDevUp,
426 test->optInNbDevDn,
427 (TA_MAType)test->optInMethod_3,
428 &outBegIdx, &outNbElement,
429 gBuffer[1].in, gBuffer[1].out1, gBuffer[1].out2 );
430
431 /* The previous call should have the same output
432 * as this call.
433 *
434 * checkSameContent verify that all value different than NAN in
435 * the first parameter is identical in the second parameter.
436 */
437 errNb = checkSameContent( gBuffer[0].out0, gBuffer[1].in );
438 if( errNb != TA_TEST_PASS )
439 return errNb;
440
441 CHECK_EXPECTED_VALUE( gBuffer[1].in, 0 );
442 CHECK_EXPECTED_VALUE( gBuffer[1].out1, 1 );
443 CHECK_EXPECTED_VALUE( gBuffer[1].out2, 2 );
444
445 outBegIdx = outNbElement = 0;
446
447 /* Make another call where the input and the output are the
448 * same buffer.
449 */
450 retCode = TA_BBANDS( test->startIdx,
451 test->endIdx,
452 gBuffer[2].in,
453 test->optInTimePeriod,
454 test->optInNbDevUp,
455 test->optInNbDevDn,
456 (TA_MAType)test->optInMethod_3,
457 &outBegIdx, &outNbElement,
458 gBuffer[2].out1,
459 gBuffer[2].in,
460 gBuffer[2].out2 );
461
462 /* The previous call should have the same output
463 * as this call.
464 *
465 * checkSameContent verify that all value different than NAN in
466 * the first parameter is identical in the second parameter.
467 */
468 errNb = checkSameContent( gBuffer[1].out1, gBuffer[2].in );
469 if( errNb != TA_TEST_PASS )
470 return errNb;
471
472 CHECK_EXPECTED_VALUE( gBuffer[2].out1, 0 );
473 CHECK_EXPECTED_VALUE( gBuffer[2].in, 1 );
474 CHECK_EXPECTED_VALUE( gBuffer[2].out2, 2 );
475
476 outBegIdx = outNbElement = 0;
477
478 /* Make another call where the input and the output are the
479 * same buffer.
480 */
481 retCode = TA_BBANDS( test->startIdx,
482 test->endIdx,
483 gBuffer[3].in,
484 test->optInTimePeriod,
485 test->optInNbDevUp,
486 test->optInNbDevDn,
487 (TA_MAType)test->optInMethod_3,
488 &outBegIdx, &outNbElement,
489 gBuffer[3].out0,
490 gBuffer[3].out1,
491 gBuffer[3].in );
492
493 /* The previous call should have the same output
494 * as this call.
495 *
496 * checkSameContent verify that all value different than NAN in
497 * the first parameter is identical in the second parameter.
498 */
499 errNb = checkSameContent( gBuffer[2].out2, gBuffer[3].in );
500 if( errNb != TA_TEST_PASS )
501 return errNb;
502
503 CHECK_EXPECTED_VALUE( gBuffer[3].out0, 0 );
504 CHECK_EXPECTED_VALUE( gBuffer[3].out1, 1 );
505 CHECK_EXPECTED_VALUE( gBuffer[3].in, 2 );
506
507 /* Do a systematic test of most of the
508 * possible startIdx/endIdx range.
509 */
510 testParam.test = test;
511 testParam.close = history->close;
512
513 if( test->doRangeTestFlag )
514 {
515 if( test->optInMethod_3 == TA_MAType_EMA )
516 {
517 errNb = doRangeTest( rangeTestFunction,
518 TA_FUNC_UNST_EMA,
519 (void *)&testParam, 3, 0 );
520 }
521 else
522 {
523 errNb = doRangeTest( rangeTestFunction,
524 TA_FUNC_UNST_NONE,
525 (void *)&testParam, 3, 0 );
526 }
527
528 if( errNb != TA_TEST_PASS )
529 return errNb;
530 }
531
532 return TA_TEST_PASS;
533 }
534