polygon-io/client-python

BadRequest for list_trades on timestamp parsing

Closed this issue · 8 comments

Describe the bug
When issuing a request to list_trades I consistently get an error that the timestamp cannot be parsed. According to the API it can take the form of a str, int, datetime, date. I've tried passing in all 4 and still get the same error.

To Reproduce
Steps to reproduce the behavior:
Call the API with the following dictionary:

polygon.exceptions.BadResponse: {"status":"ERROR","request_id":"cb399e7fd0ae69e62906982f0f259c67","error":"failed to parse timestamp query params: invalid time string: parsing time "**{'timestamp.gt': '2024-02-27', 'order': 'asc', 'sort': 'timestamp', 'limit': 50000, 'timestamp.lt': '2024-03-13'}**" as "2006-01-02": cannot parse "{'timestamp.gt': '2024-02-27', 'order': 'asc', 'sort': 'timestamp', 'limit': 50000, 'timestamp.lt': '2024-03-13'}" as "2006""}

Expected behavior
Expect the API to succeed, and if there are no trades to return an empty result list.

Screenshots

Additional context
Using:
"polygon-api-client": {
"hashes": [
"sha256:0b1a4b0f6110be5732ac21858b91c61cca23160c1b696fd02f3d2ec6a658e929",
"sha256:57115f21851b100a06dd95245d2f9eec8fee84c1e2f4f7c5967dc8b2c371fc99"
],
"index": "pypi",
"markers": "python_version >= '3.8' and python_version < '4.0'",
"version": "==1.13.4"
},

Hey @brendanfly, do you mind adding trace=True to your client to enable debugging? Like this:

client = RESTClient(trace=True)

Can you paste the output. Also, do you mind pasting the request code that's actually making the request so I can see the params being passed? This will help me debug and reproduce the issue.

Is this what you need?

Request URL: https://api.polygon.io/v3/trades/O:MSFT240621C00110000?timestamp=%7B%27timestamp.gte%27%3A+%272024-02-27%27%2C+%27order%27%3A+%27asc%27%2C+%27sort%27%3A+%27timestamp%27%2C+%27limit%27%3A+50000%2C+%27timestamp.lt%27%3A+%272024-03-13%27%7D
Request Headers: {'Authorization': 'Bearer REDACTED', 'Accept-Encoding': 'gzip', 'User-Agent': 'Polygon.io PythonClient/1.13.4'}
Response Headers: {'Server': 'nginx/1.19.2', 'Date': 'Tue, 12 Mar 2024 20:28:43 GMT', 'Content-Type': 'application/json', 'Content-Length': '237', 'Connection': 'keep-alive', 'Content-Encoding': 'gzip', 'Vary': 'Accept-Encoding', 'X-Request-Id': 'a7fc84afa35494f17ae5b9e06809ee49', 'Strict-Transport-Security': 'max-age=15724800; includeSubDomains'}

Request exception:

polygon.exceptions.BadResponse: {"status":"ERROR","request_id":"a7fc84afa35494f17ae5b9e06809ee49","error":"failed to parse timestamp query params: invalid time string: parsing time "{'timestamp.gte': '2024-02-27', 'order': 'asc', 'sort': 'timestamp', 'limit': 50000, 'timestamp.lt': '2024-03-13'}" as "2006-01-02": cannot parse "{'timestamp.gte': '2024-02-27', 'order': 'asc', 'sort': 'timestamp', 'limit': 50000, 'timestamp.lt': '2024-03-13'}" as "2006""}

Request code:
self.client = RESTClient(self.api_key, trace=True)

def get_options_trades(self, options_ticker, start_date, end_date=""):
        trades = []
        print("Getting trades for: {}".format(options_ticker))
        request_params = {
            "timestamp.gte" : '2024-02-27',
            "order" : "asc",
            "sort" : "timestamp",
            "limit" : 50000
        }

        if end_date != "":
            request_params.update({"timestamp.lt" : end_date})
        for t in self.client.list_trades(
            options_ticker,
            request_params
        ):
            trades.append(t)
        return trades

Hey,

Here's an example that works:

from polygon import RESTClient

client = RESTClient(trace=True)  # POLYGON_API_KEY environment variable is used

trades = []
for t in client.list_trades("O:MSFT240621C00110000", 
	params={
        "timestamp.gte": "2024-02-27"
    },
	limit=50000):
    trades.append(t)

# prints each trade that took place
print(trades)

For your code, it looks like you might be directly passing the request_params dictionary without specifying it as params:

for t in self.client.list_trades(options_ticker, request_params):
    trades.append(t)

To fix the issue, try explicitly naming the params argument when calling the list_trades function:

trades = []
print("Getting trades for: {}".format(options_ticker))
request_params = {
    "timestamp.gte": '2024-02-27',
    "order": "asc",
    "sort": "timestamp",
    "limit": 50000
}

if end_date != "":
    request_params.update({"timestamp.lt": end_date})
for t in self.client.list_trades(options_ticker, params=request_params):  # Note the 'params=' here
    trades.append(t)
return trades

This change specifies that request_params should be used as the value for the params argument, which should resolve the parsing issue you're encountering.

Also, I'm not sure if you have seen it yet but we released flat files for all plans https://polygon.io/blog/flat-files and you can download all trades that happen on a day now via https://polygon.io/flat-files/options-trades. If this fits your workflow it might help.

Hopefully, this is fixed now. I'm going to close it. If you need anything else just pop a comment in here. Cheers.

Wow - how embarrassing. Thanks for helping out and point out the obvious mistake.

I was doing the above (improperly) for the list_snapshot_options_chain API in my production code as well. Maybe there's an opportunity to throw a better exception when a dictionary is there but not called 'params'? I am not sure how the list_snapshot_options_chain call was working. Just a thought on improving the story around the API.

Honestly, happens to the best of us. You just needed a second set of eyes on it. haha. Yeah, I'll take a look to see if there is something more obvious we can throw as an error there.