Every year, N47 as a tech family celebrates a tech festival as Hackdays at the end of the year. In December 2019 we were in Budapest, Hungary for Hackdays. There were five different teams and each team had created some cool projects in a short time. I was also part of a team and we implemented a simple Trading Bot for Crypto. In this blog post, I want to share my experiences.
Trading Platform
To create a Trading Bot, you first need to find the right trading platform. We selected Binance DEX, which can offer a good volume for selected trading pairs, testnet for test purposes and was a Decentralized EXchange (DEX). Thanks to DEX, we can connect the wallet directly and use the credit directly from it.
Binance Chain is a new blockchain and peer-to-peer system developed by Binance and the community. Binance DEX is a secure, native marketplace that is based on the Binance Chain and enables the exchange of digital assets that are issued and listed in the DEX. Reconciliation takes place within the blockchain nodes, and all transactions are recorded in the chain, creating a complete, verifiable activity book. BNB is the native token in the Binance Chain, so users are charged the BNB for sending transactions.
Trading fees are subject to a complex logic, which can lead to individual transactions not being calculated exactly at the rates mentioned here, but instead between them. This is due to the block-based matching engine used in the DEX. The difference between Binance Chain and Ethereum is that there is no idea โโof gas
. As a result, the fees for the remaining transactions are set. There are no fees for a new order.
The testnet is a test environment for Binance Chain network, run by the Binance Chain development community, which is open to developers. The validators on the testnet are from the development team. There is also a web wallet that can directly interact with the DEX testnet. It also provides 200 testnet BNB so that you can interact with the Binance DEX testnet.
For developers, Binance DEX has also provided the REST API for testnet and main net. It also provides different Binance Chain SDKs for different languages like GoLang, Javascript, Java etc. We used Java SDK for the Trading Bot with Spring Boot.
Trading Strategy
To implement a Trading Bot, you need to know which pair and when to buy and sell Crypto for these pairs. We selected a very simple trading strategy for our project. First, we selected the NEXO / BINANCE trading pair (Nexo / BNB) because this pair has the highest trading volume. Perhaps you can choose a different trading pair based on your analysis.
For the purchase and sale, we made a decision based on Candlestick count. We considered the size of Candlestick for 15 minutes. If three are still red (price drops), buy Nexo and if three are still green (price increase), sell Nexo. Once you’ve bought or sold, you’ll have to wait for the next three. Continue with the red or green Candlestick. The purchase and sales volume is always 20 Nexo. You can also choose this based on your analysis.
Let’s Code IT
We have implemented the frontend (Vue.Js) and the backend (Spring Boot) for the Trading Bot, but here I will only go into the backend application as it contains the main logic. As already mentioned, the backend application was created with Spring Boot and Binance Chain Java SDK.
We used ThreadPoolTaskScheduler for the application. This scheduler runs every 2 seconds and checks Candlestick. This scheduler has to be activated once via the frontend app and is then triggered automatically every 2 seconds.
ThreadPoolTaskScheduler.scheduleAtFixedRate(task, 2000);
Based on the scheduler, the execute() method is triggered every two seconds. This method first collects all previous Candlestick for 15 minutes and calculates the green and red Candlestick. Based on this, it will buy or sell.
private double quantity = 20.0;
private String symbol = NEXO-A84_BNB;
public void execute() {
List<Candlestick> candleSticks = binanceDexApiRestClient.getCandleStickBars(this.symbol, CandlestickInterval.FIFTEEN_MINUTES);
List<Candlestick> lastThreeElements = candleSticks.subList(candleSticks.size() - 4, candleSticks.size() - 1);
// check if last three candlesticks are all red (close - open is negative)
boolean allRed = lastThreeElements.stream()
.filter(cs -> Double.parseDouble(cs.getClose()) - Double.parseDouble(cs.getOpen()) < 0.0d).count() == 3;
// check if last three candlesticks are all green (close - open is positive)
boolean allGreen = lastThreeElements.stream()
.filter(cs -> Double.parseDouble(cs.getOpen()) - Double.parseDouble(cs.getClose()) < 0.0d).count() == 3;
Wallet wallet = new Wallet(privateKey, binanceDexEnvironment);
// open and closed orders required to check last order creation time
OrderList closedOrders = binanceDexApiRestClient.getClosedOrders(wallet.getAddress());
OrderList openOrders = binanceDexApiRestClient.getOpenOrders(wallet.getAddress());
// order book required for buying and selling price
OrderBook orderBook = binanceDexApiRestClient.getOrderBook(symbol, 5);
Account account = binanceDexApiRestClient.getAccount(wallet.getAddress());
if ((openOrders.getOrder().isEmpty() || openOrders.getOrder().get(0).getOrderCreateTime().plusMinutes(45).isBeforeNow()) && (closedOrders.getOrder().isEmpty() || closedOrders.getOrder().get(0).getOrderCreateTime().plusMinutes(45).isBeforeNow())) {
if (allRed) {
if (Double.parseDouble(account.getBalances().stream().filter(b -> b.getSymbol().equals(symbol.split("_")[1])).findFirst().get().getFree()) >= (quantity * Double.parseDouble(orderBook.getBids().get(0).getPrice()))) {
order(wallet, symbol, OrderSide.BUY, orderBook.getBids().get(0).getPrice());
System.out.println("Buy Order Placed Quantity:" + quantity + " Symbol:" + symbol + " Price:" + orderBook.getAsks().get(0).getPrice());
} else {
System.out.println("do not have enough Token: " + symbol + " in wallet for buy");
}
} else if (allGreen) {
if (Double.parseDouble(account.getBalances().stream().filter(b -> b.getSymbol().equals(symbol.split("_")[0])).findFirst().get().getFree()) >= quantity) {
order(wallet, symbol, OrderSide.SELL, orderBook.getAsks().get(0).getPrice());
System.out.println("Sell Order Placed Quantity:" + quantity + " Symbol:" + symbol + " Price:" + orderBook.getAsks().get(0).getPrice());
} else {
System.out.println("do not have enough Token:" + symbol + " in wallet for sell");
}
} else System.out.println("do nothing");
} else System.out.println("do nothing");
}
private void order(Wallet wallet, String symbol, OrderSide orderSide, String price) {
NewOrder no = new NewOrder();
no.setTimeInForce(TimeInForce.GTE);
no.setOrderType(OrderType.LIMIT);
no.setSide(orderSide);
no.setPrice(price);
no.setQuantity(String.valueOf(quantity));
no.setSymbol(symbol);
TransactionOption options = TransactionOption.DEFAULT_INSTANCE;
try {
List<TransactionMetadata> resp = binanceDexApiRestClient.newOrder(no, wallet, options, true);
log.info("TransactionMetadata", resp);
} catch (Exception e) {
log.error("Error occurred while order", e);
}
}
At first glance, the strategy looks really simple, I agree. After this initial setup, however, it’s easy to add more complex logic with some AI.
Result
Since 12th December 2019, this bot is running on Google Cloud and did 1130 transactions (buy/sell) until 14th April 2020. Initially, I started this bot with 2.6 BNB. On 7th February 2020, the balance was 2.1 BNB in the wallet, but while writing this blog on 14th April 2020, it looks like the bot has recovered the loss and the balance is 2.59 BNB. Hopefully, in future it will make some profit๐ฐ๐.
Let me know your suggestions in a comment on this bot and I would also like to answer your questions if you have anything on this topic. Thanks for the time.