betfair 0.0.18 → 0.0.20
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|