public static RetCode Cos(decimal[] inReal, int startIdx, int endIdx, decimal[] outReal, out int outBegIdx, out int outNbElement) { outBegIdx = outNbElement = 0; if (startIdx < 0 || endIdx < 0 || endIdx < startIdx) { return(RetCode.OutOfRangeStartIndex); } if (inReal == null || outReal == null) { return(RetCode.BadParam); } int outIdx = default; for (int i = startIdx; i <= endIdx; i++) { outReal[outIdx++] = DecimalMath.Cos(inReal[i]); } outNbElement = outIdx; outBegIdx = startIdx; return(RetCode.Success); }
public static RetCode HtDcPhase(decimal[] inReal, int startIdx, int endIdx, decimal[] outReal, out int outBegIdx, out int outNbElement) { outBegIdx = outNbElement = 0; if (startIdx < 0 || endIdx < 0 || endIdx < startIdx) { return RetCode.OutOfRangeStartIndex; } if (inReal == null || outReal == null) { return RetCode.BadParam; } int lookbackTotal = HtDcPhaseLookback(); if (startIdx < lookbackTotal) { startIdx = lookbackTotal; } if (startIdx > endIdx) { return RetCode.Success; } const int smoothPriceSize = 50; var smoothPrice = new decimal[smoothPriceSize]; const decimal rad2Deg = 180m / DecimalMath.PI; const decimal constDeg2RadBy360 = 2m * DecimalMath.PI; outBegIdx = startIdx; int trailingWMAIdx = startIdx - lookbackTotal; int today = trailingWMAIdx; decimal tempReal = inReal[today++]; decimal periodWMASub = tempReal; decimal periodWMASum = tempReal; tempReal = inReal[today++]; periodWMASub += tempReal; periodWMASum += tempReal * 2m; tempReal = inReal[today++]; periodWMASub += tempReal; periodWMASum += tempReal * 3m; decimal trailingWMAValue = default; var i = 34; do { tempReal = inReal[today++]; DoPriceWma(inReal, ref trailingWMAIdx, ref periodWMASub, ref periodWMASum, ref trailingWMAValue, tempReal, out _); } while (--i != 0); int hilbertIdx = default; int smoothPriceIdx = default; var hilbertVariables = InitHilbertVariables<decimal>(); int outIdx = default; decimal prevI2, prevQ2, re, im, i1ForOddPrev3, i1ForEvenPrev3, i1ForOddPrev2, i1ForEvenPrev2, smoothPeriod, dcPhase; decimal period = prevI2 = prevQ2 = re = im = i1ForOddPrev3 = i1ForEvenPrev3 = i1ForOddPrev2 = i1ForEvenPrev2 = smoothPeriod = dcPhase = default; while (today <= endIdx) { decimal i2; decimal q2; decimal adjustedPrevPeriod = 0.075m * period + 0.54m; decimal todayValue = inReal[today]; DoPriceWma(inReal, ref trailingWMAIdx, ref periodWMASub, ref periodWMASum, ref trailingWMAValue, todayValue, out var smoothedValue); smoothPrice[smoothPriceIdx] = smoothedValue; if (today % 2 == 0) { DoHilbertEven(hilbertVariables, "detrender", smoothedValue, hilbertIdx, adjustedPrevPeriod); DoHilbertEven(hilbertVariables, "q1", hilbertVariables["detrender"], hilbertIdx, adjustedPrevPeriod); DoHilbertEven(hilbertVariables, "jI", i1ForEvenPrev3, hilbertIdx, adjustedPrevPeriod); DoHilbertEven(hilbertVariables, "jQ", hilbertVariables["q1"], hilbertIdx, adjustedPrevPeriod); if (++hilbertIdx == 3) { hilbertIdx = 0; } q2 = 0.2m * (hilbertVariables["q1"] + hilbertVariables["jI"]) + 0.8m * prevQ2; i2 = 0.2m * (i1ForEvenPrev3 - hilbertVariables["jQ"]) + 0.8m * prevI2; i1ForOddPrev3 = i1ForOddPrev2; i1ForOddPrev2 = hilbertVariables["detrender"]; } else { DoHilbertOdd(hilbertVariables, "detrender", smoothedValue, hilbertIdx, adjustedPrevPeriod); DoHilbertOdd(hilbertVariables, "q1", hilbertVariables["detrender"], hilbertIdx, adjustedPrevPeriod); DoHilbertOdd(hilbertVariables, "jI", i1ForOddPrev3, hilbertIdx, adjustedPrevPeriod); DoHilbertOdd(hilbertVariables, "jQ", hilbertVariables["q1"], hilbertIdx, adjustedPrevPeriod); q2 = 0.2m * (hilbertVariables["q1"] + hilbertVariables["jI"]) + 0.8m * prevQ2; i2 = 0.2m * (i1ForOddPrev3 - hilbertVariables["jQ"]) + 0.8m * prevI2; i1ForEvenPrev3 = i1ForEvenPrev2; i1ForEvenPrev2 = hilbertVariables["detrender"]; } re = 0.2m * (i2 * prevI2 + q2 * prevQ2) + 0.8m * re; im = 0.2m * (i2 * prevQ2 - q2 * prevI2) + 0.8m * im; prevQ2 = q2; prevI2 = i2; tempReal = period; if (im != Decimal.Zero && re != Decimal.Zero) { period = 360m / (DecimalMath.Atan(im / re) * rad2Deg); } decimal tempReal2 = 1.5m * tempReal; if (period > tempReal2) { period = tempReal2; } tempReal2 = 0.67m * tempReal; if (period < tempReal2) { period = tempReal2; } if (period < 6m) { period = 6m; } else if (period > 50m) { period = 50m; } period = 0.2m * period + 0.8m * tempReal; smoothPeriod = 0.33m * period + 0.67m * smoothPeriod; decimal dcPeriod = smoothPeriod + 0.5m; int dcPeriodInt = (int) dcPeriod; decimal realPart = default; decimal imagPart = default; int idx = smoothPriceIdx; for (i = 0; i < dcPeriodInt; i++) { tempReal = i * constDeg2RadBy360 / dcPeriodInt; tempReal2 = smoothPrice[idx]; realPart += DecimalMath.Sin(tempReal) * tempReal2; imagPart += DecimalMath.Cos(tempReal) * tempReal2; if (idx == 0) { idx = smoothPriceSize - 1; } else { idx--; } } tempReal = Math.Abs(imagPart); if (tempReal > Decimal.Zero) { dcPhase = DecimalMath.Atan(realPart / imagPart) * rad2Deg; } else if (tempReal <= 0.01m) { if (realPart < Decimal.Zero) { dcPhase -= 90m; } else if (realPart > Decimal.Zero) { dcPhase += 90m; } } dcPhase += 90m; dcPhase += 360m / smoothPeriod; if (imagPart < Decimal.Zero) { dcPhase += 180m; } if (dcPhase > 315m) { dcPhase -= 360m; } if (today >= startIdx) { outReal[outIdx++] = dcPhase; } if (++smoothPriceIdx > smoothPriceSize - 1) { smoothPriceIdx = 0; } today++; } outNbElement = outIdx; return RetCode.Success; }
public static RetCode HtTrendMode(int startIdx, int endIdx, decimal[] inReal, ref int outBegIdx, ref int outNBElement, int[] outInteger) { if (startIdx < 0 || endIdx < 0 || endIdx < startIdx) { return(RetCode.OutOfRangeStartIndex); } if (inReal == null || outInteger == null) { return(RetCode.BadParam); } const int smoothPriceSize = 50; var smoothPrice = new decimal[smoothPriceSize]; const decimal rad2Deg = 180m / DecimalMath.PI; const decimal deg2Rad = Decimal.One / rad2Deg; const decimal constDeg2RadBy360 = 2m * DecimalMath.PI; decimal iTrend3 = default; decimal iTrend2 = iTrend3; decimal iTrend1 = iTrend2; int daysInTrend = default; decimal sine = default; decimal leadSine = default; int lookbackTotal = HtTrendModeLookback(); if (startIdx < lookbackTotal) { startIdx = lookbackTotal; } if (startIdx > endIdx) { outBegIdx = 0; outNBElement = 0; return(RetCode.Success); } outBegIdx = startIdx; int trailingWMAIdx = startIdx - lookbackTotal; int today = trailingWMAIdx; decimal tempReal = inReal[today++]; decimal periodWMASub = tempReal; decimal periodWMASum = tempReal; tempReal = inReal[today++]; periodWMASub += tempReal; periodWMASum += tempReal * 2m; tempReal = inReal[today++]; periodWMASub += tempReal; periodWMASum += tempReal * 3m; decimal trailingWMAValue = default; int i = 34; do { tempReal = inReal[today++]; DoPriceWma(inReal, ref trailingWMAIdx, ref periodWMASub, ref periodWMASum, ref trailingWMAValue, out var _, tempReal); } while (--i != 0); int hilbertIdx = default; int smoothPriceIdx = default; var hilbertVariables = InitHilbertVariables <decimal>(); int outIdx = default; decimal prevI2, prevQ2, re, im, i1ForOddPrev3, i1ForEvenPrev3, i1ForOddPrev2, i1ForEvenPrev2, smoothPeriod, dcPhase; decimal period = prevI2 = prevQ2 = re = im = i1ForOddPrev3 = i1ForEvenPrev3 = i1ForOddPrev2 = i1ForEvenPrev2 = smoothPeriod = dcPhase = default; while (today <= endIdx) { decimal i2; decimal q2; decimal adjustedPrevPeriod = 0.075m * period + 0.54m; decimal todayValue = inReal[today]; DoPriceWma(inReal, ref trailingWMAIdx, ref periodWMASub, ref periodWMASum, ref trailingWMAValue, out var smoothedValue, todayValue); smoothPrice[smoothPriceIdx] = smoothedValue; if (today % 2 == 0) { DoHilbertEven(hilbertVariables, "detrender", smoothedValue, hilbertIdx, adjustedPrevPeriod); DoHilbertEven(hilbertVariables, "q1", hilbertVariables["detrender"], hilbertIdx, adjustedPrevPeriod); DoHilbertEven(hilbertVariables, "jI", i1ForEvenPrev3, hilbertIdx, adjustedPrevPeriod); DoHilbertEven(hilbertVariables, "jQ", hilbertVariables["q1"], hilbertIdx, adjustedPrevPeriod); if (++hilbertIdx == 3) { hilbertIdx = 0; } q2 = 0.2m * (hilbertVariables["q1"] + hilbertVariables["jI"]) + 0.8m * prevQ2; i2 = 0.2m * (i1ForEvenPrev3 - hilbertVariables["jQ"]) + 0.8m * prevI2; i1ForOddPrev3 = i1ForOddPrev2; i1ForOddPrev2 = hilbertVariables["detrender"]; } else { DoHilbertOdd(hilbertVariables, "detrender", smoothedValue, hilbertIdx, adjustedPrevPeriod); DoHilbertOdd(hilbertVariables, "q1", hilbertVariables["detrender"], hilbertIdx, adjustedPrevPeriod); DoHilbertOdd(hilbertVariables, "jI", i1ForOddPrev3, hilbertIdx, adjustedPrevPeriod); DoHilbertOdd(hilbertVariables, "jQ", hilbertVariables["q1"], hilbertIdx, adjustedPrevPeriod); q2 = 0.2m * (hilbertVariables["q1"] + hilbertVariables["jI"]) + 0.8m * prevQ2; i2 = 0.2m * (i1ForOddPrev3 - hilbertVariables["jQ"]) + 0.8m * prevI2; i1ForEvenPrev3 = i1ForEvenPrev2; i1ForEvenPrev2 = hilbertVariables["detrender"]; } re = 0.2m * (i2 * prevI2 + q2 * prevQ2) + 0.8m * re; im = 0.2m * (i2 * prevQ2 - q2 * prevI2) + 0.8m * im; prevQ2 = q2; prevI2 = i2; tempReal = period; if (im != Decimal.Zero && re != Decimal.Zero) { period = 360m / (DecimalMath.Atan(im / re) * rad2Deg); } decimal tempReal2 = 1.5m * tempReal; if (period > tempReal2) { period = tempReal2; } tempReal2 = 0.67m * tempReal; if (period < tempReal2) { period = tempReal2; } if (period < 6m) { period = 6m; } else if (period > 50m) { period = 50m; } period = 0.2m * period + 0.8m * tempReal; smoothPeriod = 0.33m * period + 0.67m * smoothPeriod; decimal prevDCPhase = dcPhase; decimal dcPeriod = smoothPeriod + 0.5m; int dcPeriodInt = (int)dcPeriod; decimal realPart = default; decimal imagPart = default; int idx = smoothPriceIdx; for (i = 0; i < dcPeriodInt; i++) { tempReal = i * constDeg2RadBy360 / dcPeriodInt; tempReal2 = smoothPrice[idx]; realPart += DecimalMath.Sin(tempReal) * tempReal2; imagPart += DecimalMath.Cos(tempReal) * tempReal2; if (idx == 0) { idx = smoothPriceSize - 1; } else { idx--; } } tempReal = Math.Abs(imagPart); if (tempReal > Decimal.Zero) { dcPhase = DecimalMath.Atan(realPart / imagPart) * rad2Deg; } else if (tempReal <= 0.01m) { if (realPart < Decimal.Zero) { dcPhase -= 90m; } else if (realPart > Decimal.Zero) { dcPhase += 90m; } } dcPhase += 90m; dcPhase += 360m / smoothPeriod; if (imagPart < Decimal.Zero) { dcPhase += 180m; } if (dcPhase > 315m) { dcPhase -= 360m; } decimal prevSine = sine; decimal prevLeadSine = leadSine; sine = DecimalMath.Sin(dcPhase * deg2Rad); leadSine = DecimalMath.Sin((dcPhase + 45m) * deg2Rad); dcPeriod = smoothPeriod + 0.5m; dcPeriodInt = (int)dcPeriod; idx = today; tempReal = default; for (i = 0; i < dcPeriodInt; i++) { tempReal += inReal[idx--]; } if (dcPeriodInt > 0) { tempReal /= dcPeriodInt; } decimal trendline = (4m * tempReal + 3m * iTrend1 + 2m * iTrend2 + iTrend3) / 10m; iTrend3 = iTrend2; iTrend2 = iTrend1; iTrend1 = tempReal; int trend = 1; if (sine > leadSine && prevSine <= prevLeadSine || sine < leadSine && prevSine >= prevLeadSine) { daysInTrend = 0; trend = 0; } if (++daysInTrend < 0.5m * smoothPeriod) { trend = 0; } tempReal = dcPhase - prevDCPhase; if (smoothPeriod != Decimal.Zero && tempReal > 0.67m * 360m / smoothPeriod && tempReal < 1.5m * 360m / smoothPeriod) { trend = 0; } tempReal = smoothPrice[smoothPriceIdx]; if (trendline != Decimal.Zero && Math.Abs((tempReal - trendline) / trendline) >= 0.015m) { trend = 1; } if (today >= startIdx) { outInteger[outIdx++] = trend; } if (++smoothPriceIdx > smoothPriceSize - 1) { smoothPriceIdx = 0; } today++; } outNBElement = outIdx; return(RetCode.Success); }