Using VB2008 to acccess the Betfair API: A tutorial

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • granted
    Junior Member
    • Jun 2009
    • 14

    #391
    Get Silks V2 (exchange) - GetSilksV2Req is of type ArrayOfInt

    the GetSilksV2Req 'markets' parameter is of type ArrayOfInt.

    But i just want to put in one market id...the one im currently looking at

    i tried

    With oGetSilksV2Req
    .header = oHeaderAU()
    .markets = marketid.text

    but it says: value of type integer cannot be converted to a 1-dimensional array of integer

    what does it want me to put there?

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

    also, when we print the runners, they appear as follows for example:

    4290762 1. Sharufa
    3286065 2. Spend The Money
    4914968 3. Amberman
    4914969 4. Ieramugadu
    4183913 5. Last To Leave
    2127783 6. Intercode
    4914970 7. Charming Manners
    3661066 8. Enhanced Design
    2016704 9. Circus Pony
    4914971 10. Gangway

    how can i put each runners name into a vb 'label' and assign the runner id to a 'button'

    i know how to do it for the event name...because there's only one name...but here, there is an array

    can you help please...as even more confusing is on the GetMarketResp, the parameter runners is of type ArrayOfRunners

    thanks
    Last edited by granted; 14-08-2010, 05:34 AM.

    Comment

    • Mumbles0
      Junior Member
      • Jan 2009
      • 240

      #392
      Arrays in request objects

      granted,

      First read my tutorial post regarding arrays here. This, I hope, will give you a better understanding of arrays.

      If you look at the Sports API Guide for any API call you will see, under the heading Input, details of the request parameters that must be assigned. With VB2008/2010 these parameters are the properties of the request object. For each parameter a type is given. You must use either a value of the given type, or a value that VB can convert to the given type.

      For example, for getSilksV2 the markets request parameter has type ArrayOfInt (i.e. array of type integer). Using an array lets you request data for several markets in one call. If you only want one market then you must use an integer array with a length of one, with its’ single element containing the (integer) marketId. You can do it like this:

      Code:
      Dim oGetSilksV2Req As New BFAU.GetSilksV2Req
      With oGetSilksV2Req
        .header = oHeaderAU()
        ReDim .markets(0)
        .markets(0) = marketidt.Text
      End With
      Because the .markets property of oGetSilksV2Req is, in fact, an array of integer we can create a suitable array by ReDiming this to 0 (0 being the upper bound of the array). Because array elements are numbered from 0, this creates an array with one element. This single element is referred to as .markets(0), to which we assign the marketId.

      (Note that getSilksV2 is not available on the free API.)

      Your query about buttons and labels is a more advanced topic. I will look at this in a separate post.

      Comment

      • Mumbles0
        Junior Member
        • Jan 2009
        • 240

        #393
        Reply to gvigliani (re: getCompleteMarketPricesCompressed)

        The two API “Prices” calls return runner prices differently. getMarketPricesCompressed returns two arrays for each runner in the unpacked response object:

        oMarketPrices.runnerPrices(i).bestPricesToBack()
        containing the best (up to) 3 prices available to back for runner i, and:

        oMarketPrices.runnerPrices(i).bestPricesToLay()
        containing the best (up to) 3 prices available to lay for the same runner. I see that you have succeeded in “digging out” these arrays.

        But getCompleteMarketPricesCompressed returns all prices (both back and lay) in a single array for each runner:

        oMarketPrices.runnerInfo(i).prices()
        If I modify the code of Step 10 a bit so that it now “prints” the .prices array:

        Code:
         [COLOR="Gray"] ......
          Dim oMarketPrices As New UnpackCompleteMarketPricesCompressed(.completeMarketPrices)
          With oMarketPrices
            Print(.marketId & "  " & .runnerInfo.Length & " runners")
            'Process returned market prices here.
            For i = 0 To .runnerInfo.Length - 1
              With .runnerInfo(i)
        [COLOR="Black"]        Print("Selection = " & .selectionId & vbCrLf & "price  backAmount layAmount")
                For j = 0 To .prices.Length - 1
                  With .prices(j)
                    Print(.price & " " & .backAmount & " " & .layAmount)
                  End With
                Next[/COLOR]
              End With
            Next
          End With
          .....[/COLOR]
        we can see what's in the .prices array for a typical runner:

        Code:
        Selection = 201255
        price  backAmount layAmount
        1.01     64.14         0
        1.74     47.03         0
        1.99      4.88         0
        2.02      0.14         0
        2.06     30.16         0
        2.08     66.12         0
        2.1      15.26         0
        2.16    112.52         0
        2.26    113.64         0
        2.28     90.59         0
        2.4          0     144.3
        2.54         0    125.72
        2.6          0      0.11
        2.72         0      17.4
        1000         0      4.17
        From this you can see that the 3 best back prices are 2.28, 2.26 & 2.16. Also the 3 best lay prices are 2.4, 2.54 & 2.6.

        There are usually many prices for each runner. You may have a problem trying to fit them all on your UI form. You may need to write additional code to extract only the prices and amounts that interest you.

        Comment

        • G-Factor
          Junior Member
          • Jan 2009
          • 2

          #394
          Inspired!

          Over the last few days I've worked my way through the whole thread.

          Firstly, all credit to you Mumbles0 for sparing your time and knowledge.

          I've made some crude apps with self-taught vb.net, but nothing very complicated.
          My progs normally manage to do what I want them to, but after reading this thread I realise (already suspected) that my code is very untidy! I plan to re-look at them and try to make them more efficient, and easier to read, if I can.

          You've said before that there can be many ways to do things in vb.net and I'd just like to suggest an alternative that I use to saving settings in a separate file.

          I use the settings built in to each project.

          For those that don't know, if you double-click "My Project" in the solution explorer a new 'tab' will open with lots of complicated settings that I wouldn't go near, but one of the options on the left hand side is Settings.

          If you click on that it will give you a list of settings currently being used. There should be your web references there as application settings, but you can add your own.
          Just choose a name, a type, and a value if required.

          These settings can then be accessed in your program using My.Settings. and will be available to you each time you run it.

          ***********************

          I was hoping to find answers to a couple of things that have been bugging (no pun intended) me for a while now, and haven't, so I hope you won't mind me asking them.

          Whenever I start my app, the first call to the API always takes way longer than any subsequent calls, typically 5-10 seconds! I know it's not just the Login call, as I've started my prog already logged in and a GetEvents call took just as long.
          It's only the first call though, weird!
          Has anyone got any ideas as to why this might be?

          Secondly, I've been trying to get my display to look a little easier to read.
          I display runners and prices in a datagridview, and would like to show price & amount available but with the price in bold text (as the website does).

          I've managed to concatenate the price and amount together and to display one above the other, but can't change from bold to not in the middle of it. I've tried tags and ascii characters but that's the limit of my ideas and I can't find anything by Googling.

          Any ideas? Is it even possible? It seems daft that I can do it in Excel and not .NET

          Thanks in advance for anyone who might be able to help.

          Comment

          • Mumbles0
            Junior Member
            • Jan 2009
            • 240

            #395
            G-Factor,

            Thanks for your post.

            Settings

            You suggestion to use the in-built Settings facility is good. I might post a step taking a closer look at this.

            Response time variations

            I too have noticed this. The first API call made after a project starts running take a lot longer than subsequent calls. I timed some calls made to getMarket with a VB program. The first call took 1.7 sec, while subsequent calls made every 30 sec thereafter took only 0.4 sec. If I ceased calling for a few minutes, the next call took longer (1.1 sec). I’m calling the UK exchange from Australia with a fairly modest line speed, using Windows XP.

            I also called getMarket using SoapUI (which a Java app). The Same effect was noticed (although the times were a bit different).

            I'm fairly sure this phenomenon is caused by the secure (SSL) behavior of the transmission. Using Wireshark I observed the packet sequence. On the initial call there was a lot of handshaking going on (exchanging certificates, etc.), whereas the subsequent transmissions were a lot briefer. This accounted for the time difference.

            Your times of “5 - 10 seconds” seem a bit excessive. Is this for all API calls? What does it reduce to? Have you enabled gzip? There are other tweaks that can be done. I suggest you take a closer look at your interactions using a network analyser such as Wireshark.

            Text styles in DataGridView

            Unlike Excel and HTML, you cannot have different text styles within a single cell of a DataGridView, although the cells can have individual text styles.

            But .... having said this I think there is a way it can be done using graphics. I will investigate this.
            Last edited by Mumbles0; 19-08-2010, 01:12 AM.

            Comment

            • G-Factor
              Junior Member
              • Jan 2009
              • 2

              #396
              I put a timer on it today.

              The first Login took 14397ms, then I logged out and in again several times and they ranged from 90-110ms!

              I vaguely remember reading somewhere when I first noticed this that it was something to do with 64-bit or Windows7, I can't remember now.

              It doesn't really matter, as it's only once and well before racing starts, I was just curious if anyone else had come across it.

              I do have gzip enabled, and a couple of other things (which I've tried removing with no effect) which did make my prog faster when I was on XP.

              I have this in my app.config file

              Code:
              <system.net>
              		<connectionManagement>
              			<add address="*" maxconnection="20" />
              		</connectionManagement>
              		<settings>
              			<servicePointManager
                  expect100Continue="false"
                  useNagleAlgorithm="false"/>
              		</settings>
              	</system.net>
              I don't have enough knowledge to know what I was doing by monitoring what's being sent and received over my network. As I said, it doesn't really matter.
              15 seconds seems like ages in this day and age though doesn't it!

              As for changing the text style in the datagridview, that doesn't really matter either. I wouldn't be using the extra information for anything, just curious if anyone had a way to do it.

              Once again, great work.

              Comment

              • Mumbles0
                Junior Member
                • Jan 2009
                • 240

                #397
                Step 29. Adding controls to a form at run time.

                It is easy to add a control when you are designing a form - you simply drag the control from the Toolbox onto the form. But what if, for example, you want to add a button for each runner in a horse race? You can’t do this at design time because you don’t know how many runners there will be. Because the controls in the Toolbox are objects derived from classes, they can be added by the program while it is running.

                To display the list of runners returned by a getMarket call, a logical choice would be to use either a ListBox or a DataGridView control. As an alternative, this step will show how to add a set of buttons for the runners in a market. This is an interesting exercise.

                First add a new form to your project. From the Project menu select Add New Item . Select Windows Form and name it MarketForm.vb, then click the Add button. The new form should now appear in the solution explorer.

                The code for the form is this:

                Code:
                Public Class MarketForm
                
                  Const PosLeft = 25   'Position of buttons from left edge of form
                  Const PosTop = 25    'Position of buttons from top of form
                  Const PosBut = 30    'Button spacing
                  Const Bwidth = 150   'Button width
                
                  Private Buttons As Button()  'The array of buttons
                
                  Sub AddRunnerButtons(ByVal oMarketResp As BFUK.GetMarketResp)
                    Dim Tpos As Integer = PosTop   'Top position of first button
                    Dim m As Integer = oMarketResp.market.runners.Length - 1  'Number of runners - 1
                
                    ReDim Buttons(m)
                    For i = 0 To m   'For each runner
                      Buttons(i) = New Button  'Create a new button object in the array element
                      With Buttons(i)  'Set button properties as required
                        .Left = PosLeft   'Set left position
                        .Text = oMarketResp.market.runners(i).name   'Set the text
                        .Tag = oMarketResp.market.runners(i).selectionId 'Save the selectionId in the button's Tag property
                        .TextAlign = ContentAlignment.MiddleLeft  'Set the text alignment
                        .Top = Tpos  'Set top position
                        .Width = Bwidth 'Set button width
                      End With
                      Controls.Add(Buttons(i))   'Display this button on the form
                      AddHandler Buttons(i).Click, AddressOf RunnerButton_Click  'Assign the event handler for this button's click event
                      Tpos += PosBut   'Top position of the next button
                    Next
                
                  End Sub
                
                  'The 'Click' event handler
                
                  Private Sub RunnerButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)
                    Dim RunnerButton As Button = sender  'A reference to the button that was clicked
                    With RunnerButton
                      MsgBox(.Tag & "   " & .Text)  'Show the data for the clicked button
                    End With
                  End Sub
                
                End Class
                The constants (PosLeft, PosTop, PosBut, Bwidth) define the physical position of the buttons on the form. You can change these as required. These values are in pixels.

                The Buttons array will hold references to the buttons that we add.

                Sub AddRunnerButtons is called with the response object from a getMarket call as a parameter. This contains the runner info.

                For each runner we create a new Button object from the Button class (in the System.Windows.Forms namespace) and assign it to the next array element. We now set the properties of this button to what we want. We set the button’s .Text property to the runner’s name, and the selectionId is stored in the .Tag property. (The .Tag is a handy property that you can use for any purpose.)

                A windows form is said the be a “container” object, meaning that it can contain controls. Container objects have a Controls property which is a Collection object. (A Collection is a kind of array). The statement: Controls.Add(Buttons(i)) causes this button to appear on the form.

                The AddHandler statement links this button’s Click event to the event handler sub.

                That takes care of this button. the variable Tpos is incremented so that the top of the next button is positioned below this button. The process repeats until buttons for all runners have been created.

                The click event handler Sub RunnerButton_Click is executed whenever one of the buttons is clicked. The sender parameter contains a reference to the button that was clicked. Using this we can access the button’s properties, in particular .Tag which holds the selectionId. You can now take action such as setting up a bet or displaying the prices for this runner.

                Elsewhere in your program it is easy to access to properties of the runner buttons using the Buttons array. The buttons are numbered 0, 1, 2 ... n-1 corresponding to the array elements. For example:

                Buttons(2).BackColor = Color.LightBlue
                changes the colour of the button for the 3rd runner.

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

                We can test this using the code of Step 12 which calls getMarket to get a list of runners. Add 2 more lines to Sub bRunners_Click :

                Code:
                [COLOR="Gray"].....
                With oMarketResp        'Process the response
                  CheckHeader(.header)
                  Print("ErrorCode = " & .errorCode.ToString)
                  If .errorCode = BFUK.GetMarketErrorEnum.OK Then
                    With .market
                      Print("MarketId = " & .marketId)    'Print id, name and status
                      Print("Name = " & .name)
                      Print("Status = " & .marketStatus.ToString)
                      For i = 0 To .runners.Length - 1
                        With .runners(i)
                          Print(.selectionId & "  " & .name)   'Print list of runners
                        End With
                      Next
                [COLOR="Black"]      MarketForm.Show()    'Show the market form
                      MarketForm.AddRunnerButtons(oMarketResp)  'Add the runner buttons[/COLOR]
                    End With
                  End If
                End With
                .....[/COLOR]
                Run the project. When you click the "Runners" button an array of runner buttons should appear on MarketForm.

                Comment

                • gvigliani
                  Junior Member
                  • Jul 2010
                  • 17

                  #398
                  Horse Racing in Quick List

                  Hello Mumbles0,
                  as time passes the more I am fascinated by bees of Bf. For several days trying desperately to create a 'Quick List' to Win Horse Racing UK. The code I wrote is this:
                  Code:
                  Friend Sub PopulateTreeViewIppicaGB(ByVal AllMarkets As UnpackAllMarkets, ByVal TreeView As TreeView)
                          Dim Ids, Names As String(), Nodes As TreeNodeCollection
                          Dim NumMerc As Integer = 0
                          Dim ok As Boolean
                          With AllMarkets
                              For i = 0 To .marketData.Length - 1          'For each market
                                  With .marketData(i)
                                      NumMerc += 1 : N_Mark.Text = NumMerc.ToString
                                      Ids = .eventHeirachy.Split("/")        'Array of Ids
                                      Names = .menuPath.Split("\")       'Array of names
                                      Nodes = TreeView.Nodes          'Initial collection of child nodes
                                      For j = 1 To UBound(Ids)               'For each event list item
                                          If Not Nodes.ContainsKey(Ids(j)) Then
                                              Dim Node As New TreeNode       'Add a new node if it doesn't exist
                                              Node.Text = If(j <= UBound(Names), Names(j), .marketName)
                                              Node.Name = Ids(j)  'This is the key
                                              Node.Tag = Format(.eventDate, "HH:mm")
                                              If (Names(1) = "Ippica" Or Names(1) = "Horse Racing") And Names(2) = "GB" Then
                                                  If Val(Mid$(Node.Text, 1, 1)) > 0 Then
                                                      Nodes.Add(Node)
                                                      ok = True
                                                  End If
                                              End If
                                          End If
                                      Next
                                  End With
                              Next
                          End With
                      End Sub
                  Unfortunately, the quick list is not sorted by time and then I could have a first race at 18:15 and the second string at 15.22. Is there a way to sort the events by time start?
                  Thanks

                  gvigliani

                  Comment

                  • Mumbles0
                    Junior Member
                    • Jan 2009
                    • 240

                    #399
                    gvigliani,

                    You can sort the AllMarkets.marketData array in order of .eventDate (which is start time) with this statement:

                    Array.Sort(AllMarkets.marketData, Function(x, y) Date.Compare(x.eventDate, y.eventDate))

                    Comment

                    • gunhero
                      Junior Member
                      • Aug 2010
                      • 6

                      #400
                      Step 7: Problem with SoapHeaderException

                      Hi community,
                      today I have started to programm the bot by this thread. First ... thank you for this thread
                      Step by step I programmed the bot, and it runs. But in step 7 I 've a problem and no idea to get it.

                      I have included following code:

                      Code:
                       
                          Function MpricesReq() As BFUK.GetMarketPricesReq
                              Dim oMPReq As New BFUK.GetMarketPricesReq
                              With oMPReq
                                  .header = oHeaderUK()
                                  .marketId = 101657573
                              End With
                          End Function
                      
                          Sub ShowMprices(ByVal MpriceResp As BFUK.GetMarketPricesResp)
                              Dim Lay, Back As String
                              With MpriceResp
                                  CheckHeader(.header)
                                  Print("ErrorCode = " & .errorCode.ToString)
                                  If .errorCode = BFUK.GetMarketPricesErrorEnum.OK Then
                                      With .marketPrices
                                          Print("MarketID = " & .marketId)
                                          For i = 0 To .runnerPrices.Length - 1
                                              With .runnerPrices(i)
                                                  Print("Runner " & i + 1 & "  LPM = " & .lastPriceMatched)
                                                  Back = ""
                                                  For j = 0 To .bestPricesToBack.Length - 1
                                                      With .bestPricesToBack(j)
                                                          Back = Back & "  " & .price & "/" & Int(.amountAvailable)
                                                      End With
                                                  Next
                                                  Lay = ""
                                                  For j = 0 To .bestPricesToLay.Length - 1
                                                      With .bestPricesToLay(j)
                                                          Lay = Lay & "  " & .price & "/" & Int(.amountAvailable)
                                                      End With
                                                  Next
                                                  Print("Back = " & Back & "   Lay = " & Lay)
                                              End With
                                          Next
                                      End With
                                  End If
                              End With
                          End Sub
                      
                      Private Sub bPrices_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bPrices.Click
                              Print("*** Prices ***")
                              ShowMprices(BetFairUK.getMarketPrices(MpricesReq))   'Get market prices
                          End Sub
                      When I start the Debugger, login and click the "Price"-Button the Debugger says: "Eine Ausnahme (erste Chance) des Typs "System.Web.Services.Protocols.SoapHeaderException " ist in System.Web.Services.dll aufgetreten." ("An exception of the type "System.Web.Services.Protocols.SoapHeaderException " occured in System.Web.Services.dll")
                      The pointer shows to "ShowMprices(BetFairUK.getMarketPrices(MpricesReq) ) 'Get market prices".

                      Can you help me to find the mistake?

                      Thank you at all

                      gunhero

                      and sorry for my bad english
                      Last edited by gunhero; 23-08-2010, 04:44 PM.

                      Comment

                      • gvigliani
                        Junior Member
                        • Jul 2010
                        • 17

                        #401
                        Market id

                        Are you sure for the value in .marketid??

                        Bye

                        Comment

                        • gunhero
                          Junior Member
                          • Aug 2010
                          • 6

                          #402
                          I have the value changed, but the mistake don't go away.
                          the marketId is the number before the marketName if i press the button markets right?

                          thanks

                          Comment

                          • Mumbles0
                            Junior Member
                            • Jan 2009
                            • 240

                            #403
                            gunhero,

                            Your problem is because Function MpricesReq does not return a value. You must return the object it creates with a Return statement.

                            Code:
                            [COLOR="Gray"]Function MpricesReq() As BFUK.GetMarketPricesReq
                              Dim oMPReq As New BFUK.GetMarketPricesReq
                              With oMPReq
                                .header = oHeaderUK()
                                .marketId = 101657573
                              End With
                              [COLOR="Black"]Return oMPReq    '<<< Must have return statement![/COLOR]
                            End Function[/COLOR]

                            Comment

                            • gunhero
                              Junior Member
                              • Aug 2010
                              • 6

                              #404
                              oh thank you
                              now it works

                              thanks @ mumbles0
                              gunny

                              Comment

                              • whymetry
                                Junior Member
                                • Aug 2010
                                • 2

                                #405
                                Mumbles thank you ever so much for this tutorial. I am amazed how much I have managed to understand and get through so quickly. I am having a problem however with step 10 getting unpack2 to work correctly. I follow the instructions but for line

                                Dim oMarketPrices As New UnpackCompleteMarketPricesCompressed(.completeMark etPrices)

                                get
                                Error 1 'completeMarketPrices' is not a member of 'BetfairX.BFUK.GetMarketPricesCompressedResp'.

                                Any ideas to what silly mistake I have made?
                                Last edited by whymetry; 24-08-2010, 11:34 AM.

                                Comment

                                Working...
                                X