mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
Deribit: Fix options combo currency formatting and various other improvements (#2048)
* update getAssetFromInstrument * Some fixes for deribit * neaten and improve * Update exchanges/deribit/deribit.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update exchanges/deribit/deribit.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * comment improvements to appease T-1000 * Update exchanges/deribit/deribit.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update exchanges/deribit/deribit_test.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix AI issues * niteroos * fix return order, min func footprint * fix disgusting egregious crime * >=( ">=5" * dropping e all the time --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -2628,85 +2628,48 @@ func (e *Exchange) StringToAssetKind(assetType string) (asset.Item, error) {
|
|||||||
|
|
||||||
// getAssetPairByInstrument is able to determine the asset type and currency pair
|
// getAssetPairByInstrument is able to determine the asset type and currency pair
|
||||||
// based on the received instrument ID
|
// based on the received instrument ID
|
||||||
func (e *Exchange) getAssetPairByInstrument(instrument string) (currency.Pair, asset.Item, error) {
|
func getAssetPairByInstrument(instrument string) (asset.Item, currency.Pair, error) {
|
||||||
if instrument == "" {
|
if instrument == "" {
|
||||||
return currency.EMPTYPAIR, asset.Empty, errInvalidInstrumentName
|
return asset.Empty, currency.EMPTYPAIR, currency.ErrSymbolStringEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
var item asset.Item
|
item, err := getAssetFromInstrument(instrument)
|
||||||
// Find the first occurrence of the delimiter and split the instrument string accordingly
|
if err != nil {
|
||||||
parts := strings.Split(instrument, currency.DashDelimiter)
|
return asset.Empty, currency.EMPTYPAIR, err
|
||||||
switch {
|
|
||||||
case len(parts) == 1:
|
|
||||||
if i := strings.IndexAny(instrument, currency.UnderscoreDelimiter); i == -1 {
|
|
||||||
return currency.EMPTYPAIR, asset.Empty, fmt.Errorf("%w %s", errUnsupportedInstrumentFormat, instrument)
|
|
||||||
}
|
|
||||||
item = asset.Spot
|
|
||||||
case len(parts) == 2:
|
|
||||||
item = asset.Futures
|
|
||||||
case parts[len(parts)-1] == "C" || parts[len(parts)-1] == "P":
|
|
||||||
item = asset.Options
|
|
||||||
case len(parts) >= 3:
|
|
||||||
// Check for options or other types
|
|
||||||
switch parts[1] {
|
|
||||||
case "USDC", "USDT":
|
|
||||||
item = asset.Futures
|
|
||||||
case "FS":
|
|
||||||
item = asset.FutureCombo
|
|
||||||
default:
|
|
||||||
item = asset.OptionCombo
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return currency.EMPTYPAIR, asset.Empty, fmt.Errorf("%w %s", errUnsupportedInstrumentFormat, instrument)
|
|
||||||
}
|
}
|
||||||
cp, err := currency.NewPairFromString(instrument)
|
cp, err := currency.NewPairFromString(instrument)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return currency.EMPTYPAIR, asset.Empty, err
|
return asset.Empty, currency.EMPTYPAIR, err
|
||||||
}
|
}
|
||||||
|
return item, cp, nil
|
||||||
return cp, item, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAssetFromPair(currencyPair currency.Pair) (asset.Item, error) {
|
// getAssetFromInstrument extrapolates the asset type from the instrument formatting as each type is unique
|
||||||
currencyPairString := currencyPair.String()
|
func getAssetFromInstrument(instrument string) (asset.Item, error) {
|
||||||
vals := strings.Split(currencyPairString, currency.DashDelimiter)
|
currencyParts := strings.Split(instrument, currency.DashDelimiter)
|
||||||
if strings.HasSuffix(currencyPairString, perpString) || len(vals) == 2 {
|
partsLen := len(currencyParts)
|
||||||
|
currencySuffix := currencyParts[partsLen-1]
|
||||||
|
hasUnderscore := strings.Contains(instrument, currency.UnderscoreDelimiter)
|
||||||
|
switch {
|
||||||
|
case partsLen == 1 && !hasUnderscore: // no pair delimiter found
|
||||||
|
return asset.Empty, fmt.Errorf("%w %s", errUnsupportedInstrumentFormat, instrument)
|
||||||
|
case partsLen == 1: // spot pairs use underscore eg BTC_USDC
|
||||||
|
return asset.Spot, nil
|
||||||
|
case partsLen == 2: // futures pairs use single dash eg ETH_USDC-PERPETUAL, BTC-12SEP25
|
||||||
return asset.Futures, nil
|
return asset.Futures, nil
|
||||||
} else if len(vals) == 1 {
|
case currencySuffix == "C", currencySuffix == "P": // options end in P or C to denote puts or calls eg BTC-26SEP25-30000-C
|
||||||
if vals = strings.Split(vals[0], currency.UnderscoreDelimiter); len(vals) == 2 {
|
|
||||||
return asset.Spot, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
added := false
|
|
||||||
if len(vals) >= 3 {
|
|
||||||
for a := range vals {
|
|
||||||
lastVals := strings.Split(vals[a], currency.UnderscoreDelimiter)
|
|
||||||
if len(lastVals) > 1 {
|
|
||||||
added = true
|
|
||||||
if a < len(vals)-1 {
|
|
||||||
lastVals = append(lastVals, vals[a+1:]...)
|
|
||||||
}
|
|
||||||
vals = append(vals[:a], lastVals...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
length := len(vals)
|
|
||||||
if strings.EqualFold(vals[length-1], "C") || strings.EqualFold(vals[length-1], "P") {
|
|
||||||
return asset.Options, nil
|
return asset.Options, nil
|
||||||
}
|
case partsLen == 3: // futures combos have 3 parts eg BTC-FS-12SEP25_PERP
|
||||||
if length == 4 {
|
return asset.FutureCombo, nil
|
||||||
if added {
|
case partsLen == 4: // option combos with more than 3 parts eg BTC_USDC-PS-19SEP25-113000_111000
|
||||||
return asset.FutureCombo, nil
|
|
||||||
}
|
|
||||||
return asset.OptionCombo, nil
|
|
||||||
} else if length >= 5 {
|
|
||||||
return asset.OptionCombo, nil
|
return asset.OptionCombo, nil
|
||||||
|
default: // deribit has changed their format and needs a review
|
||||||
|
return asset.Empty, fmt.Errorf("%w %s", errUnsupportedInstrumentFormat, instrument)
|
||||||
}
|
}
|
||||||
return asset.Empty, fmt.Errorf("%w currency pair: %v", errUnsupportedInstrumentFormat, currencyPair)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateTradingFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
|
func calculateTradingFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
|
||||||
assetType, err := getAssetFromPair(feeBuilder.Pair)
|
assetType, err := getAssetFromInstrument(feeBuilder.Pair.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@@ -2757,7 +2720,7 @@ func getOfflineTradeFee(price, amount float64) float64 {
|
|||||||
return 0.0003 * price * amount
|
return 0.0003 * price * amount
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) formatFuturesTradablePair(pair currency.Pair) string {
|
func formatFuturesTradablePair(pair currency.Pair) string {
|
||||||
var instrumentID string
|
var instrumentID string
|
||||||
if result := strings.Split(pair.String(), currency.DashDelimiter); len(result) == 3 {
|
if result := strings.Split(pair.String(), currency.DashDelimiter); len(result) == 3 {
|
||||||
instrumentID = strings.Join(result[:2], currency.UnderscoreDelimiter) + currency.DashDelimiter + result[2]
|
instrumentID = strings.Join(result[:2], currency.UnderscoreDelimiter) + currency.DashDelimiter + result[2]
|
||||||
@@ -2772,7 +2735,7 @@ func (e *Exchange) formatFuturesTradablePair(pair currency.Pair) string {
|
|||||||
// EXPIRE is DDMMMYY
|
// EXPIRE is DDMMMYY
|
||||||
// STRIKE may include a d for decimal point in linear options
|
// STRIKE may include a d for decimal point in linear options
|
||||||
// TYPE is Call or Put
|
// TYPE is Call or Put
|
||||||
func (e *Exchange) optionPairToString(pair currency.Pair) string {
|
func optionPairToString(pair currency.Pair) string {
|
||||||
initialDelimiter := currency.DashDelimiter
|
initialDelimiter := currency.DashDelimiter
|
||||||
q := pair.Quote.String()
|
q := pair.Quote.String()
|
||||||
if strings.HasPrefix(q, "USDC") && len(q) > 11 { // Linear option
|
if strings.HasPrefix(q, "USDC") && len(q) > 11 { // Linear option
|
||||||
@@ -2783,3 +2746,22 @@ func (e *Exchange) optionPairToString(pair currency.Pair) string {
|
|||||||
}
|
}
|
||||||
return pair.Base.String() + initialDelimiter + q
|
return pair.Base.String() + initialDelimiter + q
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// optionComboPairToString formats an option combo pair to deribit request format
|
||||||
|
// e.g. XRP-USDC-CS-26SEP25-3D3_3D5 -> XRP_USDC-CS-26SEP25-3d3_3d5
|
||||||
|
func optionComboPairToString(pair currency.Pair) string {
|
||||||
|
parts := strings.Split(pair.String(), "-")
|
||||||
|
// Deribit uses lowercase 'd' to represent the decimal point
|
||||||
|
lastIdx := len(parts) - 1
|
||||||
|
parts[lastIdx] = strings.ReplaceAll(parts[lastIdx], "D", "d")
|
||||||
|
// Leave unchanged when:
|
||||||
|
// * length <= 3 (not enough info to be a combo needing underscore)
|
||||||
|
// * length == 4 and second token is not USDC (original logic kept as-is)
|
||||||
|
if len(parts) <= 3 || (len(parts) == 4 && parts[1] != "USDC") {
|
||||||
|
return strings.Join(parts, "-")
|
||||||
|
}
|
||||||
|
// Otherwise insert underscore after base (covers:
|
||||||
|
// * any length > 4
|
||||||
|
// * length == 4 with USDC as second token)
|
||||||
|
return parts[0] + "_" + strings.Join(parts[1:], "-")
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/futures"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/futures"
|
||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
|
||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||||
|
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
|
||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/subscription"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/subscription"
|
||||||
"github.com/thrasher-corp/gocryptotrader/exchanges/trade"
|
"github.com/thrasher-corp/gocryptotrader/exchanges/trade"
|
||||||
@@ -219,7 +220,7 @@ func TestSubmitOrder(t *testing.T) {
|
|||||||
var err error
|
var err error
|
||||||
var info *InstrumentData
|
var info *InstrumentData
|
||||||
for assetType, cp := range assetToPairStringMap {
|
for assetType, cp := range assetToPairStringMap {
|
||||||
info, err = e.GetInstrument(t.Context(), e.formatPairString(assetType, cp))
|
info, err = e.GetInstrument(t.Context(), formatPairString(assetType, cp))
|
||||||
require.NoErrorf(t, err, "expected nil, got %v for asset type %s pair %s", err, assetType, cp)
|
require.NoErrorf(t, err, "expected nil, got %v for asset type %s pair %s", err, assetType, cp)
|
||||||
require.NotNilf(t, result, "expected result not to be nil for asset type %s pair %s", assetType, cp)
|
require.NotNilf(t, result, "expected result not to be nil for asset type %s pair %s", assetType, cp)
|
||||||
|
|
||||||
@@ -252,7 +253,7 @@ func TestGetMarkPriceHistory(t *testing.T) {
|
|||||||
|
|
||||||
var result []MarkPriceHistory
|
var result []MarkPriceHistory
|
||||||
for _, ps := range []string{
|
for _, ps := range []string{
|
||||||
e.optionPairToString(optionsTradablePair),
|
optionPairToString(optionsTradablePair),
|
||||||
spotTradablePair.String(),
|
spotTradablePair.String(),
|
||||||
btcPerpInstrument,
|
btcPerpInstrument,
|
||||||
futureComboTradablePair.String(),
|
futureComboTradablePair.String(),
|
||||||
@@ -270,7 +271,7 @@ func TestWSRetrieveMarkPriceHistory(t *testing.T) {
|
|||||||
|
|
||||||
var result []MarkPriceHistory
|
var result []MarkPriceHistory
|
||||||
for _, ps := range []string{
|
for _, ps := range []string{
|
||||||
e.optionPairToString(optionsTradablePair),
|
optionPairToString(optionsTradablePair),
|
||||||
spotTradablePair.String(),
|
spotTradablePair.String(),
|
||||||
btcPerpInstrument,
|
btcPerpInstrument,
|
||||||
futureComboTradablePair.String(),
|
futureComboTradablePair.String(),
|
||||||
@@ -311,17 +312,19 @@ func TestGetBookSummaryByInstrument(t *testing.T) {
|
|||||||
_, err := e.GetBookSummaryByInstrument(t.Context(), "")
|
_, err := e.GetBookSummaryByInstrument(t.Context(), "")
|
||||||
require.ErrorIs(t, err, errInvalidInstrumentName)
|
require.ErrorIs(t, err, errInvalidInstrumentName)
|
||||||
|
|
||||||
var result []BookSummaryData
|
|
||||||
for _, ps := range []string{
|
for _, ps := range []string{
|
||||||
btcPerpInstrument,
|
btcPerpInstrument,
|
||||||
spotTradablePair.String(),
|
spotTradablePair.String(),
|
||||||
futureComboTradablePair.String(),
|
futureComboTradablePair.String(),
|
||||||
e.optionPairToString(optionsTradablePair),
|
optionPairToString(optionsTradablePair),
|
||||||
optionComboTradablePair.String(),
|
optionComboPairToString(optionComboTradablePair),
|
||||||
} {
|
} {
|
||||||
result, err = e.GetBookSummaryByInstrument(t.Context(), ps)
|
t.Run(ps, func(t *testing.T) {
|
||||||
require.NoErrorf(t, err, "expected nil, got %v for pair %s", err, ps)
|
t.Parallel()
|
||||||
require.NotNilf(t, result, "expected result not to be nil for pair %s", ps)
|
result, err := e.GetBookSummaryByInstrument(t.Context(), ps)
|
||||||
|
require.NoError(t, err, "GetBookSummaryByInstrument must not error")
|
||||||
|
require.NotNil(t, result, "result must not be nil")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,8 +337,8 @@ func TestWSRetrieveBookSummaryByInstrument(t *testing.T) {
|
|||||||
btcPerpInstrument,
|
btcPerpInstrument,
|
||||||
spotTradablePair.String(),
|
spotTradablePair.String(),
|
||||||
futureComboTradablePair.String(),
|
futureComboTradablePair.String(),
|
||||||
e.optionPairToString(optionsTradablePair),
|
optionPairToString(optionsTradablePair),
|
||||||
optionComboTradablePair.String(),
|
optionComboPairToString(optionComboTradablePair),
|
||||||
} {
|
} {
|
||||||
result, err = e.WSRetrieveBookSummaryByInstrument(t.Context(), ps)
|
result, err = e.WSRetrieveBookSummaryByInstrument(t.Context(), ps)
|
||||||
require.NoErrorf(t, err, "expected nil, got %v for pair %s", err, ps)
|
require.NoErrorf(t, err, "expected nil, got %v for pair %s", err, ps)
|
||||||
@@ -548,7 +551,7 @@ func TestGetInstrumentData(t *testing.T) {
|
|||||||
|
|
||||||
var result *InstrumentData
|
var result *InstrumentData
|
||||||
for assetType, cp := range assetTypeToPairsMap {
|
for assetType, cp := range assetTypeToPairsMap {
|
||||||
result, err = e.GetInstrument(t.Context(), e.formatPairString(assetType, cp))
|
result, err = e.GetInstrument(t.Context(), formatPairString(assetType, cp))
|
||||||
require.NoErrorf(t, err, "expected nil, got %v for asset type %s pair %s", err, assetType, cp)
|
require.NoErrorf(t, err, "expected nil, got %v for asset type %s pair %s", err, assetType, cp)
|
||||||
require.NotNilf(t, result, "expected result not to be nil for asset type %s pair %s", assetType, cp)
|
require.NotNilf(t, result, "expected result not to be nil for asset type %s pair %s", assetType, cp)
|
||||||
}
|
}
|
||||||
@@ -558,12 +561,13 @@ func TestWSRetrieveInstrumentData(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
_, err := e.WSRetrieveInstrumentData(t.Context(), "")
|
_, err := e.WSRetrieveInstrumentData(t.Context(), "")
|
||||||
require.ErrorIs(t, err, errInvalidInstrumentName)
|
require.ErrorIs(t, err, errInvalidInstrumentName)
|
||||||
|
|
||||||
var result *InstrumentData
|
|
||||||
for assetType, cp := range assetTypeToPairsMap {
|
for assetType, cp := range assetTypeToPairsMap {
|
||||||
result, err = e.WSRetrieveInstrumentData(t.Context(), e.formatPairString(assetType, cp))
|
t.Run(fmt.Sprintf("%s %s", assetType, cp), func(t *testing.T) {
|
||||||
require.NoErrorf(t, err, "expected nil, got %v for asset type %s pair %s", err, assetType, cp)
|
t.Parallel()
|
||||||
require.NotNilf(t, result, "expected result not to be nil for asset type %s pair %s", assetType, cp)
|
result, err := e.WSRetrieveInstrumentData(request.WithVerbose(t.Context()), formatPairString(assetType, cp))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, result, "result must not be nil")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -617,7 +621,7 @@ func TestWSRetrieveLastSettlementsByInstrument(t *testing.T) {
|
|||||||
_, err := e.WSRetrieveLastSettlementsByInstrument(t.Context(), "", "settlement", "5", 0, time.Now().Add(-2*time.Hour))
|
_, err := e.WSRetrieveLastSettlementsByInstrument(t.Context(), "", "settlement", "5", 0, time.Now().Add(-2*time.Hour))
|
||||||
require.ErrorIs(t, err, errInvalidInstrumentName)
|
require.ErrorIs(t, err, errInvalidInstrumentName)
|
||||||
|
|
||||||
result, err := e.WSRetrieveLastSettlementsByInstrument(t.Context(), e.formatFuturesTradablePair(futuresTradablePair), "settlement", "5", 0, time.Now().Add(-2*time.Hour))
|
result, err := e.WSRetrieveLastSettlementsByInstrument(t.Context(), formatFuturesTradablePair(futuresTradablePair), "settlement", "5", 0, time.Now().Add(-2*time.Hour))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, result)
|
assert.NotNil(t, result)
|
||||||
}
|
}
|
||||||
@@ -627,7 +631,7 @@ func TestGetLastSettlementsByInstrument(t *testing.T) {
|
|||||||
_, err := e.GetLastSettlementsByInstrument(t.Context(), "", "settlement", "5", 0, time.Now().Add(-2*time.Hour))
|
_, err := e.GetLastSettlementsByInstrument(t.Context(), "", "settlement", "5", 0, time.Now().Add(-2*time.Hour))
|
||||||
require.ErrorIs(t, err, errInvalidInstrumentName)
|
require.ErrorIs(t, err, errInvalidInstrumentName)
|
||||||
|
|
||||||
result, err := e.GetLastSettlementsByInstrument(t.Context(), e.formatFuturesTradablePair(futuresTradablePair), "settlement", "5", 0, time.Now().Add(-2*time.Hour))
|
result, err := e.GetLastSettlementsByInstrument(t.Context(), formatFuturesTradablePair(futuresTradablePair), "settlement", "5", 0, time.Now().Add(-2*time.Hour))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, result)
|
assert.NotNil(t, result)
|
||||||
}
|
}
|
||||||
@@ -684,7 +688,7 @@ func TestGetLastTradesByInstrument(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, errInvalidInstrumentName)
|
require.ErrorIs(t, err, errInvalidInstrumentName)
|
||||||
|
|
||||||
for assetType, cp := range assetTypeToPairsMap {
|
for assetType, cp := range assetTypeToPairsMap {
|
||||||
result, err := e.GetLastTradesByInstrument(t.Context(), e.formatPairString(assetType, cp), "30500", "31500", "desc", 0, true)
|
result, err := e.GetLastTradesByInstrument(t.Context(), formatPairString(assetType, cp), "30500", "31500", "desc", 0, true)
|
||||||
require.NoErrorf(t, err, "expected %v, got %v currency asset %v pair %v", nil, err, assetType, cp)
|
require.NoErrorf(t, err, "expected %v, got %v currency asset %v pair %v", nil, err, assetType, cp)
|
||||||
require.NotNilf(t, result, "expected value not to be nil for asset %v pair: %v", assetType, cp)
|
require.NotNilf(t, result, "expected value not to be nil for asset %v pair: %v", assetType, cp)
|
||||||
}
|
}
|
||||||
@@ -696,7 +700,7 @@ func TestWSRetrieveLastTradesByInstrument(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, errInvalidInstrumentName)
|
require.ErrorIs(t, err, errInvalidInstrumentName)
|
||||||
|
|
||||||
for assetType, cp := range assetTypeToPairsMap {
|
for assetType, cp := range assetTypeToPairsMap {
|
||||||
result, err := e.WSRetrieveLastTradesByInstrument(t.Context(), e.formatPairString(assetType, cp), "30500", "31500", "desc", 0, true)
|
result, err := e.WSRetrieveLastTradesByInstrument(t.Context(), formatPairString(assetType, cp), "30500", "31500", "desc", 0, true)
|
||||||
require.NoErrorf(t, err, "expected %v, got %v currency asset %v pair %v", nil, err, assetType, cp)
|
require.NoErrorf(t, err, "expected %v, got %v currency asset %v pair %v", nil, err, assetType, cp)
|
||||||
require.NotNilf(t, result, "expected value not to be nil for asset %v pair: %v", assetType, cp)
|
require.NotNilf(t, result, "expected value not to be nil for asset %v pair: %v", assetType, cp)
|
||||||
}
|
}
|
||||||
@@ -708,7 +712,7 @@ func TestGetLastTradesByInstrumentAndTime(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, errInvalidInstrumentName)
|
require.ErrorIs(t, err, errInvalidInstrumentName)
|
||||||
|
|
||||||
for assetType, cp := range assetTypeToPairsMap {
|
for assetType, cp := range assetTypeToPairsMap {
|
||||||
result, err := e.GetLastTradesByInstrumentAndTime(t.Context(), e.formatPairString(assetType, cp), "", 0, time.Now().Add(-8*time.Hour), time.Now())
|
result, err := e.GetLastTradesByInstrumentAndTime(t.Context(), formatPairString(assetType, cp), "", 0, time.Now().Add(-8*time.Hour), time.Now())
|
||||||
require.NoErrorf(t, err, "expected %v, got %v currency pair %v", nil, err, cp)
|
require.NoErrorf(t, err, "expected %v, got %v currency pair %v", nil, err, cp)
|
||||||
require.NotNilf(t, result, "expected value not to be nil for pair: %v", cp)
|
require.NotNilf(t, result, "expected value not to be nil for pair: %v", cp)
|
||||||
}
|
}
|
||||||
@@ -720,7 +724,7 @@ func TestWSRetrieveLastTradesByInstrumentAndTime(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, errInvalidInstrumentName)
|
require.ErrorIs(t, err, errInvalidInstrumentName)
|
||||||
|
|
||||||
for assetType, cp := range assetTypeToPairsMap {
|
for assetType, cp := range assetTypeToPairsMap {
|
||||||
result, err := e.WSRetrieveLastTradesByInstrumentAndTime(t.Context(), e.formatPairString(assetType, cp), "", 0, true, time.Now().Add(-8*time.Hour), time.Now())
|
result, err := e.WSRetrieveLastTradesByInstrumentAndTime(t.Context(), formatPairString(assetType, cp), "", 0, true, time.Now().Add(-8*time.Hour), time.Now())
|
||||||
require.NoErrorf(t, err, "expected %v, got %v currency pair %v", nil, err, cp)
|
require.NoErrorf(t, err, "expected %v, got %v currency pair %v", nil, err, cp)
|
||||||
require.NotNilf(t, result, "expected value not to be nil for pair: %v", cp)
|
require.NotNilf(t, result, "expected value not to be nil for pair: %v", cp)
|
||||||
}
|
}
|
||||||
@@ -734,7 +738,7 @@ func TestWSProcessTrades(t *testing.T) {
|
|||||||
testexch.FixtureToDataHandler(t, "testdata/wsAllTrades.json", e.wsHandleData)
|
testexch.FixtureToDataHandler(t, "testdata/wsAllTrades.json", e.wsHandleData)
|
||||||
close(e.Websocket.DataHandler)
|
close(e.Websocket.DataHandler)
|
||||||
|
|
||||||
p, a, err := e.getAssetPairByInstrument("BTC-PERPETUAL")
|
a, p, err := getAssetPairByInstrument("BTC-PERPETUAL")
|
||||||
require.NoError(t, err, "getAssetPairByInstrument must not error")
|
require.NoError(t, err, "getAssetPairByInstrument must not error")
|
||||||
|
|
||||||
exp := []trade.Data{
|
exp := []trade.Data{
|
||||||
@@ -780,7 +784,7 @@ func TestGetOrderbookData(t *testing.T) {
|
|||||||
|
|
||||||
var result *Orderbook
|
var result *Orderbook
|
||||||
for assetType, cp := range assetTypeToPairsMap {
|
for assetType, cp := range assetTypeToPairsMap {
|
||||||
result, err = e.GetOrderbook(t.Context(), e.formatPairString(assetType, cp), 0)
|
result, err = e.GetOrderbook(t.Context(), formatPairString(assetType, cp), 0)
|
||||||
require.NoErrorf(t, err, "expected %v, got %v currency pair %v", nil, err, cp)
|
require.NoErrorf(t, err, "expected %v, got %v currency pair %v", nil, err, cp)
|
||||||
require.NotNilf(t, result, "expected value not to be nil for pair: %v", cp)
|
require.NotNilf(t, result, "expected value not to be nil for pair: %v", cp)
|
||||||
}
|
}
|
||||||
@@ -796,7 +800,7 @@ func TestWSRetrieveOrderbookData(t *testing.T) {
|
|||||||
|
|
||||||
var result *Orderbook
|
var result *Orderbook
|
||||||
for assetType, cp := range assetTypeToPairsMap {
|
for assetType, cp := range assetTypeToPairsMap {
|
||||||
result, err = e.WSRetrieveOrderbookData(t.Context(), e.formatPairString(assetType, cp), 0)
|
result, err = e.WSRetrieveOrderbookData(t.Context(), formatPairString(assetType, cp), 0)
|
||||||
require.NoErrorf(t, err, "expected %v, got %v currency pair %v", nil, err, cp)
|
require.NoErrorf(t, err, "expected %v, got %v currency pair %v", nil, err, cp)
|
||||||
require.NotNilf(t, result, "expected value not to be nil for pair: %v", cp)
|
require.NotNilf(t, result, "expected value not to be nil for pair: %v", cp)
|
||||||
}
|
}
|
||||||
@@ -2192,22 +2196,22 @@ func TestWSSubmitCancelByLabel(t *testing.T) {
|
|||||||
|
|
||||||
func TestSubmitCancelQuotes(t *testing.T) {
|
func TestSubmitCancelQuotes(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
_, err := e.SubmitCancelQuotes(t.Context(), currency.EMPTYCODE, 0, 0, "all", "", futuresTradablePair.String(), "future", true)
|
_, err := e.SubmitCancelQuotes(t.Context(), currency.EMPTYCODE, 0, 0, "all", "", formatFuturesTradablePair(futuresTradablePair), "future", true)
|
||||||
require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty)
|
require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty)
|
||||||
|
|
||||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||||
result, err := e.SubmitCancelQuotes(t.Context(), currency.BTC, 0, 0, "all", "", futuresTradablePair.String(), "future", true)
|
result, err := e.SubmitCancelQuotes(t.Context(), currency.BTC, 0, 0, "all", "", formatFuturesTradablePair(futuresTradablePair), "future", true)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, result)
|
assert.NotNil(t, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWSSubmitCancelQuotes(t *testing.T) {
|
func TestWSSubmitCancelQuotes(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
_, err := e.WSSubmitCancelQuotes(t.Context(), currency.EMPTYCODE, 0, 0, "all", "", futuresTradablePair.String(), "future", true)
|
_, err := e.WSSubmitCancelQuotes(t.Context(), currency.EMPTYCODE, 0, 0, "all", "", formatFuturesTradablePair(futuresTradablePair), "future", true)
|
||||||
require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty)
|
require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty)
|
||||||
|
|
||||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||||
result, err := e.WSSubmitCancelQuotes(t.Context(), currency.BTC, 0, 0, "all", "", futuresTradablePair.String(), "future", true)
|
result, err := e.WSSubmitCancelQuotes(t.Context(), currency.BTC, 0, 0, "all", "", formatFuturesTradablePair(futuresTradablePair), "future", true)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, result)
|
assert.NotNil(t, result)
|
||||||
}
|
}
|
||||||
@@ -2218,7 +2222,7 @@ func TestSubmitClosePosition(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, errInvalidInstrumentName)
|
require.ErrorIs(t, err, errInvalidInstrumentName)
|
||||||
|
|
||||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||||
result, err := e.SubmitClosePosition(t.Context(), e.formatFuturesTradablePair(futuresTradablePair), "limit", 35000)
|
result, err := e.SubmitClosePosition(t.Context(), formatFuturesTradablePair(futuresTradablePair), "limit", 35000)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, result)
|
assert.NotNil(t, result)
|
||||||
}
|
}
|
||||||
@@ -2229,7 +2233,7 @@ func TestWSSubmitClosePosition(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, errInvalidInstrumentName)
|
require.ErrorIs(t, err, errInvalidInstrumentName)
|
||||||
|
|
||||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||||
result, err := e.WSSubmitClosePosition(t.Context(), e.formatFuturesTradablePair(futuresTradablePair), "limit", 35000)
|
result, err := e.WSSubmitClosePosition(t.Context(), formatFuturesTradablePair(futuresTradablePair), "limit", 35000)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, result)
|
assert.NotNil(t, result)
|
||||||
}
|
}
|
||||||
@@ -2238,13 +2242,13 @@ func TestGetMargins(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
_, err := e.GetMargins(t.Context(), "", 5, 35000)
|
_, err := e.GetMargins(t.Context(), "", 5, 35000)
|
||||||
require.ErrorIs(t, err, errInvalidInstrumentName)
|
require.ErrorIs(t, err, errInvalidInstrumentName)
|
||||||
_, err = e.GetMargins(t.Context(), e.formatFuturesTradablePair(futuresTradablePair), 0, 35000)
|
_, err = e.GetMargins(t.Context(), formatFuturesTradablePair(futuresTradablePair), 0, 35000)
|
||||||
require.ErrorIs(t, err, errInvalidAmount)
|
require.ErrorIs(t, err, errInvalidAmount)
|
||||||
_, err = e.GetMargins(t.Context(), e.formatFuturesTradablePair(futuresTradablePair), 5, -1)
|
_, err = e.GetMargins(t.Context(), formatFuturesTradablePair(futuresTradablePair), 5, -1)
|
||||||
require.ErrorIs(t, err, errInvalidPrice)
|
require.ErrorIs(t, err, errInvalidPrice)
|
||||||
|
|
||||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
|
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
|
||||||
result, err := e.GetMargins(t.Context(), e.formatFuturesTradablePair(futuresTradablePair), 5, 35000)
|
result, err := e.GetMargins(t.Context(), formatFuturesTradablePair(futuresTradablePair), 5, 35000)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, result)
|
assert.NotNil(t, result)
|
||||||
}
|
}
|
||||||
@@ -2255,7 +2259,7 @@ func TestWSRetrieveMargins(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, errInvalidInstrumentName)
|
require.ErrorIs(t, err, errInvalidInstrumentName)
|
||||||
|
|
||||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
|
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
|
||||||
result, err := e.WSRetrieveMargins(t.Context(), e.formatFuturesTradablePair(futuresTradablePair), 5, 35000)
|
result, err := e.WSRetrieveMargins(t.Context(), formatFuturesTradablePair(futuresTradablePair), 5, 35000)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, result)
|
assert.NotNil(t, result)
|
||||||
}
|
}
|
||||||
@@ -2626,7 +2630,7 @@ func TestSendRequestForQuote(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, errInvalidInstrumentName)
|
require.ErrorIs(t, err, errInvalidInstrumentName)
|
||||||
|
|
||||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
|
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
|
||||||
err = e.SendRequestForQuote(t.Context(), e.formatFuturesTradablePair(futuresTradablePair), 1000, order.Buy)
|
err = e.SendRequestForQuote(t.Context(), formatFuturesTradablePair(futuresTradablePair), 1000, order.Buy)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2636,7 +2640,7 @@ func TestWSSendRequestForQuote(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, errInvalidInstrumentName)
|
require.ErrorIs(t, err, errInvalidInstrumentName)
|
||||||
|
|
||||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
|
sharedtestvalues.SkipTestIfCredentialsUnset(t, e)
|
||||||
err = e.WSSendRequestForQuote(t.Context(), e.formatFuturesTradablePair(futuresTradablePair), 1000, order.Buy)
|
err = e.WSSendRequestForQuote(t.Context(), formatFuturesTradablePair(futuresTradablePair), 1000, order.Buy)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3445,12 +3449,13 @@ func TestGetWithdrawalsHistory(t *testing.T) {
|
|||||||
|
|
||||||
func TestGetRecentTrades(t *testing.T) {
|
func TestGetRecentTrades(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
var result []trade.Data
|
|
||||||
var err error
|
|
||||||
for assetType, cp := range assetTypeToPairsMap {
|
for assetType, cp := range assetTypeToPairsMap {
|
||||||
result, err = e.GetRecentTrades(t.Context(), cp, assetType)
|
t.Run(fmt.Sprintf("%s %s", assetType, cp), func(t *testing.T) {
|
||||||
require.NoErrorf(t, err, "expected nil, got %v for asset type %s pair %s", err, assetType, cp)
|
t.Parallel()
|
||||||
require.NotNilf(t, result, "expected result not to be nil for asset type %s pair %s", assetType, cp)
|
result, err := e.GetRecentTrades(t.Context(), cp, assetType)
|
||||||
|
require.NoError(t, err, "GetRecentTrades must not error")
|
||||||
|
require.NotNil(t, result, "result must not be nil")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3539,30 +3544,6 @@ func TestGetOrderHistory(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAssetFromPair(t *testing.T) {
|
|
||||||
var assetTypeNew asset.Item
|
|
||||||
for _, assetType := range []asset.Item{asset.Spot, asset.Futures, asset.Options, asset.OptionCombo, asset.FutureCombo} {
|
|
||||||
availablePairs, err := e.GetEnabledPairs(assetType)
|
|
||||||
require.NoErrorf(t, err, "expected nil, got %v for asset type %s", err, assetType)
|
|
||||||
require.NotNilf(t, availablePairs, "expected result not to be nil for asset type %s", assetType)
|
|
||||||
|
|
||||||
format, err := e.GetPairFormat(assetType, true)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
for id, cp := range availablePairs {
|
|
||||||
t.Run(strconv.Itoa(id), func(t *testing.T) {
|
|
||||||
assetTypeNew, err = getAssetFromPair(cp.Format(format))
|
|
||||||
require.Equalf(t, assetType, assetTypeNew, "expected %s, but found %s for pair string %s", assetType.String(), assetTypeNew.String(), cp.Format(format))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cp, err := currency.NewPairFromString("some_thing_else")
|
|
||||||
require.NoError(t, err)
|
|
||||||
_, err = getAssetFromPair(cp)
|
|
||||||
assert.ErrorIs(t, err, errUnsupportedInstrumentFormat)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetAssetPairByInstrument(t *testing.T) {
|
func TestGetAssetPairByInstrument(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
for _, assetType := range []asset.Item{asset.Spot, asset.Futures, asset.Options, asset.OptionCombo, asset.FutureCombo} {
|
for _, assetType := range []asset.Item{asset.Spot, asset.Futures, asset.Options, asset.OptionCombo, asset.FutureCombo} {
|
||||||
@@ -3570,27 +3551,64 @@ func TestGetAssetPairByInstrument(t *testing.T) {
|
|||||||
require.NoErrorf(t, err, "expected nil, got %v for asset type %s", err, assetType)
|
require.NoErrorf(t, err, "expected nil, got %v for asset type %s", err, assetType)
|
||||||
require.NotNilf(t, availablePairs, "expected result not to be nil for asset type %s", assetType)
|
require.NotNilf(t, availablePairs, "expected result not to be nil for asset type %s", assetType)
|
||||||
for _, cp := range availablePairs {
|
for _, cp := range availablePairs {
|
||||||
t.Run(fmt.Sprintf("%s %s", assetType, cp), func(t *testing.T) {
|
instrument := formatPairString(assetType, cp)
|
||||||
|
t.Run(fmt.Sprintf("%s %s", assetType, instrument), func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
extractedPair, extractedAsset, err := e.getAssetPairByInstrument(cp.String())
|
extractedAsset, extractedPair, err := getAssetPairByInstrument(instrument)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, cp.String(), extractedPair.String())
|
fPair, err := e.FormatExchangeCurrency(extractedPair, assetType)
|
||||||
assert.Equal(t, assetType.String(), extractedAsset.String())
|
require.NoError(t, err, "FormatExchangeCurrency must not error")
|
||||||
|
assert.Equal(t, cp.String(), fPair.String())
|
||||||
|
assert.Equal(t, assetType.String(), extractedAsset.String(), "asset should match for")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.Run("empty asset, empty pair", func(t *testing.T) {
|
t.Run("empty asset, empty pair", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
_, _, err := e.getAssetPairByInstrument("")
|
_, _, err := getAssetPairByInstrument("")
|
||||||
assert.ErrorIs(t, err, errInvalidInstrumentName)
|
assert.ErrorIs(t, err, currency.ErrSymbolStringEmpty)
|
||||||
})
|
})
|
||||||
t.Run("thisIsAFakeCurrency", func(t *testing.T) {
|
t.Run("thisIsAFakeCurrency", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
_, _, err := e.getAssetPairByInstrument("thisIsAFakeCurrency")
|
_, _, err := getAssetPairByInstrument("thisIsAFakeCurrency")
|
||||||
assert.ErrorIs(t, err, errUnsupportedInstrumentFormat)
|
assert.ErrorIs(t, err, errUnsupportedInstrumentFormat)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetAssetFromInstrument(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
tc := []struct {
|
||||||
|
instrument string
|
||||||
|
expectedAsset asset.Item
|
||||||
|
expectedError error
|
||||||
|
}{
|
||||||
|
{"BNB_USDC", asset.Spot, nil},
|
||||||
|
{"BTC-30DEC22", asset.Futures, nil},
|
||||||
|
{"BTCDVOL_USDC-1OCT25", asset.Futures, nil},
|
||||||
|
{"ADA_USDC-PERPETUAL", asset.Futures, nil},
|
||||||
|
{"PAXG_USDC-12SEP25-3320-P", asset.Options, nil},
|
||||||
|
{"ETH-3OCT25-4800-P", asset.Options, nil},
|
||||||
|
{"ETH-FS-26JUN26_26DEC25", asset.FutureCombo, nil},
|
||||||
|
{"BTC_USDC-PBUT-31OCT25-90000_100000_102000", asset.OptionCombo, nil},
|
||||||
|
{"XRP_USDC-CBUT-26SEP25-2d9_3d2_3d4", asset.OptionCombo, nil},
|
||||||
|
{"ETH-CS-26SEP25-5000_5500", asset.OptionCombo, nil},
|
||||||
|
{"HELLOMOTO", asset.Empty, errUnsupportedInstrumentFormat},
|
||||||
|
{"hi-my-name-is-moto", asset.Empty, errUnsupportedInstrumentFormat},
|
||||||
|
}
|
||||||
|
for _, test := range tc {
|
||||||
|
t.Run(test.instrument, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
a, err := getAssetFromInstrument(test.instrument)
|
||||||
|
if test.expectedError != nil {
|
||||||
|
assert.ErrorIs(t, err, test.expectedError)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, test.expectedAsset, a)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||||
feeBuilder := &exchange.FeeBuilder{
|
feeBuilder := &exchange.FeeBuilder{
|
||||||
Amount: 1,
|
Amount: 1,
|
||||||
@@ -3666,7 +3684,7 @@ func TestCalculateTradingFee(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, result)
|
require.NotNil(t, result)
|
||||||
_, err = calculateTradingFee(feeBuilder)
|
_, err = calculateTradingFee(feeBuilder)
|
||||||
assert.ErrorIs(t, err, errUnsupportedInstrumentFormat)
|
assert.ErrorIs(t, err, asset.ErrNotSupported)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTime(t *testing.T) {
|
func TestGetTime(t *testing.T) {
|
||||||
@@ -3757,7 +3775,7 @@ func TestProcessPushData(t *testing.T) {
|
|||||||
t.Run(k, func(t *testing.T) {
|
t.Run(k, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
err := e.wsHandleData(t.Context(), []byte(v))
|
err := e.wsHandleData(t.Context(), []byte(v))
|
||||||
require.NoErrorf(t, err, "%s: Received unexpected error for", k)
|
require.NoError(t, err, "wsHandleData must not error")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3774,7 +3792,7 @@ func TestFormatFuturesTradablePair(t *testing.T) {
|
|||||||
for pair, instrumentID := range futuresInstrumentsOutputList {
|
for pair, instrumentID := range futuresInstrumentsOutputList {
|
||||||
t.Run(instrumentID, func(t *testing.T) {
|
t.Run(instrumentID, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
instrument := e.formatFuturesTradablePair(pair)
|
instrument := formatFuturesTradablePair(pair)
|
||||||
require.Equal(t, instrumentID, instrument)
|
require.Equal(t, instrumentID, instrument)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -3790,7 +3808,7 @@ func TestOptionPairToString(t *testing.T) {
|
|||||||
{Delimiter: currency.DashDelimiter, Base: currency.MATIC, Quote: currency.NewCode("USDC-8JUN24-0D99-P")}: "MATIC_USDC-8JUN24-0d99-P",
|
{Delimiter: currency.DashDelimiter, Base: currency.MATIC, Quote: currency.NewCode("USDC-8JUN24-0D99-P")}: "MATIC_USDC-8JUN24-0d99-P",
|
||||||
{Delimiter: currency.DashDelimiter, Base: currency.MATIC, Quote: currency.NewCode("USDC-6DEC29-0D87-C")}: "MATIC_USDC-6DEC29-0d87-C",
|
{Delimiter: currency.DashDelimiter, Base: currency.MATIC, Quote: currency.NewCode("USDC-6DEC29-0D87-C")}: "MATIC_USDC-6DEC29-0d87-C",
|
||||||
} {
|
} {
|
||||||
assert.Equal(t, exp, e.optionPairToString(pair), "optionPairToString should return correctly")
|
assert.Equal(t, exp, optionPairToString(pair), "optionPairToString should return correctly")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4036,8 +4054,8 @@ func TestIsPerpetualFutureCurrency(t *testing.T) {
|
|||||||
t.Run(fmt.Sprintf("Asset: %s Pair: %s", assetType.String(), instances[i].Pair.String()), func(t *testing.T) {
|
t.Run(fmt.Sprintf("Asset: %s Pair: %s", assetType.String(), instances[i].Pair.String()), func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
is, err := e.IsPerpetualFutureCurrency(assetType, instances[i].Pair)
|
is, err := e.IsPerpetualFutureCurrency(assetType, instances[i].Pair)
|
||||||
require.ErrorIsf(t, err, instances[i].Error, "expected %v, got %v for asset: %s pair: %s", instances[i].Error, err, assetType.String(), instances[i].Pair.String())
|
require.ErrorIs(t, err, instances[i].Error)
|
||||||
require.Equalf(t, is, instances[i].Response, "expected %v, got %v for asset: %s pair: %s", instances[i].Response, is, assetType.String(), instances[i].Pair.String())
|
require.Equal(t, is, instances[i].Response)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4192,3 +4210,53 @@ func TestTimeInForceFromString(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, timeInForceList[i].Error)
|
require.ErrorIs(t, err, timeInForceList[i].Error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOptionsComboFormatting(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
availablePairs, err := e.GetAvailablePairs(asset.OptionCombo)
|
||||||
|
require.NoError(t, err, "GetAvailablePairs must not error")
|
||||||
|
require.GreaterOrEqual(t, len(availablePairs), 5, "availablePairs must be greater than or equal 5")
|
||||||
|
for _, cp := range availablePairs[:5] {
|
||||||
|
t.Run(cp.String(), func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
_, err := e.GetPublicTicker(t.Context(), optionComboPairToString(cp))
|
||||||
|
assert.NoError(t, err, "GetPublicTicker should not error")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppendCandles(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
_, err := appendCandles(nil, time.Time{})
|
||||||
|
assert.ErrorIs(t, err, kline.ErrNoTimeSeriesDataToConvert)
|
||||||
|
|
||||||
|
candles := &TVChartData{
|
||||||
|
Ticks: []int64{1337},
|
||||||
|
}
|
||||||
|
_, err = appendCandles(candles, time.Time{})
|
||||||
|
assert.ErrorIs(t, err, kline.ErrInsufficientCandleData)
|
||||||
|
|
||||||
|
candles = &TVChartData{
|
||||||
|
Open: []float64{1337},
|
||||||
|
High: []float64{1337},
|
||||||
|
Low: []float64{1337},
|
||||||
|
Close: []float64{1337},
|
||||||
|
Volume: []float64{1337},
|
||||||
|
Ticks: []int64{1337},
|
||||||
|
}
|
||||||
|
resp, err := appendCandles(candles, time.Time{})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, resp, 1)
|
||||||
|
|
||||||
|
candles = &TVChartData{
|
||||||
|
Open: []float64{1337},
|
||||||
|
High: []float64{1337},
|
||||||
|
Low: []float64{1337},
|
||||||
|
Close: []float64{1337},
|
||||||
|
Volume: []float64{1337},
|
||||||
|
Ticks: []int64{1337},
|
||||||
|
}
|
||||||
|
resp, err = appendCandles(candles, time.Unix(1338, 0))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Empty(t, resp)
|
||||||
|
}
|
||||||
|
|||||||
@@ -334,7 +334,7 @@ func (e *Exchange) processUserOrders(respRaw []byte, channels []string) error {
|
|||||||
}
|
}
|
||||||
orderDetails := make([]order.Detail, len(orderData))
|
orderDetails := make([]order.Detail, len(orderData))
|
||||||
for x := range orderData {
|
for x := range orderData {
|
||||||
cp, a, err := e.getAssetPairByInstrument(orderData[x].InstrumentName)
|
a, cp, err := getAssetPairByInstrument(orderData[x].InstrumentName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -390,7 +390,7 @@ func (e *Exchange) processUserOrderChanges(respRaw []byte, channels []string) er
|
|||||||
}
|
}
|
||||||
var cp currency.Pair
|
var cp currency.Pair
|
||||||
var a asset.Item
|
var a asset.Item
|
||||||
cp, a, err = e.getAssetPairByInstrument(changeData.Trades[x].InstrumentName)
|
a, cp, err = getAssetPairByInstrument(changeData.Trades[x].InstrumentName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -424,7 +424,7 @@ func (e *Exchange) processUserOrderChanges(respRaw []byte, channels []string) er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cp, a, err := e.getAssetPairByInstrument(changeData.Orders[x].InstrumentName)
|
a, cp, err := getAssetPairByInstrument(changeData.Orders[x].InstrumentName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -450,7 +450,7 @@ func (e *Exchange) processUserOrderChanges(respRaw []byte, channels []string) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) processQuoteTicker(respRaw []byte, channels []string) error {
|
func (e *Exchange) processQuoteTicker(respRaw []byte, channels []string) error {
|
||||||
cp, a, err := e.getAssetPairByInstrument(channels[1])
|
a, cp, err := getAssetPairByInstrument(channels[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -498,7 +498,7 @@ func (e *Exchange) processTrades(respRaw []byte, channels []string) error {
|
|||||||
for x := range tradesData {
|
for x := range tradesData {
|
||||||
var cp currency.Pair
|
var cp currency.Pair
|
||||||
var a asset.Item
|
var a asset.Item
|
||||||
cp, a, err = e.getAssetPairByInstrument(tradeList[x].InstrumentName)
|
a, cp, err = getAssetPairByInstrument(tradeList[x].InstrumentName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -528,7 +528,7 @@ func (e *Exchange) processIncrementalTicker(respRaw []byte, channels []string) e
|
|||||||
if len(channels) != 2 {
|
if len(channels) != 2 {
|
||||||
return fmt.Errorf("%w, expected format 'incremental_ticker.{instrument_name}', but found %s", errMalformedData, strings.Join(channels, "."))
|
return fmt.Errorf("%w, expected format 'incremental_ticker.{instrument_name}', but found %s", errMalformedData, strings.Join(channels, "."))
|
||||||
}
|
}
|
||||||
cp, a, err := e.getAssetPairByInstrument(channels[1])
|
a, cp, err := getAssetPairByInstrument(channels[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -564,7 +564,7 @@ func (e *Exchange) processInstrumentTicker(respRaw []byte, channels []string) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) processTicker(respRaw []byte, channels []string) error {
|
func (e *Exchange) processTicker(respRaw []byte, channels []string) error {
|
||||||
cp, a, err := e.getAssetPairByInstrument(channels[1])
|
a, cp, err := getAssetPairByInstrument(channels[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -615,7 +615,7 @@ func (e *Exchange) processCandleChart(respRaw []byte, channels []string) error {
|
|||||||
if len(channels) != 4 {
|
if len(channels) != 4 {
|
||||||
return fmt.Errorf("%w, expected format 'chart.trades.{instrument_name}.{resolution}', but found %s", errMalformedData, strings.Join(channels, "."))
|
return fmt.Errorf("%w, expected format 'chart.trades.{instrument_name}.{resolution}', but found %s", errMalformedData, strings.Join(channels, "."))
|
||||||
}
|
}
|
||||||
cp, a, err := e.getAssetPairByInstrument(channels[2])
|
a, cp, err := getAssetPairByInstrument(channels[2])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -649,7 +649,7 @@ func (e *Exchange) processOrderbook(respRaw []byte, channels []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(channels) == 3 {
|
if len(channels) == 3 {
|
||||||
cp, a, err := e.getAssetPairByInstrument(orderbookData.InstrumentName)
|
a, cp, err := getAssetPairByInstrument(orderbookData.InstrumentName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -718,7 +718,7 @@ func (e *Exchange) processOrderbook(respRaw []byte, channels []string) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if len(channels) == 5 {
|
} else if len(channels) == 5 {
|
||||||
cp, a, err := e.getAssetPairByInstrument(orderbookData.InstrumentName)
|
a, cp, err := getAssetPairByInstrument(orderbookData.InstrumentName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ func (e *Exchange) UpdateTicker(ctx context.Context, p currency.Pair, assetType
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
instrumentID := e.formatPairString(assetType, p)
|
instrumentID := formatPairString(assetType, p)
|
||||||
var tickerData *TickerData
|
var tickerData *TickerData
|
||||||
if e.Websocket.IsConnected() {
|
if e.Websocket.IsConnected() {
|
||||||
tickerData, err = e.WSRetrievePublicTicker(ctx, instrumentID)
|
tickerData, err = e.WSRetrievePublicTicker(ctx, instrumentID)
|
||||||
@@ -294,7 +294,7 @@ func (e *Exchange) UpdateOrderbook(ctx context.Context, p currency.Pair, assetTy
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
instrumentID := e.formatPairString(assetType, p)
|
instrumentID := formatPairString(assetType, p)
|
||||||
var obData *Orderbook
|
var obData *Orderbook
|
||||||
if e.Websocket.IsConnected() {
|
if e.Websocket.IsConnected() {
|
||||||
obData, err = e.WSRetrieveOrderbookData(ctx, instrumentID, 50)
|
obData, err = e.WSRetrieveOrderbookData(ctx, instrumentID, 50)
|
||||||
@@ -477,7 +477,7 @@ func (e *Exchange) GetRecentTrades(ctx context.Context, p currency.Pair, assetTy
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
instrumentID := e.formatPairString(assetType, p)
|
instrumentID := formatPairString(assetType, p)
|
||||||
resp := []trade.Data{}
|
resp := []trade.Data{}
|
||||||
var trades *PublicTradesData
|
var trades *PublicTradesData
|
||||||
if e.Websocket.IsConnected() {
|
if e.Websocket.IsConnected() {
|
||||||
@@ -521,7 +521,7 @@ func (e *Exchange) GetHistoricTrades(ctx context.Context, p currency.Pair, asset
|
|||||||
var instrumentID string
|
var instrumentID string
|
||||||
switch assetType {
|
switch assetType {
|
||||||
case asset.Futures, asset.Options, asset.Spot:
|
case asset.Futures, asset.Options, asset.Spot:
|
||||||
instrumentID = e.formatPairString(assetType, p)
|
instrumentID = formatPairString(assetType, p)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("%w asset type %v", asset.ErrNotSupported, assetType)
|
return nil, fmt.Errorf("%w asset type %v", asset.ErrNotSupported, assetType)
|
||||||
}
|
}
|
||||||
@@ -1050,45 +1050,52 @@ func (e *Exchange) GetHistoricCandles(ctx context.Context, pair currency.Pair, a
|
|||||||
case asset.Futures, asset.Spot:
|
case asset.Futures, asset.Spot:
|
||||||
var tradingViewData *TVChartData
|
var tradingViewData *TVChartData
|
||||||
if e.Websocket.IsConnected() {
|
if e.Websocket.IsConnected() {
|
||||||
tradingViewData, err = e.WSRetrievesTradingViewChartData(ctx, e.formatFuturesTradablePair(req.RequestFormatted), intervalString, start, end)
|
tradingViewData, err = e.WSRetrievesTradingViewChartData(ctx, formatFuturesTradablePair(req.RequestFormatted), intervalString, start, end)
|
||||||
} else {
|
} else {
|
||||||
tradingViewData, err = e.GetTradingViewChart(ctx, e.formatFuturesTradablePair(req.RequestFormatted), intervalString, start, end)
|
tradingViewData, err = e.GetTradingViewChart(ctx, formatFuturesTradablePair(req.RequestFormatted), intervalString, start, end)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if len(tradingViewData.Ticks) == 0 {
|
|
||||||
return nil, kline.ErrNoTimeSeriesDataToConvert
|
|
||||||
}
|
}
|
||||||
checkLen := len(tradingViewData.Ticks)
|
listCandles, err := appendCandles(tradingViewData, start)
|
||||||
if len(tradingViewData.Open) != checkLen ||
|
if err != nil {
|
||||||
len(tradingViewData.High) != checkLen ||
|
return nil, err
|
||||||
len(tradingViewData.Low) != checkLen ||
|
|
||||||
len(tradingViewData.Close) != checkLen ||
|
|
||||||
len(tradingViewData.Volume) != checkLen {
|
|
||||||
return nil, fmt.Errorf("%s - %v: invalid trading view chart data received", a, req.RequestFormatted)
|
|
||||||
}
|
|
||||||
listCandles := make([]kline.Candle, 0, len(tradingViewData.Ticks))
|
|
||||||
for x := range tradingViewData.Ticks {
|
|
||||||
timeInfo := time.UnixMilli(tradingViewData.Ticks[x]).UTC()
|
|
||||||
if timeInfo.Before(start) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
listCandles = append(listCandles, kline.Candle{
|
|
||||||
Open: tradingViewData.Open[x],
|
|
||||||
High: tradingViewData.High[x],
|
|
||||||
Low: tradingViewData.Low[x],
|
|
||||||
Close: tradingViewData.Close[x],
|
|
||||||
Volume: tradingViewData.Volume[x],
|
|
||||||
Time: timeInfo,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return req.ProcessResponse(listCandles)
|
return req.ProcessResponse(listCandles)
|
||||||
case asset.OptionCombo, asset.FutureCombo, asset.Options:
|
|
||||||
// TODO: candlestick data for asset item option_combo, future_combo, and option not supported yet
|
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("%w candlestick data for asset type %v", asset.ErrNotSupported, a)
|
return nil, fmt.Errorf("%w candlestick data for asset type %v", asset.ErrNotSupported, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func appendCandles(tradingViewData *TVChartData, start time.Time) ([]kline.Candle, error) {
|
||||||
|
if tradingViewData == nil || len(tradingViewData.Ticks) == 0 {
|
||||||
|
return nil, kline.ErrNoTimeSeriesDataToConvert
|
||||||
|
}
|
||||||
|
checkLen := len(tradingViewData.Ticks)
|
||||||
|
if len(tradingViewData.Open) != checkLen ||
|
||||||
|
len(tradingViewData.High) != checkLen ||
|
||||||
|
len(tradingViewData.Low) != checkLen ||
|
||||||
|
len(tradingViewData.Close) != checkLen ||
|
||||||
|
len(tradingViewData.Volume) != checkLen {
|
||||||
|
return nil, fmt.Errorf("%w: ohlcv len must be equal", kline.ErrInsufficientCandleData)
|
||||||
|
}
|
||||||
|
listCandles := make([]kline.Candle, 0, len(tradingViewData.Ticks))
|
||||||
|
for x := range tradingViewData.Ticks {
|
||||||
|
timeInfo := time.UnixMilli(tradingViewData.Ticks[x]).UTC()
|
||||||
|
if timeInfo.Before(start) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
listCandles = append(listCandles, kline.Candle{
|
||||||
|
Open: tradingViewData.Open[x],
|
||||||
|
High: tradingViewData.High[x],
|
||||||
|
Low: tradingViewData.Low[x],
|
||||||
|
Close: tradingViewData.Close[x],
|
||||||
|
Volume: tradingViewData.Volume[x],
|
||||||
|
Time: timeInfo,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return listCandles, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetHistoricCandlesExtended returns candles between a time period for a set time interval
|
// GetHistoricCandlesExtended returns candles between a time period for a set time interval
|
||||||
func (e *Exchange) GetHistoricCandlesExtended(ctx context.Context, pair currency.Pair, a asset.Item, interval kline.Interval, start, end time.Time) (*kline.Item, error) {
|
func (e *Exchange) GetHistoricCandlesExtended(ctx context.Context, pair currency.Pair, a asset.Item, interval kline.Interval, start, end time.Time) (*kline.Item, error) {
|
||||||
req, err := e.GetKlineExtendedRequest(pair, a, interval, start, end)
|
req, err := e.GetKlineExtendedRequest(pair, a, interval, start, end)
|
||||||
@@ -1105,39 +1112,19 @@ func (e *Exchange) GetHistoricCandlesExtended(ctx context.Context, pair currency
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if e.Websocket.IsConnected() {
|
if e.Websocket.IsConnected() {
|
||||||
tradingViewData, err = e.WSRetrievesTradingViewChartData(ctx, e.formatFuturesTradablePair(req.RequestFormatted), intervalString, req.RangeHolder.Ranges[x].Start.Time, req.RangeHolder.Ranges[x].End.Time)
|
tradingViewData, err = e.WSRetrievesTradingViewChartData(ctx, formatFuturesTradablePair(req.RequestFormatted), intervalString, req.RangeHolder.Ranges[x].Start.Time, req.RangeHolder.Ranges[x].End.Time)
|
||||||
} else {
|
} else {
|
||||||
tradingViewData, err = e.GetTradingViewChart(ctx, e.formatFuturesTradablePair(req.RequestFormatted), intervalString, req.RangeHolder.Ranges[x].Start.Time, req.RangeHolder.Ranges[x].End.Time)
|
tradingViewData, err = e.GetTradingViewChart(ctx, formatFuturesTradablePair(req.RequestFormatted), intervalString, req.RangeHolder.Ranges[x].Start.Time, req.RangeHolder.Ranges[x].End.Time)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
checkLen := len(tradingViewData.Ticks)
|
timeSeries, err = appendCandles(tradingViewData, start)
|
||||||
if len(tradingViewData.Open) != checkLen ||
|
if err != nil {
|
||||||
len(tradingViewData.High) != checkLen ||
|
return nil, err
|
||||||
len(tradingViewData.Low) != checkLen ||
|
|
||||||
len(tradingViewData.Close) != checkLen ||
|
|
||||||
len(tradingViewData.Volume) != checkLen {
|
|
||||||
return nil, fmt.Errorf("%s - %v: invalid trading view chart data received", a, e.formatFuturesTradablePair(req.RequestFormatted))
|
|
||||||
}
|
|
||||||
for i := range tradingViewData.Ticks {
|
|
||||||
timeInfo := time.UnixMilli(tradingViewData.Ticks[i]).UTC()
|
|
||||||
if timeInfo.Before(start) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
timeSeries = append(timeSeries, kline.Candle{
|
|
||||||
Open: tradingViewData.Open[i],
|
|
||||||
High: tradingViewData.High[i],
|
|
||||||
Low: tradingViewData.Low[i],
|
|
||||||
Close: tradingViewData.Close[i],
|
|
||||||
Volume: tradingViewData.Volume[i],
|
|
||||||
Time: timeInfo,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return req.ProcessResponse(timeSeries)
|
return req.ProcessResponse(timeSeries)
|
||||||
case asset.OptionCombo, asset.FutureCombo, asset.Options:
|
|
||||||
// TODO: candlestick data for asset item option_combo, future_combo, and option not supported yet
|
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("%w candlestick data for asset type %v", asset.ErrNotSupported, a)
|
return nil, fmt.Errorf("%w candlestick data for asset type %v", asset.ErrNotSupported, a)
|
||||||
}
|
}
|
||||||
@@ -1352,7 +1339,7 @@ func (e *Exchange) GetOpenInterest(ctx context.Context, k ...key.PairAsset) ([]f
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cp := k[i].Pair().Format(pFmt)
|
cp := k[i].Pair().Format(pFmt)
|
||||||
p := e.formatPairString(k[i].Asset, cp)
|
p := formatPairString(k[i].Asset, cp)
|
||||||
var oi []BookSummaryData
|
var oi []BookSummaryData
|
||||||
if e.Websocket.IsConnected() {
|
if e.Websocket.IsConnected() {
|
||||||
oi, err = e.WSRetrieveBookSummaryByInstrument(ctx, p)
|
oi, err = e.WSRetrieveBookSummaryByInstrument(ctx, p)
|
||||||
@@ -1446,7 +1433,7 @@ func (e *Exchange) GetLatestFundingRates(ctx context.Context, r *fundingrate.Lat
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cp := r.Pair.Format(pFmt)
|
cp := r.Pair.Format(pFmt)
|
||||||
p := e.formatPairString(r.Asset, cp)
|
p := formatPairString(r.Asset, cp)
|
||||||
var fri []FundingRateHistory
|
var fri []FundingRateHistory
|
||||||
fri, err = e.GetFundingRateHistory(ctx, p, time.Now().Add(-time.Hour*16), time.Now())
|
fri, err = e.GetFundingRateHistory(ctx, p, time.Now().Add(-time.Hour*16), time.Now())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1503,7 +1490,7 @@ func (e *Exchange) GetHistoricalFundingRates(ctx context.Context, r *fundingrate
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cp := r.Pair.Format(pFmt)
|
cp := r.Pair.Format(pFmt)
|
||||||
p := e.formatPairString(r.Asset, cp)
|
p := formatPairString(r.Asset, cp)
|
||||||
ed := r.EndDate
|
ed := r.EndDate
|
||||||
|
|
||||||
var fundingRates []fundingrate.Rate
|
var fundingRates []fundingrate.Rate
|
||||||
@@ -1555,12 +1542,14 @@ func (e *Exchange) GetHistoricalFundingRates(ctx context.Context, r *fundingrate
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) formatPairString(assetType asset.Item, pair currency.Pair) string {
|
func formatPairString(assetType asset.Item, pair currency.Pair) string {
|
||||||
switch assetType {
|
switch assetType {
|
||||||
case asset.Futures:
|
case asset.Futures:
|
||||||
return e.formatFuturesTradablePair(pair)
|
return formatFuturesTradablePair(pair)
|
||||||
case asset.Options:
|
case asset.Options:
|
||||||
return e.optionPairToString(pair)
|
return optionPairToString(pair)
|
||||||
|
case asset.OptionCombo:
|
||||||
|
return optionComboPairToString(pair)
|
||||||
}
|
}
|
||||||
return pair.String()
|
return pair.String()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user