Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.knowm.xchange.binance.dto.BinanceException;
import org.knowm.xchange.binance.dto.marketdata.BinanceAggTrades;
import org.knowm.xchange.binance.dto.marketdata.BinanceFundingRate;
import org.knowm.xchange.binance.dto.marketdata.BinanceFundingRateHistory;
import org.knowm.xchange.binance.dto.marketdata.BinanceFundingRateInfo;
import org.knowm.xchange.binance.dto.marketdata.BinanceOrderbook;
import org.knowm.xchange.binance.dto.marketdata.BinanceTicker24h;
Expand Down Expand Up @@ -154,4 +155,23 @@ List<Object[]> klines(
@QueryParam("startTime") Long startTime,
@QueryParam("endTime") Long endTime)
throws IOException, BinanceException;

/**
* Get Funding Rate History
*
* @param symbol optional, instrument
* @param limit optional, Default 100;
* @param startTime optional, Timestamp in ms to get funding rate from INCLUSIVE.
* @param endTime optional, Timestamp in ms to get funding rate until INCLUSIVE.
* @throws IOException
* @throws BinanceException
*/
@GET
@Path("fapi/v1/fundingRate")
List<BinanceFundingRateHistory> fundingRateHistory(
@QueryParam("symbol") String symbol,
@QueryParam("startTime") Long startTime,
@QueryParam("endTime") Long endTime,
@QueryParam("limit") Integer limit)
throws IOException, BinanceException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public final class BinanceResilience {

// Futures specified
public static final String ORDERS_PER_MINUTE_RATE_LIMITER = "ordersPerMINUTE";
public static final String FUNDING_RATE_AND_INFO_RATE_LIMITER = "fundingRateAndInfo";

private BinanceResilience() {}

Expand Down Expand Up @@ -68,6 +69,14 @@ public static ResilienceRegistries createRegistries() {

public static ResilienceRegistries createRegistriesFuture() {
ResilienceRegistries registries = new ResilienceRegistries();
registries
.rateLimiters()
.rateLimiter(
FUNDING_RATE_AND_INFO_RATE_LIMITER,
RateLimiterConfig.from(registries.rateLimiters().getDefaultConfig())
.limitRefreshPeriod(Duration.ofMinutes(5))
.limitForPeriod(500)
.build());
registries
.rateLimiters()
.rateLimiter(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.knowm.xchange.binance.dto.marketdata;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
import java.time.Instant;
import lombok.Getter;
import lombok.ToString;
import org.knowm.xchange.binance.BinanceAdapters;
import org.knowm.xchange.instrument.Instrument;

@Getter
@ToString
public class BinanceFundingRateHistory {

private final Instrument instrument;
private final BigDecimal fundingRate;
private final Instant fundingTime;
private final BigDecimal markPrice;

public BinanceFundingRateHistory(
@JsonProperty("symbol") String symbol,
@JsonProperty("fundingRate") BigDecimal fundingRate,
@JsonProperty("fundingTime") long fundingTime,
@JsonProperty("markPrice") BigDecimal markPrice) {
this.instrument = BinanceAdapters.adaptSymbol(symbol, true);
this.fundingRate = fundingRate;
this.fundingTime = Instant.ofEpochMilli(fundingTime);
this.markPrice = markPrice;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@
import org.knowm.xchange.binance.BinanceErrorAdapter;
import org.knowm.xchange.binance.BinanceExchange;
import org.knowm.xchange.binance.dto.BinanceException;
import org.knowm.xchange.binance.dto.marketdata.BinanceFundingRateHistory;
import org.knowm.xchange.binance.dto.marketdata.BinanceOrderbook;
import org.knowm.xchange.binance.dto.marketdata.BinanceTicker24h;
import org.knowm.xchange.client.ResilienceRegistries;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.derivative.FuturesContract;
import org.knowm.xchange.dto.Order.OrderType;
import org.knowm.xchange.dto.marketdata.*;
import org.knowm.xchange.dto.marketdata.FundingRate;
import org.knowm.xchange.dto.marketdata.FundingRates;
import org.knowm.xchange.dto.marketdata.OrderBook;
import org.knowm.xchange.dto.marketdata.Ticker;
import org.knowm.xchange.dto.marketdata.Trades;
import org.knowm.xchange.dto.meta.ExchangeHealth;
import org.knowm.xchange.dto.trade.LimitOrder;
import org.knowm.xchange.exceptions.ExchangeException;
Expand Down Expand Up @@ -146,6 +151,10 @@ private OrderBook getBinanceOrderBook(Instrument instrument, Object... args) thr
}
}

public List<BinanceFundingRateHistory> getFundingRateHistory(Instrument instrument, Long startTime, Long endTime, Integer limit) throws IOException {
return fundingRateHistoryRaw(instrument, startTime, endTime, limit);
}

public static OrderBook convertOrderBook(BinanceOrderbook ob, Instrument pair) {
List<LimitOrder> bids =
ob.bids.entrySet().stream()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.knowm.xchange.binance.service;

import static org.knowm.xchange.binance.BinanceResilience.FUNDING_RATE_AND_INFO_RATE_LIMITER;
import static org.knowm.xchange.binance.BinanceResilience.REQUEST_WEIGHT_RATE_LIMITER;

import java.io.IOException;
Expand All @@ -9,6 +10,7 @@
import org.knowm.xchange.binance.BinanceExchange;
import org.knowm.xchange.binance.dto.marketdata.BinanceAggTrades;
import org.knowm.xchange.binance.dto.marketdata.BinanceFundingRate;
import org.knowm.xchange.binance.dto.marketdata.BinanceFundingRateHistory;
import org.knowm.xchange.binance.dto.marketdata.BinanceFundingRateInfo;
import org.knowm.xchange.binance.dto.marketdata.BinanceKline;
import org.knowm.xchange.binance.dto.marketdata.BinanceOrderbook;
Expand Down Expand Up @@ -171,6 +173,7 @@ public BinanceFundingRate getBinanceFundingRate(Instrument instrument) throws IO

public List<BinanceFundingRateInfo> getBinanceFundingRateInfo() throws IOException {
return decorateApiCall(() -> binanceFutures.fundingRateInfo())
.withRateLimiter(rateLimiter(FUNDING_RATE_AND_INFO_RATE_LIMITER))
.withRetry(retry("fundingRate"))
.call();
}
Expand All @@ -195,6 +198,13 @@ public List<BinancePriceQuantity> tickerAllBookTickers() throws IOException {
.call();
}

public List<BinanceFundingRateHistory> fundingRateHistoryRaw(Instrument instrument, Long startTime, Long endTime, Integer limit) throws IOException {
return decorateApiCall(() -> binanceFutures.fundingRateHistory(BinanceAdapters.toSymbol(instrument), startTime, endTime, limit))
.withRetry(retry("fundingRateHistory"))
.withRateLimiter(rateLimiter(FUNDING_RATE_AND_INFO_RATE_LIMITER))
.call();
}

protected int depthPermits(Integer limit) {
if (limit == null || limit <= 100) {
return 5;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
import org.knowm.xchange.Exchange;
import org.knowm.xchange.ExchangeFactory;
import org.knowm.xchange.ExchangeSpecification;
import org.knowm.xchange.binance.dto.marketdata.BinanceFundingRateHistory;
import org.knowm.xchange.binance.dto.trade.BinanceCancelOrderParams;
import org.knowm.xchange.binance.dto.trade.BinanceQueryOrderParams;
import org.knowm.xchange.binance.dto.trade.BinanceTradeHistoryParams;
import org.knowm.xchange.binance.service.BinanceAccountService;
import org.knowm.xchange.binance.service.BinanceMarketDataService;
import org.knowm.xchange.derivative.FuturesContract;
import org.knowm.xchange.dto.Order;
import org.knowm.xchange.dto.account.AccountInfo;
Expand Down Expand Up @@ -87,6 +89,9 @@ public void binanceFutureMarketDataService() throws IOException {
fundingRates
.getFundingRates()
.forEach(fundingRate -> System.out.println(fundingRate.toString()));
List<BinanceFundingRateHistory> fundingRateHistory = ((BinanceMarketDataService) binanceExchange.getMarketDataService())
.getFundingRateHistory(instrument, System.currentTimeMillis() - 24 * 60 * 60 * 1000, System.currentTimeMillis(), null);
fundingRateHistory.forEach(fundingRate -> System.out.println(fundingRate.toString()));
}

@Test
Expand Down
14 changes: 14 additions & 0 deletions xchange-bybit/src/main/java/org/knowm/xchange/bybit/Bybit.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import java.io.IOException;
import org.knowm.xchange.bybit.dto.BybitCategorizedPayload;
import org.knowm.xchange.bybit.dto.BybitResult;
import org.knowm.xchange.bybit.dto.marketdata.BybitOrderbook;
import org.knowm.xchange.bybit.dto.marketdata.BybitFundingRateHistoryRaw;
import org.knowm.xchange.bybit.dto.marketdata.instruments.BybitInstrumentInfo;
import org.knowm.xchange.bybit.dto.marketdata.instruments.BybitInstrumentsInfo;
import org.knowm.xchange.bybit.dto.marketdata.tickers.BybitTicker;
Expand Down Expand Up @@ -54,4 +56,16 @@ BybitResult<BybitInstrumentsInfo<BybitInstrumentInfo>> getInstrumentsInfo(
@Path("/tickers")
BybitResult<BybitTickers<BybitTicker>> getTickers(@QueryParam("category") String category)
throws IOException, BybitException;

/**
* @apiSpec <a href="https://bybit-exchange.github.io/docs/v5/market/history-fund-rate">API</a>
*/
@GET
@Path("/funding/history")
BybitResult<BybitCategorizedPayload<BybitFundingRateHistoryRaw>> getFundingHistory(@QueryParam("category") String category,
@QueryParam("symbol") String symbol,
@QueryParam("startTime") Long startTime,
@QueryParam("endTime") Long endTime,
@QueryParam("limit") Integer limit)
throws IOException, BybitException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.knowm.xchange.bybit.dto.marketdata;

import java.math.BigDecimal;
import java.time.Instant;
import lombok.Getter;
import org.knowm.xchange.instrument.Instrument;

@Getter
public class BybitFundingRateHistory {

private final Instrument instrument;

private final BigDecimal fundingRate;

private final Instant fundingRateTimestamp;

public BybitFundingRateHistory(Instrument instrument, BigDecimal fundingRate, Instant fundingRateTimestamp) {
this.instrument = instrument;
this.fundingRate = fundingRate;
this.fundingRateTimestamp = fundingRateTimestamp;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.knowm.xchange.bybit.dto.marketdata;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
import java.time.Instant;
import lombok.Getter;
import lombok.ToString;

@Getter
@ToString
public class BybitFundingRateHistoryRaw {

private final String instrument;

private final BigDecimal fundingRate;

private final Instant fundingRateTimestamp;

public BybitFundingRateHistoryRaw(@JsonProperty("symbol") String instrument, @JsonProperty("fundingRate") BigDecimal fundingRate, @JsonProperty("fundingRateTimestamp") long fundingRateTimestamp) {
this.instrument = instrument;
this.fundingRate = fundingRate;
this.fundingRateTimestamp = Instant.ofEpochMilli(fundingRateTimestamp);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import org.knowm.xchange.bybit.BybitAdapters;
import org.knowm.xchange.bybit.BybitExchange;
import org.knowm.xchange.bybit.dto.BybitCategory;
import org.knowm.xchange.bybit.dto.BybitResult;
import org.knowm.xchange.bybit.dto.marketdata.BybitOrderbook;
import org.knowm.xchange.bybit.dto.marketdata.BybitFundingRateHistory;
import org.knowm.xchange.bybit.dto.marketdata.BybitFundingRateHistoryRaw;
import org.knowm.xchange.bybit.dto.marketdata.tickers.BybitTicker;
import org.knowm.xchange.bybit.dto.marketdata.tickers.BybitTickers;
import org.knowm.xchange.bybit.dto.marketdata.tickers.linear.BybitLinearInverseTicker;
Expand Down Expand Up @@ -143,4 +146,17 @@ public static OrderBook convertOrderBook(BybitOrderbook ob, Instrument pair) {
return new OrderBook(
Date.from(Instant.ofEpochMilli(ob.getTimestamp())), asks, bids);
}

public List<BybitFundingRateHistory> getFundingRateHistory(Instrument instrument, Long startTime, Long endTime, Integer limit) throws IOException {
BybitCategory category = BybitAdapters.getCategory(instrument);
List<BybitFundingRateHistoryRaw> raw = getFundingRateHistoryRaw(instrument, startTime, endTime, limit);
List<BybitFundingRateHistory> result = new ArrayList<>();
for (BybitFundingRateHistoryRaw entry : raw) {
Instrument converted = BybitAdapters.convertBybitSymbolToInstrument(entry.getInstrument(), category);
result.add(new BybitFundingRateHistory(converted, entry.getFundingRate(), entry.getFundingRateTimestamp()));
}
// sort, oldest first
result.sort(Comparator.comparingLong(s -> s.getFundingRateTimestamp().toEpochMilli()));
return result;
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package org.knowm.xchange.bybit.service;

import java.io.IOException;
import java.util.List;
import org.knowm.xchange.bybit.BybitAdapters;
import org.knowm.xchange.bybit.BybitExchange;
import org.knowm.xchange.bybit.dto.BybitCategory;
import org.knowm.xchange.bybit.dto.BybitResult;
import org.knowm.xchange.bybit.dto.marketdata.BybitOrderbook;
import org.knowm.xchange.bybit.dto.marketdata.BybitFundingRateHistoryRaw;
import org.knowm.xchange.bybit.dto.marketdata.instruments.BybitInstrumentInfo;
import org.knowm.xchange.bybit.dto.marketdata.instruments.BybitInstrumentsInfo;
import org.knowm.xchange.bybit.dto.marketdata.tickers.BybitTicker;
import org.knowm.xchange.bybit.dto.marketdata.tickers.BybitTickers;
import org.knowm.xchange.client.ResilienceRegistries;
import org.knowm.xchange.instrument.Instrument;

public class BybitMarketDataServiceRaw extends BybitBaseService {

Expand Down Expand Up @@ -63,4 +66,8 @@ public BybitResult<BybitOrderbook> getOrderbook(
}
return result;
}

public List<BybitFundingRateHistoryRaw> getFundingRateHistoryRaw(Instrument instrument, Long startTime, Long endTime, Integer limit) throws IOException {
return bybit.getFundingHistory(BybitAdapters.getCategory(instrument).getValue(), BybitAdapters.convertToBybitSymbol(instrument), startTime, endTime, limit).getResult().getList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
import static org.assertj.core.api.Assertions.assertThat;

import java.math.BigDecimal;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.knowm.xchange.Exchange;
import org.knowm.xchange.bybit.dto.marketdata.BybitFundingRateHistory;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.derivative.FuturesContract;
import org.knowm.xchange.dto.marketdata.OrderBook;
import org.knowm.xchange.dto.marketdata.Ticker;
import org.knowm.xchange.instrument.Instrument;
import org.knowm.xchange.service.marketdata.MarketDataService;

public class BybitMarketDataServiceTest extends BaseWiremockTest {
Expand Down Expand Up @@ -49,7 +53,7 @@ public void testGetTickerWithInverseArg() throws Exception {
public void testGetTickerWithSpotArg() throws Exception {
initGetStub("/v5/market/tickers", "/getTickerSpot.json5");

Ticker ticker = marketDataService.getTicker(CurrencyPair.BTC_USD);
Ticker ticker = marketDataService.getTicker((Instrument) CurrencyPair.BTC_USD);

assertThat(ticker.getInstrument().toString()).isEqualTo("BTC/USD");
assertThat(ticker.getOpen()).isEqualTo(new BigDecimal("20393.48"));
Expand Down Expand Up @@ -79,4 +83,17 @@ public void testGetOrderBook() throws Exception {
assertThat(orderBook.getBids().get(0).getInstrument()).isEqualTo(CurrencyPair.BTC_USD);
assertThat(orderBook.getAsks().get(0).getLimitPrice()).isEqualTo(new BigDecimal("65557.7"));
}

@Test
public void testGetFundingRateHistory() throws Exception {
initGetStub("/v5/market/funding/history", "/getFundingRateHistory.json5");

List<BybitFundingRateHistory> fundingRateHistory = ((BybitMarketDataService) marketDataService).getFundingRateHistory(new FuturesContract("ETH/USDT/PERP"),
null, null, null);

assertThat(fundingRateHistory.get(0).getInstrument().toString()).isEqualTo("ETH/USDT/PERP");
assertThat(fundingRateHistory.get(0).getFundingRate()).isEqualTo(new BigDecimal("0.0001"));
assertThat(fundingRateHistory.get(0).getFundingRateTimestamp()).isEqualTo(Instant.ofEpochMilli(1672051897447L));

}
}
16 changes: 16 additions & 0 deletions xchange-bybit/src/test/resources/getFundingRateHistory.json5
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"retCode": 0,
"retMsg": "OK",
"result": {
"category": "linear",
"list": [
{
"symbol": "ETHUSDT",
"fundingRate": "0.0001",
"fundingRateTimestamp": "1672051897447"
}
]
},
"retExtInfo": {},
"time": 1672051897447
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,11 @@ private static long calculateFundingRateEffectiveInMinutes(Date fundingRateDate)
public enum FundingRateInterval {
H1(1),
H2(2),
H3(3),
H4(4),
H5(5),
H6(6),
H7(7),
H8(8);
private final int hours;

Expand Down
Loading
Loading