/// <summary> /// Loop through all exchanges, get a json string for all symbols /// </summary> /// <returns></returns> private async Task <string> GetAllSymbolsJsonAsync() { Dictionary <string, string[]> allSymbols = new Dictionary <string, string[]>(); List <Task> tasks = new List <Task>(); foreach (ExchangeAPI api in ExchangeAPI.GetExchangeAPIs()) { tasks.Add(Task.Run(async() => { try { string[] symbols = (await api.GetMarketSymbolsAsync()).ToArray(); lock (allSymbols) { allSymbols[api.Name] = symbols; } } catch (NotImplementedException) { } catch (Exception ex) { Console.WriteLine("Failed to get symbols for {0}, error: {1}", api, ex); } })); } await Task.WhenAll(tasks); return(JsonConvert.SerializeObject(allSymbols)); }
public async Task GlobalSymbolTest() { // if tests fail, uncomment this and add replace Resources.AllSymbolsJson // string allSymbolsJson = GetAllSymbolsJson(); System.IO.File.WriteAllText("TestData/AllSymbols.json", allSymbolsJson); string globalMarketSymbol = "BTC-ETH"; string globalMarketSymbolAlt = "KRW-BTC"; // WTF Bitthumb... Dictionary <string, string[]> allSymbols = JsonConvert.DeserializeObject <Dictionary <string, string[]> >(System.IO.File.ReadAllText("TestData/AllSymbols.json")); // sanity test that all exchanges return the same global symbol when converted back and forth foreach (IExchangeAPI api in ExchangeAPI.GetExchangeAPIs()) { try { if (api is ExchangeUfoDexAPI || api is ExchangeOKExAPI || api is ExchangeHitBTCAPI || api is ExchangeKuCoinAPI || api is ExchangeOKCoinAPI || api is ExchangeDigifinexAPI) { // WIP continue; } bool isBithumb = (api.Name == ExchangeName.Bithumb); string exchangeMarketSymbol = await api.GlobalMarketSymbolToExchangeMarketSymbolAsync(isBithumb?globalMarketSymbolAlt : globalMarketSymbol); string globalMarketSymbol2 = await api.ExchangeMarketSymbolToGlobalMarketSymbolAsync(exchangeMarketSymbol); if ((!isBithumb && globalMarketSymbol2.EndsWith("-BTC")) || globalMarketSymbol2.EndsWith("-USD") || globalMarketSymbol2.EndsWith("-USDT")) { Assert.Fail($"Exchange {api.Name} has wrong SymbolIsReversed parameter"); } try { if (!allSymbols.ContainsKey(api.Name)) { throw new InvalidOperationException("If new exchange has no symbols, run GetAllSymbolsJson to make a new string " + "then apply this new string to Resources.AllSymbolsJson"); } string[] symbols = allSymbols[api.Name]; Assert.IsTrue(symbols.Contains(exchangeMarketSymbol), "Symbols does not contain exchange symbol"); } catch { Assert.Fail("Error getting symbols"); } Assert.IsTrue(globalMarketSymbol == globalMarketSymbol2 || globalMarketSymbolAlt == globalMarketSymbol2); } catch (NotImplementedException) { } catch (Exception ex) { Assert.Fail($"Exchange {api.Name} error converting symbol: {ex}"); } } }
protected override void OnShown(EventArgs e) { base.OnShown(e); foreach (var exchange in ExchangeAPI.GetExchangeAPIs()) { cmbExchange.Items.Add(exchange.Name); } cmbExchange.SelectedIndex = 0; }
/// <summary> /// Loop through all exchanges, get a json string for all symbols /// </summary> /// <returns></returns> private string GetAllSymbolsJson() { Dictionary <string, string[]> allSymbols = new Dictionary <string, string[]>(); foreach (IExchangeAPI api in ExchangeAPI.GetExchangeAPIs()) { allSymbols[api.Name] = api.GetSymbolsAsync().Sync().ToArray(); } return(JsonConvert.SerializeObject(allSymbols)); }
public void GlobalSymbolTest() { string globalSymbol = "BTC-ETH"; string globalSymbolAlt = "KRW-BTC"; // WTF Bitthumb... Dictionary <string, string[]> allSymbols = JsonConvert.DeserializeObject <Dictionary <string, string[]> >(Resources.AllSymbolsJson); // sanity test that all exchanges return the same global symbol when converted back and forth foreach (IExchangeAPI api in ExchangeAPI.GetExchangeAPIs()) { try { bool isBithumb = (api.Name == ExchangeName.Bithumb); string exchangeSymbol = api.GlobalSymbolToExchangeSymbol(isBithumb ? globalSymbolAlt : globalSymbol); string globalSymbol2 = api.ExchangeSymbolToGlobalSymbol(exchangeSymbol); if ((!isBithumb && globalSymbol2.EndsWith("-BTC")) || globalSymbol2.EndsWith("-USD") || globalSymbol2.EndsWith("-USDT")) { Assert.Fail($"Exchange {api.Name} has wrong SymbolIsReversed parameter"); } try { if (!allSymbols.ContainsKey(api.Name)) { throw new InvalidOperationException("If new exchange has no symbols, run GetAllSymbolsJson to make a new string " + "then apply this new string to Resources.AllSymbolsJson"); } string[] symbols = allSymbols[api.Name]; Assert.IsTrue(symbols.Contains(exchangeSymbol), "Symbols does not contain exchange symbol"); } catch { Assert.Fail("Error getting symbols"); } Assert.IsTrue(globalSymbol == globalSymbol2 || globalSymbolAlt == globalSymbol2); } catch (NotImplementedException) { } catch (Exception ex) { Assert.Fail($"Exchange {api.Name} error converting symbol: {ex}"); } } }
/// <summary> /// Loop through all exchanges, get a json string for all symbols /// </summary> /// <returns></returns> private async Task <string> GetAllSymbolsJsonAsync() { Dictionary <string, string[]> allSymbols = new Dictionary <string, string[]>(); List <Task> tasks = new List <Task>(); foreach (ExchangeAPI api in ExchangeAPI.GetExchangeAPIs()) { tasks.Add(Task.Run(async() => { string[] symbols = (await api.GetMarketSymbolsAsync()).ToArray(); lock (allSymbols) { allSymbols[api.Name] = symbols; } })); } await Task.WhenAll(tasks); return(JsonConvert.SerializeObject(allSymbols)); }
/// <summary> /// Loop through all exchanges, get a json string for all symbols /// </summary> /// <returns></returns> private string GetAllSymbolsJson() { Dictionary <string, string[]> allSymbols = new Dictionary <string, string[]>(); Parallel.ForEach(ExchangeAPI.GetExchangeAPIs(), (api) => { try { lock (allSymbols) { allSymbols[api.Name] = api.GetMarketSymbolsAsync().Sync().ToArray(); } } catch (Exception ex) { Logger.Error(ex); } }); return(JsonConvert.SerializeObject(allSymbols)); }
public void GlobalSymbolTest() { string symbol = "BTC-ETH"; string altSymbol = "BTC-KRW"; // WTF Bitthumb... // sanity test that all exchanges return the same global symbol when converted back and forth foreach (IExchangeAPI api in ExchangeAPI.GetExchangeAPIs()) { try { string exchangeSymbol = api.GlobalSymbolToExchangeSymbol(symbol); string globalSymbol = api.ExchangeSymbolToGlobalSymbol(exchangeSymbol); Assert.IsTrue(symbol == globalSymbol || altSymbol == globalSymbol); } catch (Exception ex) { Assert.Fail($"Exchange {api.Name} error converting symbol: {ex}"); } } }
public override async Task RunCommand() { var apis = ExchangeAPI.GetExchangeAPIs(); foreach (var api in apis) { // WIP exchanges... if (api is ExchangeUfoDexAPI) { continue; } if (ExchangeName != null && !Regex.IsMatch(api.Name, ExchangeName, RegexOptions.IgnoreCase)) { continue; } // test all public API for each exchange try { var marketSymbol = api.NormalizeMarketSymbol(GetSymbol(api)); await TestMarketSymbols(api, marketSymbol); await TestCurrencies(api); await TestOrderBook(api, marketSymbol); await TestTicker(api, marketSymbol); await TestTrade(api, marketSymbol); await TestCandle(api, marketSymbol); } catch (Exception ex) { Console.WriteLine("Request failed, api: {0}, error: {1}", api.Name, ex.Message); } } }
public static IExchangeAPI[] GetAvailableExchanges() { return(ExchangeAPI.GetExchangeAPIs()); }
private static void TestExchanges(string nameRegex = null, string functionRegex = null) { string GetSymbol(IExchangeAPI api) { if (api is ExchangeCryptopiaAPI || api is ExchangeLivecoinAPI || api is ExchangeZBcomAPI) { return("LTC-BTC"); } else if (api is ExchangeKrakenAPI) { return("XXBTZ-USD"); } else if (api is ExchangeBittrexAPI || api is ExchangePoloniexAPI) { return("BTC-LTC"); } else if (api is ExchangeBinanceAPI || api is ExchangeOkexAPI || api is ExchangeBleutradeAPI || api is ExchangeKucoinAPI || api is ExchangeHuobiAPI || api is ExchangeAbucoinsAPI) { return("ETH-BTC"); } else if (api is ExchangeYobitAPI) { return("LTC-BTC"); } else if (api is ExchangeTuxExchangeAPI) { return("BTC-ETH"); } else if (api is ExchangeBitMEXAPI) { return("XBT-USD"); } return("BTC-USD"); } ExchangeTrade[] trades = null; bool histTradeCallback(IEnumerable <ExchangeTrade> tradeEnum) { trades = tradeEnum.ToArray(); return(true); } IExchangeAPI[] apis = ExchangeAPI.GetExchangeAPIs(); foreach (IExchangeAPI api in apis) { if (nameRegex != null && !Regex.IsMatch(api.Name, nameRegex, RegexOptions.IgnoreCase)) { continue; } // test all public API for each exchange try { string symbol = api.NormalizeSymbol(GetSymbol(api)); if (functionRegex == null || Regex.IsMatch("symbol", functionRegex, RegexOptions.IgnoreCase)) { Console.Write("Test {0} GetSymbolsAsync... ", api.Name); IReadOnlyCollection <string> symbols = api.GetSymbolsAsync().Sync().ToArray(); Assert(symbols != null && symbols.Count != 0 && symbols.Contains(symbol, StringComparer.OrdinalIgnoreCase)); Console.WriteLine($"OK (default: {symbol}; {symbols.Count} symbols)"); } if (functionRegex == null || Regex.IsMatch("orderbook", functionRegex, RegexOptions.IgnoreCase)) { try { Console.Write("Test {0} GetOrderBookAsync... ", api.Name); var book = api.GetOrderBookAsync(symbol).Sync(); Assert(book.Asks.Count != 0 && book.Bids.Count != 0 && book.Asks.First().Value.Amount > 0m && book.Asks.First().Value.Price > 0m && book.Bids.First().Value.Amount > 0m && book.Bids.First().Value.Price > 0m); Console.WriteLine($"OK ({book.Asks.Count} asks, {book.Bids.Count} bids)"); } catch (NotImplementedException) { Console.WriteLine($"Not implemented"); } } if (functionRegex == null || Regex.IsMatch("ticker", functionRegex, RegexOptions.IgnoreCase)) { try { Console.Write("Test {0} GetTickerAsync... ", api.Name); var ticker = api.GetTickerAsync(symbol).Sync(); Assert(ticker != null && ticker.Ask > 0m && ticker.Bid > 0m && ticker.Last > 0m && ticker.Volume != null && ticker.Volume.BaseVolume > 0m && ticker.Volume.ConvertedVolume > 0m); Console.WriteLine($"OK (ask: {ticker.Ask}, bid: {ticker.Bid}, last: {ticker.Last})"); } catch { Console.WriteLine($"Data invalid or empty"); } } if (functionRegex == null || Regex.IsMatch("trade", functionRegex, RegexOptions.IgnoreCase)) { try { Console.Write("Test {0} GetHistoricalTradesAsync... ", api.Name); api.GetHistoricalTradesAsync(histTradeCallback, symbol).Sync(); Assert(trades.Length != 0 && trades[0].Price > 0m && trades[0].Amount > 0m); Console.WriteLine($"OK ({trades.Length})"); Console.Write("Test {0} GetRecentTradesAsync... ", api.Name); trades = api.GetRecentTradesAsync(symbol).Sync().ToArray(); Assert(trades.Length != 0 && trades[0].Price > 0m && trades[0].Amount > 0m); Console.WriteLine($"OK ({trades.Length} trades)"); } catch (NotImplementedException) { Console.WriteLine($"Not implemented"); } } if (functionRegex == null || Regex.IsMatch("candle", functionRegex, RegexOptions.IgnoreCase)) { try { Console.Write("Test {0} GetCandlesAsync... ", api.Name); var candles = api.GetCandlesAsync(symbol, 86400, CryptoUtility.UtcNow.Subtract(TimeSpan.FromDays(7.0)), null).Sync().ToArray(); Assert(candles.Length != 0 && candles[0].ClosePrice > 0m && candles[0].HighPrice > 0m && candles[0].LowPrice > 0m && candles[0].OpenPrice > 0m && candles[0].HighPrice >= candles[0].LowPrice && candles[0].HighPrice >= candles[0].ClosePrice && candles[0].HighPrice >= candles[0].OpenPrice && !string.IsNullOrWhiteSpace(candles[0].Name) && candles[0].ExchangeName == api.Name && candles[0].PeriodSeconds == 86400 && candles[0].BaseVolume > 0.0 && candles[0].ConvertedVolume > 0.0 && candles[0].WeightedAverage >= 0m); Console.WriteLine($"OK ({candles.Length})"); } catch (NotImplementedException) { Console.WriteLine($"Not implemented"); } catch { // These API require private access to get candles end points if (!(api is ExchangeKucoinAPI)) { throw; } } } } catch (Exception ex) { Console.WriteLine("Request failed, api: {0}, error: {1}", api, ex.Message); } } }
public async Task GlobalSymbolTest() { // if tests fail, uncomment this and it will save a new test file // string allSymbolsJson = GetAllSymbolsJsonAsync().Sync(); System.IO.File.WriteAllText("TestData/AllSymbols.json", allSymbolsJson); string globalMarketSymbol = "ETH-BTC"; //1 ETH is worth 0.0192 BTC... string globalMarketSymbolAlt = "BTC-KRW"; // WTF Bitthumb... //1 BTC worth 9,783,000 won Dictionary <string, string[]> allSymbols = JsonConvert.DeserializeObject <Dictionary <string, string[]> >(System.IO.File.ReadAllText("TestData/AllSymbols.json")); // sanity test that all exchanges return the same global symbol when converted back and forth foreach (IExchangeAPI api in ExchangeAPI.GetExchangeAPIs()) { try { if (api is ExchangeUfoDexAPI || api is ExchangeOKExAPI || api is ExchangeHitBTCAPI || api is ExchangeKuCoinAPI || api is ExchangeOKCoinAPI || api is ExchangeDigifinexAPI || api is ExchangeNDAXAPI || api is ExchangeBL3PAPI || api is ExchangeBinanceUSAPI || api is ExchangeBinanceJerseyAPI || api is ExchangeBinanceDEXAPI || api is ExchangeBitMEXAPI || api is ExchangeBTSEAPI || api is ExchangeBybitAPI) { // WIP continue; } bool isBithumb = (api.Name == ExchangeName.Bithumb); string exchangeMarketSymbol = await api.GlobalMarketSymbolToExchangeMarketSymbolAsync(isBithumb?globalMarketSymbolAlt : globalMarketSymbol); string globalMarketSymbol2 = await api.ExchangeMarketSymbolToGlobalMarketSymbolAsync(exchangeMarketSymbol); if ((!isBithumb && globalMarketSymbol2.StartsWith("BTC-")) || globalMarketSymbol2.StartsWith("USD-") || globalMarketSymbol2.StartsWith("USDT-")) { Assert.Fail($"Exchange {api.Name} has wrong SymbolIsReversed parameter"); } try { if (!allSymbols.ContainsKey(api.Name)) { throw new InvalidOperationException("If new exchange has no symbols, run GetAllSymbolsJson to make a new string " + "then apply this new string to Resources.AllSymbolsJson"); } string[] symbols = allSymbols[api.Name]; // BL3P does not have usd if (api.Name != ExchangeName.BL3P) { Assert.IsTrue(symbols.Contains(exchangeMarketSymbol), "Symbols does not contain exchange symbol"); } } catch { Assert.Fail("Error getting symbols"); } Assert.IsTrue(globalMarketSymbol == globalMarketSymbol2 || globalMarketSymbolAlt == globalMarketSymbol2); } catch (NotImplementedException) { } catch (Exception ex) { Assert.Fail($"Exchange {api.Name} error converting symbol: {ex}"); } } }