bbgo_origin/pkg/strategy/xdepthmaker/profitfixer.go
2024-03-05 18:12:30 +08:00

86 lines
1.9 KiB
Go

package xdepthmaker
import (
"context"
"sync"
"time"
"golang.org/x/sync/errgroup"
"github.com/c9s/bbgo/pkg/exchange/batch"
"github.com/c9s/bbgo/pkg/types"
)
type ProfitFixerConfig struct {
TradesSince types.Time `json:"tradesSince,omitempty"`
}
// ProfitFixer implements a trade history based profit fixer
type ProfitFixer struct {
market types.Market
sessions map[string]types.ExchangeTradeHistoryService
}
func NewProfitFixer(market types.Market) *ProfitFixer {
return &ProfitFixer{
market: market,
sessions: make(map[string]types.ExchangeTradeHistoryService),
}
}
func (f *ProfitFixer) AddExchange(sessionName string, service types.ExchangeTradeHistoryService) {
f.sessions[sessionName] = service
}
func (f *ProfitFixer) batchQueryTrades(
ctx context.Context,
service types.ExchangeTradeHistoryService,
symbol string,
since time.Time,
) ([]types.Trade, error) {
now := time.Now()
q := &batch.TradeBatchQuery{ExchangeTradeHistoryService: service}
trades, err := q.QueryTrades(ctx, symbol, &types.TradeQueryOptions{
StartTime: &since,
EndTime: &now,
})
return trades, err
}
func (f *ProfitFixer) Fix(ctx context.Context, since time.Time) (*types.ProfitStats, error) {
stats := types.NewProfitStats(f.market)
var mu sync.Mutex
var allTrades = make([]types.Trade, 0, 1000)
g, subCtx := errgroup.WithContext(ctx)
for _, service := range f.sessions {
g.Go(func() error {
trades, err := f.batchQueryTrades(subCtx, service, f.market.Symbol, since)
if err != nil {
log.WithError(err).Errorf("unable to batch query trades for fixer")
return err
}
mu.Lock()
allTrades = append(allTrades, trades...)
mu.Unlock()
return nil
})
}
if err := g.Wait(); err != nil {
return nil, err
}
allTrades = types.SortTradesAscending(allTrades)
for _, trade := range allTrades {
stats.AddTrade(trade)
}
return stats, nil
}