mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-22 07:26:50 +00:00
Bitfinex: Implement leaderboard API (#458)
* Bitfinex: Implement leaderboard API * Expand test coverage * fix grammer
This commit is contained in:
@@ -57,6 +57,7 @@ const (
|
||||
bitfinexMarginClose = "funding/close"
|
||||
bitfinexLendbook = "lendbook/"
|
||||
bitfinexLends = "lends/"
|
||||
bitfinexLeaderboard = "rankings"
|
||||
|
||||
// Version 2 API endpoints
|
||||
bitfinexAPIVersion2 = "/v2/"
|
||||
@@ -506,11 +507,73 @@ func (b *Bitfinex) GetLiquidationFeed() error {
|
||||
return common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// GetLeaderBoard returns leaderboard standings for unrealized
|
||||
// profit (period delta), unrealized profit (inception), volume, and realized
|
||||
// profit.
|
||||
func (b *Bitfinex) GetLeaderBoard() error {
|
||||
return common.ErrNotYetImplemented
|
||||
// GetLeaderboard returns leaderboard standings for unrealized profit (period
|
||||
// delta), unrealized profit (inception), volume, and realized profit.
|
||||
// Allowed key values: "plu_diff" for unrealized profit (period delta), "plu"
|
||||
// for unrealized profit (inception); "vol" for volume; "plr" for realized
|
||||
// profit
|
||||
// Allowed time frames are 3h, 1w and 1M
|
||||
// Allowed symbols are trading pairs (e.g. tBTCUSD, tETHUSD and tGLOBAL:USD)
|
||||
func (b *Bitfinex) GetLeaderboard(key, timeframe, symbol string, sort, limit int, start, end string) ([]LeaderboardEntry, error) {
|
||||
validLeaderboardKey := func(input string) bool {
|
||||
switch input {
|
||||
case LeaderboardUnrealisedProfitPeriodDelta,
|
||||
LeaderboardUnrealisedProfitInception,
|
||||
LeaderboardVolume,
|
||||
LeaderbookRealisedProfit:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if !validLeaderboardKey(key) {
|
||||
return nil, errors.New("invalid leaderboard key")
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("%s/%s:%s:%s/hist", b.API.Endpoints.URL+bitfinexAPIVersion2+bitfinexLeaderboard,
|
||||
key,
|
||||
timeframe,
|
||||
symbol)
|
||||
vals := url.Values{}
|
||||
if sort != 0 {
|
||||
vals.Set("sort", strconv.Itoa(sort))
|
||||
}
|
||||
if limit != 0 {
|
||||
vals.Set("limit", strconv.Itoa(limit))
|
||||
}
|
||||
if start != "" {
|
||||
vals.Set("start", start)
|
||||
}
|
||||
if end != "" {
|
||||
vals.Set("end", end)
|
||||
}
|
||||
path = common.EncodeURLValues(path, vals)
|
||||
var resp []interface{}
|
||||
if err := b.SendHTTPRequest(path, &resp, leaderBoardReqRate); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parseTwitterHandle := func(i interface{}) string {
|
||||
r, ok := i.(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
var result []LeaderboardEntry
|
||||
for x := range resp {
|
||||
r := resp[x].([]interface{})
|
||||
result = append(result, LeaderboardEntry{
|
||||
Timestamp: time.Unix(0, int64(r[0].(float64))*int64(time.Millisecond)),
|
||||
Username: r[2].(string),
|
||||
Ranking: int(r[3].(float64)),
|
||||
Value: r[6].(float64),
|
||||
TwitterHandle: parseTwitterHandle(r[9]),
|
||||
})
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetMarketAveragePrice calculates the average execution price for Trading or
|
||||
|
||||
@@ -159,6 +159,41 @@ func TestGetCandles(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLeaderboard(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Test invalid key
|
||||
_, err := b.GetLeaderboard("", "", "", 0, 0, "", "")
|
||||
if err == nil {
|
||||
t.Error("an error should have been thrown for an invalid key")
|
||||
}
|
||||
// Test default
|
||||
_, err = b.GetLeaderboard(LeaderboardUnrealisedProfitInception,
|
||||
"1M",
|
||||
"tGLOBAL:USD",
|
||||
0,
|
||||
0,
|
||||
"",
|
||||
"")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Test params
|
||||
var result []LeaderboardEntry
|
||||
result, err = b.GetLeaderboard(LeaderboardUnrealisedProfitInception,
|
||||
"1M",
|
||||
"tGLOBAL:USD",
|
||||
-1,
|
||||
1000,
|
||||
"1582695181661",
|
||||
"1583299981661")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result) == 0 {
|
||||
t.Error("should have retrieved leaderboard data")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccountFees(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.SkipNow()
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package bitfinex
|
||||
|
||||
import "time"
|
||||
|
||||
// AcceptedOrderType defines the accepted market types, exchange strings denote
|
||||
// non-contract order types.
|
||||
var AcceptedOrderType = []string{"market", "limit", "stop", "trailing-stop",
|
||||
@@ -394,6 +396,23 @@ type Candle struct {
|
||||
Volume float64
|
||||
}
|
||||
|
||||
// Leaderboard keys
|
||||
const (
|
||||
LeaderboardUnrealisedProfitPeriodDelta = "plu_diff"
|
||||
LeaderboardUnrealisedProfitInception = "plu"
|
||||
LeaderboardVolume = "vol"
|
||||
LeaderbookRealisedProfit = "plr"
|
||||
)
|
||||
|
||||
// LeaderboardEntry holds leaderboard data
|
||||
type LeaderboardEntry struct {
|
||||
Timestamp time.Time
|
||||
Username string
|
||||
Ranking int
|
||||
Value float64
|
||||
TwitterHandle string
|
||||
}
|
||||
|
||||
// WebsocketTicker holds ticker information
|
||||
type WebsocketTicker struct {
|
||||
Bid float64
|
||||
|
||||
Reference in New Issue
Block a user