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