mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
GateIO: Enhance order execution limits and currency pair details (#2018)
* refactor(gateio): enhance order execution limits and currency pair details * Update exchanges/gateio/gateio_wrapper.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * REEEEEHHHHHH * linter: fix * fix GetOpenInterest when a contract is delisted * add handling for delisting end time correctly * Update exchange/order/limits/limits_types.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchange/order/limits/limits_types.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/gateio/gateio_types.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/gateio/gateio_types.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * gk: nits * gci: fix * linter: fix * gateio: Add launch and update tests (cherry-pick) * gk: nits + removed spot setting delisting as delisted because it is not a start time value * glorious: apply diff --------- Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>
This commit is contained in:
@@ -2489,11 +2489,33 @@ func TestUpdateOrderExecutionLimits(t *testing.T) {
|
||||
require.ErrorIs(t, e.UpdateOrderExecutionLimits(t.Context(), a), asset.ErrNotSupported)
|
||||
default:
|
||||
require.NoError(t, e.UpdateOrderExecutionLimits(t.Context(), a), "UpdateOrderExecutionLimits must not error")
|
||||
pairs, err := e.CurrencyPairs.GetPairs(a, true)
|
||||
require.NoError(t, err, "GetPairs must not error")
|
||||
l, err := e.GetOrderExecutionLimits(a, pairs[0])
|
||||
require.NoError(t, err, "GetOrderExecutionLimits must not error")
|
||||
assert.Positive(t, l.MinimumBaseAmount, "MinimumBaseAmount should be positive")
|
||||
avail, err := e.GetAvailablePairs(a)
|
||||
require.NoError(t, err, "GetAvailablePairs must not error")
|
||||
for _, pair := range avail {
|
||||
l, err := e.GetOrderExecutionLimits(a, pair)
|
||||
require.NoErrorf(t, err, "GetOrderExecutionLimits must not error for %s", pair)
|
||||
require.NotNilf(t, l, "GetOrderExecutionLimits %s result cannot be nil", pair)
|
||||
assert.Equalf(t, a, l.Key.Asset, "asset should equal for %s", pair)
|
||||
assert.Truef(t, pair.Equal(l.Key.Pair()), "pair should equal for %s", pair)
|
||||
assert.Positivef(t, l.MinimumBaseAmount, "MinimumBaseAmount should be positive for %s", pair)
|
||||
assert.Positivef(t, l.AmountStepIncrementSize, "AmountStepIncrementSize should be positive for %s", pair)
|
||||
|
||||
switch a {
|
||||
case asset.USDTMarginedFutures:
|
||||
assert.Positivef(t, l.MultiplierDecimal, "MultiplierDecimal should be positive for %s", pair)
|
||||
assert.NotZerof(t, l.Listed, "Listed should be populated for %s", pair)
|
||||
fallthrough
|
||||
case asset.CoinMarginedFutures:
|
||||
if !l.Delisted.IsZero() {
|
||||
assert.Truef(t, l.Delisted.After(l.Delisting), "Delisted should be after Delisting for %s", pair)
|
||||
}
|
||||
case asset.Spot:
|
||||
assert.Positivef(t, l.MinimumQuoteAmount, "MinimumQuoteAmount should be positive for %s", pair)
|
||||
assert.Positivef(t, l.QuoteStepIncrementSize, "QuoteStepIncrementSize should be positive for %s", pair)
|
||||
case asset.DeliveryFutures:
|
||||
assert.NotZerof(t, l.Expiry, "Expiry should be populated for %s", pair)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -486,17 +486,25 @@ type CurrencyInfo struct {
|
||||
|
||||
// CurrencyPairDetail represents a single currency pair detail.
|
||||
type CurrencyPairDetail struct {
|
||||
ID string `json:"id"`
|
||||
Base string `json:"base"`
|
||||
Quote string `json:"quote"`
|
||||
TradingFee types.Number `json:"fee"`
|
||||
MinBaseAmount types.Number `json:"min_base_amount"`
|
||||
MinQuoteAmount types.Number `json:"min_quote_amount"`
|
||||
AmountPrecision float64 `json:"amount_precision"` // Amount scale
|
||||
Precision float64 `json:"precision"` // Price scale
|
||||
TradeStatus string `json:"trade_status"`
|
||||
SellStart float64 `json:"sell_start"`
|
||||
BuyStart float64 `json:"buy_start"`
|
||||
ID currency.Pair `json:"id"`
|
||||
Base currency.Code `json:"base"`
|
||||
BaseName string `json:"base_name"`
|
||||
Quote currency.Code `json:"quote"`
|
||||
QuoteName string `json:"quote_name"`
|
||||
Fee types.Number `json:"fee"`
|
||||
MinBaseAmount types.Number `json:"min_base_amount"`
|
||||
MinQuoteAmount types.Number `json:"min_quote_amount"`
|
||||
MaxBaseAmount types.Number `json:"max_base_amount"`
|
||||
MaxQuoteAmount types.Number `json:"max_quote_amount"`
|
||||
AmountPrecision float64 `json:"amount_precision"`
|
||||
PricePrecision float64 `json:"precision"`
|
||||
TradeStatus string `json:"trade_status"` // e.g. "untradable", "buyable", "sellable", "tradable"
|
||||
SellStart types.Time `json:"sell_start"`
|
||||
BuyStart types.Time `json:"buy_start"`
|
||||
DelistingTime types.Time `json:"delisting_time"`
|
||||
Type string `json:"type"` // e.g. "normal", "pre-market"
|
||||
TradeURL string `json:"trade_url"`
|
||||
STTag bool `json:"st_tag"`
|
||||
}
|
||||
|
||||
// Ticker holds detail ticker information for a currency pair
|
||||
@@ -641,49 +649,52 @@ type OrderbookOfLendingLoan struct {
|
||||
|
||||
// FuturesContract represents futures contract detailed data.
|
||||
type FuturesContract struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
QuantoMultiplier types.Number `json:"quanto_multiplier"`
|
||||
RefDiscountRate types.Number `json:"ref_discount_rate"`
|
||||
OrderPriceDeviate string `json:"order_price_deviate"`
|
||||
MaintenanceRate types.Number `json:"maintenance_rate"`
|
||||
MarkType string `json:"mark_type"`
|
||||
LastPrice types.Number `json:"last_price"`
|
||||
MarkPrice types.Number `json:"mark_price"`
|
||||
IndexPrice types.Number `json:"index_price"`
|
||||
FundingRateIndicative types.Number `json:"funding_rate_indicative"`
|
||||
MarkPriceRound types.Number `json:"mark_price_round"`
|
||||
FundingOffset int64 `json:"funding_offset"`
|
||||
InDelisting bool `json:"in_delisting"`
|
||||
RiskLimitBase string `json:"risk_limit_base"`
|
||||
InterestRate string `json:"interest_rate"`
|
||||
OrderPriceRound types.Number `json:"order_price_round"`
|
||||
OrderSizeMin int64 `json:"order_size_min"`
|
||||
RefRebateRate string `json:"ref_rebate_rate"`
|
||||
FundingInterval int64 `json:"funding_interval"`
|
||||
RiskLimitStep string `json:"risk_limit_step"`
|
||||
LeverageMin types.Number `json:"leverage_min"`
|
||||
LeverageMax types.Number `json:"leverage_max"`
|
||||
RiskLimitMax string `json:"risk_limit_max"`
|
||||
MakerFeeRate types.Number `json:"maker_fee_rate"`
|
||||
TakerFeeRate types.Number `json:"taker_fee_rate"`
|
||||
FundingRate types.Number `json:"funding_rate"`
|
||||
OrderSizeMax int64 `json:"order_size_max"`
|
||||
FundingNextApply types.Time `json:"funding_next_apply"`
|
||||
ConfigChangeTime types.Time `json:"config_change_time"`
|
||||
ShortUsers int64 `json:"short_users"`
|
||||
TradeSize int64 `json:"trade_size"`
|
||||
PositionSize int64 `json:"position_size"`
|
||||
LongUsers int64 `json:"long_users"`
|
||||
FundingImpactValue string `json:"funding_impact_value"`
|
||||
OrdersLimit int64 `json:"orders_limit"`
|
||||
TradeID int64 `json:"trade_id"`
|
||||
OrderbookID int64 `json:"orderbook_id"`
|
||||
EnableBonus bool `json:"enable_bonus"`
|
||||
EnableCredit bool `json:"enable_credit"`
|
||||
CreateTime types.Time `json:"create_time"`
|
||||
FundingCapRatio types.Number `json:"funding_cap_ratio"`
|
||||
VoucherLeverage types.Number `json:"voucher_leverage"`
|
||||
Name currency.Pair `json:"name"`
|
||||
Type string `json:"type"`
|
||||
QuantoMultiplier types.Number `json:"quanto_multiplier"`
|
||||
RefDiscountRate types.Number `json:"ref_discount_rate"`
|
||||
OrderPriceDeviate types.Number `json:"order_price_deviate"`
|
||||
MaintenanceRate types.Number `json:"maintenance_rate"`
|
||||
MarkType string `json:"mark_type"`
|
||||
LastPrice types.Number `json:"last_price"`
|
||||
MarkPrice types.Number `json:"mark_price"`
|
||||
IndexPrice types.Number `json:"index_price"`
|
||||
FundingRateIndicative types.Number `json:"funding_rate_indicative"`
|
||||
MarkPriceRound types.Number `json:"mark_price_round"`
|
||||
FundingOffset types.Number `json:"funding_offset"`
|
||||
Delisting bool `json:"in_delisting"`
|
||||
RiskLimitBase types.Number `json:"risk_limit_base"`
|
||||
InterestRate types.Number `json:"interest_rate"`
|
||||
OrderPriceRound types.Number `json:"order_price_round"`
|
||||
OrderSizeMin types.Number `json:"order_size_min"`
|
||||
RefRebateRate types.Number `json:"ref_rebate_rate"`
|
||||
FundingInterval int64 `json:"funding_interval"`
|
||||
RiskLimitStep types.Number `json:"risk_limit_step"`
|
||||
LeverageMin types.Number `json:"leverage_min"`
|
||||
LeverageMax types.Number `json:"leverage_max"`
|
||||
RiskLimitMax types.Number `json:"risk_limit_max"`
|
||||
MakerFeeRate types.Number `json:"maker_fee_rate"`
|
||||
TakerFeeRate types.Number `json:"taker_fee_rate"`
|
||||
FundingRate types.Number `json:"funding_rate"`
|
||||
OrderSizeMax types.Number `json:"order_size_max"`
|
||||
FundingNextApply types.Time `json:"funding_next_apply"`
|
||||
ShortUsers types.Number `json:"short_users"`
|
||||
ConfigChangeTime types.Time `json:"config_change_time"`
|
||||
TradeSize types.Number `json:"trade_size"`
|
||||
PositionSize types.Number `json:"position_size"`
|
||||
LongUsers types.Number `json:"long_users"`
|
||||
FundingImpactValue types.Number `json:"funding_impact_value"`
|
||||
OrdersLimit types.Number `json:"orders_limit"`
|
||||
TradeID int64 `json:"trade_id"`
|
||||
OrderbookID int64 `json:"orderbook_id"`
|
||||
EnableBonus bool `json:"enable_bonus"`
|
||||
EnableCredit bool `json:"enable_credit"`
|
||||
CreateTime types.Time `json:"create_time"`
|
||||
FundingCapRatio types.Number `json:"funding_cap_ratio"`
|
||||
Status string `json:"status"`
|
||||
LaunchTime types.Time `json:"launch_time"`
|
||||
DelistingTime types.Time `json:"delisting_time"`
|
||||
DelistedTime types.Time `json:"delisted_time"`
|
||||
}
|
||||
|
||||
// TradingHistoryItem represents futures trading history item.
|
||||
|
||||
@@ -422,12 +422,7 @@ func (e *Exchange) FetchTradablePairs(ctx context.Context, a asset.Item) (curren
|
||||
if tradables[x].TradeStatus == "untradable" {
|
||||
continue
|
||||
}
|
||||
p := strings.ToUpper(tradables[x].ID)
|
||||
cp, err := currency.NewPairFromString(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pairs = append(pairs, cp)
|
||||
pairs = append(pairs, currency.NewPair(tradables[x].Base, tradables[x].Quote))
|
||||
}
|
||||
return pairs, nil
|
||||
case asset.Margin, asset.CrossMargin:
|
||||
@@ -459,15 +454,10 @@ func (e *Exchange) FetchTradablePairs(ctx context.Context, a asset.Item) (curren
|
||||
}
|
||||
pairs := make([]currency.Pair, 0, len(contracts))
|
||||
for i := range contracts {
|
||||
if contracts[i].InDelisting {
|
||||
if !contracts[i].DelistedTime.Time().IsZero() && contracts[i].DelistedTime.Time().Before(time.Now()) {
|
||||
continue
|
||||
}
|
||||
p := strings.ToUpper(contracts[i].Name)
|
||||
cp, err := currency.NewPairFromString(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pairs = append(pairs, cp)
|
||||
pairs = append(pairs, contracts[i].Name)
|
||||
}
|
||||
return slices.Clip(pairs), nil
|
||||
case asset.DeliveryFutures:
|
||||
@@ -1800,23 +1790,19 @@ func (e *Exchange) GetFuturesContractDetails(ctx context.Context, a asset.Item)
|
||||
}
|
||||
resp := make([]futures.Contract, len(contracts))
|
||||
for i := range contracts {
|
||||
name, err := currency.NewPairFromString(contracts[i].Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
contractSettlementType := futures.Linear
|
||||
switch {
|
||||
case name.Base.Equal(currency.BTC) && settle.Equal(currency.BTC):
|
||||
case contracts[i].Name.Base.Equal(currency.BTC) && settle.Equal(currency.BTC):
|
||||
contractSettlementType = futures.Inverse
|
||||
case !name.Base.Equal(settle) && !settle.Equal(currency.USDT):
|
||||
case !contracts[i].Name.Base.Equal(settle) && !settle.Equal(currency.USDT):
|
||||
contractSettlementType = futures.Quanto
|
||||
}
|
||||
c := futures.Contract{
|
||||
Exchange: e.Name,
|
||||
Name: name,
|
||||
Underlying: name,
|
||||
Name: contracts[i].Name,
|
||||
Underlying: contracts[i].Name,
|
||||
Asset: a,
|
||||
IsActive: !contracts[i].InDelisting,
|
||||
IsActive: contracts[i].DelistedTime.Time().IsZero() || contracts[i].DelistedTime.Time().After(time.Now()),
|
||||
Type: futures.Perpetual,
|
||||
SettlementType: contractSettlementType,
|
||||
SettlementCurrencies: currency.Currencies{settle},
|
||||
@@ -1904,10 +1890,6 @@ func (e *Exchange) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item)
|
||||
if pairsData[i].TradeStatus == "untradable" {
|
||||
continue
|
||||
}
|
||||
pair, err := e.MatchSymbolWithAvailablePairs(pairsData[i].ID, a, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Minimum base amounts are not always provided this will default to
|
||||
// precision for base deployment. This can't be done for quote.
|
||||
@@ -1917,77 +1899,67 @@ func (e *Exchange) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item)
|
||||
}
|
||||
|
||||
l = append(l, limits.MinMaxLevel{
|
||||
Key: key.NewExchangeAssetPair(e.Name, a, pair),
|
||||
QuoteStepIncrementSize: math.Pow10(-int(pairsData[i].Precision)),
|
||||
Key: key.NewExchangeAssetPair(e.Name, a, currency.NewPair(pairsData[i].Base, pairsData[i].Quote)),
|
||||
QuoteStepIncrementSize: math.Pow10(-int(pairsData[i].PricePrecision)),
|
||||
AmountStepIncrementSize: math.Pow10(-int(pairsData[i].AmountPrecision)),
|
||||
MinimumBaseAmount: minBaseAmount,
|
||||
MinimumQuoteAmount: pairsData[i].MinQuoteAmount.Float64(),
|
||||
Delisted: pairsData[i].DelistingTime.Time(),
|
||||
})
|
||||
}
|
||||
case asset.CoinMarginedFutures:
|
||||
btcContracts, err := e.GetAllFutureContracts(ctx, currency.BTC)
|
||||
case asset.USDTMarginedFutures, asset.CoinMarginedFutures:
|
||||
settlement := currency.USDT
|
||||
if a == asset.CoinMarginedFutures {
|
||||
settlement = currency.BTC
|
||||
}
|
||||
contractInfo, err := e.GetAllFutureContracts(ctx, settlement)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l = make([]limits.MinMaxLevel, 0, len(btcContracts))
|
||||
for x := range btcContracts {
|
||||
p := strings.ToUpper(btcContracts[x].Name)
|
||||
cp, err := currency.NewPairFromString(p)
|
||||
if err != nil {
|
||||
return err
|
||||
// MBABYDOGE price is 1e6 x spot price
|
||||
divCurrency := currency.NewCode("MBABYDOGE")
|
||||
l = make([]limits.MinMaxLevel, 0, len(contractInfo))
|
||||
for i := range contractInfo {
|
||||
priceDiv := 1.0
|
||||
if contractInfo[i].Name.Base.Equal(divCurrency) {
|
||||
priceDiv = 1e6
|
||||
}
|
||||
|
||||
l = append(l, limits.MinMaxLevel{
|
||||
Key: key.NewExchangeAssetPair(e.Name, a, cp),
|
||||
MinimumBaseAmount: float64(btcContracts[x].OrderSizeMin),
|
||||
MaximumBaseAmount: float64(btcContracts[x].OrderSizeMax),
|
||||
PriceStepIncrementSize: btcContracts[x].OrderPriceRound.Float64(),
|
||||
AmountStepIncrementSize: 1,
|
||||
})
|
||||
}
|
||||
case asset.USDTMarginedFutures:
|
||||
usdtContracts, err := e.GetAllFutureContracts(ctx, currency.USDT)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l = make([]limits.MinMaxLevel, 0, len(usdtContracts))
|
||||
for x := range usdtContracts {
|
||||
p := strings.ToUpper(usdtContracts[x].Name)
|
||||
cp, err := currency.NewPairFromString(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l = append(l, limits.MinMaxLevel{
|
||||
Key: key.NewExchangeAssetPair(e.Name, a, cp),
|
||||
MinimumBaseAmount: float64(usdtContracts[x].OrderSizeMin),
|
||||
MaximumBaseAmount: float64(usdtContracts[x].OrderSizeMax),
|
||||
PriceStepIncrementSize: usdtContracts[x].OrderPriceRound.Float64(),
|
||||
AmountStepIncrementSize: 1,
|
||||
Key: key.NewExchangeAssetPair(e.Name, a, contractInfo[i].Name),
|
||||
MinimumBaseAmount: contractInfo[i].OrderSizeMin.Float64(),
|
||||
MaximumBaseAmount: contractInfo[i].OrderSizeMax.Float64(),
|
||||
PriceStepIncrementSize: contractInfo[i].OrderPriceRound.Float64(),
|
||||
AmountStepIncrementSize: 1, // 1 Contract
|
||||
MultiplierDecimal: contractInfo[i].QuantoMultiplier.Float64(),
|
||||
PriceDivisor: priceDiv,
|
||||
Delisting: contractInfo[i].DelistingTime.Time(),
|
||||
Delisted: contractInfo[i].DelistedTime.Time(),
|
||||
Listed: contractInfo[i].LaunchTime.Time(),
|
||||
})
|
||||
}
|
||||
case asset.DeliveryFutures:
|
||||
btcContracts, err := e.GetAllDeliveryContracts(ctx, currency.BTC)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
usdtContracts, err := e.GetAllDeliveryContracts(ctx, currency.USDT)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
btcContracts = append(btcContracts, usdtContracts...)
|
||||
l = make([]limits.MinMaxLevel, 0, len(btcContracts))
|
||||
for x := range btcContracts {
|
||||
p := strings.ToUpper(btcContracts[x].Name)
|
||||
cp, err := currency.NewPairFromString(p)
|
||||
for _, settlement := range []currency.Code{currency.BTC, currency.USDT} {
|
||||
contractInfo, err := e.GetAllDeliveryContracts(ctx, settlement)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l = append(l, limits.MinMaxLevel{
|
||||
Key: key.NewExchangeAssetPair(e.Name, a, cp),
|
||||
MinimumBaseAmount: float64(btcContracts[x].OrderSizeMin),
|
||||
MaximumBaseAmount: float64(btcContracts[x].OrderSizeMax),
|
||||
PriceStepIncrementSize: btcContracts[x].OrderPriceRound.Float64(),
|
||||
AmountStepIncrementSize: 1,
|
||||
})
|
||||
l = slices.Grow(l, len(contractInfo))
|
||||
for x := range contractInfo {
|
||||
p := strings.ToUpper(contractInfo[x].Name)
|
||||
cp, err := currency.NewPairFromString(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l = append(l, limits.MinMaxLevel{
|
||||
Key: key.NewExchangeAssetPair(e.Name, a, cp),
|
||||
MinimumBaseAmount: float64(contractInfo[x].OrderSizeMin),
|
||||
MaximumBaseAmount: float64(contractInfo[x].OrderSizeMax),
|
||||
PriceStepIncrementSize: contractInfo[x].OrderPriceRound.Float64(),
|
||||
AmountStepIncrementSize: 1,
|
||||
Expiry: contractInfo[x].ExpireTime.Time(),
|
||||
})
|
||||
}
|
||||
}
|
||||
case asset.Options:
|
||||
underlyings, err := e.GetAllOptionsUnderlyings(ctx)
|
||||
@@ -2142,14 +2114,10 @@ func (e *Exchange) GetLatestFundingRates(ctx context.Context, r *fundingrate.Lat
|
||||
}
|
||||
resp := make([]fundingrate.LatestRateResponse, 0, len(contracts))
|
||||
for i := range contracts {
|
||||
cp, err := currency.NewPairFromString(contracts[i].Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !pairs.Contains(cp, false) {
|
||||
if !pairs.Contains(contracts[i].Name, true) {
|
||||
continue
|
||||
}
|
||||
resp = append(resp, contractToFundingRate(e.Name, r.Asset, cp, &contracts[i], r.IncludePredictedRate))
|
||||
resp = append(resp, contractToFundingRate(e.Name, r.Asset, contracts[i].Name, &contracts[i], r.IncludePredictedRate))
|
||||
}
|
||||
|
||||
return slices.Clip(resp), nil
|
||||
@@ -2212,8 +2180,10 @@ func (e *Exchange) GetOpenInterest(ctx context.Context, keys ...key.PairAsset) (
|
||||
for _, c := range contracts {
|
||||
if p.IsEmpty() { // If not exactly one key provided
|
||||
p, err = e.MatchSymbolWithAvailablePairs(c.contractName(), a, true)
|
||||
if err != nil && !errors.Is(err, currency.ErrPairNotFound) {
|
||||
errs = common.AppendError(errs, fmt.Errorf("%w from %s contract %s", err, a, c.contractName()))
|
||||
if err != nil {
|
||||
if err := common.ExcludeError(err, currency.ErrPairNotFound); err != nil {
|
||||
errs = common.AppendError(errs, fmt.Errorf("%w from %s contract %s", err, a, c.contractName()))
|
||||
}
|
||||
continue
|
||||
}
|
||||
if len(keys) == 0 { // No keys: All enabled pairs
|
||||
@@ -2257,7 +2227,7 @@ func (c *FuturesContract) openInterest() float64 {
|
||||
}
|
||||
|
||||
func (c *FuturesContract) contractName() string {
|
||||
return c.Name
|
||||
return c.Name.String()
|
||||
}
|
||||
|
||||
func (c *DeliveryContract) openInterest() float64 {
|
||||
|
||||
Reference in New Issue
Block a user