Skip to content

Commit

Permalink
[TASK 117] Adding orderbook websocket to hitbtc wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
saniales authored and wb73 committed Oct 11, 2018
1 parent 68edc8f commit 275e92c
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 155 deletions.
9 changes: 9 additions & 0 deletions environment/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package environment

import (
"fmt"
"time"

"github.com/shopspring/decimal"
Expand All @@ -37,6 +38,14 @@ type OrderBook struct {
Bids []Order `json:"bids,required"`
}

// String returns the string representation of the object.
func (book OrderBook) String() string {
return fmt.Sprintln("ASKS") +
fmt.Sprintln(book.Asks) +
fmt.Sprintln("BIDS") +
fmt.Sprintln(book.Bids)
}

//Order represents a single order in the Order Book for a market.
type Order struct {
Value decimal.Decimal //Value of the trade : e.g. in a BTC ETH is the value of a single ETH in BTC.
Expand Down
176 changes: 51 additions & 125 deletions exchanges/bitfinex.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"math"
"sort"
"time"

"github.com/shopspring/decimal"
Expand Down Expand Up @@ -280,7 +281,7 @@ func (wrapper *BitfinexWrapper) FeedConnect(markets []*environment.Market) error
func (wrapper *BitfinexWrapper) subscribeFeeds(market *environment.Market) {
tickers := make(chan []float64)
orderbooks := make(chan []float64)
trades := make(chan []float64)
//trades := make(chan []float64)

tickerKey := MarketNameFor(market, wrapper)

Expand All @@ -295,13 +296,14 @@ func (wrapper *BitfinexWrapper) subscribeFeeds(market *environment.Market) {
// VOLUME float Daily volume
// HIGH float Daily high
// LOW float Daily low
handleTicker := func(results <-chan []float64, tickerKey string) {
handleTicker := func(results <-chan []float64, market *environment.Market) {
for {

fmt.Println("ENTER")
values, stillOpen := <-results
if !stillOpen {
return
}
fmt.Println("EXIT")
if len(values) == 10 { // for client bug : https://github.com/bitfinexcom/bitfinex-api-go/issues/133
wrapper.summaries.Set(market, &environment.MarketSummary{
Bid: decimal.NewFromFloat(values[0]),
Expand All @@ -315,139 +317,50 @@ func (wrapper *BitfinexWrapper) subscribeFeeds(market *environment.Market) {
}

handleOrderbook := func(results <-chan []float64, m *environment.Market) {
orderbookMap := make(map[float64]float64)
for {
// values : []float64 { PRICE, COUNT, TOTAL_AMOUNT }
values, closed := <-results
if closed {
values, stillOpen := <-results
if !stillOpen {
return
}

orderbook, initialized := wrapper.orderbook.Get(m)
if !initialized {
orderbook = &environment.OrderBook{
Asks: make([]environment.Order, 0, 25),
Bids: make([]environment.Order, 0, 25),
}
if len(values) != 3 { // for client bug : https://github.com/bitfinexcom/bitfinex-api-go/issues/133
continue
}

price := decimal.NewFromFloat(values[0])
price := values[0]
count := values[1]
amount := decimal.NewFromFloat(values[2])

if count == 0 { // remove price level
var temp []environment.Order

found := false
for i, ask := range orderbook.Asks {
if found || ask.Value.GreaterThan(price) {
break
} else if ask.Value.Equals(price) {
temp = append(orderbook.Asks[:i], orderbook.Asks[i+1:]...)
found = true
}
}
amount := values[2]

if found {
orderbook.Asks = temp
} else {
var temp []environment.Order
for i, bid := range orderbook.Bids {
if found || bid.Value.GreaterThan(price) {
break
} else if bid.Value.Equals(price) {
temp = append(orderbook.Bids[:i], orderbook.Bids[i+1:]...)
found = true
}
}

if found {
orderbook.Bids = temp
}
}
} else if amount.GreaterThan(decimal.Zero) { // adding to asks
found := false
for _, bid := range orderbook.Bids {
if found || bid.Value.GreaterThan(price) {
break
} else if bid.Value.Equals(price) {
found = true
delta := bid.Quantity.Sub(amount)
if amount.GreaterThan(bid.Quantity) {
orderbook.Asks = append([]environment.Order{environment.Order{
Value: price,
Quantity: delta,
Timestamp: time.Now(),
}}, orderbook.Asks...)
}
}
}

var temp []environment.Order
for i, ask := range orderbook.Asks {
if found {
break
} else if ask.Value.GreaterThan(price) {
temp = append(orderbook.Asks[:i], environment.Order{
Value: price,
Quantity: amount,
Timestamp: time.Now(),
})
temp = append(temp, orderbook.Asks[i+1:]...)

found = true
} else if ask.Value.Equals(price) {
found = true
ask.Quantity.Add(amount)
}
}
if count == 0 {
delete(orderbookMap, price)
continue
}

if temp != nil {
orderbook.Asks = temp
}
} else if amount.LessThan(decimal.Zero) {
amount = amount.Abs()

found := false
for _, bid := range orderbook.Asks {
if found || bid.Value.GreaterThan(price) {
break
} else if bid.Value.Equals(price) {
found = true
delta := bid.Quantity.Sub(amount)
if amount.GreaterThan(bid.Quantity) {
orderbook.Bids = append([]environment.Order{environment.Order{
Value: price,
Quantity: delta,
Timestamp: time.Now(),
}}, orderbook.Bids...)
}
}
}
orderbookMap[price] += amount

var temp []environment.Order
for i, ask := range orderbook.Bids {
if found {
break
} else if ask.Value.GreaterThan(price) {
temp = append(orderbook.Bids[:i], environment.Order{
Value: price,
Quantity: amount,
Timestamp: time.Now(),
})
temp = append(temp, orderbook.Bids[i+1:]...)

found = true
} else if ask.Value.Equals(price) {
found = true
ask.Quantity.Add(amount)
}
}
orderbook := environment.OrderBook{
Asks: make([]environment.Order, 0, 25),
Bids: make([]environment.Order, 0, 25),
}

if temp != nil {
orderbook.Bids = temp
// now let's create the cache
for price, amount := range orderbookMap {
if amount < 0 {
orderbook.Bids = insertSort(orderbook.Bids, environment.Order{
Value: decimal.NewFromFloat(price),
Quantity: decimal.NewFromFloat(-amount),
}, false)
} else if amount > 0 {
orderbook.Asks = insertSort(orderbook.Asks, environment.Order{
Value: decimal.NewFromFloat(price),
Quantity: decimal.NewFromFloat(amount),
}, true)
}
}
wrapper.orderbook.Set(m, orderbook)

wrapper.orderbook.Set(m, &orderbook)
}
}

Expand All @@ -469,12 +382,12 @@ func (wrapper *BitfinexWrapper) subscribeFeeds(market *environment.Market) {
}
*/

go handleTicker(tickers, tickerKey)
go handleTicker(tickers, market)
go handleOrderbook(orderbooks, market)

wrapper.api.WebSocket.AddSubscribe(bitfinex.ChanTicker, tickerKey, tickers)
//wrapper.api.WebSocket.AddSubscribe(bitfinex.ChanTicker, tickerKey, tickers)
wrapper.api.WebSocket.AddSubscribe(bitfinex.ChanBook, tickerKey, orderbooks)
wrapper.api.WebSocket.AddSubscribe(bitfinex.ChanTrade, tickerKey, trades)
//wrapper.api.WebSocket.AddSubscribe(bitfinex.ChanTrade, tickerKey, trades)
}

// Withdraw performs a withdraw operation from the exchange to a destination address.
Expand All @@ -489,3 +402,16 @@ func (wrapper *BitfinexWrapper) Withdraw(destinationAddress string, coinTicker s

return nil
}

func insertSort(data []environment.Order, el environment.Order, reverse bool) []environment.Order {
index := sort.Search(len(data), func(i int) bool {
if reverse {
return data[i].Value.LessThan(el.Value)
}
return data[i].Value.GreaterThan(el.Value)
})
data = append(data, environment.Order{})
copy(data[index+1:], data[index:])
data[index] = el
return data
}
Loading

0 comments on commit 275e92c

Please sign in to comment.