All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.knowm.xchange.kucoin.KucoinAdapters Maven / Gradle / Ivy
package org.knowm.xchange.kucoin;
import static java.util.stream.Collectors.toCollection;
import static org.knowm.xchange.dto.Order.OrderStatus.CANCELED;
import static org.knowm.xchange.dto.Order.OrderStatus.NEW;
import static org.knowm.xchange.dto.Order.OrderStatus.PARTIALLY_FILLED;
import static org.knowm.xchange.dto.Order.OrderStatus.UNKNOWN;
import static org.knowm.xchange.dto.Order.OrderType.ASK;
import static org.knowm.xchange.dto.Order.OrderType.BID;
import static org.knowm.xchange.kucoin.dto.KucoinOrderFlags.HIDDEN;
import static org.knowm.xchange.kucoin.dto.KucoinOrderFlags.ICEBERG;
import static org.knowm.xchange.kucoin.dto.KucoinOrderFlags.POST_ONLY;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Ordering;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.knowm.xchange.currency.Currency;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.dto.Order;
import org.knowm.xchange.dto.Order.IOrderFlags;
import org.knowm.xchange.dto.Order.OrderStatus;
import org.knowm.xchange.dto.Order.OrderType;
import org.knowm.xchange.dto.account.Balance;
import org.knowm.xchange.dto.marketdata.OrderBook;
import org.knowm.xchange.dto.marketdata.Ticker;
import org.knowm.xchange.dto.marketdata.Trade;
import org.knowm.xchange.dto.marketdata.Trades;
import org.knowm.xchange.dto.marketdata.Trades.TradeSortType;
import org.knowm.xchange.dto.meta.CurrencyMetaData;
import org.knowm.xchange.dto.meta.CurrencyPairMetaData;
import org.knowm.xchange.dto.meta.ExchangeMetaData;
import org.knowm.xchange.dto.trade.LimitOrder;
import org.knowm.xchange.dto.trade.MarketOrder;
import org.knowm.xchange.dto.trade.StopOrder;
import org.knowm.xchange.dto.trade.UserTrade;
import org.knowm.xchange.exceptions.ExchangeException;
import org.knowm.xchange.kucoin.KucoinTradeService.KucoinOrderFlags;
import org.knowm.xchange.kucoin.dto.request.OrderCreateApiRequest;
import org.knowm.xchange.kucoin.dto.response.AccountBalancesResponse;
import org.knowm.xchange.kucoin.dto.response.OrderBookResponse;
import org.knowm.xchange.kucoin.dto.response.OrderResponse;
import org.knowm.xchange.kucoin.dto.response.SymbolResponse;
import org.knowm.xchange.kucoin.dto.response.SymbolTickResponse;
import org.knowm.xchange.kucoin.dto.response.TradeHistoryResponse;
import org.knowm.xchange.kucoin.dto.response.TradeResponse;
public class KucoinAdapters {
public static String adaptCurrencyPair(CurrencyPair pair) {
return pair == null ? null : pair.base.getCurrencyCode() + "-" + pair.counter.getCurrencyCode();
}
public static CurrencyPair adaptCurrencyPair(String symbol) {
String[] split = symbol.split("-");
if (split.length != 2) {
throw new ExchangeException("Invalid kucoin symbol: " + symbol);
}
return new CurrencyPair(split[0], split[1]);
}
public static Ticker.Builder adaptTickerFull(CurrencyPair pair, SymbolTickResponse stats) {
return new Ticker.Builder()
.currencyPair(pair)
.bid(stats.getBuy())
.ask(stats.getSell())
.last(stats.getLast())
.high(stats.getHigh())
.low(stats.getLow())
.volume(stats.getVol())
.quoteVolume(stats.getVolValue())
.open(stats.getOpen())
.timestamp(new Date(stats.getTime()));
}
/**
* Imperfect implementation. Kucoin appears to enforce a base and quote min
* and max amount that the XChange API current doesn't take account of.
*
* @param exchangeMetaData The static exchange metadata.
* @param kucoinSymbols Kucoin symbol data.
* @return Exchange metadata.
*/
public static ExchangeMetaData adaptMetadata(
ExchangeMetaData exchangeMetaData, List kucoinSymbols) {
Map currencyPairs = exchangeMetaData.getCurrencyPairs();
Map currencies = exchangeMetaData.getCurrencies();
for (SymbolResponse symbol : kucoinSymbols) {
CurrencyPair pair = adaptCurrencyPair(symbol.getSymbol());
CurrencyPairMetaData staticMetaData = exchangeMetaData.getCurrencyPairs().get(pair);
BigDecimal minSize = symbol.getBaseMinSize();
BigDecimal maxSize = symbol.getBaseMaxSize();
int priceScale = symbol.getQuoteIncrement().stripTrailingZeros().scale();
CurrencyPairMetaData cpmd =
new CurrencyPairMetaData(
null,
minSize,
maxSize,
priceScale,
staticMetaData != null ? staticMetaData.getFeeTiers() : null);
currencyPairs.put(pair, cpmd);
if (!currencies.containsKey(pair.base)) currencies.put(pair.base, null);
if (!currencies.containsKey(pair.counter)) currencies.put(pair.counter, null);
}
return new ExchangeMetaData(
currencyPairs,
currencies,
exchangeMetaData.getPublicRateLimits(),
exchangeMetaData.getPrivateRateLimits(),
true);
}
public static OrderBook adaptOrderBook(CurrencyPair currencyPair, OrderBookResponse kc) {
Date timestamp = new Date(Long.parseLong(kc.getSequence()));
List asks =
kc.getAsks().stream()
.map(PriceAndSize::new)
.sorted(Ordering.natural().onResultOf(s -> s.price))
.map(s -> adaptLimitOrder(currencyPair, ASK, s, timestamp))
.collect(toCollection(LinkedList::new));
List bids =
kc.getBids().stream()
.map(PriceAndSize::new)
.sorted(Ordering.natural().onResultOf((PriceAndSize s) -> s.price).reversed())
.map(s -> adaptLimitOrder(currencyPair, BID, s, timestamp))
.collect(toCollection(LinkedList::new));
return new OrderBook(timestamp, asks, bids);
}
private static LimitOrder adaptLimitOrder(
CurrencyPair currencyPair, OrderType orderType, PriceAndSize priceAndSize, Date timestamp) {
return new LimitOrder.Builder(orderType, currencyPair)
.limitPrice(priceAndSize.price)
.originalAmount(priceAndSize.size)
.orderStatus(NEW)
.build();
}
public static Trades adaptTrades(
CurrencyPair currencyPair, List kucoinTrades) {
return new Trades(
kucoinTrades.stream().map(o -> adaptTrade(currencyPair, o)).collect(Collectors.toList()),
TradeSortType.SortByTimestamp);
}
public static Balance adaptBalance(AccountBalancesResponse a) {
return new Balance(Currency.getInstance(a.getCurrency()), a.getBalance(), a.getAvailable());
}
private static Trade adaptTrade(CurrencyPair currencyPair, TradeHistoryResponse trade) {
return new Trade.Builder()
.currencyPair(currencyPair)
.originalAmount(trade.getSize())
.price(trade.getPrice())
.timestamp(new Date(Long.parseLong(trade.getSequence())))
.type(adaptSide(trade.getSide()))
.build();
}
private static OrderType adaptSide(String side) {
return "sell".equals(side) ? ASK : BID;
}
private static String adaptSide(OrderType type) {
return type.equals(ASK) ? "sell" : "buy";
}
public static Order adaptOrder(OrderResponse order) {
OrderType orderType = adaptSide(order.getSide());
CurrencyPair currencyPair = adaptCurrencyPair(order.getSymbol());
OrderStatus status;
if (order.isCancelExist()) {
status = CANCELED;
} else if (order.isActive()) {
if (order.getDealSize().signum() == 0) {
status = NEW;
} else {
status = PARTIALLY_FILLED;
}
} else {
status = UNKNOWN;
}
Order.Builder builder;
if (StringUtils.isNotEmpty(order.getStop())) {
BigDecimal limitPrice = order.getPrice();
if (limitPrice != null && limitPrice.compareTo(BigDecimal.ZERO) == 0) {
limitPrice = null;
}
builder =
new StopOrder.Builder(orderType, currencyPair)
.limitPrice(limitPrice)
.stopPrice(order.getStopPrice());
} else {
builder = new LimitOrder.Builder(orderType, currencyPair).limitPrice(order.getPrice());
}
builder =
builder
.averagePrice(
order.getDealSize().compareTo(BigDecimal.ZERO) == 0
? MoreObjects.firstNonNull(order.getPrice(), order.getStopPrice())
: order.getDealFunds().divide(order.getDealSize(), RoundingMode.HALF_UP))
.cumulativeAmount(order.getDealSize())
.fee(order.getFee())
.id(order.getId())
.orderStatus(status)
.originalAmount(order.getSize())
.remainingAmount(order.getSize().subtract(order.getDealSize()))
.timestamp(order.getCreatedAt());
if (StringUtils.isNotEmpty(order.getTimeInForce())) {
builder.flag(TimeInForce.getTimeInForce(order.getTimeInForce()));
}
return StopOrder.Builder.class.isInstance(builder)
? ((StopOrder.Builder) builder).build()
: ((LimitOrder.Builder) builder).build();
}
public static UserTrade adaptUserTrade(TradeResponse trade) {
return new UserTrade.Builder()
.currencyPair(adaptCurrencyPair(trade.getSymbol()))
.feeAmount(trade.getFee())
.feeCurrency(Currency.getInstance(trade.getFeeCurrency()))
.id(trade.getTradeId())
.orderId(trade.getOrderId())
.originalAmount(trade.getSize())
.price(trade.getPrice())
.timestamp(trade.getTradeCreatedAt())
.type(adaptSide(trade.getSide()))
.build();
}
public static OrderCreateApiRequest adaptLimitOrder(LimitOrder limitOrder) {
return ((OrderCreateApiRequest.OrderCreateApiRequestBuilder) adaptOrder(limitOrder))
.type("limit")
.price(limitOrder.getLimitPrice())
.postOnly(limitOrder.hasFlag(POST_ONLY))
.hidden(limitOrder.hasFlag(HIDDEN))
.iceberg(limitOrder.hasFlag(ICEBERG))
.build();
}
public static OrderCreateApiRequest adaptStopOrder(StopOrder stopOrder) {
return ((OrderCreateApiRequest.OrderCreateApiRequestBuilder) adaptOrder(stopOrder))
.type(stopOrder.getLimitPrice() == null ? "market" : "limit")
.price(stopOrder.getLimitPrice())
.stop(stopOrder.getType().equals(ASK) ? "loss" : "entry")
.stopPrice(stopOrder.getStopPrice())
.build();
}
public static OrderCreateApiRequest adaptMarketOrder(MarketOrder marketOrder) {
return ((OrderCreateApiRequest.OrderCreateApiRequestBuilder) adaptOrder(marketOrder))
.type("market")
.build();
}
/**
* Returns {@code Object} instead of the Lombok builder in order to avoid a Lombok limitation with
* Javadoc.
*/
private static Object adaptOrder(Order order) {
OrderCreateApiRequest.OrderCreateApiRequestBuilder request = OrderCreateApiRequest.builder();
boolean hasClientId = false;
for (IOrderFlags flag : order.getOrderFlags()) {
if (flag instanceof KucoinOrderFlags) {
request.clientOid(((KucoinOrderFlags) flag).getClientId());
hasClientId = true;
} else if (flag instanceof TimeInForce) {
request.timeInForce(((TimeInForce) flag).name());
}
}
if (!hasClientId) {
request.clientOid(UUID.randomUUID().toString());
}
return request
.symbol(adaptCurrencyPair(order.getCurrencyPair()))
.size(order.getOriginalAmount())
.side(adaptSide(order.getType()));
}
private static final class PriceAndSize {
final BigDecimal price;
final BigDecimal size;
PriceAndSize(List data) {
this.price = new BigDecimal(data.get(0));
this.size = new BigDecimal(data.get(1));
}
}
}