rodders 3.1.0 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.0
1
+ 3.1.1
@@ -2,34 +2,40 @@
2
2
  # Includes methods for sports betting arbitrage. Due to the discrete nature
3
3
  # of real-world monetary amounts, there may be small rounding errors.
4
4
  class MutuallyExclusiveCollection
5
+ include Enumerable
6
+
5
7
  # create a new collection with the given odds
6
8
  # @param [Array<FixedOdds>] mutually_exclusive_outcome_odds the odds for all the mutually exclusive outcomes
7
9
  def initialize mutually_exclusive_outcome_odds
8
- @mutually_exclusive_outcome_odds = mutually_exclusive_outcome_odds.sort
10
+ @mutually_exclusive_outcome_odds = mutually_exclusive_outcome_odds
11
+ end
12
+
13
+ def each
14
+ @mutually_exclusive_outcome_odds.each {|outcome| yield outcome }
9
15
  end
10
16
 
11
17
  # the least likely of the odds to occur
12
18
  # @return [FixedOdds] the least likely odd
13
19
  def least_likely
14
- @mutually_exclusive_outcome_odds.first
20
+ min
15
21
  end
16
22
 
17
23
  # the most likely of the odds to occur
18
24
  # @return [FixedOdds] the most likely odd
19
25
  def most_likely
20
- @mutually_exclusive_outcome_odds.last
26
+ max
21
27
  end
22
28
 
23
29
  # the odds in ascending order of probability
24
30
  # @return [Array<FixedOdds>] odds in ascending probability
25
31
  def in_ascending_probability
26
- @mutually_exclusive_outcome_odds
32
+ sort
27
33
  end
28
34
 
29
35
  # the odds in descending order of probability
30
36
  # @return [Array<FixedOdds>] odds in descending probability
31
37
  def in_descending_probability
32
- @mutually_exclusive_outcome_odds.reverse
38
+ sort.reverse
33
39
  end
34
40
 
35
41
  # tells if arbitrage is possible for a collection of odds
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "rodders"
8
- s.version = "3.1.0"
8
+ s.version = "3.1.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Nigel Lowry"]
12
- s.date = "2012-11-11"
12
+ s.date = "2013-08-15"
13
13
  s.description = "Converts between fractional, decimal and moneyline odds for betting and gambling. Calculates how much can be won on a given stake."
14
14
  s.email = "nigel-lowry@ultra.eclipse.co.uk"
15
15
  s.extra_rdoc_files = [
@@ -4,138 +4,125 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
4
  describe "MutuallyExclusiveCollection" do
5
5
 
6
6
  context "non-arbitrage methods" do
7
- before(:each) do
8
- @good_team = FixedOdds.from_s '-275'
9
- @draw = FixedOdds.from_s '+429'
10
- @bad_team = FixedOdds.from_s '+915'
7
+ let(:good_team) { FixedOdds.from_s '-275' }
8
+ let(:draw) { FixedOdds.from_s '+429' }
9
+ let(:bad_team) { FixedOdds.from_s '+915' }
10
+ let(:events) { MutuallyExclusiveCollection.new [draw, bad_team, good_team] }
11
11
 
12
- @events = MutuallyExclusiveCollection.new [@draw, @bad_team, @good_team]
13
- end
14
-
15
- subject { @events }
12
+ subject { events }
16
13
 
17
- its(:most_likely) { should == @good_team }
18
- its(:least_likely) { should == @bad_team }
19
- its(:in_descending_probability) { should == [@good_team, @draw, @bad_team] }
20
- its(:in_ascending_probability) { should == [@bad_team, @draw, @good_team] }
14
+ its(:most_likely) { should == good_team }
15
+ its(:least_likely) { should == bad_team }
16
+ its(:in_descending_probability) { should == [good_team, draw, bad_team] }
17
+ its(:in_ascending_probability) { should == [bad_team, draw, good_team] }
21
18
  end
22
19
 
23
20
  context "empty array" do
24
- before(:each) do
25
- @bookmaker = MutuallyExclusiveCollection.new []
26
- end
21
+ subject { MutuallyExclusiveCollection.new [] }
27
22
 
28
- specify { @bookmaker.bookmakers_return_rate.should be_nil }
23
+ its(:bookmakers_return_rate) { should be_nil }
29
24
  end
30
25
 
31
26
  context "decimal odds arbitrage" do
32
- before(:each) do
33
- @bookmaker1outcome1 = FixedOdds.from_s '2.25'
34
- @bookmaker1outcome2 = FixedOdds.from_s '4.9'
35
- @bookmaker2outcome1 = FixedOdds.from_s '2.43'
36
- @bookmaker2outcome2 = FixedOdds.from_s '3.85'
27
+ let(:bookmaker1outcome1) { FixedOdds.from_s '2.25' }
28
+ let(:bookmaker1outcome2) { FixedOdds.from_s '4.9' }
29
+ let(:bookmaker2outcome1) { FixedOdds.from_s '2.43' }
30
+ let(:bookmaker2outcome2) { FixedOdds.from_s '3.85' }
37
31
 
38
- @bookmaker1 = MutuallyExclusiveCollection.new [@bookmaker1outcome1, @bookmaker1outcome2]
39
- @bookmaker2 = MutuallyExclusiveCollection.new [@bookmaker2outcome1, @bookmaker2outcome2]
32
+ let(:bookmaker1) { MutuallyExclusiveCollection.new [bookmaker1outcome1, bookmaker1outcome2] }
33
+ let(:bookmaker2) { MutuallyExclusiveCollection.new [bookmaker2outcome1, bookmaker2outcome2] }
40
34
 
41
- @bookmaker_vulnerable_to_arbitrage = MutuallyExclusiveCollection.new [@bookmaker2outcome1, @bookmaker1outcome2]
42
- end
35
+ let(:bookmaker_vulnerable_to_arbitrage) { MutuallyExclusiveCollection.new [bookmaker2outcome1, bookmaker1outcome2] }
43
36
 
44
- specify { @bookmaker1.should_not be_arbitrageable }
45
- specify { @bookmaker2.should_not be_arbitrageable }
46
- specify { @bookmaker_vulnerable_to_arbitrage.should be_arbitrageable }
37
+ specify { bookmaker1.should_not be_arbitrageable }
38
+ specify { bookmaker2.should_not be_arbitrageable }
39
+ specify { bookmaker_vulnerable_to_arbitrage.should be_arbitrageable }
47
40
 
48
- specify { @bookmaker1.bookmakers_return_rate.should be_within(0.0001).of(0.0534) }
49
- specify { @bookmaker2.bookmakers_return_rate.should be_within(0.0001).of(0.0478) }
41
+ specify { bookmaker1.bookmakers_return_rate.should be_within(0.0001).of(0.0534) }
42
+ specify { bookmaker2.bookmakers_return_rate.should be_within(0.0001).of(0.0478) }
50
43
 
51
- specify { @bookmaker_vulnerable_to_arbitrage.profit_on_stake('£100'.to_money).should == '£4.63'.to_money }
52
- specify { @bookmaker_vulnerable_to_arbitrage.profit_percentage.should be_within(0.001).of(0.046) }
44
+ specify { bookmaker_vulnerable_to_arbitrage.profit_on_stake('£100'.to_money).should == '£4.63'.to_money }
45
+ specify { bookmaker_vulnerable_to_arbitrage.profit_percentage.should be_within(0.001).of(0.046) }
53
46
  end
54
47
 
55
48
  context "fractional odds arbitrage" do
56
- before(:each) do
57
- @odds1 = FixedOdds.from_s '2/1'
58
- @odds2 = FixedOdds.from_s '3/1'
49
+ let(:odds1) { FixedOdds.from_s '2/1' }
50
+ let(:odds2) { FixedOdds.from_s '3/1' }
59
51
 
60
- @bookmaker_vulnerable_to_arbitrage = MutuallyExclusiveCollection.new [@odds1, @odds2]
61
- end
52
+ let(:bookmaker_vulnerable_to_arbitrage) { MutuallyExclusiveCollection.new [odds1, odds2] }
62
53
 
63
- subject { @bookmaker_vulnerable_to_arbitrage }
54
+ subject { bookmaker_vulnerable_to_arbitrage }
64
55
 
65
- specify { @bookmaker_vulnerable_to_arbitrage.should be_arbitrageable }
56
+ specify { bookmaker_vulnerable_to_arbitrage.should be_arbitrageable }
66
57
  its(:profit_percentage) { should be_within(0.001).of(0.2) }
67
- specify { @bookmaker_vulnerable_to_arbitrage.profit_on_stake('£500'.to_money).should == '£100'.to_money }
58
+ specify { bookmaker_vulnerable_to_arbitrage.profit_on_stake('£500'.to_money).should == '£100'.to_money }
68
59
  end
69
60
 
70
61
  context "more than two mutually exclusive events" do
71
- before(:each) do
72
- @odds1 = FixedOdds.from_s '2.3'
73
- @odds2 = FixedOdds.from_s '8.0'
74
- @odds3 = FixedOdds.from_s '18.0'
62
+ let(:odds1) { FixedOdds.from_s '2.3' }
63
+ let(:odds2) { FixedOdds.from_s '8.0' }
64
+ let(:odds3) { FixedOdds.from_s '18.0' }
75
65
 
76
- @bookmaker_vulnerable_to_arbitrage = MutuallyExclusiveCollection.new [@odds1, @odds2, @odds3]
77
- end
66
+ let(:bookmaker_vulnerable_to_arbitrage) { MutuallyExclusiveCollection.new [odds1, odds2, odds3] }
78
67
 
79
- subject { @bookmaker_vulnerable_to_arbitrage }
68
+ subject { bookmaker_vulnerable_to_arbitrage }
80
69
 
81
- specify { @bookmaker_vulnerable_to_arbitrage.should be_arbitrageable }
70
+ it { should be_arbitrageable }
82
71
  its(:profit_percentage) { should be_within(0.0000001).of(0.02996) }
83
72
 
84
73
  describe "#percentages" do
85
74
  it "gives the percentages to put on each bet" do
86
- percentages = @bookmaker_vulnerable_to_arbitrage.percentages
75
+ percentages = bookmaker_vulnerable_to_arbitrage.percentages
87
76
  percentages.should have(3).items
88
- percentages[@odds1].should be_within(0.0001).of(0.7922)
89
- percentages[@odds2].should be_within(0.0001).of(0.1472)
90
- percentages[@odds3].should be_within(0.0001).of(0.0606)
77
+ percentages[odds1].should be_within(0.0001).of(0.7922)
78
+ percentages[odds2].should be_within(0.0001).of(0.1472)
79
+ percentages[odds3].should be_within(0.0001).of(0.0606)
91
80
  end
92
81
  end
93
82
 
94
83
  describe "#stakes_for_total_stake" do
95
84
  it "gives the right amounts" do
96
85
  total = Money.parse '£500'
97
- amounts = @bookmaker_vulnerable_to_arbitrage.stakes_for_total_stake total
86
+ amounts = bookmaker_vulnerable_to_arbitrage.stakes_for_total_stake total
98
87
  amounts.should have(3).items
99
- amounts[@odds1].should == '£396.14'.to_money
100
- amounts[@odds2].should == '£73.57'.to_money
101
- amounts[@odds3].should == '£30.29'.to_money
88
+ amounts[odds1].should == '£396.14'.to_money
89
+ amounts[odds2].should == '£73.57'.to_money
90
+ amounts[odds3].should == '£30.29'.to_money
102
91
  amounts.values.reduce(:+).should == total
103
92
  end
104
93
  end
105
94
 
106
- specify { @bookmaker_vulnerable_to_arbitrage.profit_on_stake('£500'.to_money).should == '£14.98'.to_money }
95
+ specify { bookmaker_vulnerable_to_arbitrage.profit_on_stake('£500'.to_money).should == '£14.98'.to_money }
107
96
 
108
97
  describe "#stakes_for_profit" do
109
98
  it "gives the right amounts" do
110
- amounts = @bookmaker_vulnerable_to_arbitrage.stakes_for_profit '£750'.to_money
99
+ amounts = bookmaker_vulnerable_to_arbitrage.stakes_for_profit '£750'.to_money
111
100
  amounts.should have(3).items
112
- amounts[@odds1].should == '£19833.33'.to_money
113
- amounts[@odds2].should == '£3683.33'.to_money
114
- amounts[@odds3].should == '£1516.67'.to_money
101
+ amounts[odds1].should == '£19833.33'.to_money
102
+ amounts[odds2].should == '£3683.33'.to_money
103
+ amounts[odds3].should == '£1516.67'.to_money
115
104
  amounts.values.reduce(:+).should == '£25033.33'.to_money
116
105
  end
117
106
  end
118
107
 
119
- specify { @bookmaker_vulnerable_to_arbitrage.stake_to_profit('£750'.to_money).should == '£25033.33'.to_money }
108
+ specify { bookmaker_vulnerable_to_arbitrage.stake_to_profit('£750'.to_money).should == '£25033.33'.to_money }
120
109
  end
121
110
 
122
111
  context "different events with same odds" do
123
- before(:each) do
124
- @odds1 = FixedOdds.from_s '15/1'
125
- @odds2 = FixedOdds.from_s '15/1'
112
+ let(:odds1) { FixedOdds.from_s '15/1' }
113
+ let(:odds2) { FixedOdds.from_s '15/1' }
126
114
 
127
- @bookmaker_vulnerable_to_arbitrage = MutuallyExclusiveCollection.new [@odds1, @odds2]
128
- end
115
+ let(:bookmaker_vulnerable_to_arbitrage) { MutuallyExclusiveCollection.new [odds1, odds2] }
129
116
 
130
- specify { @bookmaker_vulnerable_to_arbitrage.should be_arbitrageable }
131
- specify { @bookmaker_vulnerable_to_arbitrage.profit_on_stake('£100'.to_money).should == '£650'.to_money }
117
+ specify { bookmaker_vulnerable_to_arbitrage.should be_arbitrageable }
118
+ specify { bookmaker_vulnerable_to_arbitrage.profit_on_stake('£100'.to_money).should == '£650'.to_money }
132
119
 
133
120
  describe "#percentages" do
134
121
  it "gives the percentages to put on each bet" do
135
- percentages = @bookmaker_vulnerable_to_arbitrage.percentages
122
+ percentages = bookmaker_vulnerable_to_arbitrage.percentages
136
123
  percentages.should have(2).items
137
- percentages[@odds1].should be_within(0.0001).of(0.5)
138
- percentages[@odds2].should be_within(0.0001).of(0.5)
124
+ percentages[odds1].should be_within(0.0001).of(0.5)
125
+ percentages[odds2].should be_within(0.0001).of(0.5)
139
126
  end
140
127
  end
141
128
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rodders
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-11 00:00:00.000000000 Z
12
+ date: 2013-08-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: money
@@ -194,7 +194,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
194
194
  version: '0'
195
195
  segments:
196
196
  - 0
197
- hash: 437333735277840555
197
+ hash: -1412755025322987782
198
198
  required_rubygems_version: !ruby/object:Gem::Requirement
199
199
  none: false
200
200
  requirements: