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

@@ -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,