Read live Binance candlestick data using java-spring boot

This article describes how to read and store the candlestick data from Binance.com. We are using “binance-java-api” an api build on java here on the GitHub repository. This java api is not very active on Github, but it is good enough to read the candlestick data from Binance.

Adding required dependencies

Our example uses “binance-api-client” an open source java implementation of Binance APIs. Since this implementation is published on Github we need to add the GitPack repository to our pom.xml, otherwise binance-api-client won’t load.

Add below code as a child element of <project> tag in pom.xml

           <repositories>
			<repository>
				<id>jitpack.io</id>
				<url>https://jitpack.io</url>
			</repository>
          </repositories>
<dependency>
  <groupId>com.binance.api</groupId>
  <artifactId>binance-api-client</artifactId>
  <version>1.0.0</version>
</dependency>

This example uses the several other dependencies as well,

  • lombok – Reduces the boilerplate codes.
  • spring-boot-starter-data-jpa – This includes all the classes and files required for data persistence
  • mysql-connector-java – For connecting to MySQL database

Here is the link to the entire pom.xml to see all dependencies and how they are configured – pom.xml

Let’s work with the code now,

Entity Class to store CandleStick Data

This class serves as an Entity, in spring boot entities represents the structure of object saved in the database.

package com.bitcoinbuyindia.websocketexample.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Data;
@Entity
@Data
public class CandleStickData {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    private String coinPairName;
    
    /* Properties from Binance pojo */
    private String eventType;
    private long eventTime;
    private String symbol;
    private Long openTime;
    private String open;
    private String high;
    private String low;
    private String close;
    private String volume;
    private Long closeTime;
    private String intervalId;
    private Long firstTradeId;
    private Long lastTradeId;
    private String quoteAssetVolume;
    private Long numberOfTrades;
    private String takerBuyBaseAssetVolume;
    private String takerBuyQuoteAssetVolume;
    private Boolean isBarFinal;
    
}

Repository for CandleStickData

Now for accessing the entities we need to create the corresponding repository interface. The spring will provide the implementations for these interfaces on runtime with apopriate methods to query and persist the data.

package com.bitcoinbuyindia.websocketexample.repositories;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.bitcoinbuyindia.websocketexample.entities.CandleStickData;
@Repository
public interface CandleStickDataReposiory extends CrudRepository<CandleStickData,Long> {
	
}

Service class to read WebSocket data from Binance and save it to our repository

Here we have the main logic to subscribe the Websocket stream of bitcoin Klines. We are using the BinanceApiWebSocketClient implementation from our binance-api-client dependency. The callback is as an argument to the onCandlestickEvent() method of the WebsocketClient.

package com.bitcoinbuyindia.websocketexample.service;
import com.binance.api.client.BinanceApiClientFactory;
import com.binance.api.client.BinanceApiWebSocketClient;
import com.binance.api.client.domain.market.CandlestickInterval;
import com.bitcoinbuyindia.websocketexample.entities.CandleStickData;
import com.bitcoinbuyindia.websocketexample.repositories.CandleStickDataReposiory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@Data
@Slf4j
@Service
public class CandleStickService {
	private String apiKey = "your api key";
	private String apiSecret = "your api secret";
	private String coinPairName = "btcusdt";
	@Autowired
	private CandleStickDataReposiory candleStickDataReposiory;
	public void subscribeCandleStickData() {
		BinanceApiWebSocketClient client = BinanceApiClientFactory.newInstance(apiKey,apiSecret).newWebSocketClient();
		client.onCandlestickEvent(coinPairName, CandlestickInterval.FIVE_MINUTES, response -> {
			// Save only if candle stick bar is final
			if(response.getBarFinal()) {
				CandleStickData candleStickEvent = new CandleStickData();
				candleStickEvent.setCoinPairName(coinPairName);
				candleStickEvent.setEventType(response.getEventType());
				candleStickEvent.setEventTime(response.getEventTime());
				candleStickEvent.setSymbol(response.getSymbol());
				candleStickEvent.setOpenTime(response.getOpenTime());
				candleStickEvent.setOpen(response.getOpen());
				candleStickEvent.setClose(response.getClose());
				candleStickEvent.setHigh(response.getHigh());
				candleStickEvent.setLow(response.getLow());
				candleStickEvent.setVolume(response.getVolume());
				candleStickEvent.setCloseTime(response.getCloseTime());
				candleStickEvent.setIntervalId(response.getIntervalId());
				candleStickEvent.setFirstTradeId(response.getFirstTradeId());
				candleStickEvent.setLastTradeId(response.getLastTradeId());
				candleStickEvent.setQuoteAssetVolume(response.getQuoteAssetVolume());
				candleStickEvent.setNumberOfTrades(response.getNumberOfTrades());
				candleStickEvent.setTakerBuyBaseAssetVolume(response.getTakerBuyBaseAssetVolume());
				candleStickEvent.setTakerBuyQuoteAssetVolume(response.getTakerBuyQuoteAssetVolume());
				candleStickEvent.setIsBarFinal(response.getBarFinal());
				candleStickDataReposiory.save(candleStickEvent);
			} else {
				log.info("kline is not final open_time={}",response.getOpenTime());
			}
		});
		
	}

	@EventListener
	public void onApplicationEvent(ContextRefreshedEvent event) {
		log.info("starting service");
		this.subscribeCandleStickData(); //Start reading Binance data whenever the application loads
	}
}

The CandleStickService will subscribe to the WebSocket stream as soon as the application loads or restarts. We will save the candlestick data when we get a final version of the candle.

The source-code is available here on GitHub

Happy Trading !!! Happy Coding !!

How to get candlestick data from crypto exchanges using java, spring boot