Files
gocryptotrader/currency/currency.go

202 lines
5.7 KiB
Go

package currency
import (
"fmt"
"log"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/currency/forexprovider"
"github.com/thrasher-/gocryptotrader/currency/pair"
)
const (
// DefaultBaseCurrency is the base currency used for conversion
DefaultBaseCurrency = "USD"
// DefaultCurrencies has the default minimum of FIAT values
DefaultCurrencies = "USD,AUD,EUR,CNY"
// DefaultCryptoCurrencies has the default minimum of crytpocurrency values
DefaultCryptoCurrencies = "BTC,LTC,ETH,DOGE,DASH,XRP,XMR"
)
// Manager is the overarching type across this package
var (
FXRates map[string]float64
FiatCurrencies []string
CryptoCurrencies []string
BaseCurrency string
FXProviders *forexprovider.ForexProviders
)
// SetDefaults sets the default currency provider and settings for
// currency conversion used outside of the bot setting
func SetDefaults() {
FXRates = make(map[string]float64)
BaseCurrency = DefaultBaseCurrency
FXProviders = forexprovider.NewDefaultFXProvider()
err := SeedCurrencyData(DefaultCurrencies)
if err != nil {
log.Printf("Failed to seed currency data. Err: %s", err)
return
}
}
// SeedCurrencyData returns rates correlated with suported currencies
func SeedCurrencyData(currencies string) error {
if FXRates == nil {
FXRates = make(map[string]float64)
}
if FXProviders == nil {
FXProviders = forexprovider.NewDefaultFXProvider()
}
newRates, err := FXProviders.GetCurrencyData(BaseCurrency, currencies)
if err != nil {
return err
}
for key, value := range newRates {
FXRates[key] = value
}
return nil
}
// GetExchangeRates returns the currency exchange rates
func GetExchangeRates() map[string]float64 {
return FXRates
}
// IsDefaultCurrency checks if the currency passed in matches the default fiat
// currency
func IsDefaultCurrency(currency string) bool {
defaultCurrencies := common.SplitStrings(DefaultCurrencies, ",")
return common.StringDataCompare(defaultCurrencies, common.StringToUpper(currency))
}
// IsDefaultCryptocurrency checks if the currency passed in matches the default
// cryptocurrency
func IsDefaultCryptocurrency(currency string) bool {
cryptoCurrencies := common.SplitStrings(DefaultCryptoCurrencies, ",")
return common.StringDataCompare(cryptoCurrencies, common.StringToUpper(currency))
}
// IsFiatCurrency checks if the currency passed is an enabled fiat currency
func IsFiatCurrency(currency string) bool {
return common.StringDataCompare(FiatCurrencies, common.StringToUpper(currency))
}
// IsCryptocurrency checks if the currency passed is an enabled CRYPTO currency.
func IsCryptocurrency(currency string) bool {
return common.StringDataCompare(CryptoCurrencies, common.StringToUpper(currency))
}
// IsCryptoPair checks to see if the pair is a crypto pair e.g. BTCLTC
func IsCryptoPair(p pair.CurrencyPair) bool {
return IsCryptocurrency(p.FirstCurrency.String()) &&
IsCryptocurrency(p.SecondCurrency.String())
}
// IsCryptoFiatPair checks to see if the pair is a crypto fiat pair e.g. BTCUSD
func IsCryptoFiatPair(p pair.CurrencyPair) bool {
return IsCryptocurrency(p.FirstCurrency.String()) && !IsCryptocurrency(p.SecondCurrency.String()) ||
!IsCryptocurrency(p.FirstCurrency.String()) && IsCryptocurrency(p.SecondCurrency.String())
}
// IsFiatPair checks to see if the pair is a fiat pair e.g. EURUSD
func IsFiatPair(p pair.CurrencyPair) bool {
return IsFiatCurrency(p.FirstCurrency.String()) &&
IsFiatCurrency(p.SecondCurrency.String())
}
// Update updates the local crypto currency or base currency store
func Update(input []string, cryptos bool) {
for x := range input {
if cryptos {
if !common.StringDataCompare(CryptoCurrencies, input[x]) {
CryptoCurrencies = append(CryptoCurrencies, common.StringToUpper(input[x]))
}
} else {
if !common.StringDataCompare(FiatCurrencies, input[x]) {
FiatCurrencies = append(FiatCurrencies, common.StringToUpper(input[x]))
}
}
}
}
func extractBaseCurrency() string {
for k := range FXRates {
return k[0:3]
}
return ""
}
// ConvertCurrency for example converts $1 USD to the equivalent Japanese Yen
// or vice versa.
func ConvertCurrency(amount float64, from, to string) (float64, error) {
if FXProviders == nil {
SetDefaults()
}
from = common.StringToUpper(from)
to = common.StringToUpper(to)
if from == to {
return amount, nil
}
if from == "RUR" {
from = "RUB"
}
if to == "RUR" {
to = "RUB"
}
if len(FXRates) == 0 {
SeedCurrencyData(from + "," + to)
}
// Need to extract the base currency to see if we actually got it from the Forex API
// Fixer free API sets the base currency to EUR
baseCurr := extractBaseCurrency()
var resultFrom float64
var resultTo float64
// check to see if we're converting from the base currency
if to == baseCurr {
resultFrom, ok := FXRates[baseCurr+from]
if !ok {
return 0, fmt.Errorf("Currency conversion failed. Unable to find %s in currency map [%s -> %s]", from, from, to)
}
return amount / resultFrom, nil
}
// Check to see if we're converting from the base currency
if from == baseCurr {
resultTo, ok := FXRates[baseCurr+to]
if !ok {
return 0, fmt.Errorf("Currency conversion failed. Unable to find %s in currency map [%s -> %s]", to, from, to)
}
return resultTo * amount, nil
}
// Otherwise convert to base currency, then to the target currency
resultFrom, ok := FXRates[baseCurr+from]
if !ok {
return 0, fmt.Errorf("Currency conversion failed. Unable to find %s in currency map [%s -> %s]", from, from, to)
}
converted := amount / resultFrom
resultTo, ok = FXRates[baseCurr+to]
if !ok {
return 0, fmt.Errorf("Currency conversion failed. Unable to find %s in currency map [%s -> %s]", to, from, to)
}
return converted * resultTo, nil
}