Skip to content
This repository has been archived by the owner on Feb 1, 2024. It is now read-only.

feat/add ttlMap + binanceExchangeWs + binanceExchangeWs.GetTickerPrice #717

Merged
merged 10 commits into from
Jul 18, 2021
8 changes: 0 additions & 8 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

134 changes: 69 additions & 65 deletions glide.yaml
Original file line number Diff line number Diff line change
@@ -1,67 +1,71 @@
package: github.com/stellar/kelp
import:
- package: github.com/cavaliercoder/grab
version: 9f014744ee41e6bca139fe07601e65ac8b9c5109
- package: github.com/Beldur/kraken-go-api-client
version: 8d8ccfe4cc60d1703ffe596c889b887a318a884c
- package: github.com/pkg/errors
version: v0.8.0
- package: github.com/spf13/cobra
version: v0.0.1
- package: github.com/spf13/pflag
version: v1.0.0
- package: github.com/stellar/go
version: horizonclient-v3.0.0
subpackages:
- build
- clients/horizonclient
- support/config
- support/errors
- package: github.com/auth0/go-jwt-middleware
version: v1.0.0
- package: github.com/form3tech-oss/jwt-go
version: 5b2d2b5f6c34ccb3b6b65f77f4706558067690ef
- package: github.com/sirupsen/logrus
version: 070c81def33f6362a8267b6a4e56fb7bf23fc6b5
- package: github.com/Sirupsen/logrus
version: 070c81def33f6362a8267b6a4e56fb7bf23fc6b5
repo: git@github.com:sirupsen/logrus
vcs: git
- package: golang.org/x/crypto
version: 2509b142fb2b797aa7587dad548f113b2c0f20ce
- package: golang.org/x/sys
version: 6c81ef8f67ca3f42fc9cd71dfbd5f35b0c4b5771
- package: github.com/PagerDuty/go-pagerduty
version: 635c5ce271490fba94880e62cde4eea3c1c184b9
- package: github.com/lechengfan/googleauth
version: 7595ba02fbce171759c10d69d96e4cd898d1fa93
- package: github.com/nikhilsaraf/go-tools
version: a26df67722de7fcf1a8e22cd934e63e553dd3875
- package: github.com/mitchellh/mapstructure
version: v1.1.2
- package: github.com/go-chi/chi
version: v4.0.2
- package: github.com/shurcooL/vfsgen
version: 6a9ea43bcacdf716a5c1b38efff722c07adf0069
- package: github.com/rs/cors
version: v1.6.0
- package: github.com/pkg/browser
version: 0a3d74bf9ce488f035cf5bc36f753a711bc74334
- package: github.com/asticode/go-astilectron
version: 8e68f812e8a2dd6655af42a8d6bc44856dd172be
- package: github.com/asticode/go-astilectron-bootstrap
version: 25b8572859996696903f9417598ebc94d5d61035
- package: github.com/asticode/go-astilectron-bundler
version: 155c2a10bbb1791fbafe89a9b64be05c64f16c81
- package: github.com/lib/pq
version: v1.2.0
- package: github.com/openlyinc/pointy
version: 945de578d11bbf43bd9729c2ea0837735a21d475
- package: github.com/denisbrodbeck/machineid
version: v1.0.1
- package: github.com/google/uuid
version: v1.1.2
- package: github.com/adshao/go-binance
version: ^2.3.0
subpackages:
- v2
- package: github.com/cavaliercoder/grab
version: 9f014744ee41e6bca139fe07601e65ac8b9c5109
- package: github.com/Beldur/kraken-go-api-client
version: 8d8ccfe4cc60d1703ffe596c889b887a318a884c
- package: github.com/pkg/errors
version: v0.8.0
- package: github.com/spf13/cobra
version: v0.0.1
- package: github.com/spf13/pflag
version: v1.0.0
- package: github.com/stellar/go
version: horizonclient-v3.0.0
subpackages:
- build
- clients/horizonclient
- support/config
- support/errors
- package: github.com/auth0/go-jwt-middleware
version: v1.0.0
- package: github.com/form3tech-oss/jwt-go
version: 5b2d2b5f6c34ccb3b6b65f77f4706558067690ef
##############################################################
# manually added dependencies to fix glide import resolution
##############################################################
- package: github.com/sirupsen/logrus
version: 070c81def33f6362a8267b6a4e56fb7bf23fc6b5
- package: github.com/Sirupsen/logrus
version: 2509b142fb2b797aa7587dad548f113b2c0f20ce
- package: golang.org/x/crypto
version: 2509b142fb2b797aa7587dad548f113b2c0f20ce
- package: golang.org/x/sys
##############################################################
# /manually added dependencies to fix glide import resolution
##############################################################
version: 6c81ef8f67ca3f42fc9cd71dfbd5f35b0c4b5771
- package: github.com/PagerDuty/go-pagerduty
version: 635c5ce271490fba94880e62cde4eea3c1c184b9
- package: github.com/lechengfan/googleauth
version: 7595ba02fbce171759c10d69d96e4cd898d1fa93
- package: github.com/nikhilsaraf/go-tools
version: a26df67722de7fcf1a8e22cd934e63e553dd3875
- package: github.com/mitchellh/mapstructure
version: v1.1.2
- package: github.com/go-chi/chi
version: v4.0.2
- package: github.com/shurcooL/vfsgen
version: 6a9ea43bcacdf716a5c1b38efff722c07adf0069
- package: github.com/rs/cors
version: v1.6.0
- package: github.com/pkg/browser
version: 0a3d74bf9ce488f035cf5bc36f753a711bc74334
- package: github.com/asticode/go-astilectron
version: 8e68f812e8a2dd6655af42a8d6bc44856dd172be
- package: github.com/asticode/go-astilectron-bootstrap
version: 25b8572859996696903f9417598ebc94d5d61035
- package: github.com/asticode/go-astilectron-bundler
version: 155c2a10bbb1791fbafe89a9b64be05c64f16c81
- package: github.com/lib/pq
version: v1.2.0
- package: github.com/openlyinc/pointy
version: 945de578d11bbf43bd9729c2ea0837735a21d475
- package: github.com/denisbrodbeck/machineid
version: v1.0.1
- package: github.com/google/uuid
version: v1.1.2
- package: github.com/adshao/go-binance
version: v2.3.0
subpackages:
- v2
54 changes: 34 additions & 20 deletions plugins/binanceExchange_ws.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ import (
)

const (
STREAMTICKER = "@ticker"
TTLTIME = time.Second * 3 // ttl time in seconds
STREAM_TICKER_FMT = "%s@ticker"
TTLTIME = time.Second * 3 // ttl time in seconds
)

var (
waitForFirstEvent = true
nikhilsaraf marked this conversation as resolved.
Show resolved Hide resolved
)

var (
Expand Down Expand Up @@ -68,21 +72,25 @@ func (s stream) Close() {
}
}

//mapData... struct used to data from events and timestamp when they are cached
type mapData struct {
data interface{}
createdAt time.Time
}

//isStatle... check if data it's stale
func isStale(data mapData, ttl time.Duration) bool {

return time.Now().Sub(data.createdAt).Seconds() > ttl.Seconds()
}

//struct used to cache events
type mapEvents struct {
data map[string]mapData
mtx *sync.Mutex
mtx *sync.RWMutex
}

//Set ... set value
func (m *mapEvents) Set(key string, data interface{}) {

now := time.Now()
Expand All @@ -95,28 +103,32 @@ func (m *mapEvents) Set(key string, data interface{}) {
m.mtx.Unlock()
nikhilsaraf marked this conversation as resolved.
Show resolved Hide resolved
}

//Get ... get value
func (m *mapEvents) Get(key string) (mapData, bool) {
m.mtx.Lock()
m.mtx.RLock()
data, isData := m.data[key]
m.mtx.Unlock()
m.mtx.RUnlock()

return data, isData
}

//Del ... delete cached value
func (m *mapEvents) Del(key string) {
m.mtx.Lock()
delete(m.data, key)
m.mtx.Unlock()

}

// create new map for cache
func makeMapEvents() *mapEvents {
return &mapEvents{
data: make(map[string]mapData),
mtx: &sync.Mutex{},
mtx: &sync.RWMutex{},
}
}

//struct used to keep all cached data
type events struct {
SymbolStats *mapEvents
}
Expand Down Expand Up @@ -153,14 +165,13 @@ func subcribeTicker(symbol string, state *mapEvents) (*stream, error) {
}

type binanceExchangeWs struct {
events *events
delimiter string
events *events

streams map[string]*stream
streams map[string]*stream
streamLock *sync.Mutex

assetConverter model.AssetConverterInterface

mtx *sync.Mutex
delimiter string
}

// makeBinanceWs is a factory method to make an binance exchange over ws
Expand All @@ -174,19 +185,20 @@ func makeBinanceWs() (*binanceExchangeWs, error) {
events: events,
delimiter: "",
assetConverter: model.CcxtAssetConverter,
mtx: &sync.Mutex{},
streamLock: &sync.Mutex{},
streams: make(map[string]*stream),
}

return beWs, nil
}

//getPrceision... get precision for float string
func getPrecision(floatStr string) int8 {

strs := strings.Split(floatStr, ".")

if len(strs) != 2 {
log.Printf("error get precision for float %s\n", floatStr)
log.Printf("could not get precision for float %s\n", floatStr)
return 0
}

Expand Down Expand Up @@ -215,12 +227,14 @@ func (beWs *binanceExchangeWs) GetTickerPrice(pairs []model.TradingPair) (map[mo
}

//Store stream
beWs.mtx.Lock()
beWs.streams[symbol+STREAMTICKER] = stream
beWs.mtx.Unlock()
beWs.streamLock.Lock()
beWs.streams[fmt.Sprintf(STREAM_TICKER_FMT, symbol)] = stream
beWs.streamLock.Unlock()

//Wait for binance to send events
time.Sleep(time.Second)
if waitForFirstEvent {
//Wait for binance to send events
time.Sleep(time.Second)
nikhilsaraf marked this conversation as resolved.
Show resolved Hide resolved
}

tickerData, isTicker = beWs.events.SymbolStats.Get(symbol)

Expand Down Expand Up @@ -273,11 +287,11 @@ func (beWs *binanceExchangeWs) GetTickerPrice(pairs []model.TradingPair) (map[mo
//Unsubscribe ... unsubscribe from binance streams
func (beWs *binanceExchangeWs) Unsubscribe(stream string) {
nikhilsaraf marked this conversation as resolved.
Show resolved Hide resolved

beWs.mtx.Lock()
beWs.streamLock.Lock()

if stream, isStream := beWs.streams[stream]; isStream {
stream.Close()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we also need to remove all values from beWs.streams?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove them, but it's only if we want this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes lets' remove please


beWs.mtx.Unlock()
beWs.streamLock.Unlock()
}
59 changes: 19 additions & 40 deletions plugins/binanceExchange_ws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,6 @@ import (
"github.com/stretchr/testify/assert"
)

// import (
// "fmt"
// "log"
// "math"
// "strconv"
// "testing"
// "time"

// "github.com/stretchr/testify/assert"

// "github.com/stellar/kelp/api"
// "github.com/stellar/kelp/model"
// )

var testOrderConstraintsBinanceWs = map[string]map[model.TradingPair]model.OrderConstraints{
"binance": {
*model.MakeTradingPair(model.XLM, model.USDT): *model.MakeOrderConstraints(4, 5, 0.1),
*model.MakeTradingPair(model.XLM, model.BTC): *model.MakeOrderConstraints(8, 4, 1.0),
},
"kraken": {
*model.MakeTradingPair(model.XLM, model.USD): *model.MakeOrderConstraints(6, 8, 30.0),
*model.MakeTradingPair(model.XLM, model.BTC): *model.MakeOrderConstraints(8, 8, 30.0),
},
"bitstamp": {
*model.MakeTradingPair(model.XLM, model.USD): *model.MakeOrderConstraints(5, 2, 25.0),
},
}

func Test_createStateEvents(t *testing.T) {

events := createStateEvents()
Expand All @@ -44,28 +16,35 @@ func Test_createStateEvents(t *testing.T) {
}

func Test_binanceExchangeWs_GetTickerPrice(t *testing.T) {
nikhilsaraf marked this conversation as resolved.
Show resolved Hide resolved
if testing.Short() {
return
}
pair := model.TradingPair{Base: model.XLM, Quote: model.BTC}
pairs := []model.TradingPair{pair}

testBinanceExchangeWs, e := makeBinanceWs()
if !assert.NoError(t, e) {
testBinanceExchangeWs, err := makeBinanceWs()

if !assert.NoError(t, err) {
return
}

pair := model.TradingPair{Base: model.XLM, Quote: model.BTC}
pairs := []model.TradingPair{pair}

m, e := testBinanceExchangeWs.GetTickerPrice(pairs)
if !assert.NoError(t, e) {
return
}

assert.Equal(t, 1, len(m))

ticker := m[pair]
fmt.Printf("ticker price: bid=%s, ask=%s, last=%s\n", ticker.BidPrice.AsString(), ticker.AskPrice.AsString(), ticker.LastPrice.AsString())

assert.True(t, ticker.AskPrice.AsFloat() < 1, ticker.AskPrice.AsString())
assert.True(t, ticker.BidPrice.AsFloat() < 1, ticker.BidPrice.AsString())
assert.True(t, ticker.BidPrice.AsFloat() < ticker.AskPrice.AsFloat(), fmt.Sprintf("bid price (%s) should be less than ask price (%s)", ticker.BidPrice.AsString(), ticker.AskPrice.AsString()))
assert.True(t, ticker.LastPrice.AsFloat() < 1, ticker.LastPrice.AsString())
if !assert.True(t, ticker.AskPrice.AsFloat() < 1, ticker.AskPrice.AsString()) {
return
}
if !assert.True(t, ticker.BidPrice.AsFloat() < 1, ticker.BidPrice.AsString()) {
return
}
if !assert.True(t, ticker.BidPrice.AsFloat() < ticker.AskPrice.AsFloat(), fmt.Sprintf("bid price (%s) should be less than ask price (%s)", ticker.BidPrice.AsString(), ticker.AskPrice.AsString())) {
return
}
if !assert.True(t, ticker.LastPrice.AsFloat() < 1, ticker.LastPrice.AsString()) {
return
}
}