Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
… into poloniex
  • Loading branch information
samuael committed Jan 5, 2025
2 parents 6b0e134 + 4fcee84 commit 29df848
Show file tree
Hide file tree
Showing 11 changed files with 311 additions and 531 deletions.
21 changes: 16 additions & 5 deletions cmd/documentation/exchanges_templates/deribit.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,23 @@ if err != nil {
}
```

### How to do Websocket public/private calls
### Subscriptions

```go
// Exchanges will be abstracted out in further updates and examples will be
// supplied then
```
All default subscriptions are for all enabled assets.

Default Public Subscriptions:
- Candles ( Timeframe: 1 day )
- Orderbook ( Full depth @ Interval: 100ms )
- Ticker ( Interval: 100ms )
- All Trades ( Interval: 100ms )

Default Authenticated Subscriptions:
- My Account Orders
- My Account Trades

kline.Raw Interval configurable for a raw orderbook subscription when authenticated

Subscriptions are subject to enabled assets and pairs.

### Please click GoDocs chevron above to view current GoDoc information for this package
{{template "contributions"}}
Expand Down
21 changes: 16 additions & 5 deletions exchanges/deribit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,23 @@ if err != nil {
}
```

### How to do Websocket public/private calls
### Subscriptions

```go
// Exchanges will be abstracted out in further updates and examples will be
// supplied then
```
All default subscriptions are for all enabled assets.

Default Public Subscriptions:
- Candles ( Timeframe: 1 day )
- Orderbook ( Full depth @ Interval: 100ms )
- Ticker ( Interval: 100ms )
- All Trades ( Interval: 100ms )

Default Authenticated Subscriptions:
- My Account Orders
- My Account Trades

kline.Raw Interval configurable for a raw orderbook subscription when authenticated

Subscriptions are subject to enabled assets and pairs.

### Please click GoDocs chevron above to view current GoDoc information for this package

Expand Down
33 changes: 12 additions & 21 deletions exchanges/deribit/deribit.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"fmt"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
"time"
Expand All @@ -28,12 +27,6 @@ type Deribit struct {
exchange.Base
}

var (
// optionRegex compiles optionDecimalRegex at startup and is used to help set
// option currency lower-case d eg MATIC-USDC-3JUN24-0d64-P
optionRegex *regexp.Regexp
)

const (
deribitAPIVersion = "/api/v2"
tradeBaseURL = "https://www.deribit.com/"
Expand All @@ -43,8 +36,7 @@ const (
tradeFuturesCombo = "futures-spreads/"
tradeOptionsCombo = "combos/"

perpString = "PERPETUAL"
optionDecimalRegex = `\d+(D)\d+`
perpString = "PERPETUAL"

// Public endpoints
// Market Data
Expand Down Expand Up @@ -2837,20 +2829,19 @@ func (d *Deribit) formatFuturesTradablePair(pair currency.Pair) string {
return instrumentID
}

// optionPairToString to format and return an Options currency pairs with the following format: MATIC_USDC-6APR24-0d98-P
// it has both uppercase or lowercase characters, which we can not achieve with the Upper=true or Upper=false
// optionPairToString formats an options pair as: SYMBOL-EXPIRE-STRIKE-TYPE
// SYMBOL may be a currency (BTC) or a pair (XRP_USDC)
// EXPIRE is DDMMMYY
// STRIKE may include a d for decimal point in linear options
// TYPE is Call or Put
func (d *Deribit) optionPairToString(pair currency.Pair) string {
subCodes := strings.Split(pair.Quote.String(), currency.DashDelimiter)
initialDelimiter := currency.DashDelimiter
if subCodes[0] == "USDC" {
q := pair.Quote.String()
if strings.HasPrefix(q, "USDC") && len(q) > 11 { // Linear option
initialDelimiter = currency.UnderscoreDelimiter
// Replace a capital D with d for decimal place in Strike price
// Char 11 is either the hyphen before Strike price or first digit
q = q[:11] + strings.Replace(q[11:], "D", "d", -1)
}
for i := range subCodes {
if match := optionRegex.MatchString(subCodes[i]); match {
subCodes[i] = strings.ToLower(subCodes[i])
break
}
}

return pair.Base.String() + initialDelimiter + strings.Join(subCodes, currency.DashDelimiter)
return pair.Base.String() + initialDelimiter + q
}
92 changes: 81 additions & 11 deletions exchanges/deribit/deribit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
"github.com/thrasher-corp/gocryptotrader/exchanges/subscription"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
"github.com/thrasher-corp/gocryptotrader/exchanges/trade"
testexch "github.com/thrasher-corp/gocryptotrader/internal/testing/exchange"
testsubs "github.com/thrasher-corp/gocryptotrader/internal/testing/subscriptions"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)

Expand Down Expand Up @@ -3266,11 +3268,82 @@ func setupWs() {
}
}

func TestGenerateDefaultSubscriptions(t *testing.T) {
func TestGenerateSubscriptions(t *testing.T) {
t.Parallel()
result, err := d.GenerateDefaultSubscriptions()

d := new(Deribit) //nolint:govet // Intentional lexical scope shadow
require.NoError(t, testexch.Setup(d), "Test instance Setup must not error")

d.Websocket.SetCanUseAuthenticatedEndpoints(true)
subs, err := d.generateSubscriptions()
require.NoError(t, err)
assert.NotNil(t, result)
exp := subscription.List{}
for _, s := range d.Features.Subscriptions {
for _, a := range d.GetAssetTypes(true) {
if !d.IsAssetWebsocketSupported(a) {
continue
}
pairs, err := d.GetEnabledPairs(a)
require.NoErrorf(t, err, "GetEnabledPairs %s must not error", a)
s := s.Clone() //nolint:govet // Intentional lexical scope shadow
s.Asset = a
if isSymbolChannel(s) {
for i, p := range pairs {
s := s.Clone() //nolint:govet // Intentional lexical scope shadow
s.QualifiedChannel = channelName(s) + "." + p.String()
if s.Interval != 0 {
s.QualifiedChannel += "." + channelInterval(s)
}
s.Pairs = pairs[i : i+1]
exp = append(exp, s)
}
} else {
s.Pairs = pairs
s.QualifiedChannel = channelName(s)
exp = append(exp, s)
}
}
}
testsubs.EqualLists(t, exp, subs)
}

func TestChannelInterval(t *testing.T) {
t.Parallel()

for _, i := range []int64{1, 3, 5, 10, 15, 30, 60, 120, 180, 360, 720} {
a := channelInterval(&subscription.Subscription{Channel: subscription.CandlesChannel, Interval: kline.Interval(i * int64(time.Minute))})
assert.Equal(t, strconv.Itoa(int(i)), a)
}

a := channelInterval(&subscription.Subscription{Channel: subscription.CandlesChannel, Interval: kline.OneDay})
assert.Equal(t, "1D", a)

assert.Panics(t, func() {
channelInterval(&subscription.Subscription{Channel: subscription.CandlesChannel, Interval: kline.OneMonth})
})

a = channelInterval(&subscription.Subscription{Channel: subscription.OrderbookChannel, Interval: kline.ThousandMilliseconds})
assert.Equal(t, "agg2", a, "1 second should expand to agg2")

a = channelInterval(&subscription.Subscription{Channel: subscription.OrderbookChannel, Interval: kline.HundredMilliseconds})
assert.Equal(t, "100ms", a, "100ms should expand correctly")

a = channelInterval(&subscription.Subscription{Channel: subscription.OrderbookChannel, Interval: kline.Raw})
assert.Equal(t, "raw", a, "raw should expand correctly")

assert.Panics(t, func() {
channelInterval(&subscription.Subscription{Channel: subscription.OrderbookChannel, Interval: kline.OneMonth})
})

a = channelInterval(&subscription.Subscription{Channel: userAccessLogChannel})
assert.Empty(t, a, "Anything else should return empty")
}

func TestChannelName(t *testing.T) {
t.Parallel()
assert.Equal(t, tickerChannel, channelName(&subscription.Subscription{Channel: subscription.TickerChannel}))
assert.Equal(t, userLockChannel, channelName(&subscription.Subscription{Channel: userLockChannel}))
assert.Panics(t, func() { channelName(&subscription.Subscription{Channel: "wibble"}) }, "Unknown channels should panic")
}

func TestFetchTicker(t *testing.T) {
Expand Down Expand Up @@ -3681,18 +3754,15 @@ func TestFormatFuturesTradablePair(t *testing.T) {

func TestOptionPairToString(t *testing.T) {
t.Parallel()
optionsList := map[currency.Pair]string{
for pair, exp := range map[currency.Pair]string{
{Delimiter: currency.DashDelimiter, Base: currency.BTC, Quote: currency.NewCode("30MAY24-61000-C")}: "BTC-30MAY24-61000-C",
{Delimiter: currency.DashDelimiter, Base: currency.ETH, Quote: currency.NewCode("1JUN24-3200-P")}: "ETH-1JUN24-3200-P",
{Delimiter: currency.DashDelimiter, Base: currency.SOL, Quote: currency.NewCode("USDC-31MAY24-162-P")}: "SOL_USDC-31MAY24-162-P",
{Delimiter: currency.DashDelimiter, Base: currency.MATIC, Quote: currency.NewCode("USDC-6APR24-0d98-P")}: "MATIC_USDC-6APR24-0d98-P",
}
for pair, instrumentID := range optionsList {
t.Run(instrumentID, func(t *testing.T) {
t.Parallel()
instrument := d.optionPairToString(pair)
require.Equal(t, instrumentID, instrument)
})
{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",
} {
assert.Equal(t, exp, d.optionPairToString(pair), "optionPairToString should return correctly")
}
}

Expand Down
Loading

0 comments on commit 29df848

Please sign in to comment.