Skip to content

Commit

Permalink
Merge pull request knowm#814 from jheusser/bitvc_huobi_support
Browse files Browse the repository at this point in the history
Support Huobi trading in BitVc adapter
  • Loading branch information
timmolter committed Jan 9, 2015
2 parents 3def36b + 8e28f63 commit f2dac5f
Show file tree
Hide file tree
Showing 13 changed files with 338 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.xeiam.xchange.ExchangeException;
import com.xeiam.xchange.bitvc.dto.account.BitVcAccountInfo;
import com.xeiam.xchange.bitvc.dto.account.HuobiAccountInfo;
import com.xeiam.xchange.bitvc.dto.marketdata.BitVcDepth;
import com.xeiam.xchange.bitvc.dto.marketdata.BitVcOrderBookTAS;
import com.xeiam.xchange.bitvc.dto.marketdata.BitVcTicker;
Expand Down Expand Up @@ -115,6 +116,21 @@ public static AccountInfo adaptAccountInfo(BitVcAccountInfo a) {
List<Wallet> wallets = Arrays.asList(cny, btc, ltc, cnyLoan, btcLoan, ltcLoan);
return new AccountInfo(null, wallets);
}

public static AccountInfo adaptHuobiAccountInfo(HuobiAccountInfo a) {

Wallet cny = new Wallet(CNY, a.getAvailableCnyDisplay().add(a.getFrozenCnyDisplay()).subtract(a.getLoanCnyDisplay()), "available");
Wallet btc = new Wallet(BTC, a.getAvailableBtcDisplay().add(a.getFrozenBtcDisplay()).subtract(a.getLoanBtcDisplay()), "available");
Wallet ltc = new Wallet(LTC, a.getAvailableLtcDisplay().add(a.getFrozenLtcDisplay()).subtract(a.getLoanLtcDisplay()), "available");

// loaned wallets
Wallet cnyLoan = new Wallet(CNY, a.getLoanCnyDisplay(), "loan");
Wallet btcLoan = new Wallet(BTC, a.getLoanBtcDisplay(), "loan");
Wallet ltcLoan = new Wallet(LTC, a.getLoanLtcDisplay(), "loan");

List<Wallet> wallets = Arrays.asList(cny, btc, ltc, cnyLoan, btcLoan, ltcLoan);
return new AccountInfo(null, wallets);
}

public static String adaptPlaceOrderResult(BitVcPlaceOrderResult result) {

Expand All @@ -129,8 +145,8 @@ public static String adaptPlaceOrderResult(BitVcPlaceOrderResult result) {
public static List<LimitOrder> adaptOpenOrders(BitVcOrder[] orders, CurrencyPair currencyPair) {

List<LimitOrder> openOrders = new ArrayList<LimitOrder>(orders.length);
for (BitVcOrder order : orders) {
openOrders.add(adaptOpenOrder(order, currencyPair));
for (int i = 0; i < orders.length; i++) {
openOrders.add(adaptOpenOrder(orders[i], currencyPair));
}
return openOrders;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,19 @@
import com.xeiam.xchange.bitvc.service.polling.BitVcAccountService;
import com.xeiam.xchange.bitvc.service.polling.BitVcMarketDataService;
import com.xeiam.xchange.bitvc.service.polling.BitVcTradeService;
import com.xeiam.xchange.bitvc.service.polling.BitVcTradeServiceRaw;
import com.xeiam.xchange.currency.CurrencyPair;
import com.xeiam.xchange.huobi.service.polling.HuobiAccountService;
import com.xeiam.xchange.huobi.service.polling.HuobiTradeServiceRaw;

public class BitVcExchange extends BaseExchange implements Exchange {

public static final String SYMBOLS_PARAMETER = "symbols";
public static final String TRADE_PASSWORD_PARAMETER = "trade_password";

public static final String URI_HUOBI = "huobi_uri";
public static final String URI_HUOBI_MARKETDATA = "huobi_uri_marketdata";
public static final String USE_HUOBI = "use_huobi";

private static final List<CurrencyPair> SYMBOLS = Arrays.asList(CurrencyPair.BTC_CNY, CurrencyPair.LTC_CNY);

@Override
Expand All @@ -24,8 +30,15 @@ public void applySpecification(ExchangeSpecification exchangeSpecification) {
super.applySpecification(exchangeSpecification);
pollingMarketDataService = new BitVcMarketDataService(exchangeSpecification);
if (exchangeSpecification.getApiKey() != null) {
pollingAccountService = new BitVcAccountService(exchangeSpecification);
pollingTradeService = new BitVcTradeService(exchangeSpecification);
if((Boolean) exchangeSpecification.getExchangeSpecificParametersItem(USE_HUOBI)) {
pollingAccountService = new HuobiAccountService(exchangeSpecification);
pollingTradeService = new BitVcTradeService(new HuobiTradeServiceRaw(exchangeSpecification));

} else {

pollingAccountService = new BitVcAccountService(exchangeSpecification);
pollingTradeService = new BitVcTradeService(new BitVcTradeServiceRaw(exchangeSpecification));
}
}
}

Expand All @@ -37,10 +50,18 @@ public ExchangeSpecification getDefaultExchangeSpecification() {

ExchangeSpecification spec = new ExchangeSpecification(getClass());
spec.setExchangeName("BitVc");
spec.setExchangeDescription("BitVC");
spec.setExchangeDescription("BitVC and Huobi");

/* by default we request market data from huobi and execute on bitvc */
spec.setPlainTextUri("http://market.huobi.com/staticmarket");
spec.setSslUri("https://api.bitvc.com");
spec.setExchangeSpecificParametersItem(SYMBOLS_PARAMETER, SYMBOLS);

/* set to true if trade and account service should be from Huobi too */
spec.setExchangeSpecificParametersItem(USE_HUOBI, false);
spec.setExchangeSpecificParametersItem(URI_HUOBI, "https://api.huobi.com/apiv3");
spec.setExchangeSpecificParametersItem(URI_HUOBI_MARKETDATA, "http://market.huobi.com/staticmarket");

return spec;
}
}
41 changes: 41 additions & 0 deletions xchange-bitvc/src/main/java/com/xeiam/xchange/bitvc/Huobi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.xeiam.xchange.bitvc;

import java.io.IOException;

import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.xeiam.xchange.bitvc.dto.account.HuobiAccountInfo;
import com.xeiam.xchange.bitvc.dto.trade.BitVcCancelOrderResult;
import com.xeiam.xchange.bitvc.dto.trade.BitVcOrder;
import com.xeiam.xchange.bitvc.dto.trade.BitVcPlaceOrderResult;

import si.mazi.rescu.ParamsDigest;


@Path("")
@Produces(MediaType.APPLICATION_JSON)
public interface Huobi {

@POST
public HuobiAccountInfo getAccountInfo(@FormParam("access_key") String accessKey, @FormParam("created") long created, @FormParam("method") String method, @FormParam("sign") ParamsDigest sign) throws IOException;

@POST
public BitVcOrder[] getOrders(@FormParam("access_key") String accessKey, @FormParam("coin_type") int coinType, @FormParam("created") long created, @FormParam("method") String method, @FormParam("sign") ParamsDigest sign)
throws IOException;

@POST
public BitVcPlaceOrderResult placeLimitOrder(@FormParam("access_key") String accessKey, @FormParam("amount") String amount, @FormParam("coin_type") int coinType, @FormParam("created") long created,
@FormParam("price") String price, @FormParam("method") String method, @FormParam("sign") ParamsDigest sign) throws IOException;

@POST
public BitVcPlaceOrderResult placeMarketOrder(@FormParam("access_key") String accessKey, @FormParam("amount") String amount, @FormParam("coin_type") int coinType,
@FormParam("created") long created, @FormParam("method") String method, @FormParam("sign") ParamsDigest sign) throws IOException;

@POST
public BitVcCancelOrderResult cancelOrder(@FormParam("access_key") String accessKey, @FormParam("coin_type") int coinType, @FormParam("created") long created, @FormParam("id") long id,
@FormParam("method") String method, @FormParam("sign") ParamsDigest sign) throws IOException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.xeiam.xchange.bitvc.dto.account;

import java.math.BigDecimal;

import com.fasterxml.jackson.annotation.JsonProperty;

public class HuobiAccountInfo {

private final BigDecimal availableCny;
private final BigDecimal availableBtc;
private final BigDecimal availableLtc;
private final BigDecimal frozenCny;
private final BigDecimal frozenBtc;
private final BigDecimal frozenLtc;
private final BigDecimal loanCny;
private final BigDecimal loanBtc;
private final BigDecimal loanLtc;

private final String message;

public HuobiAccountInfo(@JsonProperty("available_cny_display") final BigDecimal availableCnyDisplay, @JsonProperty("available_btc_display") final BigDecimal availableBtcDisplay,
@JsonProperty("available_ltc_display") final BigDecimal availableLtcDisplay, @JsonProperty("frozen_cny_display") final BigDecimal frozenCnyDisplay,
@JsonProperty("frozen_btc_display") final BigDecimal frozenBtcDisplay, @JsonProperty("frozen_ltc_display") final BigDecimal frozenLtcDisplay, @JsonProperty("loan_cny_display") final BigDecimal loanCnyDisplay,
@JsonProperty("loan_btc_display") final BigDecimal loanBtcDisplay, @JsonProperty("loan_ltc_display") final BigDecimal loanLtcDisplay, @JsonProperty("message") String message) {

this.availableCny = availableCnyDisplay;
this.availableBtc = availableBtcDisplay;
this.availableLtc = availableLtcDisplay;
this.frozenCny = frozenCnyDisplay;
this.frozenBtc = frozenBtcDisplay;
this.frozenLtc = frozenLtcDisplay;
this.loanCny = loanCnyDisplay;
this.loanBtc = loanBtcDisplay;
this.loanLtc = loanLtcDisplay;

this.message = message;
}

public BigDecimal getAvailableCnyDisplay() {

return availableCny == null ? BigDecimal.ZERO : availableCny;
}

public BigDecimal getAvailableBtcDisplay() {

return availableBtc == null ? BigDecimal.ZERO : availableBtc;
}

public BigDecimal getAvailableLtcDisplay() {

return availableLtc == null ? BigDecimal.ZERO : availableLtc;
}

public BigDecimal getFrozenCnyDisplay() {

return frozenCny == null ? BigDecimal.ZERO : frozenCny;
}

public BigDecimal getFrozenBtcDisplay() {

return frozenBtc == null ? BigDecimal.ZERO : frozenBtc;
}

public BigDecimal getFrozenLtcDisplay() {

return frozenLtc == null ? BigDecimal.ZERO : frozenLtc;
}

public BigDecimal getLoanCnyDisplay() {

return loanCny == null ? BigDecimal.ZERO : loanCny;
}

public BigDecimal getLoanBtcDisplay() {

return loanBtc == null ? BigDecimal.ZERO : loanBtc;
}

public BigDecimal getLoanLtcDisplay() {

return loanLtc == null ? BigDecimal.ZERO : loanLtc;
}

public String getMessage() {
return message;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@
public class BitVcAccountService extends BitVcAccountServiceRaw implements PollingAccountService {

public BitVcAccountService(ExchangeSpecification exchangeSpecification) {

super(exchangeSpecification);
}

@Override
public AccountInfo getAccountInfo() throws IOException {

return BitVcAdapters.adaptAccountInfo(getBitVcAccountInfo());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import com.xeiam.xchange.ExchangeSpecification;
import com.xeiam.xchange.bitvc.BitVc;
import com.xeiam.xchange.bitvc.BitVcExchange;
import com.xeiam.xchange.bitvc.dto.marketdata.BitVcDepth;
import com.xeiam.xchange.bitvc.dto.marketdata.BitVcOrderBookTAS;
import com.xeiam.xchange.bitvc.dto.marketdata.BitVcTicker;
Expand All @@ -18,7 +19,7 @@ protected BitVcMarketDataServiceRaw(ExchangeSpecification exchangeSpecification)

super(exchangeSpecification);

final String baseUrl = exchangeSpecification.getPlainTextUri();
final String baseUrl = (String) exchangeSpecification.getExchangeSpecificParametersItem(BitVcExchange.URI_HUOBI_MARKETDATA);
bitvc = RestProxyFactory.createProxy(BitVc.class, baseUrl);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.xeiam.xchange.ExchangeException;
import com.xeiam.xchange.ExchangeSpecification;
import com.xeiam.xchange.NotAvailableFromExchangeException;
import com.xeiam.xchange.NotYetImplementedForExchangeException;
import com.xeiam.xchange.bitvc.BitVcAdapters;
Expand All @@ -20,17 +20,18 @@
import com.xeiam.xchange.dto.trade.MarketOrder;
import com.xeiam.xchange.dto.trade.OpenOrders;
import com.xeiam.xchange.dto.trade.UserTrades;
import com.xeiam.xchange.huobi.service.polling.TradeServiceRaw;
import com.xeiam.xchange.service.polling.PollingTradeService;
import com.xeiam.xchange.service.polling.trade.TradeHistoryParams;

public class BitVcTradeService extends BitVcTradeServiceRaw implements PollingTradeService {

public class BitVcTradeService implements PollingTradeService {
private final Map<CurrencyPair, Integer> coinTypes;
private final TradeServiceRaw tradeServiceRaw;
private static final OpenOrders noOpenOrders = new OpenOrders(Collections.<LimitOrder> emptyList());

public BitVcTradeService(ExchangeSpecification exchangeSpecification) {
public BitVcTradeService(TradeServiceRaw tradeServiceRaw) {

super(exchangeSpecification);
this.tradeServiceRaw = tradeServiceRaw;
coinTypes = new HashMap<CurrencyPair, Integer>(2);
coinTypes.put(CurrencyPair.BTC_CNY, 1);
coinTypes.put(CurrencyPair.LTC_CNY, 2);
Expand All @@ -41,7 +42,7 @@ public OpenOrders getOpenOrders() throws ExchangeException, NotAvailableFromExch

List<LimitOrder> openOrders = new ArrayList<LimitOrder>();
for (CurrencyPair currencyPair : getExchangeSymbols()) {
BitVcOrder[] orders = getBitVcOrders(coinTypes.get(currencyPair));
BitVcOrder[] orders = tradeServiceRaw.getBitVcOrders(coinTypes.get(currencyPair));

for (int i = 0; i < orders.length; i++) {
openOrders.add(BitVcAdapters.adaptOpenOrder(orders[i], currencyPair));
Expand All @@ -58,14 +59,14 @@ public OpenOrders getOpenOrders() throws ExchangeException, NotAvailableFromExch
@Override
public String placeMarketOrder(MarketOrder marketOrder) throws ExchangeException, NotAvailableFromExchangeException, NotYetImplementedForExchangeException, IOException {

BitVcPlaceOrderResult result = placeBitVcMarketOrder(marketOrder.getType(), coinTypes.get(marketOrder.getCurrencyPair()), marketOrder.getTradableAmount());
BitVcPlaceOrderResult result = tradeServiceRaw.placeBitVcMarketOrder(marketOrder.getType(), coinTypes.get(marketOrder.getCurrencyPair()), marketOrder.getTradableAmount());
return BitVcAdapters.adaptPlaceOrderResult(result);
}

@Override
public String placeLimitOrder(LimitOrder limitOrder) throws ExchangeException, NotAvailableFromExchangeException, NotYetImplementedForExchangeException, IOException {

BitVcPlaceOrderResult result = placeBitVcLimitOrder(limitOrder.getType(), coinTypes.get(limitOrder.getCurrencyPair()), limitOrder.getLimitPrice(), limitOrder.getTradableAmount());
BitVcPlaceOrderResult result = tradeServiceRaw.placeBitVcLimitOrder(limitOrder.getType(), coinTypes.get(limitOrder.getCurrencyPair()), limitOrder.getLimitPrice(), limitOrder.getTradableAmount());
return BitVcAdapters.adaptPlaceOrderResult(result);
}

Expand All @@ -76,7 +77,7 @@ public boolean cancelOrder(String orderId) throws IOException {

BitVcCancelOrderResult result = null;
for (CurrencyPair currencyPair : getExchangeSymbols()) {
result = cancelBitVcOrder(coinTypes.get(currencyPair), id);
result = tradeServiceRaw.cancelBitVcOrder(coinTypes.get(currencyPair), id);

if (result.getCode() == 0) {
break;
Expand All @@ -99,14 +100,16 @@ public UserTrades getTradeHistory(Object... arguments) {

@Override
public UserTrades getTradeHistory(TradeHistoryParams params) throws ExchangeException, NotAvailableFromExchangeException, NotYetImplementedForExchangeException, IOException {

throw new NotAvailableFromExchangeException();
}

@Override
public com.xeiam.xchange.service.polling.trade.TradeHistoryParams createTradeHistoryParams() {

return null;
}

@Override
public Collection<CurrencyPair> getExchangeSymbols() throws IOException {
return tradeServiceRaw.getExchangeSymbols();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
import com.xeiam.xchange.bitvc.dto.trade.BitVcOrderResult;
import com.xeiam.xchange.bitvc.dto.trade.BitVcPlaceOrderResult;
import com.xeiam.xchange.dto.Order.OrderType;
import com.xeiam.xchange.huobi.service.polling.TradeServiceRaw;

public class BitVcTradeServiceRaw extends BitVcBaseTradeService {

protected BitVcTradeServiceRaw(ExchangeSpecification exchangeSpecification) {
public class BitVcTradeServiceRaw extends BitVcBaseTradeService implements TradeServiceRaw {

public BitVcTradeServiceRaw(ExchangeSpecification exchangeSpecification) {
super(exchangeSpecification);
}

Expand Down
Loading

0 comments on commit f2dac5f

Please sign in to comment.