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