Using VB2008 to acccess the Betfair API: A tutorial

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Contrarian
    Junior Member
    • May 2009
    • 4

    #136
    Multithreading using the same subroutine in different threads

    Hi Mumbles,

    Let me just say thank you for a really clear introduction to VB for the API.

    I've written an application which runs very smoothly (I need it to be very quick because I use it to trade in-play), because I've put all the different calls to the Betfair server on separate threads.

    I want to expand the application to incorporate several Betfair markets simultaneously, which, if I am to make it as fast as possible, will have to call the same subroutine in different threads. For instance, I may want to create two threads which make separate calls on my subroutine:

    Sub GetPrices(ByVal MktId As Integer)
    .
    ' Puts the market prices/amounts into an array which is used to display the data on the form (in a different call of the application)
    .
    End Sub

    Is this possible, or will the data in the two separate threads get confused?

    Of course, I could just create a new subroutine for each different market I want to access (so my application would contains Subs GetPrices1, GetPrices2, etc. . ) but this is not a very elegant solution.

    Thanks.

    Comment

    • Mumbles0
      Junior Member
      • Jan 2009
      • 240

      #137
      Reply to Vreljanski (re: Market Outcome)

      I don’t think there is a market results service on the API, but to check how your bets fared you could do one of the following after the market has closed (and the bets are settled):

      Call getBet

      If you have a list of all betIds placed on your market you can call getBet once for each betId. Each calls returns bet details, including .profitAndLoss which will give the amounts each bet has won or lost.

      Call getBetHistory

      This call returns details of all settled bets placed within the time period you specify (if you can figure out how to set up the request parameters). I don’t think you can specify a marketId for this case. Instead to will have to scan the returned .betHistoryItems array looking for bets associated with your marketId. For each bet there is a .profitAndLoss parameter which you can total up.

      Call getAccountStatement

      This returns the .items array containing account transactions within the time period you specify. Commissions are also included. The marketId is returned in the .eventId parameter. Here is an example of a Sub which calls getAccountStatement and prints a summary of bets on a market:

      Code:
      Sub PrintOutcome(ByVal marketId As Integer)
        Dim Req As New BFUK.GetAccountStatementReq, Profit As Decimal
        With Req
          .header = oHeaderUK
          .startRecord = 0
          .recordCount = 99
          .startDate = Today
          .endDate = Now
          .itemsIncluded = BFUK.AccountStatementIncludeEnum.EXCHANGE
        End With
        Dim Resp As BFUK.GetAccountStatementResp = BetfairUK.getAccountStatement(Req)
        With Resp
          CheckHeader(.header)
          Print(.errorCode.ToString)
          If .errorCode = BFUK.GetAccountStatementErrorEnum.OK Then
            For i = 0 To .items.Length - 1
              With .items(i)
                If .eventId = marketId Then
                  Print(.betId & " " & .amount.ToString("c") & "   " & .selectionName & " " & .winLose.ToString)
                  Profit = Profit + .amount
                End If
              End With
            Next
            Print("Profit: " & Profit.ToString("c"))
          End If
        End With
      End Sub
      Other bet details are also returned. Note that you can only call getAccountStatement once per minute on the free API.

      Comment

      • runen
        Junior Member
        • May 2009
        • 6

        #138
        How do I place a SP back bet if SP-odds is >=2 and <=4


        Thanks
        Rune

        Comment

        • Mumbles0
          Junior Member
          • Jan 2009
          • 240

          #139
          Reply to Contrarian (re: Multithreading)

          Calling the same procedure from separate threads should be OK provided that you have a separate output array for each call, and the procedure has some means of knowing which array to write to. It is interesting to know that one thread may be “in the sub” when another thread calls it. Simultaneous (or concurrent) operation is possible because of how the system stack works.
          A reasonable approach is to pass each output array as a parameter. The sub now becomes:

          Sub GetPrices(ByVal MktId As Integer, ByRef MarketPrices As PriceType())

          Where MarketPrices is the output array which is built by the sub. The sub can be called this way:

          Dim MarketPrices1 As PriceType()
          GetPrices(MarketId1, MarketPrices1)


          Alternatively you could make GetPrices a function which returns the output array:

          Function GetPrices(ByVal MktId As Integer) As PriceType())

          And call it this way:

          Dim MarketPrices1 as PriceType()
          MarketPrices1 = GetPrices(MarketId1)


          Repeat this for another thread, using MarketId2, MarketPrice2.

          If I can add some general comments:

          I have run into problems when trying to display data returned on separate threads. For example, if I attempt to print error messages on a TextBox, I get the “Cross-thread operation not valid” exception. Have you had this problem? I’ve got a lot more to learn about this.

          Instead of executing Sync calls on separate threads, I prefer to use Async calls. These return the data on the primary thread and the system handles all the multithreading details for me.

          If you are using the Free API, you will find that it is not ideally suited to multi-market work. If you require frequent price updates you will be limited to about 2 or 3 concurrent markets because of the 60 calls/minute limit for getMarketPricesCompressed and getCompleteMarketPricesCompressed.

          Comment

          • Drifter
            Junior Member
            • Mar 2009
            • 30

            #140
            @ Contrarian

            On threading and multithreading, including aspects of synchronisation and asynchronous use; there is an excellent treatment in an ebook by Joe Albahari at http://www.albahari.com/threading/. There's a couple of places where the whole thing is also available in a PDF format, though I'm not sure about the copyright issues there, as it is all essentially under an O'Reilly banner even though touted as free. I'm pretty sure that any issues regarding threading that you may come across will be clearly explained in it. The code examples aren't in VB, but ought to be easily portable

            Comment

            • Contrarian
              Junior Member
              • May 2009
              • 4

              #141
              Thanks Mumbles - that's great (I''ve got a transactional subscription, so I'm not limited in the amount of calls I can do).

              Drifter,

              I'll take a look at that ebook.

              Cheers.

              Comment

              • Mumbles0
                Junior Member
                • Jan 2009
                • 240

                #142
                Reply to Runen (Re: SP back bet)

                For a Betfair SP bet the exact price that you will be matched at is not known in advance, but two estimates are returned by getMarketPricesCompressed (also getCompleteMarketPricesCompressed). These are .nearBSP and .farBSP. A comprehensive explanation of how these values are determined is given in the Help section of the main Betfair website.

                if you require a match between, say, 2.00 and 4.00 you could use the .nearBSP price (which is generally more accurate) and use a simple test like this:

                Code:
                If nearBSP >= 2 And nearBSP <= 4 Then
                   [I]Code to place an SP back bet on your selection[/I]
                End If
                However this does not guarantee that your SP bet will be matched between the limits. The closer to the market suspend time (i.e. start of the event) you place the bet the more confident you will be of the match being within the limits.

                When calling placeBets you can specify a minimum price for a SP back bet. This takes care of the lower price limit, but the high limit remains uncertain. A test procedure to place the bet could be something like this:

                Code:
                Sub PlaceSPBackBet(ByVal marketId As Integer, ByVal selectionId As Integer, ByVal nearBSP As Double)
                
                  Const MinPrice = 2, MaxPrice = 4      'Your price limits
                  If nearBSP <= MaxPrice Then            'Place bet only if <= upper price limit
                
                    Dim Bets As BFUK.PlaceBets()         'Create a Bets array
                    ReDim Bets(0)
                    Bets(0) = New BFUK.PlaceBets             'Set up the bet parameters:
                    With Bets(0)
                      .asianLineId = 0                            'Not used for SP
                      .betCategoryType = BFUK.BetCategoryTypeEnum.L      'Limit on close bet  (i.e. SP)
                      .betPersistenceType = BFUK.BetPersistenceTypeEnum.NONE     'Not used for SP
                      .betType = BFUK.BetTypeEnum.B     'Back bet
                      .bspLiability = 10       'Your stake (for example)
                      .marketId = marketId       'Your marketId
                      .price = MinPrice        'The lower price limit
                      .selectionId = selectionId     'Your selection Id
                      .size = 0       'Not used for SP
                    End With
                
                    Dim Req As New BFUK.PlaceBetsReq    'The request object
                    With Req
                      .header = oHeaderUK()
                      .bets = Bets
                    End With
                    Dim Resp As BFUK.PlaceBetsResp = BetFairUK.placeBets(Req)  'Call placeBets
                    With Resp
                      CheckHeader(.header)          'Check the response
                      Print(.errorCode.ToString)
                      If .errorCode = BFUK.PlaceBetsErrorEnum.OK Then
                        For i = 0 To .betResults.Length - 1
                          With .betResults(i)
                            Print("BetId = " & .betId & "  " & .resultCode.ToString & "  Success = " & .success)
                          End With
                        Next
                      End If
                    End With
                  End If
                End Sub
                Call this sub to place the bet as close as possible to the market suspend time. nearBSP is the estimate returned by getMarketPricesCompressed for your selection.

                Comment

                • runen
                  Junior Member
                  • May 2009
                  • 6

                  #143
                  Thanks Mumbles0

                  Nice and clear description!

                  Comment

                  • Vreljanski
                    Junior Member
                    • May 2009
                    • 16

                    #144
                    I am having a small problem with getting results if my bets are matched or not. For example i am using a procedure to do automatic bets, then when i lay bets i check if a selection is matched... using this procedure:


                    Dim Req As New BFUK.GetMUBetsReq()
                    Dim Resp As New BFUK.GetMUBetsResp

                    With Req
                    .header = oHeaderUK()
                    .marketId = marketid
                    .betStatus = BFUK.BetStatusEnum.M
                    .recordCount = 100
                    End With

                    Resp = BetFairUK.getMUBets(Req)

                    With Resp
                    CheckHeader(.header)

                    If .errorCode = BFUK.GetMUBetsErrorEnum.OK Then
                    For i = 0 To .bets().Length - 1
                    If .bets(i).betType = BFUK.BetTypeEnum.L Then
                    IsLayMatched = True
                    End If
                    Next
                    End If
                    End With



                    Return IsLayMatched


                    Then if is matched i remove the bet from procedure and dont do any more bets...

                    But what happens to me is that when i place lay bet i dont get isbet layed as true asap so my procedure goes another turn and make double lay...

                    is there any delay in marking bet as matched or my pro0cedure isnt ok?

                    thanks

                    Comment

                    • Tam's Loup
                      Junior Member
                      • Jan 2009
                      • 4

                      #145
                      A couple of things.

                      Your function searches for the existence of a matched lay bet for a particular market, and returns TRUE if it finds any. Ths is fine if you only ever lay one selection per market.

                      If you lay more than one selection, it will return TRUE even if just one is matched.

                      Secondly, it will also return TRUE if a lay bet is only partially matched. You may wish to know how much is matched.

                      But I'm also having difficulty in understanding your strategy. You say that if the bet is matched, then you don't do any more bets, which I can understand would be reasonable. But if you don't find a matched bet, then your program places the bet again. That's the part I don't understand. Isn't it possible (or likely) that your bet is unmatched, and that you should then either:

                      Do nothing, and wait for it to be either matched or cancelled
                      Update your bet
                      Cancel your bet, and possibly place it again.

                      Comment

                      • Vreljanski
                        Junior Member
                        • May 2009
                        • 16

                        #146
                        totally following you... let me try to clearify


                        Your function searches for the existence of a matched lay bet for a particular market, and returns TRUE if it finds any. Ths is fine if you only ever lay one selection per market.

                        If you lay more than one selection, it will return TRUE even if just one is matched.

                        Secondly, it will also return TRUE if a lay bet is only partially matched. You may wish to know how much is matched.


                        I must implement this i havent been able to find good examples to be able to achieve this... and my strategy only picks one selection atm so it works atm.

                        But I'm also having difficulty in understanding your strategy. You say that if the bet is matched, then you don't do any more bets, which I can understand would be reasonable. But if you don't find a matched bet, then your program places the bet again. That's the part I don't understand. Isn't it possible (or likely) that your bet is unmatched, and that you should then either:


                        I havent wrote properly, yes it must cancel a particular bet! then remake the bet.


                        Also... what happened to me gave me a thought that betfair maybe dont give back is lay matched asap.... but on the other hand... it may be that the bet was not matched at the time of the check then it was matched later on...

                        Anyway if someone could provide some code or ideas how to check is particular runner bet matched or partialy matched and how much partially and also some code for canceling bets that would be helpfull...

                        thanks for reply

                        Comment

                        • Vreljanski
                          Junior Member
                          • May 2009
                          • 16

                          #147
                          I figured out where was the problem... now I am exploring CancelBets and CancelBets by market to be able to get what i need.

                          Does anyone has some vb.net sample code for canceling bets? I used some code founded here where i declared CancelBetsbyMarket req, gave it market id and header, then i declared CancelBetByMarket resp and gave it req object as parameter... but it aint working...

                          can someone post a good example here how to cancel bets.

                          Dim oCancelBBMreq As New BFUK.CancelBetsByMarketReq
                          With oCancelBBMreq
                          .header = oHeaderUK()
                          ReDim .markets(0) 'Set up the array
                          .markets(0) = Your marketId Of Interest 'Put your marketId in the array
                          End With

                          Dim oCancelBBMresp as new BFUK.CancelBetsByMarketResp

                          oCancelBBMresp(oCancelBBMreq)

                          I think this is how mine canceling thingie looks like... i will double check it tmrw on work...

                          thanks a lot

                          AH ONE THINGIE CANCEL BETS BY MARKET IS AVAILABLE IN TRANSACTIONAL API..

                          WE DO HAVE FULL API CONNECTED TO ONE ACCOUNT... HOW ON EARTH I SET THAT IN CODE AS WELL.


                          thanks
                          Last edited by Vreljanski; 11-06-2009, 07:53 PM.

                          Comment

                          • Mumbles0
                            Junior Member
                            • Jan 2009
                            • 240

                            #148
                            Reply to Vreljanski (re: CancelBetsByMarket)

                            To cancel all bets on a given market you can call cancelBetsByMarket. If you fixed up the line where you call the API your code should work.

                            This is a Sub which will cancel all bets on marketId and print the result of the operation:

                            Code:
                            Sub CancelBetsByMarket(ByVal marketId As Integer)
                              Dim Req As New BFUK.CancelBetsByMarketReq
                              With Req
                                .header = oHeaderUK()
                                ReDim .markets(0)
                                .markets(0) = marketId
                              End With
                              Dim Resp As BFUK.CancelBetsByMarketResp = BetfairUK.cancelBetsByMarket(Req)  'Call API to cancel the bets
                              With Resp
                                CheckHeader(.header)
                                Print(.errorCode.ToString)
                                If .errorCode = BFUK.CancelBetsByMarketErrorEnum.OK Then
                                  For i = 0 To .results.Length - 1
                                    With .results(i)
                                      Print(.marketId & " " & .resultCode.ToString)      'Print result for the market
                                    End With
                                  Next
                                End If
                              End With
                            End Sub
                            If you are using the Free API, cancelBetsByMarket is not available. Instead you will have to save (in an array) the betIds of all bets you have placed on a market and call cancelBets if you want to cancel them all.

                            WE DO HAVE FULL API CONNECTED TO ONE ACCOUNT... HOW ON EARTH I SET THAT IN CODE AS WELL.
                            I don’t understand this ???

                            Comment

                            • Vreljanski
                              Junior Member
                              • May 2009
                              • 16

                              #149
                              Quote:
                              WE DO HAVE FULL API CONNECTED TO ONE ACCOUNT... HOW ON EARTH I SET THAT IN CODE AS WELL.
                              I don’t understand this ???



                              What I ment is we have one betfair account and that one has read only personal api connected to it... (I know cancel bets is not available)

                              I plan to update that account to personal transactional api.

                              So when i code, loging in using that account only wont work for me to have my api enabled... I have to provide product id or some other id for the code so it knows i am using some sort of registered api... right?

                              How do I make that happen... what i put where... etc...

                              I hope its now a bit more clear.

                              thanks.

                              Comment

                              • Vreljanski
                                Junior Member
                                • May 2009
                                • 16

                                #150
                                Also...

                                How do I upgrade my api...? I send email from account that has registered personal read only api to upgrade it to personal full transactional api... will that work?

                                I cant send ticket as they say i am not able to... even tho in the past i was able to send tickets... I know this is a litle bit off topic... so sorry.

                                thanks

                                Comment

                                Working...
                                X