From 923aa1b2d3dda40d058befd10b1593032408e1b4 Mon Sep 17 00:00:00 2001 From: Emil Koutanov Date: Tue, 2 Jan 2024 11:47:01 +1100 Subject: [PATCH] Pricing multi from a selections file --- .gitignore | 2 ++ Cargo.toml | 1 + brumby-soccer/Cargo.toml | 1 + brumby-soccer/src/bin/soc_prices.rs | 52 ++++++++++++++++++++--------- 4 files changed, 41 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index e380581..1c51f29 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ Cargo.lock /.idea /coverage lcov.info + +selections.json diff --git a/Cargo.toml b/Cargo.toml index f16be4e..21a1878 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ tracing-subscriber = "0.3.17" bytes = "1.5.0" linregress = "0.5.3" ordinalizer = "0.1.0" +regex = "1.10.2" strum = "0.25.0" strum_macros = "0.25.3" serde = { version = "1.0.189", features = ["derive"] } diff --git a/brumby-soccer/Cargo.toml b/brumby-soccer/Cargo.toml index d0baf47..a225038 100644 --- a/brumby-soccer/Cargo.toml +++ b/brumby-soccer/Cargo.toml @@ -17,6 +17,7 @@ anyhow = { workspace = true } clap = { workspace = true } ordinalizer = { workspace = true } racing_scraper = { workspace = true } +regex = { workspace = true } rustc-hash = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } diff --git a/brumby-soccer/src/bin/soc_prices.rs b/brumby-soccer/src/bin/soc_prices.rs index fbc663c..1a2b8c8 100644 --- a/brumby-soccer/src/bin/soc_prices.rs +++ b/brumby-soccer/src/bin/soc_prices.rs @@ -1,10 +1,13 @@ -use std::collections::HashMap; use std::env; +use std::collections::HashMap; use std::error::Error; +use std::fs::File; +use std::io::{BufRead, BufReader}; use std::path::PathBuf; -use anyhow::bail; +use anyhow::{bail, Context}; use clap::Parser; +use regex::Regex; use rustc_hash::FxHashMap; use stanza::renderer::console::Console; use stanza::renderer::Renderer; @@ -16,14 +19,14 @@ use brumby::hash_lookup::HashLookup; use brumby::market::{Market, OverroundMethod, PriceBounds}; use brumby::tables; use brumby::timed::Timed; -use brumby_soccer::data::{download_by_id, ContestSummary, SoccerFeedId}; -use brumby_soccer::domain::{Offer, OfferType, Outcome, Over, Period, Player, Side}; +use brumby_soccer::{fit, model, print}; +use brumby_soccer::data::{ContestSummary, download_by_id, SoccerFeedId}; +use brumby_soccer::domain::{Offer, OfferType, Outcome}; use brumby_soccer::fit::{ErrorType, FittingErrors}; +use brumby_soccer::model::{Model, score_fitter, Stub}; use brumby_soccer::model::player_assist_fitter::PlayerAssistFitter; use brumby_soccer::model::player_goal_fitter::PlayerGoalFitter; use brumby_soccer::model::score_fitter::ScoreFitter; -use brumby_soccer::model::{score_fitter, Model, Stub}; -use brumby_soccer::{fit, model, print}; const OVERROUND_METHOD: OverroundMethod = OverroundMethod::OddsRatio; const SINGLE_PRICE_BOUNDS: PriceBounds = 1.01..=301.0; @@ -48,6 +51,9 @@ struct Args { /// print player assists markets #[clap(long = "player-assists")] player_assists: bool, + + /// JSON file containing the selections to price + selections: Option, } impl Args { fn validate(&self) -> anyhow::Result<()> { @@ -60,6 +66,21 @@ impl Args { } } +fn load_selections(filename: &str) -> anyhow::Result> { + let file = File::open(filename).context(format!("opening file '{filename}'"))?; + let reader = BufReader::new(file); + let mut contents = String::new(); + let comment = Regex::new(r"^.*#")?; + for line in reader.lines() { + let line = line?; + if !comment.is_match(&line) { + contents.push_str(&line); + } + } + let selections = serde_json::from_str(&contents)?; + Ok(selections) +} + #[tokio::main] async fn main() -> Result<(), Box> { if env::var("RUST_BACKTRACE").is_err() { @@ -218,15 +239,16 @@ async fn main() -> Result<(), Box> { ); } - let selections = [ - // (OfferType::TotalGoals(Period::FullTime, Over(2)), Outcome::Over(2)), - (OfferType::HeadToHead(Period::FullTime), Outcome::Win(Side::Home)), - (OfferType::FirstGoalscorer, Outcome::Player(Player::Named(Side::Away, String::from("João Pedro")))), - (OfferType::AnytimeGoalscorer, Outcome::Player(Player::Named(Side::Away, String::from("Welbeck")))), - // (OfferType::AnytimeGoalscorer, Outcome::Player(Player::Named(Side::Home, String::from("Bowen")))), - ]; - let encoded = serde_json::to_string(&selections)?; - info!("selections: {encoded}"); + // let selections = [ + // // (OfferType::TotalGoals(Period::FullTime, Over(2)), Outcome::Over(2)), + // (OfferType::HeadToHead(Period::FullTime), Outcome::Win(Side::Home)), + // (OfferType::FirstGoalscorer, Outcome::Player(Player::Named(Side::Away, String::from("João Pedro")))), + // (OfferType::AnytimeGoalscorer, Outcome::Player(Player::Named(Side::Away, String::from("Welbeck")))), + // // (OfferType::AnytimeGoalscorer, Outcome::Player(Player::Named(Side::Home, String::from("Bowen")))), + // ]; + // let encoded = serde_json::to_string(&selections)?; + // info!("selections: {encoded}"); + let selections = load_selections(args.selections.as_ref().unwrap())?; let price = model.derive_multi(&selections)?; let scaling_exponent = compute_scaling_exponent(price.relatedness);