Skip to content
This repository has been archived by the owner on Jun 8, 2020. It is now read-only.

Commit

Permalink
Merge pull request #275 from BenjaminTrapani/user/betrapan/cexio-stre…
Browse files Browse the repository at this point in the history
…aming-orderbook

Add streaming order book support for CEX.IO
  • Loading branch information
badgerwithagun authored Jun 16, 2019
2 parents 0832e53 + 909b67d commit f101cf2
Show file tree
Hide file tree
Showing 23 changed files with 1,567 additions and 986 deletions.
Original file line number Diff line number Diff line change
@@ -1,74 +1,131 @@
package info.bitrich.xchangestream.cexio;

import info.bitrich.xchangestream.cexio.dto.CexioWebSocketOrder;
import info.bitrich.xchangestream.cexio.dto.CexioWebSocketOrderBookSubscribeResponse;
import info.bitrich.xchangestream.cexio.dto.CexioWebSocketPair;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.dto.Order;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.dto.Order;
import org.knowm.xchange.dto.Order.OrderType;
import org.knowm.xchange.dto.marketdata.OrderBook;
import org.knowm.xchange.dto.trade.LimitOrder;

public class CexioAdapters {

private static final int PRECISION = 3;
private static final BigDecimal SATOSHI_SCALE = new BigDecimal("100000000");
private static final int PRECISION = 3;
private static final BigDecimal SATOSHI_SCALE = new BigDecimal("100000000");

static Order adaptOrder(CexioWebSocketOrder order) {
if (order.getType() != null) {
return new CexioOrder(adaptOrderType(order.getType()),
adaptCurrencyPair(order.getPair()),
adaptAmount(order.getRemains()),
order.getId(),
order.getTime(),
order.getPrice(),
order.getFee(),
getOrderStatus(order));
} else {
return new CexioOrder(adaptCurrencyPair(order.getPair()),
order.getId(),
getOrderStatus(order),
adaptAmount(order.getRemains()));
}
static Order adaptOrder(CexioWebSocketOrder order) {
if (order.getType() != null) {
return new CexioOrder(
adaptOrderType(order.getType()),
adaptCurrencyPair(order.getPair()),
adaptAmount(order.getRemains()),
order.getId(),
order.getTime(),
order.getPrice(),
order.getFee(),
getOrderStatus(order));
} else {
return new CexioOrder(
adaptCurrencyPair(order.getPair()),
order.getId(),
getOrderStatus(order),
adaptAmount(order.getRemains()));
}
}

private static CurrencyPair adaptCurrencyPair(CexioWebSocketPair pair) {
return new CurrencyPair(pair.getSymbol1(), pair.getSymbol2());
private static CurrencyPair adaptCurrencyPair(CexioWebSocketPair pair) {
return new CurrencyPair(pair.getSymbol1(), pair.getSymbol2());
}

private static Order.OrderType adaptOrderType(String type) {
if (type == null) {
return null;
}

private static Order.OrderType adaptOrderType(String type) {
if (type == null) {
return null;
}
switch (type) {
case "buy":
return Order.OrderType.BID;
case "sell":
return Order.OrderType.ASK;
default:
return null;
}
}

switch (type) {
case "buy":
return Order.OrderType.BID;
case "sell":
return Order.OrderType.ASK;
default:
return null;
}
private static BigDecimal adaptAmount(BigDecimal amount) {
if (amount == null) {
return null;
}

private static BigDecimal adaptAmount(BigDecimal amount) {
if (amount == null) {
return null;
}
return amount.divide(SATOSHI_SCALE, PRECISION, RoundingMode.DOWN);
}

return amount.divide(SATOSHI_SCALE, PRECISION, RoundingMode.DOWN);
private static Order.OrderStatus getOrderStatus(CexioWebSocketOrder order) {
Order.OrderStatus status;
if (order.isCancel()) {
status = Order.OrderStatus.CANCELED;
} else if (order.getRemains().compareTo(BigDecimal.ZERO) == 0) {
status = Order.OrderStatus.FILLED;
} else if (order.getType() != null) {
status = Order.OrderStatus.NEW;
} else {
status = Order.OrderStatus.PARTIALLY_FILLED;
}
return status;
}

private static Order.OrderStatus getOrderStatus(CexioWebSocketOrder order) {
Order.OrderStatus status;
if (order.isCancel()) {
status = Order.OrderStatus.CANCELED;
} else if (order.getRemains().compareTo(BigDecimal.ZERO) == 0) {
status = Order.OrderStatus.FILLED;
} else if (order.getType() != null) {
status = Order.OrderStatus.NEW;
} else {
status = Order.OrderStatus.PARTIALLY_FILLED;
}
return status;
private static OrderBook updateOrInsertQuantityForPrice(
OrderBook orderBook,
List<List<BigDecimal>> updatedQuantitiesPerPrice,
OrderType orderType,
Date timestamp,
CurrencyPair currencyPair,
String id) {
for (List<BigDecimal> updatedQuantityPrice : updatedQuantitiesPerPrice) {
if (updatedQuantityPrice.size() != 2) {
throw new IllegalArgumentException(
"Expected price quantity list to contain exactly two big decimals");
}
BigDecimal price = updatedQuantityPrice.get(0);
BigDecimal quantity = updatedQuantityPrice.get(1);
LimitOrder orderForUpdatedQuantityPrice =
new LimitOrder(orderType, quantity, currencyPair, id, timestamp, price);
orderBook.update(orderForUpdatedQuantityPrice);
}
return orderBook;
}

// Copied from xchange org.knowm.xchange.cexio.CexIOAdapters since that implementation
// is private as of the time of writing
protected static CurrencyPair adaptCurrencyPair(String pair) {
// Currency pair is in the format: "BCH:USD"
return new CurrencyPair(pair.replace(":", "/"));
}

protected static OrderBook adaptOrderBookIncremental(
OrderBook prevOrderBook, CexioWebSocketOrderBookSubscribeResponse update) {
CurrencyPair currencyPair = adaptCurrencyPair(update.pair);
prevOrderBook =
updateOrInsertQuantityForPrice(
prevOrderBook,
update.asks,
OrderType.ASK,
update.timestamp,
currencyPair,
update.id.toString());
prevOrderBook =
updateOrInsertQuantityForPrice(
prevOrderBook,
update.bids,
OrderType.BID,
update.timestamp,
currencyPair,
update.id.toString());
return prevOrderBook;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,33 @@

public class CexioDigest extends BaseParamsDigest {

private static final char[] DIGITS = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

protected CexioDigest(String secretKey) {
super(secretKey, HMAC_SHA_256);
}

static CexioDigest createInstance(String secretKey) {
return secretKey == null ? null : new CexioDigest(secretKey);
}

@Override
public String digestParams(RestInvocation restInvocation) {
return null;
}

private static char[] encodeHex(byte[] data) {
int l = data.length;
char[] out = new char[l << 1];
for (int i = 0, j = 0; i < l; i++) {
out[j++] = DIGITS[(0xF0 & data[i]) >>> 4];
out[j++] = DIGITS[0x0F & data[i]];
}
return out;
}

public String createSignature(long timestamp, String apiKey) {
return new String(encodeHex(getMac().doFinal((timestamp + apiKey).getBytes())));
private static final char[] DIGITS =
new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

protected CexioDigest(String secretKey) {
super(secretKey, HMAC_SHA_256);
}

static CexioDigest createInstance(String secretKey) {
return secretKey == null ? null : new CexioDigest(secretKey);
}

@Override
public String digestParams(RestInvocation restInvocation) {
return null;
}

private static char[] encodeHex(byte[] data) {
int l = data.length;
char[] out = new char[l << 1];
for (int i = 0, j = 0; i < l; i++) {
out[j++] = DIGITS[(0xF0 & data[i]) >>> 4];
out[j++] = DIGITS[0x0F & data[i]];
}
return out;
}

public String createSignature(long timestamp, String apiKey) {
return new String(encodeHex(getMac().doFinal((timestamp + apiKey).getBytes())));
}
}
Original file line number Diff line number Diff line change
@@ -1,59 +1,59 @@
package info.bitrich.xchangestream.cexio;

import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.dto.trade.LimitOrder;

import java.math.BigDecimal;
import java.util.Date;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.dto.trade.LimitOrder;

public class CexioOrder extends LimitOrder {

private BigDecimal remainingAmount;

public CexioOrder(OrderType type,
CurrencyPair currencyPair,
BigDecimal originalAmount,
String id,
Date timestamp,
BigDecimal limitPrice,
BigDecimal fee,
OrderStatus status) {
super(type, originalAmount, currencyPair, id, timestamp, limitPrice,
null, null, fee, status);
this.remainingAmount = null;
private BigDecimal remainingAmount;

public CexioOrder(
OrderType type,
CurrencyPair currencyPair,
BigDecimal originalAmount,
String id,
Date timestamp,
BigDecimal limitPrice,
BigDecimal fee,
OrderStatus status) {
super(type, originalAmount, currencyPair, id, timestamp, limitPrice, null, null, fee, status);
this.remainingAmount = null;
}

public CexioOrder(
CurrencyPair currencyPair, String id, OrderStatus status, BigDecimal remainingAmount) {
this(null, currencyPair, null, id, null, null, null, status);
this.remainingAmount = remainingAmount;
}

@Override
public BigDecimal getRemainingAmount() {
if (remainingAmount != null) {
return remainingAmount;
}

public CexioOrder(CurrencyPair currencyPair, String id, OrderStatus status, BigDecimal remainingAmount) {
this(null, currencyPair, null, id, null, null, null, status);
this.remainingAmount = remainingAmount;
}
return super.getRemainingAmount();
}

@Override
public BigDecimal getRemainingAmount() {
if (remainingAmount != null) {
return remainingAmount;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CexioOrder)) return false;
if (!super.equals(o)) return false;

return super.getRemainingAmount();
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CexioOrder)) return false;
if (!super.equals(o)) return false;
CexioOrder that = (CexioOrder) o;

CexioOrder that = (CexioOrder) o;
return remainingAmount != null
? remainingAmount.compareTo(that.remainingAmount) == 0
: that.remainingAmount == null;
}

return remainingAmount != null
? remainingAmount.compareTo(that.remainingAmount) == 0
: that.remainingAmount == null;
}

@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (remainingAmount != null ? remainingAmount.hashCode() : 0);
return result;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (remainingAmount != null ? remainingAmount.hashCode() : 0);
return result;
}
}
Loading

0 comments on commit f101cf2

Please sign in to comment.