Skip to content

Commit

Permalink
okx: add account positions api
Browse files Browse the repository at this point in the history
  • Loading branch information
c9s committed Jan 23, 2025
1 parent 13c2f85 commit 06ef3d8
Show file tree
Hide file tree
Showing 8 changed files with 464 additions and 36 deletions.
22 changes: 22 additions & 0 deletions pkg/exchange/okex/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,3 +362,25 @@ func toGlobalOrder(okexOrder *okexapi.OrderDetails) (*types.Order, error) {
IsIsolated: false,
}, nil
}

func toGlobalMarginLoan(record okexapi.MarginHistoryEntry) types.MarginLoan {
return types.MarginLoan{
Exchange: types.ExchangeOKEx,
TransactionID: uint64(record.Ts.Time().UnixMilli()),
Asset: record.Currency,
Principle: record.Amount,
Time: types.Time(record.Ts.Time()),
IsolatedSymbol: "",
}
}

func toGlobalMarginRepay(record okexapi.MarginHistoryEntry) types.MarginRepay {
return types.MarginRepay{
Exchange: types.ExchangeOKEx,
TransactionID: uint64(record.Ts.Time().UnixMilli()),
Asset: record.Currency,
Principle: record.Amount,
Time: types.Time(record.Ts.Time()),
IsolatedSymbol: "",
}
}
58 changes: 58 additions & 0 deletions pkg/exchange/okex/exchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,64 @@ func (e *Exchange) QueryMarginAssetMaxBorrowable(ctx context.Context, asset stri
return resp[0].MaxLoan, nil
}

func (e *Exchange) QueryLoanHistory(ctx context.Context, asset string, startTime, endTime *time.Time) ([]types.MarginLoan, error) {
req := e.client.NewGetAccountSpotBorrowRepayHistoryRequest().Currency(asset)
if endTime != nil {
req.Before(*endTime)
}
if startTime != nil {
req.After(*startTime)
}

resp, err := req.Do(ctx)
if err != nil {
return nil, err
}

var records []types.MarginLoan
for _, r := range resp {
switch r.Type {
case okexapi.MarginEventTypeManualBorrow, okexapi.MarginEventTypeAutoBorrow:
records = append(records, toGlobalMarginLoan(r))
}
}

return records, nil
}

func (e *Exchange) QueryRepayHistory(ctx context.Context, asset string, startTime, endTime *time.Time) ([]types.MarginRepay, error) {
req := e.client.NewGetAccountSpotBorrowRepayHistoryRequest().Currency(asset)
if endTime != nil {
req.Before(*endTime)
}
if startTime != nil {
req.After(*startTime)
}

resp, err := req.Do(ctx)
if err != nil {
return nil, err
}

var records []types.MarginRepay
for _, r := range resp {
switch r.Type {
case okexapi.MarginEventTypeManualRepay, okexapi.MarginEventTypeAutoRepay:
records = append(records, toGlobalMarginRepay(r))
}
}

return records, nil
}

func (e *Exchange) QueryLiquidationHistory(ctx context.Context, startTime, endTime *time.Time) ([]types.MarginLiquidation, error) {
return nil, nil
}

func (e *Exchange) QueryInterestHistory(ctx context.Context, asset string, startTime, endTime *time.Time) ([]types.MarginInterest, error) {
return nil, nil
}

/*
QueryTrades can query trades in last 3 months, there are no time interval limitations, as long as end_time >= start_time.
okx does not provide an API to query by trade ID, so we use the bill ID to do it. The trades result is ordered by timestamp.
Expand Down
19 changes: 19 additions & 0 deletions pkg/exchange/okex/okexapi/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package okexapi

import (
"context"
"encoding/json"
"fmt"
"os"
"strconv"
Expand Down Expand Up @@ -429,6 +430,11 @@ func TestClient_Margin(t *testing.T) {
if assert.NoError(t, err) {
t.Logf("borrow response: %+v", resp)

positionRiskResp, err2 := client.NewGetAccountPositionRiskRequest().Do(ctx)
if assert.NoError(t, err2) {
t.Logf("position risk response: %+v", positionRiskResp)
}

time.Sleep(1 * time.Second)
repayResp, repayErr := client.NewSpotManualBorrowRepayRequest().
Currency("BTC").
Expand All @@ -450,4 +456,17 @@ func TestClient_Margin(t *testing.T) {
t.Logf("history response: %+v", historyResp)
}
})

t.Run("get account positions", func(t *testing.T) {
resp, err := client.NewGetAccountPositionsRequest().InstType(InstrumentTypeMargin).Do(ctx)
if assert.NoError(t, err) {
t.Logf("positions: %+v", resp)

if len(resp) > 0 {
out, err2 := json.MarshalIndent(resp[0], "", " ")
assert.NoError(t, err2)
t.Logf("positions: %s", out)
}
}
})
}
28 changes: 15 additions & 13 deletions pkg/exchange/okex/okexapi/get_account_config_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,21 @@ type AccountConfig struct {
Label string `json:"label"`
Level string `json:"level"`
LevelTmp string `json:"levelTmp"`
LiquidationGear string `json:"liquidationGear"`
MainUid string `json:"mainUid"`
MgnIsoMode string `json:"mgnIsoMode"`
OpAuth string `json:"opAuth"`
Perm string `json:"perm"`
PosMode string `json:"posMode"`
RoleType types.StrInt64 `json:"roleType"`
SpotBorrowAutoRepay bool `json:"spotBorrowAutoRepay"`
SpotOffsetType string `json:"spotOffsetType"`
SpotRoleType string `json:"spotRoleType"`
SpotTraderInsts []interface{} `json:"spotTraderInsts"`
TraderInsts []interface{} `json:"traderInsts"`
Uid string `json:"uid"`

LiquidationGear types.StrInt64 `json:"liquidationGear"`

MainUid string `json:"mainUid"`
MarginIsoMode string `json:"mgnIsoMode"`
OpAuth string `json:"opAuth"`
Perm string `json:"perm"`
PosMode string `json:"posMode"`
RoleType types.StrInt64 `json:"roleType"`
SpotBorrowAutoRepay bool `json:"spotBorrowAutoRepay"`
SpotOffsetType string `json:"spotOffsetType"`
SpotRoleType string `json:"spotRoleType"`
SpotTraderInsts []interface{} `json:"spotTraderInsts"`
TraderInsts []interface{} `json:"traderInsts"`
Uid string `json:"uid"`
}

//go:generate GetRequest -url "/api/v5/account/config" -type GetAccountConfigRequest -responseDataType []AccountConfig
Expand Down
53 changes: 32 additions & 21 deletions pkg/exchange/okex/okexapi/get_account_position_risk_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,49 @@ package okexapi

import (
"github.com/c9s/requestgen"

"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
)

//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Data
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Data

type PositionData struct {
Currency string `json:"ccy"`
InstId string `json:"instId"`
InstType string `json:"instType"`

MarginMode MarginMode `json:"mgnMode"`
NotionalCurrency fixedpoint.Value `json:"notionalCcy"`
NotionalUsd fixedpoint.Value `json:"notionalUsd"`
Pos fixedpoint.Value `json:"pos"`
PosCurrency string `json:"posCcy"`
PosId string `json:"posId"`
PosSide string `json:"posSide"`

BaseBal fixedpoint.Value `json:"baseBal"`
QuoteBal fixedpoint.Value `json:"quoteBal"`
}

type PositionBalanceData struct {
Currency string `json:"ccy"`
DisEquity fixedpoint.Value `json:"disEq"`
Equity fixedpoint.Value `json:"eq"`
}

type PositionRiskResponse struct {
AdjEq string `json:"adjEq"`
BalData []struct {
Ccy string `json:"ccy"`
DisEq string `json:"disEq"`
Eq string `json:"eq"`
} `json:"balData"`
PosData []struct {
BaseBal string `json:"baseBal"`
Ccy string `json:"ccy"`
InstId string `json:"instId"`
InstType string `json:"instType"`
MgnMode string `json:"mgnMode"`
NotionalCcy string `json:"notionalCcy"`
NotionalUsd string `json:"notionalUsd"`
Pos string `json:"pos"`
PosCcy string `json:"posCcy"`
PosId string `json:"posId"`
PosSide string `json:"posSide"`
QuoteBal string `json:"quoteBal"`
} `json:"posData"`
Ts string `json:"ts"`
AdjEq fixedpoint.Value `json:"adjEq"`
BalData []PositionBalanceData `json:"balData"`
PosData []PositionData `json:"posData"`
Ts types.MillisecondTimestamp `json:"ts"`
}

//go:generate GetRequest -url "/api/v5/account/account-position-risk" -type GetAccountPositionRiskRequest -responseDataType []PositionRiskResponse
type GetAccountPositionRiskRequest struct {
client requestgen.AuthenticatedAPIClient

instType *InstrumentType `param:"instType"`
}

func (c *RestClient) NewGetAccountPositionRiskRequest() *GetAccountPositionRiskRequest {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

91 changes: 91 additions & 0 deletions pkg/exchange/okex/okexapi/get_account_positions_request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package okexapi

import (
"github.com/c9s/requestgen"

"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
)

//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Data
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Data

type Position struct {
Adl fixedpoint.Value `json:"adl"`
AvailPos fixedpoint.Value `json:"availPos"`
AvgPx fixedpoint.Value `json:"avgPx"`
BaseBal fixedpoint.Value `json:"baseBal"`
BaseBorrowed fixedpoint.Value `json:"baseBorrowed"`
BaseInterest fixedpoint.Value `json:"baseInterest"`
BePx fixedpoint.Value `json:"bePx"`
BizRefId string `json:"bizRefId"`
BizRefType string `json:"bizRefType"`

Ccy string `json:"ccy"`
ClSpotInUseAmt string `json:"clSpotInUseAmt"`
CloseOrderAlgo []interface{} `json:"closeOrderAlgo"`
DeltaBS string `json:"deltaBS"`
DeltaPA string `json:"deltaPA"`
Fee fixedpoint.Value `json:"fee"`
FundingFee fixedpoint.Value `json:"fundingFee"`
GammaBS string `json:"gammaBS"`
GammaPA string `json:"gammaPA"`
IdxPx fixedpoint.Value `json:"idxPx"`
Imr string `json:"imr"`
InstId string `json:"instId"`
InstType string `json:"instType"`
Interest fixedpoint.Value `json:"interest"`
Last fixedpoint.Value `json:"last"`
Lever fixedpoint.Value `json:"lever"`
Liab fixedpoint.Value `json:"liab"`
LiabCcy string `json:"liabCcy"`
LiqPenalty string `json:"liqPenalty"`
LiqPx fixedpoint.Value `json:"liqPx"`
Margin fixedpoint.Value `json:"margin"`
MarkPx fixedpoint.Value `json:"markPx"`
MaxSpotInUseAmt string `json:"maxSpotInUseAmt"`
MgnMode string `json:"mgnMode"`
MgnRatio fixedpoint.Value `json:"mgnRatio"`
Mmr string `json:"mmr"`
NotionalUsd string `json:"notionalUsd"`
OptVal string `json:"optVal"`
PendingCloseOrdLiabVal string `json:"pendingCloseOrdLiabVal"`
Pnl fixedpoint.Value `json:"pnl"`
Pos fixedpoint.Value `json:"pos"`
PosCcy string `json:"posCcy"`
PosId string `json:"posId"`
PosSide string `json:"posSide"`
QuoteBal fixedpoint.Value `json:"quoteBal"`
QuoteBorrowed fixedpoint.Value `json:"quoteBorrowed"`
QuoteInterest fixedpoint.Value `json:"quoteInterest"`
RealizedPnl fixedpoint.Value `json:"realizedPnl"`
SpotInUseAmt string `json:"spotInUseAmt"`
SpotInUseCcy string `json:"spotInUseCcy"`
ThetaBS string `json:"thetaBS"`
ThetaPA string `json:"thetaPA"`
TradeId string `json:"tradeId"`

CreationTime types.MillisecondTimestamp `json:"cTime"`
UpdatedTime types.MillisecondTimestamp `json:"uTime"`

Upl string `json:"upl"`
UplLastPx fixedpoint.Value `json:"uplLastPx"`
UplRatio string `json:"uplRatio"`
UplRatioLastPx string `json:"uplRatioLastPx"`
UsdPx fixedpoint.Value `json:"usdPx"`
VegaBS string `json:"vegaBS"`
VegaPA string `json:"vegaPA"`
}

//go:generate GetRequest -url "/api/v5/account/positions" -type GetAccountPositionsRequest -responseDataType []Position
type GetAccountPositionsRequest struct {
client requestgen.AuthenticatedAPIClient

instType *InstrumentType `param:"instType"`
}

func (c *RestClient) NewGetAccountPositionsRequest() *GetAccountPositionsRequest {
return &GetAccountPositionsRequest{
client: c,
}
}
Loading

0 comments on commit 06ef3d8

Please sign in to comment.