Update market request

This commit is contained in:
isther 2024-01-04 21:20:40 +08:00
parent da22696037
commit 02aaf3d098
7 changed files with 2676 additions and 478 deletions

View File

@ -6,17 +6,21 @@ import (
"crypto/hmac" "crypto/hmac"
"crypto/sha256" "crypto/sha256"
"encoding/hex" "encoding/hex"
"encoding/json"
"fmt" "fmt"
"github.com/wuhewuhe/bybit.go.api/handlers"
"io" "io"
"log" "log"
"net/http" "net/http"
"os" "os"
"strconv" "strconv"
"time" "time"
"github.com/bitly/go-simplejson"
jsoniter "github.com/json-iterator/go"
"github.com/wuhewuhe/bybit.go.api/handlers"
) )
var json = jsoniter.ConfigCompatibleWithStandardLibrary
type ServerResponse struct { type ServerResponse struct {
RetCode int `json:"retCode"` RetCode int `json:"retCode"`
RetMsg string `json:"retMsg"` RetMsg string `json:"retMsg"`
@ -77,6 +81,14 @@ func GetCurrentTime() int64 {
return timeStamp return timeStamp
} }
func newJSON(data []byte) (j *simplejson.Json, err error) {
j, err = simplejson.NewJson(data)
if err != nil {
return nil, err
}
return j, nil
}
// NewBybitHttpClient NewClient Create client function for initialising new Bybit client // NewBybitHttpClient NewClient Create client function for initialising new Bybit client
func NewBybitHttpClient(apiKey string, APISecret string, options ...ClientOption) *Client { func NewBybitHttpClient(apiKey string, APISecret string, options ...ClientOption) *Client {
c := &Client{ c := &Client{
@ -152,6 +164,9 @@ func (c *Client) parseRequest(r *request, opts ...RequestOption) (err error) {
func (c *Client) callAPI(ctx context.Context, r *request, opts ...RequestOption) (data []byte, err error) { func (c *Client) callAPI(ctx context.Context, r *request, opts ...RequestOption) (data []byte, err error) {
err = c.parseRequest(r, opts...) err = c.parseRequest(r, opts...)
if err != nil {
return nil, err
}
req, err := http.NewRequest(r.method, r.fullURL, r.body) req, err := http.NewRequest(r.method, r.fullURL, r.body)
if err != nil { if err != nil {
return []byte{}, err return []byte{}, err
@ -196,36 +211,79 @@ func (c *Client) callAPI(ctx context.Context, r *request, opts ...RequestOption)
return data, nil return data, nil
} }
// NewMarketKlineService Market Endpoints func (c *Client) NewInstrumentsInfoService() *InstrumentsInfoService {
func (c *Client) NewMarketKlineService(klineType, category, symbol, interval string) *Klines { return &InstrumentsInfoService{c: c}
return &Klines{
c: c,
category: category,
symbol: symbol,
interval: interval,
klineType: klineType,
}
} }
func (c *Client) NewMarketKLinesService(klineType string, params map[string]interface{}) *MarketClient { // NewMarketKlineService Market Kline Endpoints
return &MarketClient{ func (c *Client) NewMarketKlineService() *MarketKlinesService {
c: c, return &MarketKlinesService{c: c}
klineType: klineType,
params: params,
}
} }
func (c *Client) NewMarketInfoServiceNoParams() *MarketClient { // NewMarketMarkPriceKlineService Market Mark Price Kline Endpoints
return &MarketClient{ func (c *Client) NewMarketMarkPriceKlineService() *MarketMarkPriceKlineService {
c: c, return &MarketMarkPriceKlineService{c: c}
}
} }
func (c *Client) NewMarketInfoService(params map[string]interface{}) *MarketClient { // NewMarketIndexPriceKlineService Market Index Price Kline Endpoints
return &MarketClient{ func (c *Client) NewMarketIndexPriceKlineService() *MarketIndexPriceKlineService {
c: c, return &MarketIndexPriceKlineService{c: c}
params: params,
} }
// NewMarketPremiumIndexPriceKlineService Market Premium Index Price Kline Endpoints
func (c *Client) NewMarketPremiumIndexPriceKlineService() *MarketPremiumIndexPriceKlineService {
return &MarketPremiumIndexPriceKlineService{c: c}
}
func (c *Client) NewOrderBookService() *MarketOrderBookService {
return &MarketOrderBookService{c: c}
}
func (c *Client) NewTickersService() *MarketTickersService {
return &MarketTickersService{c: c}
}
func (c *Client) NewFundingTatesService() *MarketFundingRatesService {
return &MarketFundingRatesService{c: c}
}
func (c *Client) NewGetPublicRecentTradesService() *GetPublicRecentTradesService {
return &GetPublicRecentTradesService{c: c}
}
// GetOpenInterestsServicdde
func (c *Client) NewGetOpenInterestsService() *GetOpenInterestsService {
return &GetOpenInterestsService{c: c}
}
// GetHistoricalVolatilityService
func (c *Client) NewGetHistoricalVolatilityService() *GetHistoricalVolatilityService {
return &GetHistoricalVolatilityService{c: c}
}
// GetInsuranceInfoService
func (c *Client) NewGetInsuranceInfoService() *GetInsuranceInfoService {
return &GetInsuranceInfoService{c: c}
}
// GetRiskLimitService
func (c *Client) NewGetRiskLimitService() *GetRiskLimitService {
return &GetRiskLimitService{c: c}
}
// GetDeliveryPriceService
func (c *Client) NewGetDeliveryPriceService() *GetDeliveryPriceService {
return &GetDeliveryPriceService{c: c}
}
// GetMarketLSRatioService
func (c *Client) NewGetMarketLSRatioService() *GetMarketLSRatioService {
return &GetMarketLSRatioService{c: c}
}
// GetServerTimeService
func (c *Client) NewGetServerTimeService() *GetServerTimeService {
return &GetServerTimeService{c: c}
} }
// NewPlaceOrderService Trade Endpoints // NewPlaceOrderService Trade Endpoints

296
market.go
View File

@ -1,296 +0,0 @@
package bybit_connector
import (
"context"
"encoding/json"
"github.com/wuhewuhe/bybit.go.api/handlers"
"net/http"
)
type MarketClient struct {
c *Client
klineType string
params map[string]interface{}
}
func (s *MarketClient) GetServerTime(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) {
r := &request{
method: http.MethodGet,
endpoint: "/v5/market/time",
secType: secTypeNone,
}
data, err := s.c.callAPI(ctx, r, opts...)
if err != nil {
return nil, err
}
res = new(ServerResponse)
err = json.Unmarshal(data, res)
if err != nil {
return nil, err
}
return res, nil
}
func (s *MarketClient) GetMarketKline(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) {
if err = handlers.ValidateParams(s.params); err != nil {
return nil, err
}
r := &request{
method: http.MethodGet,
endpoint: "/v5/market/" + s.klineType,
secType: secTypeNone,
}
r.setParams(s.params)
data, err := s.c.callAPI(ctx, r, opts...)
if err != nil {
return nil, err
}
res = new(ServerResponse)
err = json.Unmarshal(data, res)
if err != nil {
return nil, err
}
return res, nil
}
func (s *MarketClient) GetInstrumentInfo(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) {
if err = handlers.ValidateParams(s.params); err != nil {
return nil, err
}
r := &request{
method: http.MethodGet,
endpoint: "/v5/market/instruments-info",
secType: secTypeNone,
}
r.setParams(s.params)
data, err := s.c.callAPI(ctx, r, opts...)
if err != nil {
return nil, err
}
res = new(ServerResponse)
err = json.Unmarshal(data, res)
if err != nil {
return nil, err
}
return res, nil
}
func (s *MarketClient) GetOrderBookInfo(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) {
if err = handlers.ValidateParams(s.params); err != nil {
return nil, err
}
r := &request{
method: http.MethodGet,
endpoint: "/v5/market/orderbook",
secType: secTypeNone,
}
r.setParams(s.params)
data, err := s.c.callAPI(ctx, r, opts...)
if err != nil {
return nil, err
}
res = new(ServerResponse)
err = json.Unmarshal(data, res)
if err != nil {
return nil, err
}
return res, nil
}
func (s *MarketClient) GetMarketTickers(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) {
if err = handlers.ValidateParams(s.params); err != nil {
return nil, err
}
r := &request{
method: http.MethodGet,
endpoint: "/v5/market/tickers",
secType: secTypeNone,
}
r.setParams(s.params)
data, err := s.c.callAPI(ctx, r, opts...)
if err != nil {
return nil, err
}
res = new(ServerResponse)
err = json.Unmarshal(data, res)
if err != nil {
return nil, err
}
return res, nil
}
func (s *MarketClient) GetFundingRates(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) {
if err = handlers.ValidateParams(s.params); err != nil {
return nil, err
}
r := &request{
method: http.MethodGet,
endpoint: "/v5/market/tickers",
secType: secTypeNone,
}
r.setParams(s.params)
data, err := s.c.callAPI(ctx, r, opts...)
if err != nil {
return nil, err
}
res = new(ServerResponse)
err = json.Unmarshal(data, res)
if err != nil {
return nil, err
}
return res, nil
}
func (s *MarketClient) GetPublicRecentTrades(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) {
if err = handlers.ValidateParams(s.params); err != nil {
return nil, err
}
r := &request{
method: http.MethodGet,
endpoint: "/v5/market/recent-trade",
secType: secTypeNone,
}
r.setParams(s.params)
data, err := s.c.callAPI(ctx, r, opts...)
if err != nil {
return nil, err
}
res = new(ServerResponse)
err = json.Unmarshal(data, res)
if err != nil {
return nil, err
}
return res, nil
}
func (s *MarketClient) GetOpenInterests(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) {
if err = handlers.ValidateParams(s.params); err != nil {
return nil, err
}
r := &request{
method: http.MethodGet,
endpoint: "/v5/market/open-interest",
secType: secTypeNone,
}
r.setParams(s.params)
data, err := s.c.callAPI(ctx, r, opts...)
if err != nil {
return nil, err
}
res = new(ServerResponse)
err = json.Unmarshal(data, res)
if err != nil {
return nil, err
}
return res, nil
}
func (s *MarketClient) GetHistoricalVolatility(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) {
if err = handlers.ValidateParams(s.params); err != nil {
return nil, err
}
r := &request{
method: http.MethodGet,
endpoint: "/v5/market/historical-volatility",
secType: secTypeNone,
}
r.setParams(s.params)
data, err := s.c.callAPI(ctx, r, opts...)
if err != nil {
return nil, err
}
res = new(ServerResponse)
err = json.Unmarshal(data, res)
if err != nil {
return nil, err
}
return res, nil
}
func (s *MarketClient) GetInsuranceInfo(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) {
if err = handlers.ValidateParams(s.params); err != nil {
return nil, err
}
r := &request{
method: http.MethodGet,
endpoint: "/v5/market/insurance",
secType: secTypeNone,
}
r.setParams(s.params)
data, err := s.c.callAPI(ctx, r, opts...)
if err != nil {
return nil, err
}
res = new(ServerResponse)
err = json.Unmarshal(data, res)
if err != nil {
return nil, err
}
return res, nil
}
func (s *MarketClient) GetRiskLimit(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) {
if err = handlers.ValidateParams(s.params); err != nil {
return nil, err
}
r := &request{
method: http.MethodGet,
endpoint: "/v5/market/risk-limit",
secType: secTypeNone,
}
r.setParams(s.params)
data, err := s.c.callAPI(ctx, r, opts...)
if err != nil {
return nil, err
}
res = new(ServerResponse)
err = json.Unmarshal(data, res)
if err != nil {
return nil, err
}
return res, nil
}
func (s *MarketClient) GetDeliveryPrice(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) {
if err = handlers.ValidateParams(s.params); err != nil {
return nil, err
}
r := &request{
method: http.MethodGet,
endpoint: "/v5/market/delivery-price",
secType: secTypeNone,
}
r.setParams(s.params)
data, err := s.c.callAPI(ctx, r, opts...)
if err != nil {
return nil, err
}
res = new(ServerResponse)
err = json.Unmarshal(data, res)
if err != nil {
return nil, err
}
return res, nil
}
func (s *MarketClient) GetMarketLSRatio(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) {
if err = handlers.ValidateParams(s.params); err != nil {
return nil, err
}
r := &request{
method: http.MethodGet,
endpoint: "/v5/market/account-ratio",
secType: secTypeNone,
}
r.setParams(s.params)
data, err := s.c.callAPI(ctx, r, opts...)
if err != nil {
return nil, err
}
res = new(ServerResponse)
err = json.Unmarshal(data, res)
if err != nil {
return nil, err
}
return res, nil
}

View File

@ -1,67 +0,0 @@
package bybit_connector
import (
"context"
"encoding/json"
"net/http"
)
// Klines Market Kline (GET /v5/market/kline)
type Klines struct {
c *Client
klineType string
category string
symbol string
interval string
limit *int
start *uint64
end *uint64
}
// Limit set limit
func (s *Klines) Limit(limit int) *Klines {
s.limit = &limit
return s
}
// Start set startTime
func (s *Klines) Start(startTime uint64) *Klines {
s.start = &startTime
return s
}
// End set endTime
func (s *Klines) End(endTime uint64) *Klines {
s.end = &endTime
return s
}
func (s *Klines) Do(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) {
r := &request{
method: http.MethodGet,
endpoint: "/v5/market/" + s.klineType,
secType: secTypeNone,
}
r.setParam("category", s.category)
r.setParam("symbol", s.symbol)
r.setParam("interval", s.interval)
if s.limit != nil {
r.setParam("limit", *s.limit)
}
if s.start != nil {
r.setParam("start", *s.start)
}
if s.end != nil {
r.setParam("end", *s.end)
}
data, err := s.c.callAPI(ctx, r, opts...)
if err != nil {
return nil, err
}
res = new(ServerResponse)
err = json.Unmarshal(data, res)
if err != nil {
return nil, err
}
return res, nil
}

1167
market_service.go Normal file

File diff suppressed because it is too large Load Diff

1334
market_service_test.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,69 +0,0 @@
package bybit_connector
import (
"github.com/stretchr/testify/suite"
"github.com/wuhewuhe/bybit.go.api/models"
"testing"
)
type marketTestSuite struct {
baseTestSuite
}
func TestMarket(t *testing.T) {
suite.Run(t, new(marketTestSuite))
}
func (s *marketTestSuite) TestServerTime() {
data := []byte(`{
"retCode": 0,
"retMsg": "OK",
"result": {
"timeSecond": "1699287551",
"timeNano": "1699287551919622633"
},
"retExtInfo": {},
"time": 1699287551919
}`)
s.mockDo(data, nil)
defer s.assertDo()
s.assertReq(func(r *request) {
e := newRequest()
s.assertRequestEqual(e, r)
})
serverTime, err := s.client.NewMarketInfoServiceNoParams().GetServerTime(newContext())
e1 := &models.ServerTimeResult{
TimeSecond: "1699287551",
TimeNano: "1699287551919622633",
}
s.r().NoError(err)
s.assertServerTimeEqual(e1, serverTime)
}
func (s *marketTestSuite) assertServerTimeEqual(expected *models.ServerTimeResult, actual *ServerResponse) {
// Assert that the actual result is not nil and is a map
r := s.r()
actualResult, ok := actual.Result.(map[string]interface{})
if !ok {
r.FailNow("Actual result is not a map", "Actual Result: %#v", actual.Result)
return
}
// Cast the map to the expected struct type
var actualStruct models.ServerTimeResult
timeSecond, okSecond := actualResult["timeSecond"].(string)
timeNano, okNano := actualResult["timeNano"].(string)
if !okSecond || !okNano {
r.FailNow("Failed to cast actual result fields to string", "Actual Result: %#v", actual.Result)
return
}
actualStruct.TimeSecond = timeSecond
actualStruct.TimeNano = timeNano
// Compare the fields
r.Equal(expected.TimeSecond, actualStruct.TimeSecond, "TimeSecond field is not equal")
r.Equal(expected.TimeNano, actualStruct.TimeNano, "TimeNano field is not equal")
}

View File

@ -16,13 +16,55 @@ type MarketKlineCandle struct {
} }
type MarketKlineResponse struct { type MarketKlineResponse struct {
Category string `json:"category"` Category Category `json:"category"`
Symbol string `json:"symbol"` Symbol string `json:"symbol"`
List []MarketKlineCandle `json:"list"` List []*MarketKlineCandle `json:"list"`
} }
type InstrumentInfo struct { type MarketMarkPriceKlineCandle struct {
Category string `json:"category"` StartTime string `json:"startTime"`
OpenPrice string `json:"openPrice"`
HighPrice string `json:"highPrice"`
LowPrice string `json:"lowPrice"`
ClosePrice string `json:"closePrice"`
}
type MarketMarkPriceKlineResponse struct {
Category Category `json:"category"`
Symbol string `json:"symbol"`
List []*MarketMarkPriceKlineCandle `json:"list"`
}
type MarketIndexPriceKlineCandle struct {
StartTime string `json:"startTime"`
OpenPrice string `json:"openPrice"`
HighPrice string `json:"highPrice"`
LowPrice string `json:"lowPrice"`
ClosePrice string `json:"closePrice"`
}
type MarketIndexPriceKlineResponse struct {
Category Category `json:"category"`
Symbol string `json:"symbol"`
List []*MarketIndexPriceKlineCandle `json:"list"`
}
type MarketPremiumIndexPriceKlineCandle struct {
StartTime string `json:"startTime"`
OpenPrice string `json:"openPrice"`
HighPrice string `json:"highPrice"`
LowPrice string `json:"lowPrice"`
ClosePrice string `json:"closePrice"`
}
type MarketPremiumIndexPriceKlineResponse struct {
Category Category `json:"category"`
Symbol string `json:"symbol"`
List []*MarketPremiumIndexPriceKlineCandle `json:"list"`
}
type InstrumentInfoResponse struct {
Category Category `json:"category"`
NextPageCursor string `json:"nextPageCursor"` NextPageCursor string `json:"nextPageCursor"`
List []Instrument `json:"list"` List []Instrument `json:"list"`
} }
@ -30,13 +72,16 @@ type InstrumentInfo struct {
type Instrument struct { type Instrument struct {
Symbol string `json:"symbol"` Symbol string `json:"symbol"`
ContractType string `json:"contractType"` ContractType string `json:"contractType"`
Status string `json:"status"` OptionType string `json:"optionType"`
Innovation string `json:"innovation"`
Status SymbolStatus `json:"status"`
BaseCoin string `json:"baseCoin"` BaseCoin string `json:"baseCoin"`
QuoteCoin string `json:"quoteCoin"` QuoteCoin string `json:"quoteCoin"`
LaunchTime string `json:"launchTime"` LaunchTime string `json:"launchTime"`
DeliveryTime string `json:"deliveryTime"` DeliveryTime string `json:"deliveryTime"`
DeliveryFeeRate string `json:"deliveryFeeRate"` DeliveryFeeRate string `json:"deliveryFeeRate"`
PriceScale string `json:"priceScale"` PriceScale string `json:"priceScale"`
MarginTrading string `json:"marginTrading"`
LeverageFilter LeverageFilter `json:"leverageFilter"` LeverageFilter LeverageFilter `json:"leverageFilter"`
PriceFilter PriceFilter `json:"priceFilter"` PriceFilter PriceFilter `json:"priceFilter"`
LotSizeFilter LotSizeFilter `json:"lotSizeFilter"` LotSizeFilter LotSizeFilter `json:"lotSizeFilter"`
@ -63,12 +108,18 @@ type LotSizeFilter struct {
MinOrderQty string `json:"minOrderQty"` MinOrderQty string `json:"minOrderQty"`
QtyStep string `json:"qtyStep"` QtyStep string `json:"qtyStep"`
PostOnlyMaxOrderQty string `json:"postOnlyMaxOrderQty"` PostOnlyMaxOrderQty string `json:"postOnlyMaxOrderQty"`
BasePrecision string `json:"basePrecision"`
QuotePrecision string `json:"quotePrecision"`
MaxOrderAmt string `json:"maxOrderAmt"`
MinOrderAmt string `jsoN:"minOrderAmt"`
} }
type OrderBookEntry struct { // type OrderBookEntry struct {
Price string `json:"0"` // Price string `json:"0"`
Size string `json:"1"` // Size string `json:"1"`
} // }
type OrderBookEntry []string
type OrderBookInfo struct { type OrderBookInfo struct {
Symbol string `json:"s"` Symbol string `json:"s"`
@ -103,11 +154,19 @@ type TickerInfo struct {
Bid1Price string `json:"bid1Price"` Bid1Price string `json:"bid1Price"`
Ask1Price string `json:"ask1Price"` Ask1Price string `json:"ask1Price"`
Bid1Size string `json:"bid1Size"` Bid1Size string `json:"bid1Size"`
Ask1Iv string `json:"ask1Iv"`
Bid1Iv string `json:"bid1Iv"`
MarkIv string `json:"markIv"`
UnderlyingPrice string `json:"underlyingPrice"`
TotalVolume string `json:"totalVolume"`
TotalTurnover string `json:"totalTurnover"`
Change24h string `json:"change24h"`
UsdIndexPrice string `json:"usdIndexPrice"`
} }
type MarketTickers struct { type MarketTickers struct {
Category string `json:"category"` Category string `json:"category"`
List []TickerInfo `json:"list"` List []*TickerInfo `json:"list"`
} }
type FundingRateInfo struct { type FundingRateInfo struct {
@ -136,6 +195,18 @@ type PublicRecentTradeHistory struct {
List []TradeInfo `json:"list"` List []TradeInfo `json:"list"`
} }
type OpenInterestInfo struct {
Category string `json:"category"`
Symbol string `json:"symbol"`
List []OpenInterest `json:"list"`
NextPageCursor string `json:"nextPageCursor"`
}
type OpenInterest struct {
OpenInterest string `json:"openInterest"`
Timestamp string `json:"timeStamp"`
}
type VolatilityData struct { type VolatilityData struct {
Period int `json:"period"` Period int `json:"period"`
Value string `json:"value"` Value string `json:"value"`
@ -144,7 +215,7 @@ type VolatilityData struct {
type HistoricalVolatilityInfo struct { type HistoricalVolatilityInfo struct {
Category string `json:"category"` Category string `json:"category"`
List []VolatilityData `json:"list"` List []VolatilityData `json:"result"`
} }
type InsuranceData struct { type InsuranceData struct {
@ -162,8 +233,8 @@ type RiskLimitData struct {
Id int `json:"id"` Id int `json:"id"`
Symbol string `json:"symbol"` Symbol string `json:"symbol"`
RiskLimitValue string `json:"riskLimitValue"` RiskLimitValue string `json:"riskLimitValue"`
MaintenanceMargin float64 `json:"maintenanceMargin"` MaintenanceMargin string `json:"maintenanceMargin"`
InitialMargin float64 `json:"initialMargin"` InitialMargin string `json:"initialMargin"`
IsLowestRisk int `json:"isLowestRisk"` IsLowestRisk int `json:"isLowestRisk"`
MaxLeverage string `json:"maxLeverage"` MaxLeverage string `json:"maxLeverage"`
} }