-
Notifications
You must be signed in to change notification settings - Fork 874
orderbook: consolidate slice array types to orderbook package #1992
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR consolidates orderbook slice array types across multiple exchanges to use a unified orderbook.LevelsArrayPriceAmount
type. The refactor replaces scattered usage of [][2]types.Number
with a centralized approach that includes JSON unmarshaling functionality, reducing code duplication and improving maintainability.
- Introduces
orderbook.LevelsArrayPriceAmount
type with unified JSON unmarshaling - Replaces manual orderbook level conversion loops with direct method calls
- Simplifies orderbook processing code across 10+ exchange implementations
Reviewed Changes
Copilot reviewed 38 out of 38 changed files in this pull request and generated 3 comments.
Show a summary per file
File | Description |
---|---|
exchanges/orderbook/orderbook_types.go | Adds new LevelsArrayPriceAmount type with JSON unmarshaling and conversion methods |
exchanges/poloniex/poloniex_types.go | Updates orderbook response types to use new unified type |
exchanges/poloniex/poloniex.go | Removes manual conversion loops, uses new Levels() method |
exchanges/lbank/lbank_*.go | Converts from manual slice processing to unified type usage |
exchanges/kucoin/kucoin_*.go | Replaces custom conversion functions with unified approach |
exchanges/gateio/gateio_*.go | Updates orderbook handling to use new type system |
exchanges/bybit/bybit_*.go | Removes custom conversion code, adopts unified type |
exchanges/btcmarkets/btcmarkets_*.go | Simplifies orderbook processing with new type |
exchanges/bitstamp/bitstamp_*.go | Updates websocket and REST orderbook handling |
exchanges/binance*/binance*_*.go | Comprehensive update across Binance family exchanges |
Comments suppressed due to low confidence (2)
exchanges/kucoin/kucoin_futures.go:156
- The function name
unifyFuturesOrderbook
is unclear. Consider a more descriptive name likeconvertFuturesOrderbookResponse
orbuildOrderbookFromResponse
.
func unifyFuturesOrderbook(o *futuresOrderbookResponse) *Orderbook {
exchanges/kucoin/kucoin.go:142
- The function name
unifySpotOrderbook
is unclear. Consider a more descriptive name likeconvertSpotOrderbookResponse
orbuildOrderbookFromResponse
.
func unifySpotOrderbook(o *orderbookResponse) *Orderbook {
Asks orderbook.LevelsArrayPriceAmount `json:"asks"` | ||
Bids orderbook.LevelsArrayPriceAmount `json:"bids"` | ||
Time types.Time `json:"time"` | ||
Sequence types.Number `json:"sequence"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change from string
to types.Number
for the Sequence field appears unrelated to the main orderbook consolidation purpose and should be in a separate commit or PR.
Sequence types.Number `json:"sequence"` | |
Sequence string `json:"sequence"` |
Copilot uses AI. Check for mistakes.
for x := range a.Asks { | ||
asks[x].Price = a.Asks[x][0] | ||
asks[x].Amount = a.Asks[x][1] | ||
return &Orderbook{ID: a.ID, Current: a.Current, Update: a.Update, Asks: OrderbookLevels(a.Asks.Levels()), Bids: OrderbookLevels(a.Bids.Levels())} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The introduction of OrderbookLevels
type and its conversion logic appears to add unnecessary complexity. Consider whether this intermediate type is needed or if the orderbook could use orderbook.Levels
directly.
Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #1992 +/- ##
==========================================
- Coverage 39.70% 39.58% -0.12%
==========================================
Files 434 434
Lines 171748 171368 -380
==========================================
- Hits 68185 67829 -356
+ Misses 96417 96395 -22
+ Partials 7146 7144 -2
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got a variety of simple/minor changes I want. With those fixed, I could tACK this.
t.Parallel() | ||
|
||
var asks LevelsArrayPriceAmount | ||
err := asks.UnmarshalJSON([]byte(`[[1,2],[3,4]]`)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super optional, but if we want to be more robust in testing the functionality this should cover, you could use the byte slice [[1,2],["3","4"]]
, covering both supported ways of representing numbers without making a significant change to the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah 🚀
exchanges/binance/binance.go
Outdated
@@ -121,36 +121,20 @@ func (e *Exchange) GetExchangeInfo(ctx context.Context) (ExchangeInfo, error) { | |||
// OrderBookDataRequestParams contains the following members | |||
// symbol: string of currency pair | |||
// limit: returned limit amount |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With OrderBookDataRequestParams being removed, these comments explaining it should be too.
func (e *Exchange) SeedLocalCacheWithBook(p currency.Pair, orderbookNew *OrderBookResponse) error { | ||
t := orderbookNew.Timestamp.Time() | ||
if t.IsZero() { | ||
t = time.Now() // Time not provided for this REST book. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this handling still necessary? Are there ever books which don't return their time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it seems like all spot orderbooks don't return a time value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, but GetOrderBook() is in the non-futures file, and has a timestamp in its response struct. If that can just receive futures responses too, don't worry, but if it's spot-only, I think including a timestamp field there if one is never returned is bad.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah you are right I was most likely thinking when I convert this over to manage other assets as well when I do a full ob pass that this will auto utilise the shared field. I can drop it if you really want but it might be missed in a future upgrade pass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're better informed on the tradeoffs than me, so use your own judgement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will leave this unresolved for other peoples perspective. Either way when somebody is doing some hectic trading and they see a latency discrepancy they will be all like 👻 and open a holy PR that rectifies this issue. 🙏
if err != nil { | ||
return nil, err | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some unnecessary newlines here 💢
MarketID currency.Pair `json:"marketId"` | ||
SnapshotID int64 `json:"snapshotId"` | ||
Asks orderbook.LevelsArrayPriceAmount `json:"asks"` | ||
Bids orderbook.LevelsArrayPriceAmount `json:"bids"` | ||
} | ||
|
||
// OBData stores orderbook data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type doesn't seem to be used any more.
return book, err | ||
} | ||
return orderbook.Get(e.Name, book.Pair, a) | ||
return orderbook.Get(e.Name, p, a) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The orderbook is processed with p.Upper(); shouldn't the same be used here, just in case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope doesn't matter in the storage it just splits it for the *currency.Item
I can drop the upper when processing with no harm as well.
func (o *OrderbookLevels) UnmarshalJSON(data []byte) error { | ||
var levels []OrderbookItem | ||
if err := json.Unmarshal(data, &levels); err != nil { | ||
return err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new function misses coverage on this line, consider adding a test to get some.
return unifySpotOrderbook(o), nil | ||
} | ||
|
||
func unifySpotOrderbook(o *orderbookResponse) *Orderbook { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the goal of unifying spot with futures, would you have any interest in adding a Symbol field to Orderbook, which would be fulfilled by passing in the symbol parameter from the original function calls? That'd stop this little data loss.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather not; The caller inputs the symbol field param, it already has the pair upstream and the responses don't return the symbol field back. If it had it I would then add it as well.
exchanges/poloniex/poloniex_types.go
Outdated
Bids orderbook.LevelsArrayPriceAmount `json:"bids"` | ||
IsFrozen string `json:"isFrozen"` | ||
Error string `json:"error"` | ||
Seq int64 `json:"seq"` | ||
} | ||
|
||
// OrderbookItem holds data on an individual item |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR seems to leave this type unused.
Symbol currency.Pair `json:"symbol"` // Required field; example LTCBTC,BTCUSDT | ||
Limit int64 `json:"limit"` // Default 100; max 5000. If limit > 5000, then the response will truncate to 5000 | ||
} | ||
|
||
// OrderbookItem stores an individual orderbook item | ||
type OrderbookItem struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR seems to render this type unused.
PR Description
Refactor orderbook type processing for [][2]types.Number
orderbook.LevelsArrayPriceAmount
typeFixes # (issue)
Type of change
Please delete options that are not relevant and add an
x
in[]
as item is complete.How has this been tested
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration and
also consider improving test coverage whilst working on a certain feature or package.
Checklist