All Downloads are FREE. Search and download functionalities are using the official Maven repository.

info.bitrich.xchangestream.bitmex.BitmexStreamingMarketDataService Maven / Gradle / Ivy

package info.bitrich.xchangestream.bitmex;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import info.bitrich.xchangestream.bitmex.dto.*;
import info.bitrich.xchangestream.core.StreamingMarketDataService;
import info.bitrich.xchangestream.service.netty.StreamingObjectMapperHelper;
import io.reactivex.Observable;
import org.knowm.xchange.bitmex.BitmexExchange;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.dto.marketdata.OrderBook;
import org.knowm.xchange.dto.marketdata.Ticker;
import org.knowm.xchange.dto.marketdata.Trade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.*;

/**
 * Created by Lukas Zaoralek on 13.11.17.
 */
public class BitmexStreamingMarketDataService implements StreamingMarketDataService {
    private static final Logger LOG = LoggerFactory.getLogger(BitmexStreamingMarketDataService.class);

    private final ObjectMapper objectMapper = StreamingObjectMapperHelper.getObjectMapper();

    private final BitmexStreamingService streamingService;

    private final BitmexExchange bitmexExchange;

    private final SortedMap orderbooks = new TreeMap<>();

    public BitmexStreamingMarketDataService(BitmexStreamingService streamingService, BitmexExchange bitmexExchange) {
        this.streamingService = streamingService;
        this.streamingService.subscribeConnectionSuccess().subscribe(o -> {
            LOG.info("Bitmex connection succeeded. Clearing orderbooks.");
            orderbooks.clear();
        });
        this.bitmexExchange = bitmexExchange;
    }

    private String getBitmexSymbol(CurrencyPair currencyPair) {
        return currencyPair.base.toString() + currencyPair.counter.toString();
    }

    @Override
    public Observable getOrderBook(CurrencyPair currencyPair, Object... args) {
        String instrument = getBitmexSymbol(currencyPair);
        String channelName = String.format("orderBookL2:%s", instrument);

        return streamingService.subscribeBitmexChannel(channelName).map(s -> {
            BitmexOrderbook orderbook;
            String action = s.getAction();
            if (action.equals("partial")) {
                orderbook = s.toBitmexOrderbook();
                orderbooks.put(instrument, orderbook);
            } else {
                orderbook = orderbooks.get(instrument);
                //ignore updates until first "partial"
                if (orderbook == null) {
                    return new OrderBook(new Date(), Collections.emptyList(), Collections.emptyList());
                }
                BitmexLimitOrder[] levels = s.toBitmexOrderbookLevels();
                orderbook.updateLevels(levels, action);
            }

            return orderbook.toOrderbook();
        });
    }

    public Observable getRawTicker(CurrencyPair currencyPair) {
        String instrument = getBitmexSymbol(currencyPair);
        String channelName = String.format("quote:%s", instrument);

        return streamingService.subscribeBitmexChannel(channelName).map(s -> s.toBitmexTicker());
    }

    @Override
    public Observable getTicker(CurrencyPair currencyPair, Object... args) {
        String instrument = getBitmexSymbol(currencyPair);
        String channelName = String.format("quote:%s", instrument);

        return streamingService.subscribeBitmexChannel(channelName).map(s -> {
            BitmexTicker bitmexTicker = s.toBitmexTicker();
            return bitmexTicker.toTicker();
        });
    }

    @Override
    public Observable getTrades(CurrencyPair currencyPair, Object... args) {
        String instrument = getBitmexSymbol(currencyPair);
        String channelName = String.format("trade:%s", instrument);

        return streamingService.subscribeBitmexChannel(channelName).flatMapIterable(s -> {
            BitmexTrade[] bitmexTrades = s.toBitmexTrades();
            List trades = new ArrayList<>(bitmexTrades.length);
            for (BitmexTrade bitmexTrade : bitmexTrades) {
                trades.add(bitmexTrade.toTrade());
            }
            return trades;
        });
    }


    public Observable getRawExecutions(String symbol) {
        return streamingService.subscribeBitmexChannel("execution:" + symbol).flatMapIterable(s -> {
            JsonNode executions = s.getData();
            List bitmexExecutions = new ArrayList<>(executions.size());
            for (JsonNode execution : executions) {
                bitmexExecutions.add(objectMapper.treeToValue(execution, BitmexExecution.class));
            }
            return bitmexExecutions;
        });
    }

    public void enableDeadManSwitch() throws IOException {
        enableDeadManSwitch(BitmexStreamingService.DMS_RESUBSCRIBE, BitmexStreamingService.DMS_CANCEL_ALL_IN);
    }

    /**
     * @param rate    in milliseconds to send updated
     * @param timeout milliseconds from now after which orders will be cancelled
     */
    public void enableDeadManSwitch(long rate, long timeout) throws IOException {
        streamingService.enableDeadMansSwitch(rate, timeout);
    }

    public boolean isDeadManSwitchEnabled() throws IOException {
        return streamingService.isDeadMansSwitchEnabled();
    }

    public void disableDeadMansSwitch() throws IOException {
        streamingService.disableDeadMansSwitch();
    }

    public Observable getRawFunding() {
        String channelName = "funding";
        return streamingService.subscribeBitmexChannel(channelName).map(BitmexWebSocketTransaction::toBitmexFunding);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy