odds_converter

Crates.ioodds_converter
lib.rsodds_converter
version0.1.0
created_at2025-06-11 06:50:05.861949+00
updated_at2025-06-11 06:50:05.861949+00
descriptionA fast, accurate Rust library for converting between American, Decimal, and Fractional betting odds formats
homepagehttps://github.com/armichaud/odds_converter
repositoryhttps://github.com/armichaud/odds_converter
max_upload_size
id1708242
size121,793
Alexander Michaud (armichaud)

documentation

https://docs.rs/odds_converter

README

Odds Converter

A Rust library for converting between different betting odds formats with robust error handling and comprehensive validation.

Crates.io Documentation License: MIT

Features

  • Multiple Formats: Support for American, Decimal, and Fractional odds
  • Bidirectional Conversion: Convert between any two formats
  • Implied Probability: Calculate implied probabilities from odds
  • String Parsing: Parse odds from common string representations
  • Robust Validation: Comprehensive input validation and error handling
  • Minimal Dependencies: Pure Rust implementation with minimal dependencies

Quick Start

Add this to your Cargo.toml:

[dependencies]
odds_converter = "0.1.0"

Usage

Basic Conversions

use odds_converter::Odds;

// Create odds in different formats
let american = Odds::new_american(150);    // +150 American odds
let decimal = Odds::new_decimal(2.5);      // 2.50 decimal odds
let fractional = Odds::new_fractional(3, 2); // 3/2 fractional odds

// Convert between formats
assert_eq!(american.to_decimal().unwrap(), 2.5);
assert_eq!(decimal.to_american().unwrap(), 150);
assert_eq!(fractional.to_decimal().unwrap(), 2.5);

// Calculate implied probability
assert_eq!(decimal.implied_probability().unwrap(), 0.4); // 40%

String Parsing

use odds_converter::Odds;

// Parse from strings
let odds1: Odds = "+150".parse().unwrap();    // American format
let odds2: Odds = "2.50".parse().unwrap();    // Decimal format  
let odds3: Odds = "3/2".parse().unwrap();     // Fractional format

// Display as strings
println!("{}", odds1); // "+150"
println!("{}", odds2); // "2.50"
println!("{}", odds3); // "3/2"

Error Handling

use odds_converter::{Odds, OddsError};

// Validation catches invalid odds
let invalid = Odds::new_decimal(0.5);
match invalid.validate() {
    Err(OddsError::InvalidDecimalOdds(msg)) => {
        println!("Error: {}", msg); // "Decimal odds must be >= 1.0"
    }
    _ => {}
}

// Parsing handles malformed input
let result: Result<Odds, _> = "invalid".parse();
assert!(result.is_err());

Real-World Examples

use odds_converter::Odds;

// Convert Vegas odds to European format
let vegas_line = Odds::new_american(-110);
let european_odds = vegas_line.to_decimal().unwrap();
println!("European odds: {:.2}", european_odds); // 1.91

// Calculate probability for UK fractional odds
let uk_odds = Odds::new_fractional(9, 4);
let probability = uk_odds.implied_probability().unwrap();
println!("Implied probability: {:.1}%", probability * 100.0); // 30.8%

// Parse user input and convert
let user_input = "+200";
let odds: Odds = user_input.parse().unwrap();
let decimal_equivalent = odds.to_decimal().unwrap();
println!("{} American = {:.2} Decimal", user_input, decimal_equivalent);

Edge Case Handling

The library automatically handles edge cases in American odds between -99 to +99 (excluding zero):

use odds_converter::Odds;

// Positive odds 1-99 are normalized to equivalent negative odds
let odds_pos = Odds::new_american(50);  // Automatically becomes -200
assert_eq!(odds_pos.to_american().unwrap(), -200);

// Negative odds -1 to -99 are normalized to equivalent positive odds  
let odds_neg = Odds::new_american(-50); // Automatically becomes +200
assert_eq!(odds_neg.to_american().unwrap(), 200);

// This ensures conversions never produce invalid odds in the problematic range
let decimal = Odds::new_decimal(1.25);
let american = decimal.to_american().unwrap(); // Returns -400, not +25

Odds Formats

American Odds (Moneyline)

  • Positive numbers: Profit on a $100 bet (e.g., +150 = $150 profit)
  • Negative numbers: Amount to bet to win $100 (e.g., -200 = bet $200 to win $100)
  • Edge case handling: Values between -99 to +99 (excluding zero) are automatically normalized to their standard representation
  • Common in: United States

Decimal Odds (European)

  • Format: Total return including stake (e.g., 2.50 = $2.50 return on $1 bet)
  • Range: Always ≥ 1.0
  • Common in: Europe, Australia, Canada

Fractional Odds (UK)

  • Format: Profit ratio as fraction (e.g., 3/2 = win $3 for every $2 bet)
  • Notation: numerator/denominator
  • Common in: United Kingdom, Ireland

API Reference

Core Types

  • Odds - Main struct for holding odds in any format
  • OddsFormat - Enum representing the three odds formats
  • OddsError - Error types for validation and parsing failures

Methods

  • new_american(value: i32) - Create American odds
  • new_decimal(value: f64) - Create decimal odds
  • new_fractional(num: u32, den: u32) - Create fractional odds
  • to_american() - Convert to American format
  • to_decimal() - Convert to decimal format
  • to_fractional() - Convert to fractional format
  • implied_probability() - Calculate implied probability
  • validate() - Validate odds values
  • format() - Get underlying format

String Operations

  • parse() - Parse from string (via FromStr trait)
  • to_string() - Format as string (via Display trait)

Mathematical Accuracy

The library handles floating-point precision carefully and includes comprehensive tests for mathematical correctness:

  • Property-based testing ensures conversion accuracy
  • Round-trip conversions maintain precision within reasonable tolerances
  • Edge cases are properly handled (e.g., very small/large odds)

Error Handling

Comprehensive error types provide detailed information about failures:

  • InvalidAmericanOdds - Zero, -100, or out-of-range American odds
  • InvalidDecimalOdds - Less than 1.0, infinite, or NaN decimal odds
  • InvalidFractionalOdds - Invalid fractional values
  • ZeroDenominator - Division by zero in fractions
  • ParseError - Malformed string input
  • ValueOutOfRange - Unreasonably large values

Performance

Conversions are highly optimized with minimal allocations:

  • Typical conversion time: ~1.6-2.0 nanoseconds
  • Zero-allocation for numeric conversions
  • Efficient string parsing with detailed error messages

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Commit count: 10

cargo fmt