Beispiel #1
0
        public static double[] calcBetRateForQn(HrsTable table, out double r)
        {
            r = 0;

            // 计算Q的投注比例
            double[] pqw = null;
            if (table.HasSpQ)
            {
                if (table.SpQ.Count > 0)
                {
                    double[] sqw = table.SpQ.Sp;
                    pqw = new double[sqw.Length];

                    double rqw = 1 / sqw.Sum(x => 1 / x);
                    for (int i = 0; i < pqw.Length; i++)
                    {
                        pqw[i] = rqw / sqw[i];
                    }

                    r = rqw;
                }
            }

            return(pqw);
        }
Beispiel #2
0
        public static void calcProbility(HrsTable table, out double[] p1, out double[] p3, out double[] pq_win, out double[] pq_plc)
        {
            int CNT     = table.Count;
            int PLC_CNT = 3;

            if (CNT <= table.PLC_SPLIT_POS)
            {
                PLC_CNT = 2;
            }

            double[] ee = table.Select(x => x.Mean).ToArray();
            double[] dd = table.Select(x => x.Var).ToArray();

            if ((table.HasSpQ && table.SpQ.Count > 0) || (table.HasSpQp && table.SpQp.Count > 0))
            {
                calcProbility(ee, dd, PLC_CNT, out p1, out p3, out pq_win, out pq_plc);

                if (!table.HasSpQ || table.SpQ.Count == 0)
                {
                    pq_win = null;
                }
                if (!table.HasSpQp || table.SpQp.Count == 0)
                {
                    pq_plc = null;
                }
            }
            else
            {
                calcProbility(ee, dd, PLC_CNT, out p1, out p3);
                pq_win = null;
                pq_plc = null;
            }
        }
Beispiel #3
0
        public static double[] calcBetRateForQp(HrsTable table, out double r)
        {
            r = 0;

            int CNT     = table.Count;
            int PLC_CNT = 3;

            if (CNT <= table.PLC_SPLIT_POS)
            {
                PLC_CNT = 2;
            }

            // 计算QP的投注比例
            // 修正发现几个错误引用了其他计算的变量 2017-09-17
            double[] pqp = null;
            if (table.HasSpQp)
            {
                if (table.SpQp.Count > 0)
                {
                    double[] sqp = table.SpQp.Sp;
                    pqp = new double[sqp.Length];

                    int QP_CNT = (int)(new common.Math.Combination(PLC_CNT, 2)).Length;

                    // 计算QP赔付率
                    IOrderedEnumerable <double> sorted_sqp = sqp.OrderBy(x => x);
                    double oqp3 = sorted_sqp.Skip(QP_CNT - 1).First();
                    double aqp  = QP_CNT == 1 ? 0 : QP_CNT * (oqp3 - 1) / (QP_CNT * (oqp3 - 1) + 1) * sorted_sqp.Take(QP_CNT - 1).Sum(x => 1 / (QP_CNT * (x - 1)));
                    double bqp  = sorted_sqp.Skip(QP_CNT - 1).Sum(x => 1 / (QP_CNT * (x - 1) + 1));
                    double rqp  = (aqp + 1) / (aqp + bqp);

                    // 计算投注比例
                    double pqp3 = (1 - rqp) / ((sorted_sqp.Skip(QP_CNT - 1).Sum(x => 1 / (QP_CNT * (x - 1) + 1)) - 1) * (QP_CNT * (oqp3 - 1) + 1));
                    for (int i = 0; i < pqp.Length; i++)
                    {
                        if (sqp[i] <= oqp3)
                        {
                            pqp[i] = pqp3 * (oqp3 - 1) / (sqp[i] - 1);
                        }
                        else
                        {
                            pqp[i] = pqp3 * (QP_CNT * (oqp3 - 1) + 1) / (QP_CNT * (sqp[i] - 1) + 1);
                        }
                    }

                    r = rqp;
                }
            }

            return(pqp);
        }
Beispiel #4
0
        public static double[] calcBetRateForWin(HrsTable table, out double r)
        {
            int CNT = table.Count;

            double[] s1  = table.SpWin;
            double   rr1 = 1 / s1.Sum(x => 1 / x);

            // 计算WIN投注比率
            double[] ph1 = new double[CNT];
            for (int i = 0; i < CNT; i++)
            {
                ph1[i] = rr1 / s1[i];
            }

            r = rr1;
            return(ph1);
        }
Beispiel #5
0
        private void button1_Click(object sender, EventArgs e)
        {
            HrsTable table = new HrsTable();

            table.Add(new Hrs("1", 5.5, 2.3));
            table.Add(new Hrs("2", 9.1, 1.6));
            table.Add(new Hrs("3", 44.9, 8.2));
            table.Add(new Hrs("4", 4.9, 2.7));
            table.Add(new Hrs("5", 16.3, 2.4));
            table.Add(new Hrs("6", 3.4, 1.5));
            table.Add(new Hrs("7", 15.6, 2.3));
            table.Add(new Hrs("8", 33.3, 4.4));
            table.Add(new Hrs("9", 17.3, 2.7));
            table.Add(new Hrs("10", 16.1, 3.4));
            table.Add(new Hrs("11", 40.1, 6.4));
            table.Add(new Hrs("12", 36, 5.7));
            table.Add(new Hrs("13", 42.7, 6.7));

            double E = Fitting.fit(table, 0.00001);

            MessageBox.Show(E.ToString());
        }
Beispiel #6
0
        public static double[] calcBetRateForPlc(HrsTable table, out double r)
        {
            int CNT     = table.Count;
            int PLC_CNT = 3;

            if (CNT <= table.PLC_SPLIT_POS)
            {
                PLC_CNT = 2;
            }

            double[] s3 = table.SpPlc;

            // 计算PLC赔付率
            IOrderedEnumerable <double> sorted_s3 = s3.OrderBy(x => x);
            double o3  = sorted_s3.Skip(PLC_CNT - 1).First();
            double a   = PLC_CNT * (o3 - 1) / (PLC_CNT * (o3 - 1) + 1) * sorted_s3.Take(PLC_CNT - 1).Sum(x => 1 / (PLC_CNT * (x - 1)));
            double b   = sorted_s3.Skip(PLC_CNT - 1).Sum(x => 1 / (PLC_CNT * (x - 1) + 1));
            double rr3 = (a + 1) / (a + b);

            // 计算投注比例
            double po3 = (1 - rr3) / ((sorted_s3.Skip(PLC_CNT - 1).Sum(x => 1 / (PLC_CNT * (x - 1) + 1)) - 1) * (PLC_CNT * (o3 - 1) + 1));

            double[] ph3 = new double[CNT];
            for (int i = 0; i < CNT; i++)
            {
                if (s3[i] <= o3)
                {
                    ph3[i] = po3 * (o3 - 1) / (s3[i] - 1);
                }
                else
                {
                    ph3[i] = po3 * (PLC_CNT * (o3 - 1) + 1) / (PLC_CNT * (s3[i] - 1) + 1);
                }
            }

            r = rr3;
            return(ph3);
        }
Beispiel #7
0
        public static double[] calcMaxOddsForPlc(HrsTable table, double[] betRate, double r)
        {
            if (betRate == null)
            {
                return(null);
            }
            int CNT     = table.Count;
            int PLC_CNT = 3;

            if (CNT <= table.PLC_SPLIT_POS)
            {
                PLC_CNT = 2;
            }
            if (betRate.Length != CNT)
            {
                return(null);
            }

            IOrderedEnumerable <double> sorted_rate = betRate.OrderBy(x => x);
            double split_rate = sorted_rate.Skip(PLC_CNT - 1).First();
            double sum_top    = sorted_rate.Take(PLC_CNT - 1).Sum();

            return(betRate.Select(x => 1 + (r - sum_top > (x > split_rate ? split_rate : x) ? (r - sum_top - (x > split_rate ? split_rate : x)) / PLC_CNT / x : 0)).ToArray());
        }
Beispiel #8
0
 public RaceDataItem()
 {
     _waters = new WaterTable();
     _odds   = new HrsTable();
 }
Beispiel #9
0
 public Comb2Table(HrsTable owner)
 {
     _owner = owner;
 }
Beispiel #10
0
        public static double[] calcBetRateForQpWithStyle2(HrsTable table, ref double r)
        {
            int CNT     = table.Count;
            int PLC_CNT = 3;

            if (CNT <= table.PLC_SPLIT_POS)
            {
                PLC_CNT = 2;
            }

            double[] pqp = null;
            if (table.HasSpQp)
            {
                if (table.SpQp.Count > 0)
                {
                    double[] sqp = table.SpQp.Sp;
                    pqp = new double[sqp.Length];

                    int QP_CNT = (int)(new common.Math.Combination(PLC_CNT, 2)).Length;

                    if (sqp.Where(x => x == 1).Count() == 0)
                    {
                        // 没有有强制设为1的赔率
                        r = QP_CNT / sqp.Sum(x => 1 / x);  // 赔付率

                        for (int i = 0; i < sqp.Length; i++)
                        {
                            pqp[i] = r / sqp[i] / QP_CNT;
                        }
                    }
                    else
                    {
                        // 否则用预计赔付率
                        List <int> od_1_indices = new List <int>();
                        double     other_p_sum  = 0;
                        for (int i = 0; i < sqp.Length; i++)
                        {
                            if (sqp[i] > 1)
                            {
                                pqp[i]       = r / sqp[i] / QP_CNT;
                                other_p_sum += pqp[i];
                            }
                            else
                            {
                                od_1_indices.Add(i);
                            }
                        }

                        if (PLC_CNT > 2)
                        {
                            double TEST_QP_CNT = (int)(new common.Math.Combination(PLC_CNT - 1, 2)).Length;
                            double testP       = (1 - (other_p_sum * QP_CNT) / TEST_QP_CNT) / od_1_indices.Count;
                            if (testP > 0 && r / testP / TEST_QP_CNT < 1.1)
                            {
                                // 假设只有PLC_CNT - 1个中奖项,赔率依然成立,无法确定预计的PLC_CNT是否正确
                                r = 0;
                                return(pqp);
                            }
                        }

                        double oneOddsP = (1 - other_p_sum) / od_1_indices.Count;
                        if (oneOddsP <= 0 || r / oneOddsP / QP_CNT > 1.1)
                        {
                            // 验证
                            r = 0;      // 计算偏差过大
                        }
                        else
                        {
                            foreach (int i in od_1_indices)
                            {
                                pqp[i] = oneOddsP;
                            }
                        }
                    }
                }
            }

            return(pqp);
        }
Beispiel #11
0
        public static double[] calcBetRateForPlcWithStyle2(HrsTable table, ref double r)
        {
            int CNT     = table.Count;
            int PLC_CNT = 3;

            if (CNT <= table.PLC_SPLIT_POS)
            {
                PLC_CNT = 2;
            }

            double[] s3 = table.SpPlc;

            double[] ph3 = new double[CNT];
            if (s3.Where(x => x == 1).Count() == 0)
            {
                // 没有有强制设为1的赔率
                r = PLC_CNT / s3.Sum(x => 1 / x);  // 赔付率

                for (int i = 0; i < CNT; i++)
                {
                    ph3[i] = r / s3[i] / PLC_CNT;
                }
            }
            else
            {
                // 否则用预计赔付率
                List <int> od_1_indices = new List <int>();
                double     other_p_sum  = 0;
                for (int i = 0; i < CNT; i++)
                {
                    if (s3[i] > 1)
                    {
                        ph3[i]       = r / s3[i] / PLC_CNT;
                        other_p_sum += ph3[i];
                    }
                    else
                    {
                        od_1_indices.Add(i);
                    }
                }

                if (PLC_CNT > 2)
                {
                    double testP = (1 - (other_p_sum * PLC_CNT) / (PLC_CNT - 1)) / od_1_indices.Count;
                    if (testP > 0 && r / testP / (PLC_CNT - 1) < 1.1)
                    {
                        // 假设只有PLC_CNT - 1个中奖项,赔率依然成立,无法确定预计的PLC_CNT是否正确
                        r = 0;
                        return(ph3);
                    }
                }

                double oneOddsP = (1 - other_p_sum) / od_1_indices.Count;
                if (oneOddsP <= 0 || r / oneOddsP / PLC_CNT > 1.1)
                {
                    // 验证
                    r = 0;      // 计算偏差过大
                }
                else
                {
                    foreach (int i in od_1_indices)
                    {
                        ph3[i] = oneOddsP;
                    }
                }
            }

            return(ph3);
        }
Beispiel #12
0
        public static double fit(HrsTable table, double epsilon)
        {
            int CNT = table.Count;

            double[] s1 = table.SpWin;
            double[] s3 = table.SpPlc;

            double[] ph1, ph3, pqw, pqp;
            double   rr1, rr3, rqw, rqp;

            ph1 = calcBetRateForWin(table, out rr1);
            ph3 = calcBetRateForPlc(table, out rr3);
            pqw = calcBetRateForQn(table, out rqw);
            pqp = calcBetRateForQp(table, out rqp);

            // 设定top1第3的项期望=0,方差=1
            double trd_s1  = s1.OrderBy(x => x).Skip(2).First();
            int    trd_inx = -1;

            for (int i = 0; i < CNT; i++)
            {
                if (s1[i] == trd_s1)
                {
                    trd_inx = i;
                    break;
                }
            }
            if (trd_inx == -1)
            {
                throw new Exception("没想到找不到排行第3的项");
            }

            double[] ee, dd;
            if (table.E == 0)
            {
                ee = new double[CNT];
                dd = new double[CNT];

                ee[trd_inx] = 0;
                dd[trd_inx] = 1;

                // 初始化其他项
                // 目前全部设为期望=0,方差=1
                // 后面考虑根据s1设置
                for (int i = 0; i < CNT; i++)
                {
                    if (i == trd_inx)
                    {
                        continue;
                    }
                    ee[i] = 0;
                    dd[i] = 1;
                }
            }
            else
            {
                // 从已经训练的数据继续训练

                ee = table.Select(x => x.Mean).ToArray();
                dd = table.Select(x => x.Var).ToArray();
            }

            double[] ee2    = new double[CNT], dd2 = new double[CNT];
            double   minE   = table.E == 0 ? double.MaxValue : table.E;
            int      minE_t = 0;

            Array.Copy(ee, ee2, CNT);
            Array.Copy(dd, dd2, CNT);

            double lastE       = double.MaxValue;
            int    reach_count = 0;

            for (int t = 0; ; t++)
            {
                double[] p1, pq1 = null;
                if (pqw != null)
                {
                    calcProbilityForFitting(ee, dd, out p1, out pq1);
                }
                else
                {
                    calcProbilityForFitting(ee, dd, out p1);
                }
                double E = 0;

                // 交叉熵损失以及交叉熵损失对与各个概率的梯度
                double[] grad_p1 = new double[CNT];
                for (int i = 0; i < CNT; i++)
                {
                    E         += -(ph1[i] * Math.Log(p1[i]));
                    grad_p1[i] = -(ph1[i] / p1[i]);
                }
                double[] grad_pq1 = null;
                if (pqw != null)
                {
                    grad_pq1 = new double[pqw.Length];
                    for (int i = 0; i < pqw.Length; i++)
                    {
                        E          += -(pqw[i] * Math.Log(pq1[i]));
                        grad_pq1[i] = -(pqw[i] / pq1[i]);
                    }
                }
                if (E < minE)
                {
                    minE_t = t;
                    Array.Copy(ee, ee2, CNT);
                    Array.Copy(dd, dd2, CNT);
                    minE = E;
                }

                // 求对各个参数的梯度
                double[] d_rr_ee = new double[CNT];
                double[] d_rr_dd = new double[CNT];
                for (int i = 0; i < CNT; i++)
                {
                    double[] tp1, tpq1 = null;

                    ee[i] += EE_D_INC;
                    if (pqw != null)
                    {
                        calcProbilityForFitting(ee, dd, out tp1, out tpq1);
                    }
                    else
                    {
                        calcProbilityForFitting(ee, dd, out tp1);
                    }

                    for (int j = 0; j < CNT; j++)
                    {
                        // 第j匹马的WIN概率对第i匹马的均值的梯度 = (tp1[j] - p1[j]) / EE_D_INC
                        d_rr_ee[i] += (tp1[j] - p1[j]) / EE_D_INC * grad_p1[j];
                    }
                    if (pqw != null)
                    {
                        for (int j = 0; j < pqw.Length; j++)
                        {
                            d_rr_ee[i] += (tpq1[j] - pq1[j]) / EE_D_INC * grad_pq1[j];
                        }
                    }
                    ee[i] -= EE_D_INC;

                    dd[i] += DD_D_INC;
                    if (pqw != null)
                    {
                        calcProbilityForFitting(ee, dd, out tp1, out tpq1);
                    }
                    else
                    {
                        calcProbilityForFitting(ee, dd, out tp1);
                    }
                    for (int j = 0; j < CNT; j++)
                    {
                        // 第j匹马的WIN概率对第i匹马的方差的梯度 = (tp1[j] - p1[j]) / DD_D_INC
                        d_rr_dd[i] += (tp1[j] - p1[j]) / DD_D_INC * grad_p1[j];
                    }
                    if (pqw != null)
                    {
                        for (int j = 0; j < pqw.Length; j++)
                        {
                            d_rr_dd[i] += (tpq1[j] - pq1[j]) / DD_D_INC * grad_pq1[j];
                        }
                    }
                    dd[i] -= DD_D_INC;
                }

                // 调整各参数
                for (int i = 0; i < CNT; i++)
                {
                    // 向负梯度方向调整
                    ee[i] += -d_rr_ee[i] * EE_STEP / (1 + t * STEP_DECAY);
                    dd[i] += -d_rr_dd[i] * DD_STEP / (1 + t * STEP_DECAY);

                    if (dd[i] < 0.0001)
                    {
                        dd[i] = 0.0001;
                    }
                }

                // 调整之后再进行归一化
                for (int i = 0; i < CNT; i++)
                {
                    if (i == trd_inx)
                    {
                        continue;
                    }
                    ee[i] = (ee[i] - ee[trd_inx]) / dd[trd_inx];
                    dd[i] = dd[i] / dd[trd_inx];
                }
                ee[trd_inx] = 0;
                dd[trd_inx] = 1;

                if (Math.Abs(lastE - E) < epsilon)
                {
                    reach_count++;
                    if (reach_count > 3)
                    {
                        if (pqw != null)
                        {
                            double[] dpq = new double[pqw.Length];
                            for (int i = 0; i < dpq.Length; i++)
                            {
                                dpq[i] = Math.Log(pqw[i] / pq1[i]);
                            }
                        }
                        double[] dp1 = new double[ph1.Length];
                        for (int i = 0; i < dp1.Length; i++)
                        {
                            dp1[i] = Math.Log(ph1[i] / p1[i]);
                        }
                        break;
                    }
                }
                else if (t - minE_t > 20)
                {
                    Array.Copy(ee2, ee, CNT);
                    Array.Copy(dd2, dd, CNT);
                    lastE = minE;
                    break;
                }
                else
                {
                    reach_count = 0;
                }
                lastE = E;
            }

            // 拟合完成,将结果写回Hrs中
            for (int i = 0; i < CNT; i++)
            {
                table[i].Mean = ee[i];
                table[i].Var  = dd[i];
            }

            return(lastE);
        }
Beispiel #13
0
        public static double[][] calcMinMaxOddsForQp(HrsTable table, double[] betRate, double r)
        {
            if (betRate == null)
            {
                return(null);
            }
            int CNT     = table.Count;
            int PLC_CNT = 3;

            if (CNT <= table.PLC_SPLIT_POS)
            {
                PLC_CNT = 2;
            }

            common.Math.Combination comb = new common.Math.Combination(CNT, 2);
            if (betRate.Length != comb.Length)
            {
                return(null);
            }


            if (PLC_CNT == 2)
            {
                double[] odds = betRate.Select(x => r < x ? 1 : r / x).ToArray();
                return(new double[][] { odds, odds });
            }
            else
            {
                double[] odds_min = new double[betRate.Length];
                double[] odds_max = new double[betRate.Length];
                for (int i = 0; i < betRate.Length; i++)
                {
                    //int[] rel_indices = getQpRelationIndice(comb, i);
                    //double[] rel_rates = new double[rel_indices.Length];
                    //for (int j = 0; j < rel_indices.Length; j++) rel_rates[j] = betRate[rel_indices[j]];
                    //IOrderedEnumerable<double> sorted_rate = rel_rates.OrderByDescending(x => x);

                    double br0 = betRate[i];
                    int[]  c = comb.Combine(i);
                    double min = double.MaxValue, max = double.MinValue;
                    for (int j = 0; j < CNT; j++)
                    {
                        if (Array.IndexOf(c, j) == -1)
                        {
                            double br1 = betRate[comb.Index(new int[] { j, c[0] })];
                            double br2 = betRate[comb.Index(new int[] { j, c[1] })];

                            double od = 1 + (r - br1 - br2 - br0) / 3 / br0;
                            if (od < min)
                            {
                                min = od;
                            }
                            if (od > max)
                            {
                                max = od;
                            }
                        }
                    }
                    odds_min[i] = min;
                    odds_max[i] = max;
                }
                return(new double[][] { odds_min, odds_max });
            }
        }