mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 00:35:15 +00:00
ftx: support account info
This commit is contained in:
parent
9e596a0f63
commit
8a75b21a38
78
pkg/cmd/account.go
Normal file
78
pkg/cmd/account.go
Normal file
|
@ -0,0 +1,78 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/bbgo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
accountCmd.Flags().String("session", "", "the exchange session name for querying information")
|
||||
RootCmd.AddCommand(accountCmd)
|
||||
}
|
||||
|
||||
// go run ./cmd/bbgo account --session=ftx --config=config/bbgo.yaml
|
||||
var accountCmd = &cobra.Command{
|
||||
Use: "account",
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx := context.Background()
|
||||
|
||||
configFile, err := cmd.Flags().GetString("config")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(configFile) == 0 {
|
||||
return errors.New("--config option is required")
|
||||
}
|
||||
|
||||
var userConfig *bbgo.Config
|
||||
if _, err := os.Stat(configFile); err == nil {
|
||||
// load successfully
|
||||
userConfig, err = bbgo.Load(configFile, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if os.IsNotExist(err) {
|
||||
// config file doesn't exist
|
||||
userConfig = &bbgo.Config{}
|
||||
} else {
|
||||
// other error
|
||||
return err
|
||||
}
|
||||
|
||||
environ := bbgo.NewEnvironment()
|
||||
if err := environ.ConfigureDatabase(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := environ.ConfigureExchangeSessions(userConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sessionName, err := cmd.Flags().GetString("session")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
session, ok := environ.Session(sessionName)
|
||||
if !ok {
|
||||
return fmt.Errorf("session %s not found", sessionName)
|
||||
}
|
||||
|
||||
a, err := session.Exchange.QueryAccount(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("account info: %+v", a)
|
||||
return nil
|
||||
},
|
||||
}
|
|
@ -65,7 +65,27 @@ func (e *Exchange) QueryMarkets(ctx context.Context) (types.MarketMap, error) {
|
|||
}
|
||||
|
||||
func (e *Exchange) QueryAccount(ctx context.Context) (*types.Account, error) {
|
||||
panic("implement me")
|
||||
resp, err := e.newRest().Account(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !resp.Success {
|
||||
return nil, fmt.Errorf("ftx returns querying balances failure")
|
||||
}
|
||||
|
||||
// TODO
|
||||
a := &types.Account{
|
||||
MakerCommission: 0,
|
||||
TakerCommission: 0,
|
||||
}
|
||||
|
||||
balances, err := e.QueryAccountBalances(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a.UpdateBalances(balances)
|
||||
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (e *Exchange) QueryAccountBalances(ctx context.Context) (types.BalanceMap, error) {
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
type restRequest struct {
|
||||
*balanceRequest
|
||||
*orderRequest
|
||||
*accountRequest
|
||||
|
||||
key, secret string
|
||||
// Optional sub-account name
|
||||
|
@ -42,6 +43,7 @@ func newRestRequest(c *http.Client, baseURL *url.URL) *restRequest {
|
|||
baseURL: baseURL,
|
||||
}
|
||||
|
||||
r.accountRequest = &accountRequest{restRequest: r}
|
||||
r.balanceRequest = &balanceRequest{restRequest: r}
|
||||
r.orderRequest = &orderRequest{restRequest: r}
|
||||
return r
|
||||
|
|
47
pkg/exchange/ftx/rest_account_request.go
Normal file
47
pkg/exchange/ftx/rest_account_request.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
package ftx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type accountRequest struct {
|
||||
*restRequest
|
||||
}
|
||||
|
||||
func (r *accountRequest) Account(ctx context.Context) (accountResponse, error) {
|
||||
resp, err := r.
|
||||
Method("GET").
|
||||
ReferenceURL("api/account").
|
||||
DoAuthenticatedRequest(ctx)
|
||||
|
||||
if err != nil {
|
||||
return accountResponse{}, err
|
||||
}
|
||||
|
||||
var a accountResponse
|
||||
if err := json.Unmarshal(resp.Body, &a); err != nil {
|
||||
return accountResponse{}, fmt.Errorf("failed to unmarshal account response body to json: %w", err)
|
||||
}
|
||||
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (r *accountRequest) Positions(ctx context.Context) (positionsResponse, error) {
|
||||
resp, err := r.
|
||||
Method("GET").
|
||||
ReferenceURL("api/positions").
|
||||
DoAuthenticatedRequest(ctx)
|
||||
|
||||
if err != nil {
|
||||
return positionsResponse{}, err
|
||||
}
|
||||
|
||||
var p positionsResponse
|
||||
if err := json.Unmarshal(resp.Body, &p); err != nil {
|
||||
return positionsResponse{}, fmt.Errorf("failed to unmarshal position response body to json: %w", err)
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
|
@ -2,6 +2,94 @@ package ftx
|
|||
|
||||
import "time"
|
||||
|
||||
/*
|
||||
{
|
||||
"success": true,
|
||||
"result": {
|
||||
"backstopProvider": true,
|
||||
"collateral": 3568181.02691129,
|
||||
"freeCollateral": 1786071.456884368,
|
||||
"initialMarginRequirement": 0.12222384240257728,
|
||||
"leverage": 10,
|
||||
"liquidating": false,
|
||||
"maintenanceMarginRequirement": 0.07177992558058484,
|
||||
"makerFee": 0.0002,
|
||||
"marginFraction": 0.5588433331419503,
|
||||
"openMarginFraction": 0.2447194090423075,
|
||||
"takerFee": 0.0005,
|
||||
"totalAccountValue": 3568180.98341129,
|
||||
"totalPositionSize": 6384939.6992,
|
||||
"username": "user@domain.com",
|
||||
"positions": [
|
||||
{
|
||||
"cost": -31.7906,
|
||||
"entryPrice": 138.22,
|
||||
"future": "ETH-PERP",
|
||||
"initialMarginRequirement": 0.1,
|
||||
"longOrderSize": 1744.55,
|
||||
"maintenanceMarginRequirement": 0.04,
|
||||
"netSize": -0.23,
|
||||
"openSize": 1744.32,
|
||||
"realizedPnl": 3.39441714,
|
||||
"shortOrderSize": 1732.09,
|
||||
"side": "sell",
|
||||
"size": 0.23,
|
||||
"unrealizedPnl": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
*/
|
||||
type accountResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Result account `json:"result"`
|
||||
}
|
||||
|
||||
type account struct {
|
||||
}
|
||||
|
||||
type positionsResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Result []position `json:"result"`
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
"cost": -31.7906,
|
||||
"entryPrice": 138.22,
|
||||
"estimatedLiquidationPrice": 152.1,
|
||||
"future": "ETH-PERP",
|
||||
"initialMarginRequirement": 0.1,
|
||||
"longOrderSize": 1744.55,
|
||||
"maintenanceMarginRequirement": 0.04,
|
||||
"netSize": -0.23,
|
||||
"openSize": 1744.32,
|
||||
"realizedPnl": 3.39441714,
|
||||
"shortOrderSize": 1732.09,
|
||||
"side": "sell",
|
||||
"size": 0.23,
|
||||
"unrealizedPnl": 0,
|
||||
"collateralUsed": 3.17906
|
||||
}
|
||||
*/
|
||||
type position struct {
|
||||
Cost float64 `json:"cost"`
|
||||
EntryPrice float64 `json:"entryPrice"`
|
||||
EstimatedLiquidationPrice float64 `json:"estimatedLiquidationPrice"`
|
||||
Future string `json:"future"`
|
||||
InitialMarginRequirement float64 `json:"initialMarginRequirement"`
|
||||
LongOrderSize float64 `json:"longOrderSize"`
|
||||
MaintenanceMarginRequirement float64 `json:"maintenanceMarginRequirement"`
|
||||
NetSize float64 `json:"netSize"`
|
||||
OpenSize float64 `json:"openSize"`
|
||||
RealizedPnl float64 `json:"realizedPnl"`
|
||||
ShortOrderSize float64 `json:"shortOrderSize"`
|
||||
Side string `json:"Side"`
|
||||
Size float64 `json:"size"`
|
||||
UnrealizedPnl float64 `json:"unrealizedPnl"`
|
||||
CollateralUsed float64 `json:"collateralUsed"`
|
||||
}
|
||||
|
||||
type balances struct {
|
||||
Success bool `json:"success"`
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@ func (m BalanceMap) Print() {
|
|||
type Account struct {
|
||||
sync.Mutex `json:"-"`
|
||||
|
||||
// bps. 0.15% fee will be 15.
|
||||
MakerCommission int `json:"makerCommission,omitempty"`
|
||||
TakerCommission int `json:"takerCommission,omitempty"`
|
||||
AccountType string `json:"accountType,omitempty"`
|
||||
|
|
Loading…
Reference in New Issue
Block a user