Ok, it’s presidential election time, and some bored people on the trading floor are making markets. How to make money by betting against them ?

The principle is rather simple. Take the best quotes for each outcome, and process :

  • if the sum of 1/quote_i is less than one, an arbitrage opportunity exists ;
  • the amount to bet on each outcome is 100/quote.

Ok, here’s an example (assuming each trader doesn’t offer arbitrage opportunities within his own book).

Trader A : Obama wins @ 1.62 vs Trader B : McCain wins @ 2.72

1/1.62 + 1/2.72 = 0.98, which is less than 1, so you can arbitrage them.

Betting 100/1.62 at trader A, and 100/2.72 at trader B yields 1.50, whoever wins, or 2.44% if Obama wins, and 4.10% if McCain wins.

So, F# comes to the rescue to do the calculations, and here we go.

let findArb quotes =
  let res = quotes |> Array.fold (fun acc quote -> acc + (1.0 / quote)) 0.0
  if res < 1.0 then
    printfn "----------------------------------"
    printfn "Bet"
    printfn "----------------------------------"
    let amountsToBet = quotes |> Array.map (fun quote -> 100.0 / quote)
    let totalBet = Array.reduce (+) amountsToBet
    printfn "Total bet : %0.2f" totalBet
    printfn "----------------------------------"
    let minGainPct = ref  System.Double.MaxValue
    quotes |> Array.iteri (fun i quote ->
      let amt = amountsToBet.[i]
      let received = amt * quote - (totalBet - amt)
      let gainPct = 100.0 * (received - amt) / amt

      if gainPct < !minGainPct then minGainPct := gainPct

      printfn "quote:%0.2f \t amount to bet:%0.4f \t received* :%0.2f \t gain*:%0.2f p.c."
        quote amountsToBet.[i] received gainPct
    )
    printfn "----------------------------------"
    printfn "minimum gain:%0.2f p.c." !minGainPct
    printfn "----------------------------------"
    printfn "* : if the outcome associated with this quote happens"
  else
    printfn "No arb opportunity : do not bet on this one"

do
  //Example : Obama @ 1.62 vs McCain @ 2.72
  findArb [|1.62; 2.72|]  

  //Example : competition with 5 outcomes
  findArb [|4.77; 4.32; 5.67; 5.50; 5.10|]  

Ok… there’s a catch ! Rounding numbers may result in losses. However, this seemingly only appears when there are many outcomes… So save it for the next grand-slam tennis final !

Alternatively, you may use the following function (although it might miss an opportunity since tweaking numbers works whith the following function will just round a real number to its nearest inferior integer).

let findArb2 quotes =
  let res = quotes |> Array.fold (fun acc quote -> acc + (1.0 / quote)) 0.0
  if res < 1.0 then
    let amountsToBet = Array.map (fun quote -> floor <| 100.0 / quote) quotes
    let totalBet = Array.reduce (+) amountsToBet
    let received = Array.map2 (fun quote amt -> amt * quote - (totalBet - amt)) quotes amountsToBet
    let gainsPct = Array.map2 (fun amt received -> 100.0 * (received - amt) / amt) amountsToBet received
    let minGainPct = Array.min gainsPct
    if minGainPct > 0.0 then
      printfn "----------------------------------"
      printfn "Bet"
      printfn "----------------------------------"
      printfn "Total bet : %0.2f" totalBet
      printfn "----------------------------------"
      for i in 0 .. quotes.Length - 1 do
        printfn "quote:%0.2f \t amount to bet:%0.4f \t received* :%0.2f \t gain*:%0.2f p.c."
          quotes.[i] amountsToBet.[i] received.[i] gainsPct.[i]
      printfn "----------------------------------"
      printfn "minimum gain:%0.2f p.c." minGainPct
      printfn "----------------------------------"
      printfn "* : if the outcome associated with this quote happens"
    else
      printfn "Arb opportunity : but the automatic rounding screws it"
  else
    printfn "No arb opportunity : do not bet on this one"  

do
  //Example : Obama @ 1.62 vs McCain @ 2.72
  findArb2 [|1.62; 2.72|]
  printfn "========================================"
  //Example : competition with 5 outcomes (under consideration)
  findArb2 [|4.77; 4.32; 5.67; 5.50; 5.10|]

One Response to “Arbitraging bookmakers with F#”

  1. [...] Julien Ortin’s Arbitraging bookmakers with F# [...]