mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
improve legacy state handling and move fnv
This commit is contained in:
parent
7378c63cb7
commit
019e6a2a88
|
@ -8,14 +8,13 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/indicator"
|
"github.com/c9s/bbgo/pkg/indicator"
|
||||||
|
"github.com/c9s/bbgo/pkg/util"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
"github.com/c9s/bbgo/pkg/exchange/max"
|
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
"github.com/c9s/bbgo/pkg/service"
|
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,9 +36,12 @@ func init() {
|
||||||
bbgo.RegisterStrategy(ID, &Strategy{})
|
bbgo.RegisterStrategy(ID, &Strategy{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: State is deprecated, please use the persistence tag
|
||||||
type State struct {
|
type State struct {
|
||||||
// Deprecated: position is deprecated, please define the Position field in the strategy struct directly.
|
// Deprecated: Position is deprecated, please define the Position field in the strategy struct directly.
|
||||||
Position *types.Position `json:"position,omitempty"`
|
Position *types.Position `json:"position,omitempty"`
|
||||||
|
|
||||||
|
// Deprecated: ProfitStats is deprecated, please define the ProfitStats field in the strategy struct directly.
|
||||||
ProfitStats types.ProfitStats `json:"profitStats,omitempty"`
|
ProfitStats types.ProfitStats `json:"profitStats,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,8 +150,9 @@ type Strategy struct {
|
||||||
|
|
||||||
state *State
|
state *State
|
||||||
|
|
||||||
// TODO: we're moving position from state to outside
|
// persistence fields
|
||||||
Position *types.Position `json:"position,omitempty" persistence:"position"`
|
Position *types.Position `json:"position,omitempty" persistence:"position"`
|
||||||
|
ProfitStats *types.ProfitStats `json:"profitStats,omitempty" persistence:"profit_stats"`
|
||||||
|
|
||||||
activeMakerOrders *bbgo.LocalActiveOrderBook
|
activeMakerOrders *bbgo.LocalActiveOrderBook
|
||||||
orderStore *bbgo.OrderStore
|
orderStore *bbgo.OrderStore
|
||||||
|
@ -173,6 +176,10 @@ func (s *Strategy) ID() string {
|
||||||
return ID
|
return ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Strategy) InstanceID() string {
|
||||||
|
return fmt.Sprintf("%s:%s", ID, s.Symbol)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Strategy) Initialize() error {
|
func (s *Strategy) Initialize() error {
|
||||||
return s.SmartStops.InitializeStopControllers(s.Symbol)
|
return s.SmartStops.InitializeStopControllers(s.Symbol)
|
||||||
}
|
}
|
||||||
|
@ -264,14 +271,6 @@ func (s *Strategy) Suspend(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
s.tradeCollector.Process()
|
s.tradeCollector.Process()
|
||||||
|
|
||||||
// Save state
|
|
||||||
if err := s.SaveState(); err != nil {
|
|
||||||
log.WithError(err).Errorf("can not save state: %+v", s.state)
|
|
||||||
} else {
|
|
||||||
log.Infof("%s position is saved.", s.Symbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,36 +291,21 @@ func (s *Strategy) EmergencyStop(ctx context.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) SaveState() error {
|
func (s *Strategy) newProfitStats() *types.ProfitStats {
|
||||||
if err := s.Persistence.Save(s.state, ID, s.Symbol, stateKey); err != nil {
|
return &types.ProfitStats{
|
||||||
return err
|
Symbol: s.Market.Symbol,
|
||||||
|
BaseCurrency: s.Market.BaseCurrency,
|
||||||
|
QuoteCurrency: s.Market.QuoteCurrency,
|
||||||
|
AccumulatedSince: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("state is saved => %+v", s.state)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) LoadState() error {
|
func (s *Strategy) LoadState() error {
|
||||||
var state State
|
var state State
|
||||||
|
|
||||||
// load position
|
// load position
|
||||||
if err := s.Persistence.Load(&state, ID, s.Symbol, stateKey); err != nil {
|
if err := s.Persistence.Load(&state, ID, s.Symbol, stateKey); err == nil {
|
||||||
if err != service.ErrPersistenceNotExists {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.state = &State{}
|
|
||||||
} else {
|
|
||||||
s.state = &state
|
s.state = &state
|
||||||
log.Infof("state is restored: %+v", s.state)
|
|
||||||
}
|
|
||||||
|
|
||||||
// init profit states
|
|
||||||
s.state.ProfitStats.Symbol = s.Market.Symbol
|
|
||||||
s.state.ProfitStats.BaseCurrency = s.Market.BaseCurrency
|
|
||||||
s.state.ProfitStats.QuoteCurrency = s.Market.QuoteCurrency
|
|
||||||
if s.state.ProfitStats.AccumulatedSince == 0 {
|
|
||||||
s.state.ProfitStats.AccumulatedSince = time.Now().Unix()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -566,10 +550,6 @@ func (s *Strategy) adjustOrderQuantity(submitOrder types.SubmitOrder) types.Subm
|
||||||
return submitOrder
|
return submitOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) InstanceID() string {
|
|
||||||
return fmt.Sprintf("%s-%s", ID, s.Symbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
|
func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
|
||||||
// StrategyController
|
// StrategyController
|
||||||
s.status = types.StrategyStatusRunning
|
s.status = types.StrategyStatusRunning
|
||||||
|
@ -601,7 +581,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
|
|
||||||
// calculate group id for orders
|
// calculate group id for orders
|
||||||
instanceID := s.InstanceID()
|
instanceID := s.InstanceID()
|
||||||
s.groupID = max.GenerateGroupID(instanceID)
|
s.groupID = util.FNV32(instanceID)
|
||||||
log.Infof("using group id %d from fnv(%s)", s.groupID, instanceID)
|
log.Infof("using group id %d from fnv(%s)", s.groupID, instanceID)
|
||||||
|
|
||||||
// restore state
|
// restore state
|
||||||
|
@ -612,13 +592,24 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
// If position is nil, we need to allocate a new position for calculation
|
// If position is nil, we need to allocate a new position for calculation
|
||||||
if s.Position == nil {
|
if s.Position == nil {
|
||||||
// fallback to the legacy position struct in the state
|
// fallback to the legacy position struct in the state
|
||||||
if s.state.Position != nil {
|
if s.state != nil && s.state.Position != nil {
|
||||||
s.Position = s.state.Position
|
s.Position = s.state.Position
|
||||||
} else {
|
} else {
|
||||||
s.Position = types.NewPositionFromMarket(s.Market)
|
s.Position = types.NewPositionFromMarket(s.Market)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.ProfitStats == nil {
|
||||||
|
if s.state != nil {
|
||||||
|
// copy stats
|
||||||
|
p2 := s.state.ProfitStats
|
||||||
|
s.ProfitStats = &p2
|
||||||
|
} else {
|
||||||
|
s.ProfitStats = s.newProfitStats()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Always update the position fields
|
// Always update the position fields
|
||||||
s.Position.Strategy = ID
|
s.Position.Strategy = ID
|
||||||
s.Position.StrategyInstanceID = instanceID
|
s.Position.StrategyInstanceID = instanceID
|
||||||
|
@ -640,7 +631,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Notifiability.Notify(trade)
|
s.Notifiability.Notify(trade)
|
||||||
s.state.ProfitStats.AddTrade(trade)
|
s.ProfitStats.AddTrade(trade)
|
||||||
|
|
||||||
if profit.Compare(fixedpoint.Zero) == 0 {
|
if profit.Compare(fixedpoint.Zero) == 0 {
|
||||||
s.Environment.RecordPosition(s.Position, trade, nil)
|
s.Environment.RecordPosition(s.Position, trade, nil)
|
||||||
|
@ -651,8 +642,8 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
p.StrategyInstanceID = instanceID
|
p.StrategyInstanceID = instanceID
|
||||||
s.Notify(&p)
|
s.Notify(&p)
|
||||||
|
|
||||||
s.state.ProfitStats.AddProfit(p)
|
s.ProfitStats.AddProfit(p)
|
||||||
s.Notify(&s.state.ProfitStats)
|
s.Notify(&s.ProfitStats)
|
||||||
|
|
||||||
s.Environment.RecordPosition(s.Position, trade, &p)
|
s.Environment.RecordPosition(s.Position, trade, &p)
|
||||||
}
|
}
|
||||||
|
@ -726,10 +717,6 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
}
|
}
|
||||||
|
|
||||||
s.tradeCollector.Process()
|
s.tradeCollector.Process()
|
||||||
|
|
||||||
if err := s.SaveState(); err != nil {
|
|
||||||
log.WithError(err).Errorf("can not save state: %+v", s.state)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -9,10 +9,10 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
"github.com/c9s/bbgo/pkg/exchange/max"
|
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
"github.com/c9s/bbgo/pkg/service"
|
"github.com/c9s/bbgo/pkg/service"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
"github.com/c9s/bbgo/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ID = "grid"
|
const ID = "grid"
|
||||||
|
@ -586,7 +586,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceID := s.InstanceID()
|
instanceID := s.InstanceID()
|
||||||
s.groupID = max.GenerateGroupID(instanceID)
|
s.groupID = util.FNV32(instanceID)
|
||||||
log.Infof("using group id %d from fnv(%s)", s.groupID, instanceID)
|
log.Infof("using group id %d from fnv(%s)", s.groupID, instanceID)
|
||||||
|
|
||||||
if err := s.LoadState(); err != nil {
|
if err := s.LoadState(); err != nil {
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
"github.com/c9s/bbgo/pkg/exchange/max"
|
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
"github.com/c9s/bbgo/pkg/service"
|
"github.com/c9s/bbgo/pkg/service"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
@ -232,7 +231,7 @@ func (s *Strategy) CrossRun(ctx context.Context, _ bbgo.OrderExecutionRouter, se
|
||||||
s.tradingSession.UserDataStream.OnTradeUpdate(s.handleTradeUpdate)
|
s.tradingSession.UserDataStream.OnTradeUpdate(s.handleTradeUpdate)
|
||||||
|
|
||||||
instanceID := fmt.Sprintf("%s-%s", ID, s.Symbol)
|
instanceID := fmt.Sprintf("%s-%s", ID, s.Symbol)
|
||||||
s.groupID = max.GenerateGroupID(instanceID)
|
s.groupID = util.FNV32(instanceID)
|
||||||
log.Infof("using group id %d from fnv32(%s)", s.groupID, instanceID)
|
log.Infof("using group id %d from fnv32(%s)", s.groupID, instanceID)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
"github.com/c9s/bbgo/pkg/exchange/max"
|
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
"github.com/c9s/bbgo/pkg/indicator"
|
"github.com/c9s/bbgo/pkg/indicator"
|
||||||
"github.com/c9s/bbgo/pkg/service"
|
"github.com/c9s/bbgo/pkg/service"
|
||||||
|
@ -710,7 +709,7 @@ func (s *Strategy) CrossRun(ctx context.Context, orderExecutionRouter bbgo.Order
|
||||||
|
|
||||||
// restore state
|
// restore state
|
||||||
instanceID := fmt.Sprintf("%s-%s", ID, s.Symbol)
|
instanceID := fmt.Sprintf("%s-%s", ID, s.Symbol)
|
||||||
s.groupID = max.GenerateGroupID(instanceID)
|
s.groupID = util.FNV32(instanceID)
|
||||||
log.Infof("using group id %d from fnv(%s)", s.groupID, instanceID)
|
log.Infof("using group id %d from fnv(%s)", s.groupID, instanceID)
|
||||||
|
|
||||||
if err := s.LoadState(); err != nil {
|
if err := s.LoadState(); err != nil {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package max
|
package util
|
||||||
|
|
||||||
import "hash/fnv"
|
import "hash/fnv"
|
||||||
|
|
||||||
func GenerateGroupID(s string) uint32 {
|
func FNV32(s string) uint32 {
|
||||||
h := fnv.New32a()
|
h := fnv.New32a()
|
||||||
h.Write([]byte(s))
|
h.Write([]byte(s))
|
||||||
return h.Sum32()
|
return h.Sum32()
|
Loading…
Reference in New Issue
Block a user