package org.knowm.xchange.bitstamp; import static java.math.BigDecimal.ZERO; import java.math.BigDecimal; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.knowm.xchange.bitstamp.dto.account.BitstampBalance; import org.knowm.xchange.bitstamp.dto.marketdata.BitstampOrderBook; import org.knowm.xchange.bitstamp.dto.marketdata.BitstampTicker; import org.knowm.xchange.bitstamp.dto.marketdata.BitstampTransaction; import org.knowm.xchange.bitstamp.dto.trade.BitstampUserTransaction; import org.knowm.xchange.currency.Currency; import org.knowm.xchange.currency.CurrencyPair; import org.knowm.xchange.dto.Order; import org.knowm.xchange.dto.Order.OrderType; import org.knowm.xchange.dto.account.AccountInfo; import org.knowm.xchange.dto.account.Balance; import org.knowm.xchange.dto.account.Wallet; 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.trade.LimitOrder; import org.knowm.xchange.dto.trade.UserTrade; import org.knowm.xchange.dto.trade.UserTrades; import org.knowm.xchange.utils.DateUtils; /** * Various adapters for converting from Bitstamp DTOs to XChange DTOs */ public final class BitstampAdapters { /** * private Constructor */ private BitstampAdapters() { } /** * Adapts a BitstampBalance to an AccountInfo * * @param bitstampBalance The Bitstamp balance * @param userName The user name * @return The account info */ public static AccountInfo adaptAccountInfo(BitstampBalance bitstampBalance, String userName) { // Adapt to XChange DTOs final BigDecimal usdWithdrawing = bitstampBalance.getUsdBalance().subtract(bitstampBalance.getUsdAvailable()) .subtract(bitstampBalance.getUsdReserved()); final BigDecimal eurWithdrawing = bitstampBalance.getEurBalance().subtract(bitstampBalance.getEurAvailable()) .subtract(bitstampBalance.getEurReserved()); final BigDecimal btcWithdrawing = bitstampBalance.getBtcBalance().subtract(bitstampBalance.getBtcAvailable()) .subtract(bitstampBalance.getBtcReserved()); Balance usdBalance = new Balance(Currency.USD, bitstampBalance.getUsdBalance(), bitstampBalance.getUsdAvailable(), bitstampBalance.getUsdReserved(), ZERO, ZERO, usdWithdrawing, ZERO); Balance eurBalance = new Balance(Currency.EUR, bitstampBalance.getEurBalance(), bitstampBalance.getEurAvailable(), bitstampBalance.getEurReserved(), ZERO, ZERO, eurWithdrawing, ZERO); Balance btcBalance = new Balance(Currency.BTC, bitstampBalance.getBtcBalance(), bitstampBalance.getBtcAvailable(), bitstampBalance.getBtcReserved(), ZERO, ZERO, btcWithdrawing, ZERO); return new AccountInfo(userName, bitstampBalance.getFee(), new Wallet(usdBalance, eurBalance, btcBalance)); } /** * Adapts a org.knowm.xchange.bitstamp.api.model.OrderBook to a OrderBook Object * * @param currencyPair (e.g. BTC/USD) * @param timeScale polled order books provide a timestamp in seconds, stream in ms * @return The XChange OrderBook */ public static OrderBook adaptOrderBook(BitstampOrderBook bitstampOrderBook, CurrencyPair currencyPair, int timeScale) { List<LimitOrder> asks = createOrders(currencyPair, Order.OrderType.ASK, bitstampOrderBook.getAsks()); List<LimitOrder> bids = createOrders(currencyPair, Order.OrderType.BID, bitstampOrderBook.getBids()); Date date = new Date(bitstampOrderBook.getTimestamp() * timeScale); // polled order books provide a timestamp in seconds, stream in ms return new OrderBook(date, asks, bids); } public static List<LimitOrder> createOrders(CurrencyPair currencyPair, Order.OrderType orderType, List<List<BigDecimal>> orders) { List<LimitOrder> limitOrders = new ArrayList<LimitOrder>(); for (List<BigDecimal> ask : orders) { checkArgument(ask.size() == 2, "Expected a pair (price, amount) but got {0} elements.", ask.size()); limitOrders.add(createOrder(currencyPair, ask, orderType)); } return limitOrders; } public static LimitOrder createOrder(CurrencyPair currencyPair, List<BigDecimal> priceAndAmount, Order.OrderType orderType) { return new LimitOrder(orderType, priceAndAmount.get(1), currencyPair, "", null, priceAndAmount.get(0)); } public static void checkArgument(boolean argument, String msgPattern, Object... msgArgs) { if (!argument) { throw new IllegalArgumentException(MessageFormat.format(msgPattern, msgArgs)); } } /** * Adapts a Transaction[] to a Trades Object * * @param transactions The Bitstamp transactions * @param currencyPair (e.g. BTC/USD) * @return The XChange Trades */ public static Trades adaptTrades(BitstampTransaction[] transactions, CurrencyPair currencyPair) { List<Trade> trades = new ArrayList<Trade>(); long lastTradeId = 0; for (BitstampTransaction tx : transactions) { final long tradeId = tx.getTid(); if (tradeId > lastTradeId) { lastTradeId = tradeId; } trades.add(adaptTrade(tx, currencyPair, 1000)); } return new Trades(trades, lastTradeId, TradeSortType.SortByID); } /** * Adapts a Transaction to a Trade Object * * @param tx The Bitstamp transaction * @param currencyPair (e.g. BTC/USD) * @param timeScale polled order books provide a timestamp in seconds, stream in ms * @return The XChange Trade */ public static Trade adaptTrade(BitstampTransaction tx, CurrencyPair currencyPair, int timeScale) { OrderType orderType = tx.getType() == 0 ? OrderType.BID : OrderType.ASK; final String tradeId = String.valueOf(tx.getTid()); Date date = DateUtils.fromMillisUtc(tx.getDate() * timeScale);// polled order books provide a timestamp in seconds, stream in ms return new Trade(orderType, tx.getAmount(), currencyPair, tx.getPrice(), date, tradeId); } /** * Adapts a BitstampTicker to a Ticker Object * * @param bitstampTicker The exchange specific ticker * @param currencyPair (e.g. BTC/USD) * @return The ticker */ public static Ticker adaptTicker(BitstampTicker bitstampTicker, CurrencyPair currencyPair) { BigDecimal last = bitstampTicker.getLast(); BigDecimal bid = bitstampTicker.getBid(); BigDecimal ask = bitstampTicker.getAsk(); BigDecimal high = bitstampTicker.getHigh(); BigDecimal low = bitstampTicker.getLow(); BigDecimal vwap = bitstampTicker.getVwap(); BigDecimal volume = bitstampTicker.getVolume(); Date timestamp = new Date(bitstampTicker.getTimestamp() * 1000L); return new Ticker.Builder().currencyPair(currencyPair).last(last).bid(bid).ask(ask).high(high).low(low).vwap(vwap).volume(volume) .timestamp(timestamp).build(); } /** * Adapt the user's trades * * @param bitstampUserTransactions * @return */ public static UserTrades adaptTradeHistory(BitstampUserTransaction[] bitstampUserTransactions) { List<UserTrade> trades = new ArrayList<UserTrade>(); long lastTradeId = 0; for (BitstampUserTransaction bitstampUserTransaction : bitstampUserTransactions) { if (bitstampUserTransaction.getType().equals(BitstampUserTransaction.TransactionType.trade)) { // skip account deposits and withdrawals. OrderType orderType = bitstampUserTransaction.getCounterAmount().doubleValue() > 0.0 ? OrderType.ASK : OrderType.BID; BigDecimal tradableAmount = bitstampUserTransaction.getBtc(); BigDecimal price = bitstampUserTransaction.getPrice().abs(); Date timestamp = BitstampUtils.parseDate(bitstampUserTransaction.getDatetime()); long transactionId = bitstampUserTransaction.getId(); if (transactionId > lastTradeId) { lastTradeId = transactionId; } final String tradeId = String.valueOf(transactionId); final String orderId = String.valueOf(bitstampUserTransaction.getOrderId()); final BigDecimal feeAmount = bitstampUserTransaction.getFee(); final CurrencyPair currencyPair = new CurrencyPair(Currency.BTC, new Currency(bitstampUserTransaction.getCounterCurrency())); UserTrade trade = new UserTrade(orderType, tradableAmount, currencyPair, price, timestamp, tradeId, orderId, feeAmount, Currency.getInstance(currencyPair.counter.getCurrencyCode())); trades.add(trade); } } return new UserTrades(trades, lastTradeId, TradeSortType.SortByID); } }