示例#1
0
        public static RetCode Sin(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.Sin(inReal[i]);
            }

            outBegIdx    = startIdx;
            outNbElement = outIdx;

            return(RetCode.Success);
        }
示例#2
0
        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);
        }