-
Notifications
You must be signed in to change notification settings - Fork 100
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
client/{mm, core}: Simple Arbitrage #2480
Conversation
15ce252
to
80b6d42
Compare
80b6d42
to
8f28450
Compare
client/mm/libxc/binance.go
Outdated
// Trade executes a trade on the CEX. updaterID takes an ID returned from | ||
// SubscribeTradeUpdates, and tradeID takes an ID returned from | ||
// GenerateTradeID. | ||
func (bnc *binance) Trade(baseSymbol, quoteSymbol string, sell bool, rate, qty uint64, updaterID int, orderID string) error { |
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.
Comment says tradeID but there is no argument by that name.
Should this check that orderID is a valid order ID? Or should the variable be called tradeID? Then should it check it is the correct length? Should it check that it is unique in the bnc.tradeToUpdater
map?
return 0, 0, false, nil | ||
} | ||
|
||
return weightedSum / lots, extrema, true, nil |
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 remember seeing this code before and commenting that, if the book was sparse, would that allow an attacker to place some orders near the mid gap and then one order way far back, the bot buys them all up because the average looks good, the attacker then doesn't follow through with the extrema trades and just leaves the one at a bad rate. Was this a valid concern? I think my solution was to prevent orders that are too far from the extrema in these calculations.
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 code here makes sure that each lot included in the arbitrage must be profitable, not just the average:
dcrdex/client/mm/mm_simple_arb.go
Lines 218 to 223 in 8f28450
var currLotProfitable bool | |
if sellOnDEX { | |
currLotProfitable = dexExtrema > cexExtrema | |
} else { | |
currLotProfitable = cexExtrema > dexExtrema | |
} |
This would avoid the attack you are talking about right?
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.
Oh that's right, the extrema is the worst rate for us, I was wording it as best. Unless both markets are sparse, then Yes this should do about the same thing as I suggested. Would this be even too restrictive? Orders will probably be further apart on dex... If I am understanding correctly.
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 guess we could do something like buying 1/2 a lots worth on the CEX and a full lots worth on the DEX (since we can't buy any less), but maybe save that for a future iteration. This probably is a good idea, especially for markets with a large lot size, since it will be rare that a full lot can be arbitraged.
Unless it's someone who is running the CEX trying to manipulate someone running the arb bot, I don't think it's possible. If somehow they trick us into taking a really bad trade on the DEX, then they would've had to also trick us into taking a really good trade on the CEX. Unless they are running the CEX, they would not be able to back out of the CEX trade like they could on the DEX.
8f28450
to
3220ec2
Compare
cd492e6
to
5cbe3ae
Compare
client/mm/libxc/binance.go
Outdated
bnc.tradeToUpdater[tradeID] = updaterID | ||
bnc.tradeUpdaterMtx.Unlock() | ||
|
||
return bnc.postAPI(ctx, "/api/v3/order", v, nil, true, true, &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.
Should we be adding the updaterID
to the map if the request fails?
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 should be added to the map beforehand, because an update may arrive before postAPI
returns, but we should be removing it if it fails.
} | ||
} | ||
|
||
// keep retrying if failed to cancel? |
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. I guess so.
6a6c0df
to
42dce09
Compare
Looks ready to me. Looking for a rebase and a thumbs up from @JoeGruffins. |
This implements the simple arbitrage opportunity which only places orders when there is an arbitrage opportunity. - A `libxc` package is added which contains a `CEX` interface used to interact with a centralized exchange's API. It is implemented for Binance. - The new strategy is implemented in `mm_simple_arb.go` and can be run by creating a `BotConfig` with a non-nil `ArbCfg`. - A testbinance command line tool is added which starts a webserver that responds to the requests that the Binance testnet does not support. - A `VWAP` function is added to the client orderbook. - `client/comms/WSConn` is updated with a `SendRaw` function which sends arbitrary byte slices over the websocket connection.
42dce09
to
6f74e0c
Compare
6f74e0c
to
35091e7
Compare
This implements the simple arbitrage strategy which only places orders
when there is an arbitrage opportunity.
libxc
package is added which contains aCEX
interface used tointeract with a centralized exchange's API. It is implemented for
Binance.
mm_simple_arb.go
and can be run bycreating a
BotConfig
with a non-nilArbCfg
.responds to the requests that the Binance testnet does not support.
VWAP
function is added to the client orderbook.client/comms/WSConn
is updated with aSendRaw
function which sendsarbitrary byte slices over the websocket connection.