mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
Gateio: Implement GetHistoricalFundingRates wrapper func (#1385)
* adds funding rate implementations and improvements * merge fixes x1 * lint * kucoin funding rates func make * migrate sync-manager to keys * some kucoin work * adds some kucoin wrapper funcs * ehhh, todo * kucoin position * start of orders * adds the kucoin tests yay * multiplier * nits, EWS includes order limits * NotYetImplemented, IsPerp improvements, cleaning * lint, test fix, huobi time * fixes issues, improves testing * fixes linters I WRECKED * local lint but remote lint, lint, lint, lint * fixes err * skip CI * lint * Supported rates, binance endpoints * fixes weird mocktest problems * no, CZ is invalid * fixes some new EWS test errors * gateio: Add func GetHistoricalFundingRates * glorious: nits * rm: print call * glorious: nits fix test --------- Co-authored-by: Scott <scott.grant@thrasher.io> Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io>
This commit is contained in:
@@ -9,8 +9,14 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
)
|
||||
|
||||
// ErrFundingRateOutsideLimits is returned when a funding rate is outside the allowed date range
|
||||
var ErrFundingRateOutsideLimits = errors.New("funding rate outside limits")
|
||||
var (
|
||||
// ErrFundingRateOutsideLimits is returned when a funding rate is outside the allowed date range
|
||||
ErrFundingRateOutsideLimits = errors.New("funding rate outside limits")
|
||||
// ErrPaymentCurrencyCannotBeEmpty is returned when a payment currency is not set
|
||||
ErrPaymentCurrencyCannotBeEmpty = errors.New("payment currency cannot be empty")
|
||||
// ErrNoFundingRatesFound is returned when no funding rates are found
|
||||
ErrNoFundingRatesFound = errors.New("no funding rates found")
|
||||
)
|
||||
|
||||
// HistoricalRatesRequest is used to request funding rate details for a position
|
||||
type HistoricalRatesRequest struct {
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/core"
|
||||
@@ -3455,3 +3456,85 @@ func TestGetLatestFundingRates(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetHistoricalFundingRates(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.GetHistoricalFundingRates(context.Background(), nil)
|
||||
if !errors.Is(err, common.ErrNilPointer) {
|
||||
t.Fatalf("received: %v, expected: %v", err, common.ErrNilPointer)
|
||||
}
|
||||
|
||||
_, err = g.GetHistoricalFundingRates(context.Background(), &fundingrate.HistoricalRatesRequest{})
|
||||
if !errors.Is(err, asset.ErrNotSupported) {
|
||||
t.Fatalf("received: %v, expected: %v", err, asset.ErrNotSupported)
|
||||
}
|
||||
|
||||
_, err = g.GetHistoricalFundingRates(context.Background(), &fundingrate.HistoricalRatesRequest{
|
||||
Asset: asset.Futures,
|
||||
})
|
||||
if !errors.Is(err, currency.ErrCurrencyPairEmpty) {
|
||||
t.Fatalf("received: %v, expected: %v", err, currency.ErrCurrencyPairEmpty)
|
||||
}
|
||||
|
||||
_, err = g.GetHistoricalFundingRates(context.Background(), &fundingrate.HistoricalRatesRequest{
|
||||
Asset: asset.Futures,
|
||||
Pair: currency.NewPair(currency.ENJ, currency.USDT),
|
||||
})
|
||||
if !errors.Is(err, fundingrate.ErrPaymentCurrencyCannotBeEmpty) {
|
||||
t.Fatalf("received: %v, expected: %v", err, fundingrate.ErrPaymentCurrencyCannotBeEmpty)
|
||||
}
|
||||
|
||||
_, err = g.GetHistoricalFundingRates(context.Background(), &fundingrate.HistoricalRatesRequest{
|
||||
Asset: asset.Futures,
|
||||
Pair: currency.NewPair(currency.ENJ, currency.USDT),
|
||||
PaymentCurrency: currency.USDT,
|
||||
IncludePayments: true,
|
||||
IncludePredictedRate: true,
|
||||
})
|
||||
if !errors.Is(err, common.ErrNotYetImplemented) {
|
||||
t.Fatalf("received: %v, expected: %v", err, common.ErrNotYetImplemented)
|
||||
}
|
||||
|
||||
_, err = g.GetHistoricalFundingRates(context.Background(), &fundingrate.HistoricalRatesRequest{
|
||||
Asset: asset.Futures,
|
||||
Pair: currency.NewPair(currency.ENJ, currency.USDT),
|
||||
PaymentCurrency: currency.USDT,
|
||||
IncludePredictedRate: true,
|
||||
})
|
||||
if !errors.Is(err, common.ErrNotYetImplemented) {
|
||||
t.Fatalf("received: %v, expected: %v", err, common.ErrNotYetImplemented)
|
||||
}
|
||||
|
||||
_, err = g.GetHistoricalFundingRates(context.Background(), &fundingrate.HistoricalRatesRequest{
|
||||
Asset: asset.Futures,
|
||||
Pair: currency.NewPair(currency.ENJ, currency.USDT),
|
||||
PaymentCurrency: currency.USDT,
|
||||
StartDate: time.Now().Add(time.Hour * 16),
|
||||
EndDate: time.Now(),
|
||||
})
|
||||
if !errors.Is(err, common.ErrStartAfterEnd) {
|
||||
t.Fatalf("received: %v, expected: %v", err, common.ErrStartAfterEnd)
|
||||
}
|
||||
|
||||
_, err = g.GetHistoricalFundingRates(context.Background(), &fundingrate.HistoricalRatesRequest{
|
||||
Asset: asset.Futures,
|
||||
Pair: currency.NewPair(currency.ENJ, currency.USDT),
|
||||
PaymentCurrency: currency.USDT,
|
||||
StartDate: time.Now().Add(-time.Hour * 8008),
|
||||
EndDate: time.Now(),
|
||||
})
|
||||
if !errors.Is(err, fundingrate.ErrFundingRateOutsideLimits) {
|
||||
t.Fatalf("received: %v, expected: %v", err, fundingrate.ErrFundingRateOutsideLimits)
|
||||
}
|
||||
|
||||
history, err := g.GetHistoricalFundingRates(context.Background(), &fundingrate.HistoricalRatesRequest{
|
||||
Asset: asset.Futures,
|
||||
Pair: currency.NewPair(currency.ENJ, currency.USDT),
|
||||
PaymentCurrency: currency.USDT,
|
||||
})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: %v, expected: %v", err, nil)
|
||||
}
|
||||
|
||||
assert.NotEmpty(t, history, "should return values")
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
@@ -2168,6 +2169,88 @@ func (g *Gateio) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item) e
|
||||
return g.LoadLimits(limits)
|
||||
}
|
||||
|
||||
// GetHistoricalFundingRates returns historical funding rates for a futures contract
|
||||
func (g *Gateio) GetHistoricalFundingRates(ctx context.Context, r *fundingrate.HistoricalRatesRequest) (*fundingrate.HistoricalRates, error) {
|
||||
if r == nil {
|
||||
return nil, fmt.Errorf("%w LatestRateRequest", common.ErrNilPointer)
|
||||
}
|
||||
if r.Asset != asset.Futures {
|
||||
return nil, fmt.Errorf("%w %v", asset.ErrNotSupported, r.Asset)
|
||||
}
|
||||
|
||||
if r.Pair.IsEmpty() {
|
||||
return nil, currency.ErrCurrencyPairEmpty
|
||||
}
|
||||
|
||||
if !r.StartDate.IsZero() && !r.EndDate.IsZero() {
|
||||
err := common.StartEndTimeCheck(r.StartDate, r.EndDate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Opted to fail here as a misconfigured request will result in
|
||||
// {"label":"CONTRACT_NOT_FOUND"} and rather not mutate request using
|
||||
// quote currency as the settlement currency.
|
||||
if r.PaymentCurrency.IsEmpty() {
|
||||
return nil, fundingrate.ErrPaymentCurrencyCannotBeEmpty
|
||||
}
|
||||
|
||||
if r.IncludePayments {
|
||||
return nil, fmt.Errorf("include payments %w", common.ErrNotYetImplemented)
|
||||
}
|
||||
|
||||
if r.IncludePredictedRate {
|
||||
return nil, fmt.Errorf("include predicted rate %w", common.ErrNotYetImplemented)
|
||||
}
|
||||
|
||||
fPair, err := g.FormatExchangeCurrency(r.Pair, r.Asset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
records, err := g.GetFutureFundingRates(ctx, r.PaymentCurrency.String(), fPair, 1000)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(records) == 0 {
|
||||
return nil, fundingrate.ErrNoFundingRatesFound
|
||||
}
|
||||
|
||||
if !r.StartDate.IsZero() && !r.RespectHistoryLimits && r.StartDate.Before(records[len(records)-1].Timestamp.Time()) {
|
||||
return nil, fmt.Errorf("%w start date requested: %v last returned record: %v", fundingrate.ErrFundingRateOutsideLimits, r.StartDate, records[len(records)-1].Timestamp.Time())
|
||||
}
|
||||
|
||||
fundingRates := make([]fundingrate.Rate, 0, len(records))
|
||||
for i := range records {
|
||||
if (!r.EndDate.IsZero() && r.EndDate.Before(records[i].Timestamp.Time())) ||
|
||||
(!r.StartDate.IsZero() && r.StartDate.After(records[i].Timestamp.Time())) {
|
||||
continue
|
||||
}
|
||||
|
||||
fundingRates = append(fundingRates, fundingrate.Rate{
|
||||
Rate: decimal.NewFromFloat(records[i].Rate.Float64()),
|
||||
Time: records[i].Timestamp.Time(),
|
||||
})
|
||||
}
|
||||
|
||||
if len(fundingRates) == 0 {
|
||||
return nil, fundingrate.ErrNoFundingRatesFound
|
||||
}
|
||||
|
||||
return &fundingrate.HistoricalRates{
|
||||
Exchange: g.Name,
|
||||
Asset: r.Asset,
|
||||
Pair: r.Pair,
|
||||
FundingRates: fundingRates,
|
||||
StartDate: fundingRates[len(fundingRates)-1].Time,
|
||||
EndDate: fundingRates[0].Time,
|
||||
LatestRate: fundingRates[0],
|
||||
PaymentCurrency: r.PaymentCurrency,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetLatestFundingRates returns the latest funding rates data
|
||||
func (g *Gateio) GetLatestFundingRates(ctx context.Context, r *fundingrate.LatestRateRequest) ([]fundingrate.LatestRateResponse, error) {
|
||||
if r == nil {
|
||||
|
||||
Reference in New Issue
Block a user