Engine QA (#367)

* Improved error message when no config is set on startup

* Change inccorect error wording

* bump Bitfinex websocket orderbook return length to max

* temporary fix of incorrect orderbook updates, limit to bid and ask len of 100, will be extended later if needed

* Fixed issue in binance websocket that appended 0 volume bid/ask items

* Fix panic when unmarshalling an empty pair from config

* Add get pair asset method for exchange base
Fix Bitmex orderbook stream
Unbuffer Bitmex orderbook stream

* force syncer to update ticker instead of fetch, which allows a stream

* Fix websocket last price for coinbasepro

* fix websocket ticker for coinut

* Fix websocket orderbook stream Huobi

* increase orderbook depth REST for Huobi

* Fix websocket support and ensure data integrity

* Fix time parsing issue after error checks

* check error, only process enabled currency pairs, signal websocket data processing

* expanded websocket functionality for okgroup

* Add logic to not process zero length slice for orderbooks

* fix websocket ticker only updating enabled and individual book updates

* ZB fixes to order submission/retrieval/cancellation w/ general fixes

* Quiet unnecessary warning

* updated config entry values for REST and websocket (initial hack until I come up with a better solution for asset types)

* Ch GetName function to field access modifyer & rm useless code

* Add in error I missed

* Nits addressed

* some more fixes

* Turned kraken default websocket to true and some small changes

* fixes linter issues

* Ensured okgroup books and sent update through to datahandler. Zb update as well.

* Add test case to get asset type from pair

* Add test for pairs unmarshal

* Add testing and addressed nits

* FIX linter issue

* Addressed Gees nits

* Thanks glorious spotter

* more nitorinos

* Addres even more nits

* Add stringerino 4000

* Fix for panic cause by sort slice out of range, also nits addressed

* fix linter issues

* Changed from function to field access

* Changed from function to field access

* fix for orderbook update panic, removes quick fix - caused by sync item fetching through same protocol

* Add new test and update random generator

* pass in invalid string to future ob fetching, due to futures contract expire and a http 400 error is returned
This commit is contained in:
Ryan O'Hara-Reid
2019-11-04 15:34:30 +11:00
committed by Adrian Gallagher
parent e2c349424f
commit 22ff33cd54
53 changed files with 1813 additions and 1074 deletions

View File

@@ -45,7 +45,8 @@ func (l *LakeBTC) GetTicker() (map[string]Ticker, error) {
response := make(map[string]TickerResponse)
path := fmt.Sprintf("%s/%s", l.API.Endpoints.URL, lakeBTCTicker)
if err := l.SendHTTPRequest(path, &response); err != nil {
err := l.SendHTTPRequest(path, &response)
if err != nil {
return nil, err
}
@@ -55,22 +56,40 @@ func (l *LakeBTC) GetTicker() (map[string]Ticker, error) {
var tick Ticker
key := strings.ToUpper(k)
if v.Ask != nil {
tick.Ask, _ = strconv.ParseFloat(v.Ask.(string), 64)
tick.Ask, err = strconv.ParseFloat(v.Ask.(string), 64)
if err != nil {
return nil, err
}
}
if v.Bid != nil {
tick.Bid, _ = strconv.ParseFloat(v.Bid.(string), 64)
tick.Bid, err = strconv.ParseFloat(v.Bid.(string), 64)
if err != nil {
return nil, err
}
}
if v.High != nil {
tick.High, _ = strconv.ParseFloat(v.High.(string), 64)
tick.High, err = strconv.ParseFloat(v.High.(string), 64)
if err != nil {
return nil, err
}
}
if v.Last != nil {
tick.Last, _ = strconv.ParseFloat(v.Last.(string), 64)
tick.Last, err = strconv.ParseFloat(v.Last.(string), 64)
if err != nil {
return nil, err
}
}
if v.Low != nil {
tick.Low, _ = strconv.ParseFloat(v.Low.(string), 64)
tick.Low, err = strconv.ParseFloat(v.Low.(string), 64)
if err != nil {
return nil, err
}
}
if v.Volume != nil {
tick.Volume, _ = strconv.ParseFloat(v.Volume.(string), 64)
tick.Volume, err = strconv.ParseFloat(v.Volume.(string), 64)
if err != nil {
return nil, err
}
}
result[key] = tick
}

View File

@@ -74,9 +74,14 @@ func (l *LakeBTC) listenToEndpoints() error {
func (l *LakeBTC) GenerateDefaultSubscriptions() {
var subscriptions []wshandler.WebsocketChannelSubscription
enabledCurrencies := l.GetEnabledPairs(asset.Spot)
for j := range enabledCurrencies {
enabledCurrencies[j].Delimiter = ""
channel := fmt.Sprintf("%v%v%v", marketSubstring, enabledCurrencies[j].Lower(), globalSubstring)
channel := fmt.Sprintf("%v%v%v",
marketSubstring,
enabledCurrencies[j].Lower(),
globalSubstring)
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
Channel: channel,
Currency: enabledCurrencies[j],
@@ -164,8 +169,11 @@ func (l *LakeBTC) processOrderbook(obUpdate, channel string) error {
if err != nil {
return err
}
p := l.getCurrencyFromChannel(channel)
book := orderbook.Base{
Pair: l.getCurrencyFromChannel(channel),
Pair: p,
LastUpdated: time.Now(),
AssetType: asset.Spot,
ExchangeName: l.Name,
@@ -188,6 +196,7 @@ func (l *LakeBTC) processOrderbook(obUpdate, channel string) error {
Price: price,
})
}
for i := 0; i < len(update.Bids); i++ {
var amount, price float64
amount, err = strconv.ParseFloat(update.Bids[i][1], 64)
@@ -205,7 +214,19 @@ func (l *LakeBTC) processOrderbook(obUpdate, channel string) error {
Price: price,
})
}
return l.Websocket.Orderbook.LoadSnapshot(&book)
err = l.Websocket.Orderbook.LoadSnapshot(&book)
if err != nil {
return err
}
l.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
Pair: p,
Asset: asset.Spot,
Exchange: l.Name,
}
return nil
}
func (l *LakeBTC) getCurrencyFromChannel(channel string) currency.Pair {
@@ -221,7 +242,14 @@ func (l *LakeBTC) processTicker(ticker string) error {
l.Websocket.DataHandler <- err
return err
}
enabled := l.GetEnabledPairs(asset.Spot)
for k, v := range tUpdate {
returnCurrency := currency.NewPairFromString(k)
if !enabled.Contains(returnCurrency, true) {
continue
}
tickerData := v.(map[string]interface{})
processTickerItem := func(tick map[string]interface{}, item string) float64 {
if tick[item] == nil {
@@ -230,7 +258,10 @@ func (l *LakeBTC) processTicker(ticker string) error {
p, err := strconv.ParseFloat(tick[item].(string), 64)
if err != nil {
l.Websocket.DataHandler <- fmt.Errorf("%s error parsing ticker data '%s' %v", l.Name, item, tickerData)
l.Websocket.DataHandler <- fmt.Errorf("%s error parsing ticker data '%s' %v",
l.Name,
item,
tickerData)
return 0
}
@@ -246,7 +277,7 @@ func (l *LakeBTC) processTicker(ticker string) error {
Ask: processTickerItem(tickerData, tickerSellString),
Volume: processTickerItem(tickerData, tickerVolumeString),
AssetType: asset.Spot,
Pair: currency.NewPairFromString(k),
Pair: returnCurrency,
}
}
return nil

View File

@@ -214,20 +214,21 @@ func (l *LakeBTC) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pr
pairs := l.GetEnabledPairs(assetType)
for i := range pairs {
currency := l.FormatExchangeCurrency(pairs[i], assetType).String()
if _, ok := ticks[currency]; !ok {
c, ok := ticks[l.FormatExchangeCurrency(pairs[i], assetType).String()]
if !ok {
continue
}
var tickerPrice ticker.Price
tickerPrice.Pair = pairs[i]
tickerPrice.Ask = ticks[currency].Ask
tickerPrice.Bid = ticks[currency].Bid
tickerPrice.Volume = ticks[currency].Volume
tickerPrice.High = ticks[currency].High
tickerPrice.Low = ticks[currency].Low
tickerPrice.Last = ticks[currency].Last
tickerPrice.Ask = c.Ask
tickerPrice.Bid = c.Bid
tickerPrice.Volume = c.Volume
tickerPrice.High = c.High
tickerPrice.Low = c.Low
tickerPrice.Last = c.Last
err = ticker.ProcessTicker(l.GetName(), &tickerPrice, assetType)
err = ticker.ProcessTicker(l.Name, &tickerPrice, assetType)
if err != nil {
log.Error(log.Ticker, err)
}
@@ -237,7 +238,7 @@ func (l *LakeBTC) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pr
// FetchTicker returns the ticker for a currency pair
func (l *LakeBTC) FetchTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
tickerNew, err := ticker.GetTicker(l.GetName(), p, assetType)
tickerNew, err := ticker.GetTicker(l.Name, p, assetType)
if err != nil {
return l.UpdateTicker(p, assetType)
}
@@ -246,7 +247,7 @@ func (l *LakeBTC) FetchTicker(p currency.Pair, assetType asset.Item) (ticker.Pri
// FetchOrderbook returns orderbook base on the currency pair
func (l *LakeBTC) FetchOrderbook(p currency.Pair, assetType asset.Item) (orderbook.Base, error) {
ob, err := orderbook.Get(l.GetName(), p, assetType)
ob, err := orderbook.Get(l.Name, p, assetType)
if err != nil {
return l.UpdateOrderbook(p, assetType)
}
@@ -270,7 +271,7 @@ func (l *LakeBTC) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderb
}
orderBook.Pair = p
orderBook.ExchangeName = l.GetName()
orderBook.ExchangeName = l.Name
orderBook.AssetType = assetType
err = orderBook.Process()
@@ -285,7 +286,7 @@ func (l *LakeBTC) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderb
// LakeBTC exchange
func (l *LakeBTC) GetAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
response.Exchange = l.GetName()
response.Exchange = l.Name
accountInfo, err := l.GetAccountInformation()
if err != nil {
return response, err