-
Notifications
You must be signed in to change notification settings - Fork 146
add MEXC exchange adapter #3367
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
Conversation
bdbd182 to
ce2efe5
Compare
|
Depends on: #3354 |
client/mm/libxc/mexc.go
Outdated
| if syncChan != nil { | ||
| close(syncChan) | ||
| } | ||
| syncChan = make(chan struct{}) | ||
| b.syncChan = syncChan |
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 use of syncChan is different than binance. It doesn't seem to be used at all. I guess can remove it?
client/mm/libxc/mexc.go
Outdated
| // MEXC protobuf doesn't provide sequence IDs, accept all updates after sync. | ||
| if !acceptedUpdate { | ||
| acceptedUpdate = true | ||
| } |
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.
acceptedUpdate doesn't seem to do anything. Can remove I think.
client/mm/libxc/mexc.go
Outdated
| defer syncMtx.Unlock() | ||
| syncCache = make([]*mxctypes.BookUpdate, 0) | ||
| acceptedUpdate = false | ||
| if updateID != updateIDUnsynced { |
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.
It looks like updateID isn't necessary. The value is never used except to see if it's unsynced. Can just check and swap b.synced I think.
| // MEXC sends full snapshots; clear stale data before applying. | ||
| b.book.clear() | ||
| b.book.update(bids, asks) | ||
| return true |
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.
If I understand this correctly, you don't need a syncCache?
client/mm/libxc/mexc.go
Outdated
| b.book.clear() | ||
| b.book.update(bids, asks) | ||
|
|
||
| return processSyncCache(snapshot.LastUpdateID) |
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.
If snapshot, err := b.getSnapshot() worked, does that not mean that processing the cache would replace everything with older info? We only want the latest snapshot? We don't need the old snapshots or a cache at all do we?
| } | ||
| }() | ||
|
|
||
| // Market WS connection is deferred until first SubscribeMarket call |
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.
binance does this but mexc does not.
| minNotionalStr := m.getFilterValue(symbol, "MIN_NOTIONAL") | ||
| if minNotionalStr == "" { | ||
| return true | ||
| } | ||
| minNotional, err := strconv.ParseFloat(minNotionalStr, 64) | ||
| if err != nil { | ||
| return true | ||
| } |
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 sometimes not there? Can you log the error if ParseFloat fails? Seems like that would be false as well?
| stepSize, err := strconv.ParseFloat(stepSizeStr, 64) | ||
| if err != nil { | ||
| return qty | ||
| } |
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.
I don't think it is good to ignore the error. It cannot work correctly if there is error.
ce2efe5 to
4bb9878
Compare
JoeGruffins
left a comment
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.
Thanks for addressing some of the issues, still unsure about one. Left another comment inline.
client/mm/libxc/mexc.go
Outdated
| // Process all cached updates received during sync | ||
| for _, update := range syncCache { | ||
| if !acceptUpdate(update) { | ||
| return false | ||
| } | ||
| } |
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.
I may not be understanding correctly, but if every update has the whole book, then processing the syncCache is not necessary and worse than that it will replace the newest book with one that is older. Am I misunderstanding how it works? Binance gives us diffs, but mexc will give us the entire state?
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.
Correct, we subscribe to the MEXC market websocket for the orderbook with depth@20. The websocket sends the entire state, not a diff. BUT on initialization, we use the REST api for the initial snapshot.
Initial Sync:
- Subscribe to websocket
- Websocket updates start arriving → CACHED (not applied yet)
- Fetch REST snapshot (223 bids, 314 asks)
- Apply REST snapshot to orderbook
- Process cache: Apply any websocket updates received during step 3
- Mark as synced
- Result: Orderbook has top 20 levels (from most recent websocket snapshot)
Post-Sync:
- Websocket update arrives (20 bids, 20 asks)
- Clear orderbook
- Apply update immediately
- Result: Orderbook always has top 20 levels from latest websocket snapshot
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.
If an update happens while fetching the snapshot? A snapshot is saved in the cache if not synced. So, it could be older than that if unsynced for a while.
I still think I understand, and if I do we don't need a cache, and if we do it only needs to be one snapshot, the latest. If the cache is being used ONLY in the case where an update comes in while we are processing the snapshot we asked for, then we should use something else. The new update should just wait to be applied.
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.
I think the processing logic can be simplified like this JoeGruffins@c9086d2
The updateQueue should be all we need to process updates in order. UNTESTED
db2ad3a to
77fcb9a
Compare
client/mm/libxc/mexc.go
Outdated
| if b.synced.Load() { | ||
| b.synced.Store(false) |
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 can be atomic using "Swap", currently it is not really as there is a gap between checking and setting. https://pkg.go.dev/sync/atomic#Bool.Swap
d56a1ee to
55d6d15
Compare
go tidy adds protobuf dependency for websocket data parsing of mexc api
55d6d15 to
96f54f2
Compare
go mod tidy adds protobuf dependency for websocket data parsing of mexc websocket market data api