Skip to content
Open
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
16 changes: 16 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 @@ -7,6 +7,8 @@
import jakarta.ws.rs.core.MediaType;
import java.io.IOException;
import org.knowm.xchange.bybit.dto.BybitResult;
import org.knowm.xchange.bybit.dto.marketdata.BybitKline;
import org.knowm.xchange.bybit.dto.marketdata.BybitKlines;
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 @@ -42,4 +44,18 @@ 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/kline">API</a>
*/
@GET
@Path("/kline")
BybitResult<BybitKlines> getKlines(
@QueryParam("category") String category,
@QueryParam("symbol") String symbol,
@QueryParam("interval") String interval,
@QueryParam("start") Long start,
@QueryParam("end") Long end,
@QueryParam("limit") Integer limit)
throws IOException, BybitException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import org.knowm.xchange.bybit.dto.account.allcoins.BybitAllCoinBalance;
import org.knowm.xchange.bybit.dto.account.allcoins.BybitAllCoinsBalance;
import org.knowm.xchange.bybit.dto.account.walletbalance.BybitCoinWalletBalance;
import org.knowm.xchange.bybit.dto.marketdata.BybitKline;
import org.knowm.xchange.bybit.dto.marketdata.BybitKlines;
import org.knowm.xchange.bybit.dto.marketdata.instruments.BybitInstrumentInfo;
import org.knowm.xchange.bybit.dto.marketdata.instruments.linear.BybitLinearInverseInstrumentInfo;
import org.knowm.xchange.bybit.dto.marketdata.instruments.option.BybitOptionInstrumentInfo;
Expand Down Expand Up @@ -49,6 +51,8 @@
import org.knowm.xchange.dto.Order.OrderType;
import org.knowm.xchange.dto.account.Balance;
import org.knowm.xchange.dto.account.Wallet;
import org.knowm.xchange.dto.marketdata.CandleStick;
import org.knowm.xchange.dto.marketdata.CandleStickData;
import org.knowm.xchange.dto.marketdata.Ticker;
import org.knowm.xchange.dto.marketdata.Ticker.Builder;
import org.knowm.xchange.dto.meta.InstrumentMetaData;
Expand Down Expand Up @@ -568,4 +572,27 @@ public static BybitAmendOrderPayload adaptChangeOrder(LimitOrder order, BybitCat
null,
null);
}

public static CandleStickData adaptCandleStickData(
BybitKlines bybitKlines, BybitCategory category) {
Instrument instrument =
convertBybitSymbolToInstrument(bybitKlines.getSymbol(), category);
List<CandleStick> candleSticks = new ArrayList<>();
for (BybitKline bybitKline : bybitKlines.getList()) {
candleSticks.add(adaptBybitKline(bybitKline));
}
return new CandleStickData(instrument, candleSticks);
}

private static CandleStick adaptBybitKline(BybitKline bybitKline) {
return new CandleStick.Builder()
.timestamp(new Date(Long.parseLong(bybitKline.getStartTime())))
.open(new BigDecimal(bybitKline.getOpenPrice()))
.high(new BigDecimal(bybitKline.getHighPrice()))
.low(new BigDecimal(bybitKline.getLowPrice()))
.close(new BigDecimal(bybitKline.getClosePrice()))
.volume(new BigDecimal(bybitKline.getVolume()))
.quotaVolume(new BigDecimal(bybitKline.getTurnover()))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.knowm.xchange.bybit.dto.marketdata;

import com.fasterxml.jackson.annotation.JsonFormat;
import java.math.BigDecimal;
import lombok.Builder;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;

@Builder
@Jacksonized
@Value
@JsonFormat(shape = JsonFormat.Shape.ARRAY)
public class BybitKline {

String startTime;
String openPrice;
String highPrice;
String lowPrice;
String closePrice;
String volume;
String turnover;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.knowm.xchange.bybit.dto.marketdata;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.knowm.xchange.bybit.dto.BybitCategorizedPayload;

@Data
@EqualsAndHashCode(callSuper = true)
public class BybitKlines extends BybitCategorizedPayload<BybitKline> {

@JsonProperty("symbol")
String symbol;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@
import org.knowm.xchange.bybit.dto.marketdata.tickers.spot.BybitSpotTicker;
import org.knowm.xchange.client.ResilienceRegistries;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.dto.marketdata.CandleStickData;
import org.knowm.xchange.dto.marketdata.Ticker;
import org.knowm.xchange.exceptions.NotYetImplementedForExchangeException;
import org.knowm.xchange.instrument.Instrument;
import org.knowm.xchange.service.marketdata.MarketDataService;
import org.knowm.xchange.service.marketdata.params.Params;
import org.knowm.xchange.service.trade.params.CandleStickDataParams;
import org.knowm.xchange.service.trade.params.DefaultCandleStickParam;
import org.knowm.xchange.service.trade.params.DefaultCandleStickParamWithLimit;
import org.knowm.xchange.utils.Assert;

public class BybitMarketDataService extends BybitMarketDataServiceRaw implements MarketDataService {
Expand Down Expand Up @@ -63,6 +67,12 @@ public Ticker getTicker(CurrencyPair currencyPair, Object... args) throws IOExce
return getTicker((Instrument) currencyPair, args);
}

@Override
public CandleStickData getCandleStickData(CurrencyPair currencyPair, CandleStickDataParams params)
throws IOException {
return getCandleStickData((Instrument) currencyPair, params);
}

@Override
public List<Ticker> getTickers(Params params) throws IOException {
// get category
Expand Down Expand Up @@ -102,4 +112,45 @@ public List<Ticker> getTickers(Params params) throws IOException {
}
return result;
}

public CandleStickData getCandleStickData(Instrument instrument, CandleStickDataParams params)
throws IOException {
String interval;
Long start;
Long end;
Integer limit = null;
if (params instanceof DefaultCandleStickParamWithLimit) {
DefaultCandleStickParamWithLimit checkedParams = (DefaultCandleStickParamWithLimit) params;
start =
checkedParams.getStartDate() == null ? null : checkedParams.getStartDate().getTime();
end = checkedParams.getEndDate() == null ? null : checkedParams.getEndDate().getTime();
interval = String.valueOf(checkedParams.getPeriodInSecs() / 60);
if (checkedParams.getPeriodInSecs() == 86400) {
interval = "D";
} else if (checkedParams.getPeriodInSecs() == 604800) {
interval = "W";
} else if (checkedParams.getPeriodInSecs() == 2592000) {
interval = "M";
}
limit = checkedParams.getLimit();
} else if (params instanceof DefaultCandleStickParam) {
DefaultCandleStickParam checkedParams = (DefaultCandleStickParam) params;
start =
checkedParams.getStartDate() == null ? null : checkedParams.getStartDate().getTime();
end = checkedParams.getEndDate() == null ? null : checkedParams.getEndDate().getTime();
interval = String.valueOf(checkedParams.getPeriodInSecs() / 60);
if (checkedParams.getPeriodInSecs() == 86400) {
interval = "D";
} else if (checkedParams.getPeriodInSecs() == 604800) {
interval = "W";
} else if (checkedParams.getPeriodInSecs() == 2592000) {
interval = "M";
}
} else {
throw new IllegalArgumentException("CandleStickDataParams must be DefaultCandleStickParam or DefaultCandleStickParamWithLimit");
}
BybitCategory category = BybitAdapters.getCategory(instrument);
String symbol = BybitAdapters.convertToBybitSymbol(instrument);
return getCandleStickDataRaw(category, symbol, interval, start, end, limit);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@
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.BybitKline;
import org.knowm.xchange.bybit.dto.marketdata.BybitKlines;
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.currency.CurrencyPair;
import org.knowm.xchange.dto.marketdata.CandleStickData;
import org.knowm.xchange.exceptions.NotYetImplementedForExchangeException;
import org.knowm.xchange.service.trade.params.CandleStickDataParams;

public class BybitMarketDataServiceRaw extends BybitBaseService {

Expand Down Expand Up @@ -48,4 +54,19 @@ public BybitResult<BybitTickers<BybitTicker>> getTickers(BybitCategory category)
}
return result;
}

public CandleStickData getCandleStickDataRaw(
BybitCategory category,
String symbol,
String interval,
Long start,
Long end,
Integer limit)
throws IOException {
BybitResult<BybitKlines> result = bybit.getKlines(category.getValue(), symbol, interval, start, end, limit);
if (!result.isSuccess()) {
throw BybitAdapters.createBybitExceptionFromResult(result);
}
return BybitAdapters.adaptCandleStickData(result.getResult(), category);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.knowm.xchange.bybit.examples;

import java.io.IOException;
import java.util.Date;
import org.knowm.xchange.Exchange;
import org.knowm.xchange.ExchangeFactory;
import org.knowm.xchange.ExchangeSpecification;
import org.knowm.xchange.bybit.BybitExchange;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.dto.marketdata.CandleStick;
import org.knowm.xchange.dto.marketdata.CandleStickData;
import org.knowm.xchange.service.marketdata.MarketDataService;
import org.knowm.xchange.service.trade.params.DefaultCandleStickParam;
import org.knowm.xchange.service.trade.params.DefaultCandleStickParamWithLimit;

public class BybitGetCandlesHistoryExample {

public static void main(String[] args) throws IOException {
ExchangeSpecification exchangeSpecification =
new BybitExchange().getDefaultExchangeSpecification();
exchangeSpecification.setExchangeSpecificParametersItem(Exchange.USE_SANDBOX, true);
Exchange exchange = ExchangeFactory.INSTANCE.createExchange(exchangeSpecification);

MarketDataService marketDataService = exchange.getMarketDataService();

// 3600 seconds interval (1 hour)
long periodInSecs = 3600;
// Last 240 minutes
long endTime = System.currentTimeMillis();
long startTime = endTime - (240 * 60 * 1000);

DefaultCandleStickParam params =
new DefaultCandleStickParam(new Date(startTime), new Date(endTime), periodInSecs);

CandleStickData candleStickData =
marketDataService.getCandleStickData(CurrencyPair.BTC_USDT, params);

System.out.println("Instrument: " + candleStickData.getInstrument());
for (CandleStick candleStick : candleStickData.getCandleSticks()) {
System.out.println(candleStick);
}
startTime = endTime - (24 * 10 * 60 * 60 * 1000); // 10 days, 240 bars
DefaultCandleStickParamWithLimit paramsWithLimit =
new DefaultCandleStickParamWithLimit(new Date(startTime), new Date(endTime), periodInSecs, 240);
candleStickData =
marketDataService.getCandleStickData(CurrencyPair.BTC_USDT, paramsWithLimit);
System.out.println("response size: " + candleStickData.getCandleSticks().size());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import org.knowm.xchange.Exchange;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.derivative.FuturesContract;
import org.knowm.xchange.dto.marketdata.CandleStickData;
import org.knowm.xchange.dto.marketdata.Ticker;
import org.knowm.xchange.service.marketdata.MarketDataService;
import org.knowm.xchange.service.trade.params.DefaultCandleStickParam;

public class BybitMarketDataServiceTest extends BaseWiremockTest {

Expand Down Expand Up @@ -65,4 +67,31 @@ public void testGetTickerWithSpotArg() throws Exception {
assertThat(ticker.getAskSize()).isEqualTo(new BigDecimal("1.862172"));
assertThat(ticker.getPercentageChange()).isEqualTo(new BigDecimal("0.0068"));
}

@Test
public void testGetCandleStickData() throws Exception {
initGetStub("/v5/market/kline", "/getKlines.json5");

CandleStickData candleStickData =
marketDataService
.getCandleStickData(
CurrencyPair.BTC_USDT, new DefaultCandleStickParam(new Date(1670601600000L), new Date(1670608800000L), 60));

assertThat(candleStickData.getInstrument().toString()).isEqualTo("BTC/USDT");
assertThat(candleStickData.getCandleSticks()).hasSize(3);
assertThat(candleStickData.getCandleSticks().get(0).getTimestamp())
.isEqualTo(new Date(1670608800000L));
assertThat(candleStickData.getCandleSticks().get(0).getOpen())
.isEqualTo(new BigDecimal("17071"));
assertThat(candleStickData.getCandleSticks().get(0).getHigh())
.isEqualTo(new BigDecimal("17073"));
assertThat(candleStickData.getCandleSticks().get(0).getLow())
.isEqualTo(new BigDecimal("17027"));
assertThat(candleStickData.getCandleSticks().get(0).getClose())
.isEqualTo(new BigDecimal("17055.5"));
assertThat(candleStickData.getCandleSticks().get(0).getVolume())
.isEqualTo(new BigDecimal("268611"));
assertThat(candleStickData.getCandleSticks().get(0).getQuotaVolume())
.isEqualTo(new BigDecimal("15.74462667"));
}
}
39 changes: 39 additions & 0 deletions xchange-bybit/src/test/resources/getKlines.json5
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"retCode": 0,
"retMsg": "OK",
"result": {
"symbol": "BTCUSDT",
"category": "inverse",
"list": [
[
"1670608800000",
"17071",
"17073",
"17027",
"17055.5",
"268611",
"15.74462667"
],
[
"1670605200000",
"17071.5",
"17071.5",
"17061",
"17071",
"4177",
"0.24469757"
],
[
"1670601600000",
"17086.5",
"17088",
"16978",
"17071.5",
"6356",
"0.37288112"
]
]
},
"retExtInfo": {},
"time": 1672025956592
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import java.math.BigDecimal;
import java.util.Date;
import lombok.ToString;

/** Data object representing a CandleStick */
@JsonDeserialize(builder = CandleStick.Builder.class)
@ToString
public class CandleStick {

private final BigDecimal open;
Expand Down
Loading