mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-24 15:55:14 +00:00
add fee budget support to random strategy
This commit is contained in:
parent
0f03bc785b
commit
9cbf8a0ecf
|
@ -1,6 +1,7 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
|
@ -11,6 +12,8 @@ import (
|
|||
type FeeBudget struct {
|
||||
DailyFeeBudgets map[string]fixedpoint.Value `json:"dailyFeeBudgets,omitempty"`
|
||||
State *State `persistence:"state"`
|
||||
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (f *FeeBudget) Initialize() {
|
||||
|
@ -34,6 +37,11 @@ func (f *FeeBudget) IsBudgetAllowed() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
if f.State.IsOver24Hours() {
|
||||
f.State.Reset()
|
||||
return true
|
||||
}
|
||||
|
||||
for asset, budget := range f.DailyFeeBudgets {
|
||||
if fee, ok := f.State.AccumulatedFees[asset]; ok {
|
||||
if fee.Compare(budget) >= 0 {
|
||||
|
@ -55,18 +63,18 @@ func (f *FeeBudget) HandleTradeUpdate(trade types.Trade) {
|
|||
|
||||
// safe check
|
||||
if f.State.AccumulatedFees == nil {
|
||||
f.mu.Lock()
|
||||
f.State.AccumulatedFees = make(map[string]fixedpoint.Value)
|
||||
f.mu.Unlock()
|
||||
}
|
||||
|
||||
f.State.AccumulatedFees[trade.FeeCurrency] = f.State.AccumulatedFees[trade.FeeCurrency].Add(trade.Fee)
|
||||
f.State.AccumulatedVolume = f.State.AccumulatedVolume.Add(trade.Quantity)
|
||||
log.Infof("[FeeBudget] accumulated fee: %s %s", f.State.AccumulatedFees[trade.FeeCurrency].String(), trade.FeeCurrency)
|
||||
}
|
||||
|
||||
type State struct {
|
||||
AccumulatedFeeStartedAt time.Time `json:"accumulatedFeeStartedAt,omitempty"`
|
||||
AccumulatedFees map[string]fixedpoint.Value `json:"accumulatedFees,omitempty"`
|
||||
AccumulatedVolume fixedpoint.Value `json:"accumulatedVolume,omitempty"`
|
||||
}
|
||||
|
||||
func (s *State) IsOver24Hours() bool {
|
||||
|
@ -81,5 +89,4 @@ func (s *State) Reset() {
|
|||
|
||||
s.AccumulatedFeeStartedAt = dateTime
|
||||
s.AccumulatedFees = make(map[string]fixedpoint.Value)
|
||||
s.AccumulatedVolume = fixedpoint.Zero
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package common
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
|
@ -46,7 +47,10 @@ func TestFeeBudget(t *testing.T) {
|
|||
for _, trade := range c.trades {
|
||||
feeBudget.HandleTradeUpdate(trade)
|
||||
}
|
||||
|
||||
assert.Equal(t, c.expected, feeBudget.IsBudgetAllowed())
|
||||
|
||||
// test reset
|
||||
feeBudget.State.AccumulatedFeeStartedAt = feeBudget.State.AccumulatedFeeStartedAt.Add(-24 * time.Hour)
|
||||
assert.True(t, feeBudget.IsBudgetAllowed())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ func init() {
|
|||
|
||||
type Strategy struct {
|
||||
*common.Strategy
|
||||
*common.FeeBudget
|
||||
|
||||
Environment *bbgo.Environment
|
||||
Market types.Market
|
||||
|
@ -45,6 +46,10 @@ func (s *Strategy) Initialize() error {
|
|||
if s.Strategy == nil {
|
||||
s.Strategy = &common.Strategy{}
|
||||
}
|
||||
|
||||
if s.FeeBudget == nil {
|
||||
s.FeeBudget = &common.FeeBudget{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -71,11 +76,25 @@ func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {}
|
|||
|
||||
func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
|
||||
s.Strategy.Initialize(ctx, s.Environment, session, s.Market, s.ID(), s.InstanceID())
|
||||
s.FeeBudget.Initialize()
|
||||
|
||||
session.UserDataStream.OnStart(func() {
|
||||
if s.OnStart {
|
||||
s.placeOrder()
|
||||
if !s.OnStart {
|
||||
return
|
||||
}
|
||||
|
||||
if !s.FeeBudget.IsBudgetAllowed() {
|
||||
return
|
||||
}
|
||||
|
||||
s.placeOrder(ctx)
|
||||
})
|
||||
|
||||
session.UserDataStream.OnTradeUpdate(func(trade types.Trade) {
|
||||
if trade.Symbol != s.Symbol {
|
||||
return
|
||||
}
|
||||
s.FeeBudget.HandleTradeUpdate(trade)
|
||||
})
|
||||
|
||||
// the shutdown handler, you can cancel all orders
|
||||
|
@ -86,15 +105,19 @@ func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.
|
|||
})
|
||||
|
||||
s.cron = cron.New()
|
||||
s.cron.AddFunc(s.Schedule, s.placeOrder)
|
||||
s.cron.AddFunc(s.Schedule, func() {
|
||||
if !s.FeeBudget.IsBudgetAllowed() {
|
||||
return
|
||||
}
|
||||
|
||||
s.placeOrder(ctx)
|
||||
})
|
||||
s.cron.Start()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Strategy) placeOrder() {
|
||||
ctx := context.Background()
|
||||
|
||||
func (s *Strategy) placeOrder(ctx context.Context) {
|
||||
baseBalance, ok := s.Session.GetAccount().Balance(s.Market.BaseCurrency)
|
||||
if !ok {
|
||||
log.Errorf("base balance not found")
|
||||
|
|
Loading…
Reference in New Issue
Block a user