pkg/exchange: export SymbolFeeDetail struct

This commit is contained in:
edwin 2024-09-30 21:28:21 +08:00
parent eb2a7421da
commit 7f1e1a3a51
6 changed files with 39 additions and 39 deletions

View File

@ -325,7 +325,7 @@ func v3ToGlobalTrade(trade v3.Trade) (*types.Trade, error) {
}, nil }, nil
} }
func toGlobalTrade(trade bybitapi.Trade, feeDetail symbolFeeDetail) (*types.Trade, error) { func toGlobalTrade(trade bybitapi.Trade, feeDetail SymbolFeeDetail) (*types.Trade, error) {
side, err := toGlobalSideType(trade.Side) side, err := toGlobalSideType(trade.Side)
if err != nil { if err != nil {
return nil, fmt.Errorf("unexpected side: %s, err: %w", trade.Side, err) return nil, fmt.Errorf("unexpected side: %s, err: %w", trade.Side, err)

View File

@ -23,11 +23,11 @@ var (
type FeeRatePoller interface { type FeeRatePoller interface {
Start(ctx context.Context) Start(ctx context.Context)
Get(symbol string) (symbolFeeDetail, bool) Get(symbol string) (SymbolFeeDetail, bool)
Poll(ctx context.Context) error Poll(ctx context.Context) error
} }
type symbolFeeDetail struct { type SymbolFeeDetail struct {
bybitapi.FeeRate bybitapi.FeeRate
BaseCoin string BaseCoin string
@ -43,13 +43,13 @@ type feeRatePoller struct {
// lastSyncTime is the last time the fee rate was updated. // lastSyncTime is the last time the fee rate was updated.
lastSyncTime time.Time lastSyncTime time.Time
symbolFeeDetail map[string]symbolFeeDetail symbolFeeDetail map[string]SymbolFeeDetail
} }
func newFeeRatePoller(marketInfoProvider MarketInfoProvider) *feeRatePoller { func newFeeRatePoller(marketInfoProvider MarketInfoProvider) *feeRatePoller {
return &feeRatePoller{ return &feeRatePoller{
client: marketInfoProvider, client: marketInfoProvider,
symbolFeeDetail: map[string]symbolFeeDetail{}, symbolFeeDetail: map[string]SymbolFeeDetail{},
} }
} }
@ -105,7 +105,7 @@ func (p *feeRatePoller) Poll(ctx context.Context) error {
return nil return nil
} }
func (p *feeRatePoller) Get(symbol string) (symbolFeeDetail, bool) { func (p *feeRatePoller) Get(symbol string) (SymbolFeeDetail, bool) {
p.mu.Lock() p.mu.Lock()
defer p.mu.Unlock() defer p.mu.Unlock()
@ -113,16 +113,16 @@ func (p *feeRatePoller) Get(symbol string) (symbolFeeDetail, bool) {
return fee, found return fee, found
} }
func (e *feeRatePoller) getAllFeeRates(ctx context.Context) (map[string]symbolFeeDetail, error) { func (e *feeRatePoller) getAllFeeRates(ctx context.Context) (map[string]SymbolFeeDetail, error) {
feeRates, err := e.client.GetAllFeeRates(ctx) feeRates, err := e.client.GetAllFeeRates(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to call get fee rates: %w", err) return nil, fmt.Errorf("failed to call get fee rates: %w", err)
} }
symbolMap := map[string]symbolFeeDetail{} symbolMap := map[string]SymbolFeeDetail{}
for _, f := range feeRates.List { for _, f := range feeRates.List {
if _, found := symbolMap[f.Symbol]; !found { if _, found := symbolMap[f.Symbol]; !found {
symbolMap[f.Symbol] = symbolFeeDetail{FeeRate: f} symbolMap[f.Symbol] = SymbolFeeDetail{FeeRate: f}
} }
} }
@ -131,7 +131,7 @@ func (e *feeRatePoller) getAllFeeRates(ctx context.Context) (map[string]symbolFe
return nil, fmt.Errorf("failed to get markets: %w", err) return nil, fmt.Errorf("failed to get markets: %w", err)
} }
// update base coin, quote coin into symbolFeeDetail // update base coin, quote coin into SymbolFeeDetail
for _, mkt := range mkts { for _, mkt := range mkts {
feeRate, found := symbolMap[mkt.Symbol] feeRate, found := symbolMap[mkt.Symbol]
if !found { if !found {

View File

@ -62,7 +62,7 @@ func TestFeeRatePoller_getAllFeeRates(t *testing.T) {
mockMarketProvider.EXPECT().GetAllFeeRates(ctx).Return(feeRates, nil).Times(1) mockMarketProvider.EXPECT().GetAllFeeRates(ctx).Return(feeRates, nil).Times(1)
mockMarketProvider.EXPECT().QueryMarkets(ctx).Return(mkts, nil).Times(1) mockMarketProvider.EXPECT().QueryMarkets(ctx).Return(mkts, nil).Times(1)
expFeeRates := map[string]symbolFeeDetail{ expFeeRates := map[string]SymbolFeeDetail{
"BTCUSDT": { "BTCUSDT": {
FeeRate: feeRates.List[0], FeeRate: feeRates.List[0],
BaseCoin: "BTC", BaseCoin: "BTC",
@ -111,7 +111,7 @@ func TestFeeRatePoller_getAllFeeRates(t *testing.T) {
symbolFeeDetails, err := s.getAllFeeRates(ctx) symbolFeeDetails, err := s.getAllFeeRates(ctx)
assert.Equal(t, fmt.Errorf("failed to get markets: %w", unknownErr), err) assert.Equal(t, fmt.Errorf("failed to get markets: %w", unknownErr), err)
assert.Equal(t, map[string]symbolFeeDetail(nil), symbolFeeDetails) assert.Equal(t, map[string]SymbolFeeDetail(nil), symbolFeeDetails)
}) })
t.Run("failed to get fee rates", func(t *testing.T) { t.Run("failed to get fee rates", func(t *testing.T) {
@ -126,7 +126,7 @@ func TestFeeRatePoller_getAllFeeRates(t *testing.T) {
symbolFeeDetails, err := s.getAllFeeRates(ctx) symbolFeeDetails, err := s.getAllFeeRates(ctx)
assert.Equal(t, fmt.Errorf("failed to call get fee rates: %w", unknownErr), err) assert.Equal(t, fmt.Errorf("failed to call get fee rates: %w", unknownErr), err)
assert.Equal(t, map[string]symbolFeeDetail(nil), symbolFeeDetails) assert.Equal(t, map[string]SymbolFeeDetail(nil), symbolFeeDetails)
}) })
} }
@ -137,7 +137,7 @@ func Test_feeRatePoller_Get(t *testing.T) {
mockMarketProvider := mocks.NewMockStreamDataProvider(mockCtrl) mockMarketProvider := mocks.NewMockStreamDataProvider(mockCtrl)
t.Run("found", func(t *testing.T) { t.Run("found", func(t *testing.T) {
symbol := "BTCUSDT" symbol := "BTCUSDT"
expFeeDetail := symbolFeeDetail{ expFeeDetail := SymbolFeeDetail{
FeeRate: bybitapi.FeeRate{ FeeRate: bybitapi.FeeRate{
Symbol: symbol, Symbol: symbol,
TakerFeeRate: fixedpoint.NewFromFloat(0.1), TakerFeeRate: fixedpoint.NewFromFloat(0.1),
@ -149,7 +149,7 @@ func Test_feeRatePoller_Get(t *testing.T) {
s := &feeRatePoller{ s := &feeRatePoller{
client: mockMarketProvider, client: mockMarketProvider,
symbolFeeDetail: map[string]symbolFeeDetail{ symbolFeeDetail: map[string]SymbolFeeDetail{
symbol: expFeeDetail, symbol: expFeeDetail,
}, },
} }
@ -162,7 +162,7 @@ func Test_feeRatePoller_Get(t *testing.T) {
symbol := "BTCUSDT" symbol := "BTCUSDT"
s := &feeRatePoller{ s := &feeRatePoller{
client: mockMarketProvider, client: mockMarketProvider,
symbolFeeDetail: map[string]symbolFeeDetail{}, symbolFeeDetail: map[string]SymbolFeeDetail{},
} }
_, found := s.Get(symbol) _, found := s.Get(symbol)

View File

@ -439,18 +439,18 @@ func (s *Stream) handleKLineEvent(klineEvent KLineEvent) {
} }
} }
func pollAndGetFeeRate(ctx context.Context, symbol string, poller FeeRatePoller, marketsInfo types.MarketMap) (symbolFeeDetail, error) { func pollAndGetFeeRate(ctx context.Context, symbol string, poller FeeRatePoller, marketsInfo types.MarketMap) (SymbolFeeDetail, error) {
err := poller.Poll(ctx) err := poller.Poll(ctx)
if err != nil { if err != nil {
return symbolFeeDetail{}, err return SymbolFeeDetail{}, err
} }
return getFeeRate(symbol, poller, marketsInfo), nil return getFeeRate(symbol, poller, marketsInfo), nil
} }
func getFeeRate(symbol string, poller FeeRatePoller, marketsInfo types.MarketMap) symbolFeeDetail { func getFeeRate(symbol string, poller FeeRatePoller, marketsInfo types.MarketMap) SymbolFeeDetail {
feeRate, found := poller.Get(symbol) feeRate, found := poller.Get(symbol)
if !found { if !found {
feeRate = symbolFeeDetail{ feeRate = SymbolFeeDetail{
FeeRate: bybitapi.FeeRate{ FeeRate: bybitapi.FeeRate{
Symbol: symbol, Symbol: symbol,
TakerFeeRate: defaultTakerFee, TakerFeeRate: defaultTakerFee,

View File

@ -327,7 +327,7 @@ type TradeEvent struct {
TradeIv string `json:"tradeIv"` TradeIv string `json:"tradeIv"`
} }
func (t *TradeEvent) toGlobalTrade(symbolFee symbolFeeDetail) (*types.Trade, error) { func (t *TradeEvent) toGlobalTrade(symbolFee SymbolFeeDetail) (*types.Trade, error) {
if t.Category != bybitapi.CategorySpot { if t.Category != bybitapi.CategorySpot {
return nil, fmt.Errorf("unexected category: %s", t.Category) return nil, fmt.Errorf("unexected category: %s", t.Category)
} }
@ -385,7 +385,7 @@ func (t *TradeEvent) toGlobalTrade(symbolFee symbolFeeDetail) (*types.Trade, err
// IsMakerOrder = FALSE // IsMakerOrder = FALSE
// -> Side = Buy -> base currency (BTC) // -> Side = Buy -> base currency (BTC)
// -> Side = Sell -> quote currency (USDT) // -> Side = Sell -> quote currency (USDT)
func calculateFee(t bybitapi.Trade, feeDetail symbolFeeDetail) (string, fixedpoint.Value) { func calculateFee(t bybitapi.Trade, feeDetail SymbolFeeDetail) (string, fixedpoint.Value) {
if feeDetail.MakerFeeRate.Sign() > 0 || !t.IsMaker { if feeDetail.MakerFeeRate.Sign() > 0 || !t.IsMaker {
if t.Side == bybitapi.SideBuy { if t.Side == bybitapi.SideBuy {
return feeDetail.BaseCoin, baseCoinAsFee(t, feeDetail) return feeDetail.BaseCoin, baseCoinAsFee(t, feeDetail)
@ -399,14 +399,14 @@ func calculateFee(t bybitapi.Trade, feeDetail symbolFeeDetail) (string, fixedpoi
return feeDetail.BaseCoin, baseCoinAsFee(t, feeDetail) return feeDetail.BaseCoin, baseCoinAsFee(t, feeDetail)
} }
func baseCoinAsFee(t bybitapi.Trade, feeDetail symbolFeeDetail) fixedpoint.Value { func baseCoinAsFee(t bybitapi.Trade, feeDetail SymbolFeeDetail) fixedpoint.Value {
if t.IsMaker { if t.IsMaker {
return feeDetail.MakerFeeRate.Mul(t.ExecQty) return feeDetail.MakerFeeRate.Mul(t.ExecQty)
} }
return feeDetail.TakerFeeRate.Mul(t.ExecQty) return feeDetail.TakerFeeRate.Mul(t.ExecQty)
} }
func quoteCoinAsFee(t bybitapi.Trade, feeDetail symbolFeeDetail) fixedpoint.Value { func quoteCoinAsFee(t bybitapi.Trade, feeDetail SymbolFeeDetail) fixedpoint.Value {
baseFee := t.ExecPrice.Mul(t.ExecQty) baseFee := t.ExecPrice.Mul(t.ExecQty)
if t.IsMaker { if t.IsMaker {
return feeDetail.MakerFeeRate.Mul(baseFee) return feeDetail.MakerFeeRate.Mul(baseFee)

View File

@ -528,7 +528,7 @@ func TestTradeEvent_toGlobalTrade(t *testing.T) {
} }
*/ */
t.Run("succeeds", func(t *testing.T) { t.Run("succeeds", func(t *testing.T) {
symbolFee := symbolFeeDetail{ symbolFee := SymbolFeeDetail{
FeeRate: bybitapi.FeeRate{ FeeRate: bybitapi.FeeRate{
Symbol: "BTCUSDT", Symbol: "BTCUSDT",
TakerFeeRate: fixedpoint.NewFromFloat(0.001), TakerFeeRate: fixedpoint.NewFromFloat(0.001),
@ -597,7 +597,7 @@ func TestTradeEvent_toGlobalTrade(t *testing.T) {
Category: "test-spot", Category: "test-spot",
} }
actualTrade, err := tradeEvent.toGlobalTrade(symbolFeeDetail{}) actualTrade, err := tradeEvent.toGlobalTrade(SymbolFeeDetail{})
assert.Equal(t, fmt.Errorf("unexected category: %s", tradeEvent.Category), err) assert.Equal(t, fmt.Errorf("unexected category: %s", tradeEvent.Category), err)
assert.Nil(t, actualTrade) assert.Nil(t, actualTrade)
}) })
@ -610,7 +610,7 @@ func TestTradeEvent_toGlobalTrade(t *testing.T) {
Category: "spot", Category: "spot",
} }
actualTrade, err := tradeEvent.toGlobalTrade(symbolFeeDetail{}) actualTrade, err := tradeEvent.toGlobalTrade(SymbolFeeDetail{})
assert.Equal(t, fmt.Errorf("unexpected side: BOTH"), err) assert.Equal(t, fmt.Errorf("unexpected side: BOTH"), err)
assert.Nil(t, actualTrade) assert.Nil(t, actualTrade)
}) })
@ -625,7 +625,7 @@ func TestTradeEvent_toGlobalTrade(t *testing.T) {
} }
_, nerr := strconv.ParseUint(tradeEvent.OrderId, 10, 64) _, nerr := strconv.ParseUint(tradeEvent.OrderId, 10, 64)
actualTrade, err := tradeEvent.toGlobalTrade(symbolFeeDetail{}) actualTrade, err := tradeEvent.toGlobalTrade(SymbolFeeDetail{})
assert.Equal(t, fmt.Errorf("unexpected order id: %s, err: %w", tradeEvent.OrderId, nerr), err) assert.Equal(t, fmt.Errorf("unexpected order id: %s, err: %w", tradeEvent.OrderId, nerr), err)
assert.Nil(t, actualTrade) assert.Nil(t, actualTrade)
}) })
@ -641,7 +641,7 @@ func TestTradeEvent_toGlobalTrade(t *testing.T) {
} }
_, nerr := strconv.ParseUint(tradeEvent.ExecId, 10, 64) _, nerr := strconv.ParseUint(tradeEvent.ExecId, 10, 64)
actualTrade, err := tradeEvent.toGlobalTrade(symbolFeeDetail{}) actualTrade, err := tradeEvent.toGlobalTrade(SymbolFeeDetail{})
assert.Equal(t, fmt.Errorf("unexpected exec id: %s, err: %w", tradeEvent.ExecId, nerr), err) assert.Equal(t, fmt.Errorf("unexpected exec id: %s, err: %w", tradeEvent.ExecId, nerr), err)
assert.Nil(t, actualTrade) assert.Nil(t, actualTrade)
}) })
@ -649,7 +649,7 @@ func TestTradeEvent_toGlobalTrade(t *testing.T) {
func TestTradeEvent_CalculateFee(t *testing.T) { func TestTradeEvent_CalculateFee(t *testing.T) {
t.Run("maker fee positive, maker, buyer", func(t *testing.T) { t.Run("maker fee positive, maker, buyer", func(t *testing.T) {
symbolFee := symbolFeeDetail{ symbolFee := SymbolFeeDetail{
FeeRate: bybitapi.FeeRate{ FeeRate: bybitapi.FeeRate{
Symbol: "BTCUSDT", Symbol: "BTCUSDT",
TakerFeeRate: fixedpoint.NewFromFloat(0.001), TakerFeeRate: fixedpoint.NewFromFloat(0.001),
@ -676,7 +676,7 @@ func TestTradeEvent_CalculateFee(t *testing.T) {
}) })
t.Run("maker fee positive, maker, seller", func(t *testing.T) { t.Run("maker fee positive, maker, seller", func(t *testing.T) {
symbolFee := symbolFeeDetail{ symbolFee := SymbolFeeDetail{
FeeRate: bybitapi.FeeRate{ FeeRate: bybitapi.FeeRate{
Symbol: "BTCUSDT", Symbol: "BTCUSDT",
TakerFeeRate: fixedpoint.NewFromFloat(0.001), TakerFeeRate: fixedpoint.NewFromFloat(0.001),
@ -703,7 +703,7 @@ func TestTradeEvent_CalculateFee(t *testing.T) {
}) })
t.Run("maker fee positive, taker, buyer", func(t *testing.T) { t.Run("maker fee positive, taker, buyer", func(t *testing.T) {
symbolFee := symbolFeeDetail{ symbolFee := SymbolFeeDetail{
FeeRate: bybitapi.FeeRate{ FeeRate: bybitapi.FeeRate{
Symbol: "BTCUSDT", Symbol: "BTCUSDT",
TakerFeeRate: fixedpoint.NewFromFloat(0.001), TakerFeeRate: fixedpoint.NewFromFloat(0.001),
@ -730,7 +730,7 @@ func TestTradeEvent_CalculateFee(t *testing.T) {
}) })
t.Run("maker fee positive, taker, seller", func(t *testing.T) { t.Run("maker fee positive, taker, seller", func(t *testing.T) {
symbolFee := symbolFeeDetail{ symbolFee := SymbolFeeDetail{
FeeRate: bybitapi.FeeRate{ FeeRate: bybitapi.FeeRate{
Symbol: "BTCUSDT", Symbol: "BTCUSDT",
TakerFeeRate: fixedpoint.NewFromFloat(0.001), TakerFeeRate: fixedpoint.NewFromFloat(0.001),
@ -757,7 +757,7 @@ func TestTradeEvent_CalculateFee(t *testing.T) {
}) })
t.Run("maker fee negative, maker, buyer", func(t *testing.T) { t.Run("maker fee negative, maker, buyer", func(t *testing.T) {
symbolFee := symbolFeeDetail{ symbolFee := SymbolFeeDetail{
FeeRate: bybitapi.FeeRate{ FeeRate: bybitapi.FeeRate{
Symbol: "BTCUSDT", Symbol: "BTCUSDT",
TakerFeeRate: fixedpoint.NewFromFloat(-0.001), TakerFeeRate: fixedpoint.NewFromFloat(-0.001),
@ -784,7 +784,7 @@ func TestTradeEvent_CalculateFee(t *testing.T) {
}) })
t.Run("maker fee negative, maker, seller", func(t *testing.T) { t.Run("maker fee negative, maker, seller", func(t *testing.T) {
symbolFee := symbolFeeDetail{ symbolFee := SymbolFeeDetail{
FeeRate: bybitapi.FeeRate{ FeeRate: bybitapi.FeeRate{
Symbol: "BTCUSDT", Symbol: "BTCUSDT",
TakerFeeRate: fixedpoint.NewFromFloat(-0.001), TakerFeeRate: fixedpoint.NewFromFloat(-0.001),
@ -811,7 +811,7 @@ func TestTradeEvent_CalculateFee(t *testing.T) {
}) })
t.Run("maker fee negative, taker, buyer", func(t *testing.T) { t.Run("maker fee negative, taker, buyer", func(t *testing.T) {
symbolFee := symbolFeeDetail{ symbolFee := SymbolFeeDetail{
FeeRate: bybitapi.FeeRate{ FeeRate: bybitapi.FeeRate{
Symbol: "BTCUSDT", Symbol: "BTCUSDT",
TakerFeeRate: fixedpoint.NewFromFloat(-0.001), TakerFeeRate: fixedpoint.NewFromFloat(-0.001),
@ -838,7 +838,7 @@ func TestTradeEvent_CalculateFee(t *testing.T) {
}) })
t.Run("maker fee negative, taker, seller", func(t *testing.T) { t.Run("maker fee negative, taker, seller", func(t *testing.T) {
symbolFee := symbolFeeDetail{ symbolFee := SymbolFeeDetail{
FeeRate: bybitapi.FeeRate{ FeeRate: bybitapi.FeeRate{
Symbol: "BTCUSDT", Symbol: "BTCUSDT",
TakerFeeRate: fixedpoint.NewFromFloat(-0.001), TakerFeeRate: fixedpoint.NewFromFloat(-0.001),
@ -867,7 +867,7 @@ func TestTradeEvent_CalculateFee(t *testing.T) {
} }
func TestTradeEvent_baseCoinAsFee(t *testing.T) { func TestTradeEvent_baseCoinAsFee(t *testing.T) {
symbolFee := symbolFeeDetail{ symbolFee := SymbolFeeDetail{
FeeRate: bybitapi.FeeRate{ FeeRate: bybitapi.FeeRate{
Symbol: "BTCUSDT", Symbol: "BTCUSDT",
TakerFeeRate: fixedpoint.NewFromFloat(0.001), TakerFeeRate: fixedpoint.NewFromFloat(0.001),
@ -892,7 +892,7 @@ func TestTradeEvent_baseCoinAsFee(t *testing.T) {
} }
func TestTradeEvent_quoteCoinAsFee(t *testing.T) { func TestTradeEvent_quoteCoinAsFee(t *testing.T) {
symbolFee := symbolFeeDetail{ symbolFee := SymbolFeeDetail{
FeeRate: bybitapi.FeeRate{ FeeRate: bybitapi.FeeRate{
Symbol: "BTCUSDT", Symbol: "BTCUSDT",
TakerFeeRate: fixedpoint.NewFromFloat(0.001), TakerFeeRate: fixedpoint.NewFromFloat(0.001),