Binance trading program

in #trading7 years ago (edited)

I wrote a program to automatically trade cryptocurrency using the Binance library.
I am very tired of watching the trend while trading, and I have implemented the logic that I trade in as a program.
I do not want to encourage you to use it because you may lose money. Please refer to it and hope to have a hint.

I'll introduce the logic briefly.

  1. The base amount is the last sale price or the current price.
  2. If the present price is bigger than the base price, it is sold. If it is small, it is bought.
  3. Buying: If the price falls below a certain percentage and the specified percentage and price go up in the min price, the market will be bought.
  4. Sell: Sells in the market if it is higher than the specified percentage and the price is lowered by the specified percentage in the max price.
  5. When a transaction occurs, a message is sent to the telegram.
  6. Logs are logged at regular intervals.
  7. Save the price data as json each time, and refer to the data when reloading and reloading the program.
  8. Bring the market price at a set time interval and repeat steps 1-7.

Below is the source I wrote.

package com.binance.trading;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.ArrayUtils;

import com.binance.api.client.BinanceApiClientFactory;
import com.binance.api.client.BinanceApiRestClient;
import com.binance.api.client.domain.account.Account;
import com.binance.api.client.domain.account.AssetBalance;
import com.binance.api.client.domain.account.NewOrder;
import com.binance.api.client.domain.account.Order;
import com.binance.api.client.domain.account.Trade;
import com.binance.api.client.domain.account.request.OrderRequest;
import com.binance.api.client.domain.general.ExchangeInfo;
import com.binance.api.client.domain.general.FilterType;
import com.binance.api.client.domain.general.SymbolFilter;
import com.binance.api.client.domain.general.SymbolInfo;
import com.binance.api.client.domain.market.TickerPrice;
import com.binance.api.client.exception.BinanceApiException;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.request.SendMessage;

/**
 * Examples on how to get market data information such as the latest price of a
 * symbol, etc.
 */
public class MarketOrderTrading extends TimerTask {
    private final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    private final String ITEMS_FILE_NAME = "trading_items.json";
    private final Type ITEMS_TYPE = new TypeToken<Map<String, TradingItems>>() {}.getType();
    
    private final String API_KEY = "API_KEY ";
    private final String SECRET_KEY = "SECRET_KEY ";
    private final String TELEGRAM_TOKEN = "TELEGRAM_TOKEN ";
    private final String TELEGRAM_CHAT_ID = "TELEGRAM_CHAT_ID ";

    private final String CURRENCY_SYMBOL = "BTC";
    private final static String[] TARGET_SYMBOLS = { "ETH"};
    private final double CURRENCY_INVEST_PRICE = 0.002;
    private final double GAP_TRADING_PERCENT = 70.0;
    private final boolean IS_RISK_TASKING = false;
    private final double FEE_PERCENT = 0.05;
    private final double TAKE_EXTRA_PERCENT = 2.0;
    private final double MIN_START_PERCENT = 2.0;
    private final static int TIME_PERIOD_MILLISECONDS = 500;
    private final double MIN_ORDER_VALUE = 0.001;
    
    private final int STATUS_LOGGING_CYCLE = 600;

    private final BinanceApiClientFactory factory = BinanceApiClientFactory.newInstance(API_KEY, SECRET_KEY);
    private final BinanceApiRestClient client = factory.newRestClient();
    private final TelegramBot telegramBot = new TelegramBot(TELEGRAM_TOKEN);

    private Map<String, TradingItems> items = new HashMap<String, TradingItems>();
    private long exeCount = 0;
    private FileWriter fw;

    public MarketOrderTrading() {
        initialSettings();
    }

    
    private void initialSettings() {
        loadItems();
        for (final String key : items.keySet()) {
            if ( ArrayUtils.contains(TARGET_SYMBOLS, key) == false ) {
                items.remove(key);
            }
        }
        
        for (int i = 0; i < TARGET_SYMBOLS.length; i++) {
            final String targetSymbol = TARGET_SYMBOLS[i];
            if (items.containsKey(targetSymbol) == false) {
                initialBasicSetting(targetSymbol);
                initialSetting(items.get(targetSymbol));
            }
        }
    }
    
    private void initialBasicSetting(final String targetSymbol) {
        TradingItems item;
        if (items.containsKey(targetSymbol)) {
            item = this.items.get(targetSymbol);
        } else {
            item = new TradingItems();
            items.put(targetSymbol, item);
        }
        item.setTargetSymbol(targetSymbol);
        item.setPairSymbol(targetSymbol + CURRENCY_SYMBOL);
        getLotSize(item);
    }

    private void initialSetting(final TradingItems item) {
        final List<Order> openOrders = getOpenOrders(item.getPairSymbol());
        if (openOrders.size() > 0) {
            item.setWaiting(true);
            return;
        } else {
            item.setWaiting(false);
        }

        final TickerPrice nowTickerPrice = getPrice(item.getPairSymbol());
        final double nowPrice = Double.parseDouble(nowTickerPrice.getPrice());

        Trade trade = getLastTrade(item.getPairSymbol());
        double bagicPrice = 0.0;
        if (trade != null) {
            bagicPrice = Double.parseDouble(trade.getPrice());
        } else {
            bagicPrice = nowPrice;
        }

        item.setTopPrice(bagicPrice);
        item.setBottomPrice(bagicPrice);
        item.setLastOrderPrice(bagicPrice);

        sendLogging(item.getPairSymbol() +  ", Bagic Price : " + toString(bagicPrice), false);
    }

    private void getLotSize(final TradingItems item) {
        final ExchangeInfo exchangeInfo = client.getExchangeInfo();
        final SymbolInfo symbolInfo = exchangeInfo.getSymbolInfo(item.getPairSymbol());
        final SymbolFilter priceFilter = symbolInfo.getSymbolFilter(FilterType.LOT_SIZE);
        item.setMinQty(Double.parseDouble(priceFilter.getMinQty()));
        item.setStepSize(Double.parseDouble(priceFilter.getStepSize()));
    }

    private TickerPrice getPrice(final String pairSymbol) {
        return client.getPrice(pairSymbol);
    }

    private List<Order> getOpenOrders(final String pairSymbol) {
        return client.getOpenOrders(new OrderRequest(pairSymbol));
    }

    private Trade getLastTrade(final String pairSymbol) {
        Trade trade = null;
        List<Trade> trades = client.getMyTrades(pairSymbol, 1);
        if (trades.size() > 0) {
            trade = trades.get(0);
        }
        return trade;
    }

    private AssetBalance getCurrencyAssetBalance() {
        return getAssetBalance(CURRENCY_SYMBOL);
    }

    private AssetBalance getTargetAssetBalance(final String targetSymbol) {
        return getAssetBalance(targetSymbol);
    }

    private AssetBalance getAssetBalance(final String symbol) {
        final Account account = client.getAccount(6000000L, System.currentTimeMillis());
        return account.getAssetBalance(symbol);
    }

    private void watchTrading(final TradingItems item) {
        if (item.isWaiting()) {
            initialSetting(item);
            return;
        }
        final double lastOrderPrice = item.getLastOrderPrice();
        final TickerPrice nowTickerPrice = getPrice(item.getPairSymbol());
        final double nowPrice = Double.parseDouble(nowTickerPrice.getPrice());
        item.setNowPrice(nowPrice);
        
        if (nowPrice < lastOrderPrice) { // Buy
            item.setBuy(true);
            watchBuyTrading(item);
        } else { // Sell
            item.setBuy(false);
            watchSellTrading(item);
        }
    }

    private void watchBuyTrading(final TradingItems item) {
        final double bottomPrice = item.getBottomPrice();
        final double lastOrderPrice = item.getLastOrderPrice();
        final double nowPrice = item.getNowPrice();

        if (nowPrice < bottomPrice) {
            item.setBottomPrice(nowPrice);
        } else {

            if (this.IS_RISK_TASKING == false) {
                final double breakEvenPrice = lastOrderPrice
                        - nowPrice * (TAKE_EXTRA_PERCENT + FEE_PERCENT) / 100.0;
                if (nowPrice > breakEvenPrice) {
                    return;
                }
            }

            if (nowPrice - bottomPrice < nowPrice * (MIN_START_PERCENT / 100)) {
                return;
            }

            final double maxPrice = lastOrderPrice - (lastOrderPrice - bottomPrice) * (GAP_TRADING_PERCENT / 100.0);
            if (nowPrice < maxPrice) {
                return;
            }
            orderBuying(item, nowPrice);
            initialSetting(item);
        }
    }

    private void watchSellTrading(final TradingItems item) {
        final double topPrice = item.getTopPrice();
        final double lastOrderPrice = item.getLastOrderPrice();
        final double nowPrice = item.getNowPrice();
        
        if (nowPrice > topPrice) {
            item.setTopPrice(nowPrice);
        } else {

            if (this.IS_RISK_TASKING == false) {
                final double breakEvenPrice = lastOrderPrice
                        + nowPrice * (TAKE_EXTRA_PERCENT + FEE_PERCENT * 2) / 100.0;
                if (nowPrice < breakEvenPrice) {
                    return;
                }
            }

            if (topPrice - nowPrice < nowPrice * (MIN_START_PERCENT / 100)) {
                return;
            }

            final double minPrice = lastOrderPrice + (topPrice - lastOrderPrice) * (GAP_TRADING_PERCENT / 100.0);
            if (nowPrice > minPrice) {
                return;
            }
            orderSelling(item, nowPrice);
            initialSetting(item);
        }
    }

    private String getStatusLogging(final TradingItems item) {
        return item.getPairSymbol() + " -- " 
                        + (item.isBuy() ? "Buy" : "Sell") 
                        + ", N:" + toString(item.getNowPrice())
                        + ", T:" + toString(item.getTopPrice()) 
                        + ", B:"+ toString(item.getBottomPrice()) 
                        + ", L:" + toString(item.getLastOrderPrice());
    }
    
    private void sendStatusLogging() {
        if (exeCount % STATUS_LOGGING_CYCLE == 0) {
            final StringBuffer sb = new StringBuffer();
            for (int i = 0; i < TARGET_SYMBOLS.length; i++) {
                final String targetSymbol = TARGET_SYMBOLS[i];
                final TradingItems item = items.get(targetSymbol);
                sb.append(getStatusLogging(item)).append(System.lineSeparator());
            }
            sendLogging(sb.toString(), false);
        }
    }

    private void orderBuying(final TradingItems item, final double price) {
        final AssetBalance balance = getCurrencyAssetBalance();
        final double freeQty = Double.parseDouble(balance.getFree());
        String buyQty = null;
        if (freeQty < MIN_ORDER_VALUE) {
            sendLogging(item.getPairSymbol() + ", BTC Free Qty : " + freeQty + " --- There is not enough currency.", false);
            return;
        } else if (freeQty < CURRENCY_INVEST_PRICE) {
            buyQty = toOrderQty(item, freeQty / price);
        } else {
            buyQty = toOrderQty(item, CURRENCY_INVEST_PRICE / price);
        }

        try {
            client.newOrder(NewOrder.marketBuy(item.getPairSymbol(), buyQty));
            sendLogging(item.getPairSymbol() + " -- Buy : " + toString(price) + ", Qty : " + buyQty);
        } catch (BinanceApiException e) {
            sendLogging(e.getMessage());
            e.printStackTrace();
        }
    }

    private void orderSelling(final TradingItems item, final double price) {
        final AssetBalance balance = getTargetAssetBalance(item.getTargetSymbol());
        final double freeQty = Double.parseDouble(balance.getFree());
        final double sellMaxQty =  CURRENCY_INVEST_PRICE / price;
        final double sellMinQty =  MIN_ORDER_VALUE / price;
        String sellQty = null;
        if (sellMinQty > freeQty) {
            sendLogging(item.getPairSymbol() + ", Free Qty : " + freeQty + " --- There is not enough target.", false);
            return;
        } else if (sellMaxQty > freeQty) {
            sellQty = toOrderQty(item, freeQty);
        } else {
            sellQty = toOrderQty(item, sellMaxQty);
        }
        
        try {
            client.newOrder(NewOrder.marketSell(item.getPairSymbol(), sellQty));
            sendLogging(item.getPairSymbol() + " -- Sell : " + toString(price) + ", Qty : " + sellQty);
        } catch (BinanceApiException e) {
            sendLogging(e.getMessage());
            e.printStackTrace();
        }
    }

    private String toOrderQty(final TradingItems item, final double qty) {
        String strOrderQty = null;
        if (qty >= item.getMinQty()) {
            double orderQty = qty - qty % item.getStepSize();
            strOrderQty = toString(orderQty);
        }
        return strOrderQty;
    }

    private String toString(double num) {
        return String.format("%.9f", num);
    }

    private void sendLogging(final String message) {
        System.out.println(addDateString(message));
        sendToBot(message);
    }

    private void sendLogging(final String message, final boolean sendBot) {
        if (sendBot) {
            sendLogging(message);
        } else {
            System.out.println(addDateString(message));
        }
    }

    private String addDateString(final String message) {
        final Date nowDate = new Date();
        return message + ":: " + DATE_FORMAT.format(nowDate);
    }

    private void sendToBot(final String message) {
        try {
            final SendMessage request = new SendMessage(TELEGRAM_CHAT_ID, addDateString(message));
            telegramBot.execute(request);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private void saveItems() {
        final Gson gson = new Gson();
        final String jsonItems = gson.toJson(items);
        try {
            fw = new FileWriter(ITEMS_FILE_NAME);
            fw.write(jsonItems);
            fw.flush();
        } catch (IOException e) {
            sendLogging(e.getMessage());
            e.printStackTrace();
        }
    }
    
    private void loadItems() {
        JsonReader reader;
        Gson gson = new Gson();
        try {
            reader = new JsonReader(new FileReader(ITEMS_FILE_NAME));
            this.items = gson.fromJson(reader, ITEMS_TYPE);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    

    @Override
    public void run() {
        for (int i = 0; i < TARGET_SYMBOLS.length; i++) {
            final String targetSymbol = TARGET_SYMBOLS[i];
            final TradingItems item = items.get(targetSymbol);
            watchTrading(item);
        }
        saveItems();
        sendStatusLogging();
        
        exeCount++;
    }

    public static void main(String[] args) {

        final TimerTask task = new MarketOrderTrading();
        final ScheduledExecutorService service =
        Executors.newSingleThreadScheduledExecutor();
        service.scheduleWithFixedDelay(task, TIME_PERIOD_MILLISECONDS, 
                TIME_PERIOD_MILLISECONDS, TimeUnit.MILLISECONDS);
    }

}

Sort:  
Loading...