MarkGalloway / wealthsimple-trade

Unofficial API docs for the Wealthsimple Trade API
MIT License
98 stars 14 forks source link

Response [400] - "quantity is invalid." when trying to place an order #13

Closed ah2014 closed 3 years ago

ah2014 commented 3 years ago

I get a 400 response with "quantity is invalid." message when trying to place a market buy order. Does anybody have a similar problem?

params = {
    'account_id': account_id,
    'security_id': security['id'],
    'order_type': 'buy_quantity',
    'order_sub_type': 'market',
    'quantity': 1,
    'time_in_force': 'day'
}

self.TradeAPI.makeRequest("POST", "orders", params)

Here is the response:

<Response [400]>
apparent_encoding: 'ascii'
connection: <requests.adapters.HTTPAdapter object at 0x000002475CBDAE48>
content: b'{"error":"quantity is invalid."}'
cookies: <RequestsCookieJar[]>
elapsed: datetime.timedelta(microseconds=60428)
encoding: 'utf-8'
headers: {'Date': 'Fri, 09 Oct 2020 18:11:45 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Content-Length': '32', 'Connection': 'keep-alive', 'X-DNS-Prefetch-Control': 'off', 'X-Frame-Options': 'SAMEORIGIN', 'Strict-Transport-Security': 'max-age=15552000; includeSubDomains', 'X-Download-Options': 'noopen', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '1; mode=block', 'x-request-id': '057***', 'x-ws-device-id': '0a75***', 'Vary': 'Origin', 'X-Access-Token': '0yz***', 'CF-Cache-Status': 'DYNAMIC', 'cf-request-id': '05b***, 'Expect-CT': 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"', 'Server': 'cloudflare', 'CF-RAY': '5dfa10dec96aca53-YUL'}
history: []
is_permanent_redirect: False
is_redirect: False
links: {}
next: None
ok: False
raw: <urllib3.response.HTTPResponse object at 0x000002475CCADFC8>
reason: 'Bad Request'
request: <PreparedRequest [POST]>
status_code: 400
text: '{"error":"quantity is invalid."}'
url: 'https://trade-service.wealthsimple.com/orders'
_content: b'{"error":"quantity is invalid."}'
_content_consumed: True
_next: None
ah2014 commented 3 years ago

I found the solution. params should be passed to session.post function as json and not as data

Here are the changes that I made to requester.py:

def makeRequest(self, method, endpoint, params=None, returnValue=None, jsonData=None):
    """Make a request to a given API endpoint

    Parameters
    ----------
    method : str
        Specify POST or GET request
    endpoint : str
        URL endpoint oof API (Does not include base URL)
    params : dict
        Dictionary of parameters to be passed with request
    jsonData : dict
        Dictionary of parameters to be passed with request as json data

    Returns
    -------
    Response : Response
        A requests response object
    """
    URL = self.APIMainURL + endpoint

    if method == "POST":
        return self.post(URL, params, jsonData)
    elif method == "GET":
        return self.get(URL, params)
    else:
        raise Exception(f"Invalid request method: {method}")

def post(self, URL, params=None, jsonData=None):
    """Make a POST request to a given API endpoint

    Parameters
    ----------
    URL : str
        Full URL endpoint of API
    params : dict
        Dictionary of parameters to be passed with request
    jsonData : dict
        Dictionary of parameters to be passed with request as json data

    Returns
    -------
    Response : Response
        A requests response object
    """

    try:
        return self.session.post(URL, params, json=jsonData)
    except Exception as err:
        print(err)

It should be called like this:

params = {
    'account_id': account_id,
    'security_id': security_id,
    'order_type': 'buy_quantity',
    'order_sub_type': 'market',
    'time_in_force': time_in_force,
    'quantity': 1,
    'limit_price': limit_price
}

self.TradeAPI.makeRequest("POST", "orders", jsonData=params)