danpaquin / coinbasepro-python

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

Calculating Tick Volume #367

Closed JamesKBowler closed 5 years ago

JamesKBowler commented 5 years ago

Hi, How would I go about calculating volume for each tick. I am not sure which message type I need to parse.

Thanks

James

TheKeyboardKowboy commented 5 years ago

Get Product Ticker

Snapshot information about the last trade (tick), best bid/ask and 24h volume.

{ "trade_id": 4729088, "price": "333.99", "size": "0.193", "bid": "333.98", "ask": "333.99", "volume": "5957.11914015", "time": "2015-11-14T20:46:03.511254Z" }

JamesKBowler commented 5 years ago

Thanks but I was referring to the websocket stream.

noah222 commented 5 years ago

Volume is stored in the historical data. So you can get it in the historical data API or you can store/log each transaction in the websocket and sum them to come up with volume for your specifiied interval. The best idea is to log the stream data then you can sum it and dice it into any size sections later on.

JamesKBowler commented 5 years ago

@noah222 Thanks, I guessed as much, only i'm not sure what approach to take because each message type is different.

Do you have any code implementation to share?

Cheers

noah222 commented 5 years ago

I have many solutions, but they are very specific to my other code and is not yet modular. Let me know exactly where you are in your process and I can try to point you in the right direction with examples.

The message type does not really matter, what matters is what you do with it. What i mean is any message is just some text that can be sorted, manipulated, appended to lists, and stored in some form. So it mostly depends on what format you want the data to be in, and what granularity you need for the next steps of your code.

@noah222 Thanks, I guessed as much, only i'm not sure what approach to take because each message type is different.

Do you have any code implementation to share?

Cheers

JamesKBowler commented 5 years ago

Understand what you are saying, I guess the correct question should be "how do I calculate executed trade volume" ... or something along those lines : )

Ok, think I may have cracked the process as the volume is now matching up with the [https://pro.coinbase.com]() web platform trade history.

    def on_message(self, message):
        self._volume = Decimal('0.0')
    ...snip

    def match(self, order):
        size = Decimal(order['size'])
        price = Decimal(order['price'])

        if order['side'] == 'buy':
            bids = self.get_bids(price)
            if not bids:
                return
            assert bids[0]['id'] == order['maker_order_id']
            self._volume += size
            if bids[0]['size'] == size:
                self.set_bids(price, bids[1:])
            else:
                bids[0]['size'] -= size
                self.set_bids(price, bids)
        else:
            asks = self.get_asks(price)
            if not asks:
                return
            assert asks[0]['id'] == order['maker_order_id']
            self._volume += size
            if asks[0]['size'] == size:
                self.set_asks(price, asks[1:])
            else:
                asks[0]['size'] -= size
                self.set_asks(price, asks)
lirenz commented 5 years ago

1) The "full" channel has the L3 order book AND the matches. You can use the matches there to add up the volumes.

2) But the "full" channel is space intensive, so unless you're doing some very deep simulations on fills, you're probably better off using the "level2" channel. Plus you don't have to worry as much about missing websocket data mangling your orderbook state. You should combine the "level2" channel with the "matches" channel (which is basically every single trade-hits-order-book).

3) Avoid the ticker channel, it is busted. It should trigger a tick every time the inside quotes change, but I've found it to be unreliable. Also, the volumes seem to be the volume of the last match only, so it'll undercount actual volume.

4) See a small sample of the type "match" from the match channel. Summing up the sizes should give you volumes matching CB (I've tested this).

BTC-USD|match|1563300116.150038|{"time": "2019-07-16T18:01:56.144000Z", "type": "match", "product_id": "BTC-USD", "taker_order_id": "0ac73eac-689e-4c9b-bc90-59e4f1d674c5", "side": "buy", "maker_order_id": "d618bea9-7f69-4454-965c-41736064d573", "sequence": 10214237094, "size": "0.01822233", "trade_id": 70027984, "price": "9760.55000000"} ETH-USD|match|1563300116.167355|{"time": "2019-07-16T18:01:56.161000Z", "type": "match", "product_id": "ETH-USD", "taker_order_id": "a9e569d0-0d60-46b3-9256-de098ef63e6c", "side": "sell", "maker_order_id": "2e921b54-5175-4bca-a5fb-94b330d1a0d4", "sequence": 7010941800, "size": "2.00000000", "trade_id": 50159413, "price": "202.46000000"} ETH-USD|match|1563300116.168052|{"time": "2019-07-16T18:01:56.161000Z", "type": "match", "product_id": "ETH-USD", "taker_order_id": "a9e569d0-0d60-46b3-9256-de098ef63e6c", "side": "sell", "maker_order_id": "c5fa10f4-79d3-470d-ad74-25de7a04b506", "sequence": 7010941802, "size": "3.07700000", "trade_id": 50159414, "price": "202.47000000"} ETH-USD|match|1563300116.168420|{"time": "2019-07-16T18:01:56.161000Z", "type": "match", "product_id": "ETH-USD", "taker_order_id": "a9e569d0-0d60-46b3-9256-de098ef63e6c", "side": "sell", "maker_order_id": "c9aa97b3-8aac-4bd7-9d0c-5b419da8ff1c", "sequence": 7010941804, "size": "5.00000000", "trade_id": 50159415, "price": "202.48000000"} ETH-USD|match|1563300116.168890|{"time": "2019-07-16T18:01:56.161000Z", "type": "match", "product_id": "ETH-USD", "taker_order_id": "a9e569d0-0d60-46b3-9256-de098ef63e6c", "side": "sell", "maker_order_id": "d30a79fe-c170-47d1-9b0d-0837bd485d8c", "sequence": 7010941806, "size": "10.33800000", "trade_id": 50159416, "price": "202.49000000"} ETH-USD|match|1563300116.268488|{"time": "2019-07-16T18:01:56.251000Z", "type": "match", "product_id": "ETH-USD", "taker_order_id": "4275aefc-7878-425d-abb2-6115b81842aa", "side": "sell", "maker_order_id": "067ec5d6-be99-4a1e-ad04-24b31e4e10c7", "sequence": 7010941848, "size": "2.00000000", "trade_id": 50159417, "price": "202.55000000"} ETH-USD|match|1563300116.269007|{"time": "2019-07-16T18:01:56.251000Z", "type": "match", "product_id": "ETH-USD", "taker_order_id": "4275aefc-7878-425d-abb2-6115b81842aa", "side": "sell", "maker_order_id": "6305d147-c4ca-480a-bc48-7a8b962d6f95", "sequence": 7010941850, "size": "2.00000000", "trade_id": 50159418, "price": "202.56000000"} ETH-USD|match|1563300116.269297|{"time": "2019-07-16T18:01:56.251000Z", "type": "match", "product_id": "ETH-USD", "taker_order_id": "4275aefc-7878-425d-abb2-6115b81842aa", "side": "sell", "maker_order_id": "71e89b1c-ad44-4765-87c4-b0c32c15f33d", "sequence": 7010941852, "size": "10.00000000", "trade_id": 50159419, "price": "202.56000000"} ETH-USD|match|1563300116.293319|{"time": "2019-07-16T18:01:56.289000Z", "type": "match", "product_id": "ETH-USD", "taker_order_id": "d89c5740-86c0-484a-b82c-6ec6dcb7f862", "side": "sell", "maker_order_id": "b3891f47-6de4-460f-832b-3625b356183c", "sequence": 7010941872, "size": "12.93500000", "trade_id": 50159420, "price": "202.57000000"} LTC-USD|match|1563300116.449671|{"time": "2019-07-16T18:01:56.439000Z", "type": "match", "product_id": "LTC-USD", "taker_order_id": "79c4cdc4-4185-4aca-8d77-274d1557707d", "side": "buy", "maker_order_id": "db542f29-5ae7-45bb-aef1-2d03a5cbe9ed", "sequence": 3687224576, "size": "14.65000000", "trade_id": 40592623, "price": "80.36000000"} BTC-USD|match|1563300116.450155|{"time": "2019-07-16T18:01:56.438000Z", "type": "match", "product_id": "BTC-USD", "taker_order_id": "9d329d15-f1bf-450a-adce-f7d7fbbcad7d", "side": "sell", "maker_order_id": "a5c15fc1-f0ae-4021-9fe4-3954781e2955", "sequence": 10214237148, "size": "0.47973902", "trade_id": 70027985, "price": "9760.56000000"} BTC-USD|match|1563300116.450754|{"time": "2019-07-16T18:01:56.438000Z", "type": "match", "product_id": "BTC-USD", "taker_order_id": "9d329d15-f1bf-450a-adce-f7d7fbbcad7d", "side": "sell", "maker_order_id": "afca4f3b-5e66-4105-a515-bfd30ac42acb", "sequence": 10214237150, "size": "0.39490602", "trade_id": 70027986, "price": "9760.56000000"}

On Tue, Jul 16, 2019 at 2:18 PM James Bowler notifications@github.com wrote:

ok, think I may have something here because they match up with the coinbasepro trade history.

def on_message(self, message):
    self._volume = Decimal('0.0')
...snip

def match(self, order):
    size = Decimal(order['size'])
    price = Decimal(order['price'])

    if order['side'] == 'buy':
        bids = self.get_bids(price)
        if not bids:
            return
        assert bids[0]['id'] == order['maker_order_id']
        self._volume += size
        if bids[0]['size'] == size:
            self.set_bids(price, bids[1:])
        else:
            bids[0]['size'] -= size
            self.set_bids(price, bids)
    else:
        asks = self.get_asks(price)
        if not asks:
            return
        assert asks[0]['id'] == order['maker_order_id']
        self._volume += size
        if asks[0]['size'] == size:
            self.set_asks(price, asks[1:])
        else:
            asks[0]['size'] -= size
            self.set_asks(price, asks)

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/danpaquin/coinbasepro-python/issues/367?email_source=notifications&email_token=AABBL6GWNEF6FKQXOHEFUBTP7YGIXA5CNFSM4H2ZNUF2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2BWWQI#issuecomment-511929153, or mute the thread https://github.com/notifications/unsubscribe-auth/AABBL6HH2LPSCN2SVAQR5D3P7YGIXANCNFSM4H2ZNUFQ .

JamesKBowler commented 5 years ago

awesome, that is great info! I will close this one off. Thanks to all.