class Oddsmaker::Market

Market is a container of multiple odds. This is useful to represent the full data of sports betting. A generic moneyline of +300/-400 can be represented by a market, containing both of the individual odds. This also allows for calculating the total probability, which will be over 100% if set by a sportsbook. Additional functions include the ability to determine the odds without vig (the book's profit), and the ability to calculate odds for a given overround (the total probability above 100%).

Attributes

name[R]
odds[R]
vigged[R]

Public Class Methods

new(*odds, name: nil) click to toggle source
# File lib/oddsmaker/market.rb, line 10
def initialize(*odds, name: nil)
  @name = name
  @odds = odds.flatten
end

Public Instance Methods

==(other) click to toggle source

Compare equality to another market

@param other [Market] @return [Boolean]

# File lib/oddsmaker/market.rb, line 76
def ==(other)
  odds.sort == other.odds.sort
end
odd(id) click to toggle source

Retrieve an odd by identifier.

@param id [String, Integer] Odd identifier. Defaults to provided value. @return [Odd]

# File lib/oddsmaker/market.rb, line 19
def odd(id)
  odds_hash[id]
end
overround!(v = 5) click to toggle source

Create market with an added overround amount

@param v [Integer] Overround percent @return [Market] New market with overrounded odds

# File lib/oddsmaker/market.rb, line 60
def overround!(v = 5)
  @vigged = self.class.new(overround_odds!(v))
end
overround_odds!(v = 5) click to toggle source

Calculate the odds with given overround

@param v [Integer] Overround percent @return [Array<Odd>] Overrounded odds

# File lib/oddsmaker/market.rb, line 68
def overround_odds!(v = 5)
  without_vig_odds.map { |odd| odd.overround!(v) }
end
to_h() click to toggle source

Hash representation of a market. @return [Hash]

# File lib/oddsmaker/market.rb, line 82
def to_h
  full_odds = if self.total_probability != 1 && self.odds.size > 1
    no_vig = self.without_vig_odds
    odds.map.with_index { |odd, index| odd.to_h.merge(actual: no_vig[index].implied_probability.value, without_vig: no_vig[index].value) }
  else
    odds.map(&:to_h)
  end
  {
    name:               self.name,
    total_probability:  self.total_probability,
    vig:                self.vig,
    odds:               full_odds,
  }
end
to_json() click to toggle source

JSON representation of a market. @return [String]

# File lib/oddsmaker/market.rb, line 99
def to_json
  to_h.to_json
end
total_probability() click to toggle source

Total probability for a set of odds. This will be over 1 if set by a sportsbook.

@return [Float] Total probability, with 1.0 representing 100%

# File lib/oddsmaker/market.rb, line 27
def total_probability
  @total_probability ||= @odds.inject(0) { |total, odd| total + odd.implied_probability.value } # Change to #sum when 2.3 support can be dropped
end
vig() click to toggle source

Total vig (maximum vig under balanced book scenario)

@return [Float]

# File lib/oddsmaker/market.rb, line 52
def vig
  1 - total_probability**-1
end
without_vig() click to toggle source

Calculate equivalent market without any overround (vig).

@return [Market] New market with total probability == 1.0

# File lib/oddsmaker/market.rb, line 34
def without_vig
  self.class.new(without_vig_odds)
end
without_vig_odds() click to toggle source

Calculate the odds without any overround (vig).

@return [<Odd>] Array of odds with the vig removed

# File lib/oddsmaker/market.rb, line 41
def without_vig_odds
  @without_vig_odds = if total_probability != 1.0
    @odds.map { |odd| odd.without_vig(total_probability) }
  else
    @odds
  end
end

Private Instance Methods

odds_hash() click to toggle source

Hash of odds by name or identifier

@return [Hash{String=>Odd}]

# File lib/oddsmaker/market.rb, line 108
def odds_hash
  @odds_hash ||= @odds.map { |o| [o.id, o] }.to_h.tap do |hash|
    raise 'Must use unique odds identifiers' if hash.size != @odds.size # TODO create custom error classes
  end
end