Exemple #1
0
        /// <summary> y = (a / x) + b の形の関数として Rt の減衰を計算する </summary>
        /// <returns>計算された予測Rtの日数を返す</returns>
        public int CalcAndCopyPredictRt(double[] rts, int startIdx, double[] predRt, int realDays, int extensionDays)
        {
            if (extensionDays == 0)
            {
                extensionDays = Constants.EXTENSION_DAYS;
            }
            double rt0 = rts[startIdx];

            if (Fourstep)
            {
                // 多段階モード
                double decayFactor = 10000;
                double rt1         = Rt1;
                int    daysToRt1   = DaysToRt1;
                //if (daysToRt1 < 1) daysToRt1 = Constants.DAYS_TO_NEXT_RT;
                double a1 = 0, b1 = 0;
                if (daysToRt1 > 0)
                {
                    a1 = (rt0 - rt1) * (decayFactor + daysToRt1) * decayFactor / daysToRt1;
                    b1 = rt0 - (a1 / decayFactor);
                }
                else
                {
                    daysToRt1 = 0;
                    rt1       = rt0;
                }
                // Rt1に到達してから
                double rt2       = Rt2;
                int    daysToRt2 = DaysToRt2;
                //if (daysToRt2 == 0) daysToRt2 = Constants.DAYS_TO_NEXT_RT;
                double a2 = 0, b2 = 0;
                if (daysToRt2 > 0)
                {
                    a2 = (rt1 - rt2) * (decayFactor + daysToRt2) * decayFactor / daysToRt2;
                    b2 = rt1 - (a2 / decayFactor);
                }
                else
                {
                    daysToRt2 = 0;
                    rt2       = rt1;
                }
                // Rt2に到達してから
                double rt3       = Rt3;
                int    daysToRt3 = DaysToRt3;
                //if (daysToRt3 == 0) daysToRt3 = Constants.DAYS_TO_NEXT_RT;
                double a3 = 0, b3 = 0;
                if (daysToRt3 > 0)
                {
                    a3 = (rt2 - rt3) * (decayFactor + daysToRt3) * decayFactor / daysToRt3;
                    b3 = rt2 - (a3 / decayFactor);
                }
                else
                {
                    daysToRt3 = 0;
                    rt3       = rt2;
                }
                // Rt3に到達してから
                double rt4       = Rt4;
                int    daysToRt4 = DaysToRt4;
                //if (daysToRt4 == 0) daysToRt4 = Constants.DAYS_TO_NEXT_RT;
                double a4 = 0, b4 = 0;
                if (daysToRt4 > 0)
                {
                    a4 = (rt3 - rt4) * (decayFactor + daysToRt4) * decayFactor / daysToRt4;
                    b4 = rt3 - (a4 / decayFactor);
                }
                else
                {
                    daysToRt4 = 0;
                    rt4       = rt3;
                }
                // Rt4に到達してから
                double rt5       = Rt5;
                int    daysToRt5 = DaysToRt5;
                //if (daysToRt5 == 0) daysToRt5 = Constants.DAYS_TO_NEXT_RT;
                double a5 = 0, b5 = 0;
                if (daysToRt5 > 0)
                {
                    a5 = (rt4 - rt5) * (decayFactor + daysToRt5) * decayFactor / daysToRt5;
                    b5 = rt4 - (a5 / decayFactor);
                }
                else
                {
                    daysToRt5 = 0;
                    rt5       = rt4;
                }
                // Rt5に到達してから
                double rt6       = Rt6;
                int    daysToRt6 = DaysToRt6;
                //if (daysToRt6 == 0) daysToRt6 = Constants.DAYS_TO_NEXT_RT;
                double a6 = 0, b6 = 0;
                if (daysToRt6 > 0)
                {
                    a6 = (rt5 - rt6) * (decayFactor + daysToRt6) * decayFactor / daysToRt6;
                    b6 = rt5 - (a6 / decayFactor);
                }
                else
                {
                    daysToRt6 = 0;
                    rt6       = rt5;
                }

                int    copyLen = ((daysToRt1 + daysToRt2 + daysToRt3 + daysToRt4 + daysToRt5 + daysToRt6)._lowLimit(realDays - startIdx) + extensionDays)._highLimit(predRt.Length - startIdx);
                double rt      = 0;
                for (int i = 0; i < copyLen; ++i)
                {
                    if (i == 0)
                    {
                        rt = rt0;
                    }
                    else if (daysToRt1 + daysToRt2 + daysToRt3 + daysToRt4 + daysToRt5 + daysToRt6 == 0)
                    {
                        rt = 0;
                    }
                    else if (i <= daysToRt1)
                    {
                        rt = a1 / (decayFactor + i) + b1;
                    }
                    else if (i <= daysToRt1 + daysToRt2)
                    {
                        rt = a2 / (decayFactor + i - daysToRt1) + b2;
                        if (rt1 > rt2)
                        {
                            if (rt < rt2)
                            {
                                rt = rt2;
                            }
                        }
                        else
                        {
                            if (rt > rt2)
                            {
                                rt = rt2;
                            }
                        }
                    }
                    else if (i <= daysToRt1 + daysToRt2 + daysToRt3)
                    {
                        rt = a3 / (decayFactor + i - daysToRt1 - daysToRt2) + b3;
                        if (rt2 > rt3)
                        {
                            if (rt < rt3)
                            {
                                rt = rt3;
                            }
                        }
                        else
                        {
                            if (rt > rt3)
                            {
                                rt = rt3;
                            }
                        }
                    }
                    else if (i <= daysToRt1 + daysToRt2 + daysToRt3 + daysToRt4)
                    {
                        rt = a4 / (decayFactor + i - daysToRt1 - daysToRt2 - daysToRt3) + b4;
                        if (rt3 > rt4)
                        {
                            if (rt < rt4)
                            {
                                rt = rt4;
                            }
                        }
                        else
                        {
                            if (rt > rt4)
                            {
                                rt = rt4;
                            }
                        }
                    }
                    else if (i <= daysToRt1 + daysToRt2 + daysToRt3 + daysToRt4 + daysToRt5)
                    {
                        rt = a5 / (decayFactor + i - daysToRt1 - daysToRt2 - daysToRt3 - daysToRt4) + b5;
                        if (rt4 > rt5)
                        {
                            if (rt < rt5)
                            {
                                rt = rt5;
                            }
                        }
                        else
                        {
                            if (rt > rt5)
                            {
                                rt = rt5;
                            }
                        }
                    }
                    else if (i <= daysToRt1 + daysToRt2 + daysToRt3 + daysToRt4 + daysToRt5 + daysToRt6)
                    {
                        rt = a6 / (decayFactor + i - daysToRt1 - daysToRt2 - daysToRt3 - daysToRt4 - daysToRt5) + b6;
                        if (rt5 > rt6)
                        {
                            if (rt < rt6)
                            {
                                rt = rt6;
                            }
                        }
                        else
                        {
                            if (rt > rt6)
                            {
                                rt = rt6;
                            }
                        }
                    }
                    predRt[startIdx + i] = rt;
                }
                return(copyLen);
            }
            else
            {
                // 2段階モード
                // ここの extensionDays には、移動平均のための余分な4日分がすでに追加されているので、これを max としてよい
                int copyLen  = Math.Min(realDays - startIdx + extensionDays, predRt.Length - startIdx);
                int toOneLen = Math.Min(DaysToOne, copyLen);

                // 1st Stage (rt = a1 * / (factor1 + x) + b1)
                double rt1     = EasyRt1;
                double factor1 = DecayFactor;
                //if (factor1 < 1) factor1 = 50;
                //double a1 = Constants.CalcCoefficientA1(rt0, rt1, factor1, DaysToOne);
                //double b1 = Constants.CalcCoefficientB1(rt0, a1, factor1);
                (double a1, double b1) = Constants.CalcCoefficient1(rt0, rt1, factor1, DaysToOne);

                for (int i = 0; i < toOneLen; ++i)
                {
                    predRt[startIdx + i] = Constants.CalcRt1(a1, b1, factor1, i);
                }

                // 2nd Stage
                double tgtRt2  = EasyRt2;
                double factor2 = DecayFactorNext;
                (double a2, double b2) = Constants.CalcCoefficients2(rt0, rt1, tgtRt2, factor2, DaysToOne);

                int    ph3StartIdx = -1;
                double rt2         = Math.Min(rts._nth(startIdx + DaysToOne), rts[^ 1]) * 0.9; // 減衰の下限