From b54b1aa2e78a692bd04fbcb05e0ad8ec18ccb9d3 Mon Sep 17 00:00:00 2001 From: Valentin Nikolaev Date: Wed, 13 Mar 2024 17:51:08 +0300 Subject: [PATCH 1/2] Add functions to fetch funding rate data from market --- v2/futures/client.go | 10 +++ v2/futures/funding_rate_history.go | 82 +++++++++++++++++++++++++ v2/futures/funding_rate_history_test.go | 78 +++++++++++++++++++++++ v2/futures/funding_rate_info.go | 42 +++++++++++++ v2/futures/funding_rate_info_test.go | 50 +++++++++++++++ 5 files changed, 262 insertions(+) create mode 100644 v2/futures/funding_rate_history.go create mode 100644 v2/futures/funding_rate_history_test.go create mode 100644 v2/futures/funding_rate_info.go create mode 100644 v2/futures/funding_rate_info_test.go diff --git a/v2/futures/client.go b/v2/futures/client.go index e8832dc9..ae0b5878 100644 --- a/v2/futures/client.go +++ b/v2/futures/client.go @@ -546,6 +546,16 @@ func (c *Client) NewFundingRateService() *FundingRateService { return &FundingRateService{c: c} } +// NewFundingRateHistoryService init funding rate history service +func (c *Client) NewFundingRateHistoryService() *FundingRateHistoryService { + return &FundingRateHistoryService{c: c} +} + +// NewFundingRateInfoService init funding rate info service +func (c *Client) NewFundingRateInfoService() *FundingRateInfoService { + return &FundingRateInfoService{c: c} +} + // NewListUserLiquidationOrdersService init list user's liquidation orders service func (c *Client) NewListUserLiquidationOrdersService() *ListUserLiquidationOrdersService { return &ListUserLiquidationOrdersService{c: c} diff --git a/v2/futures/funding_rate_history.go b/v2/futures/funding_rate_history.go new file mode 100644 index 00000000..ab0b5f24 --- /dev/null +++ b/v2/futures/funding_rate_history.go @@ -0,0 +1,82 @@ +package futures + +import ( + "context" + "encoding/json" + "net/http" + + "github.com/adshao/go-binance/v2/common" +) + +// FundingRateHistoryService gets funding rate history +type FundingRateHistoryService struct { + c *Client + symbol *string + startTime *int64 + endTime *int64 + limit *int +} + +// Symbol set symbol +func (s *FundingRateHistoryService) Symbol(symbol string) *FundingRateHistoryService { + s.symbol = &symbol + return s +} + +// StartTime set startTime +func (s *FundingRateHistoryService) StartTime(startTime int64) *FundingRateHistoryService { + s.startTime = &startTime + return s +} + +// EndTime set startTime +func (s *FundingRateHistoryService) EndTime(endTime int64) *FundingRateHistoryService { + s.endTime = &endTime + return s +} + +// Limit set limit +func (s *FundingRateHistoryService) Limit(limit int) *FundingRateHistoryService { + s.limit = &limit + return s +} + +// Do send request +func (s *FundingRateHistoryService) Do(ctx context.Context, opts ...RequestOption) (res []*FundingRateHistory, err error) { + r := &request{ + method: http.MethodGet, + endpoint: "/fapi/v1/fundingRate", + secType: secTypeNone, + } + if s.symbol != nil { + r.setParam("symbol", *s.symbol) + } + if s.startTime != nil { + r.setParam("startTime", *s.startTime) + } + if s.endTime != nil { + r.setParam("endTime", *s.endTime) + } + if s.limit != nil { + r.setParam("limit", *s.limit) + } + data, _, err := s.c.callAPI(ctx, r, opts...) + data = common.ToJSONList(data) + if err != nil { + return []*FundingRateHistory{}, err + } + res = make([]*FundingRateHistory, 0) + err = json.Unmarshal(data, &res) + if err != nil { + return []*FundingRateHistory{}, err + } + return res, nil +} + +// FundingRateHistory defines funding rate history data +type FundingRateHistory struct { + Symbol string `json:"symbol"` + FundingTime int64 `json:"fundingTime"` + FundingRate string `json:"fundingRate"` + MarkPrice string `json:"markPrice"` +} diff --git a/v2/futures/funding_rate_history_test.go b/v2/futures/funding_rate_history_test.go new file mode 100644 index 00000000..2fadbd69 --- /dev/null +++ b/v2/futures/funding_rate_history_test.go @@ -0,0 +1,78 @@ +package futures + +import ( + "context" + "fmt" + "github.com/stretchr/testify/require" + "testing" + "time" + + "github.com/stretchr/testify/suite" +) + +type fundingRateHistoryServiceTestSuite struct { + baseTestSuite +} + +func TestFundingRateHistoryService(t *testing.T) { + suite.Run(t, new(fundingRateHistoryServiceTestSuite)) +} + +func (s *fundingRateHistoryServiceTestSuite) TestGetFundingRateHistory() { + data := []byte(`[{ + "symbol": "BTCUSDT", + "fundingTime": 1698768000000, + "fundingRate": "0.00010000", + "markPrice": "34287.54619963" + }]`) + s.mockDo(data, nil) + defer s.assertDo() + + symbol := "BTCUSDT" + startTime := int64(1576566020000) + endTime := int64(1676566020000) + limit := 10 + s.assertReq(func(r *request) { + e := newRequest().setParams(params{ + "symbol": symbol, + "startTime": startTime, + "endTime": endTime, + "limit": limit, + }) + s.assertRequestEqual(e, r) + }) + + res, err := s.client.NewFundingRateHistoryService().Symbol(symbol).StartTime(startTime).EndTime(endTime).Limit(limit).Do(newContext()) + s.r().NoError(err) + e := []*FundingRateHistory{ + { + Symbol: symbol, + FundingTime: 1698768000000, + FundingRate: "0.00010000", + MarkPrice: "34287.54619963", + }, + } + s.assertFundingRateHistoryEqual(e, res) +} + +func (s *fundingRateHistoryServiceTestSuite) assertFundingRateHistoryEqual(e, a []*FundingRateHistory) { + r := s.r() + r.Equal(e[0].Symbol, a[0].Symbol, "Symbol") + r.Equal(e[0].FundingRate, a[0].FundingRate, "FundingRate") + r.Equal(e[0].FundingTime, a[0].FundingTime, "FundingTime") + r.Equal(e[0].MarkPrice, a[0].MarkPrice, "MarkPrice") +} + +func TestName(t *testing.T) { + client := NewClient("", "") + + ctx, cancelFunc := context.WithDeadline(context.Background(), time.Now().Add(time.Second*5)) + defer cancelFunc() + + rateHistory, err := client.NewFundingRateHistoryService().Do(ctx) + require.NoError(t, err) + + for i := 0; i < 5; i++ { + fmt.Printf("%+v\n", rateHistory[i]) + } +} diff --git a/v2/futures/funding_rate_info.go b/v2/futures/funding_rate_info.go new file mode 100644 index 00000000..1ade1231 --- /dev/null +++ b/v2/futures/funding_rate_info.go @@ -0,0 +1,42 @@ +package futures + +import ( + "context" + "encoding/json" + "net/http" + + "github.com/adshao/go-binance/v2/common" +) + +// FundingRateInfoService gets funding rate info +type FundingRateInfoService struct { + c *Client +} + +// Do sends request +func (s *FundingRateInfoService) Do(ctx context.Context, opts ...RequestOption) (res []*FundingRateInfo, err error) { + r := &request{ + method: http.MethodGet, + endpoint: "/fapi/v1/fundingInfo", + secType: secTypeNone, + } + data, _, err := s.c.callAPI(ctx, r, opts...) + data = common.ToJSONList(data) + if err != nil { + return []*FundingRateInfo{}, err + } + res = make([]*FundingRateInfo, 0) + err = json.Unmarshal(data, &res) + if err != nil { + return []*FundingRateInfo{}, err + } + return res, nil +} + +// FundingRateInfo defines funding rate info for symbols +type FundingRateInfo struct { + Symbol string `json:"symbol"` + AdjustedFundingRateCap string `json:"adjustedFundingRateCap"` + AdjustedFundingRateFloor string `json:"adjustedFundingRateFloor"` + FundingIntervalHours int64 `json:"fundingIntervalHours"` +} diff --git a/v2/futures/funding_rate_info_test.go b/v2/futures/funding_rate_info_test.go new file mode 100644 index 00000000..71e98328 --- /dev/null +++ b/v2/futures/funding_rate_info_test.go @@ -0,0 +1,50 @@ +package futures + +import ( + "github.com/stretchr/testify/suite" + "testing" +) + +type fundingRateInfoServiceTestSuite struct { + baseTestSuite +} + +func TestFundingRateInfoService(t *testing.T) { + suite.Run(t, new(fundingRateInfoServiceTestSuite)) +} + +func (s *fundingRateInfoServiceTestSuite) TestGetFundingRateInfo() { + data := []byte(`[{ + "symbol": "BTCUSDT", + "adjustedFundingRateCap": "0.02500000", + "adjustedFundingRateFloor": "-0.02500000", + "fundingIntervalHours": 8 + }]`) + s.mockDo(data, nil) + defer s.assertDo() + + s.assertReq(func(r *request) { + e := newRequest() + s.assertRequestEqual(e, r) + }) + + res, err := s.client.NewFundingRateInfoService().Do(newContext()) + s.r().NoError(err) + e := []*FundingRateInfo{ + { + Symbol: "BTCUSDT", + AdjustedFundingRateCap: "0.02500000", + AdjustedFundingRateFloor: "-0.02500000", + FundingIntervalHours: 8, + }, + } + s.assertFundingRateInfoEqual(e, res) +} + +func (s *fundingRateInfoServiceTestSuite) assertFundingRateInfoEqual(e, a []*FundingRateInfo) { + r := s.r() + r.Equal(e[0].Symbol, a[0].Symbol, "Symbol") + r.Equal(e[0].AdjustedFundingRateCap, a[0].AdjustedFundingRateCap, "AdjustedFundingRateCap") + r.Equal(e[0].AdjustedFundingRateFloor, a[0].AdjustedFundingRateFloor, "AdjustedFundingRateFloor") + r.Equal(e[0].FundingIntervalHours, a[0].FundingIntervalHours, "FundingIntervalHours") +} From 994f76cb3f5c85a7e61195d2306043c08765b3b7 Mon Sep 17 00:00:00 2001 From: Valentin Nikolaev Date: Wed, 24 Apr 2024 12:07:59 +0300 Subject: [PATCH 2/2] Remove invalid test function --- v2/futures/funding_rate_history_test.go | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/v2/futures/funding_rate_history_test.go b/v2/futures/funding_rate_history_test.go index 2fadbd69..39ee476d 100644 --- a/v2/futures/funding_rate_history_test.go +++ b/v2/futures/funding_rate_history_test.go @@ -1,13 +1,8 @@ package futures import ( - "context" - "fmt" - "github.com/stretchr/testify/require" - "testing" - "time" - "github.com/stretchr/testify/suite" + "testing" ) type fundingRateHistoryServiceTestSuite struct { @@ -62,17 +57,3 @@ func (s *fundingRateHistoryServiceTestSuite) assertFundingRateHistoryEqual(e, a r.Equal(e[0].FundingTime, a[0].FundingTime, "FundingTime") r.Equal(e[0].MarkPrice, a[0].MarkPrice, "MarkPrice") } - -func TestName(t *testing.T) { - client := NewClient("", "") - - ctx, cancelFunc := context.WithDeadline(context.Background(), time.Now().Add(time.Second*5)) - defer cancelFunc() - - rateHistory, err := client.NewFundingRateHistoryService().Do(ctx) - require.NoError(t, err) - - for i := 0; i < 5; i++ { - fmt.Printf("%+v\n", rateHistory[i]) - } -}