Skip to content

Commit

Permalink
Derivation of split handicaps
Browse files Browse the repository at this point in the history
  • Loading branch information
ekoutanov committed Feb 2, 2024
1 parent 47819c5 commit e42dbd6
Show file tree
Hide file tree
Showing 6 changed files with 318 additions and 53 deletions.
10 changes: 4 additions & 6 deletions brumby-soccer/src/bin/soc_prices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
| OfferType::TotalGoals(_, _)
| OfferType::CorrectScore(_)
| OfferType::AsianHandicap(_, _)
| OfferType::DrawNoBet(_) => 1.0,
| OfferType::DrawNoBet(_)
| OfferType::SplitHandicap(_, _, _) => 1.0,
OfferType::AnytimeGoalscorer
| OfferType::FirstGoalscorer
| OfferType::PlayerShotsOnTarget(_)
Expand Down Expand Up @@ -169,6 +170,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
| OfferType::TotalGoals(_, _)
| OfferType::AsianHandicap(_, _)
| OfferType::DrawNoBet(_)
| OfferType::SplitHandicap(_, _, _)
| OfferType::CorrectScore(_)
| OfferType::FirstGoalscorer
| OfferType::AnytimeGoalscorer
Expand Down Expand Up @@ -338,11 +340,7 @@ fn fit_offer(offer_type: OfferType, map: &HashMap<Outcome, f64>, normal: f64) ->
}
}

fn sort_tuples<K, V, I>(tuples: I) -> Vec<(K, V)>
where
I: IntoIterator<Item = (K, V)>,
K: Ord,
{
fn sort_tuples<K: Ord, V>(tuples: impl IntoIterator<Item = (K, V)>) -> Vec<(K, V)> {
let tuples = tuples.into_iter();
let mut tuples = tuples.collect::<Vec<_>>();
tuples.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
Expand Down
21 changes: 19 additions & 2 deletions brumby-soccer/src/domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ impl DrawHandicap {
DrawHandicap::Behind(by) => WinHandicap::BehindUnder(*by)
}
}

pub fn flip(&self) -> DrawHandicap {
match self {
DrawHandicap::Ahead(by) => {
if *by > 0 {
DrawHandicap::Behind(*by)
} else {
DrawHandicap::Ahead(0)
}
},
DrawHandicap::Behind(by) => DrawHandicap::Ahead(*by)
}
}
}

#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
Expand Down Expand Up @@ -83,6 +96,7 @@ pub enum OfferType {
CorrectScore(Period),
AsianHandicap(Period, WinHandicap),
DrawNoBet(DrawHandicap),
SplitHandicap(Period, DrawHandicap, WinHandicap),
AnytimeGoalscorer,
FirstGoalscorer,
PlayerShotsOnTarget(Over),
Expand All @@ -94,8 +108,9 @@ impl OfferType {
OfferType::HeadToHead(_, _) => OfferCategory::HeadToHead,
OfferType::TotalGoals(_, _) => OfferCategory::TotalGoals,
OfferType::CorrectScore(_) => OfferCategory::CorrectScore,
OfferType::DrawNoBet(_) => OfferCategory::DrawNoBet,
OfferType::AsianHandicap(_, _) => OfferCategory::AsianHandicap,
OfferType::DrawNoBet(_) => OfferCategory::DrawNoBet,
OfferType::SplitHandicap(_, _, _) => OfferCategory::SplitHandicap,
OfferType::AnytimeGoalscorer => OfferCategory::AnytimeGoalscorer,
OfferType::FirstGoalscorer => OfferCategory::FirstGoalscorer,
OfferType::PlayerShotsOnTarget(_) => OfferCategory::PlayerShotsOnTarget,
Expand All @@ -104,7 +119,7 @@ impl OfferType {
}

pub fn is_auxiliary(&self) -> bool {
matches!(self, OfferType::DrawNoBet(_))
matches!(self, OfferType::DrawNoBet(_) | OfferType::SplitHandicap(_, _, _))
}
}

Expand All @@ -115,6 +130,7 @@ pub enum OfferCategory {
CorrectScore,
AsianHandicap,
DrawNoBet,
SplitHandicap,
AnytimeGoalscorer,
FirstGoalscorer,
PlayerShotsOnTarget,
Expand All @@ -137,6 +153,7 @@ pub enum Player {
pub enum Outcome {
Win(Side, WinHandicap),
Draw(DrawHandicap),
SplitWin(Side, DrawHandicap, WinHandicap),
Under(u8),
Over(u8),
Score(Score),
Expand Down
82 changes: 65 additions & 17 deletions brumby-soccer/src/interval/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ mod anytime_assist;
mod anytime_goalscorer;
mod correct_score;
mod first_goalscorer;
mod win_draw;
mod total_goals;
mod win_draw;

#[derive(Debug)]
pub enum QuerySpec {
Expand All @@ -27,11 +27,13 @@ pub fn requirements(offer_type: &OfferType) -> Expansions {
OfferType::TotalGoals(period, _) => total_goals::requirements(period),
OfferType::CorrectScore(period) => correct_score::requirements(period),
OfferType::AsianHandicap(period, _) => win_draw::requirements(period),
OfferType::DrawNoBet(_) => panic!("unsupported auxiliary {offer_type:?}"),
OfferType::FirstGoalscorer => first_goalscorer::requirements(),
OfferType::AnytimeGoalscorer => anytime_goalscorer::requirements(),
OfferType::PlayerShotsOnTarget(_) => unimplemented!(),
OfferType::AnytimeAssist => anytime_assist::requirements(),
OfferType::DrawNoBet(_) | OfferType::SplitHandicap(_, _, _) => {
panic!("unsupported auxiliary {offer_type:?}")
}
}
}

Expand All @@ -47,27 +49,36 @@ pub fn prepare(
OfferType::TotalGoals(_, _) => total_goals::prepare(),
OfferType::CorrectScore(_) => correct_score::prepare(),
OfferType::AsianHandicap(_, _) => win_draw::prepare(),
OfferType::DrawNoBet(_) => panic!("unsupported auxiliary {offer_type:?}"),
OfferType::FirstGoalscorer => first_goalscorer::prepare(outcome, player_lookup),
OfferType::AnytimeGoalscorer => anytime_goalscorer::prepare(outcome, player_lookup),
OfferType::PlayerShotsOnTarget(_) => unimplemented!(),
OfferType::AnytimeAssist => anytime_assist::prepare(outcome, player_lookup),
OfferType::DrawNoBet(_) | OfferType::SplitHandicap(_, _, _) => {
panic!("unsupported auxiliary {offer_type:?}")
}
}
}

#[must_use]
#[inline]
pub fn filter(offer_type: &OfferType, outcome: &Outcome, query: &QuerySpec, prospect: &Prospect) -> bool {
pub fn filter(
offer_type: &OfferType,
outcome: &Outcome,
query: &QuerySpec,
prospect: &Prospect,
) -> bool {
match offer_type {
OfferType::HeadToHead(period, _) => win_draw::filter(period, outcome, prospect),
OfferType::TotalGoals(period, _) => total_goals::filter(period, outcome, prospect),
OfferType::CorrectScore(period) => correct_score::filter(period, outcome, prospect),
OfferType::AsianHandicap(period, _) => win_draw::filter(period, outcome, prospect),
OfferType::DrawNoBet(_) => panic!("unsupported auxiliary {offer_type:?}"),
OfferType::AnytimeGoalscorer => anytime_goalscorer::filter(query, prospect),
OfferType::FirstGoalscorer => first_goalscorer::filter(query, prospect),
OfferType::PlayerShotsOnTarget(_) => unimplemented!(),
OfferType::AnytimeAssist => anytime_assist::filter(query, prospect),
OfferType::DrawNoBet(_) | OfferType::SplitHandicap(_, _, _) => {
panic!("unsupported auxiliary {offer_type:?}")
}
}
}

Expand Down Expand Up @@ -97,7 +108,11 @@ pub fn isolate_set(
let queries = selections
.iter()
.map(|(offer_type, outcome)| {
(offer_type, outcome, prepare(offer_type, outcome, player_lookup))
(
offer_type,
outcome,
prepare(offer_type, outcome, player_lookup),
)
})
.collect::<Vec<_>>();
prospects
Expand All @@ -113,9 +128,9 @@ pub fn isolate_set(

#[cfg(test)]
mod tests {
use brumby::sv;
use crate::domain::{DrawHandicap, Period, Score, Side, WinHandicap};
use crate::interval::{explore, Config, BivariateProbs, TeamProbs, UnivariateProbs};
use crate::interval::{explore, BivariateProbs, Config, TeamProbs, UnivariateProbs};
use brumby::sv;

use super::*;

Expand All @@ -125,9 +140,20 @@ mod tests {
&Config {
intervals: 4,
team_probs: TeamProbs {
h1_goals: BivariateProbs { home: 0.25, away: 0.25, common: 0.25 },
h2_goals: BivariateProbs { home: 0.25, away: 0.25, common: 0.25 },
assists: UnivariateProbs { home: 1.0, away: 1.0 },
h1_goals: BivariateProbs {
home: 0.25,
away: 0.25,
common: 0.25,
},
h2_goals: BivariateProbs {
home: 0.25,
away: 0.25,
common: 0.25,
},
assists: UnivariateProbs {
home: 1.0,
away: 1.0,
},
},
player_probs: sv![],
prune_thresholds: Default::default(),
Expand Down Expand Up @@ -167,9 +193,20 @@ mod tests {
&Config {
intervals: 4,
team_probs: TeamProbs {
h1_goals: BivariateProbs { home: 0.25, away: 0.25, common: 0.25 },
h2_goals: BivariateProbs { home: 0.25, away: 0.25, common: 0.25 },
assists: UnivariateProbs { home: 1.0, away: 1.0 },
h1_goals: BivariateProbs {
home: 0.25,
away: 0.25,
common: 0.25,
},
h2_goals: BivariateProbs {
home: 0.25,
away: 0.25,
common: 0.25,
},
assists: UnivariateProbs {
home: 1.0,
away: 1.0,
},
},
player_probs: sv![],
prune_thresholds: Default::default(),
Expand Down Expand Up @@ -229,9 +266,20 @@ mod tests {
&Config {
intervals: 4,
team_probs: TeamProbs {
h1_goals: BivariateProbs { home: 0.25, away: 0.25, common: 0.25 },
h2_goals: BivariateProbs { home: 0.25, away: 0.25, common: 0.25 },
assists: UnivariateProbs { home: 1.0, away: 1.0 },
h1_goals: BivariateProbs {
home: 0.25,
away: 0.25,
common: 0.25,
},
h2_goals: BivariateProbs {
home: 0.25,
away: 0.25,
common: 0.25,
},
assists: UnivariateProbs {
home: 1.0,
away: 1.0,
},
},
player_probs: sv![],
prune_thresholds: Default::default(),
Expand Down
Loading

0 comments on commit e42dbd6

Please sign in to comment.