rodders 3.1.0 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: