bollmaker: add position stack

This commit is contained in:
austin362667 2022-03-03 17:20:02 +08:00
parent 2108003f9b
commit 3173fa554b

View File

@ -3,12 +3,11 @@ package bollmaker
import (
"context"
"fmt"
"github.com/c9s/bbgo/pkg/indicator"
"math"
"sync"
"time"
"github.com/c9s/bbgo/pkg/indicator"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@ -37,8 +36,36 @@ func init() {
bbgo.RegisterStrategy(ID, &Strategy{})
}
// NewStack returns a new position stack.
func NewStack() *PositionStack {
return &PositionStack{}
}
// Stack is a basic LIFO stack that resizes as needed.
type PositionStack struct {
positions []*types.Position
}
// Push adds a node to the stack.
func (s *PositionStack) Length() int {
return len(s.positions)
}
// Push adds a node to the stack.
func (s *PositionStack) Push(p *types.Position) {
s.positions = append(s.positions, p)
}
// Pop removes and returns a node from the stack in last to first order.
func (s *PositionStack) Pop() *types.Position {
if len(s.positions) == 0 {
return nil
}
return s.positions[len(s.positions)-1]
}
type State struct {
Position *types.Position `json:"position,omitempty"`
Position types.Position `json:"position,omitempty"`
ProfitStats bbgo.ProfitStats `json:"profitStats,omitempty"`
}
@ -198,7 +225,7 @@ func (s *Strategy) Validate() error {
}
func (s *Strategy) CurrentPosition() *types.Position {
return s.state.Position
return &s.state.Position
}
func (s *Strategy) ClosePosition(ctx context.Context, percentage fixedpoint.Value) error {
@ -263,9 +290,9 @@ func (s *Strategy) LoadState() error {
}
// if position is nil, we need to allocate a new position for calculation
if s.state.Position == nil {
s.state.Position = types.NewPositionFromMarket(s.market)
}
//if s.state.Position == nil {
s.state.Position = *types.NewPositionFromMarket(s.market)
//}
// init profit states
s.state.ProfitStats.Symbol = s.market.Symbol
@ -518,6 +545,8 @@ func (s *Strategy) adjustOrderQuantity(submitOrder types.SubmitOrder) types.Subm
}
func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
PositionStack := NewStack()
if s.DisableShort {
s.Long = &[]bool{true}[0]
}
@ -567,8 +596,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
s.orderStore = bbgo.NewOrderStore(s.Symbol)
s.orderStore.BindStream(session.UserDataStream)
s.tradeCollector = bbgo.NewTradeCollector(s.Symbol, s.state.Position, s.orderStore)
s.tradeCollector = bbgo.NewTradeCollector(s.Symbol, &s.state.Position, s.orderStore)
s.tradeCollector.OnProfit(func(trade types.Trade, profit fixedpoint.Value, netProfit fixedpoint.Value) {
log.Infof("generated profit: %v", profit)
p := bbgo.Profit{
@ -626,6 +654,29 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
log.WithError(err).Errorf("graceful cancel order error")
}
log.Infof("trade collector position: %v", s.tradeCollector.Position())
if kline.Close.Float64() < s.state.Position.AverageCost.Float64()*0.8 {
p := s.state.Position
PositionStack.Push(&p)
s.state.Position.Reset()
//s.tradeCollector = bbgo.NewTradeCollector(s.Symbol, s.state.Position, s.orderStore)
}
if kline.Close.Float64() > s.state.Position.AverageCost.Float64()*1.2 {
if s.state.Position.GetBase().Float64() > 0 && s.state.Position.GetBase().Float64() < s.Quantity.Float64() {
if PositionStack.Length() > 1 {
s.ClosePosition(ctx, 100.0)
s.state.Position.Reset()
p := PositionStack.Pop()
s.state.Position = *p
}
}
}
if PositionStack.Length() > 1 {
log.Infof("position stack: %v, length: %d, current position: %v", PositionStack.positions, PositionStack.Length(), s.state.Position)
}
// check if there is a canceled order had partially filled.
s.tradeCollector.Process()