betfaiR

This vignette will walk through the methods used to place a bet using the betfaiR package. It will exhibit a number of different options, returning different data, before finally placing a bet, then replacing the bet, and ultimately cancelling the bet - it might become expensive if I let the bets ride.

The primary function in the betfaiR package is the betfair function, which returns an environment with the various methods to query the Betfair API.

login

First we need to login in, this requires a valid username, valid password, and valid API key. The appendix on the betfair page talks about how to best store these details in a safe manner. The suggestions come from Jenny Bryan via Hadley Wickham’s httr package (which is used by betfaiR )

So to login, first load the library, then login, saving the returned environment to a variable, here I named it bf. This can then be printed to see the available methods:

library(betfaiR)
bf <- betfair(usr = Sys.getenv("bf_usr"),
              pwd = Sys.getenv("bf_pwd"),
              key = Sys.getenv("bf_key"))
Login successful
bf
<betfaiR API>
Methods available: 
    $account(pwd) 
    $cancelOrders(..., marketId = NA) 
    $clearedOrders(betStatus = "SETTLED", eventTypeIds = NULL, eventIds = NULL, marketIds = NULL, runnerIds = NULL, 
   betIds = NULL, side = "BACK", from = NULL, to = NULL) 
    $competitions(filter = marketFilter()) 
    $countries(filter = marketFilter()) 
    $currentOrders(betId = NULL, marketId = NULL, orderProjection = "ALL", from = NULL, to = NULL, orderBy = "BY_BET", 
   sort = "EARLIEST_TO_LATEST", fromRecord = NULL, count = NULL) 
    $events(filter = marketFilter()) 
    $eventTypes(filter = marketFilter()) 
    $login(usr, pwd, key, jurisdiction = "default") 
    $marketBook(marketIds = list(), priceProjection = "EX_BEST_OFFERS", orderProjection = "EXECUTABLE", matchProjection = "NO_ROLLUP", 
   getRunners = NULL) 
    $marketCatalogue(filter = marketFilter(), marketProjection = "EVENT", sort = NULL, maxResults = 1, keepRules = FALSE) 
    $marketPnL(marketIds, settled = NULL, bsp = NULL, NET = NULL) 
    $marketTypes(filter = marketFilter()) 
    $placeOrders(marketId, selectionId, orderType = "LIMIT", handicap = NULL, side = "BACK", order = limitOrder()) 
    $replaceOrders(..., marketId) 
    $session() 
    $updateOrders(..., marketId) 
    $venues(filter = marketFilter()) 

searching for markets

It’s unlikely to be the case that you know the marketId or selectionId to go straight to placing a bet, so searching for the markets is usually required. This can be done via a number of different methods, which include, competitions, countries, events, eventTypes, venues and perhaps most useful marketCatalogue and the helper function marketFilter function.

You can filter on a wide variety of parameters, but some familiarity with these parameters is useful, for example, knowing that an eventTypeId of 1 will return football markets, while eventTypeId of 7 will return horse racing markets. We will look for 5 horse racing markets, in the UK, and we will sort by the amount traded. The response (stored as markets below) can be passed to summary for details about the 5 markets, in an easy to read format which allows users to quickly identify the market they’re interested in:

markets <- bf$marketCatalogue(filter = marketFilter(eventTypeIds = 7,
                                                    marketCountries = "GB"),
                              maxResults = 5,
                              sort = "MAXIMUM_TRADED")
summary(markets)

Market ID:      1.123618419
Event ID:       28061489 
Market Name:    Gold Cup
Event Name:     Chelt 17th Mar 
Matched:        454549
 ---------------------------------------------------------------------------
Market ID:      1.123618411
Event ID:       28061486 
Market Name:    Champion Hrd
Event Name:     Chelt 14th Mar 
Matched:        178493.84
 ---------------------------------------------------------------------------
Market ID:      1.125287736
Event ID:       28061486 
Market Name:    Supreme Nov Hrd
Event Name:     Chelt 14th Mar 
Matched:        119524.4
 ---------------------------------------------------------------------------
Market ID:      1.125287766
Event ID:       28061486 
Market Name:    Arkle Nov Chs
Event Name:     Chelt 14th Mar 
Matched:        101155.62
 ---------------------------------------------------------------------------
Market ID:      1.124139580
Event ID:       28061506 
Market Name:    Grand National
Event Name:     Aint 8th Apr 
Matched:        93247.68
 ---------------------------------------------------------------------------

Let’s look at the first market, the market name is Gold Cup while the event name is Chelt 17th Mar. Below we query this market, and retrieve additional data about the runners, via the marketProjection parameter:

marketId <- markets[[1]]$market$marketId
market <- bf$marketCatalogue(filter = marketFilter(marketIds = marketId),
                             marketProjection = "RUNNER_DESCRIPTION")
summary(market)

Market ID:      1.123618419 
Market Name:    Gold Cup 
Matched:        454549

Runners:     88 
 selectionId     runnerName handicap sortPriority
     7198646   Thistlecrack        0            1
     8902711   Native River        0            2
     6987962       Djakadam        0            3
     4360454       Cue Card        0            4
     6853519      Outlander        0            5
     8872379 Bristol De Mai        0            6

 ---------------------------------------------------------------------------

Now we know the marketId we can use the marketBook method to get up to date (well, with a second or so delays) market data. The response of this method can also be passed to summary for pretty printing, before being mined further. One unfortunate thing about the marketBook method is that it only returns selectionIds, rather than runner names, so the likes of Thistlecrack or Native River are not included.

market_data <- bf$marketBook(marketIds = marketId,
                             priceProjection = "EX_BEST_OFFERS")
summary(market_data)

Market ID:      1.123618419 
Matched:        527219.33 
Available:      25550.97

Runners:     38 (50 removed) 
     .id selectionId handicap status lastPriceTraded totalMatched
 7198646     7198646        0 ACTIVE             2.2    289139.54
 8902711     8902711        0 ACTIVE             8.6     29648.37
 6987962     6987962        0 ACTIVE            12.0     24268.79
 4360454     4360454        0 ACTIVE            13.5     37690.50
 6853519     6853519        0 ACTIVE            17.0     11272.76
 8872379     8872379        0 ACTIVE            19.0      3924.98

 ---------------------------------------------------------------------------

placing a bet

Let’s place a lay bet on the current favourite using the placeOrders method, Thistlecrack, we don’t want this to be matched, so the lay will be at the 1.01 price, and for just ?2. To place a bet, we need the marketId and selectionId:

marketId <- market_data[[1]]$market$marketId
selectionId <- market_data[[1]]$runners[[1]]$basic$selectionId

bet <- bf$placeOrders(marketId = marketId,
                      selectionId = selectionId,
                      side = "LAY",
                      order = limitOrder(size = 2, price = 1.01))

With any luck we will get a successful response:

bet

Status:         SUCCESS
MarketId:       1.123618419
summary(bet)

Status:         SUCCESS
MarketId:       1.123618419

Order:
  status       betId               placedDate averagePriceMatched
 SUCCESS 84123177274 2017-01-24T19:26:47.000Z                   0
 sizeMatched orderStatus
           0  EXECUTABLE

Instructions:
 selectionId handicap size price persistenceType orderType side
     7198646        0    2  1.01           LAPSE     LIMIT  LAY

We’ll now change that order using the replaceOrders function, for this we need the betId (which was returned above), and we’ll change the price we wish to be matched at to 1.10.

betId <- bet$order$betId
bet1 <- bf$replaceOrders(replace_inst(betId = betId,
                                      newPrice = 1.10),
                         marketId = marketId)

This update was a SUCCESS, but we don’t want to leave the bet there, so lets cancel it. We can either target this specific bet using it’s ID, returned above, or we can cancel all bets as below:

(cancel <- bf$cancelOrders())

Status:  SUCCESS