rodders 3.0.0 → 3.0.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 +1 -1
- data/lib/fixed_odds.rb +24 -25
- data/lib/mutually_exclusive_collection.rb +1 -1
- data/rodders.gemspec +3 -3
- data/spec/fixed_odds_spec.rb +69 -221
- data/spec/mutually_exclusive_collection_spec.rb +8 -0
- metadata +46 -16
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.0.
|
1
|
+
3.0.1
|
data/lib/fixed_odds.rb
CHANGED
@@ -15,7 +15,7 @@ class FixedOdds
|
|
15
15
|
# equivalent to '5/1'
|
16
16
|
# @param [String] odds the odds in fractional, moneyline or decimal form
|
17
17
|
# @return [FixedOdds]
|
18
|
-
def FixedOdds.from_s
|
18
|
+
def FixedOdds.from_s odds
|
19
19
|
case
|
20
20
|
when fractional_odds?(odds) then fractional_odds odds
|
21
21
|
when moneyline_odds?(odds) then moneyline_odds odds
|
@@ -27,22 +27,22 @@ class FixedOdds
|
|
27
27
|
# tells if the odds are in fractional form
|
28
28
|
# @param [String] odds the odds representation
|
29
29
|
# @return [Boolean] to indicate if it matches
|
30
|
-
def FixedOdds.fractional_odds?
|
31
|
-
odds =~ /^(\d
|
30
|
+
def FixedOdds.fractional_odds? odds
|
31
|
+
odds =~ /^([1-9]\d*(\/|-to-)[1-9]\d*( (against|on))?|evens|even money)$/
|
32
32
|
end
|
33
33
|
|
34
34
|
# tells if the odds are in moneyline form
|
35
35
|
# @param (see FixedOdds.fractional_odds?)
|
36
36
|
# @return (see FixedOdds.fractional_odds?)
|
37
|
-
def FixedOdds.moneyline_odds?
|
38
|
-
odds =~ /^[+-]\d
|
37
|
+
def FixedOdds.moneyline_odds? odds
|
38
|
+
odds =~ /^[+-][1-9]\d*$/
|
39
39
|
end
|
40
40
|
|
41
41
|
# tells if the odds are in decimal form
|
42
42
|
# @param (see FixedOdds.fractional_odds?)
|
43
43
|
# @return (see FixedOdds.fractional_odds?)
|
44
|
-
def FixedOdds.decimal_odds?
|
45
|
-
odds =~ /^(\d
|
44
|
+
def FixedOdds.decimal_odds? odds
|
45
|
+
odds =~ /^([1-9]\d*(\.\d+)?|\.\d+)$/
|
46
46
|
end
|
47
47
|
|
48
48
|
# creates a new FixedOdds from fractional form. These can be in the form
|
@@ -56,17 +56,19 @@ class FixedOdds
|
|
56
56
|
# * even money
|
57
57
|
# @param [String] fractional odds in fractional form
|
58
58
|
# @return (see FixedOdds.from_s)
|
59
|
-
def FixedOdds.fractional_odds
|
59
|
+
def FixedOdds.fractional_odds fractional
|
60
60
|
raise %{could not parse "#{fractional}" as fractional odds} unless self.fractional_odds?(fractional)
|
61
|
-
return new(1.to_r) if fractional == 'evens'
|
62
|
-
|
61
|
+
return new(1.to_r) if fractional == 'evens' or fractional == 'even money'
|
62
|
+
|
63
|
+
o = /(?<numerator>\d+)(\/|-to-)(?<denominator>\d+)/.match fractional
|
64
|
+
r = Rational o[:numerator], o[:denominator]
|
63
65
|
r = r.reciprocal if fractional.end_with? ' on'
|
64
66
|
new r
|
65
67
|
end
|
66
68
|
|
67
69
|
# creates a new FixedOdds from a Rational
|
68
70
|
# @param [Rational] fractional_odds the odds
|
69
|
-
def initialize
|
71
|
+
def initialize fractional_odds
|
70
72
|
@fractional_odds = fractional_odds
|
71
73
|
end
|
72
74
|
|
@@ -76,7 +78,7 @@ class FixedOdds
|
|
76
78
|
# @note (see #from_s)
|
77
79
|
# @param [String] moneyline odds in moneyline form
|
78
80
|
# @return (see FixedOdds.from_s)
|
79
|
-
def FixedOdds.moneyline_odds
|
81
|
+
def FixedOdds.moneyline_odds moneyline
|
80
82
|
raise %{could not parse "#{moneyline}" as moneyline odds} unless self.moneyline_odds?(moneyline)
|
81
83
|
sign = moneyline[0]
|
82
84
|
if sign == '+' then new(Rational(moneyline, 100))
|
@@ -89,7 +91,7 @@ class FixedOdds
|
|
89
91
|
# * 2
|
90
92
|
# @param [String] decimal odds in decimal form
|
91
93
|
# @return (see FixedOdds.from_s)
|
92
|
-
def FixedOdds.decimal_odds
|
94
|
+
def FixedOdds.decimal_odds decimal
|
93
95
|
raise %{could not parse "#{decimal}" as decimal odds} unless self.decimal_odds?(decimal)
|
94
96
|
new(decimal.to_r - 1)
|
95
97
|
end
|
@@ -97,7 +99,7 @@ class FixedOdds
|
|
97
99
|
# calculates the profit on a winning stake
|
98
100
|
# @param [Money] stake the stake
|
99
101
|
# @return [Money] the profit
|
100
|
-
def profit_on_stake
|
102
|
+
def profit_on_stake stake
|
101
103
|
stake * @fractional_odds
|
102
104
|
end
|
103
105
|
|
@@ -105,7 +107,7 @@ class FixedOdds
|
|
105
107
|
# (the profit plus the stake)
|
106
108
|
# @param (see #profit_on_stake)
|
107
109
|
# @return [Money] the total returned
|
108
|
-
def total_return_on_stake
|
110
|
+
def total_return_on_stake stake
|
109
111
|
profit_on_stake(stake) + stake
|
110
112
|
end
|
111
113
|
|
@@ -129,16 +131,13 @@ class FixedOdds
|
|
129
131
|
@fractional_odds.to_s
|
130
132
|
end
|
131
133
|
|
132
|
-
# string representation in moneyline form
|
134
|
+
# string representation in moneyline form (note
|
135
|
+
# there can be some loss of precision to make
|
136
|
+
# the number into an integer)
|
133
137
|
# @return [String] moneyline form representation
|
134
138
|
def to_s_moneyline
|
135
|
-
|
136
|
-
|
137
|
-
if @fractional_odds > 1
|
138
|
-
integral_number_with_sign_regex % (fractional_odds * 100).to_i
|
139
|
-
else
|
140
|
-
integral_number_with_sign_regex % (-100 / fractional_odds)
|
141
|
-
end
|
139
|
+
number = @fractional_odds > 1 ? fractional_odds * 100 : -100 / fractional_odds
|
140
|
+
'%+d' % number.round
|
142
141
|
end
|
143
142
|
|
144
143
|
# string representation in decimal form
|
@@ -150,13 +149,13 @@ class FixedOdds
|
|
150
149
|
protected
|
151
150
|
|
152
151
|
# equality method
|
153
|
-
def ==
|
152
|
+
def == other
|
154
153
|
other.fractional_odds == @fractional_odds
|
155
154
|
end
|
156
155
|
|
157
156
|
# low odds are those which pay out the most money
|
158
157
|
# on a winning bet and vice-versa
|
159
|
-
def <=>
|
158
|
+
def <=> other
|
160
159
|
other.fractional_odds <=> @fractional_odds
|
161
160
|
end
|
162
161
|
end
|
@@ -43,7 +43,7 @@ class MutuallyExclusiveCollection
|
|
43
43
|
# @return [Number] the bookmaker's return rate as a percentage
|
44
44
|
def bookmakers_return_rate
|
45
45
|
fs = fractions
|
46
|
-
1 - fs.reduce(:*) / fs.reduce(:+)
|
46
|
+
fs.any? ? 1 - fs.reduce(:*) / fs.reduce(:+) : 0
|
47
47
|
end
|
48
48
|
|
49
49
|
# hash of the odds and what percentage of the total stake should go on each
|
data/rodders.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "rodders"
|
8
|
-
s.version = "3.0.
|
8
|
+
s.version = "3.0.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-
|
12
|
+
s.date = "2012-05-12"
|
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 = [
|
@@ -36,7 +36,7 @@ Gem::Specification.new do |s|
|
|
36
36
|
s.homepage = "http://github.com/nigel-lowry/rodders"
|
37
37
|
s.licenses = ["MIT"]
|
38
38
|
s.require_paths = ["lib"]
|
39
|
-
s.rubygems_version = "1.8.
|
39
|
+
s.rubygems_version = "1.8.23"
|
40
40
|
s.summary = "Fixed odds betting library"
|
41
41
|
|
42
42
|
if s.respond_to? :specification_version then
|
data/spec/fixed_odds_spec.rb
CHANGED
@@ -25,33 +25,13 @@ describe "FixedOdds" do
|
|
25
25
|
value.end_with?('on').should == true
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
it "treats 'evens' as '1/1'" do
|
37
|
-
FixedOdds.fractional_odds('evens').should == FixedOdds.fractional_odds('1/1')
|
38
|
-
end
|
39
|
-
|
40
|
-
it "treats 'even money' as '1/1'" do
|
41
|
-
FixedOdds.fractional_odds('even money').should == FixedOdds.fractional_odds('1/1')
|
42
|
-
end
|
43
|
-
|
44
|
-
it "treats '4-to-1' as '4/1'" do
|
45
|
-
FixedOdds.fractional_odds('4-to-1').should == FixedOdds.fractional_odds('4/1')
|
46
|
-
end
|
47
|
-
|
48
|
-
it "treats '4-to-1 against' as '4/1'" do
|
49
|
-
FixedOdds.fractional_odds('4-to-1 against').should == FixedOdds.fractional_odds('4/1')
|
50
|
-
end
|
51
|
-
|
52
|
-
it "treats '4-to-1 on' as '1/4'" do
|
53
|
-
FixedOdds.fractional_odds('4-to-1 on').should == FixedOdds.fractional_odds('1/4')
|
54
|
-
end
|
28
|
+
specify { FixedOdds.fractional_odds('4/1 against').should == FixedOdds.fractional_odds('4/1') }
|
29
|
+
specify { FixedOdds.fractional_odds('4/1 on').should == FixedOdds.fractional_odds('1/4') }
|
30
|
+
specify { FixedOdds.fractional_odds('evens').should == FixedOdds.fractional_odds('1/1') }
|
31
|
+
specify { FixedOdds.fractional_odds('even money').should == FixedOdds.fractional_odds('1/1') }
|
32
|
+
specify { FixedOdds.fractional_odds('4-to-1').should == FixedOdds.fractional_odds('4/1') }
|
33
|
+
specify { FixedOdds.fractional_odds('4-to-1 against').should == FixedOdds.fractional_odds('4/1') }
|
34
|
+
specify { FixedOdds.fractional_odds('4-to-1 on').should == FixedOdds.fractional_odds('1/4') }
|
55
35
|
|
56
36
|
it "raises error if numerator has decimal point" do
|
57
37
|
expect {
|
@@ -100,34 +80,12 @@ describe "FixedOdds" do
|
|
100
80
|
)
|
101
81
|
end
|
102
82
|
|
103
|
-
|
104
|
-
|
105
|
-
plus400 = FixedOdds.moneyline_odds('+400')
|
106
|
-
plus400.profit_on_stake(Money.parse '£100').should == Money.parse('£400')
|
107
|
-
end
|
83
|
+
specify { FixedOdds.moneyline_odds('+400').profit_on_stake(Money.parse '£100').should == Money.parse('£400') }
|
84
|
+
specify { FixedOdds.moneyline_odds('+100').profit_on_stake(Money.parse '£100').should == Money.parse('£100') }
|
108
85
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
describe "negative figures" do
|
116
|
-
it "treats '-400' as meaning you need to wager £400 to win £100" do
|
117
|
-
minus400 = FixedOdds.moneyline_odds('-400')
|
118
|
-
minus400.profit_on_stake(Money.parse '£400').should == Money.parse('£100')
|
119
|
-
end
|
120
|
-
|
121
|
-
it "treats '-100' as meaning you need to wager £100 to win £100" do
|
122
|
-
minus100 = FixedOdds.moneyline_odds('-100')
|
123
|
-
minus100.profit_on_stake(Money.parse '£100').should == Money.parse('£100')
|
124
|
-
end
|
125
|
-
|
126
|
-
it "treats '+100' as meaning you need to wager £100 to win £100" do
|
127
|
-
plus100 = FixedOdds.moneyline_odds('+100')
|
128
|
-
plus100.profit_on_stake(Money.parse '£100').should == Money.parse('£100')
|
129
|
-
end
|
130
|
-
end
|
86
|
+
specify { FixedOdds.moneyline_odds('-400').profit_on_stake(Money.parse '£400').should == Money.parse('£100') }
|
87
|
+
specify { FixedOdds.moneyline_odds('-100').profit_on_stake(Money.parse '£100').should == Money.parse('£100') }
|
88
|
+
specify { FixedOdds.moneyline_odds('+100').profit_on_stake(Money.parse '£100').should == Money.parse('£100') }
|
131
89
|
end
|
132
90
|
|
133
91
|
describe ".decimal_odds" do
|
@@ -140,20 +98,9 @@ describe "FixedOdds" do
|
|
140
98
|
)
|
141
99
|
end
|
142
100
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
end
|
147
|
-
|
148
|
-
it "treats '5' as meaning you have to wager £1 to win £4" do
|
149
|
-
d5 = FixedOdds.decimal_odds '5'
|
150
|
-
d5.profit_on_stake(Money.parse '£1').should == Money.parse('£4')
|
151
|
-
end
|
152
|
-
|
153
|
-
it "treats '1.25' as meaning you have to wager £4 to win £1" do
|
154
|
-
d1_25 = FixedOdds.decimal_odds '1.25'
|
155
|
-
d1_25.profit_on_stake(Money.parse '£4').should == Money.parse('£1')
|
156
|
-
end
|
101
|
+
specify { FixedOdds.decimal_odds('2').profit_on_stake(Money.parse '£1').should == Money.parse('£1') }
|
102
|
+
specify { FixedOdds.decimal_odds('5').profit_on_stake(Money.parse '£1').should == Money.parse('£4') }
|
103
|
+
specify { FixedOdds.decimal_odds('1.25').profit_on_stake(Money.parse '£4').should == Money.parse('£1') }
|
157
104
|
end
|
158
105
|
|
159
106
|
describe ".from_s" do
|
@@ -178,43 +125,28 @@ describe "FixedOdds" do
|
|
178
125
|
end
|
179
126
|
|
180
127
|
describe "fractional odds" do
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
it "parses '4/1 on'" do
|
198
|
-
FixedOdds.from_s('4/1 on').should == FixedOdds.fractional_odds('1/4')
|
199
|
-
end
|
200
|
-
|
201
|
-
it "parses '4-to-1'" do
|
202
|
-
FixedOdds.from_s('4-to-1').should == FixedOdds.fractional_odds('4/1')
|
203
|
-
end
|
204
|
-
|
205
|
-
it "parses '4-to-1 against'" do
|
206
|
-
FixedOdds.from_s('4-to-1 against').should == FixedOdds.fractional_odds('4/1')
|
207
|
-
end
|
208
|
-
|
209
|
-
it "parses '4-to-1 on'" do
|
210
|
-
FixedOdds.from_s('4-to-1 on').should == FixedOdds.fractional_odds('1/4')
|
128
|
+
specify { FixedOdds.from_s('4/1').should == FixedOdds.fractional_odds('4/1') }
|
129
|
+
specify { FixedOdds.from_s('evens').should == FixedOdds.fractional_odds('1/1') }
|
130
|
+
specify { FixedOdds.from_s('even money').should == FixedOdds.fractional_odds('1/1') }
|
131
|
+
specify { FixedOdds.from_s('4/1 against').should == FixedOdds.fractional_odds('4/1') }
|
132
|
+
specify { FixedOdds.from_s('4/1 on').should == FixedOdds.fractional_odds('1/4') }
|
133
|
+
specify { FixedOdds.from_s('4-to-1').should == FixedOdds.fractional_odds('4/1') }
|
134
|
+
specify { FixedOdds.from_s('4-to-1 against').should == FixedOdds.fractional_odds('4/1') }
|
135
|
+
specify { FixedOdds.from_s('4-to-1 on').should == FixedOdds.fractional_odds('1/4') }
|
136
|
+
|
137
|
+
it "raises an error for a zero numerator" do
|
138
|
+
expect {
|
139
|
+
FixedOdds.from_s '0/4'
|
140
|
+
}.to raise_error(
|
141
|
+
ArgumentError
|
142
|
+
)
|
211
143
|
end
|
212
144
|
|
213
145
|
it "raises an error for a zero denominator" do
|
214
146
|
expect {
|
215
147
|
FixedOdds.from_s '4/0'
|
216
148
|
}.to raise_error(
|
217
|
-
|
149
|
+
ArgumentError
|
218
150
|
)
|
219
151
|
end
|
220
152
|
end
|
@@ -248,29 +180,15 @@ describe "FixedOdds" do
|
|
248
180
|
FixedOdds.fractional_odds('100/30').should == FixedOdds.fractional_odds('10/3')
|
249
181
|
end
|
250
182
|
|
251
|
-
it "recognises '1/1' and '2' are the same" do
|
252
|
-
FixedOdds.fractional_odds('1/1').should == FixedOdds.decimal_odds('2')
|
253
|
-
end
|
254
|
-
|
255
|
-
it "recognises '4/1' and '5' are the same" do
|
256
|
-
FixedOdds.fractional_odds('4/1').should == FixedOdds.decimal_odds('5')
|
257
|
-
end
|
258
|
-
|
259
|
-
it "recognises '1/4' and '1.25' are the same" do
|
260
|
-
FixedOdds.fractional_odds('1/4').should == FixedOdds.decimal_odds('1.25')
|
261
|
-
end
|
262
|
-
|
263
|
-
it "recognises '4/1' and '+400' are the same" do
|
264
|
-
FixedOdds.fractional_odds('4/1').should == FixedOdds.moneyline_odds('+400')
|
265
|
-
end
|
266
|
-
|
267
|
-
it "recognises '1/4' and '-400' are the same" do
|
268
|
-
FixedOdds.fractional_odds('1/4').should == FixedOdds.moneyline_odds('-400')
|
269
|
-
end
|
270
|
-
|
271
183
|
it "recognises '+100' and '-100' are the same" do
|
272
184
|
FixedOdds.moneyline_odds('+100').should == FixedOdds.moneyline_odds('-100')
|
273
185
|
end
|
186
|
+
|
187
|
+
specify { FixedOdds.fractional_odds('1/1').should == FixedOdds.decimal_odds('2') }
|
188
|
+
specify { FixedOdds.fractional_odds('4/1').should == FixedOdds.decimal_odds('5') }
|
189
|
+
specify { FixedOdds.fractional_odds('1/4').should == FixedOdds.decimal_odds('1.25') }
|
190
|
+
specify { FixedOdds.fractional_odds('4/1').should == FixedOdds.moneyline_odds('+400') }
|
191
|
+
specify { FixedOdds.fractional_odds('1/4').should == FixedOdds.moneyline_odds('-400') }
|
274
192
|
end
|
275
193
|
|
276
194
|
describe "#to_s" do
|
@@ -280,122 +198,52 @@ describe "FixedOdds" do
|
|
280
198
|
end
|
281
199
|
|
282
200
|
describe "#to_s_fractional" do
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
end
|
290
|
-
|
291
|
-
it "is '4/1' for '+400'" do
|
292
|
-
FixedOdds.moneyline_odds('+400').to_s_fractional.should == '4/1'
|
293
|
-
end
|
294
|
-
|
295
|
-
it "is '4/1' for '5'" do
|
296
|
-
FixedOdds.decimal_odds('5').to_s_fractional.should == '4/1'
|
297
|
-
end
|
298
|
-
|
299
|
-
it "is '1/1' for '+100'" do
|
300
|
-
FixedOdds.moneyline_odds('+100').to_s_fractional.should == '1/1'
|
301
|
-
end
|
302
|
-
|
303
|
-
it "is '1/1' for '-100'" do
|
304
|
-
FixedOdds.moneyline_odds('-100').to_s_fractional.should == '1/1'
|
305
|
-
end
|
201
|
+
specify { FixedOdds.fractional_odds('4/1').to_s_fractional.should == '4/1' }
|
202
|
+
specify { FixedOdds.fractional_odds('100/30').to_s_fractional.should == '10/3' }
|
203
|
+
specify { FixedOdds.moneyline_odds('+400').to_s_fractional.should == '4/1' }
|
204
|
+
specify { FixedOdds.decimal_odds('5').to_s_fractional.should == '4/1' }
|
205
|
+
specify { FixedOdds.moneyline_odds('+100').to_s_fractional.should == '1/1' }
|
206
|
+
specify { FixedOdds.moneyline_odds('-100').to_s_fractional.should == '1/1' }
|
306
207
|
end
|
307
208
|
|
308
209
|
describe "#to_s_moneyline" do
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
it "is '-100' as '-100'" do
|
318
|
-
FixedOdds.moneyline_odds('-100').to_s_moneyline.should == ('-100')
|
319
|
-
end
|
320
|
-
|
321
|
-
it "is '+400' for '4/1'" do
|
322
|
-
FixedOdds.fractional_odds('4/1').to_s_moneyline.should == '+400'
|
323
|
-
end
|
324
|
-
|
325
|
-
it "is '+400' for '5'" do
|
326
|
-
FixedOdds.decimal_odds('5').to_s_moneyline.should == '+400'
|
327
|
-
end
|
328
|
-
|
329
|
-
it "is '-400' for '1.25'" do
|
330
|
-
FixedOdds.decimal_odds('1.25').to_s_moneyline.should == '-400'
|
331
|
-
end
|
210
|
+
specify { FixedOdds.moneyline_odds('+400').to_s_moneyline.should == ('+400') }
|
211
|
+
specify { FixedOdds.moneyline_odds('+100').to_s_moneyline.should == ('-100') }
|
212
|
+
specify { FixedOdds.moneyline_odds('-100').to_s_moneyline.should == ('-100') }
|
213
|
+
specify { FixedOdds.fractional_odds('4/1').to_s_moneyline.should == '+400' }
|
214
|
+
specify { FixedOdds.fractional_odds('22/7').to_s_moneyline.should == '+314' }
|
215
|
+
specify { FixedOdds.decimal_odds('5').to_s_moneyline.should == '+400' }
|
216
|
+
specify { FixedOdds.decimal_odds('1.25').to_s_moneyline.should == '-400' }
|
332
217
|
end
|
333
218
|
|
334
219
|
describe "#to_s_decimal" do
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
FixedOdds.fractional_odds('1/4').to_s_decimal.should == '1.25'
|
341
|
-
end
|
342
|
-
|
343
|
-
it "is '1.25' for '-400'" do
|
344
|
-
FixedOdds.moneyline_odds('-400').to_s_decimal.should == '1.25'
|
345
|
-
end
|
346
|
-
|
347
|
-
it "is '2' for '+100'" do
|
348
|
-
FixedOdds.moneyline_odds('+100').to_s_decimal.should == '2'
|
349
|
-
end
|
350
|
-
|
351
|
-
it "is '2' for '-100'" do
|
352
|
-
FixedOdds.moneyline_odds('-100').to_s_decimal.should == '2'
|
353
|
-
end
|
220
|
+
specify { FixedOdds.decimal_odds('1.25').to_s_decimal.should == '1.25' }
|
221
|
+
specify { FixedOdds.fractional_odds('1/4').to_s_decimal.should == '1.25' }
|
222
|
+
specify { FixedOdds.moneyline_odds('-400').to_s_decimal.should == '1.25' }
|
223
|
+
specify { FixedOdds.moneyline_odds('+100').to_s_decimal.should == '2' }
|
224
|
+
specify { FixedOdds.moneyline_odds('-100').to_s_decimal.should == '2' }
|
354
225
|
end
|
355
226
|
|
356
227
|
describe "#profit_on_stake" do
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
end
|
361
|
-
|
362
|
-
it "is £0.25 on a £1 stake with a 1/4 bet" do
|
363
|
-
oneToFour = FixedOdds.fractional_odds '1/4'
|
364
|
-
oneToFour.profit_on_stake(Money.parse '£1').should == Money.parse('£0.25')
|
365
|
-
end
|
366
|
-
end
|
367
|
-
|
368
|
-
describe "#total_return_on_stake" do
|
369
|
-
it "is £5 on a winning 4/1 bet with a £1 stake" do
|
370
|
-
fourToOne = FixedOdds.fractional_odds '4/1'
|
371
|
-
fourToOne.total_return_on_stake(Money.parse '£1').should == Money.parse('£5')
|
372
|
-
end
|
373
|
-
|
374
|
-
it "is £125 on a winning 1/4 bet with a £100 stake" do
|
375
|
-
oneToFour = FixedOdds.fractional_odds '1/4'
|
376
|
-
oneToFour.total_return_on_stake(Money.parse '£100').should == Money.parse('£125')
|
377
|
-
end
|
228
|
+
specify { FixedOdds.fractional_odds('1/1').profit_on_stake(Money.parse '£1').should == Money.parse('£1') }
|
229
|
+
specify { FixedOdds.fractional_odds('2/1').profit_on_stake(Money.parse '£1').should == Money.parse('£2') }
|
230
|
+
specify { FixedOdds.fractional_odds('3/2').profit_on_stake(Money.parse '£2').should == Money.parse('£3') }
|
378
231
|
end
|
379
232
|
|
380
233
|
describe "#stake_to_profit" do
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
234
|
+
specify { FixedOdds.fractional_odds('1/1').stake_to_profit(Money.parse '£1').should == Money.parse('£1') }
|
235
|
+
specify { FixedOdds.fractional_odds('2/1').stake_to_profit(Money.parse '£2').should == Money.parse('£1') }
|
236
|
+
specify { FixedOdds.fractional_odds('3/2').stake_to_profit(Money.parse '£3').should == Money.parse('£2') }
|
237
|
+
end
|
385
238
|
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
239
|
+
describe "#total_return_on_stake" do
|
240
|
+
specify { FixedOdds.fractional_odds('1/1').total_return_on_stake(Money.parse '£1').should == Money.parse('£2') }
|
241
|
+
specify { FixedOdds.fractional_odds('2/1').total_return_on_stake(Money.parse '£1').should == Money.parse('£3') }
|
242
|
+
specify { FixedOdds.fractional_odds('3/2').total_return_on_stake(Money.parse '£2').should == Money.parse('£5') }
|
390
243
|
end
|
391
244
|
|
392
245
|
describe "object comparison" do
|
393
|
-
|
394
|
-
|
395
|
-
end
|
396
|
-
|
397
|
-
it "'-200' is more likely than '+200'" do
|
398
|
-
FixedOdds.from_s('-200').should be > FixedOdds.from_s('+200')
|
399
|
-
end
|
246
|
+
specify { FixedOdds.from_s('+200').should be < FixedOdds.from_s('-200') }
|
247
|
+
specify { FixedOdds.from_s('-200').should be > FixedOdds.from_s('+200') }
|
400
248
|
end
|
401
|
-
end
|
249
|
+
end
|
@@ -20,6 +20,14 @@ describe "MutuallyExclusiveCollection" do
|
|
20
20
|
its(:in_ascending_probability) { should == [@bad_team, @draw, @good_team] }
|
21
21
|
end
|
22
22
|
|
23
|
+
context "empty array" do
|
24
|
+
before(:each) do
|
25
|
+
@bookmaker = MutuallyExclusiveCollection.new []
|
26
|
+
end
|
27
|
+
|
28
|
+
specify { @bookmaker.bookmakers_return_rate.should == 0 }
|
29
|
+
end
|
30
|
+
|
23
31
|
context "decimal odds arbitrage" do
|
24
32
|
before(:each) do
|
25
33
|
@bookmaker1outcome1 = FixedOdds.from_s '2.25'
|
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.0.
|
4
|
+
version: 3.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-05-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: money
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: rspec
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ~>
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: 2.9.0
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.9.0
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: yard
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ~>
|
@@ -43,10 +53,15 @@ dependencies:
|
|
43
53
|
version: 0.6.0
|
44
54
|
type: :development
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.6.0
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: bundler
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ~>
|
@@ -54,10 +69,15 @@ dependencies:
|
|
54
69
|
version: 1.0.0
|
55
70
|
type: :development
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 1.0.0
|
58
78
|
- !ruby/object:Gem::Dependency
|
59
79
|
name: jeweler
|
60
|
-
requirement:
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
61
81
|
none: false
|
62
82
|
requirements:
|
63
83
|
- - ~>
|
@@ -65,10 +85,15 @@ dependencies:
|
|
65
85
|
version: 1.6.4
|
66
86
|
type: :development
|
67
87
|
prerelease: false
|
68
|
-
version_requirements:
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.6.4
|
69
94
|
- !ruby/object:Gem::Dependency
|
70
95
|
name: simplecov
|
71
|
-
requirement:
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
72
97
|
none: false
|
73
98
|
requirements:
|
74
99
|
- - ! '>='
|
@@ -76,7 +101,12 @@ dependencies:
|
|
76
101
|
version: '0'
|
77
102
|
type: :development
|
78
103
|
prerelease: false
|
79
|
-
version_requirements:
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
80
110
|
description: Converts between fractional, decimal and moneyline odds for betting and
|
81
111
|
gambling. Calculates how much can be won on a given stake.
|
82
112
|
email: nigel-lowry@ultra.eclipse.co.uk
|
@@ -116,7 +146,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
116
146
|
version: '0'
|
117
147
|
segments:
|
118
148
|
- 0
|
119
|
-
hash: -
|
149
|
+
hash: -1158855232544155326
|
120
150
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
151
|
none: false
|
122
152
|
requirements:
|
@@ -125,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
155
|
version: '0'
|
126
156
|
requirements: []
|
127
157
|
rubyforge_project:
|
128
|
-
rubygems_version: 1.8.
|
158
|
+
rubygems_version: 1.8.23
|
129
159
|
signing_key:
|
130
160
|
specification_version: 3
|
131
161
|
summary: Fixed odds betting library
|