mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
Add xpuremaker skeleton
This commit is contained in:
parent
3721714f00
commit
1e12de28da
|
@ -1,6 +1,7 @@
|
||||||
---
|
---
|
||||||
imports:
|
imports:
|
||||||
- github.com/c9s/bbgo/pkg/strategy/buyandhold
|
- github.com/c9s/bbgo/pkg/strategy/buyandhold
|
||||||
|
- github.com/c9s/bbgo/pkg/strategy/xpuremaker
|
||||||
notifications:
|
notifications:
|
||||||
slack:
|
slack:
|
||||||
defaultChannel: "bbgo"
|
defaultChannel: "bbgo"
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
|
|
||||||
// import built-in strategies
|
// import built-in strategies
|
||||||
_ "github.com/c9s/bbgo/pkg/strategy/buyandhold"
|
_ "github.com/c9s/bbgo/pkg/strategy/buyandhold"
|
||||||
|
_ "github.com/c9s/bbgo/pkg/strategy/xpuremaker"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errSlackTokenUndefined = errors.New("slack token is not defined.")
|
var errSlackTokenUndefined = errors.New("slack token is not defined.")
|
||||||
|
|
182
pkg/strategy/xpuremaker/strategy.go
Normal file
182
pkg/strategy/xpuremaker/strategy.go
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
package xpuremaker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
bbgo.RegisterExchangeStrategy("xpuremaker", &Strategy{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type Strategy struct {
|
||||||
|
Symbol string `json:"symbol"`
|
||||||
|
Side string `json:"side"`
|
||||||
|
NumOrders int `json:"numOrders"`
|
||||||
|
BehindVolume fixedpoint.Value `json:"behindVolume"`
|
||||||
|
PriceTick fixedpoint.Value `json:"priceTick"`
|
||||||
|
BaseQuantity fixedpoint.Value `json:"baseQuantity"`
|
||||||
|
BuySellRatio float64 `json:"buySellRatio"`
|
||||||
|
|
||||||
|
book *types.StreamOrderBook
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(symbol string) *Strategy {
|
||||||
|
return &Strategy{
|
||||||
|
Symbol: symbol,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Strategy) Run(ctx context.Context, orderExecutor types.OrderExecutor, session *bbgo.ExchangeSession) error {
|
||||||
|
session.Subscribe(types.BookChannel, s.Symbol, types.SubscribeOptions{})
|
||||||
|
|
||||||
|
s.book = types.NewStreamBook(s.Symbol)
|
||||||
|
s.book.BindStream(session.Stream)
|
||||||
|
|
||||||
|
// We can move the go routine to the parent level.
|
||||||
|
go func() {
|
||||||
|
ticker := time.NewTicker(1 * time.Minute)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
|
||||||
|
case <-s.book.C:
|
||||||
|
s.book.C.Drain(2*time.Second, 5*time.Second)
|
||||||
|
s.update()
|
||||||
|
|
||||||
|
case <-ticker.C:
|
||||||
|
s.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
/*
|
||||||
|
session.Stream.OnKLineClosed(func(kline types.KLine) {
|
||||||
|
market, ok := session.Market(s.Symbol)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
quoteBalance, ok := session.Account.Balance(market.QuoteCurrency)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_ = quoteBalance
|
||||||
|
|
||||||
|
err := orderExecutor.SubmitOrder(ctx, types.SubmitOrder{
|
||||||
|
Symbol: kline.Symbol,
|
||||||
|
Side: types.SideTypeBuy,
|
||||||
|
Type: types.OrderTypeMarket,
|
||||||
|
Quantity: 0.01,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("submit order error")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
*/
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Strategy) update() {
|
||||||
|
switch s.Side {
|
||||||
|
case "buy":
|
||||||
|
s.updateOrders(types.SideTypeBuy)
|
||||||
|
case "sell":
|
||||||
|
s.updateOrders(types.SideTypeSell)
|
||||||
|
case "both":
|
||||||
|
s.updateOrders(types.SideTypeBuy)
|
||||||
|
s.updateOrders(types.SideTypeSell)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Strategy) updateOrders(side types.SideType) {
|
||||||
|
book := s.book.Copy()
|
||||||
|
|
||||||
|
var pvs types.PriceVolumeSlice
|
||||||
|
|
||||||
|
switch side {
|
||||||
|
case types.SideTypeBuy:
|
||||||
|
pvs = book.Bids
|
||||||
|
case types.SideTypeSell:
|
||||||
|
pvs = book.Asks
|
||||||
|
}
|
||||||
|
|
||||||
|
if pvs == nil || len(pvs) == 0 {
|
||||||
|
log.Warn("empty bids or asks")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
index := pvs.IndexByVolumeDepth(s.BehindVolume)
|
||||||
|
if index == -1 {
|
||||||
|
// do not place orders
|
||||||
|
log.Warn("depth is not enough")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var price = pvs[index].Price
|
||||||
|
var orders = s.generateOrders(s.Symbol, side, price, s.PriceTick, s.BaseQuantity, s.NumOrders)
|
||||||
|
if len(orders) == 0 {
|
||||||
|
log.Warn("empty orders")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Infof("submitting %d orders", len(orders))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Strategy) generateOrders(symbol string, side types.SideType, price, priceTick, baseVolume fixedpoint.Value, numOrders int) (orders []types.SubmitOrder) {
|
||||||
|
var expBase = fixedpoint.NewFromFloat(0.0)
|
||||||
|
|
||||||
|
switch side {
|
||||||
|
case types.SideTypeBuy:
|
||||||
|
if priceTick > 0 {
|
||||||
|
priceTick = -priceTick
|
||||||
|
}
|
||||||
|
|
||||||
|
case types.SideTypeSell:
|
||||||
|
if priceTick < 0 {
|
||||||
|
priceTick = -priceTick
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < numOrders; i++ {
|
||||||
|
volume := math.Exp(expBase.Float64()) * baseVolume.Float64()
|
||||||
|
|
||||||
|
// skip order less than 10usd
|
||||||
|
if volume*price.Float64() < 10.0 {
|
||||||
|
log.Warnf("amount too small (< 10usd). price=%f volume=%f amount=%f", price.Float64(), volume, volume*price.Float64())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
orders = append(orders, types.SubmitOrder{
|
||||||
|
Symbol: symbol,
|
||||||
|
Side: side,
|
||||||
|
Type: types.OrderTypeLimit,
|
||||||
|
Price: price.Float64(),
|
||||||
|
Quantity: volume,
|
||||||
|
})
|
||||||
|
|
||||||
|
log.Infof("%s order: %.2f @ %.3f", side, volume, price.Float64())
|
||||||
|
|
||||||
|
if len(orders) >= numOrders {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
price = price + priceTick
|
||||||
|
declog := math.Log10(math.Abs(priceTick.Float64()))
|
||||||
|
expBase += fixedpoint.NewFromFloat(math.Pow10(-int(declog)) * math.Abs(priceTick.Float64()))
|
||||||
|
log.Infof("expBase: %f", expBase.Float64())
|
||||||
|
}
|
||||||
|
|
||||||
|
return orders
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user