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); }
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; } }
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); }
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); }
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()); }
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); }
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()); }
public RaceDataItem() { _waters = new WaterTable(); _odds = new HrsTable(); }
public Comb2Table(HrsTable owner) { _owner = owner; }
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); }
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); }
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); }
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 }); } }