Trading strategies
Description
Binance4j-strategy adds technical analysis for the binance4j ecosystem thanks to ta4j indicators and rules.
Installation
- Maven
- Gradle
<dependency>
<groupId>{{groupId}}</groupId>
<artifactId>{{artifactId}}</artifactId>
<version>{{version}}</version>
</dependency>
implementation '{{groupId}}:{{artifactId}}:{{version}}'
What is a trading strategy?
A trading strategy is a class containing two methods receiveing a BarSeries as an input and returning a trading Rule as an output, the first will send a BUY signal and the other a SELL signal.
Every trading strategy must implement the TradingStrategy
interface. This is the signature of the interface:
public interface TradingStrategy {
// The BUY signal
Rule entry(BarSeries series);
// The SELL signal
Rule exit(BarSeries series);
}
Binance4j-strategy uses ta4j for technical analysis, don't hesitate to read their documentation to understand what are indicators and rules.
Creating a trading strategy
Here is a trading strategy using the two period RSI indicator:
public class TwoPeriodRSIStrategy implements TradingStrategy {
@Override
public Rule entry(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
}
@Override
public Rule exit(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
}
}
Backtesting a strategy
Binance4j can backtest a trading strategy in many ways.
With existing data
// Here we get historical klines data from the public data API.
List<Candle> bars = new VisionSpotClient().getKlines("BTCBUSD", CandlestickInterval.FIVE_MINUTES, "2022", "01").getData();
// let's give it to the BackTestService. CandlestickInterval must match.
BackTestResult result = BackTestService.backTest(strategy, bars, CandlestickInterval.FIVE_MINUTES);
// we can also use a ta4j Barseries instance. Let's convert the existing candles
BarSeries series = BarSeriesService.convert(bars,CandlestickInterval.FIVE_MINUTES);
BackTestResult result = BackTestService.backTest(strategy, series);
With inner vision client
The service can automatically use an instance of a VisionSpotClient to collect public data from the Binance API.
// The service will automatically use an instance of a VisionClient to get the data from the API
BackTestResult result = BackTestService.backTest(strategy, "BTCBUSD", CandlestickInterval.FIVE_MINUTES, "2022", "01");
Get the strategy position other a BarSeries
The PositionService service can give us the position of our strategy over a BarSeries instance.
//The service will tell us if the strategy sends a BUY signal over the given index on the BarSeries
boolean shouldEnter = PositionService.shouldEnter(strategy, series, index);
//The service will tell us if the strategy sends a SELL signal over the given index on the BarSeries
boolean shouldExit = PositionService.shouldExit(strategy, series, index);
//The service will tell us if the strategy sends a BUY signal over the last Bar in the BarSeries
boolean shouldEnter = PositionService.shouldEnter(strategy, series);
//The service will tell us if the strategy sends a SELL signal over the last Bar in the BarSeries
boolean shouldExit = PositionService.shouldExit(strategy, series);
Live trading
In order to handle your strategy signals, you need to implement a StrategyCallback
.
public class MyStrategyCallback implements StrategyCallback {
public MyStrategyCallback() {
//...
}
// Handle BUY signal
@Override
public void onEnter(BarSeries series) {
//...
}
// Handle SELL signal
@Override
public void onExit(BarSeries series) {
//...
}
// server sent data
@Override
public void onMessage(SymbolBar symbolBar) {
//...
}
// Stream is open
@Override
public void onOpen(Response response) {
//...
}
// Stream is closing
@Override
public void onClosing(WebsocketCloseObject closeObject) {
//...
}
// Stream is closed
@Override
public void onClosed(WebsocketCloseObject closeObject) {
//...
}
// Something went wrong
@Override
public void onFailure(ApiException apiException) {
//...
}
}
Let's instantiate and run a service.
//we will use the previous strategy
WatchService service = new WatchService(strategy, myStrategyCallback);
service.watch("BTCBUSD", CandlestickInterval.FIVE_MINUTE);
When done, stop the service:
service.unwatch();