From 7be56f1f8c7d54e33a348ef1d9b7d93259f23659 Mon Sep 17 00:00:00 2001 From: Adrian Gallagher Date: Mon, 26 Feb 2018 16:44:08 +1100 Subject: [PATCH] Improve helpers and add tests --- helpers.go | 78 ++++++---- helpers_test.go | 379 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 428 insertions(+), 29 deletions(-) create mode 100644 helpers_test.go diff --git a/helpers.go b/helpers.go index 8c982f3b..c0a48e01 100644 --- a/helpers.go +++ b/helpers.go @@ -29,7 +29,7 @@ func GetAllAvailablePairs(enabledExchangesOnly bool) []pair.CurrencyPair { } for y := range pairs { - if pair.Contains(pairList, pairs[y]) { + if pair.Contains(pairList, pairs[y], false) { continue } pairList = append(pairList, pairs[y]) @@ -46,8 +46,8 @@ func GetSpecificAvailablePairs(enabledExchangesOnly, fiatPairs, includeUSDT, cry for x := range supportedPairs { if fiatPairs { - if currency.IsCryptoFiatPair(supportedPairs[x]) || currency.IsFiatPair(supportedPairs[x]) || (includeUSDT && pair.ContainsCurrency(supportedPairs[x], "USDT")) { - if pair.Contains(pairList, supportedPairs[x]) { + if currency.IsCryptoFiatPair(supportedPairs[x]) && !pair.ContainsCurrency(supportedPairs[x], "USDT") || (includeUSDT && pair.ContainsCurrency(supportedPairs[x], "USDT") && currency.IsCryptoPair(supportedPairs[x])) { + if pair.Contains(pairList, supportedPairs[x], false) { continue } pairList = append(pairList, supportedPairs[x]) @@ -55,7 +55,7 @@ func GetSpecificAvailablePairs(enabledExchangesOnly, fiatPairs, includeUSDT, cry } if cryptoPairs { if currency.IsCryptoPair(supportedPairs[x]) { - if pair.Contains(pairList, supportedPairs[x]) { + if pair.Contains(pairList, supportedPairs[x], false) { continue } pairList = append(pairList, supportedPairs[x]) @@ -66,18 +66,20 @@ func GetSpecificAvailablePairs(enabledExchangesOnly, fiatPairs, includeUSDT, cry } // IsRelatablePairs checks to see if the two pairs are relatable -func IsRelatablePairs(p1, p2 pair.CurrencyPair) bool { - if currency.IsCryptoPair(p1) && currency.IsCryptoPair(p2) { - relatablePairs := GetRelatableCurrencies(p1, false) - return pair.Contains(relatablePairs, p2) +func IsRelatablePairs(p1, p2 pair.CurrencyPair, includeUSDT bool) bool { + if p1.Equal(p2, false) { + return true } - if currency.IsCryptoFiatPair(p1) && currency.IsCryptoFiatPair(p2) { - relatablePairs := GetRelatableFiatCurrencies(p1) - relatablePairs = append(relatablePairs, GetRelatableCurrencies(p1, false)...) - return pair.Contains(relatablePairs, p2) + var relatablePairs []pair.CurrencyPair + relatablePairs = GetRelatableCurrencies(p1, true, includeUSDT) + + if currency.IsCryptoFiatPair(p1) { + for x := range relatablePairs { + relatablePairs = append(relatablePairs, GetRelatableFiatCurrencies(relatablePairs[x])...) + } } - return false + return pair.Contains(relatablePairs, p2, false) } // MapCurrenciesByExchange returns a list of currency pairs mapped to an @@ -101,7 +103,7 @@ func MapCurrenciesByExchange(p []pair.CurrencyPair, enabledExchangesOnly bool) m pairs = append(pairs, p[x]) currencyExchange[exchName] = pairs } else { - if pair.Contains(result, p[x]) { + if pair.Contains(result, p[x], false) { continue } result = append(result, p[x]) @@ -143,7 +145,7 @@ func GetRelatableCryptocurrencies(p pair.CurrencyPair) []pair.CurrencyPair { for x := range cryptocurrencies { newPair := pair.NewCurrencyPair(p.FirstCurrency.String(), cryptocurrencies[x]) - if pair.Contains(pairs, newPair) { + if pair.Contains(pairs, newPair, false) { continue } pairs = append(pairs, newPair) @@ -160,7 +162,7 @@ func GetRelatableFiatCurrencies(p pair.CurrencyPair) []pair.CurrencyPair { for x := range fiatCurrencies { newPair := pair.NewCurrencyPair(p.FirstCurrency.String(), fiatCurrencies[x]) - if pair.Contains(pairs, newPair) { + if pair.Contains(pairs, newPair, false) { continue } pairs = append(pairs, newPair) @@ -171,29 +173,47 @@ func GetRelatableFiatCurrencies(p pair.CurrencyPair) []pair.CurrencyPair { // GetRelatableCurrencies returns a list of currency pairs if it can find // any relatable currencies (e.g BTCUSD -> BTC USDT -> XBT USDT -> XBT USD) // incOrig includes the supplied pair if desired -func GetRelatableCurrencies(p pair.CurrencyPair, incOrig bool) []pair.CurrencyPair { +func GetRelatableCurrencies(p pair.CurrencyPair, incOrig, incUSDT bool) []pair.CurrencyPair { var pairs []pair.CurrencyPair - if incOrig { + + addPair := func(p pair.CurrencyPair) { + if pair.Contains(pairs, p, true) { + return + } pairs = append(pairs, p) } - first, err := translation.GetTranslation(p.FirstCurrency) - if err == nil { - pairs = append(pairs, pair.NewCurrencyPair(first.String(), - p.SecondCurrency.String())) + buildPairs := func(p pair.CurrencyPair, incOrig bool) { + if incOrig { + addPair(p) + } + + first, err := translation.GetTranslation(p.FirstCurrency) + if err == nil { + addPair(pair.NewCurrencyPair(first.String(), + p.SecondCurrency.String())) + + second, err := translation.GetTranslation(p.SecondCurrency) + if err == nil { + addPair(pair.NewCurrencyPair(first.String(), + second.String())) + } + } second, err := translation.GetTranslation(p.SecondCurrency) if err == nil { - pairs = append(pairs, pair.NewCurrencyPair(first.String(), + addPair(pair.NewCurrencyPair(p.FirstCurrency.String(), second.String())) } } - second, err := translation.GetTranslation(p.SecondCurrency) - if err == nil { - pairs = append(pairs, pair.NewCurrencyPair(p.FirstCurrency.String(), - second.String())) + buildPairs(p, incOrig) + buildPairs(p.Swap(), incOrig) + + if !incUSDT { + pairs = pair.RemovePairsByFilter(pairs, "USDT") } + return pairs } @@ -274,7 +294,7 @@ func GetAccountCurrencyInfoByExchangeName(accounts []exchange.AccountInfo, excha // price for a given currency pair and asset type func GetExchangeHighestPriceByCurrencyPair(p pair.CurrencyPair, assetType string) (string, error) { result := stats.SortExchangesByPrice(p, assetType, true) - if len(result) != 1 { + if len(result) == 0 { return "", fmt.Errorf("no stats for supplied currency pair and asset type") } @@ -285,7 +305,7 @@ func GetExchangeHighestPriceByCurrencyPair(p pair.CurrencyPair, assetType string // price for a given currency pair and asset type func GetExchangeLowestPriceByCurrencyPair(p pair.CurrencyPair, assetType string) (string, error) { result := stats.SortExchangesByPrice(p, assetType, false) - if len(result) != 1 { + if len(result) == 0 { return "", fmt.Errorf("no stats for supplied currency pair and asset type") } diff --git a/helpers_test.go b/helpers_test.go new file mode 100644 index 00000000..d331ecef --- /dev/null +++ b/helpers_test.go @@ -0,0 +1,379 @@ +package main + +import ( + "log" + "testing" + + "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" + "github.com/thrasher-/gocryptotrader/currency" + "github.com/thrasher-/gocryptotrader/currency/pair" + exchange "github.com/thrasher-/gocryptotrader/exchanges" + "github.com/thrasher-/gocryptotrader/exchanges/orderbook" + "github.com/thrasher-/gocryptotrader/exchanges/stats" + "github.com/thrasher-/gocryptotrader/exchanges/ticker" +) + +const ( + TestConfig = "./testdata/configtest.json" +) + +var helperTestLoaded = false + +func SetupTestHelpers(t *testing.T) { + if !helperTestLoaded { + if !testSetup { + bot.config = &config.Cfg + err := bot.config.LoadConfig("./testdata/configtest.json") + if err != nil { + t.Fatalf("Test failed. SetupTest: Failed to load config: %s", err) + } + testSetup = true + } + + err := bot.config.RetrieveConfigCurrencyPairs(false) + if err != nil { + t.Fatalf("Failed to retrieve config currency pairs. %s", err) + } + helperTestLoaded = true + } +} + +func TestGetSpecificAvailablePairs(t *testing.T) { + SetupTestHelpers(t) + result := GetSpecificAvailablePairs(true, true, true, false) + + log.Println(result) + if !pair.Contains(result, pair.NewCurrencyPair("BTC", "USD"), true) { + t.Fatal("Unexpected result") + } + + if !pair.Contains(result, pair.NewCurrencyPair("BTC", "USDT"), false) { + t.Fatal("Unexpected result") + } + + result = GetSpecificAvailablePairs(true, true, false, false) + + if pair.Contains(result, pair.NewCurrencyPair("BTC", "USDT"), false) { + t.Fatal("Unexpected result") + } + + result = GetSpecificAvailablePairs(true, false, false, true) + if !pair.Contains(result, pair.NewCurrencyPair("LTC", "BTC"), false) { + t.Fatal("Unexpected result") + } +} + +func TestIsRelatablePairs(t *testing.T) { + SetupTestHelpers(t) + + // Test relational pairs with similar names + result := IsRelatablePairs(pair.NewCurrencyPair("XBT", "USD"), pair.NewCurrencyPair("BTC", "USD"), false) + if !result { + t.Fatal("Unexpected result") + } + + // Test relational pairs with similar names reversed + result = IsRelatablePairs(pair.NewCurrencyPair("BTC", "USD"), pair.NewCurrencyPair("XBT", "USD"), false) + if !result { + t.Fatal("Unexpected result") + } + + // Test relational pairs with similar names but with Tether support disabled + result = IsRelatablePairs(pair.NewCurrencyPair("XBT", "USD"), pair.NewCurrencyPair("BTC", "USDT"), false) + if result { + t.Fatal("Unexpected result") + } + + // Test relational pairs with similar names but with Tether support enabled + result = IsRelatablePairs(pair.NewCurrencyPair("XBT", "USDT"), pair.NewCurrencyPair("BTC", "USD"), true) + if !result { + t.Fatal("Unexpected result") + } + + // Test relational pairs with different ordering, a delimiter and with Tether support enabled + result = IsRelatablePairs(pair.NewCurrencyPair("AE", "USDT"), pair.NewCurrencyPairDelimiter("USDT-AE", "-"), true) + if !result { + t.Fatal("Unexpected result") + } + + // Test relational pairs with different ordering, a delimiter and with Tether support disabled + result = IsRelatablePairs(pair.NewCurrencyPair("AE", "USDT"), pair.NewCurrencyPairDelimiter("USDT-AE", "-"), false) + if !result { + t.Fatal("Unexpected result") + } + + // Test relationl pairs with similar names and different fiat currencies + result = IsRelatablePairs(pair.NewCurrencyPair("XBT", "EUR"), pair.NewCurrencyPair("BTC", "AUD"), false) + if !result { + t.Fatal("Unexpected result") + } + + // Test relationl pairs with similar names, different fiat currencies and with different ordering + result = IsRelatablePairs(pair.NewCurrencyPair("USD", "BTC"), pair.NewCurrencyPair("BTC", "EUR"), false) + if !result { + t.Fatal("Unexpected result") + } + + // Test relationl pairs with similar names, different fiat currencies and with Tether enabled + result = IsRelatablePairs(pair.NewCurrencyPair("USD", "BTC"), pair.NewCurrencyPair("BTC", "USDT"), true) + if !result { + t.Fatal("Unexpected result") + } + + // Test relationl crypto pairs with similar names + result = IsRelatablePairs(pair.NewCurrencyPair("LTC", "BTC"), pair.NewCurrencyPair("BTC", "LTC"), false) + if !result { + t.Fatal("Unexpected result") + } + + // Test relationl crypto pairs with similar different pairs + result = IsRelatablePairs(pair.NewCurrencyPair("LTC", "ETH"), pair.NewCurrencyPair("BTC", "ETH"), false) + if result { + t.Fatal("Unexpected result") + } + + // Test relationl crypto pairs with similar different pairs and with USDT enabled + result = IsRelatablePairs(pair.NewCurrencyPair("USDT", "USD"), pair.NewCurrencyPair("BTC", "USD"), true) + if result { + t.Fatal("Unexpected result") + } + + // Test relationl crypto pairs with with similar names + result = IsRelatablePairs(pair.NewCurrencyPair("XBT", "LTC"), pair.NewCurrencyPair("BTC", "LTC"), false) + if !result { + t.Fatal("Unexpected result") + } + + // Test relationl crypto pairs with diffrent ordering and similar names + result = IsRelatablePairs(pair.NewCurrencyPair("LTC", "XBT"), pair.NewCurrencyPair("BTC", "LTC"), false) + if !result { + t.Fatal("Unexpected result") + } +} + +func TestGetRelatableCryptocurrencies(t *testing.T) { + SetupTestHelpers(t) + p := GetRelatableCryptocurrencies(pair.NewCurrencyPair("BTC", "LTC")) + if !pair.Contains(p, pair.NewCurrencyPair("BTC", "ETH"), true) { + t.Fatal("Unexpected result") + } + + backup := currency.CryptoCurrencies + currency.CryptoCurrencies = append(currency.CryptoCurrencies, "BTC") + + p = GetRelatableCryptocurrencies(pair.NewCurrencyPair("BTC", "LTC")) + if !pair.Contains(p, pair.NewCurrencyPair("BTC", "ETH"), true) { + t.Fatal("Unexpected result") + } + + currency.CryptoCurrencies = backup +} + +func TestGetRelatableFiatCurrencies(t *testing.T) { + SetupTestHelpers(t) + p := GetRelatableFiatCurrencies(pair.NewCurrencyPair("BTC", "USD")) + if !pair.Contains(p, pair.NewCurrencyPair("BTC", "EUR"), true) { + t.Fatal("Unexpected result") + } + + backup := currency.BaseCurrencies + currency.BaseCurrencies = append(currency.BaseCurrencies, "USD") + + p = GetRelatableFiatCurrencies(pair.NewCurrencyPair("BTC", "USD")) + if !pair.Contains(p, pair.NewCurrencyPair("BTC", "ZAR"), true) { + t.Fatal("Unexpected result") + } + + currency.BaseCurrencies = backup +} + +func TestMapCurrenciesByExchange(t *testing.T) { + SetupTestHelpers(t) + + var pairs []pair.CurrencyPair + pairs = append(pairs, pair.NewCurrencyPair("BTC", "USD")) + pairs = append(pairs, pair.NewCurrencyPair("BTC", "EUR")) + + result := MapCurrenciesByExchange(pairs, true) + pairs, ok := result["Bitstamp"] + if !ok { + t.Fatal("Unexpected result") + } + + log.Println(pairs) + if len(pairs) != 2 { + t.Fatal("Unexpected result") + } +} + +func TestGetExchangeNamesByCurrency(t *testing.T) { + SetupTestHelpers(t) + + result := GetExchangeNamesByCurrency(pair.NewCurrencyPair("BTC", "USD"), true) + if !common.StringDataCompare(result, "Bitstamp") { + t.Fatal("Unexpected result") + } + + result = GetExchangeNamesByCurrency(pair.NewCurrencyPair("BTC", "JPY"), true) + if !common.StringDataCompare(result, "Bitflyer") { + t.Fatal("Unexpected result") + } + + result = GetExchangeNamesByCurrency(pair.NewCurrencyPair("blah", "JPY"), true) + if len(result) > 0 { + t.Fatal("Unexpected result") + } +} + +func TestGetSpecificOrderbook(t *testing.T) { + SetupTestHelpers(t) + + LoadExchange("Bitstamp") + p := pair.NewCurrencyPair("BTC", "USD") + bids := []orderbook.Item{} + bids = append(bids, orderbook.Item{Price: 1000, Amount: 1}) + + orderbook.ProcessOrderbook("Bitstamp", p, orderbook.Base{Pair: p, Bids: bids}, ticker.Spot) + ob, err := GetSpecificOrderbook("BTCUSD", "Bitstamp", ticker.Spot) + if err != nil { + t.Fatal(err) + } + + if ob.Bids[0].Price != 1000 { + t.Fatal("Unexpected result") + } + + ob, err = GetSpecificOrderbook("ETHLTC", "Bitstamp", ticker.Spot) + if err == nil { + t.Fatal("Unexpected result") + } + + UnloadExchange("Bitstamp") +} + +func TestGetSpecificTicker(t *testing.T) { + SetupTestHelpers(t) + + LoadExchange("Bitstamp") + p := pair.NewCurrencyPair("BTC", "USD") + ticker.ProcessTicker("Bitstamp", p, ticker.Price{Last: 1000}, ticker.Spot) + + tick, err := GetSpecificTicker("BTCUSD", "Bitstamp", ticker.Spot) + if err != nil { + t.Fatal(err) + } + + if tick.Last != 1000 { + t.Fatal("Unexpected result") + } + + tick, err = GetSpecificTicker("ETHLTC", "Bitstamp", ticker.Spot) + if err == nil { + t.Fatal("Unexpected result") + } + + UnloadExchange("Bitstamp") +} + +func TestGetCollatedExchangeAccountInfoByCoin(t *testing.T) { + SetupTestHelpers(t) + + exchangeInfo := []exchange.AccountInfo{} + var info exchange.AccountInfo + + info.ExchangeName = "Bitfinex" + info.Currencies = append(info.Currencies, + exchange.AccountCurrencyInfo{CurrencyName: "BTC", TotalValue: 100, Hold: 0}) + exchangeInfo = append(exchangeInfo, info) + + info.ExchangeName = "Bitstamp" + info.Currencies = append(info.Currencies, exchange.AccountCurrencyInfo{CurrencyName: "LTC", TotalValue: 100, Hold: 0}) + exchangeInfo = append(exchangeInfo, info) + + result := GetCollatedExchangeAccountInfoByCoin(exchangeInfo) + if len(result) == 0 { + t.Fatal("Unexpected result") + } + + amount, ok := result["BTC"] + if !ok { + t.Fatal("Expected currency was not found in result map") + } + + if amount.TotalValue != 200 { + t.Fatal("Unexpected result") + } + + _, ok = result["ETH"] + if ok { + t.Fatal("Unexpected result") + } +} + +func TestGetAccountCurrencyInfoByExchangeName(t *testing.T) { + SetupTestHelpers(t) + + exchangeInfo := []exchange.AccountInfo{} + var info exchange.AccountInfo + info.ExchangeName = "Bitfinex" + info.Currencies = append(info.Currencies, + exchange.AccountCurrencyInfo{CurrencyName: "BTC", TotalValue: 100, Hold: 0}) + exchangeInfo = append(exchangeInfo, info) + + result, err := GetAccountCurrencyInfoByExchangeName(exchangeInfo, "Bitfinex") + if err != nil { + t.Fatal(err) + } + + if result.ExchangeName != "Bitfinex" { + t.Fatal("Unexepcted result") + } + + _, err = GetAccountCurrencyInfoByExchangeName(exchangeInfo, "ASDF") + if err.Error() != exchange.ErrExchangeNotFound { + t.Fatal("Unexepcted result") + } +} + +func TestGetExchangeHighestPriceByCurrencyPair(t *testing.T) { + SetupTestHelpers(t) + + p := pair.NewCurrencyPair("BTC", "USD") + stats.Add("Bitfinex", p, ticker.Spot, 1000, 10000) + stats.Add("Bitstamp", p, ticker.Spot, 1337, 10000) + exchange, err := GetExchangeHighestPriceByCurrencyPair(p, ticker.Spot) + if err != nil { + log.Fatal(err) + } + + if exchange != "Bitstamp" { + log.Fatal("Unexpected result") + } + + _, err = GetExchangeHighestPriceByCurrencyPair(pair.NewCurrencyPair("BTC", "AUD"), ticker.Spot) + if err == nil { + log.Fatal("Unexpected reuslt") + } +} + +func TestGetExchangeLowestPriceByCurrencyPair(t *testing.T) { + SetupTestHelpers(t) + + p := pair.NewCurrencyPair("BTC", "USD") + stats.Add("Bitfinex", p, ticker.Spot, 1000, 10000) + stats.Add("Bitstamp", p, ticker.Spot, 1337, 10000) + exchange, err := GetExchangeLowestPriceByCurrencyPair(p, ticker.Spot) + if err != nil { + log.Fatal(err) + } + + if exchange != "Bitfinex" { + log.Fatal("Unexpected result") + } + + _, err = GetExchangeLowestPriceByCurrencyPair(pair.NewCurrencyPair("BTC", "AUD"), ticker.Spot) + if err == nil { + log.Fatal("Unexpected reuslt") + } +}