271 lines
8.8 KiB
Go
271 lines
8.8 KiB
Go
package trade
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"log"
|
|
"strings"
|
|
|
|
"git.apinb.com/bsm-sdk/core/utils"
|
|
"git.apinb.com/quant/strategy/internal/core/market"
|
|
"github.com/bitget-golang/sdk-api/config"
|
|
bitget "github.com/bitget-golang/sdk-api/pkg/client/v2"
|
|
)
|
|
|
|
type BitgetClient struct {
|
|
LastUPL map[string]float64
|
|
AccountClient *bitget.MixAccountClient
|
|
MarketClient *bitget.MixMarketClient
|
|
OrderClient *bitget.MixOrderClient
|
|
}
|
|
|
|
type SymbolResp struct {
|
|
Code string `json:"code"`
|
|
Data []SymbolDataResp `json:"data"`
|
|
Msg string `json:"msg"`
|
|
RequestTime int64 `json:"requestTime"`
|
|
}
|
|
|
|
type SymbolDataResp struct {
|
|
BaseCoin string `json:"baseCoin"`
|
|
BuyLimitPriceRatio string `json:"buyLimitPriceRatio"`
|
|
DeliveryStartTime string `json:"deliveryStartTime"`
|
|
DeliveryTime string `json:"deliveryTime"`
|
|
FeeRateUpRatio string `json:"feeRateUpRatio"`
|
|
FundInterval string `json:"fundInterval"`
|
|
LaunchTime string `json:"launchTime"`
|
|
LimitOpenTime string `json:"limitOpenTime"`
|
|
MaintainTime string `json:"maintainTime"`
|
|
MakerFeeRate string `json:"makerFeeRate"`
|
|
MaxLever string `json:"maxLever"`
|
|
MaxPositionNum string `json:"maxPositionNum"`
|
|
MaxProductOrderNum string `json:"maxProductOrderNum"`
|
|
MaxSymbolOrderNum string `json:"maxSymbolOrderNum"`
|
|
MinLever string `json:"minLever"`
|
|
MinTradeNum string `json:"minTradeNum"`
|
|
MinTradeUSDT string `json:"minTradeUSDT"`
|
|
OffTime string `json:"offTime"`
|
|
OpenCostUpRatio string `json:"openCostUpRatio"`
|
|
PosLimit string `json:"posLimit"`
|
|
PriceEndStep string `json:"priceEndStep"`
|
|
PricePlace string `json:"pricePlace"`
|
|
QuoteCoin string `json:"quoteCoin"`
|
|
SellLimitPriceRatio string `json:"sellLimitPriceRatio"`
|
|
SizeMultiplier string `json:"sizeMultiplier"`
|
|
SupportMarginCoins []string `json:"supportMarginCoins"`
|
|
Symbol string `json:"symbol"`
|
|
SymbolStatus string `json:"symbolStatus"`
|
|
SymbolType string `json:"symbolType"`
|
|
TakerFeeRate string `json:"takerFeeRate"`
|
|
VolumePlace string `json:"volumePlace"`
|
|
}
|
|
|
|
type AccountsResp struct {
|
|
Code string `json:"code"`
|
|
Data []struct {
|
|
MarginCoin string `json:"marginCoin"`
|
|
Locked string `json:"locked"`
|
|
Available string `json:"available"`
|
|
CrossedMaxAvailable string `json:"crossedMaxAvailable"`
|
|
IsolatedMaxAvailable string `json:"isolatedMaxAvailable"`
|
|
MaxTransferOut string `json:"maxTransferOut"`
|
|
AccountEquity string `json:"accountEquity"`
|
|
UsdtEquity string `json:"usdtEquity"`
|
|
BtcEquity string `json:"btcEquity"`
|
|
CrossedRiskRate string `json:"crossedRiskRate"`
|
|
UnrealizedPL string `json:"unrealizedPL"`
|
|
Coupon string `json:"coupon"`
|
|
UnionTotalMagin string `json:"unionTotalMagin"`
|
|
UnionAvailable string `json:"unionAvailable"`
|
|
UnionMm string `json:"unionMm"`
|
|
AssetList []struct {
|
|
Coin string `json:"coin"`
|
|
Balance string `json:"balance"`
|
|
Available string `json:"available"`
|
|
} `json:"assetList"`
|
|
IsolatedMargin string `json:"isolatedMargin"`
|
|
CrossedMargin string `json:"crossedMargin"`
|
|
CrossedUnrealizedPL string `json:"crossedUnrealizedPL"`
|
|
IsolatedUnrealizedPL string `json:"isolatedUnrealizedPL"`
|
|
AssetMode string `json:"assetMode"`
|
|
} `json:"data"`
|
|
Msg string `json:"msg"`
|
|
RequestTime int64 `json:"requestTime"`
|
|
}
|
|
|
|
type AllPositionResp struct {
|
|
Code string `json:"code"`
|
|
Data []*BitgetPositionData `json:"data"`
|
|
Msg string `json:"msg"`
|
|
RequestTime int64 `json:"requestTime"`
|
|
}
|
|
type BitgetPositionData struct {
|
|
AchievedProfits string `json:"achievedProfits"`
|
|
Available string `json:"available"`
|
|
BreakEvenPrice string `json:"breakEvenPrice"`
|
|
CTime string `json:"cTime"`
|
|
DeductedFee string `json:"deductedFee"`
|
|
HoldSide string `json:"holdSide"`
|
|
KeepMarginRate string `json:"keepMarginRate"`
|
|
Leverage string `json:"leverage"`
|
|
LiquidationPrice string `json:"liquidationPrice"`
|
|
Locked string `json:"locked"`
|
|
MarginCoin string `json:"marginCoin"`
|
|
MarginMode string `json:"marginMode"`
|
|
MarginRatio string `json:"marginRatio"`
|
|
MarginSize string `json:"marginSize"`
|
|
MarkPrice string `json:"markPrice"`
|
|
OpenDelegateSize string `json:"openDelegateSize"`
|
|
OpenPriceAvg string `json:"openPriceAvg"`
|
|
PosMode string `json:"posMode"`
|
|
Symbol string `json:"symbol"`
|
|
Total string `json:"total"`
|
|
TotalFee string `json:"totalFee"`
|
|
UnrealizedPL string `json:"unrealizedPL"`
|
|
UnrealizedPLR string `json:"unrealizedPLR"`
|
|
}
|
|
|
|
type RespMapString struct {
|
|
Code string `json:"code"`
|
|
Data []map[string]string `json:"data"`
|
|
Msg string `json:"msg"`
|
|
RequestTime int64 `json:"requestTime"`
|
|
}
|
|
|
|
func NewBitgetClient(apiKey, apiSecret, passphrase string) *BitgetClient {
|
|
bg := &BitgetClient{
|
|
LastUPL: make(map[string]float64),
|
|
}
|
|
|
|
config.ApiKey = apiKey
|
|
config.SecretKey = apiSecret
|
|
config.PASSPHRASE = passphrase
|
|
config.BaseUrl = "https://api.bitget.com"
|
|
config.WsUrl = "wss://ws.bitget.com/v2/ws/private"
|
|
|
|
bg.AccountClient = new(bitget.MixAccountClient).Init()
|
|
bg.AccountClient.BitgetRestClient.ApiKey = config.ApiKey
|
|
bg.AccountClient.BitgetRestClient.ApiSecretKey = config.SecretKey
|
|
bg.AccountClient.BitgetRestClient.Passphrase = config.PASSPHRASE
|
|
|
|
bg.MarketClient = new(bitget.MixMarketClient).Init()
|
|
bg.MarketClient.BitgetRestClient.ApiKey = config.ApiKey
|
|
bg.MarketClient.BitgetRestClient.ApiSecretKey = config.SecretKey
|
|
bg.MarketClient.BitgetRestClient.Passphrase = config.PASSPHRASE
|
|
|
|
bg.OrderClient = new(bitget.MixOrderClient).Init()
|
|
bg.OrderClient.BitgetRestClient.ApiKey = config.ApiKey
|
|
bg.OrderClient.BitgetRestClient.ApiSecretKey = config.SecretKey
|
|
bg.OrderClient.BitgetRestClient.Passphrase = config.PASSPHRASE
|
|
|
|
Info("BitgetClient init ok")
|
|
return bg
|
|
}
|
|
|
|
func (bg *BitgetClient) GetFuturesAccountBalance() (string, map[string]*AccountsBalance, error) {
|
|
args := map[string]string{"productType": "USDT-FUTURES"}
|
|
res, err := bg.AccountClient.Accounts(args)
|
|
if err != nil {
|
|
return res, nil, err
|
|
}
|
|
|
|
// assets, _ := json.Marshal(res.Assets)
|
|
// log.Println("==>", string(assets))
|
|
|
|
var acResp AccountsResp
|
|
err = json.Unmarshal([]byte(res), &acResp)
|
|
if err != nil {
|
|
return res, nil, err
|
|
}
|
|
if acResp.Code != "00000" {
|
|
return res, nil, errors.New(acResp.Msg)
|
|
}
|
|
|
|
ac := make(map[string]*AccountsBalance)
|
|
for _, v := range acResp.Data {
|
|
ac[strings.ToUpper(v.MarginCoin)] = &AccountsBalance{
|
|
AccountEquity: utils.String2Float64(v.AccountEquity),
|
|
Available: utils.String2Float64(v.Available),
|
|
}
|
|
}
|
|
|
|
return res, ac, nil
|
|
}
|
|
|
|
func (bg *BitgetClient) GetSymbolSetting(cli *bitget.MixMarketClient, symbols []string) (map[string]*market.PairSetting, error) {
|
|
args := map[string]string{
|
|
"productType": "USDT-FUTURES",
|
|
}
|
|
resp, err := bg.MarketClient.Contracts(args)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var reply SymbolResp
|
|
json.Unmarshal([]byte(resp), &reply)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(reply.Data) == 0 {
|
|
return nil, errors.New("data is empty")
|
|
}
|
|
|
|
data := make(map[string]*market.PairSetting)
|
|
for _, item := range reply.Data {
|
|
if utils.ArrayInString(item.Symbol, symbols) {
|
|
data[item.Symbol] = &market.PairSetting{
|
|
Symbol: item.Symbol,
|
|
BaseAssetPrecision: 0,
|
|
QuantityPrecision: utils.String2Int(item.VolumePlace),
|
|
PricePrecision: utils.String2Int(item.PricePlace),
|
|
MinTradeNum: utils.String2Float64(item.MinTradeNum),
|
|
MinNotional: utils.String2Float64(item.MinTradeUSDT),
|
|
Commit: item.MaxLever,
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return data, nil
|
|
}
|
|
|
|
func (bg *BitgetClient) SetLeverage(symbol string, leve string) {
|
|
args := map[string]string{
|
|
"productType": "USDT-FUTURES",
|
|
"marginCoin": "USDT",
|
|
"symbol": symbol,
|
|
"leverage": leve,
|
|
}
|
|
|
|
_, err := bg.AccountClient.SetLeverage(args)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
log.Println("[INFO]", symbol, "SetLeverage:", leve)
|
|
}
|
|
|
|
// 获取交易对价格,限速规则: 20次/1s (IP)
|
|
func (bg *BitgetClient) GetSymbolPrice(symbol string) (map[string]string, error) {
|
|
args := map[string]string{
|
|
"productType": "USDT-FUTURES",
|
|
"symbol": symbol,
|
|
}
|
|
resp, err := bg.MarketClient.SymbolPrice(args)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var reply RespMapString
|
|
json.Unmarshal([]byte(resp), &reply)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if reply.Code != "00000" {
|
|
return nil, errors.New(reply.Msg)
|
|
}
|
|
|
|
return reply.Data[0], nil
|
|
}
|