From 04d1de9e22e9a7a936828051c22c4118707fa9b3 Mon Sep 17 00:00:00 2001 From: Adrian Gallagher Date: Wed, 13 Sep 2017 12:39:49 +1000 Subject: [PATCH] Add fiat display currency setting, defaults to USD --- config/config.go | 13 ++- currency/symbol/symbol.go | 125 ++++++++++++++++++++++++++++ currency/symbol/symbol_test.go | 21 +++++ main.go | 1 + routines.go | 148 +++++++++++++++++++++++++++------ testdata/configtest.dat | 6 +- tools/portfolio/portfolio.go | 38 ++++++--- 7 files changed, 310 insertions(+), 42 deletions(-) create mode 100644 currency/symbol/symbol.go create mode 100644 currency/symbol/symbol_test.go diff --git a/config/config.go b/config/config.go index f59039ae..322a34df 100644 --- a/config/config.go +++ b/config/config.go @@ -94,10 +94,11 @@ type Config struct { Cryptocurrencies string CurrencyExchangeProvider string CurrencyPairFormat *CurrencyPairFormatConfig `json:"CurrencyPairFormat"` - Portfolio portfolio.Base `json:"PortfolioAddresses"` - SMS SMSGlobalConfig `json:"SMSGlobal"` - Webserver WebserverConfig `json:"Webserver"` - Exchanges []ExchangeConfig `json:"Exchanges"` + FiatDisplayCurrency string + Portfolio portfolio.Base `json:"PortfolioAddresses"` + SMS SMSGlobalConfig `json:"SMSGlobal"` + Webserver WebserverConfig `json:"Webserver"` + Exchanges []ExchangeConfig `json:"Exchanges"` } // ExchangeConfig holds all the information needed for each enabled Exchange. @@ -454,6 +455,10 @@ func (c *Config) LoadConfig(configPath string) error { } } + if c.FiatDisplayCurrency == "" { + c.FiatDisplayCurrency = "USD" + } + return nil } diff --git a/currency/symbol/symbol.go b/currency/symbol/symbol.go new file mode 100644 index 00000000..8f1cefb2 --- /dev/null +++ b/currency/symbol/symbol.go @@ -0,0 +1,125 @@ +package symbol + +import "errors" + +// symbols map holds the currency name and symbol mappings +var symbols = map[string]string{ + "ALL": "Lek", + "AFN": "؋", + "ARS": "$", + "AWG": "ƒ", + "AUD": "$", + "AZN": "ман", + "BSD": "$", + "BBD": "$", + "BYN": "Br", + "BZD": "BZ$", + "BMD": "$", + "BOB": "$b", + "BAM": "KM", + "BWP": "P", + "BGN": "лв", + "BRL": "R$", + "BND": "$", + "KHR": "៛", + "CAD": "$", + "KYD": "$", + "CLP": "$", + "CNY": "¥", + "COP": "$", + "CRC": "₡", + "HRK": "kn", + "CUP": "₱", + "CZK": "Kč", + "DKK": "kr", + "DOP": "RD$", + "XCD": "$", + "EGP": "£", + "SVC": "$", + "EUR": "€", + "FKP": "£", + "FJD": "$", + "GHS": "¢", + "GIP": "£", + "GTQ": "Q", + "GGP": "£", + "GYD": "$", + "HNL": "L", + "HKD": "$", + "HUF": "Ft", + "ISK": "kr", + "INR": "₹", + "IDR": "Rp", + "IRR": "﷼", + "IMP": "£", + "ILS": "₪", + "JMD": "J$", + "JPY": "¥", + "JEP": "£", + "KZT": "лв", + "KPW": "₩", + "KRW": "₩", + "KGS": "лв", + "LAK": "₭", + "LBP": "£", + "LRD": "$", + "MKD": "ден", + "MYR": "RM", + "MUR": "₨", + "MXN": "$", + "MNT": "₮", + "MZN": "MT", + "NAD": "$", + "NPR": "₨", + "ANG": "ƒ", + "NZD": "$", + "NIO": "C$", + "NGN": "₦", + "NOK": "kr", + "OMR": "﷼", + "PKR": "₨", + "PAB": "B/.", + "PYG": "Gs", + "PEN": "S/.", + "PHP": "₱", + "PLN": "zł", + "QAR": "﷼", + "RON": "lei", + "RUB": "₽", + "SHP": "£", + "SAR": "﷼", + "RSD": "Дин.", + "SCR": "₨", + "SGD": "$", + "SBD": "$", + "SOS": "S", + "ZAR": "R", + "LKR": "₨", + "SEK": "kr", + "CHF": "CHF", + "SRD": "$", + "SYP": "£", + "TWD": "NT$", + "THB": "฿", + "TTD": "TT$", + "TRY": "₺", + "TVD": "$", + "UAH": "₴", + "GBP": "£", + "USD": "$", + "UYU": "$U", + "UZS": "лв", + "VEF": "Bs", + "VND": "₫", + "YER": "﷼", + "ZWD": "Z$", +} + +// GetSymbolByCurrencyName returns a currency symbol +func GetSymbolByCurrencyName(currency string) (string, error) { + result, ok := symbols[currency] + if !ok { + return "", errors.New("currency symbol not found") + } + return result, nil +} diff --git a/currency/symbol/symbol_test.go b/currency/symbol/symbol_test.go new file mode 100644 index 00000000..5975cb67 --- /dev/null +++ b/currency/symbol/symbol_test.go @@ -0,0 +1,21 @@ +package symbol + +import "testing" + +func TestGetSymbolByCurrencyName(t *testing.T) { + expected := "₩" + actual, err := GetSymbolByCurrencyName("KPW") + if err != nil { + t.Errorf("Test failed. TestGetSymbolByCurrencyName error: %s", err) + } + + if actual != expected { + t.Errorf("Test failed. TestGetSymbolByCurrencyName differing values") + } + + _, err = GetSymbolByCurrencyName("BLAH") + if err == nil { + t.Errorf("Test failed. TestGetSymbolByCurrencyNam returned nil on non-existant currency") + } + +} diff --git a/main.go b/main.go index 4f8c8aba..67b86f96 100644 --- a/main.go +++ b/main.go @@ -116,6 +116,7 @@ func main() { } log.Printf("Bot '%s' started.\n", bot.config.Name) + log.Printf("Fiat display currency: %s.", bot.config.FiatDisplayCurrency) AdjustGoMaxProcs() if bot.config.SMS.Enabled { diff --git a/routines.go b/routines.go index ae9f7c9d..5c32b6b0 100644 --- a/routines.go +++ b/routines.go @@ -5,16 +5,54 @@ import ( "log" "time" + "github.com/thrasher-/gocryptotrader/currency" "github.com/thrasher-/gocryptotrader/currency/pair" + "github.com/thrasher-/gocryptotrader/currency/symbol" exchange "github.com/thrasher-/gocryptotrader/exchanges" "github.com/thrasher-/gocryptotrader/exchanges/orderbook" "github.com/thrasher-/gocryptotrader/exchanges/stats" "github.com/thrasher-/gocryptotrader/exchanges/ticker" ) +func printCurrencyFormat(price float64) string { + displaySymbol, err := symbol.GetSymbolByCurrencyName(bot.config.FiatDisplayCurrency) + if err != nil { + log.Printf("Failed to get display symbol: %s", err) + } + + return fmt.Sprintf("%s%.8f", displaySymbol, price) +} + +func printConvertCurrencyFormat(origCurrency string, origPrice float64) string { + displayCurrency := bot.config.FiatDisplayCurrency + conv, err := currency.ConvertCurrency(origPrice, origCurrency, displayCurrency) + if err != nil { + log.Printf("Failed to convert currency: %s", err) + } + + displaySymbol, err := symbol.GetSymbolByCurrencyName(displayCurrency) + if err != nil { + log.Printf("Failed to get display symbol: %s", err) + } + + origSymbol, err := symbol.GetSymbolByCurrencyName(origCurrency) + if err != nil { + log.Printf("Failed to get original currency symbol: %s", err) + } + + return fmt.Sprintf("%s%.2f %s (%s%.2f %s)", + displaySymbol, + conv, + displayCurrency, + origSymbol, + origPrice, + origCurrency, + ) +} + func printSummary(result ticker.Price, p pair.CurrencyPair, assetType, exchangeName string, err error) { if err != nil { - log.Printf("failed to get %s %s ticker. Error: %s", + log.Printf("Failed to get %s %s ticker. Error: %s", p.Pair().String(), exchangeName, err) @@ -22,41 +60,103 @@ func printSummary(result ticker.Price, p pair.CurrencyPair, assetType, exchangeN } stats.Add(exchangeName, p, assetType, result.Last, result.Volume) - log.Printf("%s %s %s: Last %.8f Ask %.8f Bid %.8f High %.8f Low %.8f Volume %.8f", - exchangeName, - exchange.FormatCurrency(p).String(), - assetType, - result.Last, - result.Ask, - result.Bid, - result.High, - result.Low, - result.Volume) + if currency.IsFiatCurrency(p.SecondCurrency.String()) && p.SecondCurrency.String() != bot.config.FiatDisplayCurrency { + origCurrency := p.SecondCurrency.Upper().String() + log.Printf("%s %s %s: Last %s Ask %s Bid %s High %s Low %s Volume %.8f", + exchangeName, + exchange.FormatCurrency(p).String(), + assetType, + printConvertCurrencyFormat(origCurrency, result.Last), + printConvertCurrencyFormat(origCurrency, result.Ask), + printConvertCurrencyFormat(origCurrency, result.Bid), + printConvertCurrencyFormat(origCurrency, result.High), + printConvertCurrencyFormat(origCurrency, result.Low), + result.Volume) + } else { + if currency.IsFiatCurrency(p.SecondCurrency.String()) && p.SecondCurrency.Upper().String() == bot.config.FiatDisplayCurrency { + log.Printf("%s %s %s: Last %s Ask %s Bid %s High %s Low %s Volume %.8f", + exchangeName, + exchange.FormatCurrency(p).String(), + assetType, + printCurrencyFormat(result.Last), + printCurrencyFormat(result.Ask), + printCurrencyFormat(result.Bid), + printCurrencyFormat(result.High), + printCurrencyFormat(result.Low), + result.Volume) + } else { + log.Printf("%s %s %s: Last %.8f Ask %.8f Bid %.8f High %.8f Low %.8f Volume %.8f", + exchangeName, + exchange.FormatCurrency(p).String(), + assetType, + result.Last, + result.Ask, + result.Bid, + result.High, + result.Low, + result.Volume) + } + } } func printOrderbookSummary(result orderbook.Base, p pair.CurrencyPair, assetType, exchangeName string, err error) { if err != nil { - log.Printf("failed to get %s %s orderbook. Error: %s", + log.Printf("Failed to get %s %s orderbook. Error: %s", p.Pair().String(), exchangeName, err) return } - bidsAmount, bidsValue := result.CalculateTotalBids() asksAmount, asksValue := result.CalculateTotalAsks() - log.Printf("%s %s %s: Orderbook Bids len: %d amount: %f total value: %f Asks len: %d amount: %f total value: %f", - exchangeName, - exchange.FormatCurrency(p).String(), - assetType, - len(result.Bids), - bidsAmount, - bidsValue, - len(result.Asks), - asksAmount, - asksValue, - ) + if currency.IsFiatCurrency(p.SecondCurrency.String()) && p.SecondCurrency.String() != bot.config.FiatDisplayCurrency { + origCurrency := p.SecondCurrency.Upper().String() + log.Printf("%s %s %s: Orderbook Bids len: %d Amount: %f %s. Total value: %s Asks len: %d Amount: %f %s. Total value: %s", + exchangeName, + exchange.FormatCurrency(p).String(), + assetType, + len(result.Bids), + bidsAmount, + p.FirstCurrency.String(), + printConvertCurrencyFormat(origCurrency, bidsValue), + len(result.Asks), + asksAmount, + p.FirstCurrency.String(), + printConvertCurrencyFormat(origCurrency, asksValue), + ) + } else { + if currency.IsFiatCurrency(p.SecondCurrency.String()) && p.SecondCurrency.Upper().String() == bot.config.FiatDisplayCurrency { + log.Printf("%s %s %s: Orderbook Bids len: %d Amount: %f %s. Total value: %s Asks len: %d Amount: %f %s. Total value: %s", + exchangeName, + exchange.FormatCurrency(p).String(), + assetType, + len(result.Bids), + bidsAmount, + p.FirstCurrency.String(), + printCurrencyFormat(bidsValue), + len(result.Asks), + asksAmount, + p.FirstCurrency.String(), + printCurrencyFormat(asksValue), + ) + } else { + log.Printf("%s %s %s: Orderbook Bids len: %d Amount: %f %s. Total value: %f Asks len: %d Amount: %f %s. Total value: %f", + exchangeName, + exchange.FormatCurrency(p).String(), + assetType, + len(result.Bids), + bidsAmount, + p.FirstCurrency.String(), + bidsValue, + len(result.Asks), + asksAmount, + p.FirstCurrency.String(), + asksValue, + ) + } + } + } func relayWebsocketEvent(result interface{}, event, assetType, exchangeName string) { diff --git a/testdata/configtest.dat b/testdata/configtest.dat index e894e05e..46541e00 100644 --- a/testdata/configtest.dat +++ b/testdata/configtest.dat @@ -2,10 +2,12 @@ "Name": "Skynet", "EncryptConfig": 0, "Cryptocurrencies": "BTC,LTC,ETH,XRP,NMC,NVC,PPC,XBT,DOGE,DASH", + "CurrencyExchangeProvider": "fixer", "CurrencyPairFormat": { "Uppercase": true, "Delimiter": "-" }, + "FiatDisplayCurrency": "USD", "PortfolioAddresses": { "Addresses": [ { @@ -50,7 +52,9 @@ "Enabled": false, "AdminUsername": "admin", "AdminPassword": "Password", - "ListenAddress": ":9050" + "ListenAddress": ":9050", + "WebsocketConnectionLimit": 1, + "WebsocketAllowInsecureOrigin": false }, "Exchanges": [ { diff --git a/tools/portfolio/portfolio.go b/tools/portfolio/portfolio.go index a7b806fb..bc47dbd1 100644 --- a/tools/portfolio/portfolio.go +++ b/tools/portfolio/portfolio.go @@ -9,22 +9,33 @@ import ( "github.com/thrasher-/gocryptotrader/common" "github.com/thrasher-/gocryptotrader/config" "github.com/thrasher-/gocryptotrader/currency" + "github.com/thrasher-/gocryptotrader/currency/symbol" "github.com/thrasher-/gocryptotrader/exchanges/bitfinex" "github.com/thrasher-/gocryptotrader/portfolio" ) var ( - priceMap map[string]float64 + priceMap map[string]float64 + displayCurrency string ) -func printSummary(msg, from, to string, amount float64) { +func printSummary(msg string, amount float64) { log.Println() log.Println(fmt.Sprintf("%s in USD: $%.2f", msg, amount)) - conv, err := currency.ConvertCurrency(amount, "USD", "AUD") - if err != nil { - log.Println(err) - } else { - log.Println(fmt.Sprintf("%s in AUD: $%.2f", msg, conv)) + + if displayCurrency != "USD" { + conv, err := currency.ConvertCurrency(amount, "USD", displayCurrency) + if err != nil { + log.Println(err) + } else { + symb, err := symbol.GetSymbolByCurrencyName(displayCurrency) + if err != nil { + log.Println(fmt.Sprintf("%s in %s: %.2f", msg, displayCurrency, conv)) + } else { + log.Println(fmt.Sprintf("%s in %s: %s%.2f", msg, displayCurrency, symb, conv)) + } + + } } log.Println() } @@ -38,9 +49,9 @@ func getOnlineOfflinePortfolio(coins []portfolio.Coin, online bool) { x.Balance, value, x.Percentage) } if !online { - printSummary("\tOffline balance", "USD", "AUD", totals) + printSummary("\tOffline balance", totals) } else { - printSummary("\tOnline balance", "USD", "AUD", totals) + printSummary("\tOnline balance", totals) } } @@ -53,12 +64,13 @@ func main() { log.Println("GoCryptoTrader: portfolio tool.") var cfg config.Config - var err = cfg.ReadConfig(inFile) + var err = cfg.LoadConfig(inFile) if err != nil { log.Fatal(err) } log.Println("Loaded config file.") + displayCurrency = cfg.FiatDisplayCurrency port := portfolio.Base{} port.SeedPortfolio(cfg.Portfolio) result := port.GetPortfolioSummary() @@ -127,7 +139,7 @@ func main() { for x, y := range portfolioMap { log.Printf("\t%s Amount: %f Subtotal: $%.2f USD (1 %s = $%.2f USD). Percentage of portfolio %.3f%%", x, y.Balance, y.Subtotal, x, y.Subtotal/y.Balance, y.Subtotal/total*100/1) } - printSummary("\tTotal balance", "USD", "AUD", total) + printSummary("\tTotal balance", total) log.Println("OFFLINE COIN TOTALS:") getOnlineOfflinePortfolio(result.Offline, false) @@ -146,7 +158,7 @@ func main() { log.Printf("\t %s Amount: %f Subtotal: $%.2f Coin percentage: %.2f%%\n", y[z].Address, y[z].Balance, value, y[z].Percentage) } - printSummary(fmt.Sprintf("\t %s balance", x), "USD", "AUD", totals) + printSummary(fmt.Sprintf("\t %s balance", x), totals) } log.Println("ONLINE COINS SUMMARY:") @@ -159,6 +171,6 @@ func main() { log.Printf("\t %s Amount: %f Subtotal $%.2f Coin percentage: %.2f%%", z, w.Balance, value, w.Percentage) } - printSummary("\t Exchange balance", "USD", "AUD", totals) + printSummary("\t Exchange balance", totals) } }