betfair 0.0.18 → 0.0.20
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/.gitignore +0 -4
- data/README.md +383 -0
- data/{README → README_OLD} +7 -3
- data/examples/bar.rb +23 -0
- data/examples/foo.rb +1 -1
- data/examples/simplebot.log +4 -0
- data/examples/simplebot/README.md +51 -0
- data/examples/simplebot/daemonize.rb +8 -0
- data/examples/simplebot/monit.conf +6 -0
- data/examples/simplebot/simplebot.log +0 -0
- data/examples/simplebot/simplebot.rb +168 -0
- data/lib/betfair/api.rb +167 -105
- data/lib/betfair/version.rb +1 -1
- data/spec/betfair/api_spec.rb +92 -16
- data/spec/fixtures/cancel_bets_by_market/failure.xml +0 -0
- data/spec/fixtures/cancel_bets_by_market/success.xml +17 -0
- data/spec/fixtures/keep_alive/fail.xml +16 -0
- data/spec/fixtures/keep_alive/success.xml +16 -0
- data/spec/fixtures/logout/fail.xml +16 -0
- data/spec/fixtures/logout/success.xml +16 -0
- data/spec/fixtures/update_bets/fail.xml +27 -0
- data/spec/fixtures/update_bets/success.xml +27 -0
- metadata +37 -13
@@ -0,0 +1,4 @@
|
|
1
|
+
# Logfile created on 2012-03-28 17:07:58 +0800 by logger.rb/25413
|
2
|
+
I, [2012-03-28 17:08:20#2169] INFO -- : username - ["GBR"] - INVALID_USERNAME_OR_PASSWORD - OK - exiting
|
3
|
+
I, [2012-03-28 17:08:53#2309] INFO -- : username - ["GBR"] - INVALID_USERNAME_OR_PASSWORD - OK - exiting
|
4
|
+
I, [2012-03-28 17:09:24#2317] INFO -- : username - ["GBR"] - INVALID_USERNAME_OR_PASSWORD - OK - exiting
|
@@ -0,0 +1,51 @@
|
|
1
|
+
Credits
|
2
|
+
-------
|
3
|
+
Big thanks to wotsisname from the Betfair forums, as per [this post](http://forum.bdp.betfair.com/showthread.php?p=6117#post6117)
|
4
|
+
and [from here](http://bespokebots.com/betfair_bots.php).
|
5
|
+
|
6
|
+
I pretty much copied this directly from his Python bot.
|
7
|
+
|
8
|
+
|
9
|
+
Notes on what it does
|
10
|
+
---------------------
|
11
|
+
|
12
|
+
Logs in to the Betfair UK exchange and monitors the session, logging in again if the session is closed.
|
13
|
+
|
14
|
+
Calls GetAllMarkets and obtains all UK horse racing markets starting in the next 24 hours.
|
15
|
+
|
16
|
+
Filters the markets so we end up with a list of win only, single winner, odds markets with BSP disabled.
|
17
|
+
|
18
|
+
This should leave us with only the UK win markets.
|
19
|
+
|
20
|
+
The strategy checks each market for existing bets.
|
21
|
+
If we have no matched or unmatched bets, the bot will check for any runner available to back at 2.00 or less.
|
22
|
+
If runners are found, it places a LAY bet at the current back price +1 tick/pip to a £2 stake.
|
23
|
+
This places your bet at the front of the queue or gets matched immediately, depending on the back/lay price spread of the market.
|
24
|
+
The bots maximum lay price is 2.01.
|
25
|
+
|
26
|
+
The bot does NOT have a GUI and is intended to be run on a dedicated PC/Mac or a remote VPS.
|
27
|
+
|
28
|
+
Therefore, you should only use this code if you are comfortable with programming in Ruby AND running your scripts from a command line.
|
29
|
+
The API library has been thoroughly tested in a Linux production environment and uptimes exceeding 6 months are easily achieved with suitable error handling.
|
30
|
+
|
31
|
+
|
32
|
+
Disclaimer
|
33
|
+
----------
|
34
|
+
Please note that the bot strategy has NOT been tested beyond basic functionality, so I have no idea whether or not it is profitable long term.
|
35
|
+
The free source code is only intended as an example, so it is up to YOU decide whether or not to use it.
|
36
|
+
Please don't blame me if you lose money using the bot.
|
37
|
+
|
38
|
+
|
39
|
+
Daemonize
|
40
|
+
----------
|
41
|
+
|
42
|
+
`ruby daemonize.rb run` will test the script and output to the logfile location specified
|
43
|
+
|
44
|
+
or
|
45
|
+
|
46
|
+
`ruby daemonize.rb start` will start the script as a daemon and output to the logfile location specified in the background with a pidfile in the root folder
|
47
|
+
|
48
|
+
|
49
|
+
Monit
|
50
|
+
-----
|
51
|
+
See the monit.conf for an example on how to keep this alive on a server.
|
@@ -0,0 +1,6 @@
|
|
1
|
+
check process simplebot
|
2
|
+
with pidfile /home/foo/simplebot/simplebot.pid
|
3
|
+
start program = "/usr/local/rvm/bin/rvm-shell -l -c 'cd /home/foo/simplebot; ruby daemonize.rb start'"
|
4
|
+
stop program = "/usr/local/rvm/bin/rvm-shell -l -c 'cd /home/foo/simplebot; ruby daemonize.rb stop'"
|
5
|
+
if totalmem is greater than 150 MB for 10 cycles then restart # eating up memory?
|
6
|
+
group simplebot
|
File without changes
|
@@ -0,0 +1,168 @@
|
|
1
|
+
class SimpleBot
|
2
|
+
|
3
|
+
require 'betfair'
|
4
|
+
require 'date'
|
5
|
+
require 'active_support/core_ext' # Only really need this one to do the easy datetime stuff such as 30.minutes.from_now.utc
|
6
|
+
|
7
|
+
LOG_PATH = '/Users/lukebyrne/Sites/current/betfair/examples/simplebot/simplebot.log' # Absolute path to where you want put your log file
|
8
|
+
|
9
|
+
USERNAME = 'username' # BF Usernmae
|
10
|
+
PASSWORD = 'password' # BF Password
|
11
|
+
PRODUCT_ID = 82 # BF Product ID, Free is 82
|
12
|
+
VENDOR_SOFTWARE_ID = 0
|
13
|
+
LOCATION_ID = 0
|
14
|
+
IP_ADDRESS = nil
|
15
|
+
|
16
|
+
THROTTLE = 3 # How many seconds to wait between checking each market
|
17
|
+
BANDWIDTH_SAVER = 30 # How long to sleep for if no markets are found
|
18
|
+
|
19
|
+
EXCHANGE_ID = 2 # Exchanges you want to hit up 1 for UK, 2 for AUS
|
20
|
+
SPORTS_IDS = [7] # Array of the sports ids you want
|
21
|
+
LOCALE = nil # What coutry are you in? Dont really use this
|
22
|
+
COUNTRIES = ['GBR'] # Array of countries you wish to check for
|
23
|
+
FROM_DATE = Time.now.utc # Time you want to start checking from in UTC (which is basically GMT, which is the Betfair API time)
|
24
|
+
TO_DATE = 30.minutes.from_now.utc # How far out do you want to look for markets
|
25
|
+
|
26
|
+
MARKET_NAMES_INGORE = ['To Be Placed'] # Array of markets to ignore
|
27
|
+
MARKET_TYPE = 'O' # Not sure what this is
|
28
|
+
MARKET_STATUS = 'ACTIVE' # Active market types
|
29
|
+
NUMBER_OF_WINNERS = 1 # Only one winner per market
|
30
|
+
BSP_MARKET = true # Starting price market ?
|
31
|
+
IN_PLAY = 0 # 0 means not in play, anything above this means in play
|
32
|
+
|
33
|
+
ODDS = 2.0 # Bet on odds below this
|
34
|
+
BET_SIDE = 'L' # What type of bet, B for back and L for Lay
|
35
|
+
BET_AMOUNT = 2.0 # Note this needs to be a minimum of $5 if you have an AUS account
|
36
|
+
BET_PIP = 0.01 # Place bet one pip above the ODDS I am checking for, ie this will try and lay 2.0 pounds on odds of 2.01
|
37
|
+
|
38
|
+
BF = Betfair::API.new # Initialize BF API methods
|
39
|
+
HELPERS = Betfair::Helpers.new # Initialize Helper API methods
|
40
|
+
|
41
|
+
LOGGER = Logger.new(LOG_PATH,'daily') # New log file daily
|
42
|
+
original_formatter = Logger::Formatter.new
|
43
|
+
original_formatter.datetime_format = "%Y-%m-%d %H:%M:%S"
|
44
|
+
LOGGER.formatter = proc { |severity, datetime, progname, msg|
|
45
|
+
original_formatter.call(severity, datetime, progname, "#{USERNAME} - #{COUNTRIES} - #{msg}")
|
46
|
+
}
|
47
|
+
|
48
|
+
def run
|
49
|
+
begin
|
50
|
+
token = login # Get our session token
|
51
|
+
if token.success? # Successful login
|
52
|
+
LOGGER.info "Logged in successfully with #{USERNAME}, token returned - #{token}. Fetching Horses from #{COUNTRIES} and looking to lay odds on runners"
|
53
|
+
|
54
|
+
loop do
|
55
|
+
token = BF.keep_alive(token)
|
56
|
+
LOGGER.info("Keep alive - #{token}")
|
57
|
+
|
58
|
+
LOGGER.info 'Fetching markets'
|
59
|
+
markets = BF.get_all_markets(token, EXCHANGE_ID, SPORTS_IDS, LOCALE, COUNTRIES, FROM_DATE, TO_DATE)
|
60
|
+
|
61
|
+
if markets.is_a?(String) and markets != 'API_ERROR - NO_SESSION' # Markets returned correctly
|
62
|
+
check_markets(token, markets)
|
63
|
+
#token = nil # Set token here to nil to test the token reset below
|
64
|
+
|
65
|
+
elsif markets.is_a?(String) and markets == 'API_ERROR - NO_SESSION' # Session token has expired, try and get a new one
|
66
|
+
token = reset_login
|
67
|
+
|
68
|
+
else # No markets
|
69
|
+
LOGGER.info "No markets found, going to sleep for #{BANDWIDTH_SAVER} seconds"
|
70
|
+
sleep BANDWIDTH_SAVER
|
71
|
+
end
|
72
|
+
|
73
|
+
end # End loop
|
74
|
+
|
75
|
+
else # No login token returned
|
76
|
+
LOGGER.info "#{token.to_s} - exiting"
|
77
|
+
end
|
78
|
+
|
79
|
+
rescue
|
80
|
+
LOGGER.info "Error - SimpleBot.run - #{$!.message}\n(#{$!.class})\n#{$!.backtrace}\n"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def login
|
85
|
+
BF.login(USERNAME, PASSWORD, PRODUCT_ID, VENDOR_SOFTWARE_ID, LOCATION_ID, IP_ADDRESS)
|
86
|
+
end
|
87
|
+
|
88
|
+
def reset_login
|
89
|
+
token = login
|
90
|
+
if token.success?
|
91
|
+
LOGGER.info "Session token has expired, got a new one - #{token}"
|
92
|
+
else
|
93
|
+
LOGGER.info "Session token has expired, trying to get a new one returned #{token.to_s}"
|
94
|
+
end
|
95
|
+
return token
|
96
|
+
end
|
97
|
+
|
98
|
+
def check_markets(token, markets)
|
99
|
+
markets_hash = []
|
100
|
+
HELPERS.split_markets_string(markets).each do |m|
|
101
|
+
m[:time_to_start] = m[:event_date] - FROM_DATE.to_f # Sort the hash by the time - NEED TO DO THIS
|
102
|
+
markets_hash << m if !m[:market_id].nil? and !MARKET_NAMES_INGORE.include?(m[:market_name]) and MARKET_TYPE == m[:market_type] and MARKET_STATUS == m[:market_status] and NUMBER_OF_WINNERS == m[:number_of_winners] and IN_PLAY == m[:bet_delay] #and BSP_MARKET == m[:bsp_market]
|
103
|
+
end
|
104
|
+
|
105
|
+
if markets_hash.count > 0
|
106
|
+
markets_hash.each { |m| check_runners(token, EXCHANGE_ID, m[:market_id]); sleep THROTTLE; }
|
107
|
+
else
|
108
|
+
LOGGER.info "Markets found but none we are interested in, going to sleep for #{BANDWIDTH_SAVER} seconds"
|
109
|
+
sleep BANDWIDTH_SAVER
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def check_runners(token, exchange_id, market_id)
|
114
|
+
LOGGER.info "#{market_id} - Checking prices for market_id"
|
115
|
+
prices = HELPERS.prices_complete( BF.get_market_prices_compressed(token, exchange_id, market_id) )
|
116
|
+
# Need to recheck whether the market is ACTIVE and not IN_PLAY, this time from what gets returned from prices compressed
|
117
|
+
if MARKET_STATUS == prices[:market_status].to_s and IN_PLAY == prices[:in_play_delay]
|
118
|
+
bets_placed = bets_already_placed(token, exchange_id, market_id)
|
119
|
+
LOGGER.info "#{market_id} - #{bets_placed.count} bets already placed for market_id"
|
120
|
+
|
121
|
+
bets = []
|
122
|
+
prices.each do |k,v|
|
123
|
+
bets << { selection_id: v[:selection_id], b1: v[:b1] } if k.is_a?(Numeric) and !bets_placed.include?(v[:selection_id]) and v[:b1] <= ODDS.to_f
|
124
|
+
end
|
125
|
+
|
126
|
+
if bets.count > 0
|
127
|
+
place_bets(token, exchange_id, market_id, bets)
|
128
|
+
else
|
129
|
+
LOGGER.info "#{market_id} - Bets have already been placed for runners AND/OR no more runners to lay below odds of #{ODDS}"
|
130
|
+
end
|
131
|
+
|
132
|
+
else
|
133
|
+
LOGGER.info "#{market_id} - Is currently either not Active or is In Play"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def bets_already_placed(token, exchange_id, market_id)
|
138
|
+
begin
|
139
|
+
LOGGER.info "#{market_id} - Checking existing bets for market_id"
|
140
|
+
bets_placed = []
|
141
|
+
foo = BF.get_mu_bets(token, exchange_id, market_id)
|
142
|
+
if foo != 'NO_RESULTS - OK'
|
143
|
+
foo = [foo] if foo.is_a?(Hash) # If there is only one bet placed on a market then it returns a Hash, not an Array, needs to be an Array so we can loop it
|
144
|
+
foo.each { |bet| bets_placed << bet[:selection_id].to_i }
|
145
|
+
end
|
146
|
+
return bets_placed
|
147
|
+
rescue
|
148
|
+
LOGGER.info "Error - SimpleBot.bets_already_placed - #{$!.message}\n(#{$!.class})\n#{$!.backtrace}\n"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def place_bets(token, exchange_id, market_id, bets)
|
153
|
+
begin
|
154
|
+
foo = []
|
155
|
+
bets.each do |bet|
|
156
|
+
foo << { market_id: market_id, runner_id: bet[:selection_id], bet_type: BET_SIDE, price: bet[:b1]+BET_PIP.to_f, size: BET_AMOUNT, asian_line_id: 0,
|
157
|
+
bet_category_type: 'E', bet_peristence_type: 'NONE', bsp_liability: 0 }
|
158
|
+
end
|
159
|
+
bets = BF.place_multiple_bets(token, exchange_id, foo)
|
160
|
+
LOGGER.info "#{market_id} - Placing bets #{bets}"
|
161
|
+
rescue
|
162
|
+
LOGGER.info "Error - SimpleBot.run - #{$!.message}\n(#{$!.class})\n#{$!.backtrace}\n"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
SimpleBot.new.run
|
168
|
+
|
data/lib/betfair/api.rb
CHANGED
@@ -28,7 +28,7 @@ module Betfair
|
|
28
28
|
end # module Failure
|
29
29
|
|
30
30
|
|
31
|
-
## API METHODS
|
31
|
+
## Bet Placement API METHODS
|
32
32
|
#
|
33
33
|
|
34
34
|
def place_bet(session_token, exchange_id, market_id, selection_id, bet_type, price, size)
|
@@ -77,8 +77,51 @@ module Betfair
|
|
77
77
|
:bets => { 'PlaceBets' => bf_bets } )
|
78
78
|
|
79
79
|
return response.maybe_result( :bet_results, :place_bets_result )
|
80
|
+
end
|
81
|
+
|
82
|
+
def update_bet(session_token, exchange_id, bet_id, new_bet_persitence_type, new_price, new_size, old_bet_persitance_type, old_price, old_size)
|
83
|
+
bf_bet = {
|
84
|
+
:betId => bet_id,
|
85
|
+
:newBetPersistenceType => new_bet_persitence_type,
|
86
|
+
:newPrice => new_price,
|
87
|
+
:newSize => new_size,
|
88
|
+
:oldBetPersistenceType => old_bet_persitance_type,
|
89
|
+
:oldPrice => old_price,
|
90
|
+
:oldSize => old_size
|
91
|
+
}
|
92
|
+
|
93
|
+
response = exchange(exchange_id).
|
94
|
+
session_request( session_token,
|
95
|
+
:updateBets,
|
96
|
+
:update_bets_response,
|
97
|
+
:bets => { 'UpdateBets' => [bf_bet] } )
|
98
|
+
|
99
|
+
return response.maybe_result( :bet_results, :update_bets_result )
|
80
100
|
end
|
81
|
-
|
101
|
+
|
102
|
+
def update_multiple_bets(session_token, exchange_id, bets)
|
103
|
+
bf_bets = []
|
104
|
+
bets.each do |bet|
|
105
|
+
bf_bets << {
|
106
|
+
:betId => bet[:bet_id],
|
107
|
+
:newBetPersistenceType => bet[:new_bet_persitence_type],
|
108
|
+
:newPrice => bet[:new_price],
|
109
|
+
:newSize => bet[:new_size],
|
110
|
+
:oldBetPersistenceType => bet[:old_bet_persitance_type],
|
111
|
+
:oldPrice => bet[:old_price],
|
112
|
+
:oldSize => bet[:old_size]
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
response = exchange(exchange_id).
|
117
|
+
session_request( session_token,
|
118
|
+
:updateBets,
|
119
|
+
:update_bets_response,
|
120
|
+
:bets => { 'UpdateBets' => bf_bets } )
|
121
|
+
|
122
|
+
return response.maybe_result( :bet_results, :update_bets_result )
|
123
|
+
end
|
124
|
+
|
82
125
|
def cancel_bet(session_token, exchange_id, bet_id)
|
83
126
|
bf_bet = { :betId => bet_id }
|
84
127
|
|
@@ -90,8 +133,7 @@ module Betfair
|
|
90
133
|
|
91
134
|
return response.maybe_result( :bet_results, :cancel_bets_result )
|
92
135
|
end
|
93
|
-
|
94
|
-
|
136
|
+
|
95
137
|
def cancel_multiple_bets(session_token, exchange_id, bets)
|
96
138
|
bf_bets = []
|
97
139
|
bets.each { |bet_id| bf_bets << { :betId => bet_id } }
|
@@ -106,19 +148,29 @@ module Betfair
|
|
106
148
|
end
|
107
149
|
|
108
150
|
def cancel_bet_by_market(session_token, exchange_id, market_id)
|
109
|
-
|
151
|
+
raise 'Service not available in product id of 82'
|
110
152
|
end
|
111
153
|
|
112
|
-
|
113
|
-
|
114
|
-
end
|
154
|
+
## Read-Only Betting API METHODS
|
155
|
+
#
|
115
156
|
|
116
|
-
def
|
117
|
-
|
118
|
-
|
157
|
+
def get_mu_bets( session_token, exchange_id, market_id = 0, bet_status = 'MU', start_record = 0, record_count = 200, sort_order = 'ASC', order_by = 'PLACED_DATE') #, bet_ids = nil, , exclude_last_second = nil, matched_since = nil
|
158
|
+
response = exchange(exchange_id).
|
159
|
+
session_request( session_token,
|
160
|
+
:getMUBets,
|
161
|
+
:get_mu_bets_response,
|
162
|
+
#:betIds => bet_ids,
|
163
|
+
:betStatus => bet_status,
|
164
|
+
#:excludeLastSecond => exclude_last_second,
|
165
|
+
:marketId => market_id,
|
166
|
+
#:matchedSince => matched_since,
|
167
|
+
:orderBy => order_by,
|
168
|
+
:recordCount => record_count,
|
169
|
+
:sortOrder => sort_order,
|
170
|
+
:startRecord => start_record
|
171
|
+
)
|
119
172
|
|
120
|
-
|
121
|
-
|
173
|
+
return response.maybe_result( :bets, :mu_bet )
|
122
174
|
end
|
123
175
|
|
124
176
|
|
@@ -173,34 +225,13 @@ module Betfair
|
|
173
225
|
|
174
226
|
|
175
227
|
def get_account_funds( session_token, exchange_id )
|
176
|
-
response = exchange(
|
228
|
+
response = exchange(exchange_id).
|
177
229
|
session_request( session_token,
|
178
230
|
:getAccountFunds,
|
179
231
|
:get_account_funds_response )
|
180
232
|
|
181
233
|
return response.maybe_result
|
182
234
|
end
|
183
|
-
|
184
|
-
|
185
|
-
def get_mu_bets( session_token, exchange_id, market_id = 0, bet_status = 'MU', start_record = 0, record_count = 200, sort_order = 'ASC', order_by = 'PLACED_DATE') #, bet_ids = nil, , exclude_last_second = nil, matched_since = nil
|
186
|
-
response = exchange( exchange_id ).
|
187
|
-
session_request( session_token,
|
188
|
-
:getMUBets,
|
189
|
-
:get_mu_bets_response,
|
190
|
-
#:betIds => bet_ids,
|
191
|
-
:betStatus => bet_status,
|
192
|
-
#:excludeLastSecond => exclude_last_second,
|
193
|
-
:marketId => market_id,
|
194
|
-
#:matchedSince => matched_since,
|
195
|
-
:orderBy => order_by,
|
196
|
-
:recordCount => record_count,
|
197
|
-
:sortOrder => sort_order,
|
198
|
-
:startRecord => start_record
|
199
|
-
)
|
200
|
-
|
201
|
-
return response.maybe_result( :bets, :mu_bet )
|
202
|
-
end
|
203
|
-
|
204
235
|
|
205
236
|
def login(username, password, product_id, vendor_software_id, location_id, ip_address)
|
206
237
|
response = @global_service.request( :login,
|
@@ -215,12 +246,27 @@ module Betfair
|
|
215
246
|
return response.maybe_result( :header, :session_token )
|
216
247
|
end
|
217
248
|
|
218
|
-
|
249
|
+
## General API METHODS
|
250
|
+
#
|
251
|
+
|
252
|
+
def keep_alive(session_token)
|
253
|
+
response = @global_service.
|
254
|
+
session_request( session_token,
|
255
|
+
:keep_alive,
|
256
|
+
:keep_alive_response )
|
219
257
|
|
258
|
+
# Need to do the old school way of checking as the keep_alive response doesn't return a minorErrorCode, so fails
|
259
|
+
error_code = response[:header][:error_code]
|
260
|
+
return error_code == 'OK' ? response[:header][:session_token] : error_code
|
261
|
+
#return response.maybe_result( :header, :session_token )
|
220
262
|
end
|
221
263
|
|
222
|
-
def logout
|
223
|
-
|
264
|
+
def logout(session_token)
|
265
|
+
response = @global_service.
|
266
|
+
session_request( session_token,
|
267
|
+
:logout,
|
268
|
+
:logout_response )
|
269
|
+
return response.maybe_result( :header, :session_token )
|
224
270
|
end
|
225
271
|
|
226
272
|
#
|
@@ -351,35 +397,63 @@ module Betfair
|
|
351
397
|
|
352
398
|
|
353
399
|
class Helpers
|
354
|
-
|
400
|
+
|
401
|
+
## HELPER METHODS
|
402
|
+
#
|
403
|
+
|
355
404
|
def all_markets(markets)
|
356
405
|
market_hash = {}
|
357
406
|
markets.gsub! '\:', "\0"
|
358
407
|
markets = markets.split ":"
|
359
408
|
markets.each do |piece|
|
360
409
|
piece.gsub! "\0", '\:'
|
361
|
-
|
362
|
-
|
363
|
-
:
|
364
|
-
:
|
410
|
+
foo = piece.split('~')
|
411
|
+
market_hash[foo[0].to_i] = {
|
412
|
+
:market_id => foo[0].to_i,
|
413
|
+
:market_name => foo[1].to_s,
|
414
|
+
:market_type => foo[2].to_s,
|
415
|
+
:market_status => foo[3].to_s,
|
365
416
|
# bf returns in this case time in Epoch, but in milliseconds
|
366
|
-
:event_date => Time.at(
|
367
|
-
:menu_path =>
|
368
|
-
:event_hierarchy =>
|
369
|
-
:bet_delay =>
|
370
|
-
:exchange_id =>
|
371
|
-
:iso3_country_code =>
|
372
|
-
# bf returns in this case time in Epoch, but in milliseconds
|
373
|
-
:last_refresh => Time.at(
|
374
|
-
:number_of_runners =>
|
375
|
-
:number_of_winners =>
|
376
|
-
:total_amount_matched =>
|
377
|
-
:bsp_market =>
|
378
|
-
:turning_in_play =>
|
417
|
+
:event_date => Time.at(foo[4].to_i/1000),
|
418
|
+
:menu_path => foo[5].to_s,
|
419
|
+
:event_hierarchy => foo[6].to_s,
|
420
|
+
:bet_delay => foo[7].to_s,
|
421
|
+
:exchange_id => foo[8].to_i,
|
422
|
+
:iso3_country_code => foo[9].to_s,
|
423
|
+
# bf returns in this case time in Epoch, but in milliseconds
|
424
|
+
:last_refresh => Time.at(foo[10].to_i/1000),
|
425
|
+
:number_of_runners => foo[11].to_i,
|
426
|
+
:number_of_winners => foo[12].to_i,
|
427
|
+
:total_amount_matched => foo[13].to_f,
|
428
|
+
:bsp_market => foo[14] == 'Y' ? true : false,
|
429
|
+
:turning_in_play => foo[15] == 'Y' ? true : false
|
379
430
|
}
|
380
431
|
end
|
381
432
|
return market_hash
|
382
433
|
end
|
434
|
+
|
435
|
+
# Pass in the string returned from the get_all_markets() API call and get back a proper hash
|
436
|
+
# This duplicates the helper above, not sure where this came from one of contributors must have added it.
|
437
|
+
def split_markets_string(string)
|
438
|
+
string_raw = string
|
439
|
+
foo = []
|
440
|
+
if string_raw.is_a?(String)
|
441
|
+
string_raw.split(':').each do |string|
|
442
|
+
bar = string.split('~')
|
443
|
+
|
444
|
+
bsp_market = bar[14] == 'Y' ? true : false
|
445
|
+
turning_in_play = bar[15] == 'Y' ? true : false
|
446
|
+
event_date = Time.at(bar[4].to_i/1000).utc
|
447
|
+
last_refresh = Time.at(bar[10].to_i/1000).utc
|
448
|
+
|
449
|
+
doh = { market_id: bar[0].to_i, market_name: bar[1], market_type: bar[2], market_status: bar[3], event_date: event_date, menu_path: bar[5], event_heirachy: bar[6],
|
450
|
+
bet_delay: bar[7].to_i, exchange_id: bar[8].to_i, iso3_country_code: bar[9], last_refresh: last_refresh, number_of_runners: bar[11].to_i, number_of_winners: bar[12].to_i,
|
451
|
+
total_amount_matched: bar[13].to_f, bsp_market: bsp_market, turning_in_play: turning_in_play }
|
452
|
+
foo << doh if !doh[:market_name].nil?
|
453
|
+
end
|
454
|
+
end
|
455
|
+
return foo
|
456
|
+
end
|
383
457
|
|
384
458
|
def market_info(details)
|
385
459
|
{ :exchange_id => nil,
|
@@ -392,16 +466,6 @@ module Betfair
|
|
392
466
|
}
|
393
467
|
end
|
394
468
|
|
395
|
-
def combine(market, prices)
|
396
|
-
market = details(market)
|
397
|
-
prices = prices(prices)
|
398
|
-
market[:runners].each do |runner|
|
399
|
-
runner.merge!( { :market_id => market[:market_id] } )
|
400
|
-
runner.merge!( { :market_type_id => market[:market_type_id] } )
|
401
|
-
runner.merge!(price_string(prices[runner[:runner_id]]))
|
402
|
-
end
|
403
|
-
end
|
404
|
-
|
405
469
|
def details(market)
|
406
470
|
runners = []
|
407
471
|
market[:runners][:runner].each { |runner| runners << { :runner_id => runner[:selection_id].to_i, :runner_name => runner[:name] } }
|
@@ -418,6 +482,16 @@ module Betfair
|
|
418
482
|
end
|
419
483
|
return price_hash
|
420
484
|
end
|
485
|
+
|
486
|
+
def combine(market, prices)
|
487
|
+
market = details(market)
|
488
|
+
prices = prices(prices)
|
489
|
+
market[:runners].each do |runner|
|
490
|
+
runner.merge!( { :market_id => market[:market_id] } )
|
491
|
+
runner.merge!( { :market_type_id => market[:market_type_id] } )
|
492
|
+
runner.merge!(price_string(prices[runner[:runner_id]]))
|
493
|
+
end
|
494
|
+
end
|
421
495
|
|
422
496
|
##
|
423
497
|
#
|
@@ -435,37 +509,40 @@ module Betfair
|
|
435
509
|
# parsing first the auxiliary price info
|
436
510
|
aux = pieces.first
|
437
511
|
aux.gsub! "\0", '\:'
|
512
|
+
foo = aux.split('~')
|
438
513
|
aux_hash = {
|
439
|
-
:market_id =>
|
440
|
-
:currency =>
|
441
|
-
:market_status =>
|
442
|
-
:in_play_delay =>
|
443
|
-
:number_of_winners =>
|
444
|
-
:market_information =>
|
445
|
-
:discount_allowed =>
|
446
|
-
:market_base_rate =>
|
447
|
-
:refresh_time_in_milliseconds =>
|
448
|
-
:removed_runners =>
|
449
|
-
:bsp_market =>
|
514
|
+
:market_id => foo[0].to_i,
|
515
|
+
:currency => foo[1].to_s,
|
516
|
+
:market_status => foo[2].to_s,
|
517
|
+
:in_play_delay => foo[3].to_i,
|
518
|
+
:number_of_winners => foo[4].to_i,
|
519
|
+
:market_information => foo[5].to_s,
|
520
|
+
:discount_allowed => foo[6] == 'true' ? true : false,
|
521
|
+
:market_base_rate => foo[7].to_s,
|
522
|
+
:refresh_time_in_milliseconds => foo[8].to_i,
|
523
|
+
:removed_runners => foo[9].to_s,
|
524
|
+
:bsp_market => foo[10] == 'Y' ? true : false
|
450
525
|
}
|
451
526
|
|
452
527
|
# now iterating over the prices excluding the first piece that we already parsed above
|
453
528
|
pieces[1..-1].each do |piece|
|
454
529
|
piece.gsub! "\0", '\:'
|
455
|
-
|
530
|
+
|
531
|
+
bar = piece.split('~')
|
456
532
|
# using the selection_id as hash key
|
457
|
-
price_hash_key =
|
458
|
-
|
459
|
-
price_hash[price_hash_key] = {
|
460
|
-
:
|
461
|
-
:
|
462
|
-
:
|
463
|
-
:
|
464
|
-
:
|
465
|
-
:
|
466
|
-
:
|
467
|
-
:
|
468
|
-
:
|
533
|
+
price_hash_key = bar[0].to_i
|
534
|
+
|
535
|
+
price_hash[price_hash_key] = {
|
536
|
+
:selection_id => bar[0].to_i,
|
537
|
+
:order_index => bar[1].to_i,
|
538
|
+
:total_amount_matched => bar[2].to_f,
|
539
|
+
:last_price_matched => bar[3].to_f,
|
540
|
+
:handicap => bar[4].to_f,
|
541
|
+
:reduction_factor => bar[5].to_f,
|
542
|
+
:vacant => bar[6] == 'true' ? true : false,
|
543
|
+
:far_sp_price => bar[7].to_f,
|
544
|
+
:near_sp_price => bar[8].to_f,
|
545
|
+
:actual_sp_price => bar[9].to_f
|
469
546
|
}
|
470
547
|
|
471
548
|
# merge lay and back prices into price_hash
|
@@ -521,21 +598,6 @@ module Betfair
|
|
521
598
|
|
522
599
|
return price
|
523
600
|
end
|
524
|
-
|
525
|
-
# Pass in the string returned from the get_all_markets() API call and get back a proper hash
|
526
|
-
def split_markets_string(markets)
|
527
|
-
foo = []
|
528
|
-
if markets.is_a?(String)
|
529
|
-
markets.split(':').each do |market|
|
530
|
-
bar = market.split('~')
|
531
|
-
doh = { market_id: bar[0].to_i, market_name: bar[1], market_type: bar[2], market_status: bar[3], event_date: bar[4].to_i, menu_path: bar[5], event_heirachy: bar[6],
|
532
|
-
bet_delay: bar[7].to_i, exchange_id: bar[8].to_i, iso3_country_code: bar[9], last_refresh: bar[10].to_i, number_of_runners: bar[11].to_i, number_of_winners: bar[12].to_i,
|
533
|
-
total_amount_matched: bar[13].to_f, bsp_market: bar[14], turning_in_play: bar[15] }
|
534
|
-
foo << doh if !doh[:market_name].nil?
|
535
|
-
end
|
536
|
-
end
|
537
|
-
return foo
|
538
|
-
end
|
539
601
|
|
540
602
|
end
|
541
603
|
|