6

I am creating a c# windows app to display current sports market rates using betfair exchange webservice, I used the

getmarketpricescompressed()

method which returns a price string that looks like this:

106093239~GBP~ACTIVE~0~1~~true~5.0~1343114432333~~N:7337~1~6992.56~2.16~~~false~~~~|2.16~1036.19~L~1~2.14~97.18~L~2~2.12~5.0~L~3~|2.18~467.36~B~1~2.2~34.12~B~2~2.22~162.03~B~3~:414464~2~102181.96~1.86~~~false~~~~|1.85~2900.33~L~1~1.84~1831.59~L~2~1.83~1593.73~L~3~|1.86~58.83~B~1~1.87~1171.77~B~2~1.88~169.15~B~3~

i don't know how to properly unpack this string, for now i am using this code:

GetMarketPricesCompressedReq price_req1 = new GetMarketPricesCompressedReq();
            price_req1.header = header2;
            price_req1.marketId = marketid_temp;
            price_req1.currencyCode = "GBP";
            GetMarketPricesCompressedResp price_resp = new GetMarketPricesCompressedResp();
            price_resp = bfg2.getMarketPricesCompressed(price_req1);
            //MessageBox.Show(price_resp.errorCode.ToString());
            //richTextBox1.Text = "";
            //richTextBox1.Text = price_resp.marketPrices;
            string prices = price_resp.marketPrices;
            richTextBox1.Text = price_resp.marketPrices;
            string[] ab1 = prices.Split('|');
            string[] temp = ab1[1].Split('~');
            textBox3.Text = temp[0];
            textBox4.Text = temp[4];
            textBox5.Text = temp[8];
            temp = ab1[2].Split('~');
            textBox6.Text = temp[0];
            textBox7.Text = temp[4];
            textBox8.Text = temp[8];
            temp = ab1[3].Split('~');
            textBox9.Text = temp[0];
            textBox10.Text = temp[4];
            textBox11.Text = temp[8];
            temp = ab1[4].Split('~');
            textBox12.Text = temp[0];
            textBox13.Text = temp[4];
            textBox14.Text = temp[8];
            if (ab1.Length >5)
            {
                temp = ab1[5].Split('~');
                textBox15.Text = temp[0];
                textBox16.Text = temp[4];
                textBox17.Text = temp[8];
                temp = ab1[6].Split('~');
                textBox18.Text = temp[0];
                textBox19.Text = temp[4];
                textBox20.Text = temp[8];
            }

It works fine for a few matches, but i observed the string changes for a few other matches and it thus generates exceptions, Can any1 help me with a proper code to unpack this string, i've googled it and found a vb code, which was not very usefull,

and btw, i want to arrange the data in something like this:

enter image description here

Samy S.Rathore
  • 1,825
  • 3
  • 26
  • 43
  • The method returns a price string that looks like a long google URL? – Jodrell Jul 24 '12 at 07:17
  • oh gosh, m sorry, that was a mistake, i corrected it for real :3 – Samy S.Rathore Jul 24 '12 at 07:19
  • What was wrong with the (presumably) VB.NET code? If it really was VB.NET it's rather easily convertible to C# with a little knowhow. =) Also, consider posting your second question as an actual second question. =) – J. Steen Jul 24 '12 at 07:24
  • Also - what does the documentation say for that particular method's return values? I'm sure it describes any sort of dynamic content available to you. =) – J. Steen Jul 24 '12 at 07:26
  • Actually the vb code was for unpacking a similar method string, and i don't understand it well....:/ I need to use this method only, as instructed by my lead :| – Samy S.Rathore Jul 24 '12 at 07:27
  • @J.Steen: the documentation just says that "Back/Lay Prices then delimited by a | (pipe), 0 or more iterations" It does'nt gives any algo to extract the data – Samy S.Rathore Jul 24 '12 at 07:30
  • Well, you have an unknown number of price-sequences, yet you're accessing them directly by index. Try going at this with a more iterative approach, looking at each pipe-delimited chunk separately. =) – J. Steen Jul 24 '12 at 07:31
  • It seems to me the data is delimited into rows first by `":"` first, the first row being the header. Then each row is seperated into a kind of Selection ID, Lays and Backs by the `"|"` delimiter. Don't betfair document this, perhaps somewhere here. I can't look, its deemed NSFW. https://docs.developer.betfair.com – Jodrell Jul 24 '12 at 07:35
  • It does, actually - there's a fairly comprehensive breakdown of the entire string in the documentation here: https://docs.developer.betfair.com/betfair/#!page=00008360-MC.00008307-MC – J. Steen Jul 24 '12 at 07:37
  • @Jodrell: i've already been through that documentation, not helpfull, well this is the vb code i was talking about, can some1 help me convert it....pleeeesssssee....:/ http://forum.bdp.betfair.com/showpost.php?p=762&postcount=60 – Samy S.Rathore Jul 24 '12 at 07:40

3 Answers3

3

Consider the following:

a|b|c|d

In this, you have four chunks. But it doesn't necessarily have to be only four. It can be two, it can be six.

Try going at it by iterating the string-array you get as a result of the

string[] ab1 = prices.Split('|');

Something like

foreach(var stringChunk in ab1)
{
    string[] temp = stringChunk.Split('~');
    // use the strings here as you please
}

Consider using a more dynamic approach in presenting your data as well, using a row-based, repeating control instead of static textboxes. =)

The full documentation for the compressed data is available here: https://docs.developer.betfair.com/betfair/#!page=00008360-MC.00008307-MC

J. Steen
  • 15,470
  • 15
  • 56
  • 63
  • well this seems legit, but what if i had to display the parsed data on labels, then i would have to generate and position those labels dynamically......but i guess it's worth a shot....thanxx – Samy S.Rathore Jul 24 '12 at 07:37
2

Just guessing, I think the data is organised like this

first delimited by : then | we get

106093239~GBP~ACTIVE~0~1~~true~5.0~1343114432333~~N

7337~1~6992.56~2.16~~~false~~~~
2.16~1036.19~L~1~2.14~97.18~L~2~2.12~5.0~L~3~ 2.18~467.36~B~1~2.2~34.12~B~2~2.22~162.03~B~3~

414464~2~102181.96~1.86~~~false~~~~ 1.85~2900.33~L~1~1.84~1831.59~L~2~1.83~1593.73~L~3~ 1.86~58.83~B~1~1.87~1171.77~B~2~1.88~169.15~B~3~

I think that first row is clearly a header, that first number being the market ID perhaps. Likewise, the first part of each subsequent section is a row identifier. Delimited by ~ something like

(SelectionId)7337 (Order)1 (TotalMatched?)6992.56 (EvenPoint)2.16 (???)false

I think the price rows are delimited by ~ in tuples of 4, like this

(Price)2.16 (MatchAvailable)1036.19 (Type)L (Order)1
(Price)2.14 (MatchAvailable)0097.18 (Type)L (Order)2
(Price)2.12 (MatchAvailable)0005.00 (Type)L (Order)3

for example.

To test my guesses I'd have to compare with the BetFair rendering on thier web site.

Jodrell
  • 34,946
  • 5
  • 87
  • 124
  • Clearly that is as near as it could be with the original data shown on the website, the (Price) and (MatchAvailable) are as shown on the website, – Samy S.Rathore Jul 24 '12 at 10:34
2

I converted the vb code to c# myself, if anyone might find it useful, I am posting it here:

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;

namespace stock
{
    class UnpackMarketPricesCompressed : stock.BFExchangeService.MarketPrices
{
        //The substitute code for "\:"
    private const string ColonCode = "&%^@";

    //Unpack the string
    public UnpackMarketPricesCompressed(string MarketPrices)
    {
        string[] Mprices = null;
        string[] Part = null;
        string[] Field = null;
        int n = 0;

        Mprices = MarketPrices.Replace("\\:", ColonCode).Split(':');
        //Split header and runner data
        Field = Mprices[0].Replace("\\~", "-").Split('~');
        //Split market data fields
        marketId = Convert.ToInt32(Field[0]);
        //Assign the market data
        currencyCode = Field[1];
        marketStatus = (stock.BFExchangeService.MarketStatusEnum)Enum.Parse(typeof(stock.BFExchangeService.MarketStatusEnum), Field[2], true);
        delay = Convert.ToInt32(Field[3]);
        numberOfWinners = Convert.ToInt32(Field[4]);
        marketInfo = Field[5].Replace(ColonCode, ":");
        discountAllowed = (Field[6].ToLower() == "true");
        marketBaseRate = float.Parse(Field[7]);
        lastRefresh = long.Parse(Field[8]);
        removedRunners = Field[9].Replace(ColonCode, ":");
        bspMarket = (Field[10] == "Y");

        n = Mprices.Length - 1;
         // ERROR: Not supported in C#: ReDimStatement

        //For each runner
        for (int i = 0; i <= n; i++) 
        {
            Part = Mprices[i + 1].Split('|');
            //Split runner string into 3 parts
            Field = Part[0].Split('~');
            //Split runner data fields
             runnerPrices[i] = new stock.BFExchangeService.RunnerPrices();
            var _with1 = runnerPrices[i];
            //Assign the runner data
            _with1.selectionId = Convert.ToInt32(Field[0]);
            _with1.sortOrder = Convert.ToInt32(Field[1]);
            _with1.totalAmountMatched = Convert.ToDouble(Field[2]);
            _with1.lastPriceMatched = Convert.ToDouble(Field[3]);
            _with1.handicap = Convert.ToDouble(Field[4]);
            _with1.reductionFactor = Convert.ToDouble(Field[5]);
            _with1.vacant = (Field[6].ToLower() == "true");
            _with1.farBSP = Convert.ToDouble(Field[7]);
            _with1.nearBSP = Convert.ToDouble(Field[8]);
            _with1.actualBSP = Convert.ToDouble(Field[9]);
            _with1.bestPricesToBack = Prices(Part[1]);
            _with1.bestPricesToLay = Prices(Part[2]);
        }
    }

    private stock.BFExchangeService.Price[] Prices(string PriceString)
    {
        string[] Field = null;
        stock.BFExchangeService.Price[] Price = null;
        int k = 0;
        int m = 0;

        Field = PriceString.Split('~');
        //Split price fields
        m = (Field.Length / 4) - 1;
        //m = number of prices - 1 
         // ERROR: Not supported in C#: ReDimStatement

        for (int i = 0; i <= m; i++) 
        {
            Price[i] = new stock.BFExchangeService.Price();
            var _with2 = Price[i];
            _with2.price = Convert.ToInt32(Field[k + 0]);
            //Assign price data
            _with2.amountAvailable = Convert.ToInt32(Field[k + 1]);
            _with2.betType = (stock.BFExchangeService.BetTypeEnum)Enum.Parse(typeof(stock.BFExchangeService.BetTypeEnum), Field[k + 2], true);
            _with2.depth = Convert.ToInt32(Field[k + 3]);
            k += 4;
        }
        return Price;
        //Return the array of prices
    }

    }
}
Samy S.Rathore
  • 1,825
  • 3
  • 26
  • 43