futures: add GetFuturesContractDetails wrapper function (#1274)

* all in a days work

* cleanup

* cleanup for real, also stop it binance.json

* minor coverage

* adds gateio to the slurry

* cleanup of types

* verbose verbose verbose verbose verbose verbose

* fixes huobi parsing issue

* fix bybit contract identification

* cleanup

* merge fixes

* addresses many big problems raised by SHAZ

* tracking errors and fixes

* funding rate if avail, fixes currency formatting

* Addresses nits and sneaks in extra fixes

* lint

* minor fixes after rebase

* better contract splitter for currencies like T-USDT

* forgot to add the exchange name like a fool

* merge fixes x1

* kucoin, direction, contract size

* rn direction, fix kucoin time

* WHOOPS

* Update exchanges/kucoin/kucoin_wrapper.go

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>

* misdirection

---------

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>
This commit is contained in:
Scott
2023-10-03 15:04:45 +10:00
committed by GitHub
parent 08c27afded
commit 7f0faf7850
98 changed files with 5034 additions and 3273 deletions

View File

@@ -355,7 +355,8 @@ func TestSettingsPrint(t *testing.T) {
}
var unsupportedDefaultConfigExchanges = []string{
"itbit", // due to unsupported API
"itbit", // due to unsupported API
"poloniex", // outdated API // TODO remove once updated
}
func TestGetDefaultConfigurations(t *testing.T) {

View File

@@ -20,6 +20,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/currencystate"
"github.com/thrasher-corp/gocryptotrader/exchanges/fundingrate"
"github.com/thrasher-corp/gocryptotrader/exchanges/futures"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -52,7 +53,7 @@ func SetupOrderManager(exchangeManager iExchangeManager, communicationsManager i
exchangeManager: exchangeManager,
commsManager: communicationsManager,
wg: wg,
futuresPositionController: order.SetupPositionController(),
futuresPositionController: futures.SetupPositionController(),
},
verbose: cfg.Verbose,
cfg: orderManagerConfig{
@@ -239,7 +240,7 @@ func (m *OrderManager) Cancel(ctx context.Context, cancel *order.Cancel) error {
// GetFuturesPositionsForExchange returns futures positions stored within
// the order manager's futures position tracker that match the provided params
func (m *OrderManager) GetFuturesPositionsForExchange(exch string, item asset.Item, pair currency.Pair) ([]order.Position, error) {
func (m *OrderManager) GetFuturesPositionsForExchange(exch string, item asset.Item, pair currency.Pair) ([]futures.Position, error) {
if m == nil {
return nil, fmt.Errorf("order manager %w", ErrNilSubsystem)
}
@@ -247,7 +248,7 @@ func (m *OrderManager) GetFuturesPositionsForExchange(exch string, item asset.It
return nil, fmt.Errorf("order manager %w", ErrSubSystemNotStarted)
}
if !item.IsFutures() {
return nil, fmt.Errorf("%v %w", item, order.ErrNotFuturesAsset)
return nil, fmt.Errorf("%v %w", item, futures.ErrNotFuturesAsset)
}
return m.orderStore.futuresPositionController.GetPositionsForExchange(exch, item, pair)
@@ -255,7 +256,7 @@ func (m *OrderManager) GetFuturesPositionsForExchange(exch string, item asset.It
// GetOpenFuturesPosition returns an open futures position stored within
// the order manager's futures position tracker that match the provided params
func (m *OrderManager) GetOpenFuturesPosition(exch string, item asset.Item, pair currency.Pair) (*order.Position, error) {
func (m *OrderManager) GetOpenFuturesPosition(exch string, item asset.Item, pair currency.Pair) (*futures.Position, error) {
if m == nil {
return nil, fmt.Errorf("order manager %w", ErrNilSubsystem)
}
@@ -263,7 +264,7 @@ func (m *OrderManager) GetOpenFuturesPosition(exch string, item asset.Item, pair
return nil, fmt.Errorf("order manager %w", ErrSubSystemNotStarted)
}
if !item.IsFutures() {
return nil, fmt.Errorf("%v %w", item, order.ErrNotFuturesAsset)
return nil, fmt.Errorf("%v %w", item, futures.ErrNotFuturesAsset)
}
if !m.activelyTrackFuturesPositions {
return nil, errFuturesTrackingDisabled
@@ -273,7 +274,7 @@ func (m *OrderManager) GetOpenFuturesPosition(exch string, item asset.Item, pair
// GetAllOpenFuturesPositions returns all open futures positions stored within
// the order manager's futures position tracker that match the provided params
func (m *OrderManager) GetAllOpenFuturesPositions() ([]order.Position, error) {
func (m *OrderManager) GetAllOpenFuturesPositions() ([]futures.Position, error) {
if m == nil {
return nil, fmt.Errorf("order manager %w", ErrNilSubsystem)
}
@@ -296,7 +297,7 @@ func (m *OrderManager) ClearFuturesTracking(exch string, item asset.Item, pair c
return fmt.Errorf("order manager %w", ErrSubSystemNotStarted)
}
if !item.IsFutures() {
return fmt.Errorf("%v %w", item, order.ErrNotFuturesAsset)
return fmt.Errorf("%v %w", item, futures.ErrNotFuturesAsset)
}
return m.orderStore.futuresPositionController.ClearPositionsForExchange(exch, item, pair)
@@ -313,7 +314,7 @@ func (m *OrderManager) UpdateOpenPositionUnrealisedPNL(e string, item asset.Item
return decimal.Zero, fmt.Errorf("order manager %w", ErrSubSystemNotStarted)
}
if !item.IsFutures() {
return decimal.Zero, fmt.Errorf("%v %w", item, order.ErrNotFuturesAsset)
return decimal.Zero, fmt.Errorf("%v %w", item, futures.ErrNotFuturesAsset)
}
return m.orderStore.futuresPositionController.UpdateOpenPositionUnrealisedPNL(e, item, pair, last, updated)
@@ -711,9 +712,10 @@ func (m *OrderManager) processOrders() {
wg.Add(1)
go m.processMatchingOrders(exchanges[x], orders, &wg)
}
supportedFeatures := exchanges[x].GetSupportedFeatures()
if m.activelyTrackFuturesPositions && enabledAssets[y].IsFutures() && supportedFeatures.FuturesCapabilities.OrderManagerPositionTracking {
var positions []order.PositionResponse
var positions []futures.PositionResponse
var sd time.Time
sd, err = m.orderStore.futuresPositionController.LastUpdated()
if err != nil {
@@ -723,7 +725,7 @@ func (m *OrderManager) processOrders() {
if sd.IsZero() {
sd = time.Now().Add(m.futuresPositionSeekDuration)
}
positions, err = exchanges[x].GetFuturesPositionOrders(context.TODO(), &order.PositionsRequest{
positions, err = exchanges[x].GetFuturesPositionOrders(context.TODO(), &futures.PositionsRequest{
Asset: enabledAssets[y],
Pairs: pairs,
StartDate: sd,
@@ -754,7 +756,7 @@ func (m *OrderManager) processOrders() {
}
// processFuturesPositions ensures any open position found is kept up to date in the order manager
func (m *OrderManager) processFuturesPositions(exch exchange.IBotExchange, position *order.PositionResponse) error {
func (m *OrderManager) processFuturesPositions(exch exchange.IBotExchange, position *futures.PositionResponse) error {
if !m.activelyTrackFuturesPositions {
return errFuturesTrackingDisabled
}
@@ -780,7 +782,7 @@ func (m *OrderManager) processFuturesPositions(exch exchange.IBotExchange, posit
}
_, err = m.orderStore.futuresPositionController.GetOpenPosition(exch.GetName(), position.Asset, position.Pair)
if err != nil {
if errors.Is(err, order.ErrPositionNotFound) {
if errors.Is(err, futures.ErrPositionNotFound) {
return nil
}
return err
@@ -986,7 +988,7 @@ func (s *store) updateExisting(od *order.Detail) error {
return nil
}
err = s.futuresPositionController.TrackNewOrder(r[x])
if err != nil && !errors.Is(err, order.ErrPositionClosed) {
if err != nil && !errors.Is(err, futures.ErrPositionClosed) {
return err
}
return nil
@@ -1012,7 +1014,7 @@ func (s *store) modifyExisting(id string, mod *order.ModifyResponse) error {
return nil
}
err := s.futuresPositionController.TrackNewOrder(r[x])
if err != nil && !errors.Is(err, order.ErrPositionClosed) {
if err != nil && !errors.Is(err, futures.ErrPositionClosed) {
return err
}
return nil
@@ -1035,7 +1037,7 @@ func (s *store) upsert(od *order.Detail) (*OrderUpsertResponse, error) {
defer s.m.Unlock()
if od.AssetType.IsFutures() {
err = s.futuresPositionController.TrackNewOrder(od)
if err != nil && !errors.Is(err, order.ErrPositionClosed) {
if err != nil && !errors.Is(err, futures.ErrPositionClosed) {
return nil, err
}
}

View File

@@ -16,6 +16,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/futures"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
@@ -120,17 +121,18 @@ func (f omfExchange) ModifyOrder(_ context.Context, action *order.Modify) (*orde
return modResp, nil
}
func (f omfExchange) GetFuturesPositionOrders(_ context.Context, req *order.PositionsRequest) ([]order.PositionResponse, error) {
func (f omfExchange) GetFuturesPositions(_ context.Context, req *futures.PositionsRequest) ([]futures.PositionDetails, error) {
id, err := uuid.NewV4()
if err != nil {
return nil, err
}
resp := make([]order.PositionResponse, len(req.Pairs))
resp := make([]futures.PositionDetails, len(req.Pairs))
tt := time.Now()
for i := range req.Pairs {
resp[i] = order.PositionResponse{
Asset: req.Asset,
Pair: req.Pairs[i],
resp[i] = futures.PositionDetails{
Exchange: f.GetName(),
Asset: req.Asset,
Pair: req.Pairs[i],
Orders: []order.Detail{
{
Exchange: f.GetName(),
@@ -857,7 +859,7 @@ func TestProcessOrders(t *testing.T) {
}
}
m.orderStore.futuresPositionController = order.SetupPositionController()
m.orderStore.futuresPositionController = futures.SetupPositionController()
if err = m.orderStore.add(&order.Detail{
Exchange: testExchange,
Pair: pairs[0],
@@ -1149,15 +1151,15 @@ func TestGetFuturesPositionsForExchange(t *testing.T) {
t.Errorf("received '%v', expected '%v'", err, ErrSubSystemNotStarted)
}
o.started = 1
o.orderStore.futuresPositionController = order.SetupPositionController()
o.orderStore.futuresPositionController = futures.SetupPositionController()
_, err = o.GetFuturesPositionsForExchange("test", asset.Spot, cp)
if !errors.Is(err, order.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, order.ErrNotFuturesAsset)
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrNotFuturesAsset)
}
_, err = o.GetFuturesPositionsForExchange("test", asset.Futures, cp)
if !errors.Is(err, order.ErrPositionNotFound) {
t.Errorf("received '%v', expected '%v'", err, order.ErrPositionNotFound)
if !errors.Is(err, futures.ErrPositionNotFound) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrPositionNotFound)
}
err = o.orderStore.futuresPositionController.TrackNewOrder(&order.Detail{
@@ -1196,15 +1198,15 @@ func TestClearFuturesPositionsForExchange(t *testing.T) {
t.Errorf("received '%v', expected '%v'", err, ErrSubSystemNotStarted)
}
o.started = 1
o.orderStore.futuresPositionController = order.SetupPositionController()
o.orderStore.futuresPositionController = futures.SetupPositionController()
err = o.ClearFuturesTracking("test", asset.Spot, cp)
if !errors.Is(err, order.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, order.ErrNotFuturesAsset)
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrNotFuturesAsset)
}
err = o.ClearFuturesTracking("test", asset.Futures, cp)
if !errors.Is(err, order.ErrPositionNotFound) {
t.Errorf("received '%v', expected '%v'", err, order.ErrPositionNotFound)
if !errors.Is(err, futures.ErrPositionNotFound) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrPositionNotFound)
}
err = o.orderStore.futuresPositionController.TrackNewOrder(&order.Detail{
@@ -1247,15 +1249,15 @@ func TestUpdateOpenPositionUnrealisedPNL(t *testing.T) {
t.Errorf("received '%v', expected '%v'", err, ErrSubSystemNotStarted)
}
o.started = 1
o.orderStore.futuresPositionController = order.SetupPositionController()
o.orderStore.futuresPositionController = futures.SetupPositionController()
_, err = o.UpdateOpenPositionUnrealisedPNL("test", asset.Spot, cp, 1, time.Now())
if !errors.Is(err, order.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, order.ErrNotFuturesAsset)
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrNotFuturesAsset)
}
_, err = o.UpdateOpenPositionUnrealisedPNL("test", asset.Futures, cp, 1, time.Now())
if !errors.Is(err, order.ErrPositionNotFound) {
t.Errorf("received '%v', expected '%v'", err, order.ErrPositionNotFound)
if !errors.Is(err, futures.ErrPositionNotFound) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrPositionNotFound)
}
err = o.orderStore.futuresPositionController.TrackNewOrder(&order.Detail{
@@ -1386,7 +1388,7 @@ func TestUpdateExisting(t *testing.T) {
s.Orders[strings.ToLower(testExchange)] = []*order.Detail{
od,
}
s.futuresPositionController = order.SetupPositionController()
s.futuresPositionController = futures.SetupPositionController()
err = s.futuresPositionController.TrackNewOrder(od)
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
@@ -1456,10 +1458,10 @@ func TestGetAllOpenFuturesPositions(t *testing.T) {
o.started = 1
o.activelyTrackFuturesPositions = true
o.orderStore.futuresPositionController = order.SetupPositionController()
o.orderStore.futuresPositionController = futures.SetupPositionController()
_, err = o.GetAllOpenFuturesPositions()
if !errors.Is(err, order.ErrNoPositionsFound) {
t.Errorf("received '%v', expected '%v'", err, order.ErrNoPositionsFound)
if !errors.Is(err, futures.ErrNoPositionsFound) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrNoPositionsFound)
}
o = nil
@@ -1485,8 +1487,8 @@ func TestGetOpenFuturesPosition(t *testing.T) {
o.started = 1
_, err = o.GetOpenFuturesPosition(testExchange, asset.Spot, cp)
if !errors.Is(err, order.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, order.ErrNotFuturesAsset)
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrNotFuturesAsset)
}
em := NewExchangeManager()
@@ -1532,13 +1534,13 @@ func TestGetOpenFuturesPosition(t *testing.T) {
o.started = 1
_, err = o.GetOpenFuturesPosition(testExchange, asset.Spot, cp)
if !errors.Is(err, order.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, order.ErrNotFuturesAsset)
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrNotFuturesAsset)
}
_, err = o.GetOpenFuturesPosition(testExchange, asset.Futures, cp)
if !errors.Is(err, order.ErrPositionNotFound) {
t.Errorf("received '%v', expected '%v'", err, order.ErrPositionNotFound)
if !errors.Is(err, futures.ErrPositionNotFound) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrPositionNotFound)
}
err = o.orderStore.futuresPositionController.TrackNewOrder(&order.Detail{
@@ -1626,7 +1628,7 @@ func TestProcessFuturesPositions(t *testing.T) {
t.Errorf("received '%v', expected '%v'", err, common.ErrNilPointer)
}
position := &order.PositionResponse{
position := &futures.PositionResponse{
Asset: asset.Spot,
Pair: cp,
Orders: nil,
@@ -1650,8 +1652,8 @@ func TestProcessFuturesPositions(t *testing.T) {
*od,
}
err = o.processFuturesPositions(fakeExchange, position)
if !errors.Is(err, order.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, order.ErrNotFuturesAsset)
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrNotFuturesAsset)
}
position.Orders[0].AssetType = asset.Futures

View File

@@ -6,6 +6,7 @@ import (
"time"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchanges/futures"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
)
@@ -58,7 +59,7 @@ type store struct {
commsManager iCommsManager
exchangeManager iExchangeManager
wg *sync.WaitGroup
futuresPositionController order.PositionController
futuresPositionController futures.PositionController
}
// OrderSubmitResponse contains the order response along with an internal order ID

View File

@@ -36,6 +36,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/collateral"
"github.com/thrasher-corp/gocryptotrader/exchanges/fundingrate"
"github.com/thrasher-corp/gocryptotrader/exchanges/futures"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/margin"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
@@ -958,21 +959,21 @@ func (s *RPCServer) GetOrders(ctx context.Context, r *gctrpc.GetOrdersRequest) (
return nil, err
}
request := &order.MultiOrderRequest{
req := &order.MultiOrderRequest{
Pairs: []currency.Pair{cp},
AssetType: a,
Type: order.AnyType,
Side: order.AnySide,
}
if !start.IsZero() {
request.StartTime = start
req.StartTime = start
}
if !end.IsZero() {
request.EndTime = end
req.EndTime = end
}
var resp []order.Detail
resp, err = exch.GetActiveOrders(ctx, request)
resp, err = exch.GetActiveOrders(ctx, req)
if err != nil {
return nil, err
}
@@ -1474,11 +1475,11 @@ func (s *RPCServer) CancelBatchOrders(ctx context.Context, r *gctrpc.CancelBatch
status := make(map[string]string)
orders := strings.Split(r.OrdersId, ",")
request := make([]order.Cancel, len(orders))
req := make([]order.Cancel, len(orders))
for x := range orders {
orderID := orders[x]
status[orderID] = order.Cancelled.String()
request[x] = order.Cancel{
req[x] = order.Cancel{
AccountID: r.AccountId,
OrderID: orderID,
Side: side,
@@ -1489,7 +1490,7 @@ func (s *RPCServer) CancelBatchOrders(ctx context.Context, r *gctrpc.CancelBatch
}
// TODO: Change to order manager
_, err = exch.CancelBatchOrders(ctx, request)
_, err = exch.CancelBatchOrders(ctx, req)
if err != nil {
return nil, err
}
@@ -1704,7 +1705,7 @@ func (s *RPCServer) WithdrawCryptocurrencyFunds(ctx context.Context, r *gctrpc.W
return nil, err
}
request := &withdraw.Request{
req := &withdraw.Request{
Exchange: r.Exchange,
Amount: r.Amount,
Currency: currency.NewCode(strings.ToUpper(r.Currency)),
@@ -1733,7 +1734,7 @@ func (s *RPCServer) WithdrawCryptocurrencyFunds(ctx context.Context, r *gctrpc.W
if errOTP != nil {
return nil, errOTP
}
request.OneTimePassword = codeNum
req.OneTimePassword = codeNum
}
if exchCfg.API.Credentials.PIN != "" {
@@ -1741,12 +1742,12 @@ func (s *RPCServer) WithdrawCryptocurrencyFunds(ctx context.Context, r *gctrpc.W
if err != nil {
return nil, errPin
}
request.PIN = pinCode
req.PIN = pinCode
}
request.TradePassword = exchCfg.API.Credentials.TradePassword
req.TradePassword = exchCfg.API.Credentials.TradePassword
resp, err := s.Engine.WithdrawManager.SubmitWithdrawal(ctx, request)
resp, err := s.Engine.WithdrawManager.SubmitWithdrawal(ctx, req)
if err != nil {
return nil, err
}
@@ -1777,7 +1778,7 @@ func (s *RPCServer) WithdrawFiatFunds(ctx context.Context, r *gctrpc.WithdrawFia
}
}
request := &withdraw.Request{
req := &withdraw.Request{
Exchange: r.Exchange,
Amount: r.Amount,
Currency: currency.NewCode(strings.ToUpper(r.Currency)),
@@ -1803,7 +1804,7 @@ func (s *RPCServer) WithdrawFiatFunds(ctx context.Context, r *gctrpc.WithdrawFia
if err != nil {
return nil, errOTP
}
request.OneTimePassword = codeNum
req.OneTimePassword = codeNum
}
if exchCfg.API.Credentials.PIN != "" {
@@ -1811,12 +1812,12 @@ func (s *RPCServer) WithdrawFiatFunds(ctx context.Context, r *gctrpc.WithdrawFia
if err != nil {
return nil, errPIN
}
request.PIN = pinCode
req.PIN = pinCode
}
request.TradePassword = exchCfg.API.Credentials.TradePassword
req.TradePassword = exchCfg.API.Credentials.TradePassword
resp, err := s.Engine.WithdrawManager.SubmitWithdrawal(ctx, request)
resp, err := s.Engine.WithdrawManager.SubmitWithdrawal(ctx, req)
if err != nil {
return nil, err
}
@@ -4222,7 +4223,7 @@ func (s *RPCServer) CurrencyStateTradingPair(_ context.Context, r *gctrpc.Curren
ai)
}
func (s *RPCServer) buildFuturePosition(position *order.Position, getFundingPayments, includeFundingRates, includeOrders, includePredictedRate bool) *gctrpc.FuturePosition {
func (s *RPCServer) buildFuturePosition(position *futures.Position, getFundingPayments, includeFundingRates, includeOrders, includePredictedRate bool) *gctrpc.FuturePosition {
response := &gctrpc.FuturePosition{
Exchange: position.Exchange,
Asset: position.Asset.String(),
@@ -4312,7 +4313,7 @@ func (s *RPCServer) GetManagedPosition(_ context.Context, r *gctrpc.GetManagedPo
if r == nil {
return nil, fmt.Errorf("%w GetManagedPositionRequest", common.ErrNilPointer)
}
if err := order.CheckFundingRatePrerequisites(r.GetFundingPayments, r.IncludePredictedRate, r.GetFundingPayments); err != nil {
if err := futures.CheckFundingRatePrerequisites(r.GetFundingPayments, r.IncludePredictedRate, r.GetFundingPayments); err != nil {
return nil, err
}
if r.Pair == nil {
@@ -4340,7 +4341,7 @@ func (s *RPCServer) GetManagedPosition(_ context.Context, r *gctrpc.GetManagedPo
return nil, err
}
if !ai.IsFutures() {
return nil, fmt.Errorf("%w '%v'", order.ErrNotFuturesAsset, ai)
return nil, fmt.Errorf("%w '%v'", futures.ErrNotFuturesAsset, ai)
}
cp, err = currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote)
if err != nil {
@@ -4365,7 +4366,7 @@ func (s *RPCServer) GetAllManagedPositions(_ context.Context, r *gctrpc.GetAllMa
if r == nil {
return nil, fmt.Errorf("%w GetAllManagedPositionsRequest", common.ErrNilPointer)
}
if err := order.CheckFundingRatePrerequisites(r.GetFundingPayments, r.IncludePredictedRate, r.GetFundingPayments); err != nil {
if err := futures.CheckFundingRatePrerequisites(r.GetFundingPayments, r.IncludePredictedRate, r.GetFundingPayments); err != nil {
return nil, err
}
positions, err := s.OrderManager.GetAllOpenFuturesPositions()
@@ -4407,7 +4408,7 @@ func (s *RPCServer) GetFuturesPositionsSummary(ctx context.Context, r *gctrpc.Ge
return nil, err
}
if !ai.IsFutures() {
return nil, fmt.Errorf("%s %w", ai, order.ErrNotFuturesAsset)
return nil, fmt.Errorf("%s %w", ai, futures.ErrNotFuturesAsset)
}
enabledPairs, err := exch.GetEnabledPairs(ai)
if err != nil {
@@ -4426,8 +4427,8 @@ func (s *RPCServer) GetFuturesPositionsSummary(ctx context.Context, r *gctrpc.Ge
}
}
var stats *order.PositionSummary
stats, err = exch.GetFuturesPositionSummary(ctx, &order.PositionSummaryRequest{
var stats *futures.PositionSummary
stats, err = exch.GetFuturesPositionSummary(ctx, &futures.PositionSummaryRequest{
Asset: ai,
Pair: cp,
UnderlyingPair: underlying,
@@ -4452,6 +4453,12 @@ func (s *RPCServer) GetFuturesPositionsSummary(ctx context.Context, r *gctrpc.Ge
if !stats.CurrentSize.IsZero() {
positionStats.CurrentSize = stats.CurrentSize.String()
}
if !stats.ContractMultiplier.IsZero() {
positionStats.ContractMultiplier = stats.ContractMultiplier.String()
}
if !stats.ContractSize.IsZero() {
positionStats.ContractSize = stats.ContractSize.String()
}
if !stats.AverageOpenPrice.IsZero() {
positionStats.AverageOpenPrice = stats.AverageOpenPrice.String()
}
@@ -4491,6 +4498,9 @@ func (s *RPCServer) GetFuturesPositionsSummary(ctx context.Context, r *gctrpc.Ge
if !stats.IsolatedEquity.IsZero() {
positionStats.IsolatedEquity = stats.IsolatedEquity.String()
}
if stats.ContractSettlementType != futures.UnsetSettlementType {
positionStats.ContractSettlementType = stats.ContractSettlementType.String()
}
if !stats.IsolatedLiabilities.IsZero() {
positionStats.IsolatedLiabilities = stats.IsolatedLiabilities.String()
}
@@ -4545,7 +4555,7 @@ func (s *RPCServer) GetFuturesPositionsOrders(ctx context.Context, r *gctrpc.Get
return nil, err
}
if !ai.IsFutures() {
return nil, fmt.Errorf("%s %w", ai, order.ErrNotFuturesAsset)
return nil, fmt.Errorf("%s %w", ai, futures.ErrNotFuturesAsset)
}
enabledPairs, err := exch.GetEnabledPairs(ai)
if err != nil {
@@ -4573,7 +4583,7 @@ func (s *RPCServer) GetFuturesPositionsOrders(ctx context.Context, r *gctrpc.Get
return nil, err
}
positionDetails, err := exch.GetFuturesPositionOrders(ctx, &order.PositionsRequest{
positionDetails, err := exch.GetFuturesPositionOrders(ctx, &futures.PositionsRequest{
Asset: ai,
Pairs: currency.Pairs{cp},
StartDate: start,
@@ -4595,27 +4605,29 @@ func (s *RPCServer) GetFuturesPositionsOrders(ctx context.Context, r *gctrpc.Get
Base: positionDetails[i].Pair.Base.String(),
Quote: positionDetails[i].Pair.Quote.String(),
},
Orders: make([]*gctrpc.OrderDetails, len(positionDetails[i].Orders)),
ContractSettlementType: positionDetails[i].ContractSettlementType.String(),
Orders: make([]*gctrpc.OrderDetails, len(positionDetails[i].Orders)),
}
for j := range positionDetails[i].Orders {
anyOrders = true
details.Orders[j] = &gctrpc.OrderDetails{
Exchange: exch.GetName(),
Id: positionDetails[i].Orders[j].OrderID,
ClientOrderId: positionDetails[i].Orders[j].ClientOrderID,
BaseCurrency: positionDetails[i].Orders[j].Pair.Base.String(),
QuoteCurrency: positionDetails[i].Orders[j].Pair.Quote.String(),
AssetType: positionDetails[i].Orders[j].AssetType.String(),
OrderSide: positionDetails[i].Orders[j].Side.String(),
OrderType: positionDetails[i].Orders[j].Type.String(),
CreationTime: positionDetails[i].Orders[j].Date.Format(common.SimpleTimeFormatWithTimezone),
UpdateTime: positionDetails[i].Orders[j].LastUpdated.Format(common.SimpleTimeFormatWithTimezone),
Status: positionDetails[i].Orders[j].Status.String(),
Price: positionDetails[i].Orders[j].Price,
Amount: positionDetails[i].Orders[j].Amount,
OpenVolume: positionDetails[i].Orders[j].RemainingAmount,
Fee: positionDetails[i].Orders[j].Fee,
Cost: positionDetails[i].Orders[j].Cost,
Exchange: exch.GetName(),
Id: positionDetails[i].Orders[j].OrderID,
ClientOrderId: positionDetails[i].Orders[j].ClientOrderID,
BaseCurrency: positionDetails[i].Orders[j].Pair.Base.String(),
QuoteCurrency: positionDetails[i].Orders[j].Pair.Quote.String(),
AssetType: positionDetails[i].Orders[j].AssetType.String(),
OrderSide: positionDetails[i].Orders[j].Side.String(),
OrderType: positionDetails[i].Orders[j].Type.String(),
CreationTime: positionDetails[i].Orders[j].Date.Format(common.SimpleTimeFormatWithTimezone),
UpdateTime: positionDetails[i].Orders[j].LastUpdated.Format(common.SimpleTimeFormatWithTimezone),
Status: positionDetails[i].Orders[j].Status.String(),
Price: positionDetails[i].Orders[j].Price,
Amount: positionDetails[i].Orders[j].Amount,
OpenVolume: positionDetails[i].Orders[j].RemainingAmount,
Fee: positionDetails[i].Orders[j].Fee,
Cost: positionDetails[i].Orders[j].Cost,
ContractAmount: positionDetails[i].Orders[j].ContractAmount,
}
}
positions[i] = details
@@ -4653,7 +4665,7 @@ func (s *RPCServer) GetFundingRates(ctx context.Context, r *gctrpc.GetFundingRat
return nil, err
}
if !a.IsFutures() {
return nil, fmt.Errorf("%s %w", a, order.ErrNotFuturesAsset)
return nil, fmt.Errorf("%s %w", a, futures.ErrNotFuturesAsset)
}
start := time.Now().AddDate(0, -1, 0)
end := time.Now()
@@ -4764,7 +4776,7 @@ func (s *RPCServer) GetLatestFundingRate(ctx context.Context, r *gctrpc.GetLates
return nil, err
}
if !a.IsFutures() {
return nil, fmt.Errorf("%s %w", a, order.ErrNotFuturesAsset)
return nil, fmt.Errorf("%s %w", a, futures.ErrNotFuturesAsset)
}
pairs, err := exch.GetEnabledPairs(a)
@@ -4833,7 +4845,7 @@ func (s *RPCServer) GetCollateral(ctx context.Context, r *gctrpc.GetCollateralRe
return nil, err
}
if !a.IsFutures() {
return nil, fmt.Errorf("%s %w", a, order.ErrNotFuturesAsset)
return nil, fmt.Errorf("%s %w", a, futures.ErrNotFuturesAsset)
}
ai, err := exch.FetchAccountInfo(ctx, a)
if err != nil {
@@ -4872,11 +4884,11 @@ func (s *RPCServer) GetCollateral(ctx context.Context, r *gctrpc.GetCollateralRe
}
}
calculators := make([]order.CollateralCalculator, 0, len(acc.Currencies))
calculators := make([]futures.CollateralCalculator, 0, len(acc.Currencies))
for i := range acc.Currencies {
total := decimal.NewFromFloat(acc.Currencies[i].Total)
free := decimal.NewFromFloat(acc.Currencies[i].AvailableWithoutBorrow)
cal := order.CollateralCalculator{
cal := futures.CollateralCalculator{
CalculateOffline: r.CalculateOffline,
CollateralCurrency: acc.Currencies[i].Currency,
Asset: a,
@@ -4904,7 +4916,7 @@ func (s *RPCServer) GetCollateral(ctx context.Context, r *gctrpc.GetCollateralRe
calculators = append(calculators, cal)
}
calc := &order.TotalCollateralCalculator{
calc := &futures.TotalCollateralCalculator{
CollateralAssets: calculators,
CalculateOffline: r.CalculateOffline,
FetchPositions: true,

View File

@@ -31,6 +31,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/collateral"
"github.com/thrasher-corp/gocryptotrader/exchanges/currencystate"
"github.com/thrasher-corp/gocryptotrader/exchanges/fundingrate"
"github.com/thrasher-corp/gocryptotrader/exchanges/futures"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/margin"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
@@ -59,9 +60,9 @@ type fExchange struct {
exchange.IBotExchange
}
func (f fExchange) GetFuturesPositionSummary(context.Context, *order.PositionSummaryRequest) (*order.PositionSummary, error) {
func (f fExchange) GetFuturesPositionSummary(context.Context, *futures.PositionSummaryRequest) (*futures.PositionSummary, error) {
leet := decimal.NewFromInt(1337)
return &order.PositionSummary{
return &futures.PositionSummary{
MaintenanceMarginRequirement: leet,
InitialMarginRequirement: leet,
EstimatedLiquidationPrice: leet,
@@ -106,15 +107,15 @@ func (f fExchange) GetCollateralMode(_ context.Context, _ asset.Item) (collatera
return collateral.SingleMode, nil
}
func (f fExchange) GetFuturesPositionOrders(_ context.Context, req *order.PositionsRequest) ([]order.PositionResponse, error) {
func (f fExchange) GetFuturesPositionOrders(_ context.Context, req *futures.PositionsRequest) ([]futures.PositionResponse, error) {
id, err := uuid.NewV4()
if err != nil {
return nil, err
}
resp := make([]order.PositionResponse, len(req.Pairs))
resp := make([]futures.PositionResponse, len(req.Pairs))
tt := time.Now()
for i := range req.Pairs {
resp[i] = order.PositionResponse{
resp[i] = futures.PositionResponse{
Asset: req.Asset,
Pair: req.Pairs[i],
Orders: []order.Detail{
@@ -312,8 +313,8 @@ func (f fExchange) FetchAccountInfo(_ context.Context, a asset.Item) (account.Ho
}
// CalculateTotalCollateral overrides testExchange's CalculateTotalCollateral function
func (f fExchange) CalculateTotalCollateral(context.Context, *order.TotalCollateralCalculator) (*order.TotalCollateralResponse, error) {
return &order.TotalCollateralResponse{
func (f fExchange) CalculateTotalCollateral(context.Context, *futures.TotalCollateralCalculator) (*futures.TotalCollateralResponse, error) {
return &futures.TotalCollateralResponse{
CollateralCurrency: currency.USD,
AvailableMaintenanceCollateral: decimal.NewFromInt(1338),
AvailableCollateral: decimal.NewFromInt(1337),
@@ -2364,8 +2365,8 @@ func TestGetFuturesPositionsOrders(t *testing.T) {
Quote: cp.Quote.String(),
},
})
if !errors.Is(err, order.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, order.ErrNotFuturesAsset)
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrNotFuturesAsset)
}
}
@@ -2457,8 +2458,8 @@ func TestGetCollateral(t *testing.T) {
Asset: asset.Spot.String(),
IncludeBreakdown: true,
})
if !errors.Is(err, order.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, order.ErrNotFuturesAsset)
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrNotFuturesAsset)
}
_, err = s.GetCollateral(ctx, &gctrpc.GetCollateralRequest{
@@ -2990,8 +2991,8 @@ func TestGetFundingRates(t *testing.T) {
request.Asset = asset.Spot.String()
_, err = s.GetFundingRates(context.Background(), request)
if !errors.Is(err, order.ErrNotFuturesAsset) {
t.Errorf("received: '%v' but expected: '%v'", err, order.ErrNotFuturesAsset)
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Errorf("received: '%v' but expected: '%v'", err, futures.ErrNotFuturesAsset)
}
request.Asset = asset.Futures.String()
@@ -3087,8 +3088,8 @@ func TestGetLatestFundingRate(t *testing.T) {
request.Asset = asset.Spot.String()
_, err = s.GetLatestFundingRate(context.Background(), request)
if !errors.Is(err, order.ErrNotFuturesAsset) {
t.Errorf("received: '%v' but expected: '%v'", err, order.ErrNotFuturesAsset)
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Errorf("received: '%v' but expected: '%v'", err, futures.ErrNotFuturesAsset)
}
request.Asset = asset.Futures.String()
@@ -3193,8 +3194,8 @@ func TestGetManagedPosition(t *testing.T) {
request.Asset = asset.Spot.String()
_, err = s.GetManagedPosition(context.Background(), request)
if !errors.Is(err, order.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, order.ErrNotFuturesAsset)
if !errors.Is(err, futures.ErrNotFuturesAsset) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrNotFuturesAsset)
}
request.Asset = asset.Futures.String()
@@ -3205,8 +3206,8 @@ func TestGetManagedPosition(t *testing.T) {
s.OrderManager.started = 1
s.OrderManager.activelyTrackFuturesPositions = true
_, err = s.GetManagedPosition(context.Background(), request)
if !errors.Is(err, order.ErrPositionNotFound) {
t.Errorf("received '%v', expected '%v'", err, order.ErrPositionNotFound)
if !errors.Is(err, futures.ErrPositionNotFound) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrPositionNotFound)
}
err = s.OrderManager.orderStore.futuresPositionController.TrackNewOrder(&order.Detail{
@@ -3318,8 +3319,8 @@ func TestGetAllManagedPositions(t *testing.T) {
}
s.OrderManager.started = 1
_, err = s.GetAllManagedPositions(context.Background(), request)
if !errors.Is(err, order.ErrNoPositionsFound) {
t.Errorf("received '%v', expected '%v'", err, order.ErrNoPositionsFound)
if !errors.Is(err, futures.ErrNoPositionsFound) {
t.Errorf("received '%v', expected '%v'", err, futures.ErrNoPositionsFound)
}
err = s.OrderManager.orderStore.futuresPositionController.TrackNewOrder(&order.Detail{