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 MACD.
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 enum {
73 TA_MACD_TEST,
74 TA_MACDFIX_TEST,
75 TA_MACDEXT_TEST
76 } TA_TestId;
77
78 typedef struct
79 {
80 TA_Integer doRangeTestFlag;
81 TA_TestId testId;
82
83 TA_Integer startIdx;
84 TA_Integer endIdx;
85
86 TA_Integer optInFastPeriod;
87 TA_Integer optInSlowPeriod;
88 TA_Integer optInSignalPeriod_2;
89 TA_Integer compatibility;
90
91 TA_RetCode expectedRetCode;
92
93 TA_Integer expectedBegIdx;
94 TA_Integer expectedNbElement;
95
96 TA_Integer oneOfTheExpectedOutRealIndex0;
97 TA_Real oneOfTheExpectedOutReal0;
98
99 TA_Integer oneOfTheExpectedOutRealIndex1;
100 TA_Real oneOfTheExpectedOutReal1;
101
102 TA_Integer oneOfTheExpectedOutRealIndex2;
103 TA_Real oneOfTheExpectedOutReal2;
104
105 } TA_Test;
106
107 typedef struct
108 {
109 const TA_Test *test;
110 const TA_Real *close;
111 } TA_RangeTestParam;
112
113 /**** Local functions declarations. ****/
114 static ErrorNumber do_test( const TA_History *history,
115 const TA_Test *test );
116
117 /**** Local variables definitions. ****/
118 static TA_Test tableTest[] =
119 {
120
121 /*********************/
122 /* MACD - CLASSIC */
123 /*********************/
124 { 0, TA_MACD_TEST, 0, 251, 12, 26, 9, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 33, 252-33, /* 25, 252-25,*/
125 0, -1.9738, /* MACD */
126 0, -2.7071, /* Signal */
127 0, (-1.9738)-(-2.7071) }, /* Histogram */
128
129 /* Test period inversion */
130 { 0, TA_MACD_TEST, 0, 251, 26, 12, 9, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 33, 252-33, /* 25, 252-25,*/
131 0, -1.9738, /* MACD */
132 0, -2.7071, /* Signal */
133 0, (-1.9738)-(-2.7071) }, /* Histogram */
134
135 /***********************/
136 /* MACD - METASTOCK */
137 /***********************/
138
139 /*******************************/
140 /* MACDEXT - MIMIC CLASSIC */
141 /*******************************/
142 { 0, TA_MACDEXT_TEST, 0, 251, 12, 26, 9, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 33, 252-33, /* 25, 252-25,*/
143 0, -1.9738, /* MACD */
144 0, -2.7071, /* Signal */
145 0, (-1.9738)-(-2.7071)}, /* Histogram */
146
147 /***************************/
148 /* MACD FIX - CLASSIC */
149 /***************************/
150
151 /***************************/
152 /* MACD FIX - METASTOCK */
153 /***************************/
154 { 1, TA_MACDFIX_TEST, 0, 251, 12, 26, 9, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 33, 252-33, /* 25, 252-25,*/
155 0, -1.2185, /* MACD */
156 0, -1.7119, /* Signal */
157 0, (-1.2185)-(-1.7119) }, /* Histogram */
158
159 { 0, TA_MACDFIX_TEST, 0, 251, 12, 26, 9, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 33, 252-33,
160 252-34, 0.8764, /* MACD */
161 252-34, 1.3533, /* Signal */
162 252-34, (0.8764)-(1.3533)}, /* Histogram */
163 /* Test period inversion */
164 { 0, TA_MACDFIX_TEST, 0, 251, 26, 12, 9, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 33, 252-33,
165 252-34, 0.8764, /* MACD */
166 252-34, 1.3533, /* Signal */
167 252-34, (0.8764)-(1.3533)} /* Histogram */
168
169 };
170
171 #define NB_TEST (sizeof(tableTest)/sizeof(TA_Test))
172
173 /**** Global functions definitions. ****/
test_func_macd(TA_History * history)174 ErrorNumber test_func_macd( TA_History *history )
175 {
176 unsigned int i;
177 ErrorNumber retValue;
178
179 for( i=0; i < NB_TEST; i++ )
180 {
181
182 if( (int)tableTest[i].expectedNbElement > (int)history->nbBars )
183 {
184 printf( "TA_MACD Failed Bad Parameter for Test #%d (%d,%d)\n",
185 i,
186 tableTest[i].expectedNbElement,
187 history->nbBars );
188 return TA_TESTUTIL_TFRR_BAD_PARAM;
189 }
190
191 retValue = do_test( history, &tableTest[i] );
192 if( retValue != 0 )
193 {
194 printf( "TA_MACD Failed Test #%d (Code=%d)\n", i, retValue );
195 return retValue;
196 }
197 }
198
199 /* All test succeed. */
200 return TA_TEST_PASS;
201 }
202
203 /**** 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)204 static TA_RetCode rangeTestFunction( TA_Integer startIdx,
205 TA_Integer endIdx,
206 TA_Real *outputBuffer,
207 TA_Integer *outputBufferInt,
208 TA_Integer *outBegIdx,
209 TA_Integer *outNbElement,
210 TA_Integer *lookback,
211 void *opaqueData,
212 unsigned int outputNb,
213 unsigned int *isOutputInteger )
214 {
215 TA_RetCode retCode;
216 TA_RangeTestParam *testParam;
217 TA_Real *dummyBuffer1, *dummyBuffer2;
218 TA_Real *out1, *out2, *out3;
219
220 (void)outputBufferInt;
221
222 *isOutputInteger = 0;
223
224 testParam = (TA_RangeTestParam *)opaqueData;
225
226 dummyBuffer1 = TA_Malloc( ((endIdx-startIdx)+1)*sizeof(TA_Real));
227 if( !dummyBuffer1 )
228 return TA_ALLOC_ERR;
229
230 dummyBuffer2 = TA_Malloc( ((endIdx-startIdx)+1)*sizeof(TA_Real));
231 if( !dummyBuffer2 )
232 {
233 TA_Free( dummyBuffer1 );
234 return TA_ALLOC_ERR;
235 }
236
237 switch( outputNb )
238 {
239 case 0:
240 out1 = outputBuffer;
241 out2 = dummyBuffer1;
242 out3 = dummyBuffer2;
243 break;
244 case 1:
245 out2 = outputBuffer;
246 out1 = dummyBuffer1;
247 out3 = dummyBuffer2;
248 break;
249 case 2:
250 out3 = outputBuffer;
251 out2 = dummyBuffer1;
252 out1 = dummyBuffer2;
253 break;
254 default:
255 TA_Free( dummyBuffer1 );
256 TA_Free( dummyBuffer2 );
257 return TA_BAD_PARAM;
258 }
259
260 switch( testParam->test->testId )
261 {
262 case TA_MACDFIX_TEST:
263 retCode = TA_MACDFIX( startIdx,
264 endIdx,
265 testParam->close,
266 testParam->test->optInSignalPeriod_2,
267 outBegIdx, outNbElement,
268 out1, out2, out3 );
269 *lookback = TA_MACDFIX_Lookback( testParam->test->optInSignalPeriod_2 );
270 break;
271 case TA_MACD_TEST:
272 retCode = TA_MACD( startIdx,
273 endIdx,
274 testParam->close,
275 testParam->test->optInFastPeriod,
276 testParam->test->optInSlowPeriod,
277 testParam->test->optInSignalPeriod_2,
278 outBegIdx, outNbElement,
279 out1, out2, out3 );
280
281 *lookback = TA_MACD_Lookback( testParam->test->optInFastPeriod,
282 testParam->test->optInSlowPeriod,
283 testParam->test->optInSignalPeriod_2 );
284 break;
285 case TA_MACDEXT_TEST:
286 retCode = TA_MACDEXT( startIdx,
287 endIdx,
288 testParam->close,
289 testParam->test->optInFastPeriod,
290 TA_MAType_EMA,
291 testParam->test->optInSlowPeriod,
292 TA_MAType_EMA,
293 testParam->test->optInSignalPeriod_2,
294 TA_MAType_EMA,
295 outBegIdx, outNbElement,
296 out1, out2, out3 );
297
298 *lookback = TA_MACDEXT_Lookback( testParam->test->optInFastPeriod,
299 TA_MAType_EMA,
300 testParam->test->optInSlowPeriod,
301 TA_MAType_EMA,
302 testParam->test->optInSignalPeriod_2,
303 TA_MAType_EMA );
304 break;
305 default:
306 retCode = TA_BAD_PARAM;
307 }
308
309 TA_Free( dummyBuffer1 );
310 TA_Free( dummyBuffer2 );
311
312 return retCode;
313 }
314
do_test(const TA_History * history,const TA_Test * test)315 static ErrorNumber do_test( const TA_History *history,
316 const TA_Test *test )
317 {
318 TA_RetCode retCode;
319 ErrorNumber errNb;
320 TA_Integer outBegIdx;
321 TA_Integer outNbElement;
322 TA_RangeTestParam testParam;
323
324 retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_EMA, 0 );
325 if( retCode != TA_SUCCESS )
326 return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL;
327
328 TA_SetCompatibility( (TA_Compatibility)test->compatibility );
329
330 /* Set to NAN all the elements of the gBuffers. */
331 clearAllBuffers();
332
333 /* Build the input. */
334 setInputBuffer( 0, history->close, history->nbBars );
335 setInputBuffer( 1, history->close, history->nbBars );
336 setInputBuffer( 2, history->close, history->nbBars );
337 setInputBuffer( 3, history->close, history->nbBars );
338
339 CLEAR_EXPECTED_VALUE(0);
340 CLEAR_EXPECTED_VALUE(1);
341 CLEAR_EXPECTED_VALUE(2);
342
343 /* Make a simple first call. */
344 switch( test->testId )
345 {
346 case TA_MACDFIX_TEST:
347 retCode = TA_MACDFIX( test->startIdx,
348 test->endIdx,
349 gBuffer[0].in,
350 test->optInSignalPeriod_2,
351 &outBegIdx, &outNbElement,
352 gBuffer[0].out0,
353 gBuffer[0].out1,
354 gBuffer[0].out2 );
355 break;
356 case TA_MACD_TEST:
357 retCode = TA_MACD(test->startIdx,
358 test->endIdx,
359 gBuffer[0].in,
360 test->optInFastPeriod,
361 test->optInSlowPeriod,
362 test->optInSignalPeriod_2,
363 &outBegIdx, &outNbElement,
364 gBuffer[0].out0,
365 gBuffer[0].out1,
366 gBuffer[0].out2 );
367 break;
368 case TA_MACDEXT_TEST:
369 retCode = TA_MACDEXT( test->startIdx,
370 test->endIdx,
371 gBuffer[0].in,
372 test->optInFastPeriod,
373 TA_MAType_EMA,
374 test->optInSlowPeriod,
375 TA_MAType_EMA,
376 test->optInSignalPeriod_2,
377 TA_MAType_EMA,
378 &outBegIdx, &outNbElement,
379 gBuffer[0].out0,
380 gBuffer[0].out1,
381 gBuffer[0].out2 );
382 break;
383 }
384
385
386 errNb = checkDataSame( gBuffer[0].in, history->close, history->nbBars );
387 if( errNb != TA_TEST_PASS )
388 return errNb;
389
390 CHECK_EXPECTED_VALUE( gBuffer[0].out0, 0 );
391 CHECK_EXPECTED_VALUE( gBuffer[0].out1, 1 );
392 CHECK_EXPECTED_VALUE( gBuffer[0].out2, 2 );
393
394 outBegIdx = outNbElement = 0;
395
396 /* Make another call where the input and the output are the
397 * same buffer.
398 */
399 switch( test->testId )
400 {
401 case TA_MACDFIX_TEST:
402 retCode = TA_MACDFIX(
403 test->startIdx,
404 test->endIdx,
405 gBuffer[1].in,
406 test->optInSignalPeriod_2,
407 &outBegIdx, &outNbElement,
408 gBuffer[1].in,
409 gBuffer[1].out1,
410 gBuffer[1].out2 );
411 break;
412 case TA_MACD_TEST:
413 retCode = TA_MACD(test->startIdx,
414 test->endIdx,
415 gBuffer[1].in,
416 test->optInFastPeriod,
417 test->optInSlowPeriod,
418 test->optInSignalPeriod_2,
419 &outBegIdx, &outNbElement,
420 gBuffer[1].in,
421 gBuffer[1].out1,
422 gBuffer[1].out2 );
423 break;
424 case TA_MACDEXT_TEST:
425 retCode = TA_MACDEXT( test->startIdx,
426 test->endIdx,
427 gBuffer[1].in,
428 test->optInFastPeriod,
429 TA_MAType_EMA,
430 test->optInSlowPeriod,
431 TA_MAType_EMA,
432 test->optInSignalPeriod_2,
433 TA_MAType_EMA,
434 &outBegIdx, &outNbElement,
435 gBuffer[1].in,
436 gBuffer[1].out1,
437 gBuffer[1].out2 );
438 break;
439 }
440
441 /* The previous call should have the same output
442 * as this call.
443 *
444 * checkSameContent verify that all value different than NAN in
445 * the first parameter is identical in the second parameter.
446 */
447 errNb = checkSameContent( gBuffer[0].out0, gBuffer[1].in );
448 if( errNb != TA_TEST_PASS )
449 return errNb;
450
451 CHECK_EXPECTED_VALUE( gBuffer[1].in, 0 );
452 CHECK_EXPECTED_VALUE( gBuffer[1].out1, 1 );
453 CHECK_EXPECTED_VALUE( gBuffer[1].out2, 2 );
454
455 outBegIdx = outNbElement = 0;
456
457 CLEAR_EXPECTED_VALUE(0);
458 CLEAR_EXPECTED_VALUE(1);
459 CLEAR_EXPECTED_VALUE(2);
460
461 /* Make another call where the input and the output are the
462 * same buffer.
463 */
464 switch( test->testId )
465 {
466 case TA_MACDFIX_TEST:
467 retCode = TA_MACDFIX(
468 test->startIdx,
469 test->endIdx,
470 gBuffer[2].in,
471 test->optInSignalPeriod_2,
472 &outBegIdx, &outNbElement,
473 gBuffer[2].out1,
474 gBuffer[2].in,
475 gBuffer[2].out2 );
476 break;
477
478 case TA_MACD_TEST:
479 retCode = TA_MACD(
480 test->startIdx,
481 test->endIdx,
482 gBuffer[2].in,
483 test->optInFastPeriod,
484 test->optInSlowPeriod,
485 test->optInSignalPeriod_2,
486 &outBegIdx, &outNbElement,
487 gBuffer[2].out1,
488 gBuffer[2].in,
489 gBuffer[2].out2 );
490 break;
491 case TA_MACDEXT_TEST:
492 retCode = TA_MACDEXT(
493 test->startIdx,
494 test->endIdx,
495 gBuffer[2].in,
496 test->optInFastPeriod,
497 TA_MAType_EMA,
498 test->optInSlowPeriod,
499 TA_MAType_EMA,
500 test->optInSignalPeriod_2,
501 TA_MAType_EMA,
502 &outBegIdx, &outNbElement,
503 gBuffer[2].out1,
504 gBuffer[2].in,
505 gBuffer[2].out2 );
506 break;
507 }
508
509 /* The previous call should have the same output
510 * as this call.
511 *
512 * checkSameContent verify that all value different than NAN in
513 * the first parameter is identical in the second parameter.
514 */
515 errNb = checkSameContent( gBuffer[1].out1, gBuffer[2].in );
516 if( errNb != TA_TEST_PASS )
517 return errNb;
518
519 CHECK_EXPECTED_VALUE( gBuffer[2].out1, 0 );
520 CHECK_EXPECTED_VALUE( gBuffer[2].in, 1 );
521 CHECK_EXPECTED_VALUE( gBuffer[2].out2, 2 );
522
523 outBegIdx = outNbElement = 0;
524
525 CLEAR_EXPECTED_VALUE(0);
526 CLEAR_EXPECTED_VALUE(1);
527 CLEAR_EXPECTED_VALUE(2);
528
529 /* Make another call where the input and the output are the
530 * same buffer.
531 */
532 switch( test->testId )
533 {
534 case TA_MACDFIX_TEST:
535 retCode = TA_MACDFIX( test->startIdx,
536 test->endIdx,
537 gBuffer[3].in,
538 test->optInSignalPeriod_2,
539 &outBegIdx, &outNbElement,
540 gBuffer[3].out1,
541 gBuffer[3].out2,
542 gBuffer[3].in );
543 break;
544 case TA_MACD_TEST:
545 retCode = TA_MACD(test->startIdx,
546 test->endIdx,
547 gBuffer[3].in,
548 test->optInFastPeriod,
549 test->optInSlowPeriod,
550 test->optInSignalPeriod_2,
551 &outBegIdx, &outNbElement,
552 gBuffer[3].out1,
553 gBuffer[3].out2,
554 gBuffer[3].in );
555 break;
556 case TA_MACDEXT_TEST:
557 retCode = TA_MACDEXT( test->startIdx,
558 test->endIdx,
559 gBuffer[3].in,
560 test->optInFastPeriod,
561 TA_MAType_EMA,
562 test->optInSlowPeriod,
563 TA_MAType_EMA,
564 test->optInSignalPeriod_2,
565 TA_MAType_EMA,
566 &outBegIdx, &outNbElement,
567 gBuffer[3].out1,
568 gBuffer[3].out2,
569 gBuffer[3].in );
570 break;
571 }
572
573 /* The previous call should have the same output
574 * as this call.
575 *
576 * checkSameContent verify that all value different than NAN in
577 * the first parameter is identical in the second parameter.
578 */
579 errNb = checkSameContent( gBuffer[2].out2, gBuffer[3].in );
580 if( errNb != TA_TEST_PASS )
581 return errNb;
582
583 CHECK_EXPECTED_VALUE( gBuffer[3].out1, 0 );
584 CHECK_EXPECTED_VALUE( gBuffer[3].out2, 1 );
585 CHECK_EXPECTED_VALUE( gBuffer[3].in, 2 );
586
587 /* Do a systematic test of most of the
588 * possible startIdx/endIdx range.
589 */
590 testParam.test = test;
591 testParam.close = history->close;
592
593 if( test->doRangeTestFlag )
594 {
595 errNb = doRangeTest( rangeTestFunction,
596 TA_FUNC_UNST_EMA,
597 (void *)&testParam, 3, 0 );
598 if( errNb != TA_TEST_PASS )
599 return errNb;
600 }
601
602 return TA_TEST_PASS;
603 }
604