Using VB2008 to acccess the Betfair API: A tutorial

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts

  • Mumbles0
    replied
    INVALID_PRICE problems

    Hoytman999,

    I’m fairly sure floating-point rounding errors cause these problems. I prefer to use the Decimal data type (rather than Double) to hold price and amount values.

    Here's Function BFPrice. This will round any value to a valid Betfair price:

    Code:
    'Rounds to the nearest Betfair price value 
    
    Private OddsLim() As Decimal = {2, 3, 4, 6, 10, 20, 30, 50, 100}   'Odds range limits
    Private OddsInc() As Decimal = {0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10} 'Odds increments
    
    Function BFPrice(ByVal Price As Decimal) As Decimal
      Dim i As Integer, p As Decimal
    
      For i = 0 To UBound(OddsLim)  'Determine price range
        If Price <= OddsLim(i) Then Exit For
      Next i
      p = Decimal.Round(Price / OddsInc(i), MidpointRounding.AwayFromZero) * OddsInc(i) 'Round to the nearest valid price
      Return Math.Min(Math.Max(p, 1.01D), 1000D)  'Keep within limits
    
    End Function

    Leave a comment:


  • Hoytman999
    replied
    Thanks for the swift reply BigSprout,

    I'll give those a whirl sometime soon...

    Hoytman

    Leave a comment:


  • BigSprout
    replied
    Hi Hoytman,

    Mumbles produced a couple of functions called "IncToPrice" and "PriceToInc", which I use and have never had an "Invalid_Price" error.

    I also use Decimal.Round(Cdec("MyPrice"),2) rather than Math.Round....



    Here we are Page 52, #519 (PriceToInc stuff)

    cheers

    Leave a comment:


  • Hoytman999
    replied
    Hi All,

    I'm (occasionally) getting an "INVALID_PRICE" returned by the .resultcode part of the BFUK.PlaceBetsResp object. In trying to ensure that the price requested is a valid betfair price i've used the following logic:

    Dim tempBackPrice As double
    Dim betfairBackPrice As double

    'Assign value to tempBackPrice here

    If tempBackPrice >= 1 And tempBackPrice < 2 Then betfairBackPrice = 0.01 * Math.Round(tempBackPrice / 0.01, 0)
    If tempBackPrice >= 2 And tempBackPrice < 3 Then betfairBackPrice = 0.02 * Math.Round(tempBackPrice / 0.02, 0)
    If tempBackPrice >= 3 And tempBackPrice < 4 Then betfairBackPrice = 0.05 * Math.Round(tempBackPrice / 0.05, 0)
    If tempBackPrice >= 4 And tempBackPrice < 6 Then betfairBackPrice = 0.1 * Math.Round(tempBackPrice / 0.1, 0)
    If tempBackPrice >= 6 And tempBackPrice < 10 Then betfairBackPrice = 0.2 * Math.Round(tempBackPrice / 0.2, 0)
    If tempBackPrice >= 10 And tempBackPrice < 20 Then betfairBackPrice = 0.5 * Math.Round(tempBackPrice / 0.5, 0)
    If tempBackPrice >= 20 And tempBackPrice < 30 Then betfairBackPrice = Math.Round(tempBackPrice, 0)
    If tempBackPrice >= 30 And tempBackPrice < 50 Then betfairBackPrice = 2 * Math.Round(tempBackPrice / 2, 0)
    If tempBackPrice >= 50 And tempBackPrice < 100 Then betfairBackPrice = 5 * Math.Round(tempBackPrice / 5, 0)
    If tempBackPrice >= 100 And tempBackPrice <= 1000 Then betfairBackPrice = 10 * Math.Round(tempBackPrice / 10, 0)

    Can anyone see any problems with this logic? Is there an easier way to assign a valid betfair price?

    Apologies if this has been asked/answered before but I can't find it anywhere on the forum.

    Thanks

    Leave a comment:


  • Mumbles0
    replied
    Step 36. Handling Excel events

    Excel can raise events which can be handled by the VB2010 project. An event indicates that something has happened within Excel, and usually originates from an Application, Workbook or Worksheet object.

    If you add the WithEvents keyword to the object variable declarations, the events associated with each object will be listed in the left-hand dropdown of the code window. You will see that there are many events. In most cases the name gives a brief description of the event.

    Code:
    [COLOR="Gray"]Private [COLOR="Black"]WithEvents[/COLOR] Exl As Application   'A variable for the Excel object
    Private [COLOR="Black"]WithEvents[/COLOR] Mbook As Workbook    'A variable for the markets workbook
    Private [COLOR="Black"]WithEvents[/COLOR] Msheet As Worksheet  'A variable for the market worksheet
    
    Private Sub ExcelEx_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    
      ........
      ........
    
      Exl = New Excel.Application  'Launch an instance of Excel
      With Exl
        .WindowState = XlWindowState.xlNormal
        .Visible = True           'Show it
        If My.Computer.FileSystem.FileExists(MarketsFile) Then
          Mbook = .Workbooks.Open(MarketsFile)   'Open the Excel file if it exists
          [COLOR="Black"]Msheet = .ActiveSheet [/COLOR] 
        End If
      End With
    
    End Sub[/COLOR]
    Also add the line Msheet = .ActiveSheet to the Load event sub (to make this example work better).

    You handle events originating from Excel in the same way as events originating in the VB2010 project itself. For this example a handler for the Excel application’s SheetActivate event is:

    Code:
    [COLOR="Black"]Private Sub Exl_SheetActivate(ByVal Sh As Object) Handles Exl.SheetActivate
      Msheet = Exl.ActiveSheet  'Msheet refers to the active worksheet
    End Sub[/COLOR]
    This event fires whenever a new worksheet is selected. This allows the variable Msheet to keep track of the currently active worksheet.

    Now add a handler for the worksheet’s Change event:

    Code:
    [COLOR="Black"]Private Sub Msheet_Change(ByVal Target As Excel.Range) Handles Msheet.Change
    
      With Target
        If .Column = 6 Then  'A cell in column F has changed
          Print(.Offset(0, -4).Value & " " & .Offset(0, -3).Value)  'Print selectionId & name
        End If
      End With
    
    End Sub[/COLOR]
    The Change event fires whenever the contents of a cell on the currently-active worksheet changes. The Target parameter is a Range object which references the changed cell. If you manually enter something into a cell in column F, alongside the runner list, this sub should print the selectionId and name of the runner on the same line.

    Looks simple, but... if you try it you will probably get this exception when Sub Print executes:
    Cross-thread operation not valid:
    Control 'tLog' accessed from a thread other than the thread it was created on.

    As I mentioned previously, the Excel application executes on a different thread to your VB2010 project. This means that the event handlers we’ve just added also execute on the Excel application’s thread. Textbox tLog (which is used by Sub Print to log messages) belongs to the VB2010 project’s thread and raises the exception if we attempt to access it from Excel’s thread.

    There is a quick fix for this problem. Put this statement in you form’s Load event handler:

    System.Windows.Forms.TextBox.CheckForIllegalCrossT hreadCalls = False
    This turns off the system’s cross-thread checking facility and Sub Msheet_Change should now work. However, this approach is not recommended by the powers that be. Apparently it is a case of two wrongs making a right. The "proper" way of doing it is to declare a Delegate for the Print sub, then invoke this Delegate if calling from a another thread. We now revise the Print sub:

    Code:
    [COLOR="Black"]Delegate Sub PrintDelegate(ByVal Message As String)  'The delegate declaration
    
    Sub Print(ByVal Message As String)
      If tLog.InvokeRequired Then  'Call is from another thread
        Dim PrintDel As New PrintDelegate(AddressOf Printx) 'Create a delegate for Sub Printx
        Invoke(PrintDel, New Object() {Message})  'Invoke Sub Printx
      Else              'Call is from tLog's thread
        Printx(Message)     'Call Sub Printx normally
      End If
    End Sub
    
    [COLOR="Gray"]Sub [COLOR="Black"]Printx[/COLOR](ByVal Message As String)  'The existing Print sub (re-named Printx)
      With tLog
        .SelectionStart = .Text.Length
        .SelectedText = vbCrLf & Message
      End With
    End Sub[/COLOR][/COLOR]
    Here we have changed the name of the existing Print sub to Printx and added a new Sub Print. The Delegate statement is simply a template for Sub Printx, having the same "signature" i.e. number and type of calling parameters.

    Now, when Sub Print is called, the InvokeRequired property of the tLog textbox is tested to see if the call is being made on the form’s thread or on a different (i.e. Excel’s) thread. If the call is on a different thread, tLog.InvokeRequired returns True, and the delegate PrintDel is created. This delegate "represents" Sub Printx. The form’s Invoke method is now called using this delegate as an argument. This has the effect of marshalling Printx onto the form’s thread. Note that the Message parameter required by Sub Printx is passed in an Object array.

    If the call is on the form’s (i.e. tLog’s) thread then tLog.InvokeRequired returns False, and Sub Printx is called in the usual way.

    I hope this makes sense. Multithreading is a complex field with many pitfalls, and I’m no expert.

    In a typical VB2010 project your UI will consist of several controls on a form. If you intend updating these controls from event handlers driven from an Excel application, the rule is you must Invoke an updating sub via a Delegate, rather than access the control directly from Excel's thread.

    Leave a comment:


  • BigSprout
    replied
    This is most welcome Mumbles, I have been using the quick and dirty way of formatting & saving as a *.CSV file to get any data into excel

    following with interest
    cheers

    Leave a comment:


  • Mumbles0
    replied
    Step 35. Using Excel with VB2010 (continued)

    We now add code to update the prices for the market shown on the active Excel worksheet.

    To get regular price updates we will call getMarketPricesCompressedAsync from a timer. Add a Timer control to your form and set these properties: Name = PriceTimer, Enabled = True, Interval = 2000 (for 2 sec period). Add this Tick event handler:

    Code:
    Private Sub PriceTimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles PriceTimer.Tick
    
      Try
        With Exl
          If .ActiveSheet IsNot Nothing Then
            Dim Req As New BFUK.GetMarketPricesCompressedReq
            Req.header = oHeaderUK()
            Req.marketId = .ActiveSheet.Range(rMarketId).Value   'The marketId on the current worksheet
            BetFairUK.getMarketPricesCompressedAsync(Req, New UserState(.ActiveSheet)) 'Call the API to get prices
          End If
        End With
      Catch
      End Try
    
    End Sub
    At regular intervals determined by PriceTimer, market prices for the marketId contained in cell B2 of the active spreadsheet are requested. In the API call we include a reference to the ActiveSheet so that we can check to see if it has changed when we get the response. The UserState class is as per Step 32.

    The async response is processed with this event handler:

    Code:
    Private Sub BetFairUK_getMarketPricesCompressedCompleted(ByVal sender As Object, ByVal e As BFUK.getMarketPricesCompressedCompletedEventArgs) Handles BetFairUK.getMarketPricesCompressedCompleted
      Dim r As Range, i, j, selectionId As Integer
    
      Try
        If Not e.Cancelled Then
          With e.Result
            CheckHeader(.header)
            If .errorCode = BFUK.GetMarketPricesErrorEnum.OK Then 'Response is OK
    
              Dim Sheet As Worksheet = e.UserState.Param  'The active worksheet when the request was made
              If Sheet Is Exl.ActiveSheet Then  'This sheet is still active
                Dim oMarketPrices As New UnpackMarketPricesCompressed(.marketPrices)  'Unpack the prices
                With oMarketPrices
    
                  r = Sheet.Range(rRunners)  'The start of the runners list
                  i = 0
                  Try
                    Do  'Update runner prices
                      selectionId = Val(r.Offset(i, 0).Value)  'Next runner in the list
                      If selectionId = 0 Then Exit Do 'End of runners list
    
                      j = Array.FindIndex(.runnerPrices, Function(x As BFUK.RunnerPrices) x.selectionId = selectionId) 'Array index for this runner
                      If j >= 0 Then  'Prices exist for this runner
    
                        With .runnerPrices(j)
                          r.Offset(i, 2).Value = If(.bestPricesToBack.Length > 0, .bestPricesToBack(0).price, "")  'Update best back price
                          r.Offset(i, 3).Value = If(.bestPricesToLay.Length > 0, .bestPricesToLay(0).price, "")    'Update best lay price
                        End With
    
                      Else  'No prices, could be removed runner
                        r.Offset(i, 2).Value = ""
                        r.Offset(i, 3).Value = ""
                      End If
                      i += 1
                    Loop
    
                    r.Offset(-2, 1).Value = .marketStatus.ToString  'Show market status
    
                  Catch
                  End Try
                End With
              End If
    
            Else
              Print("GetMarketPricesCompressed error:" & .errorCode.ToString) 'If problem
            End If
          End With
        End If
      Catch ex As ApplicationException
        Print(e.Error.Message)
      End Try
    
    End Sub
    If the response from the API is OK, and ActiveSheet has not changed, the market prices are unpacked. The local Range object variable r is set to the cell which defines the start of the runner list (B7).

    In the Do loop we extract the selectionId from column B of the worksheet for each runner in turn, and look up the oMarketPrices.runnerPrices array to find the index of the element for this selectionId. We use the data in this element to update the best Back and Lay price columns.

    When the end of the runner list is reached (defined by an empty cell) the Do loop terminates and the current market status is updated (in cell C5). That's all.

    If you click on a tab to select another market, the ActiveSheet changes, causing the prices for the newly-selected market to be updated the next time the timer ticks.


    VB2010/Excel relationship

    If you are developing an app with Excel (using the ideas in this example) you will find that the relationship between your VB2010 project and the Excel application is quite shaky.

    The reason is because Excel runs concurrently on a different thread. If, for example, your project attempt to update cells on a worksheet while Excel is doing something else, Excel may complain, raising obscure COM exceptions, (such as "Exception from HRESULT: 0x800AC472".

    Notice that I have enclosed the parts of the code which access the Excel objects in Try..Catch blocks. This is to prevent exceptions of this nature crashing the app.


    These two steps have demonstrated how a VB2010 app can read from, or write to the cells of an Excel spreadsheet. I intend posting another step looking at responding to events raised by the Excel application.
    Last edited by Mumbles0; 14-10-2011, 09:42 PM.

    Leave a comment:


  • Mumbles0
    replied
    Step 34. Using Excel with VB2010

    Some readers of this thread have expressed interest in using an Excel spreadsheet to display API data. There is, of course, a section in the forum devoted to this topic (VB6 and Excel). It is interesting to know that you can also drive Excel from a VB2010 project. In this step we will have a look how to do this.

    It’s probably best to start a new project for this exercise. Include login facilities and a tLog textbox, also include the basic procedures (Print, CheckHeader, etc.) and add the web references (BFGlobal and BFUK) as given in the earlier tutorial steps. Provide some means of selecting your markets of interest, such as the TreeView of step 15 or a perhaps a "Today’s Card" ListBox using the idea of step 18. Once you have a "skeleton" project up and running we can proceed.

    First we must add a reference to the Excel library. On the Project menu select "Add Reference". On the "COM" tab select "Microsoft Excel 11.0 Object Library", then click "OK".

    This exercise is similar to what was outlined in Steps 31 and 32 where a TabControl was used to display the market data, but instead of using the TabControl, here we will use an Excel spreadsheet.

    I have named the project’s startup form ExcelEx. Note the Imports statement at the very top of the form's code. This allows us to refer to classes, etc. within the Excel namespace without the Excel prefix. Add the constants and private variables as shown, also add more code to the form’s Load event handler sub:

    Code:
    Imports Excel
    Public Class ExcelEx
    
      'A project using Excel to display markets
    
       ........
      ........
      ........
    
      Const MarketsFile = "C:\Betfair\Markets.xls"  'The Excel file containing the market data
      Const rMarketId = "B2"          'Cell for the marketId
      Const rRunners = "B7"           'Start of runners list
    
      Private Exl As Application              'A variable for the Excel object
      Private Mbook As Workbook               'A variable for the markets workbook
      Private WithEvents Msheet As Worksheet  'A variable for the market worksheet
    
      Private Sub ExcelEx_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    
        ........
        ........
        ........
     
        Exl = New Excel.Application  'Launch an instance of Excel
        With Exl
          .WindowState = XlWindowState.xlNormal
          .Visible = True           'Show it
          If My.Computer.FileSystem.FileExists(MarketsFile) Then
            Mbook = .Workbooks.Open(MarketsFile)   'Open the Excel file if it exists
          End If
        End With
    
      End Sub
    When you run the project, the first code to execute is Sub ExcelEx_Load. Here Exl is an object which represents the Excel application. By creating this object we launch an instance of Excel. This object has many properties pertaining to the Excel application and we assign two of them here. Run the project and you will see what happens.

    The MarketsFile constant defines a path to a spreadsheet file which will be opened if it exists. Initially, this file does not exist so Excel starts up "empty".

    Now add the following two subs. I mentioned previously that you require some means of selecting markets. Arrange your code so that Sub DisplayMarketSheet is called with your marketId of interest.

    Code:
    Sub DisplayMarketSheet(ByVal MarketId As Integer)
      Dim r As Range
    
      Try
        With Exl
          If .Workbooks.Count = 0 Then  'First time run, there is no workbook
            .SheetsInNewWorkbook = 1
            Mbook = .Workbooks.Add        'Add a workbook with 1 worksheet
            Msheet = Mbook.Worksheets(1)   'A reference to the worksheet
    
          Else  'Workbook exists
    
            Msheet = FindSheet(MarketId)  'Look for a worksheet for this market
            If Msheet IsNot Nothing Then
              Msheet.Activate() 'Show the existing sheet for this market
              Exit Sub
    
            Else  'New market
              Msheet = Mbook.Worksheets.Add()  'Add a new sheet
            End If
          End If
    
          Dim Req As New BFUK.GetMarketReq With {.header = oHeaderUK(), .marketId = MarketId}
          Dim Resp As BFUK.GetMarketResp = BetFairUK.getMarket(Req)    'Call API (getMarket)
          With Resp
            CheckHeader(.header)
            If .errorCode = BFUK.GetMarketErrorEnum.OK Then  'Put the market data on the spreadsheet
              With .market
    
                r = Msheet.Range(rMarketId)   'The cell for the MarketId
                r.ColumnWidth = 12
                r.Value = MarketId                     'marketId in B2
                r.Offset(0, 1).ColumnWidth = 25
                r.Offset(0, 1).Value = .menuPath       'menuPath in C2
                r.Offset(1, 0).NumberFormat = "hh:mm"  'set a time format
                r.Offset(1, 0).Value = .marketTime.ToLocalTime     'marketTime in B3
                r.Offset(1, 1).Value = .name           'marketName in C3
    
                r = Msheet.Range(rRunners)    'Start of runner list
                With r.Offset(-2, 2) 'Back' column
                  .HorizontalAlignment = XlHAlign.xlHAlignRight  'Align right
                  .Value = "Back"   'Heading
                End With
                With r.Offset(-2, 3) 'Lay' column
                  .HorizontalAlignment = XlHAlign.xlHAlignRight  'Align right
                  .Value = "Lay"   'Heading
                End With
    
                For i = 0 To .runners.Length - 1  'Show runner list
                  With .runners(i)
                    r.Offset(i, 0).Value = .selectionId
                    r.Offset(i, 1).Value = .name
                  End With
                Next
    
                Msheet.Name = .name  'Tab is marketName
              End With
    
            Else  'Problem with API call
              Print("GetMarket error: " & .errorCode.ToString)
            End If
          End With
    
        End With
      Catch
      End Try
    
    End Sub
    
    Function FindSheet(ByVal MarketId As Integer) As Worksheet  'Returns the worksheet for the marketId
      Dim Sheet As Worksheet
      For Each Sheet In Mbook.Worksheets
        If Sheet.Range(rMarketId).Value = MarketId Then Return Sheet
      Next
    End Function
    To show a worksheet for a market you call sub DisplayMarketSheet. If a worksheet already exists for the market it simply activates. For a new market, a new worksheet is created and an API call to getMarket is made. The returned data is written to this new worksheet, with the runner info (selectionId and Name) appearing as a list starting at cell B7. The first call to DisplayMarketSheet creates a new workbook because none exists initially.

    The code detail demonstrates the use of the Range object to assign values to the various cells on the spreadsheet. Frequent use is made of the Offset property to reference cells relative to an “anchor” cell. Of course there would be other ways to achieve a similar result.

    Function FindSheet determines if a worksheet exists for a given marketId. If so, a reference to this worksheet is returned. If not, Nothing is returned. Note that the worksheets are identified by the marketId value in cell B2 (as defined by the constant rMarketId).

    To understand more about the Excel classes and their members, for example Range, Worksheet, Worksheets, Workbook, Workbooks, Application, etc. it would be nice to have some documentation on the Interop.Excel namespace but, unfortunately, not much exists. Some information is given here and here, but this is very sketchy. You can go hunting for more.

    However, the classes are virtually the same as the VBA classes. VBAers will have no problem with this. So I suggest that you learn a bit about VBA, particularly the objects used to access the spreadsheet. There is a great deal of information (tutorials, references, etc.) on the internet about VBA. A good run down on the important Range object is given here.

    To finish this Step add the FormClosing event handler. This executes when you close the project. (Use this rather than closing Excel directly.)

    Code:
    Private Sub ExcelEx_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
      Try
        Mbook.Close(True)  'Close and save the workbook 
        Exl.Quit()         'Close Excel 
      Catch
      End Try
    End Sub
    This saves the workbook and closes Excel. The first time you do this you will be prompted to save the workbook. If you choose the file name Markets.xls and save in the C:\Betfair\ folder (as given by the MarketsFile constant) this file will be opened next time you run the project.

    In the next Step we will call getMarketPricesCompressed to include best Back and Lay prices for the runners on the spreadsheet.


    Note: This example was developed using Excel 2003. I’m fairly confident that it will work with other versions of Excel.

    Leave a comment:


  • Camper
    replied
    I've been using multiple forms and I'm login in on each form.

    How can I use multiple forms without using this wrong code?

    EDIT: Solved.
    Last edited by Camper; 10-10-2011, 10:32 PM.

    Leave a comment:


  • Geierkind
    replied
    Thanks for your great advice.

    The source of my problem was, as I found out, Betfair not recognizing one of the countrycodes in the array. But your method of course, is far better.

    Leave a comment:


  • BigSprout
    replied
    Geierkind,
    Countries of type arrayofcountrycode is used to restrict the data you receive and is not mandatory, if you want all countries then just comment out the line.

    Code:
    'ReDim .countries(40) : .countries(0) = "ARG"......etc
    Normally a response as you are receiving is due to no sporting activity happening during the time period you have specified - or BF may have a maximum number of countries to call at one time (should get an error for that tho)

    Leave a comment:


  • Geierkind
    replied
    Hi, in my getmarkets Sub, I dim the following Countries, with this code:

    Code:
    ReDim .countries(23) : .countries(0) = "ARG" : .countries(1) = "AUT" : .countries(2) = "BEL" : .countries(3) = "BRA" : .countries(4) = "BGR" : .countries(5) = "CHL" : .countries(6) = "COL" : .countries(7) = "HRV" : .countries(8) = "CYP" : .countries(9) = "CZE" : .countries(10) = "DNK" : .countries(11) = "NLD" : .countries(12) = "GBR" : .countries(13) = "EST" : .countries(14) = "FIN" : .countries(15) = "FRA" : .countries(16) = "DEU" : .countries(17) = "GRC" : .countries(18) = "HKG" : .countries(19) = "HUN" : .countries(20) = "ISL" : .countries(21) = "IRL" : .countries(22) = "ITA" : .countries(23) = "JPN"
    This Code is working!

    Now I change it to this, which is essentially the same thing, only larger, as you see:

    Code:
    ReDim .countries(40) : .countries(0) = "ARG" : .countries(1) = "AUT" : .countries(2) = "BEL" : .countries(3) = "BRA" : .countries(4) = "BGR" : .countries(5) = "CHL" : .countries(6) = "COL" : .countries(7) = "HRV" : .countries(8) = "CYP" : .countries(9) = "CZE" : .countries(10) = "DNK" : .countries(11) = "NLD" : .countries(12) = "GBR" : .countries(13) = "EST" : .countries(14) = "FIN" : .countries(15) = "FRA" : .countries(16) = "DEU" : .countries(17) = "GRC" : .countries(18) = "HKG" : .countries(19) = "HUN" : .countries(20) = "ISL" : .countries(21) = "IRL" : .countries(22) = "ITA" : .countries(23) = "JPN" : .countries(24) = "MEX" : .countries(25) = "USA" : .countries(26) = "NOR" : .countries(27) = "POL" : .countries(28) = "PRT" : .countries(29) = "ROM" : .countries(30) = "RUS" : .countries(31) = "GBR" : .countries(32) = "SRB" : .countries(33) = "SGP" : .countries(34) = "SVK" : .countries(35) = "SVN" : .countries(36) = "KOR" : .countries(37) = "ESP" : .countries(38) = "SWE" : .countries(39) = "CHE" : .countries(40) = "TUR"
    Now the program just stops working, gives no error message but also recieves no markets at all.
    What is happening here?

    Thank you.

    Leave a comment:


  • luckyjock
    replied
    Trying to do something similar to step 6 - Dim AllMarkets

    Further to my earlier post about trying to get data to a database, i have managed to get the Market data unpacked in Step 6 into a datatable and then into a SQL table via a tableadapter.

    I did this by setting up an object
    Code:
    Dim matchdata(15) As Object
    and then using Mumbles original code tweaked slightly
    Code:
    Dim AllMarkets As New UnpackAllMarkets(.marketData)
                    With AllMarkets
                        For i = 0 To .marketData.Length - 1
                            With .marketData(i)
                                Print(.marketId & " " & .marketStatus & " " & .eventDate & " " & .marketName & " " & .menuPath)
                                matchdata(0) = .marketId
                                matchdata(1) = .marketName
                                matchdata(2) = .marketType
                                matchdata(3) = .marketStatus
                                matchdata(4) = .eventDate.ToLocalTime
                                matchdata(5) = .menuPath
                                matchdata(6) = .eventHeirachy
                                matchdata(7) = .betDelay
                                matchdata(8) = .exchangeId
                                matchdata(9) = .countryCode
                                matchdata(10) = .lastRefresh
                                matchdata(11) = .noOfRunners
                                matchdata(12) = .noOfWinners
                                matchdata(13) = .totalAmountMatched
                                matchdata(14) = .bspMarket
                                matchdata(15) = .turningInPlay
    I am now trying to do something similar with the Unpack 2 module that uses the UnpackCompleteMarketPricesCompressed API call.

    My problem is that the data is split into 3 parts. If i use this code it doesn't recognise the marketId or delay fields as they are part of the UnpackCompleteMarketPricesCompressed Class not the runnerInfoType. I have setup a object for the data but then not quite sure how to do the rest?

    Code:
    Dim runnerData(18) As Object
                            With oMarketPrices
                                Print(.marketId & "  " & .runnerInfo.Length & " runners")
                                'Process returned market prices here.
                                For i = 0 To .runnerInfo.Length - 1
                                    With .runnerInfo(i)
                                        Print(.sortOrder & " " & .selectionId & " " & .totalAmountMatched & " " & .lastPriceMatched)
                                        runnerData(0) = .marketId
                                        runnerData(1) = .delay
                                        runnerData(2) = 
                                        runnerData(3) =
                                        runnerData(4) =
                                        runnerData(5) =
                                        runnerData(6) =
    Could anyone point me in the general direction so i can try and do it? I thought i could probably put it like this but how would i incorporate the PricesType info and get that into my runnerData object?

    Many thanks for any help, cheers

    Code:
    With oMarketPrices
                                Print(.marketId & "  " & .runnerInfo.Length & " runners")
                                runnerData(0) = .marketId
                                runnerData(1) = .delay
                                runnerData(2) = .removedRunners
    
                                'Process returned market prices here.
                                For i = 0 To .runnerInfo.Length - 1
                                    With .runnerInfo(i)
                                        Print(.sortOrder & " " & .selectionId & " " & .totalAmountMatched & " " & .lastPriceMatched)
                                        runnerData(3) = .selectionId

    Leave a comment:


  • Camper
    replied
    Anyone? I can't figure this out.

    EDIT: I solved it, thanks anyway.

    Small error, I only changed ToUpper.Contains to ToUpper.Equals

    Regards
    Last edited by Camper; 28-09-2011, 04:00 PM.

    Leave a comment:


  • Camper
    replied
    I'm using CompleteMarketPricesCompressed to build a ladder.

    This is part of my code:
    Code:
    For i = 0 To .runnerInfo.Length - 1
                                    With .runnerInfo(i)
                                        If .selectionId = player1id Then
    
                                            TAM1 = Int(.totalAmountMatched) & " €"
                                            LPM1 = .lastPriceMatched
                                            Dim Row As DataGridViewRow
                                            Dim ColumnName As String = "Odd"
    
                                            For k = 0 To .prices.Length - 1
                                                With .prices(k)
                                                    Dim x As Integer
                                                    If .backAmount > 0 Then
                                                        Dim preco As String = CStr(.price)
                                                        BPrice1.Add(.price)
                                                        Dim backprice() As Double = BPrice1.ToArray
                                                        For m = 0 To backprice.Length - 1
                                                            x = backprice.Length - 1
                                                        Next
    
                                                        BP1 = backprice(x)
    
                                                        Row = (From Rows In DataGridView1.Rows.Cast(Of DataGridViewRow)() _
                                                                  Where Rows.Cells(ColumnName).Value.ToString().ToUpper.Contains(preco)).FirstOrDefault
    
                                                        If .backAmount >= 1 Then
                                                            If Row IsNot Nothing Then
                                                                Row.Cells("BUA").Value = Int(.backAmount)
                                                            End If
                                                        End If
                                                        If .backAmount > 0 And .backAmount < 1 Then
                                                            If Row IsNot Nothing Then
                                                                Row.Cells("BUA").Value = .backAmount
                                                            End If
                                                        End If
                                                    End If
    
                                                    If .layAmount > 0 Then
                                                        Dim preco As String = CStr(.price)
                                                        LPrice1.Add(.price)
                                                        Dim layprices() As Double = LPrice1.ToArray
                                                        LP1 = layprices(0)
                                                        Row = (From Rows In DataGridView1.Rows.Cast(Of DataGridViewRow)() _
                                                                      Where Rows.Cells(ColumnName).Value.ToString().ToUpper.Contains(preco)).FirstOrDefault
                                                        If .layAmount >= 1 Then
                                                            If Row IsNot Nothing Then
                                                                Row.Cells("LUA").Value = Int(.layAmount)
                                                            End If
                                                        End If
                                                        If .layAmount > 0 And .layAmount < 1 Then
                                                            If Row IsNot Nothing Then
                                                                Row.Cells("LUA").Value = .layAmount
                                                            End If
                                                        End If
                                                    End If
                                                End With
                                            Next
                                        End If
    Sometimes it works great and sometimes a small bug appears:


    This value should not be here ! I have no idea why, I tried all of kind of solutions. Needing help here

    Leave a comment:

Working...
X