Merge pull request #1541 from c9s/narumi/price-type

FEATURE: [rebalance] add price type
This commit is contained in:
なるみ 2024-02-23 20:32:09 +08:00 committed by GitHub
commit 9538a41c1b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 103 additions and 34 deletions

View File

@ -6,8 +6,8 @@ exchangeStrategies:
symbol: MAXTWD symbol: MAXTWD
schedule: "@every 1s" schedule: "@every 1s"
threshold: 200 threshold: 200
# price type: buy, sell, last or mid # price type: LAST, BUY, SELL, MID, TAKER, MAKER
priceType: buy priceType: BUY
# order quantity or amount # order quantity or amount
# quantity: 100 # quantity: 100

View File

@ -11,5 +11,6 @@ exchangeStrategies:
threshold: 1% threshold: 1%
maxAmount: 1_000 # max amount to buy or sell per order maxAmount: 1_000 # max amount to buy or sell per order
orderType: LIMIT_MAKER # LIMIT, LIMIT_MAKER or MARKET orderType: LIMIT_MAKER # LIMIT, LIMIT_MAKER or MARKET
priceType: MAKER # LAST, MID, TAKER or MAKER
dryRun: true dryRun: true
onStart: true onStart: true

View File

@ -18,8 +18,6 @@ const ID = "autobuy"
var log = logrus.WithField("strategy", ID) var log = logrus.WithField("strategy", ID)
var two = fixedpoint.NewFromInt(2)
func init() { func init() {
bbgo.RegisterStrategy(ID, &Strategy{}) bbgo.RegisterStrategy(ID, &Strategy{})
} }
@ -33,7 +31,7 @@ type Strategy struct {
Symbol string `json:"symbol"` Symbol string `json:"symbol"`
Schedule string `json:"schedule"` Schedule string `json:"schedule"`
Threshold fixedpoint.Value `json:"threshold"` Threshold fixedpoint.Value `json:"threshold"`
PriceType PriceType `json:"priceType"` PriceType types.PriceType `json:"priceType"`
Bollinger *types.BollingerSetting `json:"bollinger"` Bollinger *types.BollingerSetting `json:"bollinger"`
DryRun bool `json:"dryRun"` DryRun bool `json:"dryRun"`
@ -67,7 +65,7 @@ func (s *Strategy) Validate() error {
func (s *Strategy) Defaults() error { func (s *Strategy) Defaults() error {
if s.PriceType == "" { if s.PriceType == "" {
s.PriceType = PriceTypeBuy s.PriceType = types.PriceTypeMaker
} }
return nil return nil
} }
@ -122,19 +120,8 @@ func (s *Strategy) autobuy(ctx context.Context) {
return return
} }
var price fixedpoint.Value side := types.SideTypeBuy
switch s.PriceType { price := s.PriceType.Map(ticker, side)
case PriceTypeLast:
price = ticker.Last
case PriceTypeBuy:
price = ticker.Buy
case PriceTypeSell:
price = ticker.Sell
case PriceTypeMid:
price = ticker.Buy.Add(ticker.Sell).Div(two)
default:
price = ticker.Buy
}
if price.Float64() > s.boll.UpBand.Last(0) { if price.Float64() > s.boll.UpBand.Last(0) {
log.Infof("price %s is higher than upper band %f, skip", price.String(), s.boll.UpBand.Last(0)) log.Infof("price %s is higher than upper band %f, skip", price.String(), s.boll.UpBand.Last(0))
@ -150,7 +137,7 @@ func (s *Strategy) autobuy(ctx context.Context) {
quantity := s.CalculateQuantity(price) quantity := s.CalculateQuantity(price)
submitOrder := types.SubmitOrder{ submitOrder := types.SubmitOrder{
Symbol: s.Symbol, Symbol: s.Symbol,
Side: types.SideTypeBuy, Side: side,
Type: types.OrderTypeLimitMaker, Type: types.OrderTypeLimitMaker,
Quantity: quantity, Quantity: quantity,
Price: price, Price: price,

View File

@ -1,10 +0,0 @@
package autobuy
type PriceType string
const (
PriceTypeLast = PriceType("last")
PriceTypeBuy = PriceType("buy")
PriceTypeSell = PriceType("sell")
PriceTypeMid = PriceType("mid")
)

View File

@ -33,6 +33,7 @@ type Strategy struct {
Threshold fixedpoint.Value `json:"threshold"` Threshold fixedpoint.Value `json:"threshold"`
MaxAmount fixedpoint.Value `json:"maxAmount"` // max amount to buy or sell per order MaxAmount fixedpoint.Value `json:"maxAmount"` // max amount to buy or sell per order
OrderType types.OrderType `json:"orderType"` OrderType types.OrderType `json:"orderType"`
PriceType types.PriceType `json:"priceType"`
DryRun bool `json:"dryRun"` DryRun bool `json:"dryRun"`
OnStart bool `json:"onStart"` // rebalance on start OnStart bool `json:"onStart"` // rebalance on start
@ -46,6 +47,10 @@ func (s *Strategy) Defaults() error {
if s.OrderType == "" { if s.OrderType == "" {
s.OrderType = types.OrderTypeLimitMaker s.OrderType = types.OrderTypeLimitMaker
} }
if s.PriceType == "" {
s.PriceType = types.PriceTypeMaker
}
return nil return nil
} }
@ -243,12 +248,11 @@ func (s *Strategy) generateOrder(ctx context.Context) (*types.SubmitOrder, error
return nil, err return nil, err
} }
var price fixedpoint.Value price := s.PriceType.Map(ticker, side)
if side == types.SideTypeBuy { if side == types.SideTypeBuy {
price = ticker.Buy quantity = fixedpoint.Min(quantity, balances[s.QuoteCurrency].Available.Div(price))
quantity = fixedpoint.Min(quantity, balances[s.QuoteCurrency].Available.Div(ticker.Sell))
} else if side == types.SideTypeSell { } else if side == types.SideTypeSell {
price = ticker.Sell
quantity = fixedpoint.Min(quantity, balances[market.BaseCurrency].Available) quantity = fixedpoint.Min(quantity, balances[market.BaseCurrency].Available)
} }

87
pkg/types/price_type.go Normal file
View File

@ -0,0 +1,87 @@
package types
import (
"encoding/json"
"strings"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/pkg/errors"
)
type PriceType string
const (
PriceTypeLast PriceType = "LAST"
PriceTypeBuy PriceType = "BUY" // BID
PriceTypeSell PriceType = "SELL" // ASK
PriceTypeMid PriceType = "MID"
PriceTypeMaker PriceType = "MAKER"
PriceTypeTaker PriceType = "TAKER"
)
var ErrInvalidPriceType = errors.New("invalid price type")
func StrToPriceType(s string) (price PriceType, err error) {
switch strings.ToLower(s) {
case "last":
price = PriceTypeLast
case "buy":
price = PriceTypeBuy
case "sell":
price = PriceTypeSell
case "mid":
price = PriceTypeMid
case "maker":
price = PriceTypeMaker
case "taker":
price = PriceTypeTaker
default:
err = ErrInvalidPriceType
}
return price, err
}
func (p *PriceType) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
t, err := StrToPriceType(s)
if err != nil {
return err
}
*p = t
return nil
}
func (p PriceType) Map(ticker *Ticker, side SideType) fixedpoint.Value {
price := ticker.Last
switch p {
case PriceTypeLast:
price = ticker.Last
case PriceTypeBuy:
price = ticker.Buy
case PriceTypeSell:
price = ticker.Sell
case PriceTypeMid:
price = ticker.Buy.Add(ticker.Sell).Div(fixedpoint.NewFromInt(2))
case PriceTypeMaker:
if side == SideTypeBuy {
price = ticker.Buy
} else if side == SideTypeSell {
price = ticker.Sell
}
case PriceTypeTaker:
if side == SideTypeBuy {
price = ticker.Sell
} else if side == SideTypeSell {
price = ticker.Buy
}
}
return price
}