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