mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 00:35:15 +00:00
rewrite trade profit handling
This commit is contained in:
parent
6fec30d79c
commit
5db4e11167
|
@ -22,6 +22,7 @@ import (
|
||||||
"gopkg.in/tucnak/telebot.v2"
|
"gopkg.in/tucnak/telebot.v2"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/cmd/cmdutil"
|
"github.com/c9s/bbgo/pkg/cmd/cmdutil"
|
||||||
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
"github.com/c9s/bbgo/pkg/interact"
|
"github.com/c9s/bbgo/pkg/interact"
|
||||||
"github.com/c9s/bbgo/pkg/notifier/slacknotifier"
|
"github.com/c9s/bbgo/pkg/notifier/slacknotifier"
|
||||||
"github.com/c9s/bbgo/pkg/notifier/telegramnotifier"
|
"github.com/c9s/bbgo/pkg/notifier/telegramnotifier"
|
||||||
|
@ -596,15 +597,20 @@ func (environ *Environment) RecordPosition(position *types.Position, trade types
|
||||||
position.StrategyInstanceID = profit.StrategyInstanceID
|
position.StrategyInstanceID = profit.StrategyInstanceID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if profit != nil {
|
||||||
if err := environ.PositionService.Insert(position, trade, profit.Profit); err != nil {
|
if err := environ.PositionService.Insert(position, trade, profit.Profit); err != nil {
|
||||||
log.WithError(err).Errorf("can not insert position record")
|
log.WithError(err).Errorf("can not insert position record")
|
||||||
}
|
}
|
||||||
|
|
||||||
if profit != nil {
|
|
||||||
if err := environ.ProfitService.Insert(*profit); err != nil {
|
if err := environ.ProfitService.Insert(*profit); err != nil {
|
||||||
log.WithError(err).Errorf("can not insert profit record: %+v", profit)
|
log.WithError(err).Errorf("can not insert profit record: %+v", profit)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if err := environ.PositionService.Insert(position, trade, fixedpoint.Zero); err != nil {
|
||||||
|
log.WithError(err).Errorf("can not insert position record")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// if:
|
// if:
|
||||||
// 1) we are not using sync
|
// 1) we are not using sync
|
||||||
|
|
|
@ -23,7 +23,7 @@ type TradeCollector struct {
|
||||||
doneTrades map[types.TradeKey]struct{}
|
doneTrades map[types.TradeKey]struct{}
|
||||||
|
|
||||||
recoverCallbacks []func(trade types.Trade)
|
recoverCallbacks []func(trade types.Trade)
|
||||||
tradeCallbacks []func(trade types.Trade)
|
tradeCallbacks []func(trade types.Trade, profit, netProfit fixedpoint.Value)
|
||||||
positionUpdateCallbacks []func(position *types.Position)
|
positionUpdateCallbacks []func(position *types.Position)
|
||||||
profitCallbacks []func(trade types.Trade, profit, netProfit fixedpoint.Value)
|
profitCallbacks []func(trade types.Trade, profit, netProfit fixedpoint.Value)
|
||||||
}
|
}
|
||||||
|
@ -108,10 +108,10 @@ func (c *TradeCollector) Process() bool {
|
||||||
if c.orderStore.Exists(trade.OrderID) {
|
if c.orderStore.Exists(trade.OrderID) {
|
||||||
c.doneTrades[key] = struct{}{}
|
c.doneTrades[key] = struct{}{}
|
||||||
if profit, netProfit, madeProfit := c.position.AddTrade(trade); madeProfit {
|
if profit, netProfit, madeProfit := c.position.AddTrade(trade); madeProfit {
|
||||||
c.EmitTrade(trade)
|
c.EmitTrade(trade, fixedpoint.Zero, fixedpoint.Zero)
|
||||||
c.EmitProfit(trade, profit, netProfit)
|
c.EmitProfit(trade, profit, netProfit)
|
||||||
} else {
|
} else {
|
||||||
c.EmitTrade(trade)
|
c.EmitTrade(trade, fixedpoint.Zero, fixedpoint.Zero)
|
||||||
}
|
}
|
||||||
positionChanged = true
|
positionChanged = true
|
||||||
return true
|
return true
|
||||||
|
@ -139,10 +139,10 @@ func (c *TradeCollector) processTrade(trade types.Trade) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
if profit, netProfit, madeProfit := c.position.AddTrade(trade); madeProfit {
|
if profit, netProfit, madeProfit := c.position.AddTrade(trade); madeProfit {
|
||||||
c.EmitTrade(trade)
|
c.EmitTrade(trade, fixedpoint.Zero, fixedpoint.Zero)
|
||||||
c.EmitProfit(trade, profit, netProfit)
|
c.EmitProfit(trade, profit, netProfit)
|
||||||
} else {
|
} else {
|
||||||
c.EmitTrade(trade)
|
c.EmitTrade(trade, fixedpoint.Zero, fixedpoint.Zero)
|
||||||
}
|
}
|
||||||
c.EmitPositionUpdate(c.position)
|
c.EmitPositionUpdate(c.position)
|
||||||
c.doneTrades[key] = struct{}{}
|
c.doneTrades[key] = struct{}{}
|
||||||
|
|
|
@ -17,13 +17,13 @@ func (c *TradeCollector) EmitRecover(trade types.Trade) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TradeCollector) OnTrade(cb func(trade types.Trade)) {
|
func (c *TradeCollector) OnTrade(cb func(trade types.Trade, profit fixedpoint.Value, netProfit fixedpoint.Value)) {
|
||||||
c.tradeCallbacks = append(c.tradeCallbacks, cb)
|
c.tradeCallbacks = append(c.tradeCallbacks, cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TradeCollector) EmitTrade(trade types.Trade) {
|
func (c *TradeCollector) EmitTrade(trade types.Trade, profit fixedpoint.Value, netProfit fixedpoint.Value) {
|
||||||
for _, cb := range c.tradeCallbacks {
|
for _, cb := range c.tradeCallbacks {
|
||||||
cb(trade)
|
cb(trade, profit, netProfit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -566,22 +566,26 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
s.orderStore.BindStream(session.UserDataStream)
|
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) {
|
s.tradeCollector.OnProfit(func(trade types.Trade, profit, netProfit fixedpoint.Value) {
|
||||||
log.Infof("generated profit: %v", profit)
|
|
||||||
p := s.state.Position.NewProfit(trade, profit, netProfit)
|
|
||||||
p.Strategy = ID
|
|
||||||
p.StrategyInstanceID = instanceID
|
|
||||||
s.Environment.RecordPosition(s.state.Position, trade, &p)
|
|
||||||
|
|
||||||
s.state.ProfitStats.AddProfit(p)
|
|
||||||
s.Notify(&p)
|
|
||||||
s.Notify(&s.state.ProfitStats)
|
s.Notify(&s.state.ProfitStats)
|
||||||
})
|
})
|
||||||
|
|
||||||
s.tradeCollector.OnTrade(func(trade types.Trade) {
|
s.tradeCollector.OnTrade(func(trade types.Trade, profit, netProfit fixedpoint.Value) {
|
||||||
s.Notifiability.Notify(trade)
|
s.Notifiability.Notify(trade)
|
||||||
s.state.ProfitStats.AddTrade(trade)
|
s.state.ProfitStats.AddTrade(trade)
|
||||||
|
|
||||||
|
if profit.Compare(fixedpoint.Zero) == 0 {
|
||||||
s.Environment.RecordPosition(s.state.Position, trade, nil)
|
s.Environment.RecordPosition(s.state.Position, trade, nil)
|
||||||
|
} else {
|
||||||
|
log.Infof("%s generated profit: %v", s.Symbol, profit)
|
||||||
|
p := s.state.Position.NewProfit(trade, profit, netProfit)
|
||||||
|
p.Strategy = ID
|
||||||
|
p.StrategyInstanceID = instanceID
|
||||||
|
s.state.ProfitStats.AddProfit(p)
|
||||||
|
s.Notify(&p)
|
||||||
|
|
||||||
|
s.Environment.RecordPosition(s.state.Position, trade, &p)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
s.tradeCollector.OnPositionUpdate(func(position *types.Position) {
|
s.tradeCollector.OnPositionUpdate(func(position *types.Position) {
|
||||||
|
|
|
@ -605,7 +605,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
|
|
||||||
s.tradeCollector = bbgo.NewTradeCollector(s.Symbol, s.state.Position, s.orderStore)
|
s.tradeCollector = bbgo.NewTradeCollector(s.Symbol, s.state.Position, s.orderStore)
|
||||||
|
|
||||||
s.tradeCollector.OnTrade(func(trade types.Trade) {
|
s.tradeCollector.OnTrade(func(trade types.Trade, profit, netProfit fixedpoint.Value) {
|
||||||
s.Notifiability.Notify(trade)
|
s.Notifiability.Notify(trade)
|
||||||
s.state.ProfitStats.AddTrade(trade)
|
s.state.ProfitStats.AddTrade(trade)
|
||||||
})
|
})
|
||||||
|
|
|
@ -38,6 +38,7 @@ type Strategy struct {
|
||||||
*bbgo.Graceful
|
*bbgo.Graceful
|
||||||
*bbgo.Notifiability
|
*bbgo.Notifiability
|
||||||
*bbgo.Persistence
|
*bbgo.Persistence
|
||||||
|
Environment *bbgo.Environment
|
||||||
|
|
||||||
Symbol string `json:"symbol"`
|
Symbol string `json:"symbol"`
|
||||||
|
|
||||||
|
@ -745,12 +746,12 @@ func (s *Strategy) CrossRun(ctx context.Context, orderExecutionRouter bbgo.Order
|
||||||
s.tradeCollector = bbgo.NewTradeCollector(s.Symbol, s.state.Position, s.orderStore)
|
s.tradeCollector = bbgo.NewTradeCollector(s.Symbol, s.state.Position, s.orderStore)
|
||||||
|
|
||||||
if s.NotifyTrade {
|
if s.NotifyTrade {
|
||||||
s.tradeCollector.OnTrade(func(trade types.Trade) {
|
s.tradeCollector.OnTrade(func(trade types.Trade, profit, netProfit fixedpoint.Value) {
|
||||||
s.Notifiability.Notify(trade)
|
s.Notifiability.Notify(trade)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
s.tradeCollector.OnTrade(func(trade types.Trade) {
|
s.tradeCollector.OnTrade(func(trade types.Trade, profit, netProfit fixedpoint.Value) {
|
||||||
c := trade.PositionChange()
|
c := trade.PositionChange()
|
||||||
if trade.Exchange == s.sourceSession.ExchangeName {
|
if trade.Exchange == s.sourceSession.ExchangeName {
|
||||||
s.state.CoveredPosition = s.state.CoveredPosition.Add(c)
|
s.state.CoveredPosition = s.state.CoveredPosition.Add(c)
|
||||||
|
@ -758,25 +759,25 @@ func (s *Strategy) CrossRun(ctx context.Context, orderExecutionRouter bbgo.Order
|
||||||
|
|
||||||
s.state.ProfitStats.AddTrade(trade)
|
s.state.ProfitStats.AddTrade(trade)
|
||||||
|
|
||||||
|
if profit.Compare(fixedpoint.Zero) == 0 {
|
||||||
|
s.Environment.RecordPosition(s.state.Position, trade, nil)
|
||||||
|
} else {
|
||||||
|
log.Infof("%s generated profit: %v", s.Symbol, profit)
|
||||||
|
|
||||||
|
p := s.state.Position.NewProfit(trade, profit, netProfit)
|
||||||
|
p.Strategy = ID
|
||||||
|
p.StrategyInstanceID = instanceID
|
||||||
|
s.Notify(&p)
|
||||||
|
s.state.ProfitStats.AddProfit(p)
|
||||||
|
|
||||||
|
s.Environment.RecordPosition(s.state.Position, trade, &p)
|
||||||
|
}
|
||||||
|
|
||||||
if err := s.SaveState(); err != nil {
|
if err := s.SaveState(); err != nil {
|
||||||
log.WithError(err).Error("save state error")
|
log.WithError(err).Error("save state error")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
s.tradeCollector.OnProfit(func(trade types.Trade, profit fixedpoint.Value, netProfit fixedpoint.Value) {
|
|
||||||
p := types.Profit{
|
|
||||||
Symbol: s.Symbol,
|
|
||||||
Profit: profit,
|
|
||||||
NetProfit: netProfit,
|
|
||||||
QuoteQuantity: trade.QuoteQuantity,
|
|
||||||
ProfitMargin: profit.Div(trade.QuoteQuantity),
|
|
||||||
NetProfitMargin: netProfit.Div(trade.QuoteQuantity),
|
|
||||||
QuoteCurrency: s.state.Position.QuoteCurrency,
|
|
||||||
BaseCurrency: s.state.Position.BaseCurrency,
|
|
||||||
TradedAt: trade.Time.Time(),
|
|
||||||
}
|
|
||||||
s.state.ProfitStats.AddProfit(p)
|
|
||||||
s.Notify(&p)
|
|
||||||
})
|
|
||||||
s.tradeCollector.OnPositionUpdate(func(position *types.Position) {
|
s.tradeCollector.OnPositionUpdate(func(position *types.Position) {
|
||||||
s.Notifiability.Notify(position)
|
s.Notifiability.Notify(position)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue
Block a user