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  *     Test functions that have one output and takes a period and
51  *     basically use only an EMA in its algorithm.
52  */
53 
54 /**** Headers ****/
55 #include <stdio.h>
56 #include <string.h>
57 
58 #include "ta_test_priv.h"
59 #include "ta_test_func.h"
60 #include "ta_utility.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_TRIX_TEST
74 } TA_TestId;
75 
76 typedef struct
77 {
78    TA_Integer doRangeTestFlag;
79 
80    TA_TestId  theFunction;
81 
82    TA_Integer unstablePeriod;
83 
84    TA_Integer startIdx;
85    TA_Integer endIdx;
86    TA_Integer optInTimePeriod;
87 
88    TA_RetCode expectedRetCode;
89 
90    TA_Integer oneOfTheExpectedOutRealIndex;
91    TA_Real    oneOfTheExpectedOutReal;
92 
93    TA_Integer expectedBegIdx;
94    TA_Integer expectedNbElement;
95 } TA_Test;
96 
97 typedef struct
98 {
99    const TA_Test *test;
100    const TA_Real *close;
101 } TA_RangeTestParam;
102 
103 /**** Local functions declarations.    ****/
104 static ErrorNumber do_test_per_ema( const TA_History *history,
105                                     const TA_Test *test );
106 
107 /**** Local variables definitions.     ****/
108 
109 static TA_Test tableTest[] =
110 {
111    /****************/
112    /*   TRIX TEST  */
113    /****************/
114    { 0, TA_TRIX_TEST, 0, 0, 251,  5, TA_SUCCESS,      0,   0.2589, 13,  252-13 }, /* First Value */
115    { 0, TA_TRIX_TEST, 0, 0, 251,  5, TA_SUCCESS,      1,   0.010495, 13,  252-13 },
116    { 0, TA_TRIX_TEST, 0, 0, 251,  5, TA_SUCCESS, 252-15,  -0.058, 13,  252-13 },
117    { 0, TA_TRIX_TEST, 0, 0, 251,  5, TA_SUCCESS, 252-14,  -0.095, 13,  252-13 }, /* Last Value */
118 
119 #if 0
120    /* Metastock values. */
121    { 0, TA_TRIX_TEST, 0, 0, 251,  5, TA_SUCCESS,      0,   0.221, 13,  252-13 }, /* First Value */
122    { 0, TA_TRIX_TEST, 0, 0, 251,  5, TA_SUCCESS,      1,  -0.009, 13,  252-13 },
123    { 0, TA_TRIX_TEST, 0, 0, 251,  5, TA_SUCCESS, 252-15,  -0.058, 13,  252-13 },
124    { 0, TA_TRIX_TEST, 0, 0, 251,  5, TA_SUCCESS, 252-14,  -0.095, 13,  252-13 }, /* Last Value */
125 #endif
126 
127 };
128 
129 #define NB_TEST (sizeof(tableTest)/sizeof(TA_Test))
130 
131 /**** Global functions definitions.   ****/
test_func_per_ema(TA_History * history)132 ErrorNumber test_func_per_ema( TA_History *history )
133 {
134    unsigned int i;
135    ErrorNumber retValue;
136 
137    /* Re-initialize all the unstable period to zero. */
138    TA_SetUnstablePeriod( TA_FUNC_UNST_ALL, 0 );
139 
140    for( i=0; i < NB_TEST; i++ )
141    {
142       if( (int)tableTest[i].expectedNbElement > (int)history->nbBars )
143       {
144          printf( "TA_MA Failed Bad Parameter for Test #%d (%d,%d)\n",
145                  i, tableTest[i].expectedNbElement, history->nbBars );
146          return TA_TESTUTIL_TFRR_BAD_PARAM;
147       }
148 
149       retValue = do_test_per_ema( history, &tableTest[i] );
150       if( retValue != 0 )
151       {
152          printf( "TA_MA Failed Test #%d (Code=%d)\n", i, retValue );
153          return retValue;
154       }
155    }
156 
157    /* Re-initialize all the unstable period to zero. */
158    TA_SetUnstablePeriod( TA_FUNC_UNST_ALL, 0 );
159 
160    /* All test succeed. */
161    return TA_TEST_PASS;
162 }
163 
164 /**** 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)165 static TA_RetCode rangeTestFunction( TA_Integer    startIdx,
166                                      TA_Integer    endIdx,
167                                      TA_Real      *outputBuffer,
168                                      TA_Integer   *outputBufferInt,
169                                      TA_Integer   *outBegIdx,
170                                      TA_Integer   *outNbElement,
171                                      TA_Integer   *lookback,
172                                      void         *opaqueData,
173                                      unsigned int  outputNb,
174                                      unsigned int *isOutputInteger )
175 {
176    TA_RetCode retCode;
177    TA_RangeTestParam *testParam;
178 
179    (void)outputNb;
180    (void)outputBufferInt;
181 
182    *isOutputInteger = 0;
183 
184    testParam = (TA_RangeTestParam *)opaqueData;
185 
186    switch( testParam->test->theFunction )
187    {
188    case TA_TRIX_TEST:
189       retCode = TA_TRIX( startIdx,
190                          endIdx,
191                          testParam->close,
192                          testParam->test->optInTimePeriod,
193                          outBegIdx,
194                          outNbElement,
195                          outputBuffer );
196       *lookback = TA_TRIX_Lookback( testParam->test->optInTimePeriod );
197    default:
198       retCode = TA_INTERNAL_ERROR(131);
199    }
200 
201    return retCode;
202 }
203 
do_test_per_ema(const TA_History * history,const TA_Test * test)204 static ErrorNumber do_test_per_ema( const TA_History *history,
205                                     const TA_Test *test )
206 {
207    TA_RetCode retCode;
208    ErrorNumber errNb;
209    TA_Integer outBegIdx;
210    TA_Integer outNbElement;
211    TA_RangeTestParam testParam;
212 
213    /* Set to NAN all the elements of the gBuffers.  */
214    clearAllBuffers();
215 
216    /* Build the input. */
217    setInputBuffer( 0, history->close, history->nbBars );
218    setInputBuffer( 1, history->close, history->nbBars );
219 
220    /* Set the unstable period requested for that test. */
221    retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_EMA, test->unstablePeriod );
222    if( retCode != TA_SUCCESS )
223       return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL;
224 
225    /* Make a simple first call. */
226    switch( test->theFunction )
227    {
228    case TA_TRIX_TEST:
229       retCode = TA_TRIX( test->startIdx,
230                          test->endIdx,
231                          gBuffer[0].in,
232                          test->optInTimePeriod,
233                          &outBegIdx,
234                          &outNbElement,
235                          gBuffer[0].out0 );
236 
237    }
238 
239    errNb = checkDataSame( gBuffer[0].in, history->close,history->nbBars );
240 
241    if( errNb != TA_TEST_PASS )
242       return errNb;
243 
244    errNb = checkExpectedValue( gBuffer[0].out0,
245                                retCode, test->expectedRetCode,
246                                outBegIdx, test->expectedBegIdx,
247                                outNbElement, test->expectedNbElement,
248                                test->oneOfTheExpectedOutReal,
249                                test->oneOfTheExpectedOutRealIndex );
250    if( errNb != TA_TEST_PASS )
251       return errNb;
252 
253    outBegIdx = outNbElement = 0;
254 
255    /* Make another call where the input and the output are the
256     * same buffer.
257     */
258    switch( test->theFunction )
259    {
260    case TA_TRIX_TEST:
261       retCode = TA_TRIX( test->startIdx,
262                          test->endIdx,
263                          gBuffer[1].in,
264                          test->optInTimePeriod,
265                          &outBegIdx,
266                          &outNbElement,
267                          gBuffer[1].in );
268    }
269 
270    /* The previous call to TA_MA should have the same output
271     * as this call.
272     *
273     * checkSameContent verify that all value different than NAN in
274     * the first parameter is identical in the second parameter.
275     */
276    errNb = checkSameContent( gBuffer[0].out0, gBuffer[1].in );
277    if( errNb != TA_TEST_PASS )
278       return errNb;
279 
280    errNb = checkExpectedValue( gBuffer[1].in,
281                                retCode, test->expectedRetCode,
282                                outBegIdx, test->expectedBegIdx,
283                                outNbElement, test->expectedNbElement,
284                                test->oneOfTheExpectedOutReal,
285                                test->oneOfTheExpectedOutRealIndex );
286    if( errNb != TA_TEST_PASS )
287       return errNb;
288 
289    /* Do a systematic test of most of the
290     * possible startIdx/endIdx range.
291     */
292    testParam.test  = test;
293    testParam.close = history->close;
294 
295    if( test->doRangeTestFlag )
296    {
297       errNb = doRangeTest( rangeTestFunction,
298                            TA_FUNC_UNST_EMA,
299                            (void *)&testParam, 1, 0 );
300       if( errNb != TA_TEST_PASS )
301          return errNb;
302    }
303 
304    return TA_TEST_PASS;
305 }
306 
307