Skip to content

Commit

Permalink
Use MultiTrade instead of Trade
Browse files Browse the repository at this point in the history
  • Loading branch information
martonp committed Aug 27, 2023
1 parent 7e4ecf9 commit 3220ec2
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 31 deletions.
6 changes: 3 additions & 3 deletions client/mm/libxc/binance_live_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import (
var (
log = dex.StdOutLogger("T", dex.LevelTrace)
u, _ = user.Current()
apiKey = "OBV9Z4i5hnORfyLLBLKeO5k5DUkfiuPIrbvRltPTEfcjwyMZAhTckGrlo42q472n"
apiSecret = "EAws4Ke02lo4qenzIZD8OPthDqy7J7DpAVIo0ibJQnLDpteFAj7U76HGpt1Agws0"
apiKey = ""
apiSecret = ""
)

func tNewBinance(t *testing.T, network dex.Network) *binance {
Expand Down Expand Up @@ -116,7 +116,7 @@ func TestTrade(t *testing.T) {
}
}()
tradeID := bnc.GenerateTradeID()
err = bnc.Trade(ctx, "eth", "btc", false, 62e4, 1e8, updaterID, tradeID)
err = bnc.Trade(ctx, "eth", "btc", true, 6327e2, 1e8, updaterID, tradeID)
if err != nil {
t.Fatalf("trade error: %v", err)
}
Expand Down
42 changes: 31 additions & 11 deletions client/mm/mm_simple_arb.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ type SimpleArbConfig struct {
// NumEpochsLeaveOpen is the number of epochs an arbitrage sequence will
// stay open if one or both of the orders were not filled.
NumEpochsLeaveOpen uint32 `json:"numEpochsLeaveOpen"`
// BaseOptions are the multi-order options for the base asset wallet.
BaseOptions map[string]string `json:"baseOptions"`
// QuoteOptions are the multi-order options for the quote asset wallet.
QuoteOptions map[string]string `json:"quoteOptions"`
}

func (c *SimpleArbConfig) Validate() error {
Expand Down Expand Up @@ -274,17 +278,33 @@ func (a *simpleArbMarketMaker) executeArb(sellOnDex bool, lotsToArb, dexRate, ce
return
}

dexOrder, err := a.core.Trade(nil, &core.TradeForm{
Host: a.host,
IsLimit: true,
Sell: sellOnDex,
Base: a.base,
Quote: a.quote,
Qty: lotsToArb * a.mkt.LotSize,
Rate: dexRate,
var options map[string]string
if sellOnDex {
options = a.cfg.BaseOptions
} else {
options = a.cfg.QuoteOptions
}

dexOrders, err := a.core.MultiTrade(nil, &core.MultiTradeForm{
Host: a.host,
Sell: sellOnDex,
Base: a.base,
Quote: a.quote,
Placements: []*core.QtyRate{
{
Qty: lotsToArb * a.mkt.LotSize,
Rate: dexRate,
},
},
Options: options,
})
if err != nil {
a.log.Errorf("error placing dex order: %v", err)
if err != nil || len(dexOrders) != 1 {
if err != nil {
a.log.Errorf("error placing dex order: %v", err)
}
if len(dexOrders) != 1 {
a.log.Errorf("expected 1 dex order, got %v", len(dexOrders))
}

err := a.cex.CancelTrade(a.ctx, dex.BipIDSymbol(a.base), dex.BipIDSymbol(a.quote), cexTradeID)
if err != nil {
Expand All @@ -295,7 +315,7 @@ func (a *simpleArbMarketMaker) executeArb(sellOnDex bool, lotsToArb, dexRate, ce
}

a.activeArbs = append(a.activeArbs, &arbSequence{
dexOrder: dexOrder,
dexOrder: dexOrders[0],
dexRate: dexRate,
cexOrderID: cexTradeID,
cexRate: cexRate,
Expand Down
42 changes: 25 additions & 17 deletions client/mm/mm_simple_arb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,25 +77,24 @@ func (c *tCEX) Balance(symbol string) (*libxc.ExchangeBalance, error) {
func (c *tCEX) GenerateTradeID() string {
return c.tradeID
}
func (c *tCEX) Trade(baseSymbol, quoteSymbol string, sell bool, rate, qty uint64, updaterID int, orderID string) error {
func (c *tCEX) Trade(ctx context.Context, baseSymbol, quoteSymbol string, sell bool, rate, qty uint64, updaterID int, orderID string) error {
if c.tradeErr != nil {
return c.tradeErr
}
c.lastTrade = &cexOrder{baseSymbol, quoteSymbol, qty, rate, sell}
return nil
}
func (c *tCEX) CancelTrade(baseSymbol, quoteSymbol, tradeID string) error {
func (c *tCEX) CancelTrade(ctx context.Context, baseSymbol, quoteSymbol, tradeID string) error {
if c.cancelTradeErr != nil {
return c.cancelTradeErr
}
c.cancelledTrades = append(c.cancelledTrades, tradeID)
return nil
}
func (c *tCEX) SubscribeMarket(baseSymbol, quoteSymbol string) error {
func (c *tCEX) SubscribeMarket(ctx context.Context, baseSymbol, quoteSymbol string) error {
return nil
}
func (c *tCEX) UnsubscribeMarket(baseSymbol, quoteSymbol string) error {
return nil
func (c *tCEX) UnsubscribeMarket(baseSymbol, quoteSymbol string) {
}
func (c *tCEX) VWAP(baseSymbol, quoteSymbol string, sell bool, qty uint64) (vwap, extrema uint64, filled bool, err error) {
if c.vwapErr != nil {
Expand All @@ -116,11 +115,11 @@ func (c *tCEX) VWAP(baseSymbol, quoteSymbol string, sell bool, qty uint64) (vwap
}
return res.avg, res.extrema, true, nil
}
func (c *tCEX) SubscribeTradeUpdates() (<-chan *libxc.TradeUpdate, int) {
return c.tradeUpdates, c.tradeUpdatesID
func (c *tCEX) SubscribeTradeUpdates() (<-chan *libxc.TradeUpdate, func(), int) {
return c.tradeUpdates, func() {}, c.tradeUpdatesID
}
func (c *tCEX) SubscribeCEXUpdates() <-chan interface{} {
return nil
func (c *tCEX) SubscribeCEXUpdates() (<-chan interface{}, func()) {
return nil, func() {}
}

var _ libxc.CEX = (*tCEX)(nil)
Expand Down Expand Up @@ -844,8 +843,10 @@ func TestArbRebalance(t *testing.T) {
tCore.maxSellErr = test.dexMaxSellErr
tCore.maxBuyErr = test.dexMaxBuyErr
if test.expectedDexOrder != nil {
tCore.tradeResult = &core.Order{
ID: encode.RandomBytes(32),
tCore.multiTradeResult = []*core.Order{
{
ID: encode.RandomBytes(32),
},
}
}

Expand Down Expand Up @@ -905,25 +906,32 @@ func TestArbRebalance(t *testing.T) {
}
if test.expectedDexOrder != nil {
if test.expectedDexOrder.sell {
if len(tCore.sellsPlaced) != 1 {
if len(tCore.multiTradesPlaced[0].Placements) != 1 {
t.Fatalf("%s: expected 1 sell order but got %d", test.name, len(tCore.sellsPlaced))
}
if test.expectedDexOrder.rate != tCore.sellsPlaced[0].Rate {
if !tCore.multiTradesPlaced[0].Sell {
t.Fatalf("%s: expected sell order but got buy order", test.name)
}
if test.expectedDexOrder.rate != tCore.multiTradesPlaced[0].Placements[0].Rate {
t.Fatalf("%s: expected sell order rate %d but got %d", test.name, test.expectedDexOrder.rate, tCore.sellsPlaced[0].Rate)
}
if test.expectedDexOrder.lots*mkt.LotSize != tCore.sellsPlaced[0].Qty {
if test.expectedDexOrder.lots*mkt.LotSize != tCore.multiTradesPlaced[0].Placements[0].Qty {
t.Fatalf("%s: expected sell order qty %d but got %d", test.name, test.expectedDexOrder.lots*mkt.LotSize, tCore.sellsPlaced[0].Qty)
}
}

if !test.expectedDexOrder.sell {
if len(tCore.buysPlaced) != 1 {
fmt.Printf("multi trades placed: %v\n", tCore.multiTradesPlaced)
if len(tCore.multiTradesPlaced[0].Placements) != 1 {
t.Fatalf("%s: expected 1 buy order but got %d", test.name, len(tCore.buysPlaced))
}
if test.expectedDexOrder.rate != tCore.buysPlaced[0].Rate {
if tCore.multiTradesPlaced[0].Sell {
t.Fatalf("%s: expected buy order but got sell order", test.name)
}
if test.expectedDexOrder.rate != tCore.multiTradesPlaced[0].Placements[0].Rate {
t.Fatalf("%s: expected buy order rate %d but got %d", test.name, test.expectedDexOrder.rate, tCore.buysPlaced[0].Rate)
}
if test.expectedDexOrder.lots*mkt.LotSize != tCore.buysPlaced[0].Qty {
if test.expectedDexOrder.lots*mkt.LotSize != tCore.multiTradesPlaced[0].Placements[0].Qty {
t.Fatalf("%s: expected buy order qty %d but got %d", test.name, test.expectedDexOrder.lots*mkt.LotSize, tCore.buysPlaced[0].Qty)
}
}
Expand Down
7 changes: 7 additions & 0 deletions client/mm/sample-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
"profitTrigger": 0.01,
"maxActiveArbs": 5,
"numEpochsLeaveOpen": 5
},
"baseOptions": {
"multisplit": "true"
},
"quoteOptions": {
"multisplit": "true",
"multisplitbuffer": "5"
}
}
],
Expand Down

0 comments on commit 3220ec2

Please sign in to comment.