mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +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
|
||||
# see here for more details
|
||||
# https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp
|
||||
startTime: "2022-01-01"
|
||||
endTime: "2022-05-12"
|
||||
startTime: "2022-05-01"
|
||||
endTime: "2022-05-31"
|
||||
sessions:
|
||||
- binance
|
||||
symbols:
|
||||
|
@ -26,7 +26,7 @@ backtest:
|
|||
binance:
|
||||
balances:
|
||||
ETH: 0.0
|
||||
USDT: 10_000.0
|
||||
USDT: 100_000.0
|
||||
|
||||
exchangeStrategies:
|
||||
|
||||
|
@ -38,7 +38,14 @@ exchangeStrategies:
|
|||
interval: 1m
|
||||
|
||||
# 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.
|
||||
# The back-test engine is kline-based, so the ticker price api is not supported.
|
||||
|
@ -103,7 +110,7 @@ exchangeStrategies:
|
|||
domain: [ -1, 1 ]
|
||||
# when in down band, holds 1.0 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
|
||||
# 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
|
||||
# sometimes the stop order might decrease your total profit.
|
||||
# you can setup multiple stop,
|
||||
stops:
|
||||
# stops:
|
||||
# use trailing stop order
|
||||
- trailingStop:
|
||||
# callbackRate: when the price reaches -1% from the previous highest, we trigger the stop
|
||||
callbackRate: 5.1%
|
||||
|
||||
# closePosition is how much position do you want to close
|
||||
closePosition: 20%
|
||||
|
||||
# minProfit is how much profit you want to take.
|
||||
# if you set this option, your stop will only be triggered above the average cost.
|
||||
minProfit: 5%
|
||||
|
||||
# interval is the time interval for checking your stop
|
||||
interval: 1m
|
||||
|
||||
# virtual means we don't place a a REAL stop order
|
||||
# when virtual is on
|
||||
# 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.
|
||||
virtual: true
|
||||
# - trailingStop:
|
||||
# # callbackRate: when the price reaches -1% from the previous highest, we trigger the stop
|
||||
# callbackRate: 5.1%
|
||||
#
|
||||
# # closePosition is how much position do you want to close
|
||||
# closePosition: 20%
|
||||
#
|
||||
# # minProfit is how much profit you want to take.
|
||||
# # if you set this option, your stop will only be triggered above the average cost.
|
||||
# minProfit: 5%
|
||||
#
|
||||
# # interval is the time interval for checking your stop
|
||||
# interval: 1m
|
||||
#
|
||||
# # virtual means we don't place a a REAL stop order
|
||||
# # when virtual is on
|
||||
# # 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.
|
||||
# virtual: true
|
||||
|
||||
|
|
|
@ -228,9 +228,12 @@ type Strategy struct {
|
|||
state *State
|
||||
|
||||
// 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"`
|
||||
|
||||
PushThreshold fixedpoint.Value `json:"pushThreshold,omitempty"`
|
||||
PopThreshold fixedpoint.Value `json:"popThreshold,omitempty"`
|
||||
|
||||
activeMakerOrders *bbgo.LocalActiveOrderBook
|
||||
orderStore *bbgo.OrderStore
|
||||
tradeCollector *bbgo.TradeCollector
|
||||
|
@ -289,7 +292,7 @@ func (s *Strategy) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Strategy) CurrentPosition() *types.Position {
|
||||
func (s *Strategy) CurrentPosition() *types.PositionStack {
|
||||
return s.Position
|
||||
}
|
||||
|
||||
|
@ -652,9 +655,9 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
|||
if s.Position == nil {
|
||||
// fallback to the legacy position struct in the state
|
||||
if s.state != nil && s.state.Position != nil {
|
||||
s.Position = s.state.Position
|
||||
s.Position.Position = s.state.Position
|
||||
} 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)
|
||||
|
||||
if profit.Compare(fixedpoint.Zero) == 0 {
|
||||
s.Environment.RecordPosition(s.Position, trade, nil)
|
||||
s.Environment.RecordPosition(s.Position.Position, trade, nil)
|
||||
} else {
|
||||
log.Infof("%s generated profit: %v", s.Symbol, profit)
|
||||
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.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)
|
||||
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 {
|
||||
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.
|
||||
s.tradeCollector.Process()
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user