Exemplo n.º 1
0
        /// <summary>
        /// 获得Qp相关的组合,只针对PLC_CNT=3的情况
        /// </summary>
        /// <param name="comb"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        private static int[] getQpRelationIndice(common.Math.Combination comb, int index)
        {
            if (comb.M != 2)
            {
                return(null);
            }
            int[]      c   = comb.Combine(index);
            List <int> ret = new List <int>();

            ret.Add(index);

            for (int i = 0; i < comb.N; i++)
            {
                if (Array.IndexOf(c, i) == -1)
                {
                    ret.Add(comb.Index(new int[] { i, c[0] }));
                    ret.Add(comb.Index(new int[] { i, c[1] }));
                }
            }
            return(ret.ToArray());
        }
Exemplo n.º 2
0
        private void handle(string filename)
        {
            RaceData race = RaceData.Load(filename);

            if (race.Count < 2)
            {
                return;
            }
            long tp = race.First().Key;

            if (tp - race.Skip(1).First().Key != 300000)
            {
                return;
            }
            RaceDataItem item  = race.First().Value;
            RaceDataItem item2 = race.Skip(1).First().Value;

            if (item.Odds.E == 0 || item2.Odds.E == 0)
            {
                return;
            }
            double[] p1, p3, pq_win, pq_plc;
            Fitting.calcProbility(item2.Odds, out p1, out p3, out pq_win, out pq_plc);

            // 计算预计概率与当前赔率下下注比例的交叉熵
            double[] q1, qq;
            double   r1, rq;

            q1 = Fitting.calcBetRateForWin(item.Odds, out r1);
            qq = Fitting.calcBetRateForQn(item.Odds, out rq);
            double E = cross_entropy(p1, q1) + cross_entropy(pq_win, qq);

            // 当前赔率下交叉熵过大则退出,不下单
            if (E > item2.Odds.E * E_THRESHOLD_SCALE)
            {
                this.Invoke(new MethodInvoker(delegate
                {
                    this.txtLog.AppendText(string.Format("{0:HH:mm:ss} > file {1} 变化过于剧烈{2}/{3}\r\n", DateTime.Now, filename, E, item2.Odds.E));
                }));
                return;
            }

            List <InvestRecordWp> wp_records = new List <InvestRecordWp>();

            for (int i = 0; i < item.Odds.Count; i++)
            {
                Hrs h = item.Odds[i];

                double sp_w_min = Math.Min(h.Win, item2.Odds[i].Win);
                double sp_w_max = Math.Max(h.Win, item2.Odds[i].Win);
                double sp_p_min = Math.Min(h.Plc, item2.Odds[i].Plc);
                double sp_p_max = Math.Max(h.Plc, item2.Odds[i].Plc);

                // For Bet
                {
                    WaterWPList vlist = item.Waters.GetWpEatWater(h.No).GetValuableWater(MIN_R, sp_w_min, p1[i], sp_p_min, p3[i]);
                    double      bet_amount_win = 0, bet_amount_plc = 0;
                    bool        full_win = false, full_plc = false;
                    foreach (WaterWPItem w in vlist.OrderBy(x => x.Percent))
                    {
                        if (w.WinAmount > 0 && full_win)
                        {
                            continue;
                        }
                        if (w.PlcAmount > 0 && full_plc)
                        {
                            continue;
                        }

                        double bet_amount = -1;

                        if (w.WinAmount > 0)
                        {
                            double O       = Math.Min(w.WinLimit / LIMIT_SCALE, sp_w_min) * 100 / w.Percent;
                            double max_bet = (T * Math.Pow(O * p1[i] - 1, 2)) / (LOSS_RATE_COEFFICIENT * Math.Pow(O, 2) * p1[i] * (1 - p1[i]));
                            if (bet_amount_win >= max_bet)
                            {
                                full_win = true;
                                continue;
                            }
                            else
                            {
                                bet_amount = Math.Min(max_bet - bet_amount_win, w.WinAmount);
                            }
                        }

                        if (w.PlcAmount > 0)
                        {
                            double O       = Math.Min(w.PlcLimit / LIMIT_SCALE, sp_p_min) * 100 / w.Percent;
                            double max_bet = (T * Math.Pow(O * p3[i] - 1, 2)) / (LOSS_RATE_COEFFICIENT * Math.Pow(O, 2) * p3[i] * (1 - p3[i]));
                            if (bet_amount_plc >= max_bet)
                            {
                                full_plc = true;
                                continue;
                            }
                            else
                            {
                                if (bet_amount == -1)
                                {
                                    bet_amount = Math.Min(max_bet - bet_amount_plc, w.PlcAmount);
                                }
                                else
                                {
                                    bet_amount = Math.Min(bet_amount, Math.Min(max_bet - bet_amount_plc, w.PlcAmount));   // 有Win也有Plc, 那么Plc肯定和Win一样
                                }
                            }
                        }

                        if (bet_amount > 0)
                        {
                            bet_amount = Math.Round(bet_amount / WP_STEP) * WP_STEP;
                            if (bet_amount > 0)
                            {
                                InvestRecordWp ir = new InvestRecordWp()
                                {
                                    TimeKey     = tp,
                                    Model       = MODEL,
                                    CardID      = race.CardID,
                                    RaceNo      = race.RaceNo,
                                    Direction   = "BET",
                                    HorseNo     = h.No,
                                    Percent     = w.Percent,
                                    WinLimit    = w.WinLimit,
                                    PlcLimit    = w.PlcLimit,
                                    FittingLoss = item.Odds.E
                                };

                                if (w.WinLimit > 0)
                                {
                                    ir.WinAmount    = bet_amount;
                                    ir.WinOdds      = sp_w_min;
                                    ir.WinProbility = p1[i];
                                }
                                if (w.PlcLimit > 0)
                                {
                                    ir.PlcAmount    = bet_amount;
                                    ir.PlcOdds      = sp_p_min;
                                    ir.PlcProbility = p3[i];
                                }

                                wp_records.Add(ir);

                                bet_amount_win += ir.WinAmount;
                                bet_amount_plc += ir.PlcAmount;
                            }
                        }
                    }
                }

                // For Eat
                {
                    WaterWPList vlist = item.Waters.GetWpBetWater(h.No).GetValuableWater(MIN_R, sp_w_max, p1[i], sp_p_max, p3[i]);
                    double      eat_amount_win = 0, eat_amount_plc = 0;
                    bool        full_win = false, full_plc = false;
                    foreach (WaterWPItem w in vlist.OrderByDescending(x => x.Percent))
                    {
                        if (w.WinAmount > 0 && full_win)
                        {
                            continue;
                        }
                        if (w.PlcAmount > 0 && full_plc)
                        {
                            continue;
                        }

                        double eat_amount = -1;

                        if (w.WinAmount > 0)
                        {
                            double O       = 1 + w.Percent / 100 / Math.Min(w.WinLimit / LIMIT_SCALE, sp_w_max);
                            double max_eat = (T * Math.Pow(O * (1 - p1[i]) - 1, 2)) / (LOSS_RATE_COEFFICIENT * Math.Pow(O, 2) * (1 - p1[i]) * p1[i]);
                            max_eat = max_eat / Math.Min(w.WinLimit / LIMIT_SCALE, sp_w_max);
                            if (eat_amount_win >= max_eat)
                            {
                                full_win = true;
                                continue;
                            }
                            else
                            {
                                eat_amount = Math.Min(max_eat - eat_amount_win, w.WinAmount);
                            }
                        }

                        if (w.PlcAmount > 0)
                        {
                            double O       = 1 + w.Percent / 100 / Math.Min(w.PlcLimit / LIMIT_SCALE, sp_p_max);
                            double max_eat = (T * Math.Pow(O * (1 - p3[i]) - 1, 2)) / (LOSS_RATE_COEFFICIENT * Math.Pow(O, 2) * (1 - p3[i]) * p3[i]);
                            max_eat = max_eat / Math.Min(w.PlcLimit / LIMIT_SCALE, sp_p_max);
                            if (eat_amount_plc >= max_eat)
                            {
                                full_plc = true;
                                continue;
                            }
                            else
                            {
                                if (eat_amount == -1)
                                {
                                    eat_amount = Math.Min(max_eat - eat_amount_plc, w.PlcAmount);
                                }
                                else
                                {
                                    eat_amount = Math.Min(eat_amount, Math.Min(max_eat - eat_amount_plc, w.PlcAmount));
                                }
                            }
                        }

                        if (eat_amount > 0)
                        {
                            eat_amount = Math.Round(eat_amount / WP_STEP) * WP_STEP;
                            if (eat_amount > 0)
                            {
                                InvestRecordWp ir = new InvestRecordWp()
                                {
                                    TimeKey     = tp,
                                    Model       = MODEL,
                                    CardID      = race.CardID,
                                    RaceNo      = race.RaceNo,
                                    Direction   = "EAT",
                                    HorseNo     = h.No,
                                    Percent     = w.Percent,
                                    WinLimit    = w.WinLimit,
                                    PlcLimit    = w.PlcLimit,
                                    FittingLoss = item.Odds.E
                                };

                                if (w.WinLimit > 0)
                                {
                                    ir.WinAmount    = eat_amount;
                                    ir.WinOdds      = sp_w_max;
                                    ir.WinProbility = p1[i];
                                }
                                if (w.PlcLimit > 0)
                                {
                                    ir.PlcAmount    = eat_amount;
                                    ir.PlcOdds      = sp_p_max;
                                    ir.PlcProbility = p3[i];
                                }

                                wp_records.Add(ir);

                                eat_amount_win += ir.WinAmount;
                                eat_amount_plc += ir.PlcAmount;
                            }
                        }
                    }
                }
            }

            List <InvestRecordQn> qn_records = new List <InvestRecordQn>();

            common.Math.Combination comb2 = new common.Math.Combination(item.Odds.Count, 2);
            int[][] combinations          = comb2.GetCombinations();
            for (int i = 0; i < combinations.Length; i++)
            {
                int[]  c       = combinations[i];
                string horseNo = string.Format("{0}-{1}", item.Odds[c[0]].No, item.Odds[c[1]].No);

                if (pq_win != null)
                {
                    double sp_min = Math.Min(item.Odds.SpQ[horseNo], item2.Odds.SpQ[horseNo]);
                    double sp_max = Math.Max(item.Odds.SpQ[horseNo], item2.Odds.SpQ[horseNo]);

                    // For Bet
                    {
                        WaterQnList vlist      = item.Waters.GetQnEatWater(horseNo).GetValuableWater(MIN_R, sp_min, pq_win[i]);
                        double      bet_amount = 0;
                        foreach (WaterQnItem w in vlist.OrderBy(x => x.Percent))
                        {
                            double O       = Math.Min(w.Limit / LIMIT_SCALE, sp_min) * 100 / w.Percent;
                            double max_bet = (T * Math.Pow(O * pq_win[i] - 1, 2)) / (LOSS_RATE_COEFFICIENT * Math.Pow(O, 2) * pq_win[i] * (1 - pq_win[i]));

                            if (bet_amount >= max_bet)
                            {
                                break;
                            }

                            double current_amount = Math.Min(max_bet - bet_amount, w.Amount);
                            current_amount = Math.Round(current_amount / QN_STEP) * QN_STEP;
                            if (current_amount > 0)
                            {
                                InvestRecordQn ir = new InvestRecordQn()
                                {
                                    TimeKey     = tp,
                                    Model       = MODEL,
                                    CardID      = race.CardID,
                                    RaceNo      = race.RaceNo,
                                    Direction   = "BET",
                                    Type        = "Q",
                                    HorseNo     = horseNo,
                                    Percent     = w.Percent,
                                    Amount      = current_amount,
                                    Limit       = w.Limit,
                                    Odds        = sp_min,
                                    Probility   = pq_win[i],
                                    FittingLoss = item.Odds.E
                                };
                                qn_records.Add(ir);
                                bet_amount += ir.Amount;
                            }
                        }
                    }

                    // For Eat
                    {
                        WaterQnList vlist      = item.Waters.GetQnBetWater(horseNo).GetValuableWater(MIN_R, sp_max, pq_win[i]);
                        double      eat_amount = 0;
                        foreach (WaterQnItem w in vlist.OrderByDescending(x => x.Percent))
                        {
                            double O       = 1 + w.Percent / 100 / Math.Min(w.Limit / LIMIT_SCALE, sp_max);
                            double max_eat = (T * Math.Pow(O * (1 - pq_win[i]) - 1, 2)) / (LOSS_RATE_COEFFICIENT * Math.Pow(O, 2) * (1 - pq_win[i]) * pq_win[i]);
                            max_eat = max_eat / Math.Min(w.Limit / LIMIT_SCALE, sp_max);
                            if (eat_amount >= max_eat)
                            {
                                break;
                            }

                            double current_amount = Math.Min(max_eat - eat_amount, w.Amount);
                            current_amount = Math.Round(current_amount / QN_STEP) * QN_STEP;
                            if (current_amount > 0)
                            {
                                InvestRecordQn ir = new InvestRecordQn()
                                {
                                    TimeKey     = tp,
                                    Model       = MODEL,
                                    CardID      = race.CardID,
                                    RaceNo      = race.RaceNo,
                                    Direction   = "EAT",
                                    Type        = "Q",
                                    HorseNo     = horseNo,
                                    Percent     = w.Percent,
                                    Amount      = current_amount,
                                    Limit       = w.Limit,
                                    Odds        = sp_max,
                                    Probility   = pq_win[i],
                                    FittingLoss = item.Odds.E
                                };
                                qn_records.Add(ir);
                                eat_amount += ir.Amount;
                            }
                        }
                    }
                }

                if (pq_plc != null)
                {
                    double sp_min = Math.Min(item.Odds.SpQp[horseNo], item2.Odds.SpQp[horseNo]);
                    double sp_max = Math.Max(item.Odds.SpQp[horseNo], item2.Odds.SpQp[horseNo]);

                    // For Bet
                    {
                        WaterQnList vlist      = item.Waters.GetQpEatWater(horseNo).GetValuableWater(MIN_R, sp_min, pq_plc[i]);
                        double      bet_amount = 0;
                        foreach (WaterQnItem w in vlist.OrderBy(x => x.Percent))
                        {
                            double O       = Math.Min(w.Limit / LIMIT_SCALE, sp_min) * 100 / w.Percent;
                            double max_bet = (T * Math.Pow(O * pq_plc[i] - 1, 2)) / (LOSS_RATE_COEFFICIENT * Math.Pow(O, 2) * pq_plc[i] * (1 - pq_plc[i]));

                            if (bet_amount >= max_bet)
                            {
                                break;
                            }

                            double current_amount = Math.Min(max_bet - bet_amount, w.Amount);
                            current_amount = Math.Round(current_amount / QN_STEP) * QN_STEP;
                            if (current_amount > 0)
                            {
                                InvestRecordQn ir = new InvestRecordQn()
                                {
                                    TimeKey     = tp,
                                    Model       = MODEL,
                                    CardID      = race.CardID,
                                    RaceNo      = race.RaceNo,
                                    Direction   = "BET",
                                    Type        = "QP",
                                    HorseNo     = horseNo,
                                    Percent     = w.Percent,
                                    Amount      = current_amount,
                                    Limit       = w.Limit,
                                    Odds        = sp_min,
                                    Probility   = pq_plc[i],
                                    FittingLoss = item.Odds.E
                                };
                                qn_records.Add(ir);
                                bet_amount += ir.Amount;
                            }
                        }
                    }

                    // For Eat
                    {
                        WaterQnList vlist      = item.Waters.GetQpBetWater(horseNo).GetValuableWater(MIN_R, sp_max, pq_win[i]);
                        double      eat_amount = 0;
                        foreach (WaterQnItem w in vlist.OrderByDescending(x => x.Percent))
                        {
                            double O       = 1 + w.Percent / 100 / Math.Min(w.Limit / LIMIT_SCALE, sp_max);
                            double max_eat = (T * Math.Pow(O * (1 - pq_plc[i]) - 1, 2)) / (LOSS_RATE_COEFFICIENT * Math.Pow(O, 2) * (1 - pq_plc[i]) * pq_plc[i]);
                            max_eat = max_eat / Math.Min(w.Limit / LIMIT_SCALE, sp_max);
                            if (eat_amount >= max_eat)
                            {
                                break;
                            }

                            double current_amount = Math.Min(max_eat - eat_amount, w.Amount);
                            current_amount = Math.Round(current_amount / QN_STEP) * QN_STEP;
                            if (current_amount > 0)
                            {
                                InvestRecordQn ir = new InvestRecordQn()
                                {
                                    TimeKey     = tp,
                                    Model       = MODEL,
                                    CardID      = race.CardID,
                                    RaceNo      = race.RaceNo,
                                    Direction   = "EAT",
                                    Type        = "QP",
                                    HorseNo     = horseNo,
                                    Percent     = w.Percent,
                                    Amount      = current_amount,
                                    Limit       = w.Limit,
                                    Odds        = sp_max,
                                    Probility   = pq_plc[i],
                                    FittingLoss = item.Odds.E
                                };
                                qn_records.Add(ir);
                                eat_amount += ir.Amount;
                            }
                        }
                    }
                }
            }

            using (MySqlConnection conn = new MySqlConnection("server=120.24.210.35;user id=hrsdata;password=abcd0000;database=hrsdata;port=3306;charset=utf8"))
            {
                conn.Open();

                using (MySqlCommand cmd = new MySqlCommand(@"
insert into sl_invest_wp (time_key,model,cd_id,rc_no,direction,hs_no,percent,w_limit,p_limit,rc_time,fitting_loss,w_amt,w_od,w_prob,p_amt,p_od,p_prob)
values (?time_key,?model,?cd_id,?rc_no,?direction,?hs_no,?percent,?w_limit,?p_limit,?rc_time,?fitting_loss,?w_amt,?w_od,?w_prob,?p_amt,?p_od,?p_prob)
on duplicate key update rc_time=?rc_time,fitting_loss=?fitting_loss,w_amt=?w_amt,w_od=?w_od,w_prob=?w_prob,p_amt=?p_amt,p_od=?p_od,p_prob=?p_prob,lmt=CURRENT_TIMESTAMP()
", conn))
                {
                    cmd.Parameters.Add("?time_key", MySqlDbType.Int64);
                    cmd.Parameters.Add("?model", MySqlDbType.Int32);
                    cmd.Parameters.Add("?cd_id", MySqlDbType.UInt64);
                    cmd.Parameters.Add("?rc_no", MySqlDbType.Int32);
                    cmd.Parameters.Add("?direction", MySqlDbType.VarChar, 10);
                    cmd.Parameters.Add("?hs_no", MySqlDbType.Int32);
                    cmd.Parameters.Add("?percent", MySqlDbType.Decimal);
                    cmd.Parameters.Add("?w_limit", MySqlDbType.Decimal);
                    cmd.Parameters.Add("?p_limit", MySqlDbType.Decimal);
                    cmd.Parameters.Add("?rc_time", MySqlDbType.DateTime);
                    cmd.Parameters.Add("?fitting_loss", MySqlDbType.Decimal);
                    cmd.Parameters.Add("?w_amt", MySqlDbType.Decimal);
                    cmd.Parameters.Add("?w_od", MySqlDbType.Decimal);
                    cmd.Parameters.Add("?w_prob", MySqlDbType.Decimal);
                    cmd.Parameters.Add("?p_amt", MySqlDbType.Decimal);
                    cmd.Parameters.Add("?p_od", MySqlDbType.Decimal);
                    cmd.Parameters.Add("?p_prob", MySqlDbType.Decimal);

                    foreach (InvestRecordWp ir in wp_records)
                    {
                        cmd.Parameters["?time_key"].Value     = ir.TimeKey;
                        cmd.Parameters["?model"].Value        = ir.Model;
                        cmd.Parameters["?cd_id"].Value        = ir.CardID;
                        cmd.Parameters["?rc_no"].Value        = ir.RaceNo;
                        cmd.Parameters["?direction"].Value    = ir.Direction;
                        cmd.Parameters["?hs_no"].Value        = int.Parse(ir.HorseNo);
                        cmd.Parameters["?percent"].Value      = ir.Percent;
                        cmd.Parameters["?w_limit"].Value      = ir.WinLimit;
                        cmd.Parameters["?p_limit"].Value      = ir.PlcLimit;
                        cmd.Parameters["?rc_time"].Value      = race.StartTime;
                        cmd.Parameters["?fitting_loss"].Value = ir.FittingLoss;
                        cmd.Parameters["?w_amt"].Value        = ir.WinAmount;
                        cmd.Parameters["?w_od"].Value         = ir.WinOdds;
                        cmd.Parameters["?w_prob"].Value       = ir.WinProbility;
                        cmd.Parameters["?p_amt"].Value        = ir.PlcAmount;
                        cmd.Parameters["?p_od"].Value         = ir.PlcOdds;
                        cmd.Parameters["?p_prob"].Value       = ir.PlcProbility;

                        cmd.ExecuteNonQuery();
                    }
                }

                using (MySqlCommand cmd = new MySqlCommand(@"
insert into sl_invest_qn(time_key,model,cd_id,rc_no,direction,q_type,hs_no,percent,q_limit,rc_time,fitting_loss,amt,od,prob)
values (?time_key,?model,?cd_id,?rc_no,?direction,?q_type,?hs_no,?percent,?q_limit,?rc_time,?fitting_loss,?amt,?od,?prob)
on duplicate key update rc_time=?rc_time,fitting_loss=?fitting_loss,amt=?amt,od=?od,prob=?prob,lmt=CURRENT_TIMESTAMP()
", conn))
                {
                    cmd.Parameters.Add("?time_key", MySqlDbType.Int64);
                    cmd.Parameters.Add("?model", MySqlDbType.Int32);
                    cmd.Parameters.Add("?cd_id", MySqlDbType.UInt64);
                    cmd.Parameters.Add("?rc_no", MySqlDbType.Int32);
                    cmd.Parameters.Add("?direction", MySqlDbType.VarChar, 10);
                    cmd.Parameters.Add("?q_type", MySqlDbType.VarChar, 10);
                    cmd.Parameters.Add("?hs_no", MySqlDbType.VarChar, 20);
                    cmd.Parameters.Add("?percent", MySqlDbType.Decimal);
                    cmd.Parameters.Add("?q_limit", MySqlDbType.Decimal);
                    cmd.Parameters.Add("?rc_time", MySqlDbType.DateTime);
                    cmd.Parameters.Add("?fitting_loss", MySqlDbType.Decimal);
                    cmd.Parameters.Add("?amt", MySqlDbType.Decimal);
                    cmd.Parameters.Add("?od", MySqlDbType.Decimal);
                    cmd.Parameters.Add("?prob", MySqlDbType.Decimal);

                    foreach (InvestRecordQn ir in qn_records)
                    {
                        cmd.Parameters["?time_key"].Value     = ir.TimeKey;
                        cmd.Parameters["?model"].Value        = ir.Model;
                        cmd.Parameters["?cd_id"].Value        = ir.CardID;
                        cmd.Parameters["?rc_no"].Value        = ir.RaceNo;
                        cmd.Parameters["?direction"].Value    = ir.Direction;
                        cmd.Parameters["?q_type"].Value       = ir.Type;
                        cmd.Parameters["?hs_no"].Value        = ir.HorseNo;
                        cmd.Parameters["?percent"].Value      = ir.Percent;
                        cmd.Parameters["?q_limit"].Value      = ir.Limit;
                        cmd.Parameters["?rc_time"].Value      = race.StartTime;
                        cmd.Parameters["?fitting_loss"].Value = ir.FittingLoss;
                        cmd.Parameters["?amt"].Value          = ir.Amount;
                        cmd.Parameters["?od"].Value           = ir.Odds;
                        cmd.Parameters["?prob"].Value         = ir.Probility;

                        cmd.ExecuteNonQuery();
                    }
                }
            }
        }
Exemplo n.º 3
0
        public static void calcProbility(double[] ee, double[] dd, int PLC_CNT, out double[] p1, out double[] p3, out double[] pq_win, out double[] pq_plc)
        {
            int CNT = ee.Length;

            p1 = new double[CNT];
            p3 = new double[CNT];

            // 需要计算各种组合细节
            common.Math.Combination combq = new common.Math.Combination(CNT, 2);
            pq_win = new double[combq.Length];
            pq_plc = new double[combq.Length];

            common.Math.Combination comb_plc = new common.Math.Combination(CNT - 1, PLC_CNT - 1);
            int[][] _plc_combinations        = comb_plc.GetCombinations();
            common.Math.Combination comb2    = null;
            int[][] _2_combinations          = null;
            if (PLC_CNT > 3)
            {
                comb2           = new common.Math.Combination(PLC_CNT - 1, 2);
                _2_combinations = comb2.GetCombinations();
            }

            for (int i = 0; i < CNT; i++)
            {
                common.Math.Calculus.MultiFunc f_top_3 = new common.Math.Calculus.MultiFunc(delegate(double x)
                {
                    double gx = exp(-(x - ee[i]) * (x - ee[i]) / (2 * dd[i] * dd[i])) / (SQRT_2_PI * dd[i]);

                    double[] ret;     // 前两个为WIN和PLC的概率

                    if (PLC_CNT <= 3)
                    {
                        ret = new double[comb_plc.Length + 2];
                    }
                    else
                    {
                        // 如果PLC_CNT超过3,为了计算前两名的概率,还必须计算我第二名时,其他马第一名的概率
                        ret = new double[comb_plc.Length + CNT - 1 + 2];
                    }

                    double[] V, T;

                    calcFx(CNT, PLC_CNT, i, x, ee, dd, out V, out T);

                    ret[0] = T[0];
                    ret[1] = T.Sum();

                    // 计算我跑第三(PLC_CNT)时,前两(PLC_CNT-1)名各种组合的概率
                    double tmp  = 1; // 去掉不可能赢之后的概率连乘
                    int v0count = 0, // 我赢概率为0的数量,即肯定超过我的数量
                    v1count     = 0; // 不可能超过我的数量
                    for (int j = 0; j < CNT - 1; j++)
                    {
                        if (V[j] == 0)
                        {
                            v0count++;
                        }
                        else if (V[j] == 1)
                        {
                            v1count++;
                        }
                        else
                        {
                            tmp *= V[j];
                        }
                    }
                    // 肯定超过我的数量v0count大于PLC_CNT-1,我的名次肯定低于PLC_CNT,我跑第PLC_CNT的概率为0
                    // 不可能超过的数量v1count大于CNT-PLC_CNT,我的名次肯定高于PLC_CNT
                    if (v0count < PLC_CNT && v1count <= CNT - PLC_CNT)
                    {
                        for (int j = 0, j2 = 2; j < comb_plc.Length; j++, j2++)
                        {
                            int[] c      = _plc_combinations[j];
                            int cv0count = 0;
                            ret[j2]      = tmp;
                            for (int k = 0; k < PLC_CNT - 1; k++)
                            {
                                if (V[c[k]] == 0)
                                {
                                    cv0count++;
                                }
                                else if (V[c[k]] == 1)  // 我肯定赢的人在我前面,这个组合不可能存在
                                {
                                    ret[j2] = 0;
                                    break;
                                }
                                else
                                {
                                    ret[j2] /= V[c[k]];
                                    ret[j2] *= (1 - V[c[k]]);
                                }
                            }

                            if (cv0count < v0count)  // 如果组合中没有包含全部肯定赢我的人,这个组合不可能存在
                            {
                                ret[j2] = 0;
                            }
                        }
                    }
                    // 计算我第二名时各个人第一名的概率
                    if (PLC_CNT > 3 && v0count < 2 && v1count <= CNT - 2)
                    {
                        for (int j = 0, j2 = 2 + (int)comb_plc.Length; j < CNT - 1; j++, j2++)
                        {
                            if (v0count == 1)
                            {
                                if (V[j] == 0)
                                {
                                    ret[j2] = tmp;
                                }
                                else
                                {
                                    ret[j2] = 0;
                                }
                            }
                            else
                            {
                                if (V[j] == 1)
                                {
                                    ret[j2] = 0;
                                }
                                else
                                {
                                    ret[j2] = tmp / V[j] * (1 - V[j]);
                                }
                            }
                        }
                    }

                    return(new common.Math.vector(ret) * gx);
                });

                common.Math.vector pv = common.Math.Calculus.integrate(f_top_3, ee[i] - dd[i] * 7, ee[i] + dd[i] * 7, Math.Pow(10, -PRECISION), 5);
                p1[i] = pv[0];
                p3[i] = pv[1];

                if (PLC_CNT > 3)
                {
                    // PLC_CNT大于3,Q的概率需要通过我第二名时,其他各马第一名的概率计算

                    int[] c = new int[2];
                    c[0] = i;

                    // Q的概率
                    for (int j = 0, j2 = 2 + (int)comb_plc.Length; j < PLC_CNT - 1; j++, j2++)
                    {
                        for (int k = 0; k < PLC_CNT - 1; k++)
                        {
                            if (k < i)
                            {
                                c[1] = k;
                            }
                            else
                            {
                                c[1] = k + 1;
                            }

                            pq_win[combq.Index(c)] += pv[j2];
                        }
                    }

                    // QP的概率
                    for (int j = 0, j2 = 2; j < comb_plc.Length; j++, j2++)
                    {
                        // 和我的组合
                        c[0] = i;
                        for (int k = 0; k < PLC_CNT - 1; k++)
                        {
                            if (_plc_combinations[j][k] < i)
                            {
                                c[1] = _plc_combinations[j][k];
                            }
                            else
                            {
                                c[1] = _plc_combinations[j][k] + 1;
                            }

                            pq_plc[combq.Index(c)] += pv[j2];
                        }

                        // 没有我的组合
                        for (int k = 0; k < _2_combinations.Length; k++)
                        {
                            if (_plc_combinations[j][_2_combinations[k][0]] < i)
                            {
                                c[0] = _plc_combinations[j][_2_combinations[k][0]];
                            }
                            else
                            {
                                c[0] = _plc_combinations[j][_2_combinations[k][0]] + 1;
                            }

                            if (_plc_combinations[j][_2_combinations[k][1]] < i)
                            {
                                c[1] = _plc_combinations[j][_2_combinations[k][1]];
                            }
                            else
                            {
                                c[1] = _plc_combinations[j][_2_combinations[k][1]] + 1;
                            }

                            pq_plc[combq.Index(c)] += pv[j2];
                        }
                    }
                }
                else if (PLC_CNT == 3)
                {
                    // PLC_CNT等于3,Q的概率根据我第三名时,前两名的概率计算

                    int[] c = new int[2];

                    for (int j = 0, j2 = 2; j < comb_plc.Length; j++, j2++)
                    {
                        // 和我的组合
                        c[0] = i;
                        for (int k = 0; k < PLC_CNT - 1; k++)
                        {
                            if (_plc_combinations[j][k] < i)
                            {
                                c[1] = _plc_combinations[j][k];
                            }
                            else
                            {
                                c[1] = _plc_combinations[j][k] + 1;
                            }

                            pq_plc[combq.Index(c)] += pv[j2];
                        }

                        // 没有我的组合
                        if (_plc_combinations[j][0] < i)
                        {
                            c[0] = _plc_combinations[j][0];
                        }
                        else
                        {
                            c[0] = _plc_combinations[j][0] + 1;
                        }

                        if (_plc_combinations[j][1] < i)
                        {
                            c[1] = _plc_combinations[j][1];
                        }
                        else
                        {
                            c[1] = _plc_combinations[j][1] + 1;
                        }

                        pq_win[combq.Index(c)] += pv[j2];
                        pq_plc[combq.Index(c)] += pv[j2];
                    }
                }
                else if (PLC_CNT == 2)
                {
                    // PLC_CNT等于2,Q/QP是一样的

                    int[] c = new int[2];
                    c[0] = i;

                    for (int j = 0, j2 = 2; j < comb_plc.Length; j++, j2++)
                    {
                        // 只有和我的组合
                        if (_plc_combinations[j][0] < i)
                        {
                            c[1] = _plc_combinations[j][0];
                        }
                        else
                        {
                            c[1] = _plc_combinations[j][0] + 1;
                        }

                        pq_win[combq.Index(c)] += pv[j2];
                    }
                }
            }
        }
Exemplo n.º 4
0
        private static void calcProbilityForFitting(double[] ee, double[] dd, out double[] p1, out double[] pq)
        {
            int CNT = ee.Length;

            p1 = new double[CNT];

            common.Math.Combination combq = new common.Math.Combination(CNT, 2);
            pq = new double[combq.Length];

            for (int i = 0; i < CNT; i++)
            {
                common.Math.Calculus.MultiFunc f_top_3 = new common.Math.Calculus.MultiFunc(delegate(double x)
                {
                    double gx = exp(-(x - ee[i]) * (x - ee[i]) / (2 * dd[i] * dd[i])) / (SQRT_2_PI * dd[i]);

                    double[] ret = new double[CNT];     // 第一个为WIN的概率,后面CNT-1个是我第二名时第一名的是各匹马的概率

                    double[] V, T;

                    calcFx(CNT, 2, i, x, ee, dd, out V, out T);

                    ret[0] = T[0];

                    // 计算我跑第二时,第一名各马的概率
                    double tmp  = 1; // 去掉不可能赢之后的概率连乘
                    int v0count = 0, // 我赢概率为0的数量,即肯定超过我的数量
                    v1count     = 0; // 不可能超过我的数量
                    for (int j = 0; j < CNT - 1; j++)
                    {
                        if (V[j] == 0)
                        {
                            v0count++;
                        }
                        else if (V[j] == 1)
                        {
                            v1count++;
                        }
                        else
                        {
                            tmp *= V[j];
                        }
                    }
                    // 肯定超过我的数量v0count大于1,我的名次肯定低于2,我跑第2的概率为0
                    // 不可能超过的数量v1count大于CNT-2,我的名次肯定高于2
                    if (v0count <= 1 && v1count <= CNT - 2)
                    {
                        for (int j = 0, j2 = 1; j < CNT - 1; j++, j2++)
                        {
                            if (v0count == 1)
                            {
                                if (V[j] == 0)
                                {
                                    ret[j2] = tmp;
                                }
                                else
                                {
                                    ret[j2] = 0;
                                }
                            }
                            else
                            {
                                if (V[j] == 1)
                                {
                                    ret[j2] = 0;
                                }
                                else
                                {
                                    ret[j2] = tmp / V[j] * (1 - V[j]);
                                }
                            }
                        }
                    }

                    return(new common.Math.vector(ret) * gx);
                });

                common.Math.vector pv = common.Math.Calculus.integrate(f_top_3, ee[i] - dd[i] * 7, ee[i] + dd[i] * 7, Math.Pow(10, -PRECISION), 5);
                p1[i] = pv[0];

                int[] c = new int[2];
                c[0] = i;

                for (int j = 0, j2 = 1; j < CNT - 1; j++, j2++)
                {
                    // 只有和我的组合
                    if (j < i)
                    {
                        c[1] = j;
                    }
                    else
                    {
                        c[1] = j + 1;
                    }

                    pq[combq.Index(c)] += pv[j2];
                }
            }
        }
Exemplo n.º 5
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 });
            }
        }
Exemplo n.º 6
0
        private void calc(double[] ee, double[] dd, out double[] p1, out double[] p3, out double[] p3detail)
        {
            p1 = new double[CNT];
            p3 = new double[CNT];
            common.Math.Combination comb3 = new common.Math.Combination(CNT, PLC_CNT);
            p3detail = new double[comb3.Length];

            common.Math.Combination comb2 = new common.Math.Combination(CNT - 1, PLC_CNT - 1);
            int[][] _2_combinations       = comb2.GetCombinations();

            for (int i = 0; i < CNT; i++)
            {
                common.Math.Calculus.Func r = new common.Math.Calculus.Func(delegate(double x)
                {
                    double ret = 1;
                    for (int j = 0; j < CNT; j++)
                    {
                        if (j == i)
                        {
                            continue;
                        }
                        ret += this.gauss(ee[j], dd[j], x);
                    }
                    return(ret);
                });

                // @deprecated f_top1没用了,在f_top3中计算了
                common.Math.Calculus.Func f_top1 = new common.Math.Calculus.Func(delegate(double x)
                {
                    double gx = this.exp(-(x - ee[i]) * (x - ee[i]) / (2 * dd[i] * dd[i])) / (SQRT_2_PI * dd[i]);
                    double rx = 1;
                    for (int j = 0; j < CNT; j++)
                    {
                        if (j == i)
                        {
                            continue;
                        }
                        rx *= 1 - this.gauss(ee[j], dd[j], x);
                    }
                    return(gx * rx);

                    // 这里应该是将我跑x的成绩时,赢每个人的概率连乘,转换为其中0个人赢我的泊松分布概率  2017-3-7
                    // 这样子不行的,比如假设A赢我概率0.5,B赢我概率0.5,没有人能赢我的概率是0.5*0.5 = 0.25
                    // 转换后,A赢我的期望0.5+B赢我的期望0.5=1,泊松分布概率P(0)=0.368,差蛮远
                    //double rv = Math.Exp(-r(x));

                    //return gx * rv;
                });

                common.Math.Calculus.MultiFunc f_top_3 = new common.Math.Calculus.MultiFunc(delegate(double x)
                {
                    double gx = this.exp(-(x - ee[i]) * (x - ee[i]) / (2 * dd[i] * dd[i])) / (SQRT_2_PI * dd[i]);

                    double[] ret = new double[comb2.Length + 2];     // 前两个为WIN和PLC的概率

                    // 选2 Tree最后的结果就是有两个人赢我的概率
                    // 选1 Tree最后的结果是有一个人赢我的概率
                    // LS最后结果是没人赢我的概率
                    //
                    //          不选A  - “选2 Tree”   V(A)*2T
                    //       /
                    //  root                              +                  不选B - “选1 Tree”
                    //       \                                            /
                    //          选A  -  “选1 Tree”  (1-V(A))*1T    ---
                    //                                                    \ 
                    //                                                       选B - 连乘
                    //2T(n-2) = (1-V(n-1)) * (1-V(n-2))
                    //2T(d) = V(d)*2T(d+1)+(1-V(d))*1T(d+1)
                    //1T(n-1) = (1-V(n-1))
                    //1T(d) = V(d)*1T(d+1)+(1-V(d))*LS(d+1)
                    //LS(n-1) = V(n-1)
                    //LS(d) = V(d)*LS(d+1)
                    // 目标计算2T(0)
                    //
                    // 扩展3T、4T、jT
                    // jT(n-j) = (1-V(n-1))*...*(1-V(n-j))
                    // jT(d) = V(d)*jT(d+1)+(1-V(d))*(j-1)T(d+1)

                    double[] V = new double[CNT - 1];   // 我赢i的概率
                    for (int j = 0; j < CNT; j++)
                    {
                        if (j < i)
                        {
                            V[j] = 1 - this.gauss(ee[j], dd[j], x);
                        }
                        else if (j > i)
                        {
                            V[j - 1] = 1 - this.gauss(ee[j], dd[j], x);
                        }
                        else // if (j == i)
                        {
                            continue;
                        }
                    }

                    int n      = CNT - 1;
                    double[] T = new double[PLC_CNT];
                    for (int j = 0; j < PLC_CNT; j++)
                    {
                        T[j] = 1;
                        for (int k = 1; k <= j; k++)
                        {
                            T[j] *= 1 - V[n - k];
                        }
                    }
                    for (int j = n - 1; j >= 0; j--)
                    {
                        for (int k = 0; k < PLC_CNT; k++)
                        {
                            if (k == 0)
                            {
                                T[k] *= V[j];
                            }
                            else if (j - k >= 0)
                            {
                                T[k] = V[j - k] * T[k] + (1 - V[j - k]) * T[k - 1];
                            }
                        }
                    }

                    ret[0] = T[0];
                    ret[1] = T.Sum();

                    // 计算我跑第三(PLC_CNT)时,前两(PLC_CNT-1)名各种组合的概率
                    double tmp      = 1;
                    int[] v0indices = new int[CNT - 1];
                    int v0count     = 0, // 我赢概率为0的数量,即肯定超过我的数量
                    v1count         = 0; // 不可能超过我的数量
                    for (int j = 0; j < CNT - 1; j++)
                    {
                        if (V[j] == 0)
                        {
                            v0indices[v0count++] = j;
                        }
                        else if (V[j] == 1)
                        {
                            v1count++;
                        }
                        else
                        {
                            tmp *= V[j];
                        }
                    }
                    // 肯定超过我的数量v0count大于PLC_CNT-1,我的名次肯定低于PLC_CNT,我跑第PLC_CNT的概率为0
                    // 不可能超过的数量v1count大于CNT-PLC_CNT,我的名次肯定高于PLC_CNT
                    if (v0count < PLC_CNT && v1count <= CNT - PLC_CNT)
                    {
                        for (int j = 0; j < comb2.Length; j++)
                        {
                            int[] c      = _2_combinations[j];
                            int cv0count = 0;
                            ret[j + 2]   = tmp;
                            for (int k = 0; k < PLC_CNT - 1; k++)
                            {
                                if (V[c[k]] == 0)
                                {
                                    cv0count++;
                                }
                                else if (V[c[k]] == 1)
                                {
                                    ret[j + 2] = 0;
                                    break;
                                }
                                else
                                {
                                    ret[j + 2] /= V[c[k]];
                                    ret[j + 2] *= (1 - V[c[k]]);
                                }
                            }

                            if (cv0count < v0count)
                            {
                                ret[j + 2] = 0;
                            }
                        }
                    }

                    return(new common.Math.vector(ret) * gx);
                });

                //p1[i] = common.Math.Calculus.integrate(f_top1, ee[i] - dd[i] * 8, ee[i] + dd[i] * 8, Math.Pow(10, -PRECISION), 5);
                //p3[i] = common.Math.Calculus.integrate(f_top3, ee[i] - dd[i] * 8, ee[i] + dd[i] * 8, Math.Pow(10, -PRECISION), 5);

                common.Math.vector pv = common.Math.Calculus.integrate(f_top_3, ee[i] - dd[i] * 7, ee[i] + dd[i] * 7, Math.Pow(10, -PRECISION), 5);
                p1[i] = pv[0];
                p3[i] = pv[1];

                for (int j = 0; j < comb2.Length; j++)
                {
                    int[] c = new int[PLC_CNT];
                    c[0] = i;
                    for (int k = 0; k < PLC_CNT - 1; k++)
                    {
                        if (_2_combinations[j][k] < i)
                        {
                            c[k + 1] = _2_combinations[j][k];
                        }
                        else
                        {
                            c[k + 1] = _2_combinations[j][k] + 1;
                        }
                    }

                    p3detail[comb3.Index(c)] += pv[j + 2];
                }
            }
        }
Exemplo n.º 7
0
        private void btn逆向过程_Click(object sender, EventArgs e)
        {
            this.btn逆向过程.Enabled = false;

            if (_t_o == null)
            {
                _t_o = new Thread(new ThreadStart(delegate
                {
                    try
                    {
                        this.Invoke(new MethodInvoker(delegate
                        {
                            this.btn逆向过程.Enabled = true;
                            this.btn逆向过程.Text    = "停止";
                        }));

                        double[] fp1 = rows["TOP1概率"];
                        double[] fp3 = rows["TOP3概率"];
                        double[] s1  = rows["TOP1 SP"];
                        double[] s3  = rows["TOP3 SP"];

                        double[] ee = new double[CNT];
                        double[] dd = new double[CNT];

                        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];
                        }

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

                        // 计算投注比例
                        double po3   = (1 - rr3) / ((sorted_s3.Skip(2).Sum(x => 1 / (3 * x - 2)) - 1) * (3 * o3 - 2));
                        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 * (3 * o3 - 2) / (3 * s3[i] - 2);
                            }
                        }

                        // 设定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)
                        {
                            MessageBox.Show("没想到找不到排行第3的项");
                            return;
                        }

                        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;
                        }

                        double lastE      = double.MaxValue;
                        int[] dir_d_rr_ee = new int[CNT], dir_d_rr_dd = new int[CNT];
                        for (int t = 0; ; t++)
                        {
                            double[] p1, p3, p3detail;
                            this.calc(ee, dd, out p1, out p3, out p3detail);
                            double E = 0;

                            // 交叉熵损失以及交叉熵损失对与各个概率的梯度
                            double[] grad_p1 = new double[CNT], grad_p3 = new double[CNT];
                            for (int i = 0; i < CNT; i++)
                            {
                                E         += -(ph1[i] * Math.Log(p1[i]) + (1 - ph1[i]) * Math.Log(1 - p1[i]));
                                E         += -(ph3[i] * Math.Log(p3[i]) + (1 - ph3[i]) * Math.Log(1 - p3[i]));
                                grad_p1[i] = -(ph1[i] / p1[i] - (1 - ph1[i]) / (1 - p1[i]));
                                grad_p3[i] = -(ph3[i] / p3[i] - (1 - ph3[i]) / (1 - p3[i]));
                            }

                            //double rr = this.calc_rr(s1, p1, s3, p3);
                            double maxr1 = double.MinValue, minr1 = double.MaxValue, maxr3 = double.MinValue, minr3 = double.MaxValue;
                            int maxr1_i  = -1, minr1_i = -1, maxr3_i = -1, minr3_i = -1;
                            double[] r1  = new double[CNT], r3 = new double[CNT]; // 这个是每个马的回报率,非赔付率
                            common.Math.Combination comb = new common.Math.Combination(CNT, PLC_CNT);
                            int[][] combs = comb.GetCombinations();
                            for (int i = 0; i < CNT; i++)
                            {
                                r1[i] = s1[i] * p1[i];
                                r3[i] = this.calc_plc_r(rr3, i, ph3, p3detail, combs);
                                if (r1[i] > maxr1)
                                {
                                    maxr1   = r1[i];
                                    maxr1_i = i;
                                }
                                if (r1[i] < minr1)
                                {
                                    minr1   = r1[i];
                                    minr1_i = i;
                                }
                                if (r3[i] > maxr3)
                                {
                                    maxr3   = r3[i];
                                    maxr3_i = i;
                                }
                                if (r3[i] < minr3)
                                {
                                    minr3   = r3[i];
                                    minr3_i = i;
                                }
                            }


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

                                ee[i] += EE_D_INC;
                                this.calc(ee, dd, out tp1, out tp3, out tp3detail);
                                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];
                                    // 第j匹马的PLC概率对第i匹马的均值的梯度 = (tp3[j] - p3[j]) / EE_D_INC
                                    d_rr_ee[i] += (tp3[j] - p3[j]) / EE_D_INC * grad_p3[j];
                                }
                                ee[i] -= EE_D_INC;

                                dd[i] += DD_D_INC;
                                this.calc(ee, dd, out tp1, out tp3, out tp3detail);
                                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];
                                    // 第j匹马的PLC概率对第i匹马的方差的梯度 = (tp3[j] - p3[j]) / DD_D_INC
                                    d_rr_dd[i] += (tp3[j] - p3[j]) / DD_D_INC * grad_p3[j];
                                }
                                dd[i] -= DD_D_INC;
                            }

                            // 调整各参数
                            for (int i = 0; i < CNT; i++)
                            {
                                // if (i == trd_inx) continue;
                                if (d_rr_ee[i] > 0 && dir_d_rr_ee[i] >= 0)
                                {
                                    dir_d_rr_ee[i]++;
                                }
                                else if (d_rr_ee[i] < 0 && dir_d_rr_ee[i] <= 0)
                                {
                                    dir_d_rr_ee[i]--;
                                }
                                else
                                {
                                    dir_d_rr_ee[i] = 0;
                                }

                                if (d_rr_dd[i] > 0 && dir_d_rr_dd[i] >= 0)
                                {
                                    dir_d_rr_dd[i]++;
                                }
                                else if (d_rr_dd[i] < 0 && dir_d_rr_dd[i] <= 0)
                                {
                                    dir_d_rr_dd[i]--;
                                }
                                else
                                {
                                    dir_d_rr_dd[i] = 0;
                                }

                                // 向负梯度方向调整
                                ee[i] += -d_rr_ee[i] * EE_STEP / (1 + t * STEP_DECAY) * (1 + Math.Abs(dir_d_rr_ee[i]) * STEP_DECAY);
                                dd[i] += -d_rr_dd[i] * DD_STEP / (1 + t * STEP_DECAY) * (1 + Math.Abs(dir_d_rr_dd[i]) * 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;

                            //E = r1.Sum(x => (x - rr1) * (x - rr1)) + r3.Sum(x => (x - rr3) * (x - rr3));
                            this.Invoke(new MethodInvoker(delegate
                            {
                                for (int i = 0; i < CNT; i++)
                                {
                                    lves[i].Text  = string.Format("{0:0.0000}", ee[i]);
                                    lvds[i].Text  = string.Format("{0:0.0000}", dd[i]);
                                    lres[i].Text  = string.Format("{0:0.0000}", d_rr_ee[i]);
                                    lrds[i].Text  = string.Format("{0:0.0000}", d_rr_dd[i]);
                                    lpws[i].Text  = string.Format("{0:0.0000}", p1[i] * 100);
                                    lpps[i].Text  = string.Format("{0:0.0000}", p3[i] * 100);
                                    lrcws[i].Text = string.Format("{0:0.0000}", p1[i] * s1[i]);
                                    lrcps[i].Text = string.Format("{0:0.0000}", p3[i] * s3[i]);
                                    lrfws[i].Text = string.Format("{0:0.0000}", fp1[i] * s1[i]);
                                    lrfps[i].Text = string.Format("{0:0.0000}", fp3[i] * s3[i]);
                                }

                                for (int i = 0; i < CNT; i++)
                                {
                                    if (i != maxr1_i && i != minr1_i)
                                    {
                                        lpws[i].BackColor = Color.White;
                                    }
                                    if (i != maxr3_i && i != minr3_i)
                                    {
                                        lpps[i].BackColor = Color.White;
                                    }
                                }
                                lpws[maxr1_i].BackColor = Color.Yellow;
                                lpws[minr1_i].BackColor = Color.Red;
                                lpps[maxr3_i].BackColor = Color.Yellow;
                                lpps[minr3_i].BackColor = Color.Red;

                                for (int i = lEs.Length - 1; i > 0; i--)
                                {
                                    lEs[i].Text = lEs[i - 1].Text;
                                }
                                lEs[0].Text = string.Format("{2}: {0:0.0000} | {1:0.0000000}", E, 1 / (1 + t * STEP_DECAY), t);
                                lpwSum.Text = string.Format("{0:0.0000}", p1.Sum() * 100);
                                lppSum.Text = string.Format("{0:0.0000}", p3.Sum() * 100);
                            }));

                            if (E > lastE)
                            {
                                break;
                            }
                        }
                    }
                    finally
                    {
                        _t_o = null;

                        try
                        {
                            this.Invoke(new MethodInvoker(delegate
                            {
                                this.btn逆向过程.Enabled = true;
                                this.btn逆向过程.Text    = "逆向过程";
                            }));
                        }
                        catch
                        {
                        }
                    }
                }));
                _t_o.IsBackground = true;
                _t_o.Start();
            }
            else
            {
                _t_o.Abort();
            }
        }