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  *  120802 MF   Template creation.
46  *  023003 MF   Initial Coding of MAMA.
47  *  052603 MF   Adapt code to compile with .NET Managed C++
48  *
49  */
50 
51 /**** START GENCODE SECTION 1 - DO NOT DELETE THIS LINE ****/
52 /* All code within this section is automatically
53  * generated by gen_code. Any modification will be lost
54  * next time gen_code is run.
55  */
56 /* Generated */
57 /* Generated */ #if defined( _MANAGED )
58 /* Generated */    #include "TA-Lib-Core.h"
59 /* Generated */    #define TA_INTERNAL_ERROR(Id) (RetCode::InternalError)
60 /* Generated */    namespace TicTacTec { namespace TA { namespace Library {
61 /* Generated */ #elif defined( _JAVA )
62 /* Generated */    #include "ta_defs.h"
63 /* Generated */    #include "ta_java_defs.h"
64 /* Generated */    #define TA_INTERNAL_ERROR(Id) (RetCode.InternalError)
65 /* Generated */ #else
66 /* Generated */    #include <string.h>
67 /* Generated */    #include <math.h>
68 /* Generated */    #include "ta_func.h"
69 /* Generated */ #endif
70 /* Generated */
71 /* Generated */ #ifndef TA_UTILITY_H
72 /* Generated */    #include "ta_utility.h"
73 /* Generated */ #endif
74 /* Generated */
75 /* Generated */ #ifndef TA_MEMORY_H
76 /* Generated */    #include "ta_memory.h"
77 /* Generated */ #endif
78 /* Generated */
79 /* Generated */ #define TA_PREFIX(x) TA_##x
80 /* Generated */ #define INPUT_TYPE   double
81 /* Generated */
82 /* Generated */ #if defined( _MANAGED )
MamaLookback(double optInFastLimit,double optInSlowLimit)83 /* Generated */ int Core::MamaLookback( double        optInFastLimit, /* From 0.01 to 0.99 */
84 /* Generated */                       double        optInSlowLimit )  /* From 0.01 to 0.99 */
85 /* Generated */
86 /* Generated */ #elif defined( _JAVA )
87 /* Generated */ public int mamaLookback( double        optInFastLimit, /* From 0.01 to 0.99 */
88 /* Generated */                        double        optInSlowLimit )  /* From 0.01 to 0.99 */
89 /* Generated */
90 /* Generated */ #else
91 /* Generated */ int TA_MAMA_Lookback( double        optInFastLimit, /* From 0.01 to 0.99 */
92 /* Generated */                     double        optInSlowLimit )  /* From 0.01 to 0.99 */
93 /* Generated */
94 /* Generated */ #endif
95 /**** END GENCODE SECTION 1 - DO NOT DELETE THIS LINE ****/
96 {
97    /* insert local variable here */
98 
99 /**** START GENCODE SECTION 2 - DO NOT DELETE THIS LINE ****/
100 /* Generated */ #ifndef TA_FUNC_NO_RANGE_CHECK
101 /* Generated */    if( optInFastLimit == TA_REAL_DEFAULT )
102 /* Generated */       optInFastLimit = 5.000000e-1;
103 /* Generated */    else if( (optInFastLimit < 1.000000e-2) ||/* Generated */  (optInFastLimit > 9.900000e-1) )
104 /* Generated */       return -1;
105 /* Generated */
106 /* Generated */    if( optInSlowLimit == TA_REAL_DEFAULT )
107 /* Generated */       optInSlowLimit = 5.000000e-2;
108 /* Generated */    else if( (optInSlowLimit < 1.000000e-2) ||/* Generated */  (optInSlowLimit > 9.900000e-1) )
109 /* Generated */       return -1;
110 /* Generated */
111 /* Generated */ #endif /* TA_FUNC_NO_RANGE_CHECK */
112 /**** END GENCODE SECTION 2 - DO NOT DELETE THIS LINE ****/
113 
114    /* insert lookback code here. */
115 
116    /* The two parameters are not a factor to determine
117     * the lookback, but are still requested for
118     * consistency with all other Lookback functions.
119     */
120    UNUSED_VARIABLE(optInFastLimit);
121    UNUSED_VARIABLE(optInSlowLimit);
122 
123    /* Lookback is a fix amount + the unstable period.
124     *
125     *
126     * The fix lookback is 32 and is establish as follow:
127     *
128     *         12 price bar to be compatible with the implementation
129     *            of TradeStation found in John Ehlers book.
130     *          6 price bars for the Detrender
131     *          6 price bars for Q1
132     *          3 price bars for jI
133     *          3 price bars for jQ
134     *          1 price bar for Re/Im
135     *          1 price bar for the Delta Phase
136     *        -------
137     *         32 Total
138     */
139 
140    return 32 + TA_GLOBALS_UNSTABLE_PERIOD(TA_FUNC_UNST_MAMA,Mama);
141 }
142 
143 /**** START GENCODE SECTION 3 - DO NOT DELETE THIS LINE ****/
144 /*
145  * TA_MAMA - MESA Adaptive Moving Average
146  *
147  * Input  = double
148  * Output = double, double
149  *
150  * Optional Parameters
151  * -------------------
152  * optInFastLimit:(From 0.01 to 0.99)
153  *    Upper limit use in the adaptive algorithm
154  *
155  * optInSlowLimit:(From 0.01 to 0.99)
156  *    Lower limit use in the adaptive algorithm
157  *
158  *
159  */
160 /* Generated */
161 /* Generated */ #if defined( _MANAGED ) && defined( USE_SUBARRAY )
162 /* Generated */ enum class Core::RetCode Core::Mama( int    startIdx,
163 /* Generated */                                      int    endIdx,
164 /* Generated */                                      SubArray^    inReal,
165 /* Generated */                                      double        optInFastLimit, /* From 0.01 to 0.99 */
166 /* Generated */                                      double        optInSlowLimit, /* From 0.01 to 0.99 */
167 /* Generated */                                      [Out]int%    outBegIdx,
168 /* Generated */                                      [Out]int%    outNBElement,
169 /* Generated */                                      cli::array<double>^  outMAMA,
170 /* Generated */                                      cli::array<double>^  outFAMA )
171 /* Generated */ #elif defined( _MANAGED )
172 /* Generated */ enum class Core::RetCode Core::Mama( int    startIdx,
173 /* Generated */                                      int    endIdx,
174 /* Generated */                                      cli::array<double>^ inReal,
175 /* Generated */                                      double        optInFastLimit, /* From 0.01 to 0.99 */
176 /* Generated */                                      double        optInSlowLimit, /* From 0.01 to 0.99 */
177 /* Generated */                                      [Out]int%    outBegIdx,
178 /* Generated */                                      [Out]int%    outNBElement,
179 /* Generated */                                      cli::array<double>^  outMAMA,
180 /* Generated */                                      cli::array<double>^  outFAMA )
181 /* Generated */ #elif defined( _JAVA )
182 /* Generated */ public RetCode mama( int    startIdx,
183 /* Generated */                      int    endIdx,
184 /* Generated */                      double       inReal[],
185 /* Generated */                      double        optInFastLimit, /* From 0.01 to 0.99 */
186 /* Generated */                      double        optInSlowLimit, /* From 0.01 to 0.99 */
187 /* Generated */                      MInteger     outBegIdx,
188 /* Generated */                      MInteger     outNBElement,
189 /* Generated */                      double        outMAMA[],
190 /* Generated */                      double        outFAMA[] )
191 /* Generated */ #else
192 /* Generated */ TA_RetCode TA_MAMA( int    startIdx,
193 /* Generated */                     int    endIdx,
194 /* Generated */                     const double inReal[],
195 /* Generated */                     double        optInFastLimit, /* From 0.01 to 0.99 */
196 /* Generated */                     double        optInSlowLimit, /* From 0.01 to 0.99 */
197 /* Generated */                     int          *outBegIdx,
198 /* Generated */                     int          *outNBElement,
199 /* Generated */                     double        outMAMA[],
200 /* Generated */                     double        outFAMA[] )
201 /* Generated */ #endif
202 /**** END GENCODE SECTION 3 - DO NOT DELETE THIS LINE ****/
203 {
204 	/* insert local variable here */
205 
206    int outIdx, i;
207    int lookbackTotal, today;
208    double tempReal, tempReal2;
209 
210    double adjustedPrevPeriod, period;
211 
212    /* Variable used for the price smoother (a weighted moving average). */
213    int trailingWMAIdx;
214    double periodWMASum, periodWMASub, trailingWMAValue;
215    double smoothedValue;
216 
217    /* Variables used for the Hilbert Transormation */
218    CONSTANT_DOUBLE(a) = 0.0962;
219    CONSTANT_DOUBLE(b) = 0.5769;
220    double hilbertTempReal;
221    int hilbertIdx;
222 
223    HILBERT_VARIABLES( detrender );
224    HILBERT_VARIABLES( Q1 );
225    HILBERT_VARIABLES( jI );
226    HILBERT_VARIABLES( jQ );
227 
228    double Q2, I2, prevQ2, prevI2, Re, Im;
229 
230    double I1ForOddPrev2,  I1ForOddPrev3;
231    double I1ForEvenPrev2, I1ForEvenPrev3;
232 
233    double rad2Deg;
234 
235    double mama,fama,todayValue,prevPhase;
236 
237 /**** START GENCODE SECTION 4 - DO NOT DELETE THIS LINE ****/
238 /* Generated */
239 /* Generated */ #ifndef TA_FUNC_NO_RANGE_CHECK
240 /* Generated */
241 /* Generated */    /* Validate the requested output range. */
242 /* Generated */    if( startIdx < 0 )
243 /* Generated */       return ENUM_VALUE(RetCode,TA_OUT_OF_RANGE_START_INDEX,OutOfRangeStartIndex);
244 /* Generated */    if( (endIdx < 0) || (endIdx < startIdx))
245 /* Generated */       return ENUM_VALUE(RetCode,TA_OUT_OF_RANGE_END_INDEX,OutOfRangeEndIndex);
246 /* Generated */
247 /* Generated */    #if !defined(_JAVA)
248 /* Generated */    if( !inReal ) return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
249 /* Generated */    #endif /* !defined(_JAVA)*/
250 /* Generated */    if( optInFastLimit == TA_REAL_DEFAULT )
251 /* Generated */       optInFastLimit = 5.000000e-1;
252 /* Generated */    else if( (optInFastLimit < 1.000000e-2) ||/* Generated */  (optInFastLimit > 9.900000e-1) )
253 /* Generated */       return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
254 /* Generated */
255 /* Generated */    if( optInSlowLimit == TA_REAL_DEFAULT )
256 /* Generated */       optInSlowLimit = 5.000000e-2;
257 /* Generated */    else if( (optInSlowLimit < 1.000000e-2) ||/* Generated */  (optInSlowLimit > 9.900000e-1) )
258 /* Generated */       return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
259 /* Generated */
260 /* Generated */    #if !defined(_JAVA)
261 /* Generated */    if( !outMAMA )
262 /* Generated */       return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
263 /* Generated */
264 /* Generated */    if( !outFAMA )
265 /* Generated */       return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
266 /* Generated */
267 /* Generated */    #endif /* !defined(_JAVA) */
268 /* Generated */ #endif /* TA_FUNC_NO_RANGE_CHECK */
269 /* Generated */
270 /**** END GENCODE SECTION 4 - DO NOT DELETE THIS LINE ****/
271 
272    /* Insert TA function code here. */
273 
274    /* Constant */
275    rad2Deg = 180.0 / (4.0 * std_atan(1));
276 
277    /* Identify the minimum number of price bar needed
278     * to calculate at least one output.
279     */
280    lookbackTotal = 32 + TA_GLOBALS_UNSTABLE_PERIOD(TA_FUNC_UNST_MAMA,Mama);
281 
282    /* Move up the start index if there is not
283     * enough initial data.
284     */
285    if( startIdx < lookbackTotal )
286       startIdx = lookbackTotal;
287 
288    /* Make sure there is still something to evaluate. */
289    if( startIdx > endIdx )
290    {
291       VALUE_HANDLE_DEREF_TO_ZERO(outBegIdx);
292       VALUE_HANDLE_DEREF_TO_ZERO(outNBElement);
293       return ENUM_VALUE(RetCode,TA_SUCCESS,Success);
294    }
295 
296    VALUE_HANDLE_DEREF(outBegIdx) = startIdx;
297 
298    /* Initialize the price smoother, which is simply a weighted
299     * moving average of the price.
300     * To understand this algorithm, I strongly suggest to understand
301     * first how TA_WMA is done.
302     */
303    trailingWMAIdx = startIdx - lookbackTotal;
304    today = trailingWMAIdx;
305 
306    /* Initialization is same as WMA, except loop is unrolled
307     * for speed optimization.
308     */
309    tempReal = inReal[today++];
310    periodWMASub = tempReal;
311    periodWMASum = tempReal;
312    tempReal = inReal[today++];
313    periodWMASub += tempReal;
314    periodWMASum += tempReal*2.0;
315    tempReal = inReal[today++];
316    periodWMASub += tempReal;
317    periodWMASum += tempReal*3.0;
318 
319    trailingWMAValue = 0.0;
320 
321    /* Subsequent WMA value are evaluated by using
322     * the DO_PRICE_WMA macro.
323     */
324    #define DO_PRICE_WMA(varNewPrice,varToStoreSmoothedValue) { \
325       periodWMASub     += varNewPrice; \
326       periodWMASub     -= trailingWMAValue; \
327       periodWMASum     += varNewPrice*4.0; \
328       trailingWMAValue  = inReal[trailingWMAIdx++]; \
329       varToStoreSmoothedValue = periodWMASum*0.1; \
330       periodWMASum -= periodWMASub; \
331    }
332 
333    i = 9;
334    do
335    {
336       tempReal = inReal[today++];
337       DO_PRICE_WMA(tempReal,smoothedValue);
338    } while( --i != 0);
339 
340    /* Initialize the circular buffers used by the hilbert
341     * transform logic.
342     * A buffer is used for odd day and another for even days.
343     * This minimize the number of memory access and floating point
344     * operations needed (note also that by using static circular buffer,
345     * no large dynamic memory allocation is needed for storing
346     * intermediate calculation!).
347     */
348    hilbertIdx = 0;
349 
350    INIT_HILBERT_VARIABLES(detrender);
351    INIT_HILBERT_VARIABLES(Q1);
352    INIT_HILBERT_VARIABLES(jI);
353    INIT_HILBERT_VARIABLES(jQ);
354 
355    period = 0.0;
356    outIdx = 0;
357 
358    prevI2 = prevQ2 = 0.0;
359    Re     = Im     = 0.0;
360    mama   = fama   = 0.0;
361    I1ForOddPrev3 = I1ForEvenPrev3 = 0.0;
362    I1ForOddPrev2 = I1ForEvenPrev2 = 0.0;
363 
364    prevPhase  = 0.0;
365 
366    /* The code is speed optimized and is most likely very
367     * hard to follow if you do not already know well the
368     * original algorithm.
369     * To understadn better, it is strongly suggested to look
370     * first at the Excel implementation in "test_MAMA.xls" included
371     * in this package.
372     */
373    while( today <= endIdx )
374    {
375       adjustedPrevPeriod = (0.075*period)+0.54;
376 
377       todayValue = inReal[today];
378       DO_PRICE_WMA(todayValue,smoothedValue);
379 
380       if( (today%2) == 0 )
381       {
382          /* Do the Hilbert Transforms for even price bar */
383          DO_HILBERT_EVEN(detrender,smoothedValue);
384          DO_HILBERT_EVEN(Q1,detrender);
385          DO_HILBERT_EVEN(jI,I1ForEvenPrev3);
386          DO_HILBERT_EVEN(jQ,Q1);
387          if( ++hilbertIdx == 3 )
388             hilbertIdx = 0;
389 
390          Q2 = (0.2*(Q1 + jI)) + (0.8*prevQ2);
391          I2 = (0.2*(I1ForEvenPrev3 - jQ)) + (0.8*prevI2);
392 
393          /* The variable I1 is the detrender delayed for
394           * 3 price bars.
395           *
396           * Save the current detrender value for being
397           * used by the "odd" logic later.
398           */
399          I1ForOddPrev3 = I1ForOddPrev2;
400          I1ForOddPrev2 = detrender;
401 
402          /* Put Alpha in tempReal2 */
403          if( I1ForEvenPrev3 != 0.0 )
404             tempReal2 = (std_atan(Q1/I1ForEvenPrev3)*rad2Deg);
405          else
406             tempReal2 = 0.0;
407       }
408       else
409       {
410          /* Do the Hilbert Transforms for odd price bar */
411          DO_HILBERT_ODD(detrender,smoothedValue);
412          DO_HILBERT_ODD(Q1,detrender);
413          DO_HILBERT_ODD(jI,I1ForOddPrev3);
414          DO_HILBERT_ODD(jQ,Q1);
415 
416          Q2 = (0.2*(Q1 + jI)) + (0.8*prevQ2);
417          I2 = (0.2*(I1ForOddPrev3 - jQ)) + (0.8*prevI2);
418 
419          /* The varaiable I1 is the detrender delayed for
420           * 3 price bars.
421           *
422           * Save the current detrender value for being
423           * used by the "odd" logic later.
424           */
425          I1ForEvenPrev3 = I1ForEvenPrev2;
426          I1ForEvenPrev2 = detrender;
427 
428          /* Put Alpha in tempReal2 */
429          if( I1ForOddPrev3 != 0.0 )
430             tempReal2 = (std_atan(Q1/I1ForOddPrev3)*rad2Deg);
431          else
432             tempReal2 = 0.0;
433       }
434 
435       /* Put Delta Phase into tempReal */
436       tempReal  = prevPhase - tempReal2;
437       prevPhase = tempReal2;
438       if( tempReal < 1.0 )
439          tempReal = 1.0;
440 
441       /* Put Alpha into tempReal */
442       if( tempReal > 1.0 )
443       {
444          tempReal = optInFastLimit/tempReal;
445          if( tempReal < optInSlowLimit )
446             tempReal = optInSlowLimit;
447       }
448       else
449       {
450          tempReal = optInFastLimit;
451       }
452 
453       /* Calculate MAMA, FAMA */
454       mama = (tempReal*todayValue)+((1-tempReal)*mama);
455       tempReal *= 0.5;
456       fama = (tempReal*mama)+((1-tempReal)*fama);
457       if( today >= startIdx )
458       {
459          outMAMA[outIdx] = mama;
460          outFAMA[outIdx++] = fama;
461       }
462 
463       /* Adjust the period for next price bar */
464       Re = (0.2*((I2*prevI2)+(Q2*prevQ2)))+(0.8*Re);
465       Im = (0.2*((I2*prevQ2)-(Q2*prevI2)))+(0.8*Im);
466       prevQ2 = Q2;
467       prevI2 = I2;
468       tempReal = period;
469       if( (Im != 0.0) && (Re != 0.0) )
470          period = 360.0 / (std_atan(Im/Re)*rad2Deg);
471       tempReal2 = 1.5*tempReal;
472       if( period > tempReal2)
473          period = tempReal2;
474       tempReal2 = 0.67*tempReal;
475       if( period < tempReal2 )
476          period = tempReal2;
477       if( period < 6 )
478          period = 6;
479       else if( period > 50 )
480          period = 50;
481       period = (0.2*period) + (0.8 * tempReal);
482 
483       /* Ooof... let's do the next price bar now! */
484       today++;
485    }
486 
487    /* Default return values */
488    VALUE_HANDLE_DEREF(outNBElement) = outIdx;
489 
490    return ENUM_VALUE(RetCode,TA_SUCCESS,Success);
491 }
492 
493 /**** START GENCODE SECTION 5 - DO NOT DELETE THIS LINE ****/
494 /* Generated */
495 /* Generated */ #define  USE_SINGLE_PRECISION_INPUT
496 /* Generated */ #if !defined( _MANAGED ) && !defined( _JAVA )
497 /* Generated */    #undef   TA_PREFIX
498 /* Generated */    #define  TA_PREFIX(x) TA_S_##x
499 /* Generated */ #endif
500 /* Generated */ #undef   INPUT_TYPE
501 /* Generated */ #define  INPUT_TYPE float
502 /* Generated */ #if defined( _MANAGED )
503 /* Generated */ enum class Core::RetCode Core::Mama( int    startIdx,
504 /* Generated */                                      int    endIdx,
505 /* Generated */                                      cli::array<float>^ inReal,
506 /* Generated */                                      double        optInFastLimit, /* From 0.01 to 0.99 */
507 /* Generated */                                      double        optInSlowLimit, /* From 0.01 to 0.99 */
508 /* Generated */                                      [Out]int%    outBegIdx,
509 /* Generated */                                      [Out]int%    outNBElement,
510 /* Generated */                                      cli::array<double>^  outMAMA,
511 /* Generated */                                      cli::array<double>^  outFAMA )
512 /* Generated */ #elif defined( _JAVA )
513 /* Generated */ public RetCode mama( int    startIdx,
514 /* Generated */                      int    endIdx,
515 /* Generated */                      float        inReal[],
516 /* Generated */                      double        optInFastLimit, /* From 0.01 to 0.99 */
517 /* Generated */                      double        optInSlowLimit, /* From 0.01 to 0.99 */
518 /* Generated */                      MInteger     outBegIdx,
519 /* Generated */                      MInteger     outNBElement,
520 /* Generated */                      double        outMAMA[],
521 /* Generated */                      double        outFAMA[] )
522 /* Generated */ #else
523 /* Generated */ TA_RetCode TA_S_MAMA( int    startIdx,
524 /* Generated */                       int    endIdx,
525 /* Generated */                       const float  inReal[],
526 /* Generated */                       double        optInFastLimit, /* From 0.01 to 0.99 */
527 /* Generated */                       double        optInSlowLimit, /* From 0.01 to 0.99 */
528 /* Generated */                       int          *outBegIdx,
529 /* Generated */                       int          *outNBElement,
530 /* Generated */                       double        outMAMA[],
531 /* Generated */                       double        outFAMA[] )
532 /* Generated */ #endif
533 /* Generated */ {
534 /* Generated */    int outIdx, i;
535 /* Generated */    int lookbackTotal, today;
536 /* Generated */    double tempReal, tempReal2;
537 /* Generated */    double adjustedPrevPeriod, period;
538 /* Generated */    int trailingWMAIdx;
539 /* Generated */    double periodWMASum, periodWMASub, trailingWMAValue;
540 /* Generated */    double smoothedValue;
541 /* Generated */    CONSTANT_DOUBLE(a) = 0.0962;
542 /* Generated */    CONSTANT_DOUBLE(b) = 0.5769;
543 /* Generated */    double hilbertTempReal;
544 /* Generated */    int hilbertIdx;
545 /* Generated */    HILBERT_VARIABLES( detrender );
546 /* Generated */    HILBERT_VARIABLES( Q1 );
547 /* Generated */    HILBERT_VARIABLES( jI );
548 /* Generated */    HILBERT_VARIABLES( jQ );
549 /* Generated */    double Q2, I2, prevQ2, prevI2, Re, Im;
550 /* Generated */    double I1ForOddPrev2,  I1ForOddPrev3;
551 /* Generated */    double I1ForEvenPrev2, I1ForEvenPrev3;
552 /* Generated */    double rad2Deg;
553 /* Generated */    double mama,fama,todayValue,prevPhase;
554 /* Generated */  #ifndef TA_FUNC_NO_RANGE_CHECK
555 /* Generated */     if( startIdx < 0 )
556 /* Generated */        return ENUM_VALUE(RetCode,TA_OUT_OF_RANGE_START_INDEX,OutOfRangeStartIndex);
557 /* Generated */     if( (endIdx < 0) || (endIdx < startIdx))
558 /* Generated */        return ENUM_VALUE(RetCode,TA_OUT_OF_RANGE_END_INDEX,OutOfRangeEndIndex);
559 /* Generated */     #if !defined(_JAVA)
560 /* Generated */     if( !inReal ) return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
561 /* Generated */     #endif
562 /* Generated */     if( optInFastLimit == TA_REAL_DEFAULT )
563 /* Generated */        optInFastLimit = 5.000000e-1;
564 /* Generated */     else if( (optInFastLimit < 1.000000e-2) ||  (optInFastLimit > 9.900000e-1) )
565 /* Generated */        return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
566 /* Generated */     if( optInSlowLimit == TA_REAL_DEFAULT )
567 /* Generated */        optInSlowLimit = 5.000000e-2;
568 /* Generated */     else if( (optInSlowLimit < 1.000000e-2) ||  (optInSlowLimit > 9.900000e-1) )
569 /* Generated */        return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
570 /* Generated */     #if !defined(_JAVA)
571 /* Generated */     if( !outMAMA )
572 /* Generated */        return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
573 /* Generated */     if( !outFAMA )
574 /* Generated */        return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
575 /* Generated */     #endif
576 /* Generated */  #endif
577 /* Generated */    rad2Deg = 180.0 / (4.0 * std_atan(1));
578 /* Generated */    lookbackTotal = 32 + TA_GLOBALS_UNSTABLE_PERIOD(TA_FUNC_UNST_MAMA,Mama);
579 /* Generated */    if( startIdx < lookbackTotal )
580 /* Generated */       startIdx = lookbackTotal;
581 /* Generated */    if( startIdx > endIdx )
582 /* Generated */    {
583 /* Generated */       VALUE_HANDLE_DEREF_TO_ZERO(outBegIdx);
584 /* Generated */       VALUE_HANDLE_DEREF_TO_ZERO(outNBElement);
585 /* Generated */       return ENUM_VALUE(RetCode,TA_SUCCESS,Success);
586 /* Generated */    }
587 /* Generated */    VALUE_HANDLE_DEREF(outBegIdx) = startIdx;
588 /* Generated */    trailingWMAIdx = startIdx - lookbackTotal;
589 /* Generated */    today = trailingWMAIdx;
590 /* Generated */    tempReal = inReal[today++];
591 /* Generated */    periodWMASub = tempReal;
592 /* Generated */    periodWMASum = tempReal;
593 /* Generated */    tempReal = inReal[today++];
594 /* Generated */    periodWMASub += tempReal;
595 /* Generated */    periodWMASum += tempReal*2.0;
596 /* Generated */    tempReal = inReal[today++];
597 /* Generated */    periodWMASub += tempReal;
598 /* Generated */    periodWMASum += tempReal*3.0;
599 /* Generated */    trailingWMAValue = 0.0;
600 /* Generated */    #define DO_PRICE_WMA(varNewPrice,varToStoreSmoothedValue) { \
601 /* Generated */       periodWMASub     += varNewPrice; \
602 /* Generated */       periodWMASub     -= trailingWMAValue; \
603 /* Generated */       periodWMASum     += varNewPrice*4.0; \
604 /* Generated */       trailingWMAValue  = inReal[trailingWMAIdx++]; \
605 /* Generated */       varToStoreSmoothedValue = periodWMASum*0.1; \
606 /* Generated */       periodWMASum -= periodWMASub; \
607 /* Generated */    }
608 /* Generated */    i = 9;
609 /* Generated */    do
610 /* Generated */    {
611 /* Generated */       tempReal = inReal[today++];
612 /* Generated */       DO_PRICE_WMA(tempReal,smoothedValue);
613 /* Generated */    } while( --i != 0);
614 /* Generated */    hilbertIdx = 0;
615 /* Generated */    INIT_HILBERT_VARIABLES(detrender);
616 /* Generated */    INIT_HILBERT_VARIABLES(Q1);
617 /* Generated */    INIT_HILBERT_VARIABLES(jI);
618 /* Generated */    INIT_HILBERT_VARIABLES(jQ);
619 /* Generated */    period = 0.0;
620 /* Generated */    outIdx = 0;
621 /* Generated */    prevI2 = prevQ2 = 0.0;
622 /* Generated */    Re     = Im     = 0.0;
623 /* Generated */    mama   = fama   = 0.0;
624 /* Generated */    I1ForOddPrev3 = I1ForEvenPrev3 = 0.0;
625 /* Generated */    I1ForOddPrev2 = I1ForEvenPrev2 = 0.0;
626 /* Generated */    prevPhase  = 0.0;
627 /* Generated */    while( today <= endIdx )
628 /* Generated */    {
629 /* Generated */       adjustedPrevPeriod = (0.075*period)+0.54;
630 /* Generated */       todayValue = inReal[today];
631 /* Generated */       DO_PRICE_WMA(todayValue,smoothedValue);
632 /* Generated */       if( (today%2) == 0 )
633 /* Generated */       {
634 /* Generated */          DO_HILBERT_EVEN(detrender,smoothedValue);
635 /* Generated */          DO_HILBERT_EVEN(Q1,detrender);
636 /* Generated */          DO_HILBERT_EVEN(jI,I1ForEvenPrev3);
637 /* Generated */          DO_HILBERT_EVEN(jQ,Q1);
638 /* Generated */          if( ++hilbertIdx == 3 )
639 /* Generated */             hilbertIdx = 0;
640 /* Generated */          Q2 = (0.2*(Q1 + jI)) + (0.8*prevQ2);
641 /* Generated */          I2 = (0.2*(I1ForEvenPrev3 - jQ)) + (0.8*prevI2);
642 /* Generated */          I1ForOddPrev3 = I1ForOddPrev2;
643 /* Generated */          I1ForOddPrev2 = detrender;
644 /* Generated */          if( I1ForEvenPrev3 != 0.0 )
645 /* Generated */             tempReal2 = (std_atan(Q1/I1ForEvenPrev3)*rad2Deg);
646 /* Generated */          else
647 /* Generated */             tempReal2 = 0.0;
648 /* Generated */       }
649 /* Generated */       else
650 /* Generated */       {
651 /* Generated */          DO_HILBERT_ODD(detrender,smoothedValue);
652 /* Generated */          DO_HILBERT_ODD(Q1,detrender);
653 /* Generated */          DO_HILBERT_ODD(jI,I1ForOddPrev3);
654 /* Generated */          DO_HILBERT_ODD(jQ,Q1);
655 /* Generated */          Q2 = (0.2*(Q1 + jI)) + (0.8*prevQ2);
656 /* Generated */          I2 = (0.2*(I1ForOddPrev3 - jQ)) + (0.8*prevI2);
657 /* Generated */          I1ForEvenPrev3 = I1ForEvenPrev2;
658 /* Generated */          I1ForEvenPrev2 = detrender;
659 /* Generated */          if( I1ForOddPrev3 != 0.0 )
660 /* Generated */             tempReal2 = (std_atan(Q1/I1ForOddPrev3)*rad2Deg);
661 /* Generated */          else
662 /* Generated */             tempReal2 = 0.0;
663 /* Generated */       }
664 /* Generated */       tempReal  = prevPhase - tempReal2;
665 /* Generated */       prevPhase = tempReal2;
666 /* Generated */       if( tempReal < 1.0 )
667 /* Generated */          tempReal = 1.0;
668 /* Generated */       if( tempReal > 1.0 )
669 /* Generated */       {
670 /* Generated */          tempReal = optInFastLimit/tempReal;
671 /* Generated */          if( tempReal < optInSlowLimit )
672 /* Generated */             tempReal = optInSlowLimit;
673 /* Generated */       }
674 /* Generated */       else
675 /* Generated */       {
676 /* Generated */          tempReal = optInFastLimit;
677 /* Generated */       }
678 /* Generated */       mama = (tempReal*todayValue)+((1-tempReal)*mama);
679 /* Generated */       tempReal *= 0.5;
680 /* Generated */       fama = (tempReal*mama)+((1-tempReal)*fama);
681 /* Generated */       if( today >= startIdx )
682 /* Generated */       {
683 /* Generated */          outMAMA[outIdx] = mama;
684 /* Generated */          outFAMA[outIdx++] = fama;
685 /* Generated */       }
686 /* Generated */       Re = (0.2*((I2*prevI2)+(Q2*prevQ2)))+(0.8*Re);
687 /* Generated */       Im = (0.2*((I2*prevQ2)-(Q2*prevI2)))+(0.8*Im);
688 /* Generated */       prevQ2 = Q2;
689 /* Generated */       prevI2 = I2;
690 /* Generated */       tempReal = period;
691 /* Generated */       if( (Im != 0.0) && (Re != 0.0) )
692 /* Generated */          period = 360.0 / (std_atan(Im/Re)*rad2Deg);
693 /* Generated */       tempReal2 = 1.5*tempReal;
694 /* Generated */       if( period > tempReal2)
695 /* Generated */          period = tempReal2;
696 /* Generated */       tempReal2 = 0.67*tempReal;
697 /* Generated */       if( period < tempReal2 )
698 /* Generated */          period = tempReal2;
699 /* Generated */       if( period < 6 )
700 /* Generated */          period = 6;
701 /* Generated */       else if( period > 50 )
702 /* Generated */          period = 50;
703 /* Generated */       period = (0.2*period) + (0.8 * tempReal);
704 /* Generated */       today++;
705 /* Generated */    }
706 /* Generated */    VALUE_HANDLE_DEREF(outNBElement) = outIdx;
707 /* Generated */    return ENUM_VALUE(RetCode,TA_SUCCESS,Success);
708 /* Generated */ }
709 /* Generated */
710 /* Generated */ #if defined( _MANAGED )
711 /* Generated */ }}} // Close namespace TicTacTec.TA.Lib
712 /* Generated */ #endif
713 /**** END GENCODE SECTION 5 - DO NOT DELETE THIS LINE ****/
714 
715