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 * AA Andrew Atkinson
40 *
41 * Change history:
42 *
43 * MMDDYY BY Description
44 * -------------------------------------------------------------------
45 * 112400 MF First version.
46 * 020605 MF Add regression test with inverted slow/fast period.
47 * 020805 AA Fix one of the TA_PPO call (wrong buffer was pass).
48 */
49
50 /* Description:
51 * Regression test of APO(Absolute Price Oscillator).
52 * Regression test of PPO (Percentage Price Oscillator).
53 */
54
55 /**** Headers ****/
56 #include <stdio.h>
57 #include <string.h>
58
59 #include "ta_test_priv.h"
60 #include "ta_test_func.h"
61 #include "ta_utility.h"
62
63 /**** External functions declarations. ****/
64 /* None */
65
66 /**** External variables declarations. ****/
67 /* None */
68
69 /**** Global variables definitions. ****/
70 /* None */
71
72 /**** Local declarations. ****/
73 typedef struct
74 {
75 TA_Integer doRangeTestFlag;
76
77 TA_Integer doPercentage;
78
79 TA_Integer startIdx;
80 TA_Integer endIdx;
81
82 TA_Integer optInFastPeriod; /* From 1 to 200 */
83 TA_Integer optInSlowPeriod; /* From 1 to 200 */
84 TA_Integer optInMethod_2;
85 TA_Integer compatibility;
86
87 TA_RetCode expectedRetCode;
88
89 TA_Integer oneOfTheExpectedOutRealIndex;
90 TA_Real oneOfTheExpectedOutReal;
91
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( const TA_History *history,
105 const TA_Test *test );
106
107 /**** Local variables definitions. ****/
108 static TA_Test tableTest[] =
109 {
110 /**********************************/
111 /* APO TEST - SIMPLE - CLASSIC */
112 /**********************************/
113 { 1, 0, 0, 251, 26, 12, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 0, -3.3124, 25, 252-25 }, /* First Value */
114 { 1, 0, 0, 251, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 0, -3.3124, 25, 252-25 }, /* First Value */
115 { 0, 0, 0, 251, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 1, -3.5876, 25, 252-25 },
116 { 0, 0, 0, 251, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 252-26, -0.1667, 25, 252-25 }, /* Last Value */
117
118 { 0, 0, 0, 1, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 0, 0, 0, 0 }, /* Out of range value */
119 { 0, 0, 1, 1, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 0, 0, 0, 0 }, /* Out of range value */
120 { 0, 0, 25, 25, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 0, -3.3124, 25, 1 }, /* First/Last Value */
121 { 0, 0, 250, 251, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 1, -0.1667, 250, 2 }, /* Last Value */
122
123 /************************************/
124 /* APO TEST - SIMPLE - METASTOCK */
125 /************************************/
126 { 0, 0, 0, 251, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, -3.3124, 25, 252-25 }, /* First Value */
127 { 0, 0, 0, 251, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 1, -3.5876, 25, 252-25 },
128 { 0, 0, 0, 251, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 252-26, -0.1667, 25, 252-25 }, /* Last Value */
129
130 { 0, 0, 0, 1, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, 0, 0, 0 }, /* Out of range value */
131 { 0, 0, 1, 1, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, 0, 0, 0 }, /* Out of range value */
132 { 0, 0, 25, 25, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, -3.3124, 25, 1 }, /* First/Last Value */
133 { 0, 0, 250, 251, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 1, -0.1667, 250, 2 }, /* Last Value */
134
135
136 /***************************************/
137 /* APO TEST - EXPONENTIAL - CLASSIC */
138 /***************************************/
139 /* !!! To be done. */
140
141 /*****************************************/
142 /* APO TEST - EXPONENTIAL - METASTOCK */
143 /*****************************************/
144 { 1, 0, 0, 251, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, -2.4193, 25, 252-25 }, /* First Value */
145 { 0, 0, 0, 251, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 1, -2.4367, 25, 252-25 },
146 { 0, 0, 0, 251, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 252-26, 0.90401, 25, 252-25 }, /* Last Value */
147
148 { 0, 0, 0, 1, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, 0, 0, 0 }, /* Out of range value */
149 { 0, 0, 1, 1, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, 0, 0, 0 }, /* Out of range value */
150 { 0, 0, 25, 25, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, -2.4193, 25, 1 },
151 { 0, 0, 250, 251, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 1, 0.90401, 250, 2 }, /* Last Value */
152
153 { 0, 0, 251, 251, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, 0.90401, 251, 1 }, /* Last Value */
154 { 0, 0, 25, 25, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, -2.4193, 25, 1 }, /* Just enough to calculate first. */
155 { 0, 0, 26, 26, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, -2.4367, 26, 1 }, /* Just enough to calculate second. */
156
157 /**********************************/
158 /* PPO TEST - SIMPLE - CLASSIC */
159 /**********************************/
160 { 1, 1, 0, 251, 2, 3, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 0, 1.10264, 2, 252-2 }, /* First Value */
161 { 0, 1, 0, 251, 2, 3, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 1, -0.02813, 2, 252-2 },
162 { 0, 1, 0, 251, 2, 3, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 249, -0.21191, 2, 252-2 }, /* Last Value */
163
164 { 0, 1, 0, 1, 2, 3, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 0, 0, 0, 0 }, /* Out of range value */
165 { 0, 1, 1, 1, 2, 3, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 0, 0, 0, 0 }, /* Out of range value */
166 { 0, 1, 2, 2, 2, 3, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 0, 1.10264, 2, 1 }, /* First/Last Value */
167 { 0, 1, 250, 251, 2, 3, TA_MAType_SMA, TA_COMPATIBILITY_DEFAULT, TA_SUCCESS, 1, -0.21191, 250, 2 }, /* Last Value */
168
169 /************************************/
170 /* PPO TEST - SIMPLE - METASTOCK */
171 /************************************/
172 { 0, 1, 0, 251, 3, 2, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, 1.10264, 2, 252-2 }, /* First Value */
173 { 0, 1, 0, 251, 2, 3, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 1, -0.02813, 2, 252-2 },
174 { 0, 1, 0, 251, 3, 2, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 249, -0.21191, 2, 252-2 }, /* Last Value */
175
176 { 0, 1, 0, 1, 2, 3, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, 0, 0, 0 }, /* Out of range value */
177 { 1, 1, 1, 1, 3, 2, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, 0, 0, 0 }, /* Out of range value */
178 { 1, 1, 2, 2, 2, 3, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, 1.10264, 2, 1 }, /* First/Last Value */
179 { 0, 1, 250, 251, 3, 2, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 1, -0.21191, 250, 2 }, /* Last Value */
180
181 { 0, 1, 0, 251, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, -3.6393, 25, 252-25 }, /* First Value */
182 { 0, 1, 0, 251, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 1, -3.9534, 25, 252-25 },
183 { 0, 1, 0, 251, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 252-26, -0.15281, 25, 252-25 }, /* Last Value */
184
185 { 0, 1, 0, 1, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, 0, 0, 0 }, /* Out of range value */
186 { 0, 1, 1, 1, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, 0, 0, 0 }, /* Out of range value */
187 { 0, 1, 25, 25, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, -3.6393, 25, 1 }, /* First/Last Value */
188 { 0, 1, 250, 251, 12, 26, TA_MAType_SMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 1, -0.15281, 250, 2 }, /* Last Value */
189
190 /***************************************/
191 /* PPO TEST - EXPONENTIAL - CLASSIC */
192 /***************************************/
193 /* !!! To be done. */
194
195 /*****************************************/
196 /* PPO TEST - EXPONENTIAL - METASTOCK */
197 /*****************************************/
198 { 1, 1, 0, 251, 26, 12, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, -2.7083, 25, 252-25 }, /* First Value */
199 { 0, 1, 0, 251, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 1, -2.7390, 25, 252-25 },
200 { 0, 1, 0, 251, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 252-26, 0.83644, 25, 252-25 }, /* Last Value */
201
202 { 0, 1, 0, 1, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, 0, 0, 0 }, /* Out of range value */
203 { 0, 1, 1, 1, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, 0, 0, 0 }, /* Out of range value */
204 { 0, 1, 25, 25, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, -2.7083, 25, 1 },
205 { 0, 1, 250, 251, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 1, 0.83644, 250, 2 }, /* Last Value */
206
207 { 0, 1, 251, 251, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, 0.83644, 251, 1 }, /* Last Value */
208 { 0, 1, 25, 25, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, -2.7083, 25, 1 }, /* Just enough to calculate first. */
209 { 0, 1, 26, 26, 12, 26, TA_MAType_EMA, TA_COMPATIBILITY_METASTOCK, TA_SUCCESS, 0, -2.7390, 26, 1 }, /* Just enough to calculate second. */
210 };
211
212 #define NB_TEST (sizeof(tableTest)/sizeof(TA_Test))
213
214 /**** Global functions definitions. ****/
test_func_po(TA_History * history)215 ErrorNumber test_func_po( TA_History *history )
216 {
217 unsigned int i;
218 ErrorNumber retValue;
219
220 for( i=0; i < NB_TEST; i++ )
221 {
222
223 if( (int)tableTest[i].expectedNbElement > (int)history->nbBars )
224 {
225 printf( "TA_APO/TA_PPO Failed Bad Parameter for Test #%d (%d,%d)\n",
226 i, tableTest[i].expectedNbElement, history->nbBars );
227 return TA_TESTUTIL_TFRR_BAD_PARAM;
228 }
229
230 retValue = do_test( history, &tableTest[i] );
231 if( retValue != 0 )
232 {
233 printf( "TA_APO/TA_PPO Failed Test #%d (Code=%d)\n", i, retValue );
234 return retValue;
235 }
236 }
237
238 /* All test succeed. */
239 return TA_TEST_PASS;
240 }
241
242 /**** 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)243 static TA_RetCode rangeTestFunction( TA_Integer startIdx,
244 TA_Integer endIdx,
245 TA_Real *outputBuffer,
246 TA_Integer *outputBufferInt,
247 TA_Integer *outBegIdx,
248 TA_Integer *outNbElement,
249 TA_Integer *lookback,
250 void *opaqueData,
251 unsigned int outputNb,
252 unsigned int *isOutputInteger )
253 {
254 TA_RetCode retCode;
255 TA_RangeTestParam *testParam;
256
257 (void)outputNb;
258 (void)outputBufferInt;
259
260 *isOutputInteger = 0;
261
262 testParam = (TA_RangeTestParam *)opaqueData;
263
264 if( testParam->test->doPercentage )
265 {
266 retCode = TA_PPO( startIdx,
267 endIdx,
268 testParam->close,
269 testParam->test->optInFastPeriod,
270 testParam->test->optInSlowPeriod,
271 (TA_MAType)testParam->test->optInMethod_2,
272 outBegIdx,
273 outNbElement,
274 outputBuffer );
275
276 *lookback = TA_PPO_Lookback( testParam->test->optInFastPeriod,
277 testParam->test->optInSlowPeriod,
278 (TA_MAType)testParam->test->optInMethod_2 );
279 }
280 else
281 {
282 retCode = TA_APO( startIdx,
283 endIdx,
284 testParam->close,
285 testParam->test->optInFastPeriod,
286 testParam->test->optInSlowPeriod,
287 (TA_MAType)testParam->test->optInMethod_2,
288 outBegIdx,
289 outNbElement,
290 outputBuffer );
291
292
293 *lookback = TA_APO_Lookback( testParam->test->optInFastPeriod,
294 testParam->test->optInSlowPeriod,
295 (TA_MAType)testParam->test->optInMethod_2 );
296 }
297
298 return retCode;
299 }
300
301
do_test(const TA_History * history,const TA_Test * test)302 static ErrorNumber do_test( const TA_History *history,
303 const TA_Test *test )
304 {
305 TA_RetCode retCode;
306 ErrorNumber errNb;
307 TA_Integer outBegIdx;
308 TA_Integer outNbElement;
309
310 TA_RangeTestParam testParam;
311
312 /* Set to NAN all the elements of the gBuffers. */
313 clearAllBuffers();
314
315 TA_SetCompatibility( (TA_Compatibility)test->compatibility );
316
317 /* Build the input. */
318 setInputBuffer( 0, history->close, history->nbBars );
319 setInputBuffer( 1, history->close, history->nbBars );
320
321 TA_SetUnstablePeriod( TA_FUNC_UNST_EMA, 0 );
322
323 /* Make a simple first call. */
324 if( test->doPercentage )
325 {
326 retCode = TA_PPO( test->startIdx,
327 test->endIdx,
328 gBuffer[0].in,
329 test->optInFastPeriod,
330 test->optInSlowPeriod,
331 (TA_MAType)test->optInMethod_2,
332 &outBegIdx,
333 &outNbElement,
334 gBuffer[0].out0 );
335 }
336 else
337 {
338 retCode = TA_APO( test->startIdx,
339 test->endIdx,
340 gBuffer[0].in,
341 test->optInFastPeriod,
342 test->optInSlowPeriod,
343 (TA_MAType)test->optInMethod_2,
344 &outBegIdx,
345 &outNbElement,
346 gBuffer[0].out0 );
347 }
348
349 errNb = checkDataSame( gBuffer[0].in, history->close, history->nbBars );
350 if( errNb != TA_TEST_PASS )
351 return errNb;
352
353 errNb = checkExpectedValue( gBuffer[0].out0,
354 retCode, test->expectedRetCode,
355 outBegIdx, test->expectedBegIdx,
356 outNbElement, test->expectedNbElement,
357 test->oneOfTheExpectedOutReal,
358 test->oneOfTheExpectedOutRealIndex );
359 if( errNb != TA_TEST_PASS )
360 return errNb;
361
362 outBegIdx = outNbElement = 0;
363
364 /* Make another call where the input and the output are the
365 * same buffer.
366 */
367 if( test->doPercentage )
368 {
369 retCode = TA_PPO( test->startIdx,
370 test->endIdx,
371 gBuffer[1].in,
372 test->optInFastPeriod,
373 test->optInSlowPeriod,
374 (TA_MAType)test->optInMethod_2,
375 &outBegIdx,
376 &outNbElement,
377 gBuffer[1].in );
378 }
379 else
380 {
381 retCode = TA_APO( test->startIdx,
382 test->endIdx,
383 gBuffer[1].in,
384 test->optInFastPeriod,
385 test->optInSlowPeriod,
386 (TA_MAType)test->optInMethod_2,
387 &outBegIdx,
388 &outNbElement,
389 gBuffer[1].in );
390 }
391
392 /* The previous call should have the same output
393 * as this call.
394 *
395 * checkSameContent verify that all value different than NAN in
396 * the first parameter is identical in the second parameter.
397 */
398 errNb = checkSameContent( gBuffer[0].out0, gBuffer[1].in );
399 if( errNb != TA_TEST_PASS )
400 return errNb;
401
402 errNb = checkExpectedValue( gBuffer[1].in,
403 retCode, test->expectedRetCode,
404 outBegIdx, test->expectedBegIdx,
405 outNbElement, test->expectedNbElement,
406 test->oneOfTheExpectedOutReal,
407 test->oneOfTheExpectedOutRealIndex );
408 if( errNb != TA_TEST_PASS )
409 return errNb;
410
411 /* Do a systematic test of most of the
412 * possible startIdx/endIdx range.
413 */
414 testParam.test = test;
415 testParam.close = history->close;
416
417 if( test->doRangeTestFlag )
418 {
419
420 if( test->optInMethod_2 == TA_MAType_EMA )
421 {
422 errNb = doRangeTest( rangeTestFunction,
423 TA_FUNC_UNST_EMA,
424 (void *)&testParam, 1, 0 );
425 if( errNb != TA_TEST_PASS )
426 return errNb;
427 }
428 else
429 {
430 errNb = doRangeTest( rangeTestFunction,
431 TA_FUNC_UNST_NONE,
432 (void *)&testParam, 1, 0 );
433 if( errNb != TA_TEST_PASS )
434 return errNb;
435 }
436 }
437
438 return TA_TEST_PASS;
439 }
440
441