mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-08 23:16:54 +00:00
exchanges: Use singular futures settlement currency (#2092)
* Change settlement to singular currency * whoops.go * bitmex fix * minor updates * 64 divided by 2 * whoops2.go * ROBOT ROCK Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * ROCK ROCK ROCK ROCK ROBOT Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * shazNit * currencies unmarshal and code use * Update currency/currencies.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/btse/btse_wrapper.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * reuse comment for better clarity * collapses entire thing * shazLint --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>
This commit is contained in:
@@ -15,7 +15,6 @@ import (
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"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/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
|
||||
@@ -642,10 +641,7 @@ func TestWsUnexpectedData(t *testing.T) {
|
||||
|
||||
func TestGetFuturesContractDetails(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := e.GetFuturesContractDetails(t.Context(), asset.Spot)
|
||||
assert.ErrorIs(t, err, futures.ErrNotFuturesAsset, "GetFuturesContractDetails should error correctly on Spot")
|
||||
|
||||
_, err = e.GetFuturesContractDetails(t.Context(), asset.USDTMarginedFutures)
|
||||
_, err := e.GetFuturesContractDetails(t.Context(), asset.Margin)
|
||||
assert.ErrorIs(t, err, asset.ErrNotSupported, "GetFuturesContractDetails should error correctly on Margin")
|
||||
|
||||
_, err = e.GetFuturesContractDetails(t.Context(), asset.Futures)
|
||||
@@ -771,18 +767,18 @@ func TestMarketPair(t *testing.T) {
|
||||
|
||||
for _, tt := range []struct {
|
||||
symbol string
|
||||
base string
|
||||
base currency.Code
|
||||
futures bool
|
||||
expectedErr error
|
||||
expectedSymbol string
|
||||
}{
|
||||
{symbol: "RUNEPFC", base: currency.RUNE.String(), futures: true, expectedSymbol: "RUNEPFC"},
|
||||
{symbol: "TRUMPPFC", base: "TRUMPSOL", futures: true, expectedSymbol: "TRUMPPFC"},
|
||||
{symbol: "BTCUSD", base: "NAUGHTYBASE", futures: true, expectedErr: errInvalidPairSymbol},
|
||||
{symbol: "NAUGHTYSYMBOL", base: currency.BTC.String(), expectedErr: errInvalidPairSymbol},
|
||||
{symbol: "BTC-USD", base: currency.BTC.String(), expectedSymbol: "BTCUSD"},
|
||||
{symbol: "RUNEPFC", base: currency.RUNE, futures: true, expectedSymbol: "RUNEPFC"},
|
||||
{symbol: "TRUMPPFC", base: currency.NewCode("TRUMPSOL"), futures: true, expectedSymbol: "TRUMPPFC"},
|
||||
{symbol: "BTCUSD", base: currency.NewCode("NAUGHTYBASE"), futures: true, expectedErr: errInvalidPairSymbol},
|
||||
{symbol: "NAUGHTYSYMBOL", base: currency.BTC, expectedErr: errInvalidPairSymbol},
|
||||
{symbol: "BTC-USD", base: currency.BTC, expectedSymbol: "BTCUSD"},
|
||||
} {
|
||||
mp := MarketPair{Symbol: tt.symbol, Base: tt.base, Quote: "USD", Futures: tt.futures}
|
||||
mp := MarketPair{Symbol: tt.symbol, Base: tt.base, Quote: currency.USD, Futures: tt.futures}
|
||||
p, err := mp.Pair()
|
||||
assert.ErrorIs(t, err, tt.expectedErr, "Pair should not error")
|
||||
assert.Equal(t, tt.expectedSymbol, p.String(), "Pair should return the expected symbol")
|
||||
|
||||
@@ -28,41 +28,41 @@ type MarketSummary []*MarketPair
|
||||
|
||||
// MarketPair is a single pair in Market Summary
|
||||
type MarketPair struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Last float64 `json:"last"`
|
||||
LowestAsk float64 `json:"lowestAsk"`
|
||||
HighestBid float64 `json:"highestBid"`
|
||||
PercentageChange float64 `json:"percentageChange"`
|
||||
Volume float64 `json:"volume"`
|
||||
High24Hr float64 `json:"high24Hr"`
|
||||
Low24Hr float64 `json:"low24Hr"`
|
||||
Base string `json:"base"`
|
||||
Quote string `json:"quote"`
|
||||
Active bool `json:"active"`
|
||||
Size float64 `json:"size"`
|
||||
MinValidPrice float64 `json:"minValidPrice"`
|
||||
MinPriceIncrement float64 `json:"minPriceIncrement"`
|
||||
MinOrderSize float64 `json:"minOrderSize"`
|
||||
MaxOrderSize float64 `json:"maxOrderSize"`
|
||||
MinSizeIncrement float64 `json:"minSizeIncrement"`
|
||||
OpenInterest float64 `json:"openInterest"`
|
||||
OpenInterestUSD float64 `json:"openInterestUSD"`
|
||||
ContractStart int64 `json:"contractStart"`
|
||||
ContractEnd int64 `json:"contractEnd"`
|
||||
TimeBasedContract bool `json:"timeBasedContract"`
|
||||
OpenTime types.Time `json:"openTime"`
|
||||
CloseTime types.Time `json:"closeTime"`
|
||||
StartMatching int64 `json:"startMatching"`
|
||||
InactiveTime types.Time `json:"inactiveTime"`
|
||||
FundingRate float64 `json:"fundingRate"`
|
||||
ContractSize float64 `json:"contractSize"`
|
||||
MaxPosition int64 `json:"maxPosition"`
|
||||
MinRiskLimit int `json:"minRiskLimit"`
|
||||
MaxRiskLimit int `json:"maxRiskLimit"`
|
||||
AvailableSettlement []string `json:"availableSettlement"`
|
||||
Futures bool `json:"futures"`
|
||||
IsMarketOpenToSpot bool `json:"isMarketOpenToSpot"`
|
||||
IsMarketOpenToOTC bool `json:"isMarketOpenToOtc"`
|
||||
Symbol string `json:"symbol"`
|
||||
Last float64 `json:"last"`
|
||||
LowestAsk float64 `json:"lowestAsk"`
|
||||
HighestBid float64 `json:"highestBid"`
|
||||
PercentageChange float64 `json:"percentageChange"`
|
||||
Volume float64 `json:"volume"`
|
||||
High24Hr float64 `json:"high24Hr"`
|
||||
Low24Hr float64 `json:"low24Hr"`
|
||||
Base currency.Code `json:"base"`
|
||||
Quote currency.Code `json:"quote"`
|
||||
Active bool `json:"active"`
|
||||
Size float64 `json:"size"`
|
||||
MinValidPrice float64 `json:"minValidPrice"`
|
||||
MinPriceIncrement float64 `json:"minPriceIncrement"`
|
||||
MinOrderSize float64 `json:"minOrderSize"`
|
||||
MaxOrderSize float64 `json:"maxOrderSize"`
|
||||
MinSizeIncrement float64 `json:"minSizeIncrement"`
|
||||
OpenInterest float64 `json:"openInterest"`
|
||||
OpenInterestUSD float64 `json:"openInterestUSD"`
|
||||
ContractStart int64 `json:"contractStart"`
|
||||
ContractEnd int64 `json:"contractEnd"`
|
||||
TimeBasedContract bool `json:"timeBasedContract"`
|
||||
OpenTime types.Time `json:"openTime"`
|
||||
CloseTime types.Time `json:"closeTime"`
|
||||
StartMatching int64 `json:"startMatching"`
|
||||
InactiveTime types.Time `json:"inactiveTime"`
|
||||
FundingRate float64 `json:"fundingRate"`
|
||||
ContractSize float64 `json:"contractSize"`
|
||||
MaxPosition int64 `json:"maxPosition"`
|
||||
MinRiskLimit int `json:"minRiskLimit"`
|
||||
MaxRiskLimit int `json:"maxRiskLimit"`
|
||||
AvailableSettlement currency.Currencies `json:"availableSettlement"`
|
||||
Futures bool `json:"futures"`
|
||||
IsMarketOpenToSpot bool `json:"isMarketOpenToSpot"`
|
||||
IsMarketOpenToOTC bool `json:"isMarketOpenToOtc"`
|
||||
}
|
||||
|
||||
// OHLCV holds Open, High Low, Close, Volume data for set symbol
|
||||
|
||||
@@ -996,27 +996,28 @@ func (m *MarketPair) StripExponent() (string, error) {
|
||||
// Pair returns the currency Pair for a MarketPair
|
||||
func (m *MarketPair) Pair() (currency.Pair, error) {
|
||||
baseCurr := m.Base
|
||||
var quoteCurr string
|
||||
var quoteStr string
|
||||
if m.Futures {
|
||||
if baseCurr == "TRUMPSOL" { // Only base currency which is different to the rest
|
||||
baseCurr = "TRUMP"
|
||||
quoteCurr = strings.TrimPrefix(m.Symbol, baseCurr)
|
||||
if baseCurr.String() == "TRUMPSOL" { // Only base currency which is different to the rest
|
||||
baseCurr = currency.TRUMP
|
||||
quoteStr = strings.TrimPrefix(m.Symbol, baseCurr.String())
|
||||
} else {
|
||||
s := strings.Split(m.Symbol, m.Base) // e.g. RUNEPFC for RUNE-USD futures pair
|
||||
// Quote field is the settlement currency, create the quote currency from the symbol
|
||||
s := strings.Split(m.Symbol, m.Base.String())
|
||||
if len(s) <= 1 {
|
||||
return currency.EMPTYPAIR, errInvalidPairSymbol
|
||||
}
|
||||
quoteCurr = s[1]
|
||||
quoteStr = s[1]
|
||||
}
|
||||
} else {
|
||||
s := strings.Split(m.Symbol, currency.DashDelimiter)
|
||||
if len(s) != 2 {
|
||||
return currency.EMPTYPAIR, errInvalidPairSymbol
|
||||
}
|
||||
baseCurr = s[0]
|
||||
quoteCurr = s[1]
|
||||
baseCurr = currency.NewCode(s[0])
|
||||
quoteStr = s[1]
|
||||
}
|
||||
return currency.NewPairFromStrings(baseCurr, quoteCurr)
|
||||
return currency.NewPair(baseCurr, currency.NewCode(quoteStr)), nil
|
||||
}
|
||||
|
||||
// GetMarketSummary returns filtered market pair details; Specifically:
|
||||
@@ -1055,9 +1056,6 @@ func (e *Exchange) GetMarketSummary(ctx context.Context, symbol string, spot boo
|
||||
|
||||
// GetFuturesContractDetails returns details about futures contracts
|
||||
func (e *Exchange) GetFuturesContractDetails(ctx context.Context, item asset.Item) ([]futures.Contract, error) {
|
||||
if !item.IsFutures() {
|
||||
return nil, futures.ErrNotFuturesAsset
|
||||
}
|
||||
if item != asset.Futures {
|
||||
return nil, fmt.Errorf("%w %v", asset.ErrNotSupported, item)
|
||||
}
|
||||
@@ -1065,67 +1063,46 @@ func (e *Exchange) GetFuturesContractDetails(ctx context.Context, item asset.Ite
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp := make([]futures.Contract, 0, len(marketSummary))
|
||||
resp := make([]futures.Contract, len(marketSummary))
|
||||
for i := range marketSummary {
|
||||
var cp currency.Pair
|
||||
cp, err = currency.NewPairFromStrings(marketSummary[i].Base, marketSummary[i].Symbol[len(marketSummary[i].Base):])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
settlementCurrencies := make(currency.Currencies, len(marketSummary[i].AvailableSettlement))
|
||||
var startTime, endTime time.Time
|
||||
var ct futures.ContractType
|
||||
if !marketSummary[i].OpenTime.Time().IsZero() {
|
||||
startTime = marketSummary[i].OpenTime.Time()
|
||||
}
|
||||
if !marketSummary[i].CloseTime.Time().IsZero() {
|
||||
endTime = marketSummary[i].CloseTime.Time()
|
||||
}
|
||||
// Quote field is the settlement currency, create the quote currency from the symbol
|
||||
quote := currency.NewCode(marketSummary[i].Symbol[len(marketSummary[i].Base.String()):])
|
||||
cp := currency.NewPair(marketSummary[i].Base, quote)
|
||||
startTime := marketSummary[i].OpenTime.Time()
|
||||
endTime := marketSummary[i].CloseTime.Time()
|
||||
ct := futures.Perpetual
|
||||
if marketSummary[i].TimeBasedContract {
|
||||
if endTime.Sub(startTime) > kline.OneMonth.Duration() {
|
||||
ct = futures.Quarterly
|
||||
} else {
|
||||
ct = futures.Monthly
|
||||
}
|
||||
} else {
|
||||
ct = futures.Perpetual
|
||||
}
|
||||
var contractSettlementType futures.ContractSettlementType
|
||||
for j := range marketSummary[i].AvailableSettlement {
|
||||
settlementCurrencies[j] = currency.NewCode(marketSummary[i].AvailableSettlement[j])
|
||||
if contractSettlementType == futures.LinearOrInverse {
|
||||
continue
|
||||
}
|
||||
containsUSD := strings.Contains(marketSummary[i].AvailableSettlement[j], "USD")
|
||||
if !containsUSD {
|
||||
contractSettlementType = futures.LinearOrInverse
|
||||
continue
|
||||
}
|
||||
if containsUSD {
|
||||
contractSettlementType = futures.Linear
|
||||
}
|
||||
}
|
||||
|
||||
c := futures.Contract{
|
||||
Exchange: e.Name,
|
||||
Name: cp,
|
||||
Underlying: currency.NewPair(currency.NewCode(marketSummary[i].Base), currency.NewCode(marketSummary[i].Quote)),
|
||||
Asset: item,
|
||||
SettlementCurrencies: settlementCurrencies,
|
||||
StartDate: startTime,
|
||||
EndDate: endTime,
|
||||
SettlementType: contractSettlementType,
|
||||
IsActive: marketSummary[i].Active,
|
||||
Type: ct,
|
||||
contractSettlementType := futures.LinearOrInverse
|
||||
if marketSummary[i].AvailableSettlement.Contains(currency.USD) {
|
||||
contractSettlementType = futures.Linear
|
||||
}
|
||||
var rate fundingrate.Rate
|
||||
if marketSummary[i].FundingRate > 0 {
|
||||
c.LatestRate = fundingrate.Rate{
|
||||
rate = fundingrate.Rate{
|
||||
Rate: decimal.NewFromFloat(marketSummary[i].FundingRate),
|
||||
Time: time.Now().Truncate(time.Hour),
|
||||
}
|
||||
}
|
||||
|
||||
resp = append(resp, c)
|
||||
resp[i] = futures.Contract{
|
||||
Exchange: e.Name,
|
||||
Name: cp,
|
||||
Underlying: currency.NewPair(marketSummary[i].Base, marketSummary[i].Quote),
|
||||
Asset: item,
|
||||
SettlementCurrency: currency.USDT,
|
||||
AdditionalSettlementCurrencies: marketSummary[i].AvailableSettlement,
|
||||
StartDate: startTime,
|
||||
EndDate: endTime,
|
||||
SettlementType: contractSettlementType,
|
||||
IsActive: marketSummary[i].Active,
|
||||
Type: ct,
|
||||
LatestRate: rate,
|
||||
}
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user