mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
Merge pull request #871 from c9s/improvements/maxapi
improve: improve maxapi, add v2 order api back
This commit is contained in:
commit
d31b812471
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -54,6 +55,19 @@ var klineCmd = &cobra.Command{
|
|||
return err
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
kLines, err := session.Exchange.QueryKLines(ctx, symbol, types.Interval(interval), types.KLineQueryOptions{
|
||||
Limit: 50,
|
||||
EndTime: &now,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infof("kLines from RESTful API")
|
||||
for _, k := range kLines {
|
||||
log.Info(k.String())
|
||||
}
|
||||
|
||||
s := session.Exchange.NewStream()
|
||||
s.SetPublicOnly()
|
||||
s.Subscribe(types.KLineChannel, symbol, types.SubscribeOptions{Interval: types.Interval(interval)})
|
||||
|
|
|
@ -515,7 +515,7 @@ func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder
|
|||
req.Market(toLocalSymbol(o.Symbol)).
|
||||
Side(toLocalSideType(o.Side)).
|
||||
Volume(quantityString).
|
||||
OrderType(string(orderType)).
|
||||
OrderType(orderType).
|
||||
ClientOrderID(clientOrderID)
|
||||
|
||||
switch o.Type {
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
type AccountService struct {
|
||||
client *RestClient
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
}
|
||||
|
||||
// Account is for max rest api v2, Balance and Type will be conflict with types.PrivateBalanceUpdate
|
||||
|
|
19
pkg/exchange/max/maxapi/cancel_order_request.go
Normal file
19
pkg/exchange/max/maxapi/cancel_order_request.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
package max
|
||||
|
||||
//go:generate -command GetRequest requestgen -method GET
|
||||
//go:generate -command PostRequest requestgen -method POST
|
||||
//go:generate -command DeleteRequest requestgen -method DELETE
|
||||
|
||||
import "github.com/c9s/requestgen"
|
||||
|
||||
func (s *OrderService) NewCancelOrderRequest() *CancelOrderRequest {
|
||||
return &CancelOrderRequest{client: s.client}
|
||||
}
|
||||
|
||||
//go:generate PostRequest -url "/api/v2/order/delete" -type CancelOrderRequest -responseType .Order
|
||||
type CancelOrderRequest struct {
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
|
||||
id *uint64 `param:"id,omitempty"`
|
||||
clientOrderID *string `param:"client_oid,omitempty"`
|
||||
}
|
163
pkg/exchange/max/maxapi/cancel_order_request_requestgen.go
Normal file
163
pkg/exchange/max/maxapi/cancel_order_request_requestgen.go
Normal file
|
@ -0,0 +1,163 @@
|
|||
// Code generated by "requestgen -method POST -url /api/v2/order/delete -type CancelOrderRequest -responseType .Order"; DO NOT EDIT.
|
||||
|
||||
package max
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (c *CancelOrderRequest) Id(id uint64) *CancelOrderRequest {
|
||||
c.id = &id
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CancelOrderRequest) ClientOrderID(clientOrderID string) *CancelOrderRequest {
|
||||
c.clientOrderID = &clientOrderID
|
||||
return c
|
||||
}
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (c *CancelOrderRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
query := url.Values{}
|
||||
for _k, _v := range params {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParameters builds and checks the parameters and return the result in a map object
|
||||
func (c *CancelOrderRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
// check id field -> json key id
|
||||
if c.id != nil {
|
||||
id := *c.id
|
||||
|
||||
// assign parameter of id
|
||||
params["id"] = id
|
||||
} else {
|
||||
}
|
||||
// check clientOrderID field -> json key client_oid
|
||||
if c.clientOrderID != nil {
|
||||
clientOrderID := *c.clientOrderID
|
||||
|
||||
// assign parameter of clientOrderID
|
||||
params["client_oid"] = clientOrderID
|
||||
} else {
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (c *CancelOrderRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := c.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
if c.isVarSlice(_v) {
|
||||
c.iterateSlice(_v, func(it interface{}) {
|
||||
query.Add(_k+"[]", fmt.Sprintf("%v", it))
|
||||
})
|
||||
} else {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||
func (c *CancelOrderRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := c.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(params)
|
||||
}
|
||||
|
||||
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||
func (c *CancelOrderRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (c *CancelOrderRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||
for _k, _v := range slugs {
|
||||
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||
url = needleRE.ReplaceAllString(url, _v)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func (c *CancelOrderRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||
sliceValue := reflect.ValueOf(slice)
|
||||
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||
it := sliceValue.Index(_i).Interface()
|
||||
_f(it)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CancelOrderRequest) isVarSlice(_v interface{}) bool {
|
||||
rt := reflect.TypeOf(_v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *CancelOrderRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := c.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
slugs[_k] = fmt.Sprintf("%v", _v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (c *CancelOrderRequest) Do(ctx context.Context) (*Order, error) {
|
||||
|
||||
params, err := c.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query := url.Values{}
|
||||
|
||||
apiURL := "/api/v2/order/delete"
|
||||
|
||||
req, err := c.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := c.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse Order
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &apiResponse, nil
|
||||
}
|
26
pkg/exchange/max/maxapi/create_order_request.go
Normal file
26
pkg/exchange/max/maxapi/create_order_request.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package max
|
||||
|
||||
import "github.com/c9s/requestgen"
|
||||
|
||||
//go:generate -command GetRequest requestgen -method GET
|
||||
//go:generate -command PostRequest requestgen -method POST
|
||||
//go:generate -command DeleteRequest requestgen -method DELETE
|
||||
|
||||
//go:generate PostRequest -url "/api/v2/orders" -type CreateOrderRequest -responseType .Order
|
||||
type CreateOrderRequest struct {
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
|
||||
market string `param:"market,required"`
|
||||
side string `param:"side,required"`
|
||||
volume string `param:"volume,required"`
|
||||
orderType OrderType `param:"ord_type"`
|
||||
|
||||
price *string `param:"price"`
|
||||
stopPrice *string `param:"stop_price"`
|
||||
clientOrderID *string `param:"client_oid"`
|
||||
groupID *string `param:"group_id"`
|
||||
}
|
||||
|
||||
func (s *OrderService) NewCreateOrderRequest() *CreateOrderRequest {
|
||||
return &CreateOrderRequest{client: s.client}
|
||||
}
|
247
pkg/exchange/max/maxapi/create_order_request_requestgen.go
Normal file
247
pkg/exchange/max/maxapi/create_order_request_requestgen.go
Normal file
|
@ -0,0 +1,247 @@
|
|||
// Code generated by "requestgen -method POST -url /api/v2/orders -type CreateOrderRequest -responseType .Order"; DO NOT EDIT.
|
||||
|
||||
package max
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (c *CreateOrderRequest) Market(market string) *CreateOrderRequest {
|
||||
c.market = market
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) Side(side string) *CreateOrderRequest {
|
||||
c.side = side
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) Volume(volume string) *CreateOrderRequest {
|
||||
c.volume = volume
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) OrderType(orderType OrderType) *CreateOrderRequest {
|
||||
c.orderType = orderType
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) Price(price string) *CreateOrderRequest {
|
||||
c.price = &price
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) StopPrice(stopPrice string) *CreateOrderRequest {
|
||||
c.stopPrice = &stopPrice
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) ClientOrderID(clientOrderID string) *CreateOrderRequest {
|
||||
c.clientOrderID = &clientOrderID
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) GroupID(groupID string) *CreateOrderRequest {
|
||||
c.groupID = &groupID
|
||||
return c
|
||||
}
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (c *CreateOrderRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
query := url.Values{}
|
||||
for _k, _v := range params {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParameters builds and checks the parameters and return the result in a map object
|
||||
func (c *CreateOrderRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
// check market field -> json key market
|
||||
market := c.market
|
||||
|
||||
// TEMPLATE check-required
|
||||
if len(market) == 0 {
|
||||
return nil, fmt.Errorf("market is required, empty string given")
|
||||
}
|
||||
// END TEMPLATE check-required
|
||||
|
||||
// assign parameter of market
|
||||
params["market"] = market
|
||||
// check side field -> json key side
|
||||
side := c.side
|
||||
|
||||
// TEMPLATE check-required
|
||||
if len(side) == 0 {
|
||||
return nil, fmt.Errorf("side is required, empty string given")
|
||||
}
|
||||
// END TEMPLATE check-required
|
||||
|
||||
// assign parameter of side
|
||||
params["side"] = side
|
||||
// check volume field -> json key volume
|
||||
volume := c.volume
|
||||
|
||||
// TEMPLATE check-required
|
||||
if len(volume) == 0 {
|
||||
return nil, fmt.Errorf("volume is required, empty string given")
|
||||
}
|
||||
// END TEMPLATE check-required
|
||||
|
||||
// assign parameter of volume
|
||||
params["volume"] = volume
|
||||
// check orderType field -> json key ord_type
|
||||
orderType := c.orderType
|
||||
|
||||
// assign parameter of orderType
|
||||
params["ord_type"] = orderType
|
||||
// check price field -> json key price
|
||||
if c.price != nil {
|
||||
price := *c.price
|
||||
|
||||
// assign parameter of price
|
||||
params["price"] = price
|
||||
} else {
|
||||
}
|
||||
// check stopPrice field -> json key stop_price
|
||||
if c.stopPrice != nil {
|
||||
stopPrice := *c.stopPrice
|
||||
|
||||
// assign parameter of stopPrice
|
||||
params["stop_price"] = stopPrice
|
||||
} else {
|
||||
}
|
||||
// check clientOrderID field -> json key client_oid
|
||||
if c.clientOrderID != nil {
|
||||
clientOrderID := *c.clientOrderID
|
||||
|
||||
// assign parameter of clientOrderID
|
||||
params["client_oid"] = clientOrderID
|
||||
} else {
|
||||
}
|
||||
// check groupID field -> json key group_id
|
||||
if c.groupID != nil {
|
||||
groupID := *c.groupID
|
||||
|
||||
// assign parameter of groupID
|
||||
params["group_id"] = groupID
|
||||
} else {
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (c *CreateOrderRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := c.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
if c.isVarSlice(_v) {
|
||||
c.iterateSlice(_v, func(it interface{}) {
|
||||
query.Add(_k+"[]", fmt.Sprintf("%v", it))
|
||||
})
|
||||
} else {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||
func (c *CreateOrderRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := c.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(params)
|
||||
}
|
||||
|
||||
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||
func (c *CreateOrderRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||
for _k, _v := range slugs {
|
||||
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||
url = needleRE.ReplaceAllString(url, _v)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||
sliceValue := reflect.ValueOf(slice)
|
||||
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||
it := sliceValue.Index(_i).Interface()
|
||||
_f(it)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) isVarSlice(_v interface{}) bool {
|
||||
rt := reflect.TypeOf(_v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := c.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
slugs[_k] = fmt.Sprintf("%v", _v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) Do(ctx context.Context) (*Order, error) {
|
||||
|
||||
params, err := c.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query := url.Values{}
|
||||
|
||||
apiURL := "/api/v2/orders"
|
||||
|
||||
req, err := c.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := c.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse Order
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &apiResponse, nil
|
||||
}
|
27
pkg/exchange/max/maxapi/get_k_lines_request.go
Normal file
27
pkg/exchange/max/maxapi/get_k_lines_request.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package max
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/c9s/requestgen"
|
||||
)
|
||||
|
||||
//go:generate -command GetRequest requestgen -method GET
|
||||
//go:generate -command PostRequest requestgen -method POST
|
||||
//go:generate -command DeleteRequest requestgen -method DELETE
|
||||
|
||||
type KLineData []float64
|
||||
|
||||
//go:generate GetRequest -url "/api/v2/k" -type GetKLinesRequest -responseType []KLineData
|
||||
type GetKLinesRequest struct {
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
|
||||
market string `param:"market,required"`
|
||||
limit *int `param:"limit"`
|
||||
period *int `param:"period"`
|
||||
timestamp time.Time `param:"timestamp,seconds"`
|
||||
}
|
||||
|
||||
func (s *PublicService) NewGetKLinesRequest() *GetKLinesRequest {
|
||||
return &GetKLinesRequest{client: s.client}
|
||||
}
|
193
pkg/exchange/max/maxapi/get_k_lines_request_requestgen.go
Normal file
193
pkg/exchange/max/maxapi/get_k_lines_request_requestgen.go
Normal file
|
@ -0,0 +1,193 @@
|
|||
// Code generated by "requestgen -method GET -url /api/v2/k -type GetKLinesRequest -responseType []KLineData"; DO NOT EDIT.
|
||||
|
||||
package max
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (g *GetKLinesRequest) Market(market string) *GetKLinesRequest {
|
||||
g.market = market
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetKLinesRequest) Limit(limit int) *GetKLinesRequest {
|
||||
g.limit = &limit
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetKLinesRequest) Period(period int) *GetKLinesRequest {
|
||||
g.period = &period
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetKLinesRequest) Timestamp(timestamp time.Time) *GetKLinesRequest {
|
||||
g.timestamp = timestamp
|
||||
return g
|
||||
}
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (g *GetKLinesRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
query := url.Values{}
|
||||
for _k, _v := range params {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParameters builds and checks the parameters and return the result in a map object
|
||||
func (g *GetKLinesRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
// check market field -> json key market
|
||||
market := g.market
|
||||
|
||||
// TEMPLATE check-required
|
||||
if len(market) == 0 {
|
||||
return nil, fmt.Errorf("market is required, empty string given")
|
||||
}
|
||||
// END TEMPLATE check-required
|
||||
|
||||
// assign parameter of market
|
||||
params["market"] = market
|
||||
// check limit field -> json key limit
|
||||
if g.limit != nil {
|
||||
limit := *g.limit
|
||||
|
||||
// assign parameter of limit
|
||||
params["limit"] = limit
|
||||
} else {
|
||||
}
|
||||
// check period field -> json key period
|
||||
if g.period != nil {
|
||||
period := *g.period
|
||||
|
||||
// assign parameter of period
|
||||
params["period"] = period
|
||||
} else {
|
||||
}
|
||||
// check timestamp field -> json key timestamp
|
||||
timestamp := g.timestamp
|
||||
|
||||
// assign parameter of timestamp
|
||||
// convert time.Time to seconds time stamp
|
||||
params["timestamp"] = strconv.FormatInt(timestamp.Unix(), 10)
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (g *GetKLinesRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
if g.isVarSlice(_v) {
|
||||
g.iterateSlice(_v, func(it interface{}) {
|
||||
query.Add(_k+"[]", fmt.Sprintf("%v", it))
|
||||
})
|
||||
} else {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||
func (g *GetKLinesRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(params)
|
||||
}
|
||||
|
||||
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||
func (g *GetKLinesRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (g *GetKLinesRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||
for _k, _v := range slugs {
|
||||
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||
url = needleRE.ReplaceAllString(url, _v)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func (g *GetKLinesRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||
sliceValue := reflect.ValueOf(slice)
|
||||
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||
it := sliceValue.Index(_i).Interface()
|
||||
_f(it)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GetKLinesRequest) isVarSlice(_v interface{}) bool {
|
||||
rt := reflect.TypeOf(_v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *GetKLinesRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := g.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
slugs[_k] = fmt.Sprintf("%v", _v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (g *GetKLinesRequest) Do(ctx context.Context) ([]KLineData, error) {
|
||||
|
||||
// empty params for GET operation
|
||||
var params interface{}
|
||||
query, err := g.GetParametersQuery()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
apiURL := "/api/v2/k"
|
||||
|
||||
req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := g.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse []KLineData
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return apiResponse, nil
|
||||
}
|
|
@ -4,6 +4,8 @@ package max
|
|||
//go:generate -command PostRequest requestgen -method POST
|
||||
|
||||
import (
|
||||
"github.com/c9s/requestgen"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
@ -57,7 +59,7 @@ type QueryOrderOptions struct {
|
|||
|
||||
// OrderService manages the Order endpoint.
|
||||
type OrderService struct {
|
||||
client *RestClient
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
}
|
||||
|
||||
type SubmitOrder struct {
|
||||
|
|
|
@ -4,10 +4,10 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/c9s/requestgen"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/valyala/fastjson"
|
||||
|
||||
|
@ -16,7 +16,7 @@ import (
|
|||
)
|
||||
|
||||
type PublicService struct {
|
||||
client *RestClient
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
}
|
||||
|
||||
type Market struct {
|
||||
|
@ -234,35 +234,39 @@ func (k KLine) KLine() types.KLine {
|
|||
}
|
||||
|
||||
func (s *PublicService) KLines(symbol string, resolution string, start time.Time, limit int) ([]KLine, error) {
|
||||
queries := url.Values{}
|
||||
queries.Set("market", symbol)
|
||||
|
||||
interval, err := ParseInterval(resolution)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
queries.Set("period", strconv.Itoa(int(interval)))
|
||||
|
||||
nilTime := time.Time{}
|
||||
if start != nilTime {
|
||||
queries.Set("timestamp", strconv.FormatInt(start.Unix(), 10))
|
||||
}
|
||||
|
||||
if limit > 0 {
|
||||
queries.Set("limit", strconv.Itoa(limit)) // default to 30, max limit = 10,000
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest(context.Background(), "GET", fmt.Sprintf("%s/k", s.client.BaseURL), queries, nil)
|
||||
req := s.NewGetKLinesRequest()
|
||||
req.Market(symbol).Period(int(interval)).Timestamp(start).Limit(limit)
|
||||
data, err := req.Do(context.Background())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request build error: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request failed: %s", err.Error())
|
||||
var kLines []KLine
|
||||
for _, slice := range data {
|
||||
ts := int64(slice[0])
|
||||
startTime := time.Unix(ts, 0)
|
||||
endTime := startTime.Add(time.Duration(interval)*time.Minute - time.Millisecond)
|
||||
isClosed := time.Now().Before(endTime)
|
||||
kLines = append(kLines, KLine{
|
||||
Symbol: symbol,
|
||||
Interval: resolution,
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
Open: fixedpoint.NewFromFloat(slice[1]),
|
||||
High: fixedpoint.NewFromFloat(slice[2]),
|
||||
Low: fixedpoint.NewFromFloat(slice[3]),
|
||||
Close: fixedpoint.NewFromFloat(slice[4]),
|
||||
Volume: fixedpoint.NewFromFloat(slice[5]),
|
||||
Closed: isClosed,
|
||||
})
|
||||
}
|
||||
|
||||
return parseKLines(resp.Body, symbol, resolution, interval)
|
||||
return kLines, nil
|
||||
// return parseKLines(resp.Body, symbol, resolution, interval)
|
||||
}
|
||||
|
||||
func parseKLines(payload []byte, symbol, resolution string, interval Interval) (klines []KLine, err error) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"math"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
@ -40,6 +41,7 @@ const (
|
|||
var httpTransportMaxIdleConnsPerHost = http.DefaultMaxIdleConnsPerHost
|
||||
var httpTransportMaxIdleConns = 100
|
||||
var httpTransportIdleConnTimeout = 90 * time.Second
|
||||
var disableUserAgentHeader = false
|
||||
|
||||
func init() {
|
||||
|
||||
|
@ -50,9 +52,14 @@ func init() {
|
|||
if val, ok := util.GetEnvVarInt("HTTP_TRANSPORT_MAX_IDLE_CONNS"); ok {
|
||||
httpTransportMaxIdleConns = val
|
||||
}
|
||||
|
||||
if val, ok := util.GetEnvVarDuration("HTTP_TRANSPORT_IDLE_CONN_TIMEOUT"); ok {
|
||||
httpTransportIdleConnTimeout = val
|
||||
}
|
||||
|
||||
if val, ok := util.GetEnvVarBool("DISABLE_MAX_USER_AGENT_HEADER"); ok {
|
||||
disableUserAgentHeader = val
|
||||
}
|
||||
}
|
||||
|
||||
var logger = log.WithField("exchange", "max")
|
||||
|
@ -77,7 +84,10 @@ var httpTransport = &http.Transport{
|
|||
Timeout: 10 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).DialContext,
|
||||
ForceAttemptHTTP2: true,
|
||||
|
||||
// ForceAttemptHTTP2: true,
|
||||
// DisableCompression: false,
|
||||
|
||||
MaxIdleConns: httpTransportMaxIdleConns,
|
||||
MaxIdleConnsPerHost: httpTransportMaxIdleConnsPerHost,
|
||||
IdleConnTimeout: httpTransportIdleConnTimeout,
|
||||
|
@ -218,16 +228,18 @@ func (c *RestClient) newAuthenticatedRequest(ctx context.Context, m string, refU
|
|||
req.Header.Add("X-MAX-PAYLOAD", encoded)
|
||||
req.Header.Add("X-MAX-SIGNATURE", signPayload(encoded, c.APISecret))
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (c *RestClient) sendAuthenticatedRequest(m string, refURL string, data map[string]interface{}) (*requestgen.Response, error) {
|
||||
req, err := c.newAuthenticatedRequest(nil, m, refURL, nil, data, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if disableUserAgentHeader {
|
||||
req.Header.Set("USER-AGENT", "")
|
||||
} else {
|
||||
req.Header.Set("USER-AGENT", UserAgent)
|
||||
}
|
||||
|
||||
return c.SendRequest(req)
|
||||
if false {
|
||||
out, _ := httputil.DumpRequestOut(req, true)
|
||||
fmt.Println(string(out))
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// ErrorResponse is the custom error type that is returned if the API returns an
|
||||
|
|
|
@ -123,7 +123,7 @@ func (reward Reward) Reward() (*types.Reward, error) {
|
|||
}
|
||||
|
||||
type RewardService struct {
|
||||
client *RestClient
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
}
|
||||
|
||||
func (s *RewardService) NewGetRewardsRequest() *GetRewardsRequest {
|
||||
|
|
|
@ -67,7 +67,7 @@ type QueryTradeOptions struct {
|
|||
}
|
||||
|
||||
type TradeService struct {
|
||||
client *RestClient
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
}
|
||||
|
||||
func (options *QueryTradeOptions) Map() map[string]interface{} {
|
||||
|
|
|
@ -14,7 +14,7 @@ type CreateWalletOrderRequest struct {
|
|||
market string `param:"market,required"`
|
||||
side string `param:"side,required"`
|
||||
volume string `param:"volume,required"`
|
||||
orderType string `param:"ord_type"`
|
||||
orderType OrderType `param:"ord_type"`
|
||||
|
||||
price *string `param:"price"`
|
||||
stopPrice *string `param:"stop_price"`
|
||||
|
|
|
@ -27,7 +27,7 @@ func (c *CreateWalletOrderRequest) Volume(volume string) *CreateWalletOrderReque
|
|||
return c
|
||||
}
|
||||
|
||||
func (c *CreateWalletOrderRequest) OrderType(orderType string) *CreateWalletOrderRequest {
|
||||
func (c *CreateWalletOrderRequest) OrderType(orderType max.OrderType) *CreateWalletOrderRequest {
|
||||
c.orderType = orderType
|
||||
return c
|
||||
}
|
||||
|
|
|
@ -5,16 +5,20 @@ package v3
|
|||
//go:generate -command DeleteRequest requestgen -method DELETE
|
||||
|
||||
import (
|
||||
"github.com/c9s/requestgen"
|
||||
|
||||
maxapi "github.com/c9s/bbgo/pkg/exchange/max/maxapi"
|
||||
)
|
||||
|
||||
// create type alias
|
||||
type WalletType = maxapi.WalletType
|
||||
type OrderType = maxapi.OrderType
|
||||
|
||||
type Order = maxapi.Order
|
||||
type Trade = maxapi.Trade
|
||||
type Account = maxapi.Account
|
||||
|
||||
// OrderService manages the Order endpoint.
|
||||
type OrderService struct {
|
||||
Client *maxapi.RestClient
|
||||
Client requestgen.AuthenticatedAPIClient
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ type GetWithdrawalAddressesRequest struct {
|
|||
}
|
||||
|
||||
type WithdrawalService struct {
|
||||
client *RestClient
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
}
|
||||
|
||||
func (s *WithdrawalService) NewGetWithdrawalAddressesRequest() *GetWithdrawalAddressesRequest {
|
||||
|
|
Loading…
Reference in New Issue
Block a user