Skip to main content
Version: 1.x

Strategy

 Maven Central Sonatype Nexus  License: MIT

Description

Binance4j-strategy adds technical analysis for the binance4j ecosystem.

Installation

pom.xml
<dependency>
<groupId>{{groupId}}</groupId>
<artifactId>{{artifactId}}</artifactId>
<version>{{version}}</version>
</dependency>

Dependencies

Write a strategy

Binance4j uses ta4j for technical analysis and backtesting.

To understand how indicators and rules work, read the library documentation

//Every Strategy must extend BaseTradingStrategy
public class TwoPeriodRSIStrategy extends BaseTradingStrategy {

//This is where we define the rule that will send a BUY signal
@Override
public Rule getEntry(BarSeries series) {
ClosePriceIndicator closePrice = new ClosePriceIndicator(series);
SMAIndicator shortSma = new SMAIndicator(closePrice, 5);
SMAIndicator longSma = new SMAIndicator(closePrice, 200);

// We use a 2-period RSI indicator to identify buying
// or selling opportunities within the bigger trend.
RSIIndicator rsi = new RSIIndicator(closePrice, 2);

// Entry rule
// The long-term trend is up when a security is above its 200-period SMA.
return new OverIndicatorRule(shortSma, longSma) // Trend
.and(new CrossedDownIndicatorRule(rsi, 5)) // Signal 1
.and(new OverIndicatorRule(shortSma, closePrice)); // Signal 2
}

//This is where we define the rule that will send a SELL signal
@Override
public Rule getExit(BarSeries series) {
ClosePriceIndicator closePrice = new ClosePriceIndicator(series);
SMAIndicator shortSma = new SMAIndicator(closePrice, 5);
SMAIndicator longSma = new SMAIndicator(closePrice, 200);

// We use a 2-period RSI indicator to identify buying
// or selling opportunities within the bigger trend.
RSIIndicator rsi = new RSIIndicator(closePrice, 2);

// Exit rule
// The long-term trend is down when a security is below its 200-period SMA.
return new UnderIndicatorRule(shortSma, longSma) // Trend
.and(new CrossedUpIndicatorRule(rsi, 95)) // Signal 1
.and(new UnderIndicatorRule(shortSma, closePrice)); // Signal 2

}
}

Backtest a strategy

 
// Let's get some public data with the vision SpotClient
List<CandlestickBar> bars = new SpotClient()
.getKlines("BNBBTC", CandlestickInterval.FIVE_MINUTES, "2022", "01")
.getData();

//We instantiate the strategy
TwoPeriodRSIStrategy strategy = new TwoPeriodRSIStrategy();

//We run the backtest on the series
BackTestResult result = strategy.backTest(bars, CandlestickInterval.FIVE_MINUTES);

Live trade

 

Live trading uses binance4j-websocket to get real-time klines data

TwoPeriodRSIStrategy strategy = new TwoPeriodRSIStrategy();

//The stream callback
StrategyCallback callback = new StrategyCallback();

//Stream is closed
callback.onClosed(websocketCloseObject -> {
//...
});

//Stream is closing
callback.onClosing(WebsocketCloseObject -> {
//...
});

//Stream is open
callback.onOpen(response -> {
//...
});

//connection failed/reading data failed/ping failed
callback.onFailure(apiException -> {
//...
});

//BUY signal (only called on final bar of interval)
callback.onEnter(series -> {
//...
});

//SELL signal (only called on final bar of interval)
callback.onExit(series-> {
//...
});

//every tick
callback.onMessage(symbolBar -> {
//...
});

// We set the inner BarSeries size. Default is 500.
strategy.setMaximumBarCount(200);

//We start live trading
WebsocketClient wsClient = strategy.watch("BNBBTC", CandlestickInterval.ONE_MINUTE, callback);

//We stop live trading
strategy.unwatch();

Watch multiple symbols

A strategy can watch multiple symbols at the same time. Just use a string with symbols separated by a coma:

WebsocketClient wsClient = strategy.watch("BNBBTC,BTCBUSD,SHIBBUSD", CandlestickInterval.ONE_MINUTE, callback);

or with a collection:

WebsocketClient wsClient = strategy.watch(List.of("BNBBTC","BTCBUSD","SHIBBUSD"), CandlestickInterval.ONE_MINUTE, callback);

The strategy will create a BarSeries instance for every symbol.

To know the symbol of the series returned by onEnter and onExit, do as follow:

callback.onEnter(series -> {
series.getName(); // returns the symbol
});

callback.onExit(series-> {
series.getName(); // returns the symbol
});

To know the symbol of the bar returned by onMessage, do as follow:

//every tick
callback.onMessage(symbolBar -> {
symbolBar.getSymbol(); // returns the symbol
});

Get strategy position over a candlestick

The strategy can also give its trading position over the bars.

// Let's get some public data with the vision SpotClient
List<CandlestickBar> bars = new SpotClient()
.getKlines("BNBBTC", CandlestickInterval.FIVE_MINUTES, "2022", "01")
.getData();

// We instantiate the strategy
TwoPeriodRSIStrategy strategy = new TwoPeriodRSIStrategy();

// Here we get the position of the strategy on the last bar of the series
boolean shouldEnter = strategy.shouldEnter(bars, CandlestickInterval.FIVE_MINUTES);
boolean shouldExit = strategy.shouldExit(bars, CandlestickInterval.FIVE_MINUTES);

// Here we get the position of the strategy on the 6th bar of the series
boolean shouldEnter = strategy.shouldEnter(bars, CandlestickInterval.FIVE_MINUTES, 5);
boolean shouldExit = strategy.shouldExit(bars, CandlestickInterval.FIVE_MINUTES, 5);

The CandlestickBar list will be converted at every method call.

To prevent useless computation, you can convert the list into a BarSeries before giving it to the methods.

// Let's get some public data with the vision SpotClient
List<CandlestickBar> bars = new SpotClient()
.getKlines("BNBBTC", CandlestickInterval.FIVE_MINUTES, "2022", "01")
.getData();

// We convert the bars into a BarSeries
BarSeries series = BarSeriesService.convert(bars, CandlestickInterval.FIVE_MINUTES);

//We instantiate the strategy
TwoPeriodRSIStrategy strategy = new TwoPeriodRSIStrategy();

// Here we get the position of the strategy on the last bar of the series
boolean shouldEnter = strategy.shouldEnter(series);
boolean shouldExit = strategy.shouldExit(series);

//Here we get the position of the strategy on the 6th bar of the series
boolean shouldEnter = strategy.shouldEnter(series, 5);
boolean shouldExit = strategy.shouldExit(series, 5);