Files
gocryptotrader/currency/pairs.go
Scott ccfcdf26aa Engine: Protocol Features, coverage, types, BTC markets websocket (#368)
* Attempts to update orderbook so it doesn't need to sort

* Reverts the ws ob stuff. Gets rid of sorting because it happens later. Adds some exchange features

* update existing feature lists. Expands list definition to match my emotions

* Adds bithumb bitmex and bitstamp. adds a couple more types

* Features for you, features for me, features for bittrex, btcmarkets, btse, coinbasepro, coinut, exmo, gateio and gemini

* Features for hitbtc, huobi, itbit, kraken, lakebtc, lbank, localbitcoins, okcoin, okex, poloniex, yobit, zb

* Who can forget good old alphapoint?

* Adds btcmarksets websocket :glitch_crab: fixes alphapoint features

* Adds extra data not in the documentation :/

* Replaces websocket features by using protocol features. However, it breaks it due to import cycles. I'm not sure what I'll do just yet

* Removes import cycle via duplicate structs.

* Increases coverage of config with `TestCheckCurrencyConfigValues`. Moves all currency pair package types into their own files or places it at the bottom of files if necessary

* Increase coverage in code.go

* One way of determining a test has failed, is when to it fails. Removed redundant explanation

* Increases code coverage of conversion

* Lint fixes

* Fixes orderbook tests

* Re-adds sorting because its important to still have the internal pre-processed orderbook to be representative of a real orderbook

* Secret lints that did not show up via Windows linting

* Adds protocol package to contain exchange features

* Fixes protocol implementation

* Fixes ws tests

* Addresses the following: Removes st-st-stutters in config types, changes GetAvailableForexProviders -> GetSupportedForexProviders, removes errors from tests where error is nil, removes orderbook setup when not necessary, removes import newlines, removes false bools from declaration, changes should of to should have

* imports and casing

* Fixes two more nil error checks
2019-10-22 10:56:20 +11:00

189 lines
4.0 KiB
Go

package currency
import (
"math/rand"
"strings"
"github.com/thrasher-corp/gocryptotrader/common"
log "github.com/thrasher-corp/gocryptotrader/logger"
)
// NewPairsFromStrings takes in currency pair strings and returns a currency
// pair list
func NewPairsFromStrings(pairs []string) Pairs {
var ps Pairs
for _, p := range pairs {
if p == "" {
continue
}
ps = append(ps, NewPairFromString(p))
}
return ps
}
// Strings returns a slice of strings referring to each currency pair
func (p Pairs) Strings() []string {
var list []string
for i := range p {
list = append(list, p[i].String())
}
return list
}
// Join returns a comma separated list of currency pairs
func (p Pairs) Join() string {
return strings.Join(p.Strings(), ",")
}
// Format formats the pair list to the exchange format configuration
func (p Pairs) Format(delimiter, index string, uppercase bool) Pairs {
var pairs Pairs
for i := range p {
var formattedPair = Pair{
Delimiter: delimiter,
Base: p[i].Base,
Quote: p[i].Quote,
}
if index != "" {
newP, err := NewPairFromIndex(p[i].String(), index)
if err != nil {
log.Errorf(log.Global,
"failed to create NewPairFromIndex. Err: %s\n", err)
continue
}
formattedPair.Base = newP.Base
formattedPair.Quote = newP.Quote
}
if uppercase {
pairs = append(pairs, formattedPair.Upper())
} else {
pairs = append(pairs, formattedPair.Lower())
}
}
return pairs
}
// UnmarshalJSON comforms type to the umarshaler interface
func (p *Pairs) UnmarshalJSON(d []byte) error {
var pairs string
err := common.JSONDecode(d, &pairs)
if err != nil {
return err
}
var allThePairs Pairs
for _, data := range strings.Split(pairs, ",") {
allThePairs = append(allThePairs, NewPairFromString(data))
}
*p = allThePairs
return nil
}
// MarshalJSON conforms type to the marshaler interface
func (p Pairs) MarshalJSON() ([]byte, error) {
return common.JSONEncode(p.Join())
}
// Upper returns an upper formatted pair list
func (p Pairs) Upper() Pairs {
var upper Pairs
for i := range p {
upper = append(upper, p[i].Upper())
}
return upper
}
// Slice exposes the underlying type
func (p Pairs) Slice() []Pair {
return p
}
// Contains checks to see if a specified pair exists inside a currency pair
// array
func (p Pairs) Contains(check Pair, exact bool) bool {
for _, pair := range p.Slice() {
if exact {
if pair.Equal(check) {
return true
}
} else {
if pair.EqualIncludeReciprocal(check) {
return true
}
}
}
return false
}
// RemovePairsByFilter checks to see if a pair contains a specific currency
// and removes it from the list of pairs
func (p Pairs) RemovePairsByFilter(filter Code) Pairs {
var pairs Pairs
for _, pair := range p.Slice() {
if pair.ContainsCurrency(filter) {
continue
}
pairs = append(pairs, pair)
}
return pairs
}
// Remove removes the specified pair from the list of pairs if it exists
func (p Pairs) Remove(pair Pair) Pairs {
var pairs Pairs
for x := range p {
if p[x].Equal(pair) {
continue
}
pairs = append(pairs, p[x])
}
return pairs
}
// Add adds a specified pair to the list of pairs if it doesn't exist
func (p Pairs) Add(pair Pair) Pairs {
if p.Contains(pair, true) {
return p
}
p = append(p, pair)
return p
}
// FindDifferences returns pairs which are new or have been removed
func (p Pairs) FindDifferences(pairs Pairs) (newPairs, removedPairs Pairs) {
for x := range pairs {
if pairs[x].String() == "" {
continue
}
if !p.Contains(pairs[x], true) {
newPairs = append(newPairs, pairs[x])
}
}
for _, oldPair := range p {
if oldPair.String() == "" {
continue
}
if !pairs.Contains(oldPair, true) {
removedPairs = append(removedPairs, oldPair)
}
}
return
}
// GetRandomPair returns a random pair from a list of pairs
func (p Pairs) GetRandomPair() Pair {
pairsLen := len(p)
if pairsLen == 0 {
return Pair{Base: NewCode(""), Quote: NewCode("")}
}
return p[rand.Intn(pairsLen)]
}
// Pairs defines a list of pairs
type Pairs []Pair