def test_close_by_left_then_fresh_right_tiebreak(self): qstat1 = QuadServiceStat() qstat1.update_with( prev_score=sc.Score("6-4 5-6"), prev_ingame=("30", "40"), prev_left_service=True, score=sc.Score("6-4 6-6"), ingame=("0", "2"), left_service=True, ) # closing: left hold by win 3 points: ADV(2), DEUCE(1) # freshing: right by win 1 point: DEUCE(1) # freshing: left by loss 1 point: ADV(0) self.assertEqual(WinLoss(2, 1), qstat1.srv_win_loss(co.LEFT, co.ADV)) self.assertEqual(WinLoss(1, 0), qstat1.srv_win_loss(co.LEFT, co.DEUCE)) self.assertEqual(WinLoss(1, 0), qstat1.srv_win_loss(co.RIGHT, co.DEUCE)) self.assertEqual(WinLoss(0, 0), qstat1.srv_win_loss(co.RIGHT, co.ADV))
def test_close_by_left_then_fresh_right(self): qstat1 = QuadServiceStat() qstat1.update_with( prev_score=sc.Score("5-1"), prev_ingame=("30", "40"), prev_left_service=False, score=sc.Score("6-1 0-0"), ingame=("0", "40"), left_service=True, ) # closing: right broken by 3 points self.assertEqual(WinLoss(0, 2), qstat1.srv_win_loss(co.RIGHT, co.ADV)) self.assertEqual(WinLoss(0, 1), qstat1.srv_win_loss(co.RIGHT, co.DEUCE)) # freshing: left loss 3 points self.assertEqual(WinLoss(0, 2), qstat1.srv_win_loss(co.LEFT, co.ADV)) self.assertEqual(WinLoss(0, 1), qstat1.srv_win_loss(co.LEFT, co.DEUCE))
def test_get_puig_sharapova(self): plr1 = Player(ident=10222, name="Monica Puig", cou="PUR") plr2 = Player(ident=503, name="Maria Sharapova", cou="RUS") mstat = get( sex="wta", tour_id=9125, rnd=Round("Second"), first_player_id=plr1.ident, second_player_id=plr2.ident, year_weeknum=tt.get_year_weeknum(datetime.date(2014, 5, 14)), ) self.assertNotEqual(mstat, None) self.assertEqual(mstat.left_side.aces, 3) self.assertEqual(mstat.right_side.aces, 5) self.assertEqual(mstat.left_side.first_service_in, WinLoss(32, 24)) self.assertEqual(mstat.right_side.first_service_in, WinLoss(38, 25)) self.assertEqual(mstat.left_side.bp_win, WinLoss(2, 5)) self.assertEqual(mstat.right_side.bp_win, WinLoss(4, 3)) self.assertEqual(mstat.total_points_won(), (51, 68))
def test_close_previous(self): stat1 = HoldStat() stat1.close_previous(sc.Score("1-1"), prev_left_service=True, prev_left_wingame=True) # 1/1, 0/0 stat1.close_previous(sc.Score("2-1"), prev_left_service=False, prev_left_wingame=False) # 1/1, 1/1 stat1.close_previous(sc.Score("2-2"), prev_left_service=True, prev_left_wingame=False) # 1/2, 1/1 stat1.close_previous(sc.Score("2-3"), prev_left_service=False, prev_left_wingame=False) # 1/2, 2/2 stat1.close_previous(sc.Score("2-4"), prev_left_service=True, prev_left_wingame=True) # 2/3, 2/2 stat1.close_previous(sc.Score("6-6"), prev_left_service=True, prev_left_wingame=False) # skip tie res_pair = stat1.result_pair(setnum=1, as_float=False) self.assertEqual(res_pair, (WinLoss(2, 1), WinLoss(2, 0)))
def test_get_baroni_williams(self): """baroni win 6-4 6-3""" plr1 = Player(ident=180, name="Mirjana Lucic-Baroni", cou="CRO") plr2 = Player(ident=151, name="Venus Williams", cou="USA") mstat = get( sex="wta", tour_id=9148, rnd=Round("Final"), first_player_id=plr1.ident, second_player_id=plr2.ident, year_weeknum=tt.get_year_weeknum(datetime.date(2014, 9, 14)), ) self.assertNotEqual(mstat, None) self.assertEqual(mstat.left_side.aces, 6) self.assertEqual(mstat.right_side.aces, 5) self.assertEqual(mstat.left_side.bp_win, WinLoss(4, 7)) self.assertEqual(mstat.right_side.bp_win, WinLoss(2, 2)) self.assertEqual(mstat.left_side.first_service_win, WinLoss(31, 9)) self.assertEqual(mstat.right_side.first_service_win, WinLoss(23, 14)) self.assertEqual(mstat.left_side.second_service_win, WinLoss(10, 13)) self.assertEqual(mstat.right_side.second_service_win, WinLoss(11, 21)) self.assertEqual(mstat.left_side.double_faults, 4) self.assertEqual(mstat.right_side.double_faults, 2) self.assertEqual(mstat.total_points_won(), (76, 56))
def test_compare(self): wl1 = WinLoss.create_from_text("41.2% (17)") wl2 = WinLoss.create_from_text("37.8% (339)") self.assertTrue(wl1 > wl2) self.assertTrue(wl2 < wl1) self.assertEqual([wl2, wl1], sorted([wl1, wl2]))
def run_stat(): from bet import FlatLimitedProfiter assert predicts_db_hnd is not None, 'not opened db' def get_rnd(rnd_db): return rnd_db.split(';')[0] def get_prof_coef_result(): nonlocal set2_loss_mched_cnt if rec.case_name == 'decided_00': return rec.bf_live_coef_matched, bool(rec.predict_result) elif rec.case_name == 'secondset_00': coef = 1 + (rec.bf_live_coef_matched - 1) * 0.4 iswin = bool(rec.predict_result) if not iswin: set2_loss_mched_cnt += 1 win_one_of = 4 if (set2_loss_mched_cnt % win_one_of) == 0: # assume win 1 of win_one_of by hedging, our plr looks ok iswin = True return coef, iswin return None, None def do_profiter(): if rec.bf_live_coef_matched is not None: prof_coef, prof_res = get_prof_coef_result() if prof_coef is not None: profiter.calculate_bet(coef=prof_coef, iswin=prof_res) set2_loss_mched_cnt = 0 wl = WinLoss() surf_wl_dct = defaultdict(WinLoss) rnd_wl_dct = defaultdict(WinLoss) bystartbook_wl = WinLoss() book_start_chances = [] profiter = FlatLimitedProfiter(start_money=9) predicts_db_hnd.query_predicts() for rec in predicts_db_hnd.records: if (rec.predict_result in (0, 1) and (not args.sex or (args.sex == rec.sex)) and (not args.casename or (rec.case_name == args.casename)) and (args.rejected is None or (args.rejected == 1 and rec.rejected == args.rejected) or (args.rejected == 0 and rec.rejected in (-1, 0))) and (not args.minproba or (rec.predict_proba >= args.minproba)) and (not args.maxproba or (rec.predict_proba <= args.maxproba)) and (args.opener is None or (args.opener and ('OPENER' in rec.comments)) or (not args.opener and ('CLOSER' in rec.comments)))): predict_ok = bool(rec.predict_result) if args.stat_use_matchwinner_only: predict_ok = bool(rec.back_win_match) # print(f"{rec.back_name} {rec.oppo_name} -> {predict_ok}") wl.hit(iswin=predict_ok) surf_wl_dct[rec.surface].hit(iswin=predict_ok) rnd_wl_dct[get_rnd(rec.rnd)].hit(iswin=predict_ok) book_start_chances.append(rec.book_start_chance) do_profiter() if (rec.back_win_match in (0, 1) and abs(rec.book_start_chance - 0.5) > 0.001): bystartbook_win = (bool(rec.back_win_match) is (rec.book_start_chance > 0.5)) bystartbook_wl.hit(bystartbook_win) print(f"stat: {wl} nw: {wl.win_count} nl: {wl.loss_count}") pprint([(s, str(w).strip()) for s, w in surf_wl_dct.items()]) pprint([(r, str(w).strip()) for r, w in rnd_wl_dct.items()]) if book_start_chances: avg_book_start_chance = round( sum(book_start_chances) / len(book_start_chances), 3) else: avg_book_start_chance = None print(f"avg book_start_chance: {avg_book_start_chance}") print(f"profit by matched coefs: {profiter}") print(f"bystartbook wl : {bystartbook_wl}")
def __init__(self): self.fst_wl = WinLoss() self.snd_wl = WinLoss()
class CalcSrvRatio(Calc): feat_corename = "srv_ratio" # win ratio complete_usial_game: Dict[Scr, Scr] = { (0, 3): (8, 6), # from 0:40 (1, 3): (8, 6), # from 15:40 (2, 3): (6, 4), # from 30:40 (0, 2): (7, 5), # from 0:30 (1, 2): (5, 3), # from 15:30 (0, 1): (6, 4), # from 0:15 (0, 0): (4, 2), # from 0:0 (1, 0): (4, 1), # from 15:0 (1, 1): (4, 2), # from 15:15 (2, 0): (4, 1), # from 30:0 (2, 1): (4, 2), # from 30:15 (2, 2): (5, 3), # from 30:30 (3, 3): (6, 4), # from 40:40 (3, 2): (4, 2), # from 40:30 (3, 1): (4, 1), # from 40:15 (3, 0): (4, 0), # from 40:0 } @staticmethod def complete_usial_fin_score(fin_scr: Scr) -> Scr: """suppose: game winner is left in fin_scr""" if fin_scr[0] >= 4 and fin_scr[0] >= (fin_scr[1] + 2): return fin_scr # ok need not complete res_fin_scr = CalcSrvRatio.complete_usial_game.get(fin_scr) if res_fin_scr is not None: return res_fin_scr if abs(fin_scr[0] - fin_scr[1]) <= 1: x = max(4, fin_scr[0] + 2) return x, fin_scr[1] log.warn( f"lose fin {fin_scr} game winner CalcSrvRatio::complete_usial_fin_score" ) return 5, 4 def __init__(self): self.fst_wl = WinLoss() self.snd_wl = WinLoss() def result_features(self, prefix: str) -> List[Feature]: f1, f2 = make_pair( fst_name=f"{prefix}_fst_{self.feat_corename}", snd_name=f"{prefix}_snd_{self.feat_corename}", fst_value=self.fst_wl.ratio, snd_value=self.snd_wl.ratio, ) return [f1, f2] def cumul_result_features(self, prefix: str, others: "List[CalcSrvRatio]") -> List[Feature]: fst_wl = reduce(lambda x, y: x + y, [o.fst_wl for o in others], self.fst_wl) snd_wl = reduce(lambda x, y: x + y, [o.snd_wl for o in others], self.snd_wl) f1, f2 = make_pair( fst_name=f"{prefix}_fst_{self.feat_corename}", snd_name=f"{prefix}_snd_{self.feat_corename}", fst_value=fst_wl.ratio, snd_value=snd_wl.ratio, ) return [f1, f2] def proc_set(self, setitems: SetItems): for _, dg in setitems: if not dg.tiebreak: self._proc_usial_game(dg) else: self._proc_tiebreak(setitems, dg) def _proc_tiebreak(self, setitems: SetItems, dg): scr = (0, 0) for pnt in dg: if pnt.serve(left=True): srv_win = pnt.win(left=True) self.fst_wl.hit(srv_win) scr = (scr[0] + 1, scr[1]) if srv_win else (scr[0], scr[1] + 1) else: srv_win = pnt.win(left=False) self.snd_wl.hit(srv_win) scr = (scr[0], scr[1] + 1) if srv_win else (scr[0] + 1, scr[1]) if scr <= setitems.tie_scr and scr != setitems.tie_scr: # approximate finishing x_add, y_add = setitems.tie_scr[0] - scr[0], setitems.tie_scr[ 1] - scr[1] x_win, x_lose = x_add // 2, y_add // 2 self.fst_wl.add_win(x_win) self.fst_wl.add_loss(x_lose) y_win, y_lose = y_add // 2, x_add // 2 self.snd_wl.add_win(y_win) self.snd_wl.add_loss(y_lose) def _proc_usial_game(self, dg): fin_scr = dg.final_num_score(before=False) or (0, 0) wl = self.fst_wl if dg.left_opener else self.snd_wl if dg.hold: res_fin_scr = self.complete_usial_fin_score(fin_scr) else: # game winner is right in fin_scr res_fin_scr = self.complete_usial_fin_score( co.reversed_tuple(fin_scr)) res_fin_scr = co.reversed_tuple( res_fin_scr) # we got again right dominate wl.add_win(res_fin_scr[0]) wl.add_loss(res_fin_scr[1])