Giter Club home page Giter Club logo

Comments (2)

aopoltorzhicky avatar aopoltorzhicky commented on July 19, 2024

Hello!

Perhaps you should short your order book according to the depth of the request. Kraken does not send notifications of events deeper than you want to receive. Most likely what happens is that you have a level left in your order book that has gone beyond the top 10. Then it is deleted without notification, because you are subscribed to the top 10. Then, due to some changes, it becomes one of the 10, which are taken into account in your checkout calculation.

You should save only the top 10/100/1000 levels in IndexedBook and remove all levels that exceed the specified depth.

Below I write my part of test code with your checksum implementation. Here is naive realization of dropping exceeded levels, but its work for me:

package main

import (
	"fmt"
	"hash/crc32"
	"sort"
	"strings"

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

// OrderBook -
type OrderBook struct {
	Asks map[string]string
	Bids map[string]string

	sortedAsks []Level
	sortedBids []Level

	depth int
}

// NewOrderBook -
func NewOrderBook(depth int) *OrderBook {
	return &OrderBook{
		Asks: make(map[string]string),
		Bids: make(map[string]string),

		sortedAsks: make([]Level, 0),
		sortedBids: make([]Level, 0),

		depth: depth,
	}
}

// String -
func (o *OrderBook) String() string {
	var str strings.Builder

	str.WriteString("asks:\r\n")
	for price, vol := range o.Asks {
		str.WriteString("\t" + price)
		str.WriteByte('[')
		str.WriteString(vol)
		str.WriteString("]\r\n")
	}

	str.WriteString("bids:\r\n")
	for price, vol := range o.Bids {
		str.WriteString("\t" + price)
		str.WriteByte('[')
		str.WriteString(vol)
		str.WriteString("]\r\n")
	}

	return str.String()
}

func (o *OrderBook) update(m map[string]string, upd ws.OrderBookItem) error {
	flVolume, err := upd.Volume.Float64()
	if err != nil {
		return err
	}
	price := upd.Price.String()

	if flVolume == 0 {
		delete(m, price)
	} else {
		m[price] = upd.Volume.String()
	}

	return nil
}

// Update -
func (o *OrderBook) Update(upd ws.OrderBookUpdate, withCheckSum bool) error {
	for i := range upd.Asks {
		if err := o.update(o.Asks, upd.Asks[i]); err != nil {
			return err
		}
	}

	o.sortedAsks = orderMap(o.Asks, true)[:o.depth]

	for price := range o.Asks {
		var found bool
		for i := range o.sortedAsks {
			if o.sortedAsks[i].Price == price {
				found = true
				break
			}
		}

		if !found {
			delete(o.Asks, price)
		}
	}

	for i := range upd.Bids {
		if err := o.update(o.Bids, upd.Bids[i]); err != nil {
			return err
		}
	}

	o.sortedBids = orderMap(o.Bids, false)[:o.depth]

	for price := range o.Bids {
		var found bool
		for i := range o.sortedBids {
			if o.sortedBids[i].Price == price {
				found = true
				break
			}
		}

		if !found {
			delete(o.Bids, price)
		}
	}

	if withCheckSum && !upd.IsSnapshot {
		cs := o.CheckSum()
		if cs != upd.CheckSum {
			return errors.Errorf("invalid checksum: %s != %s", cs, upd.CheckSum)
		}
	}

	return nil
}

// CheckSum -
func (o *OrderBook) CheckSum() string {
	var str strings.Builder

	for _, level := range o.sortedAsks {
		price := decimal.RequireFromString(level.Price).StringFixed(5)
		price = strings.Replace(price, ".", "", 1)
		price = strings.TrimLeft(price, "0")
		str.WriteString(price)

		volume := decimal.RequireFromString(level.Volume).StringFixed(8)
		volume = strings.Replace(volume, ".", "", 1)
		volume = strings.TrimLeft(volume, "0")
		str.WriteString(volume)
	}

	for _, level := range o.sortedBids {
		price := decimal.RequireFromString(level.Price).StringFixed(5)
		price = strings.Replace(price, ".", "", 1)
		price = strings.TrimLeft(price, "0")
		str.WriteString(price)

		volume := decimal.RequireFromString(level.Volume).StringFixed(8)
		volume = strings.Replace(volume, ".", "", 1)
		volume = strings.TrimLeft(volume, "0")
		str.WriteString(volume)
	}

	checksum := str.String()
	checksumInt := crc32.ChecksumIEEE([]byte(checksum))

	return fmt.Sprint(checksumInt)
}

type Level struct {
	Price  string
	Volume string
}

type ByPrice []Level

func (a ByPrice) Len() int           { return len(a) }
func (a ByPrice) Less(i, j int) bool { return a[i].Price < a[j].Price }
func (a ByPrice) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

func orderMap(m map[string]string, asc bool) []Level {
	result := make([]Level, 0)

	for key, value := range m {
		result = append(result, Level{key, value})
	}

	if asc {
		sort.Sort(ByPrice(result))
	} else {
		sort.Sort(sort.Reverse(ByPrice(result)))
	}

	return result
}

from go_kraken.

byroncoetsee avatar byroncoetsee commented on July 19, 2024

Wow thank you so much for taking the time 🙏🏻 I will try implement what you've done here and let you know. For now I've simply used the ticker... Not an ideal solution.

Thanks again

from go_kraken.

Related Issues (15)

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.