package org.knowm.xchange.examples.btcchina.trade;
import static org.apache.commons.lang3.time.DateUtils.parseDate;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import org.knowm.xchange.Exchange;
import org.knowm.xchange.ExchangeFactory;
import org.knowm.xchange.ExchangeSpecification;
import org.knowm.xchange.btcchina.BTCChinaExchange;
import org.knowm.xchange.btcchina.service.rest.BTCChinaTradeService.BTCChinaTradeHistoryParams;
import org.knowm.xchange.dto.trade.UserTrade;
import org.knowm.xchange.dto.trade.UserTrades;
import org.knowm.xchange.service.trade.TradeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BTCChinaTradeStat {
private static final Logger log = LoggerFactory.getLogger(BTCChinaTradeStat.class);
private final TradeService tradeService;
public BTCChinaTradeStat(String accessKey, String secretKey) {
final ExchangeSpecification spec = new ExchangeSpecification(BTCChinaExchange.class);
spec.setApiKey(accessKey);
spec.setSecretKey(secretKey);
Exchange exchange = ExchangeFactory.INSTANCE.createExchange(spec);
tradeService = exchange.getTradeService();
}
/**
* Returns the trades executed in the specified time.
* <p>
* Seems the <code>since</code> parameter does not work from the server side, we have to do this trick by ourself.
* </p>
*
* @param startTime inclusive
* @param endTime exclusive
* @return trade between the <code>startTime</code> and <code>endTime</code>.
* @throws IOException indicates I/O exception in calling RESTful API.
*/
private List<UserTrade> getUserTrades(Date startTime, Date endTime) throws IOException {
final long start = startTime.getTime(), end = endTime.getTime();
final List<UserTrade> trades = new ArrayList<UserTrade>();
final Integer pageLength = 1000;
final String type = "all";
final Integer startId = null;
for (int pageNumber = 0;; pageNumber++) {
log.trace("pageNumber: {}", pageNumber);
final BTCChinaTradeHistoryParams params = new BTCChinaTradeHistoryParams(pageLength, pageNumber, type, startTime, startId);
final UserTrades userTrades = tradeService.getTradeHistory(params);
long earliest = System.currentTimeMillis();
for (UserTrade trade : userTrades.getUserTrades()) {
long time = trade.getTimestamp().getTime();
earliest = Math.min(earliest, time);
if (time >= start && time < end) {
trades.add(trade);
}
}
log.trace("earliest: {}", earliest);
if (userTrades.getTrades().isEmpty() || earliest < start) {
break;
}
}
Collections.sort(trades, new Comparator<UserTrade>() {
@Override
public int compare(UserTrade o1, UserTrade o2) {
return new Integer(o1.getId()).compareTo(new Integer(o2.getId()));
}
});
return trades;
}
private void stat(Date startTime, Date endTime) throws IOException {
List<UserTrade> trades = getUserTrades(startTime, endTime);
if (!trades.isEmpty()) {
UserTrade first = trades.get(0);
UserTrade last = trades.get(trades.size() - 1);
log.info("{}({})-{}({}): {}", first.getTimestamp(), first.getId(), last.getTimestamp(), last.getId(), trades.size());
}
int bidCount = 0, askCount = 0;
BigDecimal totalBid = BigDecimal.ZERO, totalAsk = BigDecimal.ZERO, totalBidTradable = BigDecimal.ZERO, totalAskTradable = BigDecimal.ZERO;
for (UserTrade trade : trades) {
switch (trade.getType()) {
case BID:
bidCount++;
totalBid = totalBid.add(trade.getPrice().multiply(trade.getTradableAmount()));
totalBidTradable = totalBidTradable.add(trade.getTradableAmount());
break;
case ASK:
askCount++;
totalAsk = totalAsk.add(trade.getPrice().multiply(trade.getTradableAmount()));
totalAskTradable = totalAskTradable.add(trade.getTradableAmount());
break;
default:
break;
}
}
BigDecimal avgBid = totalBidTradable.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO
: totalBid.divide(totalBidTradable, 8, RoundingMode.HALF_EVEN);
BigDecimal avgAsk = totalAskTradable.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO
: totalAsk.divide(totalAskTradable, 8, RoundingMode.HALF_EVEN);
log.info("bid trade count: {}, ask trade count: {}", bidCount, askCount);
log.info("Total bid: {}, tradable: {}, avg: {}", totalBid, totalBidTradable, avgBid);
log.info("Total ask: {}, tradable: {}, avg: {}", totalAsk, totalAskTradable, avgAsk);
log.info("Total: {}", totalBid.add(totalAsk));
}
public static void main(String[] args) throws ParseException, IOException {
log.info("args: {}", Arrays.toString(args));
final String accessKey = args[0], secretKey = args[1];
final Date startTime = parseDate(args[2], "yyyy-MM-dd");
final Date endTime = parseDate(args[3], "yyyy-MM-dd");
BTCChinaTradeStat stat = new BTCChinaTradeStat(accessKey, secretKey);
stat.stat(startTime, endTime);
}
}