Giter Club home page Giter Club logo

go_kraken's Issues

Can't seem to avoid checksum failure

Hi. Thanks so much for this library.
I'm trying my best to implement a simple local orderbook, as all the examples suggest. However, after a few seconds, I keep hitting a checksum mismatch. If I increase the depth to 100, it lasts a whole lot longer but still crashes after about 30 minutes or so.

  • It's able to run for a few updates so the checksum calculations seem to be working.
  • I've also counted each iteration and it isn't skipping any. (see the 2 counters in the code)
  • I've compared my checksum maths to the Google Sheet provided by Kraken (here) and with my orderbook inputted, the checksum is the same (again, so my calculations are correct).

My only thought is processing speed but I'm on a 2.9GHz Quadcore i7 Macbook Pro, I don't think I should be having processing speed issues? Activity Monitor shows nothing hectic either.

Here's my code if anyone feels like lending an eye.

package kraken

import (
	"errors"
	"fmt"
	"hash/crc32"
	"os"
	"os/signal"
	e "router/exchanges"
	log "router/logging"
	"sort"
	"strings"
	"syscall"

	ws "github.com/aopoltorzhicky/go_kraken/websocket"
	"github.com/shopspring/decimal"
)

var orderbook_btc_usd = e.IndexedBook{
	Bids: make(map[float64]e.SubBook),
	Asks: make(map[float64]e.SubBook),
}

func ConnectKrakenWS() {
	signals := make(chan os.Signal, 1)
	signal.Notify(signals, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)

	kraken := ws.NewKraken(ws.ProdBaseURL)
	if err := kraken.Connect(); err != nil {
		log.LogFatal(errors.New("Error connecting to web socket: " + err.Error()))
	}

	// subscribe to BTCUSD`s ticker
	if err := kraken.SubscribeBook([]string{ws.BTCUSD}, ws.Depth10); err != nil {
		log.LogFatal(errors.New("SubscribeTicker error: " + err.Error()))
	}

	orderbook_btc_usd = e.IndexedBook{
		Bids: make(map[float64]e.SubBook),
		Asks: make(map[float64]e.SubBook),
	}

	var processedCounter = 0
	var recievedCounter = 0
	// busy := false

	for {
		select {
		case <-signals:
			log.LogInfo("Stopping kraken WS...")
			if err := kraken.Close(); err != nil {
				log.LogFatal(err)
			}
			return
		case update := <-kraken.Listen():

			switch data := update.Data.(type) {
			case ws.OrderBookUpdate:
				recievedCounter += 1
				// if !busy {
				// 	busy = true
				switch update.Pair {
				case "XBT/USD":
					handleBTCUSDUpdateEvent(&data)
				}
				processedCounter += 1
				// 	busy = false
				// }
			default:
			}
		}
	}
}

func handleBTCUSDUpdateEvent(v *ws.OrderBookUpdate) {

	capture(orderbook_btc_usd.Bids, v.Bids)
	capture(orderbook_btc_usd.Asks, v.Asks)

	newBook := sortorderbook()
	newBook.Pair.Currency1 = e.BTC
	newBook.Pair.Currency2 = e.USD

	if !v.IsSnapshot {
		if !isBookValid(newBook, v.CheckSum) {
			fmt.Println("Checksum failure. Expected", v.CheckSum)
			// log.LogFatal(errors.New("Kraken checksum failure"))
			return
		}
	}

	e.Kraken.Book = newBook
	e.Kraken.Active = true
}

func capture(liveSideCollection map[float64]e.SubBook, deltaCollection []ws.OrderBookItem) {
	// for k, v := range liveSideCollection {
	for i := range deltaCollection {
		price, _ := deltaCollection[i].Price.Float64()
		qty, _ := deltaCollection[i].Volume.Float64()
		if qty == 0 {
			delete(liveSideCollection, price)
		} else {
			liveSideCollection[price] = e.SubBook{
				Price: price,
				Qty:   qty,
			}
		}
	}
	// }
}

func sortorderbook() (Book e.Book) {
	c := orderbook_btc_usd

	Book.Bids = []e.SubBook{}
	for i := range c.Bids {
		Book.Bids = append(Book.Bids, e.SubBook{
			Price: c.Bids[i].Price,
			Qty:   c.Bids[i].Qty,
		})
	}
	sort.Sort(e.BidSubBook(Book.Bids))
	Book.Bids[0].Total = Book.Bids[0].Qty
	for i := 1; i < 10; i++ {
		Book.Bids[i].Total = Book.Bids[i-1].Total + Book.Bids[i].Qty
	}

	Book.Asks = []e.SubBook{}
	for i := range c.Asks {
		Book.Asks = append(Book.Asks, e.SubBook{
			Price: c.Asks[i].Price,
			Qty:   c.Asks[i].Qty,
		})
	}
	sort.Sort(e.AskSubBook(Book.Asks))
	Book.Asks[0].Total = Book.Asks[0].Qty
	for i := 1; i < 10; i++ {
		Book.Asks[i].Total = Book.Asks[i-1].Total + Book.Asks[i].Qty
	}

	// Book.Bids = Book.Bids[:10]
	// Book.Asks = Book.Asks[:10]

	return Book
}

func isBookValid(newBook e.Book, challengeChecksum string) bool {
	var str strings.Builder

	// Literally here so I can print the current local orderbook for checksum comparisons
	dict := map[string][][]string{}

	for _, level := range newBook.Asks[:10] {
		price := decimal.NewFromFloat(level.Price).StringFixed(5)
		price = strings.Replace(price, ".", "", 1)
		price = strings.TrimLeft(price, "0")
		str.WriteString(price)

		volume := decimal.NewFromFloat(level.Qty).StringFixed(8)
		volume = strings.Replace(volume, ".", "", 1)
		volume = strings.TrimLeft(volume, "0")
		str.WriteString(volume)

		dict["a"] = append(dict["a"], []string{
			decimal.NewFromFloat(level.Price).StringFixed(5), decimal.NewFromFloat(level.Qty).StringFixed(8), "",
		})
	}
	for _, level := range newBook.Bids[:10] {
		price := decimal.NewFromFloat(level.Price).StringFixed(5)
		price = strings.Replace(price, ".", "", 1)
		price = strings.TrimLeft(price, "0")
		str.WriteString(price)

		volume := decimal.NewFromFloat(level.Qty).StringFixed(8)
		volume = strings.Replace(volume, ".", "", 1)
		volume = strings.TrimLeft(volume, "0")
		str.WriteString(volume)

		dict["b"] = append(dict["b"], []string{
			decimal.NewFromFloat(level.Price).StringFixed(5), decimal.NewFromFloat(level.Qty).StringFixed(8), "",
		})
	}

	checksum := str.String()
	checksumInt := crc32.ChecksumIEEE([]byte(checksum))
	checksumPass := fmt.Sprint(checksumInt) == challengeChecksum

	if !checksumPass {
		fmt.Println("Kraken checksum fail")
	}

	return checksumPass
}

Missing ReqID field in `AddOrderRequest` and `AddOrderResponse`

Maybe I'm missing something, but the structs mentioned the title are both missing a ReqID field, which is present in Kraken API documentation. Without them I don't know how can I know which order an AddOrderResponse belongs to. Is there any reason for this omission that I should be aware of?

Great job! :)

Thanks for this - looks very smooth. Heads up - I noticed that running the basic orderbook example gives an 'Unknown message type:' error inside client.handleChannel. Maybe I'm missing something?

websocket orderbook panics after initial snapshot

I'm seeing the following 'panic: interface conversion: interface {} is string, not []interface {}' immediately after the first orderbook update (the snapshot is parsed fine). Anyone seen this before?

Resubscribe fails for private channels

I noticed that my private feed was not able to re-subscribe after error. I noticed this error:
"Unsupported field: 'pair' for the given msg type: private subscribe: "

I think this solution might work...

func (k *Kraken) resubscribe() error {
	for _, sub := range k.subscriptions {
		switch sub.Subscription.Name {
		// Private Channels
		case ChanOwnTrades, ChanOpenOrders:
			return k.subscribeToPrivate(sub.Subscription.Name)
		default:
			//All other channels can do normal auth
			if err := k.send(SubscriptionRequest{
				Event:        EventSubscribe,
				Pairs:        []string{sub.Pair},
				Subscription: sub.Subscription,
			}); err != nil {
				return err
			}
		}
	}
	return nil
}

Can't parse open order websocket messages

Thank you very much for your work on this library.

I'm currently getting a "Can't parse data" error when receiving incoming websocket messages regarding open orders (listening for DataUpdates from AuthClient.SubscribeOpenOrders).

I believe the type assertion data.([]interface{}) is failing. I'm not sure if Kraken changed the message format recently?

websocket subscribing to open orders fails

Hi,

I'm having trouble with subscribing to open orders using the websocket module.

I copied the code from examples/auth/main.go in this repo and added my own keys.

When running it from the shell I got some output telling me connecting and subscribing to my own open orders succeeded.

2020/12/12 21:49:10 [WARN]: invalid data length: []interface {}{[]interface {}{
*** snip many go-objects with info of requests from the past ***
}}, "openOrders", map[string]interface {}{"sequence":1}}

As expected with these kind of errors, I don't receive any mesage on the channel returned by Listen().

It seems the data length is 3 and not 4 as the library expects.

Can you reproduce this on your end? Should I make a PR with a fix?

Regards,
lk16

panic send to closed channel on example auth

Hi.
Issue with send on closed channel.
Example


goroutine 72 [running]:
github.com/aopoltorzhicky/go_kraken/websocket.(*Client).close(0xc001112500, 0x0, 0x0)
        /home/dvp/go/pkg/mod/github.com/aopoltorzhicky/go_kraken/[email protected]/client.go:285 +0xc8
github.com/aopoltorzhicky/go_kraken/websocket.(*Client).exit(0xc001112500, 0x0, 0x0, 0x0, 0x0)
        /home/dvp/go/pkg/mod/github.com/aopoltorzhicky/go_kraken/[email protected]/client.go:258 +0x52
github.com/aopoltorzhicky/go_kraken/websocket.(*Client).reconnect(0xc001112500, 0x0, 0x0, 0x0, 0x0)
        /home/dvp/go/pkg/mod/github.com/aopoltorzhicky/go_kraken/[email protected]/client.go:222 +0x7a
github.com/aopoltorzhicky/go_kraken/websocket.(*Client).listenDisconnect(0xc001112500)
        /home/dvp/go/pkg/mod/github.com/aopoltorzhicky/go_kraken/[email protected]/client.go:149 +0x357
created by github.com/aopoltorzhicky/go_kraken/websocket.(*Client).reset
        /home/dvp/go/pkg/mod/github.com/aopoltorzhicky/go_kraken/[email protected]/client.go:189 +0x67
panic: send on closed channel

goroutine 30 [running]:
github.com/aopoltorzhicky/go_kraken/websocket.(*Client).close(0xc001112500, 0xdc0ca0, 0xc00018e230)
        /home/dvp/go/pkg/mod/github.com/aopoltorzhicky/go_kraken/[email protected]/client.go:283 +0xad
github.com/aopoltorzhicky/go_kraken/websocket.(*Client).exit(0xc001112500, 0xdc0ca0, 0xc00018e230, 0x0, 0x0)
        /home/dvp/go/pkg/mod/github.com/aopoltorzhicky/go_kraken/[email protected]/client.go:258 +0x52
github.com/aopoltorzhicky/go_kraken/websocket.(*Client).reconnect(0xc001112500, 0xdc0ca0, 0xc00018e230, 0x0, 0x0)
        /home/dvp/go/pkg/mod/github.com/aopoltorzhicky/go_kraken/[email protected]/client.go:245 +0x5d0
github.com/aopoltorzhicky/go_kraken/websocket.(*Client).listenDisconnect(0xc001112500)
        /home/dvp/go/pkg/mod/github.com/aopoltorzhicky/go_kraken/[email protected]/client.go:149 +0x357
created by github.com/aopoltorzhicky/go_kraken/websocket.(*Client).reset
        /home/dvp/go/pkg/mod/github.com/aopoltorzhicky/go_kraken/[email protected]/client.go:189 +0x67

Received error "websocket: close 1013: Market data unavailable"

Hi!
I received this error and the client was not able to recover? I sent out an email to Kraken support to understand this error code a bit more. Is the correct way to handle this documented somewhere? Happy to make the change myself, just trying to gather information.

websocket: close 1013: Market data unavailable

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.