Programming for Betfair

Note - Questions are now taken via the Betfair Pro Trader Twitter account due to Google's inability to stop spam

Update, January 2019 - I never thought the book would still be selling three and a half years later but it is! The code is still robust, save for one new correction in the MarketBook class, which I include in the errata below. Again, before contacting me to debug your code, check the errata below and then check your code for typos. They are there because my code still works!

Update, March 2018 The book is still selling well as the best reference for learning how to use Betfair's API-NG. I have been notified that Microsoft has made a change to Visual Studio such that on page 37 Today.IsDaylightSavingTime() should now be Now.IsDaylightSavingTime() for those of you in countries that use daylight saving time. Thank you to Malcolm for providing that alert. Other than that work your way through the rest of this page to find addenda to correct past changes that Betfair and Microsoft have made that impacted on the book.

Some of you may also have problems with returned JSON numerical values being too big to  fit into an Integer variable due to the growth of Betfair's ID values. These will need to be changed to Long values. Read the comments at the bottom of this page to learn more, should you encounter the problem.

Update, January 2017 - Programming for Betfair was first published in the summer of 2015 and has sold over 1000 copies. Bugs and clarifications have now been dealt with. Any problems you are having are due to your typing errors or lack of programming experience (which will have to be addressed elsewhere).

Please check your code carefully. Make sure capitals are used where I used them and nowhere else. Do not confuse ohs and zeroes. Use Betfair's Visualiser to output JSON strings so that you can compare them with your program. That is usually the fastest way to pinpoint bugs in your code.

I have scaled back support for this book and so if you are making common beginner mistakes then I will just tell you, "It's a typo, check again." However, if Betfair make any revisions that affect readers of this book then I will put workarounds and updates on this page.

Good luck and may your edge be positive!

Update, May 2016 - Since May 10th 2016 Betfair now charges a one-off fee of £299 (or local currency equivalent) for the privilege of accessing live data from their servers through API-NG with a live AppKey. All users can still access data that has been delayed by up to 60 seconds for free and will still have access to live betting. Also, with the delayed AppKey, users will have access to the lastMatchTime so they will know at which time the lastPriceMatched was struck.

Remember that if you subscribe to third-party trading software, such as BetAngel etc., for long enough then you will end up spending more than £299 anyway. The Betfair fee is a large up-front charge but a big saving in the long-run.

If your intention is to use the delayed AppKey then where the book refers to not using the delayed AppKey you must ignore that instruction and use the delayed AppKey instead of the live AppKey.

And for those who still wish to progress, let's begin... 

Preface

Programming for Betfair was written over a year ago and with many hundreds of purchases you can be sure that any bugs have been found and dealt with. If you have any difficulty and have read this page fully then any problems you are having are solely your typing errors. You must not rush the book but read every page from start to finish.

As mentioned in the book I cannot help with programming problems, due to your lack of programming experience. Below, I recommend a beginner's Visual Basic programming book to help those who are new to programming. Experienced coders should have no difficulty debugging errors themselves.

I cannot help you to design your own software. The book and this help page are all you need to get you started with programming with API-NG and therefore I am now ceasing to support this book beyond what is already on this page.

No, there is no e-book so don't ask for one.

Please read on to view the errata...

Urgent Corrections Due to Betfair Server Changes

Since the book was published in June 2015 Betfair has made some changes to their servers. I offer this page to assist readers in making necessary corrections to the code in the book. The book was written soon after API-NG was released and there were a few teething problems that Betfair needed to sort out.

These problems have now been rectified and as of the summer of 2015 API-NG is running very robustly with no new changes to come that will affect the content of the book. Many hundreds of readers have completed the book in tandem with this page and you are about to be the next. The only errors you will find are in your typos. Good luck!

There are six urgent changes below that you should read before continuing with the book.

 URGENT #1  - Rather than Visual Studio Express 2013 I now recommend the latest Visual Studio Community 2015, which can be found at https://www.visualstudio.com/products/visual-studio-community-vs.

 URGENT #2  - Betfair has changed the URLs for the sports and account visualisers. The new URLs for the visualisers are as follows

On page 19 the URL for the account operations visualiser is now

https://developers.betfair.com/visualisers/api-ng-account-operations/

On page 23 the URL for the sports operations visualiser is now

https://developers.betfair.com/visualisers/api-ng-sports-operations/
 oi
 URGENT #3  - Some readers might have a problem when using interactive login (i.e. manual login using your username and password pair). If you get a Script Error dialog after clicking the Login button then you can rid yourself of it by changing the ScriptErrorsSuppressed property of the WebBrowser1 component.

Go to the LoginForm [Design] tab, click inside the form where the WebBrowser1 component is and then look for the ScriptErrorsSuppressed property in the properties dialog at the bottom right of the Visual Studio IDE. Change the property from False to True, which will ignore any script errors.

I recommend that people transition to digital certificate login as this requires no username and password and is very fast. Details below.

 URGENT #4  - Readers will hit a snag on page 40 and will see a protocol exception being flagged when running the application. This is because Betfair has made a change to its servers. Please refer to the Replacement SendSportsReq function section below and change your SendSportsReq function in SportsAPI.vb so that it matches the new one.

 URGENT #5  - If you have recently upgraded to Windows 10 (as I have) then your code might not work. My installation of Windows 10 is causing problems with the implementation of time formatting in the code. In the ListMarketCatalogue() subroutine in Form1.vb look for "Long Time" (there should be two instances) and change the code to "HH:mm".

 URGENT #6  - Add the KeepAlive functionality to avoid being logged out after four hours of inactivity or passively collecting prices rather than trading. See appropriate text below.

 URGENT #7  - On Page 56, in the MarketBook class the line Public version as Integer should be changed to Public version as Long Betfair now uses longer values for version that won't fit into the Integer type.

Introduction

Welcome to the Programming for Betfair companion web page. I hope that you have enjoyed reading the book and that it has inspired you to write your own trading applications.

So long as you read the book carefully and code the applications at a sensible pace then everything will be fine. The code might look a little odd with capital letters (JSON is case sensitive) in strange places but if you don't type the code exactly as it is written then you will be wasting your time contacting me only to get an email back listing your typos.

The most common error people report to me are their own typing errors. JSON is very particular about case so only use capitals where I use them and not where I don't. Other than three of my own typos that I list below, the lowercase and uppercase used in the book must be adhered to.

Before contacting me to do your debugging for you (which I won't - I will merely tell you how to debug properly), please double-check your code against the book and this webpage. When you have convinced yourself that you have copied everything correctly then you must check again as you almost certainly still have a typo, somewhere. If you contact me then the first thing I will do is run my code. If it still works then so should your code and I will tell you again to look for a typo.

With hundreds of books sold I have received sufficient feedback from people successfully completing the book to know that the code is correct. You can use the complete listings at the back of the book as a guide to code placement and to give yourself a general idea of what the code should look like when completed.

If you have any questions about the book then please leave them in the comments section below (No email addresses will be published if you leave one in your message for a personal reply). I will endeavour to answer all questions as quickly as I can. However, I cannot coach people on computer programming technique.

In due course I hope to publish a more advanced book covering topics mentioned in chapter 10 of Programming for Betfair. But first you need to get all the code in this book running, adapting it to your needs, trading for a while and then we can progress further.

Is there an eBook? No, there will not be an eBook. I am a self-publisher with no facilities for creating eBooks. My book is printed on demand with no advance royalties from a publisher therefore I am dependent on all future sales. I started coding in the early 1980s and so I am used to entering code from magazines and books. I feel that I learned more from that than today's generation who cut and paste their knowledge. There is a lot to be said for doing things s l o w l y.

Contents

Why can't I see the JavaScript console?

The JSON Response Is Not What I Expected

Addenda

  • Programming Convention
  • Do you already have an AppKey from a prior use of API-NG?
  • Error Codes
  • My Typos in the Book
  • Replacement SendSportsReq function
  • Australian Exchange
  • Update to ListMarketBook() subroutine
  • Keep Alive to Avoid Being Automatically Logged Off by Betfair 
  • The betting function tester is not very good is it?
  • JSON2CSV
  • Problems With Comma Delimited Files Using The Continental Numbering System
  • ChartBot
  • Automatic Login with a Digital Certificate
  • Compiling a Standalone Application

Reading Resources

Programming Resources

Visual Studio Community 2015

Extras

  • Take SP

Why can't I see the JavaScript console? 

I notice that Google has changed the menu on Chrome. The JavaScript console can still be found inside the 'More tools' dropdown but now it is in 'Developer tools' rather than 'JavaScript console'.

The JSON Response Is Not What I Expected 

Many newcomers to programming and JSON in particular do not know what to expect when they start reading this book.

If you get a strange JSON response similar to

[{"jsonrpc":"2.0","error":{"code":-32601,"message":"DSC-0021"},"id":1}]

or any other JSON response other than a list of events or prices then you have probably sent a bad JSON request. Print out your JSON request and perform the same request in the visualiser. Compare your request with the visualiser request to see where it is different. Doing that will help pinpoint where in the code you have made a mistake.

Addenda

Since I wrote the book Betfair has made some changes to how their servers operate, which has impacted on the code in the book. This addenda lists the changes you need to make.

Programming Convention

It might look strange seeing capitals in the middle of words in the code but it is there for a reason. Computer programming has some odd conventions and using capitals in the middle of words is one of them. JSON is especially fussy in this respect so make sure you use capitals where I use them and not where I don't.

Do you already have an AppKey from a prior use of API-NG?

Then use that AppKey rather than trying to create a new one. Betfair permits only one AppKey per user account.

Use the getDeveloperAppKeys operation in the Accounts Visualiser as mentioned in the book to retrieve a forgotten AppKey.

Error Codes

If you are getting an error code rather than a fully formed repsonse string then the following might help you to track down of your typing error. In all but the last case these errors are caused by typos.

-32700 = Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.

Your typo has created a malformed JSON string.

-32601 = Method not found

You typed the name of the method incorrectly.

-32602 = Problem parsing the parameters, or a mandatory parameter was not found

Invalid parameter inside the JSON request.

-32603 = Internal JSON-RPC error

Probably a Betfair problem.

My Typos in the Book

Page 46 -

In the code fragment  

Private dataTable As DataTable = DataSet.Tables.Add("Runners")

should be

Private dataTable As DataTable = dataSet.Tables.Add("Runners")

note the lowercase d in dataSet. The IDE should auto-correct this error otherwise hand correct the error.

Page 100 -

In the code fragment at the top of the page, the fifth line

row.Cells.Item("marketStartTime").Value & " " &

should have an underscore at the end (VS 2015 should ignore this problem), thus

row.Cells.Item("marketStartTime").Value & " " & _

Page 163 -

Inside Public Class PlaceInstructionRep the line

Public averagePriceMAtched As Double

has an errant uppercase A in it. Change this to the lowercase, thus

Public averagePriceMatched As Double

Replacement SendSportsReq function

Betfair has made a recent change to its servers and so the SendSportsReq function in the book will not function. A replacement function is given below.
 
Private Function SendSportsReq(ByVal jsonString As String)

  Dim request As HttpWebRequest = _
WebRequest.Create _
("https://api.betfair.com/exchange/betting/json-rpc/v1")

  Dim byteArray As Byte() = Encoding.UTF8.GetBytes(jsonString)

  Dim responseFromServer As String = ""

  Try
    request.Method = "POST"
    request.ContentType = "application/json"
    request.ContentLength = byteArray.Length
    request.Headers.Add("X-Application:
YOUR APPKEY HERE")
    request.Headers.Add("X-Authentication: " & ssoid)

    request.AutomaticDecompression = _
DecompressionMethods.GZip Or DecompressionMethods.Deflate
    request.ServicePoint.Expect100Continue = False

    request.Timeout = 2000

    Dim dataStream As Stream = request.GetRequestStream()
    dataStream.Write(byteArray, 0, byteArray.Length)

    Dim response As WebResponse = request.GetResponse()
    dataStream = response.GetResponseStream()

    Dim reader As New StreamReader(dataStream)
    responseFromServer = reader.ReadToEnd()


    Form1.Print(responseFromServer) 'delete in chapter 5

    reader.Dispose()
    dataStream.Dispose()
    response.Dispose()

  Catch ex As WebException 'Exception
    Form1.Print("SendSportsReq Error: " & ex.Message)
  End Try

  Return responseFromServer
 
End Function

You will notice a few new lines.

request.AutomaticDecompression = _
  DecompressionMethods.GZip Or DecompressionMethods.Deflate

Asks for the data to be GZipped (compressed) before being sent to the user. The data is automatically deflated. On average there is a slight speed improvement. Every millisecond counts!

request.ServicePoint.Expect100Continue = False

This line is now required since Betfair changed it servers

request.Timeout = 2000

This line adds a timeout to the request so that if there is any delay from the server then the request is cancelled. Sometimes Betfair's servers can fail to give a response under heavy traffic, which will create an exception in the code. The timeout is measured in milliseconds. You can alter the timeout value to as low as you feel comfortable with. As my application updates once every 60000 milliseconds (60 seconds) then 2 seconds is enough for 30 retries. That many retries is unlikely to happen but it provides plenty of insurance. If you get timeout errors then you will have to increase the Timeout value until they cease.

The Try/Catch commands protect the request to Betfair from exceptions that will halt your application. The Catch statement prints out the exception message which will be helpful when debugging.

Australian Exchange

For those of you wishing to use the Betfair's Australian Exchange you will need to change the URLs in the request function to the Australian Exchange from

Dim request As HttpWebRequest = _
WebRequest.Create _
("https://api.betfair.com/exchange/betting/json-rpc/v1")

to 

Dim request As HttpWebRequest = _
WebRequest.Create _
("https://api-au.betfair.com/exchange/betting/json-rpc/v1")

The AccountsAPI.vb request URL is

"https://api-au.betfair.com/exchange/account/json-rpc/v1"


You will need to create a separate program for Australian Exchange betting so that your requests go to the correct server.

Update to ListMarketBook() subroutine

The update to the SendSportsReq function allows for an update to the ListMarketBook() subroutine in Form1.vb as follows.
 
Private Sub ListMarketBook()

  Dim jsonResponse As String

  Dim keys(1) As Object 'dataView search keys
  Dim foundRow As DataRow


  ...


  For n As Integer = 0 To bookRequestList.Count - 1 

    'Dim jsonResponse As String = _
      GetRawBook(bookRequestList.Item(n))

    jsonResponse = ""

    Do
      jsonResponse = GetRawBook(bookRequestList.Item(n)) 

      If jsonResponse = "" Then
        Print("jsonResponse empty - retrying")
      End If
    Loop While jsonResponse = ""


    ...

  Dim book() As MarketBookResponse = _
    DeserializeRawBook(jsonResponse)

  For bookCount As Integer = 0 To book(0).result.Count - 1


  ...

Comment out the original Dim jsonResponse and add the new one directly after Private Sub ListMarketBook() but without the call to GetRawBook(). After commenting out the old jsonResponse declaration you must add jsonResponse = "" and the Do Loop.

This code takes advantage of the update to SendSportsReq in SportsAPI.vb because catching the timeout insures that an empty response is returned to ListMarketBook rather than a null string exception. This new code will notice the empty response and will repeat the request. On a good day you should not see any reports in TextBox1 informing you of a retry. You can monitor how many retries you get per day to inform you (and me) how bad your connection is.

Keep Alive to Avoid Being Automatically Logged Off by Betfair

If you run your code for more than 4 hours at a time then you will probably get timeout errors as Betfair will automatically log you out. Betfair will automatically log out what it believes to be dormant users for security purposes. To avoid being logged out add the following subroutine to the AccountsAPI module.

Public Sub KeepAlive()

  Dim request As HttpWebRequest = WebRequest.Create( _ 
    "https://identitysso.betfair.com/api/keepAlive")
  Dim response As HttpWebResponse = Nothing
  Dim strResponse As String = ""
 
  Try
    request.accept = "application/json"
    request.Method = "POST"
    request.Headers.Add(HttpRequestHeader.AcceptCharset, _
      "ISO-8859-1,utf-8")
    request.Headers.Add("X-Authentication: " & ssoid)
    request.Headers.Add("X-Application: YOUR APPKEY HERE")

    Using wr As System.Net.HttpWebResponse = request.GetResponse()
      Using sr As New _

        System.IO.StreamReader(wr.GetResponseStream())
        strResponse = sr.ReadToEnd().ToString
        sr.Close()
      End Using
      wr.Close()
    End Using
  
  Catch ex As Exception
    Form1.Print("KeepAlive Error " & ex.Message)
  End Try
        
End Sub

Remember to replace YOUR APPKEY HERE with your own AppKey.

For the KeepAlive subroutine to work you must also add a second Timer to Form1, set its interval to 3000000 (3 million milliseconds ~ approximately 50 minutes), double-click the timer to call up the tick handler and add code so that it looks as follows.

Private Sub Timer2_Tick(sender As Object, e As EventArgs) _
  Handles Timer2.Tick

  KeepAlive()

End Sub 

Every 50 minutes or so, Timer2 will send a KeepAlive request to Betfair and your application won't be automatically logged out. This will allow you to run bots that trade and/or capture data all day long without human interaction.

The betting function tester is not very good is it?  

A surpisingly small number of people have complained that the GUI-based betting function tester is not very good. Probably, the majority of readers understand that I am an algorithmic-trader and would never use such a thing for algo-trading bots.

I put in the betting function tester as an afterthought to help beginners get a visual idea of what is going on. As soon as the functionality is understood the reader must scrap the tester and build their own functionality that uses the basic betting functions for their specific needs. Do not bother with a GUI, just get those trades in fast and monitor them. 

GUIs are for manual traders, your sworn enemies. Let them plod a long, if they want. You need fast acting GUI-less trading bots to beat them to the gun, time after time.

JSON2CSV

There is a line of code missing in the JSON2CSV section of the book. In Form1.vb the very first line should be Imports System.IO so that the file input and output commands work. If you look at the full listing for JSON2CSV on page 177 then you will see the code as it should be.

I realise that some people might be running the Betfair application intermittently during the day. This will cause problems with the market and runner key files being loaded with duplicate entries. I have updated the LoadKeys subroutine to ignore duplicates. Ideally the user should run the Betfair application once throughout the day and then JSON2CSV on the day's complete JSON file.

Private Sub LoadKeys(ByVal marketKeysFilename As String, _
  ByVal runnerKeysFilename As String)

  Dim line As String

  Using reader As StreamReader _

    = New StreamReader(marketKeysFilename)

    line = reader.ReadLine

      Do While (Not line Is Nothing)


        Dim parts As String() = Strings.Split(line, ",")
        Try
          marketDictionary.Add(parts(0), parts(1))
        Catch ex As Exception
          Print("Ignoring duplicate market key")
        End Try

        line = reader.ReadLine

      Loop


    End Using

  Using reader As StreamReader _

    = New StreamReader(runnerKeysFilename)

    line = reader.ReadLine

    Do While (Not line Is Nothing)

      Dim parts As String() = Strings.Split(line, ",")


      Try
        runnerDictionary.Add(parts(0), parts(1))
      Catch ex As Exception
        Print("Ignoring duplicate runner key")
      End Try


      line = reader.ReadLine

    Loop

  End Using
 

End Sub

Problems With Comma Delimited Files Using The Continental Numbering System

If your numbering system uses commas in decimal numbers then loading CSV files into a spreadsheet will cause problems.

Change the following code in the ProcessJSON subroutine in JSON2CSV

writer.WriteLine(parts(0) & "," & _
marketDictionary.Item(book(0).result(bookCount).marketId) & "," _
& runnerDictionary.Item(.selectionId) & "," & .lastPriceTraded _
& "," & .totalMatched)

to

writer.WriteLine(parts(0) & "*" & _
marketDictionary.Item(book(0).result(bookCount).marketId) & "*" _
& runnerDictionary.Item(.selectionId) & "*" & .lastPriceTraded _
& "*" & .totalMatched)

so that the CSV file is now separated with stars rather than commas.

When you load the CSV into your spreadsheet untick the comma separator and click the 'other' separator option. Add a Star * to the text box next to the 'other' option and your file should be read correctly.

ChartBot

There is an error in chapter 9 that was corrected in the listings at the back of the book but not in the main text. On page 116 in Public Class MarketForm the runners List should be of type Form1.ChartDetail and not Form1.RunnerDetail. Please update your code as below with the correction.

Public Class MarketForm

  Inherits Form 'inhert a form's functions


  Private WithEvents runnerList As New ListBox
  Private WithEvents selectedList As New ListBox
  Private WithEvents startButton As New Button
 

  Private marketId As String
  Private course As String

  Private runners As New List(Of Form1.ChartDetail)


Automatic Login with a Digital Certificate

API-NG gives users the option to login automatically with a digital certificate. This obviates the need to enter a username, password and verification number (if using two-factor authentication). The advantages of this is that you don't need to keep logging in when coding and testing a new application that you are working on.

A complete tutorial on creating a digital certificate and integrating it into your application can be found at the following link


Compiling a Standalone Application

I neglected to mention that before publishing the application you should change the Solution Configuration from Debug to Release. This is done on the IDE menu strip where you will see a dropdown menu with the word Debug in it. Click on the dropdown menu and click Release. You may now publish the standalone application.

Reading Resources

If you are new to sports trading then I recommend Six Books to Start You in Sports Trading. These are the books that have inspired me through the years in which I have been a sports trader. The books cover mathematics, computer programming, trading strategy and psychology, and some academic crossover from the financial world. Sports betting exchanges are much like financial markets and there is much from the financial world that can assist you. I recommend various financial trading books in a page entitled Algorithmic Trading.

There are quite a few books on financial trading that I have found inspirational rather than educational. The writings of Michael Lewis; Liar's Poker, The Big Short and Flash Boys detail how no stone is left unturned in the pursuit of profit. Scott Patterson is another writer who has shone a light on the financial markets. His books The Quants and Dark Pools resonate somewhat with the work I have done in sports trading. After reading those two books you too might think that sports exchanges are not all they appear to be.

Programming Resources

Visual Basic is a simple to use and easy to understand language but which can easily handle all your programming requirements. In the past I have coded in many languages; C++, Java, Python and so on but I keep coming back to Visual Basic. Although I have dabbled with the Linux operating system in the past I still prefer Windows and, of course, Visual Basic is optimised for coding applications for Windows. To me coding for Windows using Java or Python feels like bolting something onto Windows that just doesn't quite fit.

Recommending a good Visual Basic book is hard because there are so many different styles of book and each one suits different people. If you are a beginner to programming then you will want a different book to someone with programming experience but who wants to translate their skills to Visual Studio. I would look at the website I recommended in the book first and then look for other similar websites. Also, visit your local bookshop (they still have their uses) and try reading a few books to see which suits you best before buying one cheaply online.

There are many Visual Basic programming forums on which you can ask questions. Once you have signed up for membership of MSDN (Microsoft Developer Network) you can access the Microsoft forum. YouTube is a good source for instructional videos that I have found useful, in the past. As I said in the book, the best way of learning is by looking at other people's code. Use Google to search for what you want to do and you will probably be led to a page that does exactly what you had hoped to achieve. Of course, you are not going to find much Betfair specific code so break your problem down into smaller problems and solve each problem independently.

Visual Basic in Easy Steps


For the newcomer to programming I recommend Visual Basic in easy steps, 4th edition, which may help the reader to extend their knowledge and their trading application further.

DotNetPerls

A good source of information on VB.NET programming including sample code can be found at DotNetPerls, which also includes information on other programming languages used in Visual Studio.

Visual Studio Community 2015

There is now an alternative to Visual Studio Express 2013 called Visual Studio Community 2015. This version of Visual Studio is also free but is more complete than the cut-down Express. I have migrated to Community 2015 as it includes F# (a functional programming language). I am interested in using concurrent programming on my trading platform and F# is the ideal language for that. The debugging messaging in Community 2015 is better, telling you what value variables held at the moment the program crashed, which can give clues as to the state of the program just before the crash.

Visual Studio Community 2015 can be downloaded from the following URL

You will still need to register for the product, as you did with Express 2013.

Extras

I will post little snippets that may be of use to people here. However, I cannot create snippets to order so WYSIWYG.

Take SP

Some have wanted to know how to force a bot to trade if the connection between computer and Betfair's server goes down. The best way to achieve this is to put in the required return leg trade at a price that you want straight after you have opened the trade with the first order but to make it a "Take SP" trade. In that way, if the race goes in-play and you have not traded out then Betfair will at least compensate you with an exit trade at SP.

For example, you Lay at 3.0 and want to close out 3.5. Rather than leaving your bot to wait and monitor until 3.5 is hit your bot places an immediatey Back at 3.5 but with the "Take SP" option set.

To achieve this you will need to have some sort of conditional in your algo-trading routines that knows the difference between an outward leg (first half of the trade) and the inward leg (closing second half of the trade).

At the moment the PlaceOrders() and the PlaceSub2Orders() routines in the book are using the persistenceType LAPSE on all bets. 

limitOrder.persistenceType = "LAPSE"

Therefore, when the market goes inPlay all open orders that have not been taken are closed. If you have a an inward leg that has not been taken they your initial outward leg has become a bet and is live during inPlay. To avoid this you need to alter your code so that your algorithm chooses the persistenceType. The persistenceType for TakeSP is MARKET_ON_CLOSE.

limitOrder.persistenceType = "MARKET_ON_CLOSE"

If you like living dangerously and want to leave a trade to ride until the end of the event then you need

limitOrder.persistenceType = "PERSIST"

but if the order is never taken then you will never close out the trade.