mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-13 02:23:51 +00:00
bollmaker: add position stack
This commit is contained in:
parent
a3ca8326f2
commit
54d60b9890
|
@ -16,8 +16,8 @@ backtest:
|
||||||
# for testing max draw down (MDD) at 03-12
|
# for testing max draw down (MDD) at 03-12
|
||||||
# see here for more details
|
# see here for more details
|
||||||
# https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp
|
# https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp
|
||||||
startTime: "2022-01-01"
|
startTime: "2022-05-01"
|
||||||
endTime: "2022-05-12"
|
endTime: "2022-05-31"
|
||||||
sessions:
|
sessions:
|
||||||
- binance
|
- binance
|
||||||
symbols:
|
symbols:
|
||||||
|
@ -26,7 +26,7 @@ backtest:
|
||||||
binance:
|
binance:
|
||||||
balances:
|
balances:
|
||||||
ETH: 0.0
|
ETH: 0.0
|
||||||
USDT: 10_000.0
|
USDT: 100_000.0
|
||||||
|
|
||||||
exchangeStrategies:
|
exchangeStrategies:
|
||||||
|
|
||||||
|
@ -38,7 +38,14 @@ exchangeStrategies:
|
||||||
interval: 1m
|
interval: 1m
|
||||||
|
|
||||||
# quantity is the base order quantity for your buy/sell order.
|
# quantity is the base order quantity for your buy/sell order.
|
||||||
quantity: 0.05
|
# quantity: 0.05
|
||||||
|
amount: 20
|
||||||
|
|
||||||
|
# Position Stack, with longer stack length, may need more capital.
|
||||||
|
# Push position in stack is initiating a position to calculate base, average cost, etc.
|
||||||
|
# Pop position in stack is loading a previous position back.
|
||||||
|
pushThreshold: 10%
|
||||||
|
# popThreshold : 1%
|
||||||
|
|
||||||
# useTickerPrice use the ticker api to get the mid price instead of the closed kline price.
|
# useTickerPrice use the ticker api to get the mid price instead of the closed kline price.
|
||||||
# The back-test engine is kline-based, so the ticker price api is not supported.
|
# The back-test engine is kline-based, so the ticker price api is not supported.
|
||||||
|
@ -103,7 +110,7 @@ exchangeStrategies:
|
||||||
domain: [ -1, 1 ]
|
domain: [ -1, 1 ]
|
||||||
# when in down band, holds 1.0 by maximum
|
# when in down band, holds 1.0 by maximum
|
||||||
# when in up band, holds 0.05 by maximum
|
# when in up band, holds 0.05 by maximum
|
||||||
range: [ 10.0, 1.0 ]
|
range: [10.0, 1.0 ]
|
||||||
|
|
||||||
# DisableShort means you can don't want short position during the market making
|
# DisableShort means you can don't want short position during the market making
|
||||||
# THe short here means you might sell some of your existing inventory.
|
# THe short here means you might sell some of your existing inventory.
|
||||||
|
@ -136,25 +143,25 @@ exchangeStrategies:
|
||||||
# Set up your stop order, this is optional
|
# Set up your stop order, this is optional
|
||||||
# sometimes the stop order might decrease your total profit.
|
# sometimes the stop order might decrease your total profit.
|
||||||
# you can setup multiple stop,
|
# you can setup multiple stop,
|
||||||
stops:
|
# stops:
|
||||||
# use trailing stop order
|
# use trailing stop order
|
||||||
- trailingStop:
|
# - trailingStop:
|
||||||
# callbackRate: when the price reaches -1% from the previous highest, we trigger the stop
|
# # callbackRate: when the price reaches -1% from the previous highest, we trigger the stop
|
||||||
callbackRate: 5.1%
|
# callbackRate: 5.1%
|
||||||
|
#
|
||||||
# closePosition is how much position do you want to close
|
# # closePosition is how much position do you want to close
|
||||||
closePosition: 20%
|
# closePosition: 20%
|
||||||
|
#
|
||||||
# minProfit is how much profit you want to take.
|
# # minProfit is how much profit you want to take.
|
||||||
# if you set this option, your stop will only be triggered above the average cost.
|
# # if you set this option, your stop will only be triggered above the average cost.
|
||||||
minProfit: 5%
|
# minProfit: 5%
|
||||||
|
#
|
||||||
# interval is the time interval for checking your stop
|
# # interval is the time interval for checking your stop
|
||||||
interval: 1m
|
# interval: 1m
|
||||||
|
#
|
||||||
# virtual means we don't place a a REAL stop order
|
# # virtual means we don't place a a REAL stop order
|
||||||
# when virtual is on
|
# # when virtual is on
|
||||||
# the strategy won't place a REAL stop order, instead if watches the close price,
|
# # the strategy won't place a REAL stop order, instead if watches the close price,
|
||||||
# and if the condition matches, it submits a market order to close your position.
|
# # and if the condition matches, it submits a market order to close your position.
|
||||||
virtual: true
|
# virtual: true
|
||||||
|
|
||||||
|
|
|
@ -228,8 +228,11 @@ type Strategy struct {
|
||||||
state *State
|
state *State
|
||||||
|
|
||||||
// persistence fields
|
// persistence fields
|
||||||
Position *types.Position `json:"position,omitempty" persistence:"position"`
|
Position *types.PositionStack `json:"position,omitempty" persistence:"position"`
|
||||||
ProfitStats *types.ProfitStats `json:"profitStats,omitempty" persistence:"profit_stats"`
|
ProfitStats *types.ProfitStats `json:"profitStats,omitempty" persistence:"profit_stats"`
|
||||||
|
|
||||||
|
PushThreshold fixedpoint.Value `json:"pushThreshold,omitempty"`
|
||||||
|
PopThreshold fixedpoint.Value `json:"popThreshold,omitempty"`
|
||||||
|
|
||||||
activeMakerOrders *bbgo.LocalActiveOrderBook
|
activeMakerOrders *bbgo.LocalActiveOrderBook
|
||||||
orderStore *bbgo.OrderStore
|
orderStore *bbgo.OrderStore
|
||||||
|
@ -289,7 +292,7 @@ func (s *Strategy) Validate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) CurrentPosition() *types.Position {
|
func (s *Strategy) CurrentPosition() *types.PositionStack {
|
||||||
return s.Position
|
return s.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -652,9 +655,9 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
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 != nil && s.state.Position != nil {
|
if s.state != nil && s.state.Position != nil {
|
||||||
s.Position = s.state.Position
|
s.Position.Position = s.state.Position
|
||||||
} else {
|
} else {
|
||||||
s.Position = types.NewPositionFromMarket(s.Market)
|
s.Position = types.NewPositionStackFromMarket(s.Market)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,7 +702,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
s.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.Position, trade, nil)
|
||||||
} else {
|
} else {
|
||||||
log.Infof("%s generated profit: %v", s.Symbol, profit)
|
log.Infof("%s generated profit: %v", s.Symbol, profit)
|
||||||
p := s.Position.NewProfit(trade, profit, netProfit)
|
p := s.Position.NewProfit(trade, profit, netProfit)
|
||||||
|
@ -710,11 +713,11 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
s.ProfitStats.AddProfit(p)
|
s.ProfitStats.AddProfit(p)
|
||||||
s.Notify(&s.ProfitStats)
|
s.Notify(&s.ProfitStats)
|
||||||
|
|
||||||
s.Environment.RecordPosition(s.Position, trade, &p)
|
s.Environment.RecordPosition(s.Position.Position, trade, &p)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
s.tradeCollector.OnPositionUpdate(func(position *types.Position) {
|
s.tradeCollector.OnPositionUpdate(func(position types.PositionInterface) {
|
||||||
log.Infof("position changed: %s", s.Position)
|
log.Infof("position changed: %s", s.Position)
|
||||||
s.Notify(s.Position)
|
s.Notify(s.Position)
|
||||||
})
|
})
|
||||||
|
@ -772,7 +775,25 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
if err := s.activeMakerOrders.GracefulCancel(ctx, s.session.Exchange); err != nil {
|
if err := s.activeMakerOrders.GracefulCancel(ctx, s.session.Exchange); err != nil {
|
||||||
log.WithError(err).Errorf("graceful cancel order error")
|
log.WithError(err).Errorf("graceful cancel order error")
|
||||||
}
|
}
|
||||||
|
//log.Error(len(s.Position.Stack), s.Position.AverageCost, kline.Close)
|
||||||
|
|
||||||
|
if s.Position.Position.AverageCost.Div(kline.Close).Compare(fixedpoint.One.Add(s.PushThreshold)) > 0 {
|
||||||
|
log.Errorf("push")
|
||||||
|
log.Error(s.Position)
|
||||||
|
s.Position = s.Position.Push(types.NewPositionFromMarket(s.Market))
|
||||||
|
}
|
||||||
|
// &&
|
||||||
|
if len(s.Position.Stack) > 1 && s.Position.Stack[len(s.Position.Stack)-2].AverageCost.Compare(kline.Close) < 0 && s.Market.IsDustQuantity(s.Position.Position.GetBase(), kline.Close) {
|
||||||
|
log.Errorf("pop")
|
||||||
|
log.Error(s.Position)
|
||||||
|
s.Position = s.Position.Pop()
|
||||||
|
}
|
||||||
|
//if s.Position.AverageCost.Div(kline.Close).Compare(fixedpoint.One.Sub(s.PopThreshold)) < 0 && && !s.Position.AverageCost.IsZero() {
|
||||||
|
// //log.Error(len(s.Position.Stack), s.Position.AverageCost, kline.Close)
|
||||||
|
// log.Errorf("pop")
|
||||||
|
// s.ClosePosition(ctx, fixedpoint.One)
|
||||||
|
// s.Position = s.Position.Pop()
|
||||||
|
//}
|
||||||
// check if there is a canceled order had partially filled.
|
// check if there is a canceled order had partially filled.
|
||||||
s.tradeCollector.Process()
|
s.tradeCollector.Process()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user