Skip to content

Commit

Permalink
extract placeOrders method
Browse files Browse the repository at this point in the history
  • Loading branch information
narumiruna committed Jan 6, 2024
1 parent cb87467 commit 2c52b11
Showing 1 changed file with 117 additions and 113 deletions.
230 changes: 117 additions & 113 deletions pkg/strategy/xgap/strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,128 +250,132 @@ func (s *Strategy) CrossRun(ctx context.Context, _ bbgo.OrderExecutionRouter, se
time.Sleep(delay)
}

bestBid, hasBid := s.tradingBook.BestBid()
bestAsk, hasAsk := s.tradingBook.BestAsk()

// try to use the bid/ask price from the trading book
if hasBid && hasAsk {
var spread = bestAsk.Price.Sub(bestBid.Price)
var spreadPercentage = spread.Div(bestAsk.Price)
log.Infof("trading book spread=%s %s",
spread.String(), spreadPercentage.Percentage())

// use the source book price if the spread percentage greater than 10%
if spreadPercentage.Compare(StepPercentageGap) > 0 {
log.Warnf("spread too large (%s %s), using source book",
spread.String(), spreadPercentage.Percentage())
bestBid, hasBid = s.sourceBook.BestBid()
bestAsk, hasAsk = s.sourceBook.BestAsk()
}

if s.MinSpread.Sign() > 0 {
if spread.Compare(s.MinSpread) < 0 {
log.Warnf("spread < min spread, spread=%s minSpread=%s bid=%s ask=%s",
spread.String(), s.MinSpread.String(),
bestBid.Price.String(), bestAsk.Price.String())
continue
}
}

// if the spread is less than 100 ticks (100 pips), skip
if spread.Compare(s.tradingMarket.TickSize.MulExp(2)) < 0 {
log.Warnf("spread too small, we can't place orders: spread=%v bid=%v ask=%v",
spread, bestBid.Price, bestAsk.Price)
continue
}

} else {
bestBid, hasBid = s.sourceBook.BestBid()
bestAsk, hasAsk = s.sourceBook.BestAsk()
}
s.placeOrders(ctx)

if !hasBid || !hasAsk {
log.Warn("no bids or asks on the source book or the trading book")
continue
}
s.cancelOrders(ctx)
}
}
}()

var spread = bestAsk.Price.Sub(bestBid.Price)
var spreadPercentage = spread.Div(bestAsk.Price)
log.Infof("spread=%v %s ask=%v bid=%v",
spread, spreadPercentage.Percentage(),
bestAsk.Price, bestBid.Price)
// var spreadPercentage = spread.Float64() / bestBid.Price.Float64()

var midPrice = bestAsk.Price.Add(bestBid.Price).Div(Two)
var price = midPrice

log.Infof("mid price %v", midPrice)

var balances = s.tradingSession.GetAccount().Balances()
var quantity = s.tradingMarket.MinQuantity

if s.Quantity.Sign() > 0 {
quantity = fixedpoint.Min(s.Quantity, s.tradingMarket.MinQuantity)
} else if s.SimulateVolume {
s.mu.Lock()
if s.lastTradingKLine.Volume.Sign() > 0 && s.lastSourceKLine.Volume.Sign() > 0 {
volumeDiff := s.lastSourceKLine.Volume.Sub(s.lastTradingKLine.Volume)
// change the current quantity only diff is positive
if volumeDiff.Sign() > 0 {
quantity = volumeDiff
}

if baseBalance, ok := balances[s.tradingMarket.BaseCurrency]; ok {
quantity = fixedpoint.Min(quantity, baseBalance.Available)
}

if quoteBalance, ok := balances[s.tradingMarket.QuoteCurrency]; ok {
maxQuantity := quoteBalance.Available.Div(price)
quantity = fixedpoint.Min(quantity, maxQuantity)
}
}
s.mu.Unlock()
} else {
// plus a 2% quantity jitter
jitter := 1.0 + math.Max(0.02, rand.Float64())
quantity = quantity.Mul(fixedpoint.NewFromFloat(jitter))
}
return nil
}

var quoteAmount = price.Mul(quantity)
if quoteAmount.Compare(s.tradingMarket.MinNotional) <= 0 {
quantity = fixedpoint.Max(
s.tradingMarket.MinQuantity,
s.tradingMarket.MinNotional.Mul(NotionModifier).Div(price))
}
func (s *Strategy) placeOrders(ctx context.Context) {
bestBid, hasBid := s.tradingBook.BestBid()
bestAsk, hasAsk := s.tradingBook.BestAsk()

// try to use the bid/ask price from the trading book
if hasBid && hasAsk {
var spread = bestAsk.Price.Sub(bestBid.Price)
var spreadPercentage = spread.Div(bestAsk.Price)
log.Infof("trading book spread=%s %s",
spread.String(), spreadPercentage.Percentage())

// use the source book price if the spread percentage greater than 10%
if spreadPercentage.Compare(StepPercentageGap) > 0 {
log.Warnf("spread too large (%s %s), using source book",
spread.String(), spreadPercentage.Percentage())
bestBid, hasBid = s.sourceBook.BestBid()
bestAsk, hasAsk = s.sourceBook.BestAsk()
}

orderForm := []types.SubmitOrder{{
Symbol: s.Symbol,
Side: types.SideTypeBuy,
Type: types.OrderTypeLimit,
Quantity: quantity,
Price: price,
Market: s.tradingMarket,
}, {
Symbol: s.Symbol,
Side: types.SideTypeSell,
Type: types.OrderTypeLimit,
Quantity: quantity,
Price: price,
Market: s.tradingMarket,
}}
createdOrders, err := s.OrderExecutor.SubmitOrders(ctx, orderForm...)
if err != nil {
log.WithError(err).Error("order submit error")
}
log.Infof("created orders: %+v", createdOrders)
if s.MinSpread.Sign() > 0 {
if spread.Compare(s.MinSpread) < 0 {
log.Warnf("spread < min spread, spread=%s minSpread=%s bid=%s ask=%s",
spread.String(), s.MinSpread.String(),
bestBid.Price.String(), bestAsk.Price.String())
return
}
}

time.Sleep(time.Second)
// if the spread is less than 100 ticks (100 pips), skip
if spread.Compare(s.tradingMarket.TickSize.MulExp(2)) < 0 {
log.Warnf("spread too small, we can't place orders: spread=%v bid=%v ask=%v",
spread, bestBid.Price, bestAsk.Price)
return
}

s.cancelOrders(ctx)
} else {
bestBid, hasBid = s.sourceBook.BestBid()
bestAsk, hasAsk = s.sourceBook.BestAsk()
}

if !hasBid || !hasAsk {
log.Warn("no bids or asks on the source book or the trading book")
return
}

var spread = bestAsk.Price.Sub(bestBid.Price)
var spreadPercentage = spread.Div(bestAsk.Price)
log.Infof("spread=%v %s ask=%v bid=%v",
spread, spreadPercentage.Percentage(),
bestAsk.Price, bestBid.Price)
// var spreadPercentage = spread.Float64() / bestBid.Price.Float64()

var midPrice = bestAsk.Price.Add(bestBid.Price).Div(Two)
var price = midPrice

log.Infof("mid price %v", midPrice)

var balances = s.tradingSession.GetAccount().Balances()
var quantity = s.tradingMarket.MinQuantity

if s.Quantity.Sign() > 0 {
quantity = fixedpoint.Min(s.Quantity, s.tradingMarket.MinQuantity)
} else if s.SimulateVolume {
s.mu.Lock()
if s.lastTradingKLine.Volume.Sign() > 0 && s.lastSourceKLine.Volume.Sign() > 0 {
volumeDiff := s.lastSourceKLine.Volume.Sub(s.lastTradingKLine.Volume)
// change the current quantity only diff is positive
if volumeDiff.Sign() > 0 {
quantity = volumeDiff
}

if baseBalance, ok := balances[s.tradingMarket.BaseCurrency]; ok {
quantity = fixedpoint.Min(quantity, baseBalance.Available)
}

if quoteBalance, ok := balances[s.tradingMarket.QuoteCurrency]; ok {
maxQuantity := quoteBalance.Available.Div(price)
quantity = fixedpoint.Min(quantity, maxQuantity)
}
}
}()
s.mu.Unlock()
} else {
// plus a 2% quantity jitter
jitter := 1.0 + math.Max(0.02, rand.Float64())
quantity = quantity.Mul(fixedpoint.NewFromFloat(jitter))
}

return nil
var quoteAmount = price.Mul(quantity)
if quoteAmount.Compare(s.tradingMarket.MinNotional) <= 0 {
quantity = fixedpoint.Max(
s.tradingMarket.MinQuantity,
s.tradingMarket.MinNotional.Mul(NotionModifier).Div(price))
}

orderForm := []types.SubmitOrder{{
Symbol: s.Symbol,
Side: types.SideTypeBuy,
Type: types.OrderTypeLimit,
Quantity: quantity,
Price: price,
Market: s.tradingMarket,
}, {
Symbol: s.Symbol,
Side: types.SideTypeSell,
Type: types.OrderTypeLimit,
Quantity: quantity,
Price: price,
Market: s.tradingMarket,
}}
createdOrders, err := s.OrderExecutor.SubmitOrders(ctx, orderForm...)
if err != nil {
log.WithError(err).Error("order submit error")
}
log.Infof("created orders: %+v", createdOrders)

time.Sleep(time.Second)
}

func (s *Strategy) cancelOrders(ctx context.Context) {
Expand Down

0 comments on commit 2c52b11

Please sign in to comment.