betfair 1.0.3 → 1.0.6
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/Gemfile +3 -2
- data/README.md +23 -22
- data/betfair.gemspec +4 -3
- data/examples/README.md +3 -0
- data/lib/betfair/api.rb +193 -216
- data/lib/betfair/version.rb +1 -1
- data/spec/betfair/api_spec.rb +75 -68
- data/spec/spec_helper.rb +9 -1
- metadata +54 -25
- data/README_OLD +0 -170
- data/examples/bar.rb +0 -23
- data/examples/foo.rb +0 -42
- data/examples/simplebot.log +0 -4
- data/examples/simplebot/README.md +0 -51
- data/examples/simplebot/daemonize.rb +0 -8
- data/examples/simplebot/monit.conf +0 -6
- data/examples/simplebot/simplebot.rb +0 -170
data/examples/bar.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'betfair'
|
2
|
-
|
3
|
-
bf = Betfair::API.new
|
4
|
-
helpers = Betfair::Helpers.new
|
5
|
-
|
6
|
-
# Test your API limits out
|
7
|
-
|
8
|
-
1.times do |i|
|
9
|
-
session_token = bf.login('username', 'password', 264, 0, 0, nil).to_s
|
10
|
-
puts session_token
|
11
|
-
puts i
|
12
|
-
end
|
13
|
-
|
14
|
-
20.times do |i|
|
15
|
-
puts bf.get_all_markets(session_token, 2, [1,3], nil, nil, '2012-01-23', '2012-01-24').split(':')
|
16
|
-
puts i
|
17
|
-
end
|
18
|
-
|
19
|
-
40.times do |i|
|
20
|
-
details = bf.get_market(session_token, 1, 104678293)
|
21
|
-
prices = bf.get_market_prices_compressed(session_token, 1, 104678293)
|
22
|
-
puts helpers.combine(details, prices)
|
23
|
-
end
|
data/examples/foo.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'betfair'
|
2
|
-
|
3
|
-
bf = Betfair::API.new
|
4
|
-
helpers = Betfair::Helpers.new
|
5
|
-
|
6
|
-
session_token = bf.login('username', 'password', 82, 0, 0, nil).to_s
|
7
|
-
puts session_token
|
8
|
-
puts ""
|
9
|
-
|
10
|
-
# This call just returns back a huge string, markets ar edeliminated by ':', run the split method to convert string to a array
|
11
|
-
markets = bf.get_all_markets(session_token, 1, [1,3], nil, nil, nil, nil).split(':')
|
12
|
-
|
13
|
-
# puts helpers.all_markets(markets)
|
14
|
-
|
15
|
-
# Loop though the markets array
|
16
|
-
markets.each do |market|
|
17
|
-
|
18
|
-
# Once we have a market then the fields with in this are delimnated by '~', run the split method to convert string to a array
|
19
|
-
market = market.split('~')
|
20
|
-
|
21
|
-
market_id = market[0]
|
22
|
-
market_name = market[1].to_s
|
23
|
-
menu_path = market[5]
|
24
|
-
|
25
|
-
# Now lets just look for Match Odds for Tottenham for the English Premier League
|
26
|
-
if market_name == 'Match Odds' and menu_path.include? 'Barclays Premier League' and menu_path.include? 'Tottenham'
|
27
|
-
# Run the API call to get the Market Info
|
28
|
-
details = bf.get_market(session_token, 1, market_id)
|
29
|
-
# Run the API call to get the prices
|
30
|
-
prices = bf.get_market_prices_compressed(session_token, 1, market_id)
|
31
|
-
|
32
|
-
# Pump the data into the helpers
|
33
|
-
bf.get_market(session_token, 1, market_id)
|
34
|
-
puts helpers.market_info(details)
|
35
|
-
puts ""
|
36
|
-
puts helpers.combine(details, prices)
|
37
|
-
puts ""
|
38
|
-
puts helpers.prices_complete(prices)
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
data/examples/simplebot.log
DELETED
@@ -1,4 +0,0 @@
|
|
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
|
@@ -1,51 +0,0 @@
|
|
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.
|
@@ -1,6 +0,0 @@
|
|
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
|
@@ -1,170 +0,0 @@
|
|
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 = nil # This needs to be set within the loop on line 59
|
24
|
-
TO_DATE = nil # This needs to be set within the loop on line 59
|
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 = 1 # 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, Time.now.utc, 30.minutes.from_now.utc)
|
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
|
-
price = @helpers.set_betfair_odds(bet[:b1], BET_PIP, false, false)[:prc]
|
157
|
-
|
158
|
-
foo << { market_id: market_id, runner_id: bet[:selection_id], bet_type: BET_SIDE, price: price, size: BET_AMOUNT, asian_line_id: 0,
|
159
|
-
bet_category_type: 'E', bet_peristence_type: 'NONE', bsp_liability: 0 }
|
160
|
-
end
|
161
|
-
bets = BF.place_multiple_bets(token, exchange_id, foo)
|
162
|
-
LOGGER.info "#{market_id} - Placing bets #{bets}"
|
163
|
-
rescue
|
164
|
-
LOGGER.info "Error - SimpleBot.run - #{$!.message}\n(#{$!.class})\n#{$!.backtrace}\n"
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
end
|
169
|
-
SimpleBot.new.run
|
170
|
-
|