diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/Gateio.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/Gateio.java index 431ecef56a4..87a508faa28 100644 --- a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/Gateio.java +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/Gateio.java @@ -1,20 +1,12 @@ package org.knowm.xchange.gateio; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; +import org.knowm.xchange.gateio.dto.GateioException; +import org.knowm.xchange.gateio.dto.marketdata.*; + import java.io.IOException; import java.util.List; -import org.knowm.xchange.gateio.dto.GateioException; -import org.knowm.xchange.gateio.dto.marketdata.GateioCurrencyChain; -import org.knowm.xchange.gateio.dto.marketdata.GateioCurrencyInfo; -import org.knowm.xchange.gateio.dto.marketdata.GateioCurrencyPairDetails; -import org.knowm.xchange.gateio.dto.marketdata.GateioOrderBook; -import org.knowm.xchange.gateio.dto.marketdata.GateioServerTime; -import org.knowm.xchange.gateio.dto.marketdata.GateioTicker; @Path("api/v4") @Produces(MediaType.APPLICATION_JSON) @@ -43,6 +35,10 @@ List getCurrencyChains(@QueryParam("currency") String curre @Path("spot/currency_pairs") List getCurrencyPairDetails() throws IOException, GateioException; + @GET + @Path("/futures/usdt/contracts") + List getInstrumentDetails() throws IOException, GateioException; + @GET @Path("spot/currency_pairs/{currency_pair}") GateioCurrencyPairDetails getCurrencyPairDetails(@PathParam("currency_pair") String currencyPair) @@ -52,4 +48,25 @@ GateioCurrencyPairDetails getCurrencyPairDetails(@PathParam("currency_pair") Str @Path("spot/tickers") List getTickers(@QueryParam("currency_pair") String currencyPair) throws IOException, GateioException; + + @GET + @Path("spot/candlesticks") + List getSpotCandlesticks( + @QueryParam("currency_pair") String currencyPair, + @QueryParam("limit") Integer limit, + @QueryParam("from") Long from, + @QueryParam("to") Long to, + @QueryParam("interval") String interval) + throws IOException, GateioException; + + @GET + @Path("futures/{settle}/candlesticks") + List getFuturesCandlesticks( + @PathParam("settle") String settle, + @QueryParam("contract") String contract, + @QueryParam("limit") Integer limit, + @QueryParam("from") Long from, + @QueryParam("to") Long to, + @QueryParam("interval") String interval) + throws IOException, GateioException; } diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/GateioAdapters.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/GateioAdapters.java index e96475c0394..1ca80422f41 100644 --- a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/GateioAdapters.java +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/GateioAdapters.java @@ -1,17 +1,13 @@ package org.knowm.xchange.gateio; -import java.math.BigDecimal; -import java.math.MathContext; -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.stream.Collectors; import lombok.experimental.UtilityClass; import org.knowm.xchange.currency.CurrencyPair; import org.knowm.xchange.dto.Order; import org.knowm.xchange.dto.Order.OrderStatus; import org.knowm.xchange.dto.Order.OrderType; import org.knowm.xchange.dto.account.FundingRecord; +import org.knowm.xchange.dto.marketdata.CandleStick; +import org.knowm.xchange.dto.marketdata.CandleStickData; import org.knowm.xchange.dto.marketdata.OrderBook; import org.knowm.xchange.dto.marketdata.Ticker; import org.knowm.xchange.dto.meta.InstrumentMetaData; @@ -21,20 +17,26 @@ import org.knowm.xchange.gateio.dto.account.GateioAccountBookRecord; import org.knowm.xchange.gateio.dto.account.GateioOrder; import org.knowm.xchange.gateio.dto.account.GateioWithdrawalRequest; -import org.knowm.xchange.gateio.dto.marketdata.GateioCurrencyPairDetails; -import org.knowm.xchange.gateio.dto.marketdata.GateioOrderBook; -import org.knowm.xchange.gateio.dto.marketdata.GateioTicker; +import org.knowm.xchange.gateio.dto.marketdata.*; import org.knowm.xchange.gateio.dto.trade.GateioUserTrade; import org.knowm.xchange.gateio.dto.trade.GateioUserTradeRaw; import org.knowm.xchange.gateio.service.params.GateioWithdrawFundsParams; import org.knowm.xchange.instrument.Instrument; +import java.math.BigDecimal; +import java.math.MathContext; +import java.time.Instant; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; + @UtilityClass public class GateioAdapters { public final BigDecimal PARTIALLY_FILLED_SCALE = new BigDecimal("0.1"); - public String toString(Instrument instrument) { + public String toGateioInstrument(Instrument instrument) { if (instrument == null) { return null; } else { @@ -75,7 +77,7 @@ public OrderBook toOrderBook(GateioOrderBook gateioOrderBook, Instrument instrum return new OrderBook(Date.from(gateioOrderBook.getGeneratedAt()), asks, bids); } - public InstrumentMetaData toInstrumentMetaData( + public InstrumentMetaData currencyPairToInstrumentMetaData( GateioCurrencyPairDetails gateioCurrencyPairDetails) { return InstrumentMetaData.builder() .tradingFee(gateioCurrencyPairDetails.getFee()) @@ -86,7 +88,23 @@ public InstrumentMetaData toInstrumentMetaData( .build(); } - public String toString(OrderStatus orderStatus) { + public InstrumentMetaData instrumentToInstrumentMetaData( + GateioInstrumentDetails gateioInstrumentDetails) { + return InstrumentMetaData.builder() + .contractValue(gateioInstrumentDetails.getQuantoMultiplier()) + .tradingFee(gateioInstrumentDetails.getTakerFeeRate()) + .minimumAmount(gateioInstrumentDetails.getOrderSizeMin().multiply(gateioInstrumentDetails.getQuantoMultiplier()).stripTrailingZeros()) + .maximumAmount(gateioInstrumentDetails.getOrderSizeMax().multiply(gateioInstrumentDetails.getQuantoMultiplier()).stripTrailingZeros()) + .priceStepSize(gateioInstrumentDetails.getOrderPriceRound()) + // no data, so suggest that equals to order min size + .amountStepSize(gateioInstrumentDetails.getOrderSizeMin().multiply(gateioInstrumentDetails.getQuantoMultiplier()).stripTrailingZeros()) + .volumeScale(numberOfDecimals(gateioInstrumentDetails.getOrderSizeMin().multiply(gateioInstrumentDetails.getQuantoMultiplier()).stripTrailingZeros())) + .priceScale(numberOfDecimals(gateioInstrumentDetails.getOrderPriceRound())) + .contractValue(gateioInstrumentDetails.getQuantoMultiplier()) + .build(); + } + + public String toGateioInstrument(OrderStatus orderStatus) { switch (orderStatus) { case OPEN: return "open"; @@ -237,6 +255,47 @@ public Ticker toTicker(GateioTicker gateioTicker) { .build(); } + public CandleStickData toCandleStickDataSpot( + List gateioSpotCandlesticks, Instrument instrument) { + List candleSticks = + gateioSpotCandlesticks.stream() + .map( + gateioSpotCandlestick -> + new CandleStick.Builder() + .timestamp(Instant.ofEpochSecond(gateioSpotCandlestick.getTimestamp())) + .open(gateioSpotCandlestick.getOpen()) + .high(gateioSpotCandlestick.getHigh()) + .low(gateioSpotCandlestick.getLow()) + .close(gateioSpotCandlestick.getClose()) + .volume(gateioSpotCandlestick.getVolume()) + .quotaVolume(gateioSpotCandlestick.getQuoteVolume()) + .completed(gateioSpotCandlestick.isCompleted()) + .build()) + .collect(Collectors.toList()); + + return new CandleStickData(instrument, candleSticks); + } + + public CandleStickData toCandleStickDataFutures( + List gateioFuturesCandlesticks, Instrument instrument, BigDecimal contractValue) { + List candleSticks = + gateioFuturesCandlesticks.stream() + .map( + gateioFuturesCandlestick -> + new CandleStick.Builder() + .timestamp(Instant.ofEpochSecond(gateioFuturesCandlestick.getTimestamp())) + .open(gateioFuturesCandlestick.getOpen()) + .high(gateioFuturesCandlestick.getHigh()) + .low(gateioFuturesCandlestick.getLow()) + .close(gateioFuturesCandlestick.getClose()) + .volume(convertContractSizeToVolume(gateioFuturesCandlestick.getVolume(), contractValue)) + .quotaVolume(gateioFuturesCandlestick.getQuoteVolume()) + .build()) + .collect(Collectors.toList()); + + return new CandleStickData(instrument, candleSticks); + } + public FundingRecord toFundingRecords(GateioAccountBookRecord gateioAccountBookRecord) { return FundingRecord.builder() .internalId(gateioAccountBookRecord.getId()) @@ -248,4 +307,15 @@ public FundingRecord toFundingRecords(GateioAccountBookRecord gateioAccountBookR .description(gateioAccountBookRecord.getTypeDescription()) .build(); } + + private static int numberOfDecimals(BigDecimal value) { + double d = value.doubleValue(); + return -(int) Math.round(Math.log10(d)); + } + + private static BigDecimal convertContractSizeToVolume( + BigDecimal size, BigDecimal contractValue) { + return size.multiply(contractValue).stripTrailingZeros(); + } + } diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/GateioExchange.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/GateioExchange.java index dd0fa22eb18..69ee0aa505d 100644 --- a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/GateioExchange.java +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/GateioExchange.java @@ -1,12 +1,10 @@ package org.knowm.xchange.gateio; -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.TimeUnit; import org.knowm.xchange.BaseExchange; import org.knowm.xchange.ExchangeSpecification; import org.knowm.xchange.dto.meta.ExchangeMetaData; import org.knowm.xchange.dto.meta.InstrumentMetaData; +import org.knowm.xchange.gateio.dto.GateioExchangeType; import org.knowm.xchange.gateio.service.GateioAccountService; import org.knowm.xchange.gateio.service.GateioMarketDataService; import org.knowm.xchange.gateio.service.GateioTradeService; @@ -14,8 +12,14 @@ import org.knowm.xchange.utils.nonce.CurrentTimeIncrementalNonceFactory; import si.mazi.rescu.SynchronizedValueFactory; -public class GateioExchange extends BaseExchange { +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import static org.knowm.xchange.gateio.dto.GateioExchangeType.SPOT; +public class GateioExchange extends BaseExchange { + public static String EXCHANGE_TYPE = "Exchange_Type"; private final SynchronizedValueFactory nonceFactory = new CurrentTimeIncrementalNonceFactory(TimeUnit.SECONDS); @@ -30,6 +34,7 @@ protected void initServices() { public ExchangeSpecification getDefaultExchangeSpecification() { ExchangeSpecification specification = new ExchangeSpecification(this.getClass()); + specification.setExchangeSpecificParametersItem(EXCHANGE_TYPE, SPOT); specification.setSslUri("https://api.gateio.ws"); specification.setHost("gate.io"); specification.setExchangeName("Gateio"); @@ -48,5 +53,11 @@ public void remoteInit() throws IOException { ((GateioMarketDataService) marketDataService).getMetaDataByInstrument(); exchangeMetaData = new ExchangeMetaData(instruments, null, null, null, null); + ((GateioMarketDataService) marketDataService).setInstrumentMetaDataMap(exchangeMetaData.getInstruments()); + } + + public boolean isFuturesEnabled() { + return GateioExchangeType.FUTURES.equals( + exchangeSpecification.getExchangeSpecificParametersItem(EXCHANGE_TYPE)); } } diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/GateioV4Authenticated.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/GateioV4Authenticated.java index 77f5603e4a3..06d33692c7c 100644 --- a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/GateioV4Authenticated.java +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/GateioV4Authenticated.java @@ -1,32 +1,16 @@ package org.knowm.xchange.gateio; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.HeaderParam; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; -import java.io.IOException; -import java.util.List; import org.knowm.xchange.gateio.dto.GateioException; -import org.knowm.xchange.gateio.dto.account.GateioAccountBookRecord; -import org.knowm.xchange.gateio.dto.account.GateioAddressRecord; -import org.knowm.xchange.gateio.dto.account.GateioCurrencyBalance; -import org.knowm.xchange.gateio.dto.account.GateioDepositAddress; -import org.knowm.xchange.gateio.dto.account.GateioDepositRecord; -import org.knowm.xchange.gateio.dto.account.GateioOrder; -import org.knowm.xchange.gateio.dto.account.GateioSubAccountTransfer; -import org.knowm.xchange.gateio.dto.account.GateioWithdrawStatus; -import org.knowm.xchange.gateio.dto.account.GateioWithdrawalRecord; -import org.knowm.xchange.gateio.dto.account.GateioWithdrawalRequest; +import org.knowm.xchange.gateio.dto.account.*; import org.knowm.xchange.gateio.dto.trade.GateioUserTradeRaw; import si.mazi.rescu.ParamsDigest; import si.mazi.rescu.SynchronizedValueFactory; +import java.io.IOException; +import java.util.List; + @Path("api/v4") @Produces(MediaType.APPLICATION_JSON) public interface GateioV4Authenticated { @@ -184,4 +168,16 @@ GateioWithdrawalRecord withdraw( @HeaderParam("SIGN") ParamsDigest signer, GateioWithdrawalRequest gateioWithdrawalRequest) throws IOException, GateioException; + + @POST + @Path("futures/{settle}/positions/{contract}/leverage") + @Consumes(MediaType.APPLICATION_JSON) + GateioPositionLeverageUpdate updatePositionLeverage( + @HeaderParam("KEY") String apiKey, + @HeaderParam("Timestamp") SynchronizedValueFactory timestamp, + @HeaderParam("SIGN") ParamsDigest signer, + @PathParam("settle") String settle, + @PathParam("contract") String contract, + @QueryParam("leverage") String leverage) + throws IOException, GateioException; } diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/GateioExchangeType.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/GateioExchangeType.java new file mode 100644 index 00000000000..1e84de84925 --- /dev/null +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/GateioExchangeType.java @@ -0,0 +1,6 @@ +package org.knowm.xchange.gateio.dto; + +public enum GateioExchangeType { + SPOT, + FUTURES, +} diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/account/GateioPositionLeverageUpdate.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/account/GateioPositionLeverageUpdate.java new file mode 100644 index 00000000000..e137998846e --- /dev/null +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/account/GateioPositionLeverageUpdate.java @@ -0,0 +1,24 @@ +package org.knowm.xchange.gateio.dto.account; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; + +import java.math.BigDecimal; + +@Getter +public class GateioPositionLeverageUpdate { + + @JsonProperty("leverage") + private final BigDecimal leverage; + + @JsonProperty("cross_leverage_limit") + private final BigDecimal crossLeverageLimit; + + public GateioPositionLeverageUpdate( + @JsonProperty("leverage") BigDecimal leverage, + @JsonProperty("cross_leverage_limit") BigDecimal crossLeverageLimit) { + this.leverage = leverage; + this.crossLeverageLimit = crossLeverageLimit; + } + +} \ No newline at end of file diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/marketdata/GateioFuturesCandlestick.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/marketdata/GateioFuturesCandlestick.java new file mode 100644 index 00000000000..cfb14ffa50f --- /dev/null +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/marketdata/GateioFuturesCandlestick.java @@ -0,0 +1,33 @@ +package org.knowm.xchange.gateio.dto.marketdata; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class GateioFuturesCandlestick { + + @JsonProperty("t") + // in seconds + private long timestamp; + // size volume (contract size). Only returned if contract is not prefixed + @JsonProperty("v") + private BigDecimal volume; + + @JsonProperty("c") + private BigDecimal close; + + @JsonProperty("h") + private BigDecimal high; + + @JsonProperty("l") + private BigDecimal low; + + @JsonProperty("o") + private BigDecimal open; + // Trading volume (unit: Quote currency) + @JsonProperty("sum") + private BigDecimal quoteVolume; + +} diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/marketdata/GateioInstrumentDetails.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/marketdata/GateioInstrumentDetails.java new file mode 100644 index 00000000000..2c1df3c0e5c --- /dev/null +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/marketdata/GateioInstrumentDetails.java @@ -0,0 +1,165 @@ +package org.knowm.xchange.gateio.dto.marketdata; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import lombok.Builder; +import lombok.Data; +import lombok.extern.jackson.Jacksonized; +import org.knowm.xchange.gateio.config.converter.DoubleToInstantConverter; + +import java.math.BigDecimal; +import java.time.Instant; + +@Data +@Builder +@Jacksonized +public class GateioInstrumentDetails { + + @JsonProperty("name") + String name; + + @JsonProperty("type") + String type; + + @JsonProperty("quanto_multiplier") + BigDecimal quantoMultiplier; + + @JsonProperty("leverage_min") + BigDecimal leverageMin; + + @JsonProperty("leverage_max") + BigDecimal leverageMax; + + @JsonProperty("maintenance_rate") + BigDecimal maintenanceRate; + + @JsonProperty("mark_type") + String markType; + + @JsonProperty("mark_price") + BigDecimal markPrice; + + @JsonProperty("index_price") + BigDecimal indexPrice; + + @JsonProperty("last_price") + BigDecimal lastPrice; + + @JsonProperty("maker_fee_rate") + BigDecimal makerFeeRate; + + @JsonProperty("taker_fee_rate") + BigDecimal takerFeeRate; + + @JsonProperty("order_price_round") + BigDecimal orderPriceRound; + + @JsonProperty("mark_price_round") + BigDecimal markPriceRound; + + @JsonProperty("funding_rate") + BigDecimal fundingRate; + + @JsonProperty("funding_interval") + Integer fundingInterval; + + @JsonProperty("funding_next_apply") + @JsonDeserialize(converter = DoubleToInstantConverter.class) + Instant fundingNextApply; + + @JsonProperty("risk_limit_base") + BigDecimal riskLimitBase; + + @JsonProperty("interest_rate") + BigDecimal interestRate; + + @JsonProperty("risk_limit_step") + BigDecimal riskLimitStep; + + @JsonProperty("risk_limit_max") + BigDecimal riskLimitMax; + + @JsonProperty("order_size_min") + BigDecimal orderSizeMin; + + @JsonProperty("enable_decimal") + Boolean enableDecimal; + + @JsonProperty("order_size_max") + BigDecimal orderSizeMax; + + @JsonProperty("order_price_deviate") + BigDecimal orderPriceDeviate; + + @JsonProperty("ref_discount_rate") + BigDecimal refDiscountRate; + + @JsonProperty("ref_rebate_rate") + BigDecimal refRebateRate; + + @JsonProperty("orderbook_id") + Long orderbookId; + + @JsonProperty("trade_id") + Long tradeId; + + @JsonProperty("trade_size") + BigDecimal tradeSize; + + @JsonProperty("position_size") + BigDecimal positionSize; + + @JsonProperty("config_change_time") + @JsonDeserialize(converter = DoubleToInstantConverter.class) + Instant configChangeTime; + + @JsonProperty("in_delisting") + Boolean inDelisting; + + @JsonProperty("orders_limit") + Integer ordersLimit; + + @JsonProperty("enable_bonus") + Boolean enableBonus; + + @JsonProperty("enable_credit") + Boolean enableCredit; + + @JsonProperty("create_time") + @JsonDeserialize(converter = DoubleToInstantConverter.class) + Instant createTime; + + @JsonProperty("funding_cap_ratio") + BigDecimal fundingCapRatio; + + @JsonProperty("status") + String status; + + @JsonProperty("launch_time") + @JsonDeserialize(converter = DoubleToInstantConverter.class) + Instant launchTime; + + @JsonProperty("delisting_time") + @JsonDeserialize(converter = DoubleToInstantConverter.class) + Instant delistingTime; + + @JsonProperty("delisted_time") + @JsonDeserialize(converter = DoubleToInstantConverter.class) + Instant delistedTime; + + @JsonProperty("market_order_slip_ratio") + BigDecimal marketOrderSlipRatio; + + @JsonProperty("market_order_size_max") + BigDecimal marketOrderSizeMax; + + @JsonProperty("funding_rate_limit") + BigDecimal fundingRateLimit; + + @JsonProperty("contract_type") + String contractType; + + @JsonProperty("funding_impact_value") + BigDecimal fundingImpactValue; + +} diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/marketdata/GateioSpotCandlestick.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/marketdata/GateioSpotCandlestick.java new file mode 100644 index 00000000000..8968a8adc4c --- /dev/null +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/dto/marketdata/GateioSpotCandlestick.java @@ -0,0 +1,39 @@ +package org.knowm.xchange.gateio.dto.marketdata; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Data; + +import java.math.BigDecimal; + +@Data +@JsonFormat(shape = JsonFormat.Shape.ARRAY) +@JsonPropertyOrder({"timestamp", "quoteVolume", "close", "high", "low", "open", "volume", "completed"}) +public class GateioSpotCandlestick { + + @JsonProperty("timestamp") + // in seconds + private long timestamp; + //Trading volume in quote currency + @JsonProperty("volume") + private BigDecimal volume; + + @JsonProperty("close") + private BigDecimal close; + + @JsonProperty("high") + private BigDecimal high; + + @JsonProperty("low") + private BigDecimal low; + + @JsonProperty("open") + private BigDecimal open; + //Trading volume in base currency + @JsonProperty("quoteVolume") + private BigDecimal quoteVolume; + //Whether window is closed; true means this candlestick data segment is complete, false means not yet complete + @JsonProperty("finished") + private boolean completed; +} diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioAccountService.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioAccountService.java index 612167dba06..54138c55b0b 100644 --- a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioAccountService.java +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioAccountService.java @@ -1,10 +1,7 @@ package org.knowm.xchange.gateio.service; -import java.io.IOException; -import java.util.EnumSet; -import java.util.List; -import java.util.stream.Collectors; import org.apache.commons.lang3.Validate; +import org.knowm.xchange.derivative.FuturesContract; import org.knowm.xchange.dto.account.AccountInfo; import org.knowm.xchange.dto.account.Balance; import org.knowm.xchange.dto.account.FundingRecord; @@ -17,10 +14,16 @@ import org.knowm.xchange.gateio.dto.account.GateioWithdrawalRecord; import org.knowm.xchange.gateio.dto.account.GateioWithdrawalRequest; import org.knowm.xchange.gateio.service.params.GateioWithdrawFundsParams; +import org.knowm.xchange.instrument.Instrument; import org.knowm.xchange.service.account.AccountService; import org.knowm.xchange.service.trade.params.TradeHistoryParams; import org.knowm.xchange.service.trade.params.WithdrawFundsParams; +import java.io.IOException; +import java.util.EnumSet; +import java.util.List; +import java.util.stream.Collectors; + public class GateioAccountService extends GateioAccountServiceRaw implements AccountService { public GateioAccountService(GateioExchange exchange) { @@ -82,4 +85,23 @@ public List getFundingHistory(TradeHistoryParams params) throws I throw GateioErrorAdapter.adapt(e); } } + + /** + * set leverage for futures contract + * Isolated margin only + * + * @param instrument symbol to change leverage + * @param leverage leverage + * @return is successful + * @throws IOException + */ + @Override + public boolean setLeverage(Instrument instrument, int leverage) throws IOException { + if (instrument instanceof FuturesContract) { + String settle = instrument.getCounter().getCurrencyCode().toLowerCase(); + String contract = GateioAdapters.toGateioInstrument(instrument); + setLeverage(settle, contract, String.valueOf(leverage)); + return true; + } else throw new UnsupportedOperationException("Leverage is not supported for spot instruments"); + } } diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioAccountServiceRaw.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioAccountServiceRaw.java index 87ccacb827a..120656597d9 100644 --- a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioAccountServiceRaw.java +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioAccountServiceRaw.java @@ -1,21 +1,10 @@ package org.knowm.xchange.gateio.service; -import java.io.IOException; -import java.util.List; -import java.util.Objects; import org.knowm.xchange.currency.Currency; import org.knowm.xchange.gateio.GateioErrorAdapter; import org.knowm.xchange.gateio.GateioExchange; import org.knowm.xchange.gateio.dto.GateioException; -import org.knowm.xchange.gateio.dto.account.GateioAccountBookRecord; -import org.knowm.xchange.gateio.dto.account.GateioAddressRecord; -import org.knowm.xchange.gateio.dto.account.GateioCurrencyBalance; -import org.knowm.xchange.gateio.dto.account.GateioDepositAddress; -import org.knowm.xchange.gateio.dto.account.GateioDepositRecord; -import org.knowm.xchange.gateio.dto.account.GateioSubAccountTransfer; -import org.knowm.xchange.gateio.dto.account.GateioWithdrawStatus; -import org.knowm.xchange.gateio.dto.account.GateioWithdrawalRecord; -import org.knowm.xchange.gateio.dto.account.GateioWithdrawalRequest; +import org.knowm.xchange.gateio.dto.account.*; import org.knowm.xchange.gateio.dto.account.params.GateioSubAccountTransfersParams; import org.knowm.xchange.gateio.service.params.GateioDepositsParams; import org.knowm.xchange.gateio.service.params.GateioFundingHistoryParams; @@ -24,6 +13,10 @@ import org.knowm.xchange.service.trade.params.TradeHistoryParams; import org.knowm.xchange.service.trade.params.TradeHistoryParamsTimeSpan; +import java.io.IOException; +import java.util.List; +import java.util.Objects; + public class GateioAccountServiceRaw extends GateioBaseService { public GateioAccountServiceRaw(GateioExchange exchange) { @@ -160,4 +153,20 @@ public List getSubAccountTransfers( params.getPageLength(), params.getZeroBasedPageNumber()); } + + public void setLeverage(String settle, String contract, String leverage) throws IOException { + try { + GateioPositionLeverageUpdate positionLeverageUpdate = + gateioV4Authenticated.updatePositionLeverage( + apiKey, + exchange.getNonceFactory(), + gateioV4ParamsDigest, + settle, + contract, + leverage); + Objects.requireNonNull(positionLeverageUpdate); + } catch (GateioException e) { + throw GateioErrorAdapter.adapt(e); + } + } } diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioMarketDataService.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioMarketDataService.java index c3bb6447b7d..4190b8db904 100644 --- a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioMarketDataService.java +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioMarketDataService.java @@ -1,15 +1,11 @@ package org.knowm.xchange.gateio.service; -import java.io.IOException; -import java.time.Duration; -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; +import lombok.Setter; import org.apache.commons.lang3.Validate; import org.knowm.xchange.currency.Currency; 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.OrderBook; import org.knowm.xchange.dto.marketdata.Ticker; import org.knowm.xchange.dto.meta.ExchangeHealth; @@ -19,17 +15,26 @@ import org.knowm.xchange.gateio.GateioExchange; import org.knowm.xchange.gateio.config.Config; import org.knowm.xchange.gateio.dto.GateioException; -import org.knowm.xchange.gateio.dto.marketdata.GateioCurrencyInfo; -import org.knowm.xchange.gateio.dto.marketdata.GateioCurrencyPairDetails; -import org.knowm.xchange.gateio.dto.marketdata.GateioOrderBook; -import org.knowm.xchange.gateio.dto.marketdata.GateioTicker; +import org.knowm.xchange.gateio.dto.marketdata.*; 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 java.io.IOException; +import java.time.Duration; +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; public class GateioMarketDataService extends GateioMarketDataServiceRaw implements MarketDataService { - + @Setter + private Map instrumentMetaDataMap; public GateioMarketDataService(GateioExchange exchange) { super(exchange); } @@ -122,18 +127,102 @@ public List getCurrencyPairs() throws IOException { public Map getMetaDataByInstrument() throws IOException { try { - List metadata = getCurrencyPairDetails(); + if (exchange.isFuturesEnabled()) { + List metadata = getInstrumentDetails(); + return metadata.stream().filter(f -> f.getType().equals("direct") && + f.getStatus().equals("trading")) + .collect( + Collectors.toMap( + gateioInstrumentDetails -> + new FuturesContract( + new CurrencyPair(gateioInstrumentDetails.getName().replace("_", "/")), + "PERP"), + GateioAdapters::instrumentToInstrumentMetaData)); + } else { + List metadata = getCurrencyPairDetails(); + + return metadata.stream() + .collect( + Collectors.toMap( + gateioCurrencyPairDetails -> + new CurrencyPair( + gateioCurrencyPairDetails.getAsset(), + gateioCurrencyPairDetails.getQuote()), + GateioAdapters::currencyPairToInstrumentMetaData)); + } + } catch (GateioException e) { + throw GateioErrorAdapter.adapt(e); + } + } - return metadata.stream() - .collect( - Collectors.toMap( - gateioCurrencyPairDetails -> - new CurrencyPair( - gateioCurrencyPairDetails.getAsset(), - gateioCurrencyPairDetails.getQuote()), - GateioAdapters::toInstrumentMetaData)); + @Override + public CandleStickData getCandleStickData(CurrencyPair currencyPair, CandleStickDataParams params) + throws IOException { + return getCandleStickData((Instrument) currencyPair, params); + } + + /** + * K-line chart data returns a maximum of 1000 points per request. When specifying from, to, and interval, ensure the number of points is not excessive + * + * @param instrument instrument. + * @param params Params for query, including start(e.g. march 2022.) and end date, period etc., + * @return + * @throws IOException + */ + @Override + public CandleStickData getCandleStickData(Instrument instrument, CandleStickDataParams params) + throws IOException { + Long from = null; + Long to = null; + Integer limit = null; + String interval = "1h"; // default + if (params instanceof DefaultCandleStickParamWithLimit) { + DefaultCandleStickParamWithLimit p = + (DefaultCandleStickParamWithLimit) params; + limit = p.getLimit(); + if (p.getPeriodInSecs() > 0) { + interval = adaptInterval(p.getPeriodInSecs()); + } + } + // limit OR (from, to) + else if (params instanceof DefaultCandleStickParam) { + DefaultCandleStickParam p = + (DefaultCandleStickParam) params; + if (p.getStartDate() != null) { + from = p.getStartDate().getTime() / 1000; + } + if (p.getEndDate() != null) { + to = p.getEndDate().getTime() / 1000; + } + if (p.getPeriodInSecs() > 0) { + interval = adaptInterval(p.getPeriodInSecs()); + } + } + try { + if (instrument instanceof FuturesContract) { + List gateiFuturesCandlesticks = getGateioFuturesCandlesticks(instrument, limit, from, to, interval); + return GateioAdapters.toCandleStickDataFutures(gateiFuturesCandlesticks, instrument, instrumentMetaDataMap.get(instrument).getContractValue()); + } else { + List gateioSpotCandlesticks = getGateioSpotCandlesticks(instrument, limit, from, to, interval); + return GateioAdapters.toCandleStickDataSpot(gateioSpotCandlesticks, instrument); + } } catch (GateioException e) { throw GateioErrorAdapter.adapt(e); } } + + private String adaptInterval(long periodInSecs) { + if (periodInSecs == 10) return "10s"; + if (periodInSecs == 60) return "1m"; + if (periodInSecs == 300) return "5m"; + if (periodInSecs == 900) return "15m"; + if (periodInSecs == 1800) return "30m"; + if (periodInSecs == 3600) return "1h"; + if (periodInSecs == 14400) return "4h"; + if (periodInSecs == 28800) return "8h"; + if (periodInSecs == 86400) return "1d"; + if (periodInSecs == 604800) return "7d"; + if (periodInSecs == 2592000) return "30d"; + return "1h"; + } } diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioMarketDataServiceRaw.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioMarketDataServiceRaw.java index 3affd6ba5c0..0845cd35457 100644 --- a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioMarketDataServiceRaw.java +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioMarketDataServiceRaw.java @@ -1,18 +1,14 @@ package org.knowm.xchange.gateio.service; -import java.io.IOException; -import java.util.List; import org.knowm.xchange.currency.Currency; import org.knowm.xchange.gateio.GateioAdapters; import org.knowm.xchange.gateio.GateioExchange; -import org.knowm.xchange.gateio.dto.marketdata.GateioCurrencyChain; -import org.knowm.xchange.gateio.dto.marketdata.GateioCurrencyInfo; -import org.knowm.xchange.gateio.dto.marketdata.GateioCurrencyPairDetails; -import org.knowm.xchange.gateio.dto.marketdata.GateioOrderBook; -import org.knowm.xchange.gateio.dto.marketdata.GateioServerTime; -import org.knowm.xchange.gateio.dto.marketdata.GateioTicker; +import org.knowm.xchange.gateio.dto.marketdata.*; import org.knowm.xchange.instrument.Instrument; +import java.io.IOException; +import java.util.List; + public class GateioMarketDataServiceRaw extends GateioBaseService { public GateioMarketDataServiceRaw(GateioExchange exchange) { @@ -24,7 +20,7 @@ public GateioServerTime getGateioServerTime() throws IOException { } public List getGateioTickers(Instrument instrument) throws IOException { - return gateio.getTickers(GateioAdapters.toString(instrument)); + return gateio.getTickers(GateioAdapters.toGateioInstrument(instrument)); } public List getGateioCurrencyInfos() throws IOException { @@ -32,7 +28,7 @@ public List getGateioCurrencyInfos() throws IOException { } public GateioOrderBook getGateioOrderBook(Instrument instrument) throws IOException { - return gateio.getOrderBook(GateioAdapters.toString(instrument), false); + return gateio.getOrderBook(GateioAdapters.toGateioInstrument(instrument), false); } public List getCurrencyChains(Currency currency) throws IOException { @@ -43,8 +39,26 @@ public List getCurrencyPairDetails() throws IOExcepti return gateio.getCurrencyPairDetails(); } + public List getInstrumentDetails() throws IOException { + return gateio.getInstrumentDetails(); + } + public GateioCurrencyPairDetails getCurrencyPairDetails(Instrument instrument) throws IOException { - return gateio.getCurrencyPairDetails(GateioAdapters.toString(instrument)); + return gateio.getCurrencyPairDetails(GateioAdapters.toGateioInstrument(instrument)); + } + + public List getGateioSpotCandlesticks( + Instrument instrument, Integer limit, Long from, Long to, String interval) + throws IOException { + return gateio.getSpotCandlesticks( + GateioAdapters.toGateioInstrument(instrument), limit, from, to, interval); + } + + public List getGateioFuturesCandlesticks( + Instrument instrument, Integer limit, Long from, Long to, String interval) + throws IOException { + return gateio.getFuturesCandlesticks(instrument.getCounter().toString().toLowerCase(), + GateioAdapters.toGateioInstrument(instrument), limit, from, to, interval); } } diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioTradeServiceRaw.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioTradeServiceRaw.java index 10776e8a3aa..c4c801d2bf1 100644 --- a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioTradeServiceRaw.java +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioTradeServiceRaw.java @@ -1,11 +1,5 @@ package org.knowm.xchange.gateio.service; -import java.io.IOException; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; -import java.util.Objects; -import java.util.Set; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.Validate; import org.knowm.xchange.currency.CurrencyPair; @@ -15,12 +9,10 @@ import org.knowm.xchange.gateio.dto.account.GateioOrder; import org.knowm.xchange.gateio.dto.trade.GateioUserTradeRaw; import org.knowm.xchange.instrument.Instrument; -import org.knowm.xchange.service.trade.params.CurrencyPairParam; -import org.knowm.xchange.service.trade.params.TradeHistoryParamCurrencyPair; -import org.knowm.xchange.service.trade.params.TradeHistoryParamPaging; -import org.knowm.xchange.service.trade.params.TradeHistoryParamTransactionId; -import org.knowm.xchange.service.trade.params.TradeHistoryParams; -import org.knowm.xchange.service.trade.params.TradeHistoryParamsTimeSpan; +import org.knowm.xchange.service.trade.params.*; + +import java.io.IOException; +import java.util.*; public class GateioTradeServiceRaw extends GateioBaseService { @@ -43,8 +35,8 @@ public List listOrders(Instrument instrument, OrderStatus orderStat apiKey, exchange.getNonceFactory(), gateioV4ParamsDigest, - GateioAdapters.toString(instrument), - GateioAdapters.toString(orderStatus)); + GateioAdapters.toGateioInstrument(instrument), + GateioAdapters.toGateioInstrument(orderStatus)); } public List getGateioUserTrades(TradeHistoryParams params) @@ -90,7 +82,7 @@ public List getGateioUserTrades(TradeHistoryParams params) apiKey, exchange.getNonceFactory(), gateioV4ParamsDigest, - GateioAdapters.toString(currencyPair), + GateioAdapters.toGateioInstrument(currencyPair), 1000, currentPageNumber, orderId, @@ -108,7 +100,7 @@ public List getGateioUserTrades(TradeHistoryParams params) apiKey, exchange.getNonceFactory(), gateioV4ParamsDigest, - GateioAdapters.toString(currencyPair), + GateioAdapters.toGateioInstrument(currencyPair), pageLength, pageNumber, orderId, @@ -128,7 +120,7 @@ public GateioOrder getOrder(String orderId, Instrument instrument) throws IOExce exchange.getNonceFactory(), gateioV4ParamsDigest, orderId, - GateioAdapters.toString(instrument)); + GateioAdapters.toGateioInstrument(instrument)); } public GateioOrder cancelOrderRaw(String orderId, Instrument instrument) throws IOException { @@ -137,6 +129,6 @@ public GateioOrder cancelOrderRaw(String orderId, Instrument instrument) throws exchange.getNonceFactory(), gateioV4ParamsDigest, orderId, - GateioAdapters.toString(instrument)); + GateioAdapters.toGateioInstrument(instrument)); } } diff --git a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioV4Digest.java b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioV4Digest.java index f7b439ac247..8cba163a706 100644 --- a/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioV4Digest.java +++ b/xchange-gateio-v4/src/main/java/org/knowm/xchange/gateio/service/GateioV4Digest.java @@ -1,13 +1,15 @@ package org.knowm.xchange.gateio.service; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import javax.crypto.Mac; import lombok.SneakyThrows; +import org.apache.commons.lang3.StringUtils; import org.knowm.xchange.service.BaseParamsDigest; import org.knowm.xchange.utils.DigestUtils; import si.mazi.rescu.RestInvocation; +import javax.crypto.Mac; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; + public final class GateioV4Digest extends BaseParamsDigest { private GateioV4Digest(String secretKeyBase64) { @@ -25,8 +27,8 @@ public String digestParams(RestInvocation restInvocation) { String method = restInvocation.getHttpMethod(); String path = restInvocation.getPath(); - String query = restInvocation.getQueryString(); - String body = restInvocation.getRequestBody(); + String query = StringUtils.defaultString(restInvocation.getQueryString()); + String body = StringUtils.defaultString(restInvocation.getRequestBody()); MessageDigest md = MessageDigest.getInstance("SHA-512"); String hexedHashedBody = DigestUtils.bytesToHex(md.digest(body.getBytes(StandardCharsets.UTF_8))); diff --git a/xchange-gateio-v4/src/test/java/org/knowm/xchange/gateio/GateioAdaptersTest.java b/xchange-gateio-v4/src/test/java/org/knowm/xchange/gateio/GateioAdaptersTest.java new file mode 100644 index 00000000000..5ed695dae93 --- /dev/null +++ b/xchange-gateio-v4/src/test/java/org/knowm/xchange/gateio/GateioAdaptersTest.java @@ -0,0 +1,84 @@ +package org.knowm.xchange.gateio; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.knowm.xchange.currency.CurrencyPair; +import org.knowm.xchange.derivative.FuturesContract; +import org.knowm.xchange.dto.marketdata.CandleStickData; +import org.knowm.xchange.dto.meta.InstrumentMetaData; +import org.knowm.xchange.gateio.dto.marketdata.GateioFuturesCandlestick; +import org.knowm.xchange.gateio.dto.marketdata.GateioInstrumentDetails; +import org.knowm.xchange.gateio.dto.marketdata.GateioSpotCandlestick; +import org.knowm.xchange.utils.ObjectMapperHelper; + +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; + +class GateioAdaptersTest { + + @Test + void testToCandleStickDataSpotFutures() throws IOException { + try (InputStream is = getClass().getResourceAsStream("futures_candlesticks.json")) { + Assertions.assertNotNull(is); + GateioFuturesCandlestick[] candlesticks = ObjectMapperHelper.readValue(new String(is.readAllBytes()), GateioFuturesCandlestick[].class); + + FuturesContract instrument = new FuturesContract("BTC/USDT/PERP"); + CandleStickData candleStickData = GateioAdapters.toCandleStickDataFutures( + Arrays.asList(candlesticks), instrument, new BigDecimal("0.0001")); + + assertThat(candleStickData.getInstrument()).isEqualTo(instrument); + assertThat(candleStickData.getCandleSticks()).hasSize(1); + assertThat(candleStickData.getCandleSticks().get(0).getOpen()).isEqualTo(new BigDecimal("100")); + assertThat(candleStickData.getCandleSticks().get(0).getHigh()).isEqualTo(new BigDecimal("110")); + assertThat(candleStickData.getCandleSticks().get(0).getLow()).isEqualTo(new BigDecimal("90")); + assertThat(candleStickData.getCandleSticks().get(0).getClose()).isEqualTo(new BigDecimal("105")); + assertThat(candleStickData.getCandleSticks().get(0).getVolume()).isEqualTo(new BigDecimal("10")); + assertThat(candleStickData.getCandleSticks().get(0).getQuotaVolume()).isEqualTo(new BigDecimal("1000")); + } + } + + @Test + void testToCandleStickDataSpotSpot() throws IOException { + try (InputStream is = getClass().getResourceAsStream("spot_candlesticks.json")) { + Assertions.assertNotNull(is); + GateioSpotCandlestick[] candlesticks = ObjectMapperHelper.readValue(new String(is.readAllBytes()), GateioSpotCandlestick[].class); + + CurrencyPair instrument = CurrencyPair.BTC_USDT; + CandleStickData candleStickData = GateioAdapters.toCandleStickDataSpot( + Arrays.asList(candlesticks), instrument); + + assertThat(candleStickData.getInstrument()).isEqualTo(instrument); + assertThat(candleStickData.getCandleSticks()).hasSize(1); + assertThat(candleStickData.getCandleSticks().get(0).getOpen()).isEqualTo(new BigDecimal("100")); + assertThat(candleStickData.getCandleSticks().get(0).getHigh()).isEqualTo(new BigDecimal("110")); + assertThat(candleStickData.getCandleSticks().get(0).getLow()).isEqualTo(new BigDecimal("90")); + assertThat(candleStickData.getCandleSticks().get(0).getClose()).isEqualTo(new BigDecimal("105")); + assertThat(candleStickData.getCandleSticks().get(0).getVolume()).isEqualTo(new BigDecimal("1000")); + assertThat(candleStickData.getCandleSticks().get(0).getQuotaVolume()).isEqualTo(new BigDecimal("10")); + } + } + + @Test + void testInstrumentToInstrumentMetaData() throws IOException { + try (InputStream is = getClass().getResourceAsStream("instrument_details.json")) { + Assertions.assertNotNull(is); + GateioInstrumentDetails[] detailsArray = ObjectMapperHelper.readValue(new String(is.readAllBytes()), GateioInstrumentDetails[].class); + GateioInstrumentDetails details = detailsArray[0]; + + InstrumentMetaData metaData = GateioAdapters.instrumentToInstrumentMetaData(details); + + assertThat(metaData.getTradingFee()).isEqualByComparingTo(new BigDecimal("0.00075")); + assertThat(metaData.getMinimumAmount()).isEqualByComparingTo(new BigDecimal("0.0001")); + assertThat(metaData.getMaximumAmount()).isEqualByComparingTo(new BigDecimal("100")); + assertThat(metaData.getPriceStepSize()).isEqualByComparingTo(new BigDecimal("0.1")); + assertThat(metaData.getAmountStepSize()).isEqualByComparingTo(new BigDecimal("0.0001")); + assertThat(metaData.getVolumeScale()).isEqualTo(4); + assertThat(metaData.getPriceScale()).isEqualTo(1); + assertThat(metaData.getContractValue()).isEqualByComparingTo(new BigDecimal("0.0001")); + } + } +} diff --git a/xchange-gateio-v4/src/test/java/org/knowm/xchange/gateio/examples/GateioFuturesTest.java b/xchange-gateio-v4/src/test/java/org/knowm/xchange/gateio/examples/GateioFuturesTest.java new file mode 100644 index 00000000000..f7ac6fac971 --- /dev/null +++ b/xchange-gateio-v4/src/test/java/org/knowm/xchange/gateio/examples/GateioFuturesTest.java @@ -0,0 +1,50 @@ +package org.knowm.xchange.gateio.examples; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.knowm.xchange.Exchange; +import org.knowm.xchange.ExchangeFactory; +import org.knowm.xchange.ExchangeSpecification; +import org.knowm.xchange.derivative.FuturesContract; +import org.knowm.xchange.gateio.GateioExchange; +import org.knowm.xchange.instrument.Instrument; +import org.knowm.xchange.service.trade.params.CandleStickDataParams; +import org.knowm.xchange.service.trade.params.DefaultCandleStickParamWithLimit; +import org.knowm.xchange.utils.AuthUtils; + +import java.io.IOException; +import java.util.Date; + +import static org.knowm.xchange.gateio.GateioExchange.EXCHANGE_TYPE; +import static org.knowm.xchange.gateio.dto.GateioExchangeType.FUTURES; + +public class GateioFuturesTest { + private static final Instrument instrument = new FuturesContract("ETH/USDT/PERP"); + public static Exchange exchange; + + @Before + public void before() throws IOException { + init(); + } + + @Test + @Ignore + public void candleStick() throws IOException { + CandleStickDataParams params = new DefaultCandleStickParamWithLimit(new Date(System.currentTimeMillis() - 86400000 * 4), new Date(), 86400, 2); + exchange.getMarketDataService().getCandleStickData(instrument, params).getCandleSticks().forEach(System.out::println); + } + + @Test + public void setLeverage() throws IOException { + exchange.getAccountService().setLeverage(instrument, 1); + } + + private void init() { + ExchangeSpecification exchangeSpecification = + new ExchangeSpecification(GateioExchange.class); + exchangeSpecification.setExchangeSpecificParametersItem(EXCHANGE_TYPE, FUTURES); + AuthUtils.setApiAndSecretKey(exchangeSpecification, "gateio-main"); + exchange = ExchangeFactory.INSTANCE.createExchange(exchangeSpecification); + } +} diff --git a/xchange-gateio-v4/src/test/java/org/knowm/xchange/gateio/examples/GateioSpotTest.java b/xchange-gateio-v4/src/test/java/org/knowm/xchange/gateio/examples/GateioSpotTest.java new file mode 100644 index 00000000000..8f623f1fb43 --- /dev/null +++ b/xchange-gateio-v4/src/test/java/org/knowm/xchange/gateio/examples/GateioSpotTest.java @@ -0,0 +1,37 @@ +package org.knowm.xchange.gateio.examples; + +import org.knowm.xchange.Exchange; +import org.knowm.xchange.ExchangeFactory; +import org.knowm.xchange.ExchangeSpecification; +import org.knowm.xchange.currency.CurrencyPair; +import org.knowm.xchange.gateio.GateioExchange; +import org.knowm.xchange.instrument.Instrument; +import org.knowm.xchange.service.trade.params.CandleStickDataParams; +import org.knowm.xchange.service.trade.params.DefaultCandleStickParam; +import org.knowm.xchange.utils.AuthUtils; + +import java.io.IOException; +import java.util.Date; + +public class GateioSpotTest { + private static final Instrument currencyPair = CurrencyPair.BTC_USDT; + public static Exchange exchange; + + public static void main(String[] args) throws IOException, InterruptedException { + init(); + Thread.sleep(1000); + candleStick(); + } + + private static void candleStick() throws IOException { + CandleStickDataParams params = new DefaultCandleStickParam(new Date(System.currentTimeMillis() - 86400000 * 4), new Date(), 86400); + exchange.getMarketDataService().getCandleStickData(currencyPair, params).getCandleSticks().forEach(System.out::println); + } + + private static void init() { + ExchangeSpecification exchangeSpecification = + new ExchangeSpecification(GateioExchange.class); + AuthUtils.setApiAndSecretKey(exchangeSpecification, "gateio-main"); + exchange = ExchangeFactory.INSTANCE.createExchange(exchangeSpecification); + } +} diff --git a/xchange-gateio-v4/src/test/java/org/knowm/xchange/gateio/service/GateioV4DigestTest.java b/xchange-gateio-v4/src/test/java/org/knowm/xchange/gateio/service/GateioV4DigestTest.java index 9f9594c7231..63dd4ecced4 100644 --- a/xchange-gateio-v4/src/test/java/org/knowm/xchange/gateio/service/GateioV4DigestTest.java +++ b/xchange-gateio-v4/src/test/java/org/knowm/xchange/gateio/service/GateioV4DigestTest.java @@ -1,16 +1,17 @@ package org.knowm.xchange.gateio.service; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; - -import java.util.HashMap; -import java.util.Map; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import si.mazi.rescu.RestInvocation; +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + @ExtendWith(MockitoExtension.class) class GateioV4DigestTest { @@ -34,4 +35,23 @@ void signature() { assertThat(actual).isEqualTo(expected); } + + @Test + void signatureWithNullBody() { + GateioV4Digest gateioV4Digest = GateioV4Digest.createInstance("b"); + + when(restInvocation.getHttpMethod()).thenReturn("POST"); + when(restInvocation.getPath()).thenReturn("a"); + when(restInvocation.getQueryString()).thenReturn("?b=c"); + when(restInvocation.getRequestBody()).thenReturn(null); + Map headers = new HashMap<>(); + headers.put("Timestamp", "1691707273890"); + when(restInvocation.getHttpHeadersFromParams()).thenReturn(headers); + + String actual = gateioV4Digest.digestParams(restInvocation); + String expected = + "cc2c75d1db1a1fcf354f7bce55f3126c5a46829449e8f6c087b785d71b12aa142fee8fb9750f60a2cdea4fd84f8e7f1835a21a47d6709cc92b4ff757f7ccdbd1"; + + assertThat(actual).isEqualTo(expected); + } } diff --git a/xchange-gateio-v4/src/test/resources/logback.xml b/xchange-gateio-v4/src/test/resources/logback.xml index c823ac40a99..0a2a5c7e0ef 100644 --- a/xchange-gateio-v4/src/test/resources/logback.xml +++ b/xchange-gateio-v4/src/test/resources/logback.xml @@ -17,7 +17,7 @@ - - + + diff --git a/xchange-gateio-v4/src/test/resources/org/knowm/xchange/gateio/futures_candlesticks.json b/xchange-gateio-v4/src/test/resources/org/knowm/xchange/gateio/futures_candlesticks.json new file mode 100644 index 00000000000..f7946494d61 --- /dev/null +++ b/xchange-gateio-v4/src/test/resources/org/knowm/xchange/gateio/futures_candlesticks.json @@ -0,0 +1,11 @@ +[ + { + "t": 1600000000, + "v": 10, + "c": "105", + "h": "110", + "l": "90", + "o": "100", + "sum": "1000" + } +] diff --git a/xchange-gateio-v4/src/test/resources/org/knowm/xchange/gateio/instrument_details.json b/xchange-gateio-v4/src/test/resources/org/knowm/xchange/gateio/instrument_details.json new file mode 100644 index 00000000000..d407978c589 --- /dev/null +++ b/xchange-gateio-v4/src/test/resources/org/knowm/xchange/gateio/instrument_details.json @@ -0,0 +1,55 @@ +[ + { + "name": "BTC_USDT", + "type": "direct", + "quanto_multiplier": "0.0001", + "ref_discount_rate": "0", + "order_price_deviate": "0.5", + "maintenance_rate": "0.005", + "mark_type": "index", + "last_price": "38026", + "mark_price": "37985.6", + "index_price": "37954.92", + "funding_rate_indicative": "0.000219", + "mark_price_round": "0.01", + "funding_offset": 0, + "in_delisting": false, + "risk_limit_base": "1000000", + "interest_rate": "0.0003", + "order_price_round": "0.1", + "order_size_min": "1", + "enable_decimal": false, + "ref_rebate_rate": "0.2", + "funding_interval": 28800, + "risk_limit_step": "1000000", + "leverage_min": "1", + "leverage_max": "100", + "risk_limit_max": "8000000", + "maker_fee_rate": "-0.00025", + "taker_fee_rate": "0.00075", + "funding_rate": "0.002053", + "order_size_max": "1000000", + "funding_next_apply": 1610035200, + "short_users": 977, + "config_change_time": 1609899548, + "trade_size": "28530850594", + "position_size": "5223816", + "long_users": 455, + "funding_impact_value": "60000", + "orders_limit": 50, + "trade_id": 10851092, + "orderbook_id": 2129638396, + "enable_bonus": true, + "enable_credit": true, + "create_time": 1669688556, + "funding_cap_ratio": "0.75", + "status": "trading", + "launch_time": 1609899548, + "delisting_time": 1609899548, + "delisted_time": 1609899548, + "market_order_slip_ratio": "0.05", + "market_order_size_max": "0", + "funding_rate_limit": "0.003", + "contract_type": "indices" + } +] diff --git a/xchange-gateio-v4/src/test/resources/org/knowm/xchange/gateio/spot_candlesticks.json b/xchange-gateio-v4/src/test/resources/org/knowm/xchange/gateio/spot_candlesticks.json new file mode 100644 index 00000000000..e242b6b5c43 --- /dev/null +++ b/xchange-gateio-v4/src/test/resources/org/knowm/xchange/gateio/spot_candlesticks.json @@ -0,0 +1,12 @@ +[ + [ + "1600000000", + "10", + "105", + "110", + "90", + "100", + "1000", + "true" + ] +]