danpaquin / coinbasepro-python

The unofficial Python client for the Coinbase Pro API
MIT License
1.82k stars 732 forks source link

inconsistent data on websocket #235

Closed koal closed 6 years ago

koal commented 6 years ago

I'm introducing myself on python and exchanges APIs. I was doing some tests last night, trying to connect and retrieve data from gdax websocket modding the example code on for your websocketclient.

This is the code I was running:

from __future__ import print_function
import json

from threading import Thread
from websocket import create_connection, WebSocketConnectionClosedException

class WebsocketClient(object):
    def __init__(self, url="wss://ws-feed.gdax.com", products=None, message_type="subscribe"):
        self.url = url
        self.products = products
        self.type = message_type
        self.stop = False
        self.ws = None
        self.thread = None

    def start(self):
        def _go():
            self._connect()
            self._listen()

        self.on_open()
        self.thread = Thread(target=_go)
        self.thread.start()

    def _connect(self):
        if self.products is None:
            self.products = ["BTC-USD"]
        elif not isinstance(self.products, list):
            self.products = [self.products]

        if self.url[-1] == "/":
            self.url = self.url[:-1]

        self.ws = create_connection(self.url)

        self.stop = False
        sub_params = {'type': 'subscribe', 'product_ids': self.products, 'name': ticker}
        self.ws.send(json.dumps(sub_params))
        if self.type == "heartbeat":
            sub_params = {"type": "heartbeat", "on": True}
            self.ws.send(json.dumps(sub_params))

    def _listen(self):
        while not self.stop:
            try:
                msg = json.loads(self.ws.recv())
            except Exception as e:
                self.on_error(e)
            else:
                self.on_message(msg)

    def close(self):
        if not self.stop:
            if self.type == "heartbeat":
                self.ws.send(json.dumps({"type": "heartbeat", "on": False}))
            self.on_close()
            self.stop = True
            try:
                if self.ws:
                    self.ws.close()
            except WebSocketConnectionClosedException as e:
                pass

    def on_open(self):
        print("-- Subscribed! --\n")

    def on_close(self):
        print("\n-- Socket Closed --")

    def on_message(self, msg):
        print(msg)

    def on_error(self, e):
        return

if __name__ == "__main__":
    import gdax
    import time

    class MyWebsocketClient(gdax.WebsocketClient):
        def on_open(self):
            self.url = "wss://ws-feed.gdax.com/"
            self.products = ["ETH-EUR"]

        def on_message(self, msg):
            if 'price' in msg and 'time' in msg:
                print('At ' + msg['time'] + ' price is: ' + msg['price'])
            else:
                print(msg)

        def on_close(self):
            print("-- Goodbye! --")

    wsClient = MyWebsocketClient()
    wsClient.start()
    print(wsClient.url, wsClient.products)
    # Do some logic with the data
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print('interrupted!')    
    wsClient.close()

As you see, it's a slight mod of your file. After a few seconds, the console shows:

wss://ws-feed.gdax.com ['ETH-EUR'] At 2018-01-20T02:20:33.923000Z price is: 879.58000000 At 2018-01-20T02:20:33.923000Z price is: 879.58000000 At 2018-01-20T02:20:33.930000Z price is: 878.01000000 At 2018-01-20T02:20:33.930000Z price is: 878.01000000 At 2018-01-20T02:20:33.932000Z price is: 876.01000000 At 2018-01-20T02:20:33.932000Z price is: 876.01000000 At 2018-01-20T02:20:33.941000Z price is: 873.87000000 At 2018-01-20T02:20:33.941000Z price is: 873.87000000 At 2018-01-20T02:20:33.944000Z price is: 872.55000000 At 2018-01-20T02:20:33.944000Z price is: 872.55000000 At 2018-01-20T02:20:33.946000Z price is: 871.98000000 At 2018-01-20T02:20:33.946000Z price is: 871.98000000 At 2018-01-20T02:20:34.065000Z price is: 1036.46000000 At 2018-01-20T02:20:34.200000Z price is: 887.88000000 At 2018-01-20T02:20:34.200000Z price is: 887.88000000 At 2018-01-20T02:20:34.534000Z price is: 875.66000000 At 2018-01-20T02:20:34.534000Z price is: 875.66000000 At 2018-01-20T02:20:34.566000Z price is: 1036.43000000 At 2018-01-20T02:20:35.099000Z price is: 888.88000000 At 2018-01-20T02:20:35.099000Z price is: 888.88000000 At 2018-01-20T02:20:35.415000Z price is: 870.27000000 At 2018-01-20T02:20:35.415000Z price is: 870.27000000 At 2018-01-20T02:20:35.416000Z price is: 874.66000000 At 2018-01-20T02:20:35.416000Z price is: 874.66000000 At 2018-01-20T02:20:35.602000Z price is: 917.23000000 At 2018-01-20T02:20:35.602000Z price is: 917.23000000 At 2018-01-20T02:20:35.757000Z price is: 889.88000000 At 2018-01-20T02:20:35.757000Z price is: 889.88000000 At 2018-01-20T02:20:35.770000Z price is: 880.41000000 At 2018-01-20T02:20:35.770000Z price is: 880.41000000 At 2018-01-20T02:20:35.776000Z price is: 884.47000000 At 2018-01-20T02:20:35.776000Z price is: 884.47000000 At 2018-01-20T02:20:35.930000Z price is: 917.23000000 At 2018-01-20T02:20:36.011000Z price is: 880.21000000 At 2018-01-20T02:20:36.011000Z price is: 880.21000000

According to the gdax web information, the price was quite stable, and it did not pass from 883€, but the feed show prices from 900 to 1040 .

What I'm missing? What's wrong in my mods?

Thanks for your work.

Froibo commented 6 years ago

I've been having inconsistent data outisde of the websocket with PublicClient.get_product_historic_rates()...

The most recent product ticker is always right, but it is never within the most recent historic rate high/low range. Something is definitely fishy.

mcardillo55 commented 6 years ago

The websocket broadcasts all transactions from the GDAX engine. This includes new orders, changed orders deleted orders and matched orders. If you're only interested in the last traded price, then you want to check that the message type == 'match' before checking the price.

koal commented 6 years ago

Thanks. I realized that I was retrieving data form the order book.

Thanks for your answers.