Skip to content

Commit d9d2fc8

Browse files
committed
add futures stats and single margin pair query; add demo application
1 parent c548eae commit d9d2fc8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1109
-139
lines changed

README.md

+9-4
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ APIv4 provides spot, margin and futures trading operations. There are public API
55
## Overview
66
This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [OpenAPI-spec](https://www.openapis.org/) from a remote server, you can easily generate an API client.
77

8-
- API version: 4.15.4
9-
- Package version: 4.15.4
8+
- API version: 4.15.5
9+
- Package version: 5.15.5
1010
- Build package: org.openapitools.codegen.languages.GoClientCodegen
1111
For more information, please visit [https://www.gate.io/page/contacts](https://www.gate.io/page/contacts)
1212

@@ -37,7 +37,7 @@ page
3737
## Installation
3838

3939
```shell
40-
go get -u github.com/gateio/gateapi-go
40+
go get github.com/gateio/gateapi-go/v5
4141
```
4242

4343
## Getting Started
@@ -52,7 +52,7 @@ import (
5252
"context"
5353
"fmt"
5454

55-
"github.com/gateio/gateapi-go"
55+
"github.com/gateio/gateapi-go/v5"
5656
)
5757

5858
func main() {
@@ -77,6 +77,8 @@ func main() {
7777

7878

7979

80+
For a more complete API usage example, refer to the demo application in [example](_example) directory
81+
8082
## Documentation for API Endpoints
8183

8284
All URIs are relative to *https://api.gateio.ws/api/v4*
@@ -119,6 +121,7 @@ Class | Method | HTTP request | Description
119121
*FuturesApi* | [**ListFuturesTickers**](docs/FuturesApi.md#listfuturestickers) | **Get** /futures/{settle}/tickers | List futures tickers
120122
*FuturesApi* | [**ListFuturesFundingRateHistory**](docs/FuturesApi.md#listfuturesfundingratehistory) | **Get** /futures/{settle}/funding_rate | Funding rate history
121123
*FuturesApi* | [**ListFuturesInsuranceLedger**](docs/FuturesApi.md#listfuturesinsuranceledger) | **Get** /futures/{settle}/insurance | Futures insurance balance history
124+
*FuturesApi* | [**ListContractStats**](docs/FuturesApi.md#listcontractstats) | **Get** /futures/{settle}/contract_stats | Futures stats
122125
*FuturesApi* | [**ListFuturesAccounts**](docs/FuturesApi.md#listfuturesaccounts) | **Get** /futures/{settle}/accounts | Query futures account
123126
*FuturesApi* | [**ListFuturesAccountBook**](docs/FuturesApi.md#listfuturesaccountbook) | **Get** /futures/{settle}/account_book | Query account book
124127
*FuturesApi* | [**ListPositions**](docs/FuturesApi.md#listpositions) | **Get** /futures/{settle}/positions | List all positions of a user
@@ -140,6 +143,7 @@ Class | Method | HTTP request | Description
140143
*FuturesApi* | [**GetPriceTriggeredOrder**](docs/FuturesApi.md#getpricetriggeredorder) | **Get** /futures/{settle}/price_orders/{order_id} | Get a single order
141144
*FuturesApi* | [**CancelPriceTriggeredOrder**](docs/FuturesApi.md#cancelpricetriggeredorder) | **Delete** /futures/{settle}/price_orders/{order_id} | Cancel a single order
142145
*MarginApi* | [**ListMarginCurrencyPairs**](docs/MarginApi.md#listmargincurrencypairs) | **Get** /margin/currency_pairs | List all supported currency pairs supported in margin trading
146+
*MarginApi* | [**GetMarginCurrencyPair**](docs/MarginApi.md#getmargincurrencypair) | **Get** /margin/currency_pairs/{currency_pair} | Query one single margin currency pair
143147
*MarginApi* | [**ListFundingBook**](docs/MarginApi.md#listfundingbook) | **Get** /margin/funding_book | Order book of lending loans
144148
*MarginApi* | [**ListMarginAccounts**](docs/MarginApi.md#listmarginaccounts) | **Get** /margin/accounts | Margin account list
145149
*MarginApi* | [**ListMarginAccountBook**](docs/MarginApi.md#listmarginaccountbook) | **Get** /margin/account_book | List margin account balance change history
@@ -188,6 +192,7 @@ Class | Method | HTTP request | Description
188192
- [CancelOrder](docs/CancelOrder.md)
189193
- [CancelOrderResult](docs/CancelOrderResult.md)
190194
- [Contract](docs/Contract.md)
195+
- [ContractStat](docs/ContractStat.md)
191196
- [CurrencyPair](docs/CurrencyPair.md)
192197
- [DeliveryContract](docs/DeliveryContract.md)
193198
- [DeliverySettlement](docs/DeliverySettlement.md)

_example/README.md

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Example Application
2+
3+
This is a demo application using `gateapi` to show how Gate APIv4 works.
4+
Instead of running it, it is recommended to read the source code to get a general idea of
5+
how this SDK is used. However, you can modify this code directly to implement your own logic.
6+
7+
## Build
8+
9+
```bash
10+
# change into your $GOPATH
11+
cd $GOPATH
12+
13+
# create a new application
14+
mkdir gateapi-demo && cd gateapi-demo
15+
16+
# install required dependency
17+
go mod init
18+
go get github.com/gateio/gateapi-go/v5
19+
go get github.com/shopspring/decimal
20+
21+
# build the demo application
22+
go build
23+
```
24+
25+
## Run
26+
27+
**READ THIS BEFORE YOU RUN ANYTHING**
28+
29+
**This application is shown for demo only. It will try to use your input API key and secret to
30+
trade, lend and borrow, etc. Make sure you know exactly what it does before running it.**
31+
32+
```bash
33+
# run futures demo against TestNet
34+
./gateapi-demo futures -k <YOUR_TESTNET_API_KEY> -s <YOUR_TESTNET_API_SECRET> -u fx-api-testnet.gateio.ws
35+
36+
# run futures demo against real trading
37+
./gateapi-demo futures -k <YOUR_API_KEY> -s <YOUR_API_SECRET>
38+
39+
# run spot demo
40+
./gateapi-demo spot -k <YOUR_API_KEY> -s <YOUR_API_SECRET>
41+
42+
# run margin demo
43+
./gateapi-demo margin -k <YOUR_API_KEY> -s <YOUR_API_SECRET>
44+
```

_example/config.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package main
2+
3+
import (
4+
"net/url"
5+
"strings"
6+
)
7+
8+
type RunConfig struct {
9+
ApiKey string
10+
ApiSecret string
11+
BaseUrl string
12+
UseTestNet bool
13+
}
14+
15+
func NewRunConfig(apiKey string, apiSecret string, hostUsed *string) (*RunConfig, error) {
16+
config := &RunConfig{
17+
ApiKey: apiKey,
18+
ApiSecret: apiSecret,
19+
UseTestNet: false,
20+
BaseUrl: *hostUsed,
21+
}
22+
if hostUsed == nil || *hostUsed == "" {
23+
config.BaseUrl = "https://api.gateio.ws/api/v4"
24+
}
25+
if !strings.HasPrefix(config.BaseUrl, "http") {
26+
config.BaseUrl = "https://" + config.BaseUrl
27+
}
28+
if !strings.HasSuffix(config.BaseUrl, "/api/v4") {
29+
config.BaseUrl += "/api/v4"
30+
}
31+
parsedUrl, err := url.Parse(config.BaseUrl)
32+
if err != nil {
33+
return nil, err
34+
}
35+
if parsedUrl.Host == "fx-api-testnet.gateio.ws" {
36+
config.UseTestNet = true
37+
}
38+
return config, nil
39+
}

_example/futures.go

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"strconv"
6+
"strings"
7+
"time"
8+
9+
"github.com/antihax/optional"
10+
"github.com/gateio/gateapi-go/v5"
11+
"github.com/shopspring/decimal"
12+
)
13+
14+
func FuturesDemo(config *RunConfig) {
15+
settle := "usdt"
16+
contract := "BTC_USDT"
17+
18+
client := gateapi.NewAPIClient(gateapi.NewConfiguration())
19+
client.ChangeBasePath(config.BaseUrl)
20+
ctx := context.WithValue(context.Background(), gateapi.ContextGateAPIV4, gateapi.GateAPIV4{
21+
Key: config.ApiKey,
22+
Secret: config.ApiSecret,
23+
})
24+
25+
// update position leverage
26+
leverage := "3"
27+
_, _, err := client.FuturesApi.UpdatePositionLeverage(ctx, settle, contract, leverage)
28+
if err != nil {
29+
panicGateError(err)
30+
}
31+
32+
// retrieve position size
33+
positionSize := int64(0)
34+
position, _, err := client.FuturesApi.GetPosition(ctx, settle, contract)
35+
if err != nil {
36+
if e, ok := err.(gateapi.GateAPIError); ok {
37+
// ignore position not found error
38+
if e.Label != "POSITION_NOT_FOUND" {
39+
panicGateError(e)
40+
}
41+
} else {
42+
panicGateError(err)
43+
}
44+
} else {
45+
positionSize = position.Size
46+
}
47+
48+
futuresContract, _, err := client.FuturesApi.GetFuturesContract(ctx, settle, contract)
49+
if err != nil {
50+
panicGateError(err)
51+
}
52+
orderSize := int64(10)
53+
if orderSize < futuresContract.OrderSizeMin {
54+
orderSize = futuresContract.OrderSizeMin
55+
}
56+
if positionSize < 0 {
57+
orderSize = 0 - orderSize
58+
}
59+
60+
// example to update risk limit
61+
riskLimit := decimal.RequireFromString(futuresContract.RiskLimitBase).Add(decimal.RequireFromString(futuresContract.RiskLimitStep))
62+
_, _, err = client.FuturesApi.UpdatePositionRiskLimit(ctx, settle, contract, riskLimit.String())
63+
if err != nil {
64+
panicGateError(err)
65+
}
66+
67+
// retrieve last price to calculate margin needed
68+
tickers, _, err := client.FuturesApi.ListFuturesTickers(ctx, settle, &gateapi.ListFuturesTickersOpts{
69+
Contract: optional.NewString(contract),
70+
})
71+
lastPrice := tickers[0].Last
72+
logger.Printf("last price of contract %s: %s", contract, lastPrice)
73+
74+
margin := decimal.NewFromInt(orderSize).Mul(
75+
decimal.RequireFromString(lastPrice)).Mul(
76+
decimal.RequireFromString(futuresContract.QuantoMultiplier)).DivRound(
77+
decimal.RequireFromString(leverage), 8).Mul(
78+
decimal.RequireFromString("1.1")).Round(8)
79+
logger.Printf("needs margin amount: %s\n", margin.String())
80+
81+
// if balance is not enough, transfer from spot account
82+
available := "0"
83+
futuresAccount, _, err := client.FuturesApi.ListFuturesAccounts(ctx, settle)
84+
if err != nil {
85+
if e, ok := err.(gateapi.GateAPIError); ok {
86+
if e.Label != "USER_NOT_FOUND" {
87+
panicGateError(e)
88+
}
89+
} else {
90+
panicGateError(err)
91+
}
92+
} else {
93+
available = futuresAccount.Available
94+
}
95+
logger.Printf("futures account available: %s %s\n", available, strings.ToUpper(settle))
96+
if margin.GreaterThan(decimal.RequireFromString(available)) {
97+
if config.UseTestNet {
98+
logger.Fatal("testnet account balance not enough, make a transferal on web")
99+
}
100+
transfer := gateapi.Transfer{
101+
Currency: strings.ToUpper(settle),
102+
From: "spot",
103+
To: "futures",
104+
Amount: margin.String(),
105+
}
106+
_, err := client.WalletApi.Transfer(ctx, transfer)
107+
if err != nil {
108+
panicGateError(err)
109+
}
110+
}
111+
112+
// example to cancel all open orders in contract
113+
_, _, err = client.FuturesApi.CancelFuturesOrders(ctx, settle, contract, nil)
114+
if err != nil {
115+
panicGateError(err)
116+
}
117+
118+
// order using market price
119+
order := gateapi.FuturesOrder{Contract: contract, Size: orderSize, Price: "0", Tif: "ioc"}
120+
orderResponse, _, err := client.FuturesApi.CreateFuturesOrder(ctx, settle, order)
121+
if err != nil {
122+
panicGateError(err)
123+
}
124+
logger.Printf("order %d created with status: %s\n", orderResponse.Id, orderResponse.Status)
125+
if orderResponse.Status == "open" {
126+
futuresOrder, _, err := client.FuturesApi.GetFuturesOrder(ctx, settle, strconv.FormatInt(orderResponse.Id, 10))
127+
if err != nil {
128+
panicGateError(err)
129+
}
130+
logger.Printf("order %d status %s, total size %d, left %d\n",
131+
futuresOrder.Id, futuresOrder.Status, futuresOrder.Size, futuresOrder.Left)
132+
_, _, err = client.FuturesApi.CancelFuturesOrder(ctx, settle, strconv.FormatInt(orderResponse.Id, 10))
133+
if err != nil {
134+
panicGateError(err)
135+
}
136+
logger.Printf("order %d cancelled\n", orderResponse.Id)
137+
} else {
138+
time.Sleep(time.Millisecond * 200)
139+
orderTrades, _, err := client.FuturesApi.GetMyTrades(ctx, settle, &gateapi.GetMyTradesOpts{
140+
Contract: optional.NewString(contract),
141+
Order: optional.NewInt64(orderResponse.Id),
142+
})
143+
if err != nil {
144+
panicGateError(err)
145+
}
146+
for _, t := range orderTrades {
147+
logger.Printf("order %s filled size %d with price %s\n", t.OrderId, t.Size, t.Price)
148+
}
149+
}
150+
151+
// example to update position margin
152+
_, _, err = client.FuturesApi.UpdatePositionMargin(ctx, settle, contract, "0.01")
153+
if err != nil {
154+
panicGateError(err)
155+
}
156+
}

_example/main.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"log"
7+
"math/rand"
8+
"os"
9+
"time"
10+
11+
"github.com/gateio/gateapi-go/v5"
12+
)
13+
14+
var logger = log.New(flag.CommandLine.Output(), "", log.LstdFlags)
15+
16+
func panicGateError(err error) {
17+
if e, ok := err.(gateapi.GateAPIError); ok {
18+
log.Fatal(fmt.Sprintf("Gate API error, label: %s, message: %s", e.Label, e.Message))
19+
}
20+
log.Fatal(err)
21+
}
22+
23+
func main() {
24+
var key, secret, baseUrl string
25+
flag.StringVar(&key, "k", "", "Gate APIv4 key")
26+
flag.StringVar(&secret, "s", "", "Gate APIv4 secret")
27+
flag.StringVar(&baseUrl, "u", "", "API based URL used")
28+
flag.Parse()
29+
30+
usage := fmt.Sprintf("Usage: %s -k <api-key> -s <api-secret> <spot|margin|futures>", os.Args[0])
31+
32+
if key == "" || secret == "" {
33+
logger.Println(usage)
34+
flag.PrintDefaults()
35+
os.Exit(1)
36+
}
37+
if flag.NArg() < 1 {
38+
logger.Println(usage)
39+
flag.PrintDefaults()
40+
os.Exit(1)
41+
}
42+
43+
runConfig, err := NewRunConfig(key, secret, &baseUrl)
44+
if err != nil {
45+
logger.Fatal(err)
46+
}
47+
rand.Seed(time.Now().Unix())
48+
for _, demo := range flag.Args() {
49+
switch demo {
50+
case "spot":
51+
SpotDemo(runConfig)
52+
case "margin":
53+
MarginDemo(runConfig)
54+
case "futures":
55+
FuturesDemo(runConfig)
56+
default:
57+
logger.Fatal("Invalid demo provided. Available: spot, margin or futures")
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)