bmoscon / cryptofeed

Cryptocurrency Exchange Websocket Data Feed Handler
Other
2.21k stars 682 forks source link

Kraken L2 crossed bid/ask prices #86

Closed AlgoTrader5 closed 5 years ago

AlgoTrader5 commented 5 years ago

I'm getting negative spreads subscribing to Kraken exchange using the demo_zmq.py example. I am also subscribing to the trades feed along with Coinbase and Binance feeds.

Here are two subsequent messages from ETH-USD where spread is incorrect. Comparing to Kraken's trading platform, it seems the ask price and ask sizes are updating correctly but the bid price and bid size are not updating.

{'type': 'book', 'feed': 'KRAKEN', 'pair': 'ETH-USD', 'data': {'timestamp': 1555987491.0964444, 'bid': {'171.68000': '0.69084773'}, 'ask': {'171.63000': '9.96411128'}}} {'type': 'book', 'feed': 'KRAKEN', 'pair': 'ETH-USD', 'data': {'timestamp': 1555987492.615416, 'bid': {'171.68000': '0.69084773'}, 'ask': {'171.63000': '31.89969709'}}}

from multiprocessing import Process
from cryptofeed.backends.zmq import BookZMQ, TradeZMQ
from cryptofeed import FeedHandler
from cryptofeed.exchanges import Coinbase, Kraken, Poloniex, Binance
from cryptofeed.defines import L3_BOOK, TRADES, L2_BOOK, TRADES

def book_receiver(port):
    import zmq
    import time
    addr = 'tcp://127.0.0.1:{}'.format(port)
    ctx = zmq.Context.instance()
    s = ctx.socket(zmq.PULL)
    s.connect(addr)
    while True:
        data = s.recv_json()
        print(data)
        time.sleep(0.5)

def trade_receiver(port):
    import zmq
    import time
    addr = 'tcp://127.0.0.1:{}'.format(port)
    ctx = zmq.Context.instance()
    s = ctx.socket(zmq.PULL)
    s.connect(addr)
    while True:
        data = s.recv_json()
        # print(data)
        time.sleep(0.5)

def read_cfg(fileName, key=None):
    '''open config file'''
    import yaml

    cfg = {}
    with open(fileName, 'r') as f:
        try:
            config = yaml.load(f)
            f.close()
            # only grab exchange specific config
            if key:
                for k, v in config.items():
                    if key in k:
                        cfg[k] = config[k]
                return cfg
            else:
                return config
        except yaml.YAMLError as exc:
            print(exc)

def main():
        subscriptions = read_cfg(fileName)
        cbpro_tickers = subscriptions['CBPRO']['TICKERS']
        kraken_tickers = subscriptions['KRAKEN']['TICKERS']
        # poloniex_tickers = subscriptions['POLONIEX']['TICKERS']
        binance_tickers = subscriptions['BINANCE']['TICKERS']

        try:
            # coinbase
            p1 = Process(target=trade_receiver, args=(5555,))
            p2 = Process(target=book_receiver, args=(5556,))
            # kraken
            p3 = Process(target=trade_receiver, args=(5557,))
            p4 = Process(target=book_receiver, args=(5558,))
            # poloniex
            # p5 = Process(target=trade_receiver, args=(5559,))
            # p6 = Process(target=book_receiver, args=(5560,))
            # binance
            p7 = Process(target=trade_receiver, args=(5561,))
            p8 = Process(target=book_receiver, args=(5562,))

            p1.start()
            p2.start()
            p3.start()
            p4.start()
            p5.start()
            p6.start()
            p7.start()
            p8.start()

            f = FeedHandler()
            f.add_feed(Coinbase(channels=[L3_BOOK, TRADES], pairs=cbpro_tickers, callbacks={TRADES: TradeZMQ(port=5555), L3_BOOK: BookZMQ(depth=1, port=5556)}))
            f.add_feed(Kraken(channels=[L2_BOOK, TRADES], pairs=kraken_tickers, callbacks={TRADES: TradeZMQ(port=5557), L2_BOOK: BookZMQ(depth=1, port=5558)}))
            # f.add_feed(Poloniex(channels=[L2_BOOK, TRADES], pairs=poloniex_tickers, callbacks={TRADES: TradeZMQ(port=5559), L2_BOOK: BookZMQ(depth=1, port=5560)}))
            f.add_feed(Binance(channels=[L2_BOOK, TRADES], pairs=binance_tickers, callbacks={TRADES: TradeZMQ(port=5561), L2_BOOK: BookZMQ(depth=1, port=5562)}))

            f.run()
        finally:
            p1.terminate()
            p2.terminate()
            p3.terminate()
            p4.terminate()
            # p5.terminate()
            # p6.terminate()
            p7.terminate()
            p8.terminate()

if __name__ == '__main__':
    main()
bmoscon commented 5 years ago

how old is your version of cryptofeed?

bmoscon commented 5 years ago

@AlgoTrader5 thanks for raising this, I found the issue, tested and committed a fix.

AlgoTrader5 commented 5 years ago

@bmoscon Thank you for the very quick turn around. This project is fantastic. This works very well with my pyqt gui. Hoping to release it soon. Cheers

bmoscon commented 5 years ago

@AlgoTrader5 cool! I havent released the change to pypi (its just on github at the moment), but it should be released sometime later this week to pypi