package org.knowm.xchange.gdax;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
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.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.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.OpenOrders;
import org.knowm.xchange.dto.trade.UserTrade;
import org.knowm.xchange.dto.trade.UserTrades;
import org.knowm.xchange.gdax.dto.account.GDAXAccount;
import org.knowm.xchange.gdax.dto.marketdata.GDAXProduct;
import org.knowm.xchange.gdax.dto.marketdata.GDAXProductBook;
import org.knowm.xchange.gdax.dto.marketdata.GDAXProductBookEntry;
import org.knowm.xchange.gdax.dto.marketdata.GDAXProductStats;
import org.knowm.xchange.gdax.dto.marketdata.GDAXProductTicker;
import org.knowm.xchange.gdax.dto.marketdata.GDAXTrade;
import org.knowm.xchange.gdax.dto.trade.GDAXFill;
import org.knowm.xchange.gdax.dto.trade.GDAXOrder;
public class GDAXAdapters {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
static {
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
}
private GDAXAdapters() {
}
private static Date parseDate(String rawDate) {
// System.out.println("before: " + rawDate);
try {
if (rawDate.length() == 20 && rawDate.endsWith("Z")) {
rawDate = rawDate.substring(0, 19) + ".000Z";
} else if (rawDate.length() == 21) {
rawDate = rawDate.substring(0, 20) + "000";
} else if (rawDate.length() == 22) {
rawDate = rawDate.substring(0, 21) + "00";
} else if (rawDate.length() == 23) {
rawDate = rawDate.substring(0, 22) + "0";
} else {
rawDate = rawDate.substring(0, rawDate.length() < 23 ? rawDate.length() : 23);
}
// System.out.println("after: " + rawDate);
// System.out.println("");
return dateFormat.parse(rawDate);
} catch (ParseException e) {
System.err.println("rawDate: " + rawDate);
e.printStackTrace();
return null;
}
}
public static Ticker adaptTicker(GDAXProductTicker ticker, GDAXProductStats stats, CurrencyPair currencyPair) {
BigDecimal last = ticker.getPrice();
BigDecimal high = stats.getHigh();
BigDecimal low = stats.getLow();
BigDecimal buy = ticker.getBid();
BigDecimal sell = ticker.getAsk();
BigDecimal volume = ticker.getVolume();
Date date = parseDate(ticker.getTime());
return new Ticker.Builder().currencyPair(currencyPair).last(last).high(high).low(low).bid(buy).ask(sell).volume(volume).timestamp(date).build();
}
public static OrderBook adaptOrderBook(GDAXProductBook book, CurrencyPair currencyPair) {
List<LimitOrder> asks = toLimitOrderList(book.getAsks(), OrderType.ASK, currencyPair);
List<LimitOrder> bids = toLimitOrderList(book.getBids(), OrderType.BID, currencyPair);
return new OrderBook(null, asks, bids);
}
private static List<LimitOrder> toLimitOrderList(GDAXProductBookEntry[] levels, OrderType orderType, CurrencyPair currencyPair) {
List<LimitOrder> allLevels = new ArrayList<LimitOrder>(levels.length);
for (int i = 0; i < levels.length; i++) {
GDAXProductBookEntry ask = levels[i];
allLevels.add(new LimitOrder(orderType, ask.getVolume(), currencyPair, "0", null, ask.getPrice()));
}
return allLevels;
}
public static Wallet adaptAccountInfo(GDAXAccount[] coinbaseExAccountInfo) {
List<Balance> balances = new ArrayList<Balance>(coinbaseExAccountInfo.length);
for (int i = 0; i < coinbaseExAccountInfo.length; i++) {
GDAXAccount account = coinbaseExAccountInfo[i];
balances.add(new Balance(Currency.getInstance(account.getCurrency()), account.getBalance(), account.getAvailable(), account.getHold()));
}
return new Wallet(coinbaseExAccountInfo[0].getProfile_id(), balances);
}
public static OpenOrders adaptOpenOrders(GDAXOrder[] coinbaseExOpenOrders) {
List<LimitOrder> orders = new ArrayList<LimitOrder>(coinbaseExOpenOrders.length);
for (int i = 0; i < coinbaseExOpenOrders.length; i++) {
GDAXOrder order = coinbaseExOpenOrders[i];
OrderType type = order.getSide().equals("buy") ? OrderType.BID : OrderType.ASK;
CurrencyPair currencyPair = new CurrencyPair(order.getProductId().replace("-", "/"));
Date createdAt = parseDate(order.getCreatedAt());
orders.add(new LimitOrder(type, order.getSize(), currencyPair, order.getId(), createdAt, order.getPrice()));
}
return new OpenOrders(orders);
}
public static UserTrades adaptTradeHistory(GDAXFill[] coinbaseExFills) {
List<UserTrade> trades = new ArrayList<UserTrade>(coinbaseExFills.length);
for (int i = 0; i < coinbaseExFills.length; i++) {
GDAXFill fill = coinbaseExFills[i];
// yes, sell means buy for Coinbase reported trades..
OrderType type = fill.getSide().equals("sell") ? OrderType.BID : OrderType.ASK;
CurrencyPair currencyPair = new CurrencyPair(fill.getProductId().replace("-", "/"));
// ToDo add fee amount
UserTrade t = new UserTrade(type, fill.getSize(), currencyPair, fill.getPrice(), parseDate(fill.getCreatedAt()),
String.valueOf(fill.getTradeId()), fill.getOrderId(), null, (Currency) null);
trades.add(t);
}
return new UserTrades(trades, TradeSortType.SortByID);
}
public static Trades adaptTrades(GDAXTrade[] coinbaseExTrades, CurrencyPair currencyPair) {
List<Trade> trades = new ArrayList<Trade>(coinbaseExTrades.length);
for (int i = 0; i < coinbaseExTrades.length; i++) {
GDAXTrade trade = coinbaseExTrades[i];
// yes, sell means buy for gdax reported trades..
OrderType type = trade.getSide().equals("sell") ? OrderType.BID : OrderType.ASK;
Trade t = new Trade(type, trade.getSize(), currencyPair, trade.getPrice(), parseDate(trade.getTimestamp()), String.valueOf(trade.getTradeId()));
trades.add(t);
}
return new Trades(trades, coinbaseExTrades[0].getTradeId(), TradeSortType.SortByID);
}
public static CurrencyPair adaptCurrencyPair(GDAXProduct product) {
return new CurrencyPair(product.getBaseCurrency(), product.getTargetCurrency());
}
public static ExchangeMetaData adaptToExchangeMetaData(ExchangeMetaData exchangeMetaData, List<GDAXProduct> products) {
Map<CurrencyPair, CurrencyPairMetaData> currencyPairs = new HashMap<>();
Map<Currency, CurrencyMetaData> currencies = new HashMap<>();
for (GDAXProduct product : products) {
BigDecimal minSize = product.getBaseMinSize().setScale(product.getQuoteIncrement().scale(), BigDecimal.ROUND_UNNECESSARY);
BigDecimal maxSize = product.getBaseMaxSize().setScale(product.getQuoteIncrement().scale(), BigDecimal.ROUND_UNNECESSARY);
CurrencyPairMetaData cpmd = new CurrencyPairMetaData(null, minSize, maxSize, 8); // TODO 8 is a wild guess
CurrencyPair pair = adaptCurrencyPair(product);
currencyPairs.put(pair, cpmd);
currencies.put(pair.base, null);
currencies.put(pair.counter, null);
}
return new ExchangeMetaData(currencyPairs, currencies, exchangeMetaData.getPublicRateLimits(), exchangeMetaData.getPrivateRateLimits(), true);
}
}