Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
303 lines (226 sloc) 12.4 KB

Examples

If you have any questions about the meaning of the fields, see the Bitfinex API documentation for further information.

Do not hesitate to report any issues/changes that we missed, as Bitfinex is contantly improving their API, and we don't keep track of them on every day basis.

Connecting and authorizing

final String apiKey = "....";
final String apiSecret = "....";

// For public operations (subscribe ticker, candles)
final BitfinexWebsocketClient client = BitfinexClientFactory.newSimpleClient();
client.connect();

// For public and private operations (executing orders, read wallets)
final BitfinexWebsocketConfiguration config = new BitfinexWebsocketConfiguration();
config.setApiCredentials(apiKey, apiSecret);

final BitfinexWebsocketClient bitfinexClient = BitfinexClientFactory.newSimpleClient(config);
bitfinexClient.connect();

Provided API key permissions

final BitfinexApiKeyPermissions permissions = client.getApiKeyPermissions();
if( !permissions.isOrderWritePermission() ) {
	System.err.println("This API key does not allow the placement of orders");
} else {
	// place order
)

Available Currency Pairs

Client implementation depends internally on BitfinexCurrencyPair class which is abstraction of available currency pairs within exchange. Since Bitfinex is introducing new currency pairs without any notice (and does it quite often), it's up to user to keep it, as library will raise an exception on unrecognized currency pair.

To retrieve all available currency pairs user may fetch data from following URLs as described here.

https://api.bitfinex.com/v1/symbols
https://api.bitfinex.com/v1/symbols_details

Since version 0.7.1, our library does not contain any hardcoded currency symbols anymore. The available currencies change very frequently and we are unable to keep the symbols up-to-date. You can register the needed currencies on your own or you can call the method registerDefaults which fetches all known currencies from Bitfinex and registers them.

BitfinexCurrencyPair.registerDefaults();

However, as explained the user can register all currency pairs on their own by fetching one of mentioned REST services.

Here's a snippet of registering process

BitfinexCurrencyPair.register("BTC","USD", 0.001); // currency, profitCurrency, minimalOrderSize

Library will raise exception during registration if currency pair is already existing. To prevent that user should call:

BitfinexCurrencyPair.unregisterAll()

PS. minimalOrderSize is not used any way by library - so user may pass 0.0d if not interested in that value.

Connection Features

// Enabling package sequence auditing (ensuring all result packages are processed)

final BitfinexWebsocketConfiguration config = new BitfinexWebsocketConfiguration();
config.setErrorPolicy(ErrorPolicy.RUNTIME_EXCEPTION);
[...]

final BitfinexWebsocketClient bitfinexClient = BitfinexClientFactory.newSimpleClient(config);

final ConnectionFeatureManager cfManager = bitfinexClient.getConnectionFeatureManager();
cfManager.enableConnectionFeature(BitfinexConnectionFeature.SEQ_ALL);

Channel subscriptions

In following chapter, we shall provide some examples on how to subscribe to different channels and listen on their events. API user needs to ensure client is firstly connected, as listeners do not perform channel subscriptions.

Low-level channel subscription

Library exposes all events that are received. Here's an end-to-end snippet

(1)     BitfinexCurrencyPair.registerDefaults();
(2a)    var config = new BitfinexApiBrokerConfig();
        config.setApiCredentials("user-api-key", "user-api-secret");
(2b)    var client = BitfinexClientFactory.newSingleClient(config);
(2c)    client.connect();
(3)     var symbol = BitfinexSymbols.*("curr1","curr2", [...]);
(4)     client.sendCommand(BitfinexCommands.subscribe*Channel(symbol));
(5)     Closeable callbackHandler = client.getCallbacks().on*Event((symbol, payload) -> {
            // handle event
        })
(6a)    callbackHandler.close();
(6b)    client.sendCommand(BitfinexCommands.unsubscribeChannel(symbol));

1 - registering bitfienx currency pairs preset in JVM 
2 - client setup 
3 - symbol creation
4 - subscribing to channel for websocket events
5 - registering listener for all events on given type (not per-symbol - for that functionality revert to managers)
6a - unregistering listener (events are still received and client still internally handles them)
6b - unsubscribing from channel (events no longer come)

6a and 6b are not depending on one another - user may wish to keep listeners registered to channels which are not operable (at given time)

Library API exposes easy way of setting up subscriptions and handling events through Managers. Following examples will depend on them.

Subscribe candles stream

final BitfinexCandlestickSymbol symbol
	= BitfinexSymbols.candlesticks(BitfinexCurrencyPair.of("BTC","USD"), Timeframe.MINUTE_1);

// The consumer will be called on all received candles for the symbol
final BiConsumer<BitfinexCandlestickSymbol, BitfinexCandle> callback = (sym, tick) -> {
	System.out.format("Got BitfinexTick (%s) for symbol (%s)\n", tick, sym);
};

final QuoteManager quoteManager = bitfinexApiBroker.getQuoteManager();
quoteManager.registerCandlestickCallback(symbol, callback);
quoteManager.subscribeCandles(symbol);

[...]

// To unsubscribe the candles stream
quoteManager.removeCandlestickCallback(symbol, callback);
tickerManager.unsubscribeCandles(symbol);

Subscribe ticker stream

// The consumer will be called on all received ticks for the symbol
final BiConsumer<BitfinexTickerSymbol, BitfinexTick> callback = (symbol, tick) -> {
	System.out.format("Got BitfinexTick (%s) for symbol (%s)\n", tick, symbol);
};

final BitfinexTickerSymbol symbol = BitfinexSymbols.ticker(BitfinexCurrencyPair.of("BTC","USD"));

final QuoteManager quoteManager = bitfinexApiBroker.getQuoteManager();
quoteManager.registerTickCallback(symbol, callback);
tickerManager.subscribeTicker(symbol);

[...]

// To unsubscribe the ticker stream
quoteManager.removeTickCallback(symbol, callback);
tickerManager.unsubscribeTicker(symbol);

Subscribe orderbook stream

final BitfinexOrderBookSymbol orderbookConfiguration = BitfinexSymbols.orderBook(
	BitfinexCurrencyPair.of("BTC","USD"), Precision.P0, Frequency.F0, 25);

final OrderbookManager orderbookManager = bitfinexClient.getOrderbookManager();

final BiConsumer<BitfinexOrderBookSymbol, BitfinexOrderBookEntry> callback = (orderbookConfig, entry) -> {
	System.out.format("Got entry (%s) for orderbook (%s)\n", entry, orderbookConfig);
};

orderbookManager.registerOrderbookCallback(orderbookConfiguration, callback);
orderbookManager.subscribeOrderbook(orderbookConfiguration);

[...]

// To unsubscribe the orderbook stream
orderbookManager.removeOrderbookCallback(orderbookConfiguration, callback);
orderbookManager.unsubscribeOrderbook(orderbookConfiguration);

Subscribe raw orderbook stream

final BitfinexOrderBookSymbol orderbookConfiguration = BitfinexSymbols.rawOrderBook(
	BitfinexCurrencyPair.of("BTC","USD"));

final RawOrderbookManager rawOrderbookManager = bitfinexClient.getRawOrderbookManager();

final BiConsumer<BitfinexOrderBookSymbol, BitfinexOrderBookEntry> callback = (orderbookConfig, entry) -> {
	System.out.format("Got entry (%s) for orderbook (%s)\n", entry, orderbookConfig);
};

rawOrderbookManager.registerOrderbookCallback(orderbookConfiguration, callback);
rawOrderbookManager.subscribeOrderbook(orderbookConfiguration);

[...]

// To unsubscribe the raw orderbook stream
rawOrderbookManager.removeOrderbookCallback(orderbookConfiguration, callback);
rawOrderbookManager.unsubscribeOrderbook(orderbookConfiguration);

Executed trade callbacks (all trades on the exchange)

final BitfinexExecutedTradeSymbol symbol = BitfinexSymbols.executedTrades(BitfinexCurrencyPair.of("BTC","USD"));

final QuoteManager quoteManager = bitfinexClient.getQuoteManager();

final BiConsumer<BitfinexExecutedTradeSymbol, ExecutedTrade> callback = (symbol, trade) -> {
	System.out.format("Got executed trade (%s) for symbol (%s)\n", trade, symbol);
};

quoteManager.registerExecutedTradeCallback(symbol, callback);
quoteManager.subscribeExecutedTrades(symbol);

[...]

// To unsubscribe the executed trades stream
quoteManager.removeExecutedTradeCallback(symbol, callback);
quoteManager.unsubscribeExecutedTrades(symbol);

Trade callbacks (generated by own orders)

final TradeManager tradeManager = bitfinexApiBroker.getTradeManager();

tradeManager.registerCallback((trade) -> {
	System.out.format("Got trade callback (%s)\n", trade);
}

Placing orders

The following order types are supported:

Ordertype API Constant Marketplace API Constant Margin
Market BitfinexOrderType.EXCHANGE_MARKET BitfinexOrderType.MARKET
Limit BitfinexOrderType.EXCHANGE_LIMIT BitfinexOrderType.LIMIT
Stop BitfinexOrderType.EXCHANGE_STOP BitfinexOrderType.STOP
Trailing stop BitfinexOrderType.EXCHANGE_TRAILING_STOP BitfinexOrderType.TRAILING_STOP
Fill or kill BitfinexOrderType.EXCHANGE_FOK BitfinexOrderType.FOK
Stop Limit BitfinexOrderType.EXCHANGE_STOP_LIMIT BitfinexOrderType.STOP_LIMIT

Please note: A negative amount will sell the currency pair, a positive amount will buy the currency pair.

final BitfinexOrder order = BitfinexOrderBuilder
		.create(currency, BitfinexOrderType.MARKET, 0.002)
		.build();

bitfinexApiBroker.getOrderManager().placeOrder(order);

Order group

Order groups are maintained automatically by Bitfinex; they have a 'one cancels the other' semantic. It means that all remaining orders of an order group are canceled automatically when one of the group orders is executed.

To set up an order group, choose a random integer value (like 4711 in the following example) and pass this value to the withGroupId() method of all orders, that should be part of the order group. In the following example, a long order is placed when the price rises and a short order is placed when the price drops. Due to the order group, it is ensured that only one of the orders is executed. The other order is canceled automatically.

final CurrencyPair currencyPair = BitfinexCurrencyPair.of("BTC","USD");
final BitfinexTick lastValue = bitfinexApiBroker.getQuoteManager().getLastTick(currencyPair);

final int orderGroup = 4711;

// Long order when price rises 1%
final BitfinexOrder bitfinexOrder1 = BitfinexOrderBuilder
		.create(currencyPair, BitfinexOrderType.EXCHANGE_LIMIT, 0.002, lastValue.getClosePrice() / 100.0 * 101.0)
		.withOrderFlag(BitfinexOrderFlag.POSTONLY)
		.withGroupId(orderGroup)
		.build();

// Short order when price drops 1%
final BitfinexOrder bitfinexOrder2 = BitfinexOrderBuilder
		.create(currencyPair, BitfinexOrderType.EXCHANGE_LIMIT, -0.002, lastValue.getClosePrice() / 100.0 * 99.0)
		.withOrderFlag(BitfinexOrderFlag.POSTONLY)
		.withGroupId(orderGroup)
		.build();

// Cancel sell order when buy order failes
final Consumer<ExchangeOrder> ordercallback = (e) -> {

	if(e.getCid() == bitfinexOrder1.getCid()) {
		if(e.getState().equals(ExchangeOrder.STATE_CANCELED)
				|| e.getState().equals(ExchangeOrder.STATE_POSTONLY_CANCELED)) {
			bitfinexApiBroker.cancelOrderGroup(orderGroup);
		}
	}
};

final OrderManager orderManager = bitfinexApiBroker.getOrderManager();

orderManager.addOrderCallback(ordercallback);
orderManager.placeOrder(bitfinexOrder1);
orderManager.placeOrder(bitfinexOrder2);

Request wallet balance

Some fields are not automatically calculated by the Bitfinex API, these values must be requested explicitly. This can be done by the calculateWalletMarginBalancecalculateWalletMarginBalance method.

System.out.println(bitfinexApiBroker.getWalletManager().getWalletTable().get("margin", "USD"));

bitfinexApiBroker.getWalletManager().calculateWalletMarginBalance("USD");

// Wait some time until Bitfinex has send us a wallet update
Thread.sleep(TimeUnit.SECONDS.toMillis(5));

System.out.println(bitfinexApiBroker.getWalletManager().getWalletTable().get("margin", "USD"));
You can’t perform that action at this time.