Skip to content

Commit

Permalink
Huobi: Fix invalid contract type err when autoUpdatePairs is false
Browse files Browse the repository at this point in the history
We were relying on autoUpdatePairs to fetch contract types before we
need them. If the user disables it in config, we'll lazily fetch just
the relevant Futures.
  • Loading branch information
gbjk committed Nov 8, 2024
1 parent 199d30d commit 6afccd2
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 9 deletions.
5 changes: 5 additions & 0 deletions exchanges/huobi/huobi_futures.go
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,11 @@ func (h *HUOBI) formatFuturesPair(p currency.Pair, convertQuoteToExpiry bool) (s
// We need this because some apis, such as ticker, use BTC_CW, NW, CQ, NQ
// Other apis, such as contract_info, use contract type of this_week, next_week, quarter (sic), and next_quater
func (h *HUOBI) pairFromContractExpiryCode(p currency.Pair) (currency.Pair, error) {
if h.futureContractCodes == nil { // Worst race-case here is that we fetch twice. No avoiding it.
if _, err := h.FetchTradablePairs(context.Background(), asset.Futures); err != nil {
return p, err
}
}
h.futureContractCodesMutex.RLock()
defer h.futureContractCodesMutex.RUnlock()
exp, ok := h.futureContractCodes[p.Quote.String()]
Expand Down
19 changes: 10 additions & 9 deletions exchanges/huobi/huobi_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,12 +283,19 @@ func (h *HUOBI) FetchTradablePairs(ctx context.Context, a asset.Item) (currency.
pairs = append(pairs, pair)
}
case asset.Futures:
// We cache contract expiries on the exchange locally right now because there's no exchange base holder for them
// It's not as dangerous as it seems, because when contracts change, so would tradeable pairs,
// so by caching them in FetchTradablePairs we're not adding any extra-layer of out-of-date data
// Note: Until this runs the first time the futureContractCodes is nil, which acts as an uninitialized flag for pairFromContractExpiryCode
h.futureContractCodesMutex.Lock()
defer h.futureContractCodesMutex.Unlock()
h.futureContractCodes = map[string]currency.Code{}

symbols, err := h.FGetContractInfo(ctx, "", "", currency.EMPTYPAIR)
if err != nil {
return nil, err
}
pairs = make([]currency.Pair, 0, len(symbols.Data))
expiryCodeDates := map[string]currency.Code{}
for _, c := range symbols.Data {
if c.ContractStatus != 1 {
continue
Expand All @@ -299,19 +306,13 @@ func (h *HUOBI) FetchTradablePairs(ctx context.Context, a asset.Item) (currency.
}
pairs = append(pairs, pair)
if cType, ok := contractExpiryNames[c.ContractType]; ok {
if v, ok := expiryCodeDates[cType]; !ok {
expiryCodeDates[cType] = currency.NewCode(pair.Quote.String())
if v, ok := h.futureContractCodes[cType]; !ok {
h.futureContractCodes[cType] = currency.NewCode(pair.Quote.String())
} else if v.String() != pair.Quote.String() {
return nil, fmt.Errorf("%w: %s (%s vs %s)", errInconsistentContractExpiry, cType, v.String(), pair.Quote.String())
}
}
}
// We cache contract expiries on the exchange locally right now because there's no exchange base holder for them
// It's not as dangerous as it seems, because when contracts change, so would tradeable pairs,
// so by caching them in FetchTradablePairs we're not adding any extra-layer of out-of-date data
h.futureContractCodesMutex.Lock()
h.futureContractCodes = expiryCodeDates
h.futureContractCodesMutex.Unlock()
}
return pairs, nil
}
Expand Down

0 comments on commit 6afccd2

Please sign in to comment.