unterstein / binance-trader

Experimental trading bot for crypto currency on Binance.com
Apache License 2.0
274 stars 144 forks source link

Candlestick question #23

Open gu3nter opened 6 years ago

gu3nter commented 6 years ago

Hello together, I have a problem and hope you can help me (I hope that it is ok to ask here :))

I want to calculate the MACD indicator, but I´m a noob and it doesn´t work :(

I would be great, if the trader is able to get the closing price of the last 2 days. I think it´s enough for me to know how to get out the closing price of the last hour and rest i can do my own. (First I only want to print the last closing price)

What I´ve done yet:

I saw at https://github.com/joaopsilva/binance-java-api the example of the Candlestick.

List<Candlestick> candlesticks = client.getCandlestickBars("NEOETH", CandlestickInterval.WEEKLY); System.out.println(candlesticks);

My changes in the code of TradingClient.java: I added after line 14: import com.binance.api.client.domain.market.Candlestick; import com.binance.api.client.domain.market.CandlestickInterval;

and after new line 73: public List<Candlestick> getCandlestickBars() { //OrderRequest request = new OrderRequest(symbol); return client.getCandlestickBars("NEOETH", CandlestickInterval.WEEKLY); }

In BinanceTrader.java: I added after line 6: import com.binance.api.client.domain.market.Candlestick; import com.binance.api.client.domain.market.CandlestickInterval;

and after new line 42: Candlestick candlestick = client.getCandlestickBars(); logger.info("candlestick: " + candlestick);

When I trie to start the trader I got the following message: /root/binance-trader/src/main/java/io/github/unterstein/BinanceTrader.java:[43,58] incompatible types: java.util.List<com.binance.api.client.domain.market.Candlestick> cannot be converted to com.binance.api.client.domain.market.Candlestick

Here the complete code of my changes: BinanceTrader.java: `package io.github.unterstein;

import com.binance.api.client.domain.OrderStatus; import com.binance.api.client.domain.account.AssetBalance; import com.binance.api.client.domain.account.Order; import com.binance.api.client.domain.market.OrderBook; import com.binance.api.client.domain.market.Candlestick; import com.binance.api.client.domain.market.CandlestickInterval;

import org.slf4j.Logger; import org.slf4j.LoggerFactory;

import java.util.List;

public class BinanceTrader {

private static Logger logger = LoggerFactory.getLogger(BinanceTrader.class);

private TradingClient client; private final double tradeDifference; private final double tradeProfit; private final int tradeAmount;

private Double currentlyBoughtPrice; private Long orderId; private int panicBuyCounter; private int panicSellCounter; private double trackingLastPrice;

BinanceTrader(double tradeDifference, double tradeProfit, int tradeAmount, String baseCurrency, String tradeCurrency, String key, String secret) { client = new TradingClient(baseCurrency, tradeCurrency, key, secret); trackingLastPrice = client.lastPrice(); this.tradeAmount = tradeAmount; this.tradeProfit = tradeProfit; this.tradeDifference = tradeDifference; clear(); }

void tick() { double lastPrice = 0; try { OrderBook orderBook = client.getOrderBook(); Candlestick candlestick = client.getCandlestickBars(); logger.info("candlestick: " + candlestick); lastPrice = client.lastPrice(); AssetBalance tradingBalance = client.getTradingBalance(); double lastKnownTradingBalance = client.getAllTradingBalance(); double lastBid = Double.valueOf(orderBook.getBids().get(0).getPrice()); double lastAsk = Double.valueOf(orderBook.getAsks().get(0).getPrice()); double buyPrice = lastBid + tradeDifference; double sellPrice = lastAsk - tradeDifference; double profitablePrice = buyPrice + (buyPrice * tradeProfit / 100);

  logger.info(String.format("buyPrice:%.8f sellPrice:%.8f bid:%.8f ask:%.8f price:%.8f profit:%.8f diff:%.8f\n", buyPrice, sellPrice, lastAsk, lastAsk, lastPrice, profitablePrice, (lastAsk - profitablePrice)));

  if (orderId == null) {
    logger.info("nothing bought, let`s check");
    // find a burst to buy
    // but make sure price is ascending!
    if (lastAsk >= profitablePrice) {
      if (lastPrice > trackingLastPrice) {
        logger.info("Buy burst detected");
        currentlyBoughtPrice = profitablePrice;
        orderId = client.buy(tradeAmount, buyPrice).getOrderId();
        panicBuyCounter = 0;
        panicSellCounter = 0;
      } else {
        logger.warn("woooops, price is falling?!? don`t do something!");
        panicSellForCondition(lastPrice, lastKnownTradingBalance, client.tradingBalanceAvailable(tradingBalance));
      }
    } else {
      logger.info(String.format("No profit detected, difference %.8f\n", lastAsk - profitablePrice));
      currentlyBoughtPrice = null;
      panicSellForCondition(lastPrice, lastKnownTradingBalance, client.tradingBalanceAvailable(tradingBalance));
    }
  } else {
    Order order = client.getOrder(orderId);
    OrderStatus status = order.getStatus();
    if (status != OrderStatus.CANCELED) {
      // not new and not canceled, check for profit
      logger.info("Tradingbalance: " + tradingBalance);
      if ("0".equals("" + tradingBalance.getLocked().charAt(0)) &&
          lastAsk >= currentlyBoughtPrice) {
        if (status == OrderStatus.NEW) {
          // nothing happened here, maybe cancel as well?
          panicBuyCounter++;
          logger.info(String.format("order still new, time %d\n", panicBuyCounter));
          if (panicBuyCounter > 4) {
            client.cancelOrder(orderId);
            clear();
          }
        } else {
          if ("0".equals("" + tradingBalance.getFree().charAt(0))) {
            logger.warn("no balance in trading money, clearing out");
            clear();
          } else if (status == OrderStatus.PARTIALLY_FILLED || status == OrderStatus.FILLED) {
            logger.info("Order filled with status " + status);
            if (lastAsk >= profitablePrice) {
              logger.info("still gaining profitable profits HODL!!");
            } else {
              logger.info("Not gaining enough profit anymore, let`s sell");
              logger.info(String.format("Bought %d for %.8f and sell it for %.8f, this is %.8f coins profit", tradeAmount, currentlyBoughtPrice, sellPrice, (1.0 * currentlyBoughtPrice - sellPrice) * tradeAmount));
              client.sell(tradeAmount, sellPrice);
            }
          } else {
            // WTF?!
            logger.error("DETECTED WTF!!!!!");
            logger.error("Order: " + order + " , Order-Status: " + status);
            client.panicSell(lastKnownTradingBalance, lastPrice);
            clear();
          }
        }
      } else {
        panicSellCounter++;
        logger.info(String.format("sell request not successful, increasing time %d\n", panicSellCounter));
        panicSellForCondition(lastPrice, lastKnownTradingBalance, panicSellCounter > 3);
      }
    } else {
      logger.warn("Order was canceled, cleaning up.");
      clear(); // Order was canceled, so clear and go on
    }
  }
} catch (Exception e) {
  logger.error("Unable to perform ticker", e);
}
trackingLastPrice = lastPrice;

}

private void panicSellForCondition(double lastPrice, double lastKnownTradingBalance, boolean condition) { if (condition) { logger.info("panicSellForCondition"); client.panicSell(lastKnownTradingBalance, lastPrice); clear(); } }

private void clear() { panicBuyCounter = 0; panicSellCounter = 0; orderId = null; currentlyBoughtPrice = null; }

List getBalances() { return client.getBalances(); } } TradingClient.java: package io.github.unterstein;

import com.binance.api.client.BinanceApiClientFactory; import com.binance.api.client.BinanceApiRestClient; import com.binance.api.client.domain.OrderSide; import com.binance.api.client.domain.OrderType; import com.binance.api.client.domain.TimeInForce; import com.binance.api.client.domain.account.AssetBalance; import com.binance.api.client.domain.account.NewOrder; import com.binance.api.client.domain.account.NewOrderResponse; import com.binance.api.client.domain.account.Order; import com.binance.api.client.domain.account.request.CancelOrderRequest; import com.binance.api.client.domain.account.request.OrderRequest; import com.binance.api.client.domain.account.request.OrderStatusRequest; import com.binance.api.client.domain.market.Candlestick; import com.binance.api.client.domain.market.CandlestickInterval; import com.binance.api.client.domain.market.OrderBook; import org.slf4j.Logger; import org.slf4j.LoggerFactory;

import java.util.List;

public class TradingClient { private static Logger logger = LoggerFactory.getLogger(TradingClient.class);

private BinanceApiRestClient client; private String baseCurrency; private String tradeCurrency; private String symbol;

TradingClient(String baseCurrency, String tradeCurrency, String key, String secret) { this.baseCurrency = baseCurrency; this.tradeCurrency = tradeCurrency; BinanceApiClientFactory factory = BinanceApiClientFactory.newInstance(key, secret); client = factory.newRestClient(); symbol = tradeCurrency + baseCurrency; }

// The bid price represents the maximum price that a buyer is willing to pay for a security. // The ask price represents the minimum price that a seller is willing to receive. public OrderBook getOrderBook() { return client.getOrderBook(symbol, 5); }

public AssetBalance getBaseBalance() { return client.getAccount().getAssetBalance(baseCurrency); }

public AssetBalance getTradingBalance() { return client.getAccount().getAssetBalance(tradeCurrency); }

public double assetBalanceToDouble(AssetBalance balance) { return Double.valueOf(balance.getFree()) + Double.valueOf(balance.getLocked()); }

public double getAllTradingBalance() { AssetBalance tradingBalance = getTradingBalance(); return assetBalanceToDouble(tradingBalance); }

public boolean tradingBalanceAvailable(AssetBalance tradingBalance) { return assetBalanceToDouble(tradingBalance) > 1; }

public List getBalances() { return client.getAccount().getBalances(); }

public List getOpenOrders() { OrderRequest request = new OrderRequest(symbol); return client.getOpenOrders(request); }

public List getCandlestickBars() { //OrderRequest request = new OrderRequest(symbol); return client.getCandlestickBars("NEOETH", CandlestickInterval.WEEKLY); }

public void cancelAllOrders() { getOpenOrders().forEach(order -> client.cancelOrder(new CancelOrderRequest(symbol, order.getOrderId()))); }

// GTC (Good-Til-Canceled) orders are effective until they are executed or canceled. // IOC (Immediate or Cancel) orders fills all or part of an order immediately and cancels the remaining part of the order. public NewOrderResponse buy(int quantity, double price) { String priceString = String.format("%.8f", price).replace(",", "."); logger.info(String.format("Buying %d for %s\n", quantity, priceString)); NewOrder order = new NewOrder(symbol, OrderSide.BUY, OrderType.LIMIT, TimeInForce.GTC, "" + quantity, priceString); return client.newOrder(order); }

public void sell(int quantity, double price) { String priceString = String.format("%.8f", price).replace(",", "."); logger.info(String.format("Selling %d for %s\n", quantity, priceString)); NewOrder order = new NewOrder(symbol, OrderSide.SELL, OrderType.LIMIT, TimeInForce.GTC, "" + quantity, priceString); client.newOrder(order); }

public void sellMarket(int quantity) { if (quantity > 0) { logger.info("Selling to MARKET with quantity " + quantity); NewOrder order = new NewOrder(symbol, OrderSide.SELL, OrderType.MARKET, null, "" + quantity); client.newOrder(order); } else { logger.info("not executing - 0 quantity sell"); } }

public Order getOrder(long orderId) { return client.getOrderStatus(new OrderStatusRequest(symbol, orderId)); }

public double lastPrice() { return Double.valueOf(client.get24HrPriceStatistics(symbol).getLastPrice()); }

public void cancelOrder(long orderId) { logger.info("Cancelling order " + orderId); client.cancelOrder(new CancelOrderRequest(symbol, orderId)); }

public void panicSell(double lastKnownAmount, double lastKnownPrice) { logger.error("!!!! PANIC SELL !!!!"); logger.warn(String.format("Probably selling %.8f for %.8f", lastKnownAmount, lastKnownPrice)); cancelAllOrders(); sellMarket(Double.valueOf(getTradingBalance().getFree()).intValue()); } } `