ftxapi: add fills request

This commit is contained in:
c9s 2022-03-02 11:12:31 +08:00
parent 14a49989fe
commit 03f0305b3d
7 changed files with 756 additions and 16 deletions

View File

@ -0,0 +1,126 @@
// Code generated by "requestgen -method DELETE -url /api/orders -type CancelAllOrderRequest -responseType .APIResponse"; DO NOT EDIT.
package ftxapi
import (
"context"
"encoding/json"
"fmt"
"net/url"
"regexp"
)
func (c *CancelAllOrderRequest) Market(market string) *CancelAllOrderRequest {
c.market = &market
return c
}
// GetQueryParameters builds and checks the query parameters and returns url.Values
func (c *CancelAllOrderRequest) 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 *CancelAllOrderRequest) GetParameters() (map[string]interface{}, error) {
var params = map[string]interface{}{}
// check market field -> json key market
if c.market != nil {
market := *c.market
// assign parameter of market
params["market"] = market
} else {
}
return params, nil
}
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
func (c *CancelAllOrderRequest) GetParametersQuery() (url.Values, error) {
query := url.Values{}
params, err := c.GetParameters()
if err != nil {
return query, err
}
for k, v := range params {
query.Add(k, fmt.Sprintf("%v", v))
}
return query, nil
}
// GetParametersJSON converts the parameters from GetParameters into the JSON format
func (c *CancelAllOrderRequest) 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 *CancelAllOrderRequest) GetSlugParameters() (map[string]interface{}, error) {
var params = map[string]interface{}{}
return params, nil
}
func (c *CancelAllOrderRequest) 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 *CancelAllOrderRequest) 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 *CancelAllOrderRequest) Do(ctx context.Context) (*APIResponse, error) {
params, err := c.GetParameters()
if err != nil {
return nil, err
}
query := url.Values{}
apiURL := "/api/orders"
req, err := c.client.NewAuthenticatedRequest(ctx, "DELETE", apiURL, query, params)
if err != nil {
return nil, err
}
response, err := c.client.SendRequest(req)
if err != nil {
return nil, err
}
var apiResponse APIResponse
if err := response.DecodeJSON(&apiResponse); err != nil {
return nil, err
}
return &apiResponse, nil
}

View File

@ -0,0 +1,133 @@
// Code generated by "requestgen -method DELETE -url /api/orders/:orderID -type CancelOrderRequest -responseType .APIResponse"; DO NOT EDIT.
package ftxapi
import (
"context"
"encoding/json"
"fmt"
"net/url"
"regexp"
)
func (c *CancelOrderRequest) OrderID(orderID string) *CancelOrderRequest {
c.orderID = orderID
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{}{}
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 {
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{}{}
// check orderID field -> json key orderID
orderID := c.orderID
// TEMPLATE check-required
if len(orderID) == 0 {
return params, fmt.Errorf("orderID is required, empty string given")
}
// END TEMPLATE check-required
// assign parameter of orderID
params["orderID"] = orderID
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) 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) (*APIResponse, error) {
// no body params
var params interface{}
query := url.Values{}
apiURL := "/api/orders/:orderID"
slugs, err := c.GetSlugsMap()
if err != nil {
return nil, err
}
apiURL = c.applySlugsToUrl(apiURL, slugs)
req, err := c.client.NewAuthenticatedRequest(ctx, "DELETE", apiURL, query, params)
if err != nil {
return nil, err
}
response, err := c.client.SendRequest(req)
if err != nil {
return nil, err
}
var apiResponse APIResponse
if err := response.DecodeJSON(&apiResponse); err != nil {
return nil, err
}
return &apiResponse, nil
}

View File

@ -4,10 +4,13 @@ import (
"context"
"os"
"regexp"
"strconv"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/c9s/bbgo/pkg/fixedpoint"
)
func maskSecret(s string) string {
@ -27,7 +30,7 @@ func integrationTestConfigured(t *testing.T) (key, secret string, ok bool) {
return key, secret, ok
}
func TestClient_NewGetAccountRequest(t *testing.T) {
func TestClient_Requests(t *testing.T) {
key, secret, ok := integrationTestConfigured(t)
if !ok {
t.SkipNow()
@ -39,9 +42,58 @@ func TestClient_NewGetAccountRequest(t *testing.T) {
client := NewClient()
client.Auth(key, secret, "")
req := client.NewGetAccountRequest()
account ,err := req.Do(ctx)
assert.NoError(t, err)
assert.NotNil(t, account)
t.Logf("account: %+v", account)
testCases := []struct {
name string
tt func(t *testing.T)
} {
{
name: "GetAccountRequest",
tt: func(t *testing.T) {
req := client.NewGetAccountRequest()
account ,err := req.Do(ctx)
assert.NoError(t, err)
assert.NotNil(t, account)
t.Logf("account: %+v", account)
},
},
{
name: "PlaceOrderRequest",
tt: func(t *testing.T) {
req := client.NewPlaceOrderRequest()
req.PostOnly(true).
Size(fixedpoint.MustNewFromString("1.0")).
Price(fixedpoint.MustNewFromString("10.0")).
OrderType(OrderTypeLimit).
Side(SideBuy).
Market("LTC/USDT")
createdOrder,err := req.Do(ctx)
if assert.NoError(t, err) {
assert.NotNil(t, createdOrder)
t.Logf("createdOrder: %+v", createdOrder)
req2 := client.NewCancelOrderRequest(strconv.FormatInt(createdOrder.Id, 10))
ret, err := req2.Do(ctx)
assert.NoError(t, err)
t.Logf("cancelOrder: %+v", ret)
assert.True(t, ret.Success)
}
},
},
{
name: "GetFillsRequest",
tt: func(t *testing.T) {
req := client.NewGetFillsRequest()
req.Market("CRO/USDT")
fills, err := req.Do(ctx)
assert.NoError(t, err)
assert.NotNil(t, fills)
t.Logf("fills: %+v", fills)
},
},
}
for _, testCase := range testCases {
t.Run(testCase.name, testCase.tt)
}
}

View File

@ -0,0 +1,128 @@
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Result -url /api/fills -type GetFillsRequest -responseDataType []Fill"; DO NOT EDIT.
package ftxapi
import (
"context"
"encoding/json"
"fmt"
"net/url"
"regexp"
)
func (g *GetFillsRequest) Market(market string) *GetFillsRequest {
g.market = &market
return g
}
// GetQueryParameters builds and checks the query parameters and returns url.Values
func (g *GetFillsRequest) 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 *GetFillsRequest) GetParameters() (map[string]interface{}, error) {
var params = map[string]interface{}{}
// check market field -> json key market
if g.market != nil {
market := *g.market
// assign parameter of market
params["market"] = market
} else {
}
return params, nil
}
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
func (g *GetFillsRequest) GetParametersQuery() (url.Values, error) {
query := url.Values{}
params, err := g.GetParameters()
if err != nil {
return query, err
}
for k, v := range params {
query.Add(k, fmt.Sprintf("%v", v))
}
return query, nil
}
// GetParametersJSON converts the parameters from GetParameters into the JSON format
func (g *GetFillsRequest) 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 *GetFillsRequest) GetSlugParameters() (map[string]interface{}, error) {
var params = map[string]interface{}{}
return params, nil
}
func (g *GetFillsRequest) 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 *GetFillsRequest) 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 *GetFillsRequest) Do(ctx context.Context) ([]Fill, error) {
// empty params for GET operation
var params interface{}
query := url.Values{}
apiURL := "/api/fills"
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 APIResponse
if err := response.DecodeJSON(&apiResponse); err != nil {
return nil, err
}
var data []Fill
if err := json.Unmarshal(apiResponse.Result, &data); err != nil {
return nil, err
}
return data, nil
}

View File

@ -0,0 +1,219 @@
// Code generated by "requestgen -method POST -responseType .APIResponse -responseDataField Result -url /api/orders -type PlaceOrderRequest -responseDataType .Order"; DO NOT EDIT.
package ftxapi
import (
"context"
"encoding/json"
"fmt"
"github.com/c9s/bbgo/pkg/fixedpoint"
"net/url"
"regexp"
)
func (p *PlaceOrderRequest) Market(market string) *PlaceOrderRequest {
p.market = market
return p
}
func (p *PlaceOrderRequest) Side(side Side) *PlaceOrderRequest {
p.side = side
return p
}
func (p *PlaceOrderRequest) Price(price fixedpoint.Value) *PlaceOrderRequest {
p.price = price
return p
}
func (p *PlaceOrderRequest) Size(size fixedpoint.Value) *PlaceOrderRequest {
p.size = size
return p
}
func (p *PlaceOrderRequest) OrderType(orderType OrderType) *PlaceOrderRequest {
p.orderType = orderType
return p
}
func (p *PlaceOrderRequest) Ioc(ioc bool) *PlaceOrderRequest {
p.ioc = &ioc
return p
}
func (p *PlaceOrderRequest) PostOnly(postOnly bool) *PlaceOrderRequest {
p.postOnly = &postOnly
return p
}
func (p *PlaceOrderRequest) ClientID(clientID string) *PlaceOrderRequest {
p.clientID = &clientID
return p
}
// GetQueryParameters builds and checks the query parameters and returns url.Values
func (p *PlaceOrderRequest) 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 (p *PlaceOrderRequest) GetParameters() (map[string]interface{}, error) {
var params = map[string]interface{}{}
// check market field -> json key market
market := p.market
// TEMPLATE check-required
if len(market) == 0 {
return params, 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 := p.side
// TEMPLATE check-required
if len(side) == 0 {
return params, fmt.Errorf("side is required, empty string given")
}
// END TEMPLATE check-required
// assign parameter of side
params["side"] = side
// check price field -> json key price
price := p.price
// assign parameter of price
params["price"] = price
// check size field -> json key size
size := p.size
// assign parameter of size
params["size"] = size
// check orderType field -> json key type
orderType := p.orderType
// assign parameter of orderType
params["type"] = orderType
// check ioc field -> json key ioc
if p.ioc != nil {
ioc := *p.ioc
// assign parameter of ioc
params["ioc"] = ioc
} else {
}
// check postOnly field -> json key postOnly
if p.postOnly != nil {
postOnly := *p.postOnly
// assign parameter of postOnly
params["postOnly"] = postOnly
} else {
}
// check clientID field -> json key clientId
if p.clientID != nil {
clientID := *p.clientID
// assign parameter of clientID
params["clientId"] = clientID
} else {
}
return params, nil
}
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
func (p *PlaceOrderRequest) GetParametersQuery() (url.Values, error) {
query := url.Values{}
params, err := p.GetParameters()
if err != nil {
return query, err
}
for k, v := range params {
query.Add(k, fmt.Sprintf("%v", v))
}
return query, nil
}
// GetParametersJSON converts the parameters from GetParameters into the JSON format
func (p *PlaceOrderRequest) GetParametersJSON() ([]byte, error) {
params, err := p.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 (p *PlaceOrderRequest) GetSlugParameters() (map[string]interface{}, error) {
var params = map[string]interface{}{}
return params, nil
}
func (p *PlaceOrderRequest) 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 (p *PlaceOrderRequest) GetSlugsMap() (map[string]string, error) {
slugs := map[string]string{}
params, err := p.GetSlugParameters()
if err != nil {
return slugs, nil
}
for k, v := range params {
slugs[k] = fmt.Sprintf("%v", v)
}
return slugs, nil
}
func (p *PlaceOrderRequest) Do(ctx context.Context) (*Order, error) {
params, err := p.GetParameters()
if err != nil {
return nil, err
}
query := url.Values{}
apiURL := "/api/orders"
req, err := p.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params)
if err != nil {
return nil, err
}
response, err := p.client.SendRequest(req)
if err != nil {
return nil, err
}
var apiResponse APIResponse
if err := response.DecodeJSON(&apiResponse); err != nil {
return nil, err
}
var data Order
if err := json.Unmarshal(apiResponse.Result, &data); err != nil {
return nil, err
}
return &data, nil
}

View File

@ -15,7 +15,7 @@ import (
type Order struct {
CreatedAt time.Time `json:"createdAt"`
Future string `json:"future"`
Id int `json:"id"`
Id int64 `json:"id"`
Market string `json:"market"`
Price fixedpoint.Value `json:"price"`
AvgFillPrice fixedpoint.Value `json:"avgFillPrice"`
@ -46,9 +46,9 @@ func (c *RestClient) NewGetOpenOrdersRequest(market string) *GetOpenOrdersReques
//go:generate GetRequest -url "/api/orders/history" -type GetOrderHistoryRequest -responseDataType []Order
type GetOrderHistoryRequest struct {
client requestgen.AuthenticatedAPIClient
client requestgen.AuthenticatedAPIClient
market string `param:"market,query"`
market string `param:"market,query"`
startTime *time.Time `param:"start_time,seconds,query"`
endTime *time.Time `param:"end_time,seconds,query"`
@ -60,3 +60,80 @@ func (c *RestClient) NewGetOrderHistoryRequest(market string) *GetOrderHistoryRe
market: market,
}
}
//go:generate PostRequest -url "/api/orders" -type PlaceOrderRequest -responseDataType .Order
type PlaceOrderRequest struct {
client requestgen.AuthenticatedAPIClient
market string `param:"market,required"`
side Side `param:"side,required"`
price fixedpoint.Value `param:"price"`
size fixedpoint.Value `param:"size"`
orderType OrderType `param:"type"`
ioc *bool `param:"ioc"`
postOnly *bool `param:"postOnly"`
clientID *string `param:"clientId,optional"`
}
func (c *RestClient) NewPlaceOrderRequest() *PlaceOrderRequest {
return &PlaceOrderRequest{
client: c,
}
}
//go:generate requestgen -method DELETE -url "/api/orders/:orderID" -type CancelOrderRequest -responseType .APIResponse
type CancelOrderRequest struct {
client requestgen.AuthenticatedAPIClient
orderID string `param:"orderID,required,slug"`
}
func (c *RestClient) NewCancelOrderRequest(orderID string) *CancelOrderRequest {
return &CancelOrderRequest{
client: c,
orderID: orderID,
}
}
//go:generate requestgen -method DELETE -url "/api/orders" -type CancelAllOrderRequest -responseType .APIResponse
type CancelAllOrderRequest struct {
client requestgen.AuthenticatedAPIClient
market *string `param:"market"`
}
func (c *RestClient) NewCancelAllOrderRequest() *CancelAllOrderRequest {
return &CancelAllOrderRequest{
client: c,
}
}
type Fill struct {
Id int `json:"id"`
Future string `json:"future"`
Liquidity Liquidity `json:"liquidity"`
Market string `json:"market"`
BaseCurrency string `json:"baseCurrency"`
QuoteCurrency string `json:"quoteCurrency"`
OrderId int `json:"orderId"`
TradeId int `json:"tradeId"`
Price fixedpoint.Value `json:"price"`
Side Side `json:"side"`
Size fixedpoint.Value `json:"size"`
Time time.Time `json:"time"`
Type string `json:"type"` // always = "order"
Fee fixedpoint.Value `json:"fee"`
FeeCurrency string `json:"feeCurrency"`
FeeRate fixedpoint.Value `json:"feeRate"`
}
//go:generate GetRequest -url "/api/fills" -type GetFillsRequest -responseDataType []Fill
type GetFillsRequest struct {
client requestgen.AuthenticatedAPIClient
market *string `param:"market"`
}
func (c *RestClient) NewGetFillsRequest() *GetFillsRequest {
return &GetFillsRequest{
client: c,
}
}

View File

@ -1,30 +1,35 @@
package ftxapi
type Liquidity string
const (
LiquidityTaker Liquidity = "taker"
LiquidityMaker Liquidity = "maker"
)
type Side string
const (
SideBuy Side = "buy"
SideBuy Side = "buy"
SideSell Side = "sell"
)
type OrderType string
const (
OrderTypeLimit OrderType = "limit"
OrderTypeLimit OrderType = "limit"
OrderTypeMarket OrderType = "market"
// trigger order types
OrderTypeStopLimit OrderType = "stop"
OrderTypeStopLimit OrderType = "stop"
OrderTypeTrailingStop OrderType = "trailingStop"
OrderTypeTakeProfit OrderType = "takeProfit"
OrderTypeTakeProfit OrderType = "takeProfit"
)
type OrderStatus string
const (
OrderStatusNew OrderStatus = "new"
OrderStatusOpen OrderStatus = "open"
OrderStatusNew OrderStatus = "new"
OrderStatusOpen OrderStatus = "open"
OrderStatusClosed OrderStatus = "closed"
)