mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 00:35:15 +00:00
add grid2 strategy
This commit is contained in:
parent
4825fb8d0e
commit
cb612a22b1
|
@ -17,6 +17,7 @@ import (
|
|||
_ "github.com/c9s/bbgo/pkg/strategy/fmaker"
|
||||
_ "github.com/c9s/bbgo/pkg/strategy/funding"
|
||||
_ "github.com/c9s/bbgo/pkg/strategy/grid"
|
||||
_ "github.com/c9s/bbgo/pkg/strategy/grid2"
|
||||
_ "github.com/c9s/bbgo/pkg/strategy/harmonic"
|
||||
_ "github.com/c9s/bbgo/pkg/strategy/irr"
|
||||
_ "github.com/c9s/bbgo/pkg/strategy/kline"
|
||||
|
|
164
pkg/strategy/grid2/strategy.go
Normal file
164
pkg/strategy/grid2/strategy.go
Normal file
|
@ -0,0 +1,164 @@
|
|||
package grid2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/bbgo"
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
"github.com/c9s/bbgo/pkg/util"
|
||||
)
|
||||
|
||||
const ID = "grid2"
|
||||
|
||||
var log = logrus.WithField("strategy", ID)
|
||||
|
||||
var notionalModifier = fixedpoint.NewFromFloat(1.0001)
|
||||
|
||||
func init() {
|
||||
// Register the pointer of the strategy struct,
|
||||
// so that bbgo knows what struct to be used to unmarshal the configs (YAML or JSON)
|
||||
// Note: built-in strategies need to imported manually in the bbgo cmd package.
|
||||
bbgo.RegisterStrategy(ID, &Strategy{})
|
||||
}
|
||||
|
||||
type Strategy struct {
|
||||
// Market stores the configuration of the market, for example, VolumePrecision, PricePrecision, MinLotSize... etc
|
||||
// This field will be injected automatically since we defined the Symbol field.
|
||||
types.Market `json:"-" yaml:"-"`
|
||||
|
||||
// These fields will be filled from the config file (it translates YAML to JSON)
|
||||
Symbol string `json:"symbol" yaml:"symbol"`
|
||||
|
||||
// ProfitSpread is the fixed profit spread you want to submit the sell order
|
||||
ProfitSpread fixedpoint.Value `json:"profitSpread" yaml:"profitSpread"`
|
||||
|
||||
// GridNum is the grid number, how many orders you want to post on the orderbook.
|
||||
GridNum int64 `json:"gridNumber" yaml:"gridNumber"`
|
||||
|
||||
UpperPrice fixedpoint.Value `json:"upperPrice" yaml:"upperPrice"`
|
||||
|
||||
LowerPrice fixedpoint.Value `json:"lowerPrice" yaml:"lowerPrice"`
|
||||
|
||||
bbgo.QuantityOrAmount
|
||||
|
||||
ProfitStats *types.ProfitStats `persistence:"profit_stats"`
|
||||
Position *types.Position `persistence:"position"`
|
||||
|
||||
// orderStore is used to store all the created orders, so that we can filter the trades.
|
||||
orderStore *bbgo.OrderStore
|
||||
|
||||
// activeOrders is the locally maintained active order book of the maker orders.
|
||||
activeOrders *bbgo.ActiveOrderBook
|
||||
|
||||
tradeCollector *bbgo.TradeCollector
|
||||
|
||||
// groupID is the group ID used for the strategy instance for canceling orders
|
||||
groupID uint32
|
||||
}
|
||||
|
||||
func (s *Strategy) ID() string {
|
||||
return ID
|
||||
}
|
||||
|
||||
func (s *Strategy) Validate() error {
|
||||
if s.UpperPrice.IsZero() {
|
||||
return errors.New("upperPrice can not be zero, you forgot to set?")
|
||||
}
|
||||
|
||||
if s.LowerPrice.IsZero() {
|
||||
return errors.New("lowerPrice can not be zero, you forgot to set?")
|
||||
}
|
||||
|
||||
if s.UpperPrice.Compare(s.LowerPrice) <= 0 {
|
||||
return fmt.Errorf("upperPrice (%s) should not be less than or equal to lowerPrice (%s)", s.UpperPrice.String(), s.LowerPrice.String())
|
||||
}
|
||||
|
||||
if s.ProfitSpread.Sign() <= 0 {
|
||||
// If profitSpread is empty or its value is negative
|
||||
return fmt.Errorf("profit spread should bigger than 0")
|
||||
}
|
||||
|
||||
if s.GridNum == 0 {
|
||||
return fmt.Errorf("gridNum can not be zero")
|
||||
}
|
||||
|
||||
if err := s.QuantityOrAmount.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {
|
||||
session.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{Interval: "1m"})
|
||||
}
|
||||
|
||||
// InstanceID returns the instance identifier from the current grid configuration parameters
|
||||
func (s *Strategy) InstanceID() string {
|
||||
return fmt.Sprintf("%s-%s-%d-%d-%d", ID, s.Symbol, s.GridNum, s.UpperPrice.Int(), s.LowerPrice.Int())
|
||||
}
|
||||
|
||||
func (s *Strategy) handleOrderFilled(o types.Order) {
|
||||
|
||||
}
|
||||
|
||||
func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
|
||||
instanceID := s.InstanceID()
|
||||
|
||||
s.groupID = util.FNV32(instanceID)
|
||||
|
||||
log.Infof("using group id %d from fnv(%s)", s.groupID, instanceID)
|
||||
|
||||
if s.ProfitStats == nil {
|
||||
s.ProfitStats = types.NewProfitStats(s.Market)
|
||||
}
|
||||
|
||||
if s.Position == nil {
|
||||
s.Position = types.NewPositionFromMarket(s.Market)
|
||||
}
|
||||
|
||||
s.orderStore = bbgo.NewOrderStore(s.Symbol)
|
||||
s.orderStore.BindStream(session.UserDataStream)
|
||||
|
||||
// we don't persist orders so that we can not clear the previous orders for now. just need time to support this.
|
||||
s.activeOrders = bbgo.NewActiveOrderBook(s.Symbol)
|
||||
s.activeOrders.OnFilled(s.handleOrderFilled)
|
||||
s.activeOrders.BindStream(session.UserDataStream)
|
||||
|
||||
s.tradeCollector = bbgo.NewTradeCollector(s.Symbol, s.Position, s.orderStore)
|
||||
|
||||
s.tradeCollector.OnTrade(func(trade types.Trade, profit, netProfit fixedpoint.Value) {
|
||||
bbgo.Notify(trade)
|
||||
s.ProfitStats.AddTrade(trade)
|
||||
})
|
||||
|
||||
s.tradeCollector.OnPositionUpdate(func(position *types.Position) {
|
||||
bbgo.Notify(position)
|
||||
})
|
||||
|
||||
s.tradeCollector.BindStream(session.UserDataStream)
|
||||
|
||||
bbgo.OnShutdown(ctx, func(ctx context.Context, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
bbgo.Sync(ctx, s)
|
||||
|
||||
// now we can cancel the open orders
|
||||
log.Infof("canceling active orders...")
|
||||
if err := session.Exchange.CancelOrders(context.Background(), s.activeOrders.Orders()...); err != nil {
|
||||
log.WithError(err).Errorf("cancel order error")
|
||||
}
|
||||
})
|
||||
|
||||
session.UserDataStream.OnStart(func() {
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user