package org.knowm.xchange.mercadobitcoin; import static org.knowm.xchange.utils.DateUtils.fromUnixTime; import java.math.BigDecimal; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.knowm.xchange.currency.Currency; import org.knowm.xchange.currency.CurrencyPair; 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.trade.LimitOrder; import org.knowm.xchange.dto.trade.UserTrade; import org.knowm.xchange.dto.trade.UserTrades; import org.knowm.xchange.mercadobitcoin.dto.MercadoBitcoinBaseTradeApiResult; import org.knowm.xchange.mercadobitcoin.dto.account.MercadoBitcoinAccountInfo; import org.knowm.xchange.mercadobitcoin.dto.marketdata.MercadoBitcoinOrderBook; import org.knowm.xchange.mercadobitcoin.dto.marketdata.MercadoBitcoinTicker; import org.knowm.xchange.mercadobitcoin.dto.marketdata.MercadoBitcoinTransaction; import org.knowm.xchange.mercadobitcoin.dto.trade.MercadoBitcoinUserOrders; import org.knowm.xchange.mercadobitcoin.dto.trade.MercadoBitcoinUserOrdersEntry; import org.knowm.xchange.mercadobitcoin.dto.trade.OperationEntry; import org.knowm.xchange.utils.DateUtils; /** * Various adapters for converting from Mercado Bitcoin DTOs to XChange DTOs * * @author Felipe Micaroni Lalli */ public final class MercadoBitcoinAdapters { /** * private Constructor */ private MercadoBitcoinAdapters() { } /** * Adapts a org.knowm.xchange.mercadobitcoin.dto.marketdata.OrderBook to a OrderBook Object * * @param currencyPair (e.g. BTC/BRL or LTC/BRL) * @return The XChange OrderBook */ public static OrderBook adaptOrderBook(MercadoBitcoinOrderBook mercadoBitcoinOrderBook, CurrencyPair currencyPair) { List<LimitOrder> asks = createOrders(currencyPair, OrderType.ASK, mercadoBitcoinOrderBook.getAsks()); List<LimitOrder> bids = createOrders(currencyPair, OrderType.BID, mercadoBitcoinOrderBook.getBids()); return new OrderBook(null, asks, bids); } public static List<LimitOrder> createOrders(CurrencyPair currencyPair, 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, 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 MercadoBitcoinTicker to a Ticker Object * * @param mercadoBitcoinTicker The exchange specific ticker * @param currencyPair (e.g. BTC/USD) * @return The ticker */ public static Ticker adaptTicker(MercadoBitcoinTicker mercadoBitcoinTicker, CurrencyPair currencyPair) { BigDecimal last = mercadoBitcoinTicker.getTicker().getLast(); BigDecimal bid = mercadoBitcoinTicker.getTicker().getBuy(); BigDecimal ask = mercadoBitcoinTicker.getTicker().getSell(); BigDecimal high = mercadoBitcoinTicker.getTicker().getHigh(); BigDecimal low = mercadoBitcoinTicker.getTicker().getLow(); BigDecimal volume = mercadoBitcoinTicker.getTicker().getVol(); Date timestamp = new Date(mercadoBitcoinTicker.getTicker().getDate() * 1000L); return new Ticker.Builder().currencyPair(currencyPair).last(last).bid(bid).ask(ask).high(high).low(low).volume(volume).timestamp(timestamp) .build(); } /** * Adapts a Transaction[] to a Trades Object * * @param transactions The Mercado Bitcoin transactions * @param currencyPair (e.g. BTC/BRL or LTC/BRL) * @return The XChange Trades */ public static Trades adaptTrades(MercadoBitcoinTransaction[] transactions, CurrencyPair currencyPair) { List<Trade> trades = new ArrayList<Trade>(); long lastTradeId = 0; for (MercadoBitcoinTransaction tx : transactions) { final long tradeId = tx.getTid(); if (tradeId > lastTradeId) { lastTradeId = tradeId; } trades.add(new Trade(toOrderType(tx.getType()), tx.getAmount(), currencyPair, tx.getPrice(), DateUtils.fromMillisUtc(tx.getDate() * 1000L), String.valueOf(tradeId))); } return new Trades(trades, lastTradeId, Trades.TradeSortType.SortByID); } /** * Adapts a MercadoBitcoinBaseTradeApiResult<MercadoBitcoinAccountInfo> to an AccountInfo * * @param accountInfo The Mercado Bitcoin accountInfo * @param userName The user name * @return The account info */ public static AccountInfo adaptAccountInfo(MercadoBitcoinBaseTradeApiResult<MercadoBitcoinAccountInfo> accountInfo, String userName) { // Adapt to XChange DTOs Balance brlBalance = new Balance(Currency.BRL, accountInfo.getTheReturn().getFunds().getBrl()); Balance btcBalance = new Balance(Currency.BTC, accountInfo.getTheReturn().getFunds().getBtc()); Balance ltcBalance = new Balance(Currency.LTC, accountInfo.getTheReturn().getFunds().getLtc()); return new AccountInfo(userName, new Wallet(brlBalance, btcBalance, ltcBalance)); } public static List<LimitOrder> adaptOrders(CurrencyPair currencyPair, MercadoBitcoinBaseTradeApiResult<MercadoBitcoinUserOrders> input) { List<LimitOrder> limitOrders = new ArrayList<LimitOrder>(); MercadoBitcoinUserOrders orders = input.getTheReturn(); for (Map.Entry<String, MercadoBitcoinUserOrdersEntry> entry : orders.entrySet()) { limitOrders.add(processOrderEntry(entry, currencyPair)); } return limitOrders; } private static LimitOrder processOrderEntry(Map.Entry<String, MercadoBitcoinUserOrdersEntry> entry, CurrencyPair currencyPair) { String id = entry.getKey(); MercadoBitcoinUserOrdersEntry userOrdersEntry = entry.getValue(); String type = userOrdersEntry.getType(); OrderType orderType = toOrderType(type); BigDecimal price = userOrdersEntry.getPrice(); BigDecimal volume = userOrdersEntry.getVolume(); long time = userOrdersEntry.getCreated() * 1000L; return new LimitOrder(orderType, volume, currencyPair, id, new Date(time), price); } private static OrderType toOrderType(String mercadoType) { return mercadoType.equals("buy") ? OrderType.BID : OrderType.ASK; } public static String adaptCurrencyPair(CurrencyPair pair) { return (pair.base.getCurrencyCode() + "_" + pair.counter.getCurrencyCode()).toLowerCase(); } public static UserTrades toUserTrades(CurrencyPair pair, MercadoBitcoinBaseTradeApiResult<MercadoBitcoinUserOrders> orders) { List<UserTrade> result = new LinkedList<>(); for (Map.Entry<String, MercadoBitcoinUserOrdersEntry> e : orders.getTheReturn().entrySet()) { String orderId = e.getKey(); MercadoBitcoinUserOrdersEntry order = e.getValue(); OrderType type = toOrderType(order.getType()); for (Map.Entry<String, OperationEntry> f : order.getOperations().entrySet()) { String txId = f.getKey(); OperationEntry op = f.getValue(); result.add(new UserTrade.Builder().currencyPair(pair).id(txId).orderId(orderId).price(op.getPrice()).timestamp(fromUnixTime(op.getCreated())) .tradableAmount(op.getVolume()).type(type).build()); } } // TODO verify sortType return new UserTrades(result, Trades.TradeSortType.SortByID); } }