Skip to content

Exchange MarketSymbol to Currencies Parsing Suggestion #424

Closed

Description

@GonzoKK

I use the following function to parse a MarketSymbol to its two currencies

ie STRATBTC = "STRAT", "BTC"

image

It requires an array of QuoteCurrencies for the exchange eg
string[] array = { "XX", "USDT", "EURS", "USD", "BTC", "Y", "ETH", "EOS", "DAI" };

as well as a SymbolFormat for the exchange eg
"{1}{0}" //Hitbtc, Binance
"{0}-{1}" //Bittrex

public static (string BaseCurrency, string QuoteCurrency) ExchangeMarketSymbolToCurrencies_V2(
    string marketSymbol, //eg  string testStr = "STRATBTC";
    string[] quoteCurrencies, //eg string[] array = { "XX", "USDT", "EURS", "USD", "BTC", "Y", "ETH", "EOS", "DAI" };
    string symbolFormat
    )
{
    if(quoteCurrencies == null) return (null, null);
    var currency1 = "";
    var currency2 = "";

    switch(symbolFormat) {
        case "{1}{0}": //eg Hitbtc, Binance
            IEnumerable<IGrouping<int, string>> groups = quoteCurrencies.OrderByDescending(x => x.Length).GroupBy(x => x.Length);
            foreach(IGrouping<int, string> grp in groups) {
                if(grp.Any(x => marketSymbol.EndsWith(x))) {
                    var idx = marketSymbol.Length - grp.Key;
                    currency1 = marketSymbol.Substring(idx);
                    currency2 = marketSymbol.Substring(0, idx);
                    return (currency1, currency2);
                }//if
            }//foreach
            break;

        case "{0}-{1}": //eg Bittrex
            var split = marketSymbol.Split('-');
            currency1 = split[0];
            currency2 = split[1];
            return (currency1, currency2);
    }//switch

    return (null, null);
}//eof


Activity

  1. jjxtra commented on Aug 20, 2019

    @jjxtra
    Collaborator

    Most of this functionality is built into the ExchangeAPI class, such as symbol separator, normalize symbol, global symbol translation, etc. A few weird exchanges (Kraken) have non-standard symbol names and they require an internal lookup table.

  2. vslee commented on Aug 20, 2019

    @vslee
    Collaborator

    Good work, can you go through and make sure the new logic works with all of the existing exchanges? Such as factoring in symbolreversal and arbitrary symbol separator. Then, we can replace the original method completely.

  3. vslee commented on Aug 20, 2019

    @vslee
    Collaborator

    Oh, looks like jjxtra put a comment before I finished typing mine. I guess try seeing what you can do to improve the existing method if needed.

  4. vslee commented on Aug 20, 2019

    @vslee
    Collaborator

    The problem with doing it this way is that you need to constantly update the list of currencies for each exchange.

  5. GonzoKK commented on Aug 20, 2019

    @GonzoKK
    Author

    You can either:

    (1) Hard code the list of "Quote Currencies" per exchange. Quote markets rarely change. Bittrex for example only has four - { "USDT", "BTC", "ETH", "USD" }

    (2) Generate a list of Distinct quote currencies once you have a list of MarketSymbols eg

    List<string> listQuoteCurrencies = listMarketSymbols.Select(x => x.QuoteCurrency).Distinct().OrderBy(s => s).ToList();

  6. vslee commented on Aug 20, 2019

    @vslee
    Collaborator

    @GonzoKK, how would you propose to parse symbol "hb10"?

  7. GonzoKK commented on Aug 21, 2019

    @GonzoKK
    Author

    @vslee, It appears that "hb10" and "huobi10" should be treated differently as they are an index of 10 coins (not markets)

    https://www.hbg.com/en-us/markets/hb_index/

    HB10 Index is composed of 10 coins that are listed on Huobi and have the higher market value, larger scale and better circulation to reflect the overall performance of Huobi Global's market.
    The sample space is all listed coins that are traded against USDT at Huobi Global.

    The list of quote currencies for Huobi would be restricted to "husd", "usdt", "btc", "eth", "trx", "ht"

    This means that "hb10" is NOT included and the above function would return (null, null)

    image

    image

  8. GonzoKK commented on Aug 21, 2019

    @GonzoKK
    Author

    Here's my method to get a list of Quote Currencies for an exchange.

    For Huobi it returns "husd", "usdt", "btc", "eth", "trx", "ht"

    public List<string> GetQuoteCurrencies(IEnumerable<ExchangeSharp.ExchangeMarket> GetMarketSymbolsMetadataAsync)
    {
        List<string> listQuoteCurrencies = GetMarketSymbolsMetadataAsync.Select(x => x.QuoteCurrency).Distinct().OrderByDescending(s => s.Length).ThenBy(s => s).ToList();
        return listQuoteCurrencies;
    }
    
  9. GonzoKK commented on Aug 21, 2019

    @GonzoKK
    Author

    @jjxtra, I'm gradually dipping into the code, so I'm still unfamiliar with many aspects.

    However it does seem that the "Symbol Separator" method (ExchangeMarketSymbolToCurrencies) is hard coded around a perfect 3/3 split btw CurrencyA and CurrencyB

    What happens if quote currency is "USDT" ie 4 chars?

    image

  10. GonzoKK commented on Aug 21, 2019

    @GonzoKK
    Author

    There are many examples of 6 char MarketSymbols where the split is 4-2 or 2-4

    Others could be 4-3, 5-2, 5-3, etc

  11. vslee commented on Aug 21, 2019

    @vslee
    Collaborator

    I do think that your parsing logic is better than the 3-3 splitting. However, extensive testing would need to be done with all places where this method is currently used to prevent breaking something in the process of improving things.

  12. GonzoKK commented on Aug 22, 2019

    @GonzoKK
    Author

    Yeah, parser should handle any number of characters and any split ratio.

    BTW I see that Binance is hard coded with regards to quote currencies.

    image

  13. jjxtra commented on Aug 22, 2019

    @jjxtra
    Collaborator

    It is frustrating that these major exchanges do not use separators. They also can't agree on which order the symbols go in. Very poor planning and architecture. So the best we can do is hard-code the pairs in these cases.

  14. GonzoKK commented on Sep 4, 2019

    @GonzoKK
    Author

    @vslee Do you plan on tackling the alternate parsing logic?

    As I mentioned, due to my unfamiliarity with the code base, I'm hesitant to make big changes on my own. However I would be more than happy to help out and do research/grunt work.

    Let me know. I can help via Telegram or Discord...

  15. 2 remaining items

  16. jjxtra commented on Sep 4, 2019

    @jjxtra
    Collaborator

    What symbols?

  17. GonzoKK commented on Sep 4, 2019

    @GonzoKK
    Author

    the errors vary, but for example on ZB.com

    System.InvalidOperationException: Sequence contains no matching element
    at System.Linq.Enumerable.First[TSource](IEnumerable1 source, Func2 predicate)
    at ExchangeSharp.ExchangeZBcomAPI.d__16.MoveNext() in C:!Dev\ExchangeSharp-master(8)\ExchangeSharp\API\Exchanges\ZBcom\ExchangeZBcomAPI.cs:line 127
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at ExchangeSharp.ExchangeAPI.<<GetTickersAsync>b__63_0>d.MoveNext() in C:\!Dev\ExchangeSharp-master(8)\ExchangeSharp\API\Exchanges\_Base\ExchangeAPI.cs:line 592 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
    at ExchangeSharp.CryptoUtility.<>c__DisplayClass84_01.<<CacheMethod>b__0>d.MoveNext() in C:\!Dev\ExchangeSharp-master(8)\ExchangeSharp\Utility\CryptoUtility.cs:line 1380 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
    at ExchangeSharp.MemoryCache.d__81.MoveNext() in C:\!Dev\ExchangeSharp-master(8)\ExchangeSharp\Utility\MemoryCache.cs:line 202 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
    at ExchangeSharp.CryptoUtility.d__841.MoveNext() in C:\!Dev\ExchangeSharp-master(8)\ExchangeSharp\Utility\CryptoUtility.cs:line 1378 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
    at ExchangeSharp.ExchangeAPI.d__63.MoveNext() in C:!Dev\ExchangeSharp-master(8)\ExchangeSharp\API\Exchanges_Base\ExchangeAPI.cs:line 592

  18. jjxtra commented on Sep 4, 2019

    @jjxtra
    Collaborator

    I'd like to write a test. Does it fail for all symbols or specific symbols?

  19. GonzoKK commented on Sep 4, 2019

    @GonzoKK
    Author

    for zb.com it fails on "xucusdt"

    {"xucusdt": {
    "high": "0",
    "vol": "0",
    "last": "1.45",
    "low": "0",
    "buy": "1.44",
    "sell": "1.45"
    }}

    the reason in this case is that "xuc_usdt" is not found in symbols

    image

  20. GonzoKK commented on Sep 4, 2019

    @GonzoKK
    Author

    i can most likely fix zb.com using my "alternate parser" logic above, however I dont want to go off at a tangent....

  21. jjxtra commented on Sep 4, 2019

    @jjxtra
    Collaborator

    This works for me, latest master. I had to fix a json parse error.

    ExchangeZBcomAPI api = new ExchangeZBcomAPI();
    string marketSymbol = api.GlobalMarketSymbolToExchangeMarketSymbol("USDT-XUC"); // becomes xuc_usdt
    var ticker = api.GetTickerAsync(marketSymbol).Sync();
    
  22. GonzoKK commented on Sep 4, 2019

    @GonzoKK
    Author

    Not resolved, ZB.com still fails OnGetTickersAsync

    image

  23. jjxtra commented on Sep 4, 2019

    @jjxtra
    Collaborator

    Looks like a bug on their exchange. http://api.zb.cn/data/v1/markets does not return xuc_usdt. I don't think I want to add hacks for this, so I will skip over not found elements in this call.

    If you use this exchange a lot, I would suggest to file a bug with them.

  24. GonzoKK commented on Sep 4, 2019

    @GonzoKK
    Author

    Here's my fix for ZB.com using the alternate parser logic...

    image

    protected override async Task<IEnumerable<KeyValuePair<string, ExchangeTicker>>> OnGetTickersAsync()
    {
        //{ "hpybtc":{ "vol":"500450.0","last":"0.0000013949","sell":"0.0000013797","buy":"0.0000012977","high":"0.0000013949","low":"0.0000011892"},"tvqc":{ "vol":"2125511.1",
        var data = await MakeRequestZBcomAsync(null, "/allTicker", BaseUrl);
        List<KeyValuePair<string, ExchangeTicker>> tickers = new List<KeyValuePair<string, ExchangeTicker>>();
        var symbols = (await GetMarketSymbolsAsync()).ToArray();
        string marketSymbol;
    
        string SymbolFormat = "{1}{0}"; //eg "xucusdt" 
        string[] QuoteCurrencies = new[] { "usdt", "btc", "qc", "zb" }; //hardcoded 
    
        foreach(JToken token in data.Item1) {
            //for some reason when returning tickers, the api doesn't include the symbol separator like it does everywhere else so we need to convert it to the correct format
            string squashedSymbol = token.Path; //eg "xucusdt" 
    
            var codeSwitch = "HardCoded_QuoteCurrencies";
            switch(codeSwitch) {
    
                case "Existing_Code": ///this crashes on "xucusdt"
                    marketSymbol = symbols.First(s => s.Replace(MarketSymbolSeparator, string.Empty).Equals(token.Path));
                    tickers.Add(new KeyValuePair<string, ExchangeTicker>(marketSymbol, ParseTickerV2(marketSymbol, token)));
                    break;
    
                case "HardCoded_QuoteCurrencies":
                    (string Currency1, string Currency2) pair = CryptoUtility.ExchangeMarketSymbolToCurrencies_V2(squashedSymbol, QuoteCurrencies, SymbolFormat);
                    if (!string.IsNullOrEmpty(pair.Currency1) && !string.IsNullOrEmpty(pair.Currency2)) {
                        marketSymbol = pair.Currency2 + MarketSymbolSeparator + pair.Currency1;
                        tickers.Add(new KeyValuePair<string, ExchangeTicker>(marketSymbol, ParseTickerV2(marketSymbol, token)));
                    }
                    break;
            }//switch
        }
        return tickers;
    }
    

    I added ExchangeMarketSymbolToCurrencies_V2 to CryptoUtility.cs

    image

    public static (string Currency1, string Currency2) ExchangeMarketSymbolToCurrencies_V2(
        string marketSymbol, //eg  string testStr = "STRATBTC";
        string[] quoteCurrencies, //eg string[] array = { "XX", "USDT", "EURS", "USD", "BTC", "Y", "ETH", "EOS", "DAI" };
        string symbolFormat
        )
    {
        if(quoteCurrencies == null) return (null, null);
        string currency1;
        string currency2;
    
        switch(symbolFormat) {
            case "{1}{0}": //eg Hitbtc, Binance, ZB.com
                IEnumerable<IGrouping<int, string>> groups = quoteCurrencies.OrderByDescending(x => x.Length).GroupBy(x => x.Length);
                foreach(IGrouping<int, string> grp in groups) {
                    if(grp.Any(x => marketSymbol.EndsWith(x))) {
                        var idx = marketSymbol.Length - grp.Key;
                        currency1 = marketSymbol.Substring(idx);
                        currency2 = marketSymbol.Substring(0, idx);
                        return (currency1, currency2);
                    }//if
                }//foreach
                break;
    
            case "{0}-{1}": //eg Bittrex
                var split = marketSymbol.Split('-');
                currency1 = split[0];
                currency2 = split[1];
                return (currency1, currency2);
        }//switch
    
        return (null, null);
    }//eof
    

    Result...

    image

  25. GonzoKK commented on Sep 4, 2019

    @GonzoKK
    Author

    Here's my fix for Huobi's OnGetTickersAsync

    image

    protected async override Task<IEnumerable<KeyValuePair<string, ExchangeTicker>>> OnGetTickersAsync()
    {
        List<KeyValuePair<string, ExchangeTicker>> tickers = new List<KeyValuePair<string, ExchangeTicker>>();
        string symbol;
        JToken obj = await MakeJsonRequestAsync<JToken>("/market/tickers", BaseUrl, null);
    
        string SymbolFormat = "{1}{0}"; //eg "xlmusdt" 
        string[] QuoteCurrencies = new[] { "husd", "usdt", "btc", "eth", "trx", "ht" }; //hardcoded 
    
        //foreach (JToken child in obj["data"])
        foreach(JToken child in obj) {
            symbol = child["symbol"].ToStringInvariant();
            (string Currency1, string Currency2) pair = CryptoUtility.ExchangeMarketSymbolToCurrencies_V2(symbol, QuoteCurrencies, SymbolFormat); //get currency pair
            if(!string.IsNullOrEmpty(pair.Currency1) && !string.IsNullOrEmpty(pair.Currency2)) { //if valid strings
                tickers.Add(new KeyValuePair<string, ExchangeTicker>(symbol, this.ParseTicker(child, symbol, null, null, "close", "amount", "vol", 
                    baseCurrency2: pair.Currency2, //pass baseCurrency
                    quoteCurrency2:pair.Currency1  //pass quoteCurrency
                    )));
            }//if
        }//foreach
    
        return tickers;
    }
    

    image

    internal static ExchangeTicker ParseTicker(this ExchangeAPI api, JToken token, string marketSymbol,
        object askKey, object bidKey, object lastKey, object baseVolumeKey,
        object quoteVolumeKey = null, object timestampKey = null, TimestampType timestampType = TimestampType.None,
        object baseCurrencyKey = null, object quoteCurrencyKey = null, object idKey = null,
        string baseCurrency2 = "",
        string quoteCurrency2 = ""
        )
    {
        if (token == null || !token.HasValues)
        {
            return null;
        }
        decimal last = token[lastKey].ConvertInvariant<decimal>();
    
        // parse out volumes, handle cases where one or both do not exist
        token.ParseVolumes(baseVolumeKey, quoteVolumeKey, last, out decimal baseCurrencyVolume, out decimal quoteCurrencyVolume);
    
        // pull out timestamp
        DateTime timestamp = (timestampKey == null ? CryptoUtility.UtcNow : CryptoUtility.ParseTimestamp(token[timestampKey], timestampType));
    
        // split apart the symbol if we have a separator, otherwise just put the symbol for base and convert symbol
        string baseCurrency;
        string quoteCurrency;
        if(!string.IsNullOrEmpty(baseCurrency2) && !string.IsNullOrEmpty(baseCurrency2)) {
            baseCurrency = baseCurrency2;
            quoteCurrency = quoteCurrency2;
        }
        else {
            if(baseCurrencyKey != null && quoteCurrencyKey != null) {
                baseCurrency = token[baseCurrencyKey].ToStringInvariant();
                quoteCurrency = token[quoteCurrencyKey].ToStringInvariant();
            }
            else if(string.IsNullOrWhiteSpace(marketSymbol)) {
                throw new ArgumentNullException(nameof(marketSymbol));
            }
            else {
                (baseCurrency, quoteCurrency) = api.ExchangeMarketSymbolToCurrencies(marketSymbol);
            }
        }//else
    
        // create the ticker and return it
        //JToken askValue = token[askKey];
        //JToken bidValue = token[bidKey];
        JToken askValue = (askKey != null) ? token[askKey] : null;
        JToken bidValue = (bidKey != null) ? token[bidKey] : null;
        if (askValue is JArray)
        {
            askValue = askValue[0];
        }
        if (bidValue is JArray)
        {
            bidValue = bidValue[0];
        }
        ExchangeTicker ticker = new ExchangeTicker
        {
            MarketSymbol = marketSymbol,
            //Ask = askValue.ConvertInvariant<decimal>(),
            //Bid = bidValue.ConvertInvariant<decimal>(),
            Ask = (askValue != null) ? askValue.ConvertInvariant<decimal>() : 0,
            Bid = (bidValue != null) ? bidValue.ConvertInvariant<decimal>() : 0,
            Id = (idKey == null ? null : token[idKey].ToStringInvariant()),
            Last = last,
            Volume = new ExchangeVolume
            {
                BaseCurrencyVolume = baseCurrencyVolume,
                BaseCurrency = baseCurrency,
                QuoteCurrencyVolume = quoteCurrencyVolume,
                QuoteCurrency = quoteCurrency,
                Timestamp = timestamp
            }
        };
        return ticker;
    }
    

    Result... Unfortunately Ask and Bid are 0 as Huobi is not providing them
    image

  26. vslee commented on Sep 4, 2019

    @vslee
    Collaborator

    what is that app at the bottom which is showing the results?

  27. GonzoKK commented on Sep 5, 2019

    @GonzoKK
    Author

    Its a very rough user control I wrote to browse/view Exchange Sharp results. Basically a Tree and a Grid.

  28. GonzoKK commented on Sep 5, 2019

    @GonzoKK
    Author

    Here's a log of test results by exchange. Note that Huobi and ZB.com are using the fixes above.

    Kraken is helluva slow (3mins - almost unusable), as are Bitstamp (45sec) and Gemini (45 sec).
    TuxExchange's API is disabled.
    Cryptopia is very broken.

    24 Exchanges...

    Abucoins
    ✓ GetTickersAsync: 66 items [0,45s]
    ✗ GetCurrenciesAsync: ERROR Abucoins does not provide data about its currencies via the API [0,00s]
    ✓ GetMarketSymbolsAsync: 66 items [0,39s]
    ✓ GetMarketSymbolsMetadataAsync: 66 items [0,39s]
    🡆 QuoteCurrencies: "BTC", "EUR", "PLN", "USD"
    🡆 SampleMarkets: "BNB-BTC", "ICN-BTC", "LTC-BTC", "PPT-BTC", "VEN-BTC", "ZEC-BTC"

    Binance
    ✓ GetTickersAsync: 614 items [0,00s]
    ✓ GetCurrenciesAsync: 202 items [0,43s]
    ✓ GetMarketSymbolsAsync: 614 items [0,66s]
    ✓ GetMarketSymbolsMetadataAsync: 614 items [0,00s]
    🡆 QuoteCurrencies: "TUSD", "USDC", "USDS", "USDT", "BNB", "BTC", "ETH", "PAX", "TRX", "XRP"
    🡆 SampleMarkets: "BATBNB", "BTGETH", "CMTETH", "DATAETH", "EOSPAX", "EVXBTC"

    BitBank
    ✗ GetTickersAsync: ERROR Length cannot be less than zero.
    Parameter name: length [0,44s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,00s]
    ✓ GetMarketSymbolsAsync: 8 items [0,00s]
    ✗ GetMarketSymbolsMetadataAsync: ERROR The method or operation is not implemented. [0,00s]

    Bitfinex
    ✓ GetTickersAsync: 421 items [6,60s]
    ✗ GetCurrenciesAsync: ERROR Bitfinex does not provide data about its currencies via the API [0,00s]
    ✓ GetMarketSymbolsAsync: 421 items [0,00s]
    ✓ GetMarketSymbolsMetadataAsync: 421 items [0,00s]
    🡆 QuoteCurrencies: "F0:USTF0", "BTC", "DAI", "EOS", "ETH", "EUR", "GBP", "JPY", "USD", "UST", "XCH", "XLM"
    🡆 SampleMarkets: "dusk:usd", "mkreth", "poyusd", "rcnbtc", "veebtc", "wbtusd"

    Bithumb
    ✗ GetTickersAsync: ERROR Splitting Bithumb symbol 'BTC' with symbol separator '-' must result in exactly 2 pieces. [0,52s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,00s]
    ✓ GetMarketSymbolsAsync: 93 items [0,51s]
    ✗ GetMarketSymbolsMetadataAsync: ERROR The method or operation is not implemented. [0,00s]

    BitMEX
    ✗ GetTickersAsync: ERROR The method or operation is not implemented. [5,45s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,00s]
    ✓ GetMarketSymbolsAsync: 344 items [0,00s]
    ✓ GetMarketSymbolsMetadataAsync: 344 items [0,00s]
    🡆 QuoteCurrencies: "CNY", "ETH", "JPY", "KRW", "USD", "XBT", "XXX"
    🡆 SampleMarkets: ".BADAXBT30M", ".ETHBON8H", "A50H16", "BCHU18", "BCHU19", "BVOL7D"

    Bitstamp
    ✓ GetTickersAsync: 15 items [45,84s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,00s]
    ✓ GetMarketSymbolsAsync: 15 items [0,00s]
    ✓ GetMarketSymbolsMetadataAsync: 15 items [0,00s]
    🡆 QuoteCurrencies: "BTC", "EUR", "USD"
    🡆 SampleMarkets: "bchusd", "btcusd", "etheur", "ethusd", "xrpbtc", "xrpeur"

    Bittrex
    ✓ GetTickersAsync: 364 items [0,00s]
    ✓ GetCurrenciesAsync: 304 items [0,61s]
    ✓ GetMarketSymbolsAsync: 364 items [0,00s]
    ✓ GetMarketSymbolsMetadataAsync: 364 items [0,00s]
    🡆 QuoteCurrencies: "USDT", "BTC", "ETH", "USD"
    🡆 SampleMarkets: "BTC-HMQ", "BTC-MAID", "BTC-MER", "BTC-PMA", "BTC-TRX", "USDT-VDX"

    Coinbase
    ✓ GetTickersAsync: 51 items [2,09s]
    ✓ GetCurrenciesAsync: 27 items [0,27s]
    ✓ GetMarketSymbolsAsync: 51 items [0,00s]
    ✓ GetMarketSymbolsMetadataAsync: 51 items [0,00s]
    🡆 QuoteCurrencies: "USDC", "BTC", "DAI", "ETH", "EUR", "GBP", "USD"
    🡆 SampleMarkets: "BAT-ETH", "ETC-BTC", "GNT-USDC", "LINK-ETH", "LTC-GBP", "ZRX-EUR"

    Cryptopia
    ✗ GetTickersAsync: ERROR Unexpected character encountered while parsing value: <. Path '', line 0, position 0. [0,41s]
    ✗ GetCurrenciesAsync: ERROR Unexpected character encountered while parsing value: <. Path '', line 0, position 0. [0,35s]
    ✗ GetMarketSymbolsAsync: ERROR Unexpected character encountered while parsing value: <. Path '', line 0, position 0. [0,38s]
    ✗ GetMarketSymbolsMetadataAsync: ERROR Unexpected character encountered while parsing value: <. Path '', line 0, position 0. [0,31s]

    Gemini
    ✓ GetTickersAsync: 15 items [45,84s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,00s]
    ✓ GetMarketSymbolsAsync: 15 items [0,00s]
    ✓ GetMarketSymbolsMetadataAsync: 15 items [0,00s]
    🡆 QuoteCurrencies: "BCH", "BTC", "ETH", "LTC", "USD"
    🡆 SampleMarkets: "ethbtc", "ethusd", "ltcbch", "ltcusd", "zecbch", "zecusd"

    HitBTC
    ✓ GetTickersAsync: 892 items [0,00s]
    ✓ GetCurrenciesAsync: 564 items [2,22s]
    ✓ GetMarketSymbolsAsync: 892 items [1,14s]
    ✓ GetMarketSymbolsMetadataAsync: 892 items [0,00s]
    🡆 QuoteCurrencies: "USDT20", "EOSDT", "EURS", "GUSD", "KRWB", "TUSD", "USDC", "BCH", "BTC", "DAI", "EOS", "ETH", "PAX", "USD"
    🡆 SampleMarkets: "AEONBTC", "B2GBTC", "CHSBBTC", "MKRBTC", "OPTBTC", "POADAI"

    Huobi
    ✓ GetTickersAsync: 535 items [1,10s]
    ✓ GetCurrenciesAsync: 62 items [1,59s]
    ✓ GetMarketSymbolsAsync: 542 items [0,00s]
    ✓ GetMarketSymbolsMetadataAsync: 542 items [0,00s]
    🡆 QuoteCurrencies: "husd", "usdt", "btc", "eth", "trx", "ht"
    🡆 SampleMarkets: "bt1btc", "kcasheth", "manabtc", "payeth", "reqbtc", "wtceth"

    Kraken
    ✓ GetTickersAsync: 18 items [197,99s] <<------------------------------ 3 Minutes WTF ?
    ✓ GetCurrenciesAsync: 29 items [0,45s]
    ✓ GetMarketSymbolsAsync: 83 items [0,00s]
    ✓ GetMarketSymbolsMetadataAsync: 94 items [0,00s]
    🡆 QuoteCurrencies: "XETH", "XXBT", "ZCAD", "ZEUR", "ZGBP", "ZJPY", "ZUSD"
    🡆 SampleMarkets: "ADA/ETH", "ATOM/EUR", "BAT/EUR", "BCH/USD", "EOS/ETH", "ETHEUR.d"

    KuCoin
    ✓ GetTickersAsync: 462 items [2,39s]
    ✗ GetCurrenciesAsync: ERROR {"success":false,"code":"404000","msg":"Not Found","retry":false,"data":null} [0,42s]
    ✓ GetMarketSymbolsAsync: 462 items [2,79s]
    ✓ GetMarketSymbolsMetadataAsync: 462 items [0,83s]
    🡆 QuoteCurrencies: "NUSD", "TUSD", "USDC", "USDT", "BTC", "DAI", "ETH", "KCS", "NEO", "PAX"
    🡆 SampleMarkets: "EDN-BTC", "ELEC-BTC", "KAT-BTC", "OCN-BTC", "ODE-ETH", "UT-BTC"

    LBank
    ✓ GetTickersAsync: 143 items [3,45s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,00s]
    ✓ GetMarketSymbolsAsync: 143 items [2,43s]
    ✓ GetMarketSymbolsMetadataAsync: 143 items [2,45s]
    🡆 QuoteCurrencies: "AUSD", "USDT", "BTC", "ETH"
    🡆 SampleMarkets: "bfdt_eth", "cs_eth", "ltc_btc", "seos_btc", "sky_btc", "trx_eth"

    Livecoin
    ✓ GetTickersAsync: 1021 items [3,33s]
    ✓ GetCurrenciesAsync: 398 items [0,99s]
    ✓ GetMarketSymbolsAsync: 1021 items [1,00s]
    ✓ GetMarketSymbolsMetadataAsync: 1021 items [0,99s]
    🡆 QuoteCurrencies: "DASH", "DOGE", "EURN", "EURS", "TUSD", "USDC", "USDT", "XSCR", "BCH", "BTC", "EMC", "EOS", "ETH", "EUR", "LEO", "LKE", "LTC", "PAX", "RUR", "TER", "TRX", "USD"
    🡆 SampleMarkets: "DENT/BTC", "DGX/ETH", "MNTP/BTC", "RBM/USD", "RLT/BTC", "WNL/ETH"

    OKCoin
    ✓ GetTickersAsync: 33 items [1,09s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,00s]
    ✓ GetMarketSymbolsAsync: 33 items [0,39s]
    ✓ GetMarketSymbolsMetadataAsync: 33 items [0,00s]
    🡆 QuoteCurrencies: "EURS", "GUSD", "TUSD", "USDC", "USDT", "EUR", "PAX", "USD"
    🡆 SampleMarkets: "BTC-EUR", "BTC-TUSD", "ETH-EUR", "LTC-USD", "PAX-USD", "XLM-USD"

    OKEx
    ✓ GetTickersAsync: 449 items [1,75s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,00s]
    ✓ GetMarketSymbolsAsync: 449 items [13,58s]
    ✓ GetMarketSymbolsMetadataAsync: 449 items [0,00s]
    🡆 QuoteCurrencies: "USDK", "USDT", "BTC", "ETH", "OKB", "USD"
    🡆 SampleMarkets: "AAC-USDT", "GTO-BTC", "LSK-BTC", "NULS-USDT", "R-BTC", "SBTC-BTC"

    Poloniex
    ✓ GetTickersAsync: 101 items [0,38s]
    ✓ GetCurrenciesAsync: 308 items [0,68s]
    ✓ GetMarketSymbolsAsync: 101 items [0,00s]
    ✓ GetMarketSymbolsMetadataAsync: 101 items [0,64s]
    🡆 QuoteCurrencies: "USDC", "USDT", "BTC", "ETH"
    🡆 SampleMarkets: "BTC_LOOM", "BTC_LPT", "BTC_QTUM", "ETH_EOS", "USDC_BTC", "USDC_ETH"

    TuxExchange
    ✗ GetTickersAsync: ERROR {
    "success": "0",
    "error": "The API is currently disabled. Please try again later."
    } [0,98s]
    ✗ GetCurrenciesAsync: ERROR {
    "success": "0",
    "error": "The API is currently disabled. Please try again later."
    } [0,89s]
    ✗ GetMarketSymbolsAsync: ERROR {
    "success": "0",
    "error": "The API is currently disabled. Please try again later."
    } [0,93s]
    ✗ GetMarketSymbolsMetadataAsync: ERROR {
    "success": "0",
    "error": "The API is currently disabled. Please try again later."
    } [0,91s]

    UfoDex
    ✓ GetTickersAsync: 20 items [1,01s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,00s]
    ✗ GetMarketSymbolsAsync: ERROR The method or operation is not implemented. [0,00s]
    ✗ GetMarketSymbolsMetadataAsync: ERROR The method or operation is not implemented. [0,00s]

    Yobit
    SKIPPING FOR NOW - TAKES TOO LONG

    ZBcom
    ✓ GetTickersAsync: 187 items [2,74s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,00s]
    ✓ GetMarketSymbolsAsync: 185 items [0,00s]
    ✓ GetMarketSymbolsMetadataAsync: 185 items [0,92s]
    🡆 QuoteCurrencies: "usdt", "btc", "qc", "zb"
    🡆 SampleMarkets: "bat_btc", "eosdac_qc", "mana_usdt", "vsys_zb", "xrp_usdt", "zrx_qc"

  29. GonzoKK commented on Sep 6, 2019

    @GonzoKK
    Author

    Updated results... lotsa fixes, including Huobi, ZB.com and Bithumb.

    Bitstamp (45sec) and Gemini (45 sec) very sloooooooooow.
    TuxExchange's API is disabled.
    Cryptopia is broken.

    24 Exchanges...

    Abucoins
    ✓ GetTickersAsync: 66 items [0,486s]
    ✗ GetCurrenciesAsync: ERROR Abucoins does not provide data about its currencies via the API [0,002s]
    ✓ GetMarketSymbolsAsync: 66 items [0,205s]
    ✓ GetMarketSymbolsMetadataAsync: 66 items [0,375s]
    🡆 QuoteCurrencies: "BTC", "EUR", "PLN", "USD"
    🡆 SampleMarkets: "ETH-USD", "MTL-BTC", "PPT-BTC", "VERI-BTC", "XEM-BTC", "XRP-BTC"

    Binance
    ✓ GetTickersAsync: 617 items [0,000s]
    ✓ GetCurrenciesAsync: 202 items [0,345s]
    ✓ GetMarketSymbolsAsync: 617 items [0,423s]
    ✓ GetMarketSymbolsMetadataAsync: 617 items [0,001s]
    🡆 QuoteCurrencies: "TUSD", "USDC", "USDS", "USDT", "BNB", "BTC", "ETH", "PAX", "TRX", "XRP"
    🡆 SampleMarkets: "ALGOBNB", "BCHSVUSDT", "BCNETH", "ERDUSDT", "WINTRX", "ZENBNB"

    BitBank
    ✗ GetTickersAsync: ERROR Market symbol btc_jpy is missing the global symbol separator '-' [0,869s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,001s]
    ✓ GetMarketSymbolsAsync: 8 items [0,000s]
    ✗ GetMarketSymbolsMetadataAsync: ERROR The method or operation is not implemented. [0,001s]

    Bitfinex
    ✓ GetTickersAsync: 421 items [6,295s]
    ✗ GetCurrenciesAsync: ERROR Bitfinex does not provide data about its currencies via the API [0,000s]
    ✓ GetMarketSymbolsAsync: 421 items [0,001s]
    ✓ GetMarketSymbolsMetadataAsync: 421 items [0,000s]
    🡆 QuoteCurrencies: "F0:USTF0", "BTC", "DAI", "EOS", "ETH", "EUR", "GBP", "JPY", "USD", "UST", "XCH", "XLM"
    🡆 SampleMarkets: "atmeth", "rcnusd", "snteth", "ustusd", "xlmeur", "xmrusd"

    Bithumb
    ✓ GetTickersAsync: 93 items [1,837s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,000s]
    ✓ GetMarketSymbolsAsync: 93 items [0,480s]
    ✗ GetMarketSymbolsMetadataAsync: ERROR The method or operation is not implemented. [0,000s]

    BitMEX
    ✗ GetTickersAsync: ERROR The method or operation is not implemented. [3,107s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,001s]
    ✓ GetMarketSymbolsAsync: 344 items [0,000s]
    ✓ GetMarketSymbolsMetadataAsync: 344 items [0,000s]
    🡆 QuoteCurrencies: "CNY", "ETH", "JPY", "KRW", "USD", "XBT", "XXX"
    🡆 SampleMarkets: ".BVOL", ".XBTKRW", "LTCM18", "XBTM19", "XBTQ15", "XMRZ17"

    Bitstamp
    ✓ GetTickersAsync: 15 items [46,856s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,001s]
    ✓ GetMarketSymbolsAsync: 15 items [0,000s]
    ✓ GetMarketSymbolsMetadataAsync: 15 items [0,000s]
    🡆 QuoteCurrencies: "BTC", "EUR", "USD"
    🡆 SampleMarkets: "bchusd", "btcusd", "ethbtc", "ltceur", "xrpbtc", "xrpeur"

    Bittrex
    ✓ GetTickersAsync: 365 items [0,000s]
    ✓ GetCurrenciesAsync: 305 items [0,427s]
    ✓ GetMarketSymbolsAsync: 365 items [0,001s]
    ✓ GetMarketSymbolsMetadataAsync: 365 items [0,000s]
    🡆 QuoteCurrencies: "USDT", "BTC", "ETH", "USD"
    🡆 SampleMarkets: "BTC-ENG", "BTC-ETH", "BTC-SPIN", "BTC-TRX", "BTC-VIB", "ETH-BCH"

    Coinbase
    ✓ GetTickersAsync: 51 items [2,677s]
    ✓ GetCurrenciesAsync: 27 items [0,277s]
    ✓ GetMarketSymbolsAsync: 51 items [0,000s]
    ✓ GetMarketSymbolsMetadataAsync: 51 items [0,000s]
    🡆 QuoteCurrencies: "USDC", "BTC", "DAI", "ETH", "EUR", "GBP", "USD"
    🡆 SampleMarkets: "BAT-USDC", "DNT-USDC", "ETH-GBP", "GNT-USDC", "XTZ-BTC", "ZRX-BTC"

    Cryptopia
    ✗ GetTickersAsync: ERROR Unexpected character encountered while parsing value: <. Path '', line 0, position 0. [0,527s]
    ✗ GetCurrenciesAsync: ERROR Unexpected character encountered while parsing value: <. Path '', line 0, position 0. [0,321s]
    ✗ GetMarketSymbolsAsync: ERROR Unexpected character encountered while parsing value: <. Path '', line 0, position 0. [0,342s]
    ✗ GetMarketSymbolsMetadataAsync: ERROR Unexpected character encountered while parsing value: <. Path '', line 0, position 0. [0,057s]

    Gemini
    ✓ GetTickersAsync: 15 items [45,859s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,001s]
    ✓ GetMarketSymbolsAsync: 15 items [0,000s]
    ✓ GetMarketSymbolsMetadataAsync: 15 items [0,000s]
    🡆 QuoteCurrencies: "BCH", "BTC", "ETH", "LTC", "USD"
    🡆 SampleMarkets: "bchbtc", "btcusd", "ethusd", "zecbch", "zecbtc", "zeceth"

    HitBTC
    ✓ GetTickersAsync: 892 items [2,874s]
    ✓ GetCurrenciesAsync: 564 items [2,101s]
    ✓ GetMarketSymbolsAsync: 892 items [2,532s]
    ✓ GetMarketSymbolsMetadataAsync: 892 items [0,000s]
    🡆 QuoteCurrencies: "USDT20", "EOSDT", "EURS", "GUSD", "KRWB", "TUSD", "USDC", "BCH", "BTC", "DAI", "EOS", "ETH", "PAX", "USD"
    🡆 SampleMarkets: "CBCBTC", "GSTETH", "IGNISETH", "LOCBTC", "POABTC", "XUCETH"

    Huobi
    ✓ GetTickersAsync: 535 items [1,143s]
    ✓ GetCurrenciesAsync: 62 items [0,412s]
    ✓ GetMarketSymbolsAsync: 542 items [0,001s]
    ✓ GetMarketSymbolsMetadataAsync: 542 items [0,000s]
    🡆 QuoteCurrencies: "husd", "usdt", "btc", "eth", "trx", "ht"
    🡆 SampleMarkets: "bixeth", "gasbtc", "idtbtc", "nasbtc", "powreth", "xlmusdt"

    Kraken
    ✓ GetTickersAsync: 83 items [1,629s]
    ✓ GetCurrenciesAsync: 29 items [0,425s]
    ✓ GetMarketSymbolsAsync: 83 items [0,000s]
    ✓ GetMarketSymbolsMetadataAsync: 94 items [0,000s]
    🡆 QuoteCurrencies: "XETH", "XXBT", "ZCAD", "ZEUR", "ZGBP", "ZJPY", "ZUSD"
    🡆 SampleMarkets: "ADACAD", "BCHEUR", "LTCUSD", "WAVESETH", "XLMEUR", "ZECXBT"

    KuCoin
    ✓ GetTickersAsync: 462 items [1,584s]
    ✗ GetCurrenciesAsync: ERROR {"success":false,"code":"404000","msg":"Not Found","retry":false,"data":null} [1,159s]
    ✓ GetMarketSymbolsAsync: 462 items [1,931s]
    ✓ GetMarketSymbolsMetadataAsync: 462 items [1,193s]
    🡆 QuoteCurrencies: "NUSD", "TUSD", "USDC", "USDT", "BTC", "DAI", "ETH", "KCS", "NEO", "PAX"
    🡆 SampleMarkets: "BTC-USDC", "CS-ETH", "DBC-BTC", "HKN-ETH", "USDT-PAX", "VNX-BTC"

    LBank
    ✓ GetTickersAsync: 144 items [6,286s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,001s]
    ✓ GetMarketSymbolsAsync: 144 items [2,587s]
    ✓ GetMarketSymbolsMetadataAsync: 144 items [2,440s]
    🡆 QuoteCurrencies: "AUSD", "USDT", "BTC", "ETH"
    🡆 SampleMarkets: "atp_usdt", "bloc_usdt", "brc_usdt", "eos_btc", "etc_btc", "vet_eth"

    Livecoin
    ✓ GetTickersAsync: 1023 items [1,865s]
    ✓ GetCurrenciesAsync: 399 items [1,382s]
    ✓ GetMarketSymbolsAsync: 1023 items [0,996s]
    ✓ GetMarketSymbolsMetadataAsync: 1023 items [0,999s]
    🡆 QuoteCurrencies: "DASH", "DOGE", "EURN", "EURS", "TUSD", "USDC", "USDT", "XSCR", "BCH", "BTC", "EMC", "EOS", "ETH", "EUR", "LEO", "LKE", "LTC", "PAX", "RUR", "TER", "TRX", "USD"
    🡆 SampleMarkets: "CASH/BTC", "CLPC/ETH", "CRC/ETH", "HOT/ETH", "MCR/ETH", "UNRC/TRX"

    OKCoin
    ✓ GetTickersAsync: 33 items [0,758s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,000s]
    ✓ GetMarketSymbolsAsync: 33 items [0,368s]
    ✓ GetMarketSymbolsMetadataAsync: 33 items [0,000s]
    🡆 QuoteCurrencies: "EURS", "GUSD", "TUSD", "USDC", "USDT", "EUR", "PAX", "USD"
    🡆 SampleMarkets: "BTC-TUSD", "ETH-EUR", "GRIN-USD", "USDK-USD", "XRP-USD", "ZEC-USD"

    OKEx
    ✓ GetTickersAsync: 450 items [2,113s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,000s]
    ✓ GetMarketSymbolsAsync: 450 items [13,301s]
    ✓ GetMarketSymbolsMetadataAsync: 450 items [0,000s]
    🡆 QuoteCurrencies: "USDK", "USDT", "BTC", "ETH", "OKB", "USD"
    🡆 SampleMarkets: "BLOC-BTC", "DGB-USDT", "EGT-BTC", "FAIR-USDT", "INS-BTC", "KAN-BTC"

    Poloniex
    ✓ GetTickersAsync: 101 items [1,098s]
    ✓ GetCurrenciesAsync: 308 items [1,100s]
    ✓ GetMarketSymbolsAsync: 101 items [0,001s]
    ✓ GetMarketSymbolsMetadataAsync: 101 items [0,437s]
    🡆 QuoteCurrencies: "USDC", "USDT", "BTC", "ETH"
    🡆 SampleMarkets: "BTC_FCT", "BTC_OMNI", "BTC_POLY", "BTC_SC", "USDC_BCHSV", "USDT_ATOM"

    TuxExchange
    ✗ GetTickersAsync: ERROR {
    "success": "0",
    "error": "The API is currently disabled. Please try again later."
    } [0,927s]
    ✗ GetCurrenciesAsync: ERROR {
    "success": "0",
    "error": "The API is currently disabled. Please try again later."
    } [0,922s]
    ✗ GetMarketSymbolsAsync: ERROR {
    "success": "0",
    "error": "The API is currently disabled. Please try again later."
    } [0,886s]
    ✗ GetMarketSymbolsMetadataAsync: ERROR {
    "success": "0",
    "error": "The API is currently disabled. Please try again later."
    } [1,149s]

    UfoDex
    ✓ GetTickersAsync: 20 items [1,049s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,004s]
    ✗ GetMarketSymbolsAsync: ERROR The method or operation is not implemented. [0,000s]
    ✗ GetMarketSymbolsMetadataAsync: ERROR The method or operation is not implemented. [0,001s]

    Yobit
    SKIPPING FOR NOW - TAKES TOO LONG

    ZBcom
    ✓ GetTickersAsync: 187 items [2,403s]
    ✗ GetCurrenciesAsync: ERROR The method or operation is not implemented. [0,000s]
    ✓ GetMarketSymbolsAsync: 187 items [0,000s]
    ✓ GetMarketSymbolsMetadataAsync: 187 items [0,853s]
    🡆 QuoteCurrencies: "usdt", "btc", "qc", "zb"
    🡆 SampleMarkets: "eos_btc", "eos_usdt", "gram_btc", "slt_btc", "xmr_usdt", "zb_btc"

  30. jjxtra commented on Sep 6, 2019

    @jjxtra
    Collaborator

    Bitstamp and Gemini have no work-around, no ability to get tickers in one call, no web socket tickers. Have to get tickers one at a time. No speed improvements by making the requests in parallel...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions