Merge pull request #1696 from c9s/c9s/fix-convert-nil-issue

FIX: [core] setting.InitializeConverter could return a nil converter object
This commit is contained in:
c9s 2024-08-16 21:52:26 +08:00 committed by GitHub
commit daa1def6d9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 33 additions and 4 deletions

View File

@ -32,9 +32,11 @@ func (s *ConverterSetting) InitializeConverter() (Converter, error) {
logrus.Infof("initializing converter %T ...", converter) logrus.Infof("initializing converter %T ...", converter)
err := converter.Initialize() err := converter.Initialize()
return nil, err return converter, err
} }
// ConverterManager manages the converters for trade conversion
// It can be used to convert the trade symbol into the target symbol, or convert the price, volume into different units.
type ConverterManager struct { type ConverterManager struct {
ConverterSettings []ConverterSetting `json:"converters,omitempty" yaml:"converters,omitempty"` ConverterSettings []ConverterSetting `json:"converters,omitempty" yaml:"converters,omitempty"`
@ -43,15 +45,18 @@ type ConverterManager struct {
func (c *ConverterManager) Initialize() error { func (c *ConverterManager) Initialize() error {
for _, setting := range c.ConverterSettings { for _, setting := range c.ConverterSettings {
converter, err := setting.InitializeConverter() converter, err := setting.InitializeConverter()
if err != nil { if err != nil {
return err return err
} }
c.AddConverter(converter) if converter != nil {
c.AddConverter(converter)
}
} }
numConverters := len(c.converters)
logrus.Infof("%d converters loaded", numConverters)
return nil return nil
} }

View File

@ -9,6 +9,28 @@ import (
"github.com/c9s/bbgo/pkg/types" "github.com/c9s/bbgo/pkg/types"
) )
func TestTradeCollector_NilConvertManager(t *testing.T) {
symbol := "BTCUSDT"
position := types.NewPosition(symbol, "BTC", "USDT")
orderStore := NewOrderStore(symbol)
collector := NewTradeCollector(symbol, position, orderStore)
trade := types.Trade{
ID: 1,
OrderID: 399,
Exchange: types.ExchangeBinance,
Price: fixedpoint.NewFromInt(40000),
Quantity: fixedpoint.One,
QuoteQuantity: fixedpoint.NewFromInt(40000),
Symbol: "BTCUSDT",
Side: types.SideTypeBuy,
IsBuyer: true,
}
trade = collector.ConvertTrade(trade)
assert.Equal(t, "BTCUSDT", trade.Symbol)
}
func TestTradeCollector_ShouldNotCountDuplicatedTrade(t *testing.T) { func TestTradeCollector_ShouldNotCountDuplicatedTrade(t *testing.T) {
symbol := "BTCUSDT" symbol := "BTCUSDT"
position := types.NewPosition(symbol, "BTC", "USDT") position := types.NewPosition(symbol, "BTC", "USDT")

View File

@ -190,6 +190,7 @@ func (p *Position) NewMarketCloseOrder(percentage fixedpoint.Value) *SubmitOrder
} }
} }
// IsDust checks if the position is dust, the first argument is the price to calculate the dust quantity
func (p *Position) IsDust(a ...fixedpoint.Value) bool { func (p *Position) IsDust(a ...fixedpoint.Value) bool {
price := p.AverageCost price := p.AverageCost
if len(a) > 0 { if len(a) > 0 {
@ -448,6 +449,7 @@ func (p *Position) String() string {
) )
} }
// BindStream binds the trade update callback and update the position
func (p *Position) BindStream(stream Stream) { func (p *Position) BindStream(stream Stream) {
stream.OnTradeUpdate(func(trade Trade) { stream.OnTradeUpdate(func(trade Trade) {
if p.Symbol == trade.Symbol { if p.Symbol == trade.Symbol {
@ -540,7 +542,7 @@ func (p *Position) AddTrade(td Trade) (profit fixedpoint.Value, netProfit fixedp
p.addTradeFee(td) p.addTradeFee(td)
// Base > 0 means we're in long position // Base > 0 means we're in long position
// Base < 0 means we're in short position // Base < 0 means we're in short position
switch td.Side { switch td.Side {
case SideTypeBuy: case SideTypeBuy: